Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: components/keyed_service/content/browser_context_keyed_service_factory.cc

Issue 654753010: Refactor (Refcounted)BrowserContextKeyedServiceFactory (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698