OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/keyed_service/content/browser_context_keyed_service_factory
.h" | 5 #include "components/keyed_service/content/browser_context_keyed_service_factory
.h" |
6 | 6 |
7 #include <map> | |
8 | |
9 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/prefs/pref_service.h" |
10 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
11 #include "components/keyed_service/content/browser_context_dependency_manager.h" | 10 #include "components/keyed_service/content/browser_context_dependency_manager.h" |
12 #include "components/keyed_service/core/keyed_service.h" | 11 #include "components/keyed_service/core/keyed_service.h" |
| 12 #include "components/pref_registry/pref_registry_syncable.h" |
| 13 #include "components/user_prefs/user_prefs.h" |
13 #include "content/public/browser/browser_context.h" | 14 #include "content/public/browser/browser_context.h" |
14 | 15 |
15 void BrowserContextKeyedServiceFactory::SetTestingFactory( | 16 void BrowserContextKeyedServiceFactory::SetTestingFactory( |
16 content::BrowserContext* context, | 17 content::BrowserContext* context, |
17 TestingFactoryFunction testing_factory) { | 18 TestingFactoryFunction testing_factory) { |
18 // Destroying the context may cause us to lose data about whether |context| | 19 KeyedServiceFactory::SetTestingFactory( |
19 // has our preferences registered on it (since the context object itself | 20 context, |
20 // isn't dead). See if we need to readd it once we've gone through normal | 21 reinterpret_cast<KeyedServiceFactory::TestingFactoryFunction>( |
21 // destruction. | 22 testing_factory)); |
22 bool add_context = ArePreferencesSetOn(context); | |
23 | |
24 #ifndef NDEBUG | |
25 // Ensure that |context| is not marked as stale (e.g., due to it aliasing an | |
26 // instance that was destroyed in an earlier test) in order to avoid accesses | |
27 // to |context| in |BrowserContextShutdown| from causing | |
28 // |AssertBrowserContextWasntDestroyed| to raise an error. | |
29 MarkContextLiveForTesting(context); | |
30 #endif | |
31 | |
32 // We have to go through the shutdown and destroy mechanisms because there | |
33 // are unit tests that create a service on a context and then change the | |
34 // testing service mid-test. | |
35 BrowserContextShutdown(context); | |
36 BrowserContextDestroyed(context); | |
37 | |
38 if (add_context) | |
39 MarkPreferencesSetOn(context); | |
40 | |
41 testing_factories_[context] = testing_factory; | |
42 } | 23 } |
43 | 24 |
44 KeyedService* BrowserContextKeyedServiceFactory::SetTestingFactoryAndUse( | 25 KeyedService* BrowserContextKeyedServiceFactory::SetTestingFactoryAndUse( |
45 content::BrowserContext* context, | 26 content::BrowserContext* context, |
46 TestingFactoryFunction testing_factory) { | 27 TestingFactoryFunction testing_factory) { |
47 DCHECK(testing_factory); | 28 return KeyedServiceFactory::SetTestingFactoryAndUse( |
48 SetTestingFactory(context, testing_factory); | 29 context, |
49 return GetServiceForBrowserContext(context, true); | 30 reinterpret_cast<KeyedServiceFactory::TestingFactoryFunction>( |
| 31 testing_factory)); |
50 } | 32 } |
51 | 33 |
52 BrowserContextKeyedServiceFactory::BrowserContextKeyedServiceFactory( | 34 BrowserContextKeyedServiceFactory::BrowserContextKeyedServiceFactory( |
53 const char* name, | 35 const char* name, |
54 BrowserContextDependencyManager* manager) | 36 BrowserContextDependencyManager* manager) |
55 : BrowserContextKeyedBaseFactory(name, manager) {} | 37 : KeyedServiceFactory(name, manager) { |
| 38 } |
56 | 39 |
57 BrowserContextKeyedServiceFactory::~BrowserContextKeyedServiceFactory() { | 40 BrowserContextKeyedServiceFactory::~BrowserContextKeyedServiceFactory() { |
58 DCHECK(mapping_.empty()); | |
59 } | 41 } |
60 | 42 |
61 KeyedService* BrowserContextKeyedServiceFactory::GetServiceForBrowserContext( | 43 KeyedService* BrowserContextKeyedServiceFactory::GetServiceForBrowserContext( |
62 content::BrowserContext* context, | 44 content::BrowserContext* context, |
63 bool create) { | 45 bool create) { |
64 context = GetBrowserContextToUse(context); | 46 return KeyedServiceFactory::GetServiceForContext(context, create); |
65 if (!context) | |
66 return NULL; | |
67 | |
68 // NOTE: If you modify any of the logic below, make sure to update the | |
69 // refcounted version in refcounted_context_keyed_service_factory.cc! | |
70 BrowserContextKeyedServices::const_iterator it = mapping_.find(context); | |
71 if (it != mapping_.end()) | |
72 return it->second; | |
73 | |
74 // Object not found. | |
75 if (!create) | |
76 return NULL; // And we're forbidden from creating one. | |
77 | |
78 // Create new object. | |
79 // Check to see if we have a per-BrowserContext testing factory that we should | |
80 // use instead of default behavior. | |
81 KeyedService* service = NULL; | |
82 BrowserContextOverriddenTestingFunctions::const_iterator jt = | |
83 testing_factories_.find(context); | |
84 if (jt != testing_factories_.end()) { | |
85 if (jt->second) { | |
86 if (!context->IsOffTheRecord()) | |
87 RegisterUserPrefsOnBrowserContextForTest(context); | |
88 service = jt->second(context); | |
89 } | |
90 } else { | |
91 service = BuildServiceInstanceFor(context); | |
92 } | |
93 | |
94 Associate(context, service); | |
95 return service; | |
96 } | 47 } |
97 | 48 |
98 void BrowserContextKeyedServiceFactory::Associate( | 49 content::BrowserContext* |
99 content::BrowserContext* context, | 50 BrowserContextKeyedServiceFactory::GetBrowserContextToUse( |
100 KeyedService* service) { | 51 content::BrowserContext* context) const { |
101 DCHECK(!ContainsKey(mapping_, context)); | 52 DCHECK(CalledOnValidThread()); |
102 mapping_.insert(std::make_pair(context, service)); | 53 |
| 54 #ifndef NDEBUG |
| 55 AssertContextWasntDestroyed(context); |
| 56 #endif |
| 57 |
| 58 // Safe default for Incognito mode: no service. |
| 59 if (context->IsOffTheRecord()) |
| 60 return nullptr; |
| 61 |
| 62 return context; |
103 } | 63 } |
104 | 64 |
105 void BrowserContextKeyedServiceFactory::Disassociate( | 65 void |
| 66 BrowserContextKeyedServiceFactory::RegisterUserPrefsOnBrowserContextForTest( |
106 content::BrowserContext* context) { | 67 content::BrowserContext* context) { |
107 BrowserContextKeyedServices::iterator it = mapping_.find(context); | 68 KeyedServiceBaseFactory::RegisterUserPrefsOnContextForTest(context); |
108 if (it != mapping_.end()) { | 69 } |
109 delete it->second; | 70 |
110 mapping_.erase(it); | 71 bool BrowserContextKeyedServiceFactory::ServiceIsCreatedWithBrowserContext() |
111 } | 72 const { |
| 73 return KeyedServiceBaseFactory::ServiceIsCreatedWithContext(); |
| 74 } |
| 75 |
| 76 bool BrowserContextKeyedServiceFactory::ServiceIsNULLWhileTesting() const { |
| 77 return KeyedServiceBaseFactory::ServiceIsNULLWhileTesting(); |
112 } | 78 } |
113 | 79 |
114 void BrowserContextKeyedServiceFactory::BrowserContextShutdown( | 80 void BrowserContextKeyedServiceFactory::BrowserContextShutdown( |
115 content::BrowserContext* context) { | 81 content::BrowserContext* context) { |
116 BrowserContextKeyedServices::iterator it = mapping_.find(context); | 82 KeyedServiceFactory::ContextShutdown(context); |
117 if (it != mapping_.end() && it->second) | |
118 it->second->Shutdown(); | |
119 } | 83 } |
120 | 84 |
121 void BrowserContextKeyedServiceFactory::BrowserContextDestroyed( | 85 void BrowserContextKeyedServiceFactory::BrowserContextDestroyed( |
122 content::BrowserContext* context) { | 86 content::BrowserContext* context) { |
123 Disassociate(context); | 87 KeyedServiceFactory::ContextDestroyed(context); |
124 | |
125 // For unit tests, we also remove the factory function both so we don't | |
126 // maintain a big map of dead pointers, but also since we may have a second | |
127 // object that lives at the same address (see other comments about unit tests | |
128 // in this file). | |
129 testing_factories_.erase(context); | |
130 | |
131 BrowserContextKeyedBaseFactory::BrowserContextDestroyed(context); | |
132 } | 88 } |
133 | 89 |
134 void BrowserContextKeyedServiceFactory::SetEmptyTestingFactory( | 90 KeyedService* BrowserContextKeyedServiceFactory::BuildServiceInstanceFor( |
135 content::BrowserContext* context) { | 91 base::SupportsUserData* context) const { |
136 SetTestingFactory(context, NULL); | 92 return BuildServiceInstanceFor( |
| 93 static_cast<content::BrowserContext*>(context)); |
137 } | 94 } |
138 | 95 |
139 bool BrowserContextKeyedServiceFactory::HasTestingFactory( | 96 bool BrowserContextKeyedServiceFactory::IsOffTheRecord( |
140 content::BrowserContext* context) { | 97 base::SupportsUserData* context) const { |
141 return testing_factories_.find(context) != testing_factories_.end(); | 98 return static_cast<content::BrowserContext*>(context)->IsOffTheRecord(); |
142 } | 99 } |
143 | 100 |
144 void BrowserContextKeyedServiceFactory::CreateServiceNow( | 101 user_prefs::PrefRegistrySyncable* |
145 content::BrowserContext* context) { | 102 BrowserContextKeyedServiceFactory::GetAssociatedPrefRegistry( |
146 GetServiceForBrowserContext(context, true); | 103 base::SupportsUserData* context) const { |
| 104 // Safe timing for pref registration is hard. Previously, we made |
| 105 // BrowserContext responsible for all pref registration on every service |
| 106 // that used BrowserContext. Now we don't and there are timing issues. |
| 107 // |
| 108 // With normal contexts, prefs can simply be registered at |
| 109 // BrowserContextDependencyManager::RegisterProfilePrefsForServices time. |
| 110 // With incognito contexts, we just never register since incognito contexts |
| 111 // share the same pref services with their parent contexts. |
| 112 // |
| 113 // TestingBrowserContexts throw a wrench into the mix, in that some tests will |
| 114 // swap out the PrefService after we've registered user prefs on the original |
| 115 // PrefService. Test code that does this is responsible for either manually |
| 116 // invoking RegisterProfilePrefs() on the appropriate |
| 117 // BrowserContextKeyedServiceFactory associated with the prefs they need, |
| 118 // or they can use SetTestingFactory() and create a service (since service |
| 119 // creation with a factory method causes registration to happen at |
| 120 // TestingProfile creation time). |
| 121 // |
| 122 // Now that services are responsible for declaring their preferences, we have |
| 123 // to enforce a uniquenes check here because some tests create one context and |
| 124 // multiple services of the same type attached to that context (serially, not |
| 125 // parallel) and we don't want to register multiple times on the same context. |
| 126 // This is the purpose of RegisterProfilePrefsIfNecessary() which could be |
| 127 // replaced directly by RegisterProfilePrefs() if this method is ever phased |
| 128 // out. |
| 129 PrefService* prefs = user_prefs::UserPrefs::Get( |
| 130 static_cast<content::BrowserContext*>(context)); |
| 131 user_prefs::PrefRegistrySyncable* registry = |
| 132 static_cast<user_prefs::PrefRegistrySyncable*>( |
| 133 prefs->DeprecatedGetPrefRegistry()); |
| 134 return registry; |
147 } | 135 } |
| 136 |
| 137 base::SupportsUserData* BrowserContextKeyedServiceFactory::GetContextToUse( |
| 138 base::SupportsUserData* context) const { |
| 139 return GetBrowserContextToUse(static_cast<content::BrowserContext*>(context)); |
| 140 } |
| 141 |
| 142 bool BrowserContextKeyedServiceFactory::ServiceIsCreatedWithContext() const { |
| 143 return ServiceIsCreatedWithBrowserContext(); |
| 144 } |
| 145 |
| 146 void BrowserContextKeyedServiceFactory::ContextShutdown( |
| 147 base::SupportsUserData* context) { |
| 148 BrowserContextShutdown(static_cast<content::BrowserContext*>(context)); |
| 149 } |
| 150 |
| 151 void BrowserContextKeyedServiceFactory::ContextDestroyed( |
| 152 base::SupportsUserData* context) { |
| 153 BrowserContextDestroyed(static_cast<content::BrowserContext*>(context)); |
| 154 } |
| 155 |
| 156 void BrowserContextKeyedServiceFactory::RegisterPrefs( |
| 157 user_prefs::PrefRegistrySyncable* registry) { |
| 158 RegisterProfilePrefs(registry); |
| 159 } |
OLD | NEW |