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