1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/keyed_service/core/keyed_service_factory.h"
#include <utility>
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "components/keyed_service/core/dependency_manager.h"
#include "components/keyed_service/core/keyed_service.h"
KeyedServiceFactory::KeyedServiceFactory(const char* name,
DependencyManager* manager)
: KeyedServiceBaseFactory(name, manager) {
}
KeyedServiceFactory::~KeyedServiceFactory() {
DCHECK(mapping_.empty());
}
void KeyedServiceFactory::SetTestingFactory(
base::SupportsUserData* context,
TestingFactoryFunction testing_factory) {
// Destroying the context may cause us to lose data about whether |context|
// has our preferences registered on it (since the context object itself
// isn't dead). See if we need to readd it once we've gone through normal
// destruction.
bool add_context = ArePreferencesSetOn(context);
#ifndef NDEBUG
// Ensure that |context| is not marked as stale (e.g., due to it aliasing an
// instance that was destroyed in an earlier test) in order to avoid accesses
// to |context| in |BrowserContextShutdown| from causing
// |AssertBrowserContextWasntDestroyed| to raise an error.
MarkContextLiveForTesting(context);
#endif
// We have to go through the shutdown and destroy mechanisms because there
// are unit tests that create a service on a context and then change the
// testing service mid-test.
ContextShutdown(context);
ContextDestroyed(context);
if (add_context)
MarkPreferencesSetOn(context);
testing_factories_[context] = testing_factory;
}
KeyedService* KeyedServiceFactory::SetTestingFactoryAndUse(
base::SupportsUserData* context,
TestingFactoryFunction testing_factory) {
DCHECK(testing_factory);
SetTestingFactory(context, testing_factory);
return GetServiceForContext(context, true);
}
KeyedService* KeyedServiceFactory::GetServiceForContext(
base::SupportsUserData* context,
bool create) {
TRACE_EVENT0("browser,startup", "KeyedServiceFactory::GetServiceForContext");
context = GetContextToUse(context);
if (!context)
return nullptr;
// NOTE: If you modify any of the logic below, make sure to update the
// refcounted version in refcounted_context_keyed_service_factory.cc!
const auto& it = mapping_.find(context);
if (it != mapping_.end())
return it->second;
// Object not found.
if (!create)
return nullptr; // And we're forbidden from creating one.
// Create new object.
// Check to see if we have a per-context testing factory that we should use
// instead of default behavior.
std::unique_ptr<KeyedService> service;
const auto& jt = testing_factories_.find(context);
if (jt != testing_factories_.end()) {
if (jt->second) {
if (!IsOffTheRecord(context))
RegisterUserPrefsOnContextForTest(context);
service = jt->second(context);
}
} else {
service = BuildServiceInstanceFor(context);
}
Associate(context, std::move(service));
return mapping_[context];
}
void KeyedServiceFactory::Associate(base::SupportsUserData* context,
std::unique_ptr<KeyedService> service) {
DCHECK(!base::ContainsKey(mapping_, context));
mapping_.insert(std::make_pair(context, service.release()));
}
void KeyedServiceFactory::Disassociate(base::SupportsUserData* context) {
const auto& it = mapping_.find(context);
if (it != mapping_.end()) {
delete it->second;
mapping_.erase(it);
}
}
void KeyedServiceFactory::ContextShutdown(base::SupportsUserData* context) {
const auto& it = mapping_.find(context);
if (it != mapping_.end() && it->second)
it->second->Shutdown();
}
void KeyedServiceFactory::ContextDestroyed(base::SupportsUserData* context) {
Disassociate(context);
// For unit tests, we also remove the factory function both so we don't
// maintain a big map of dead pointers, but also since we may have a second
// object that lives at the same address (see other comments about unit tests
// in this file).
testing_factories_.erase(context);
KeyedServiceBaseFactory::ContextDestroyed(context);
}
void KeyedServiceFactory::SetEmptyTestingFactory(
base::SupportsUserData* context) {
SetTestingFactory(context, nullptr);
}
bool KeyedServiceFactory::HasTestingFactory(base::SupportsUserData* context) {
return testing_factories_.find(context) != testing_factories_.end();
}
void KeyedServiceFactory::CreateServiceNow(base::SupportsUserData* context) {
GetServiceForContext(context, true);
}
|