• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
6 
7 #include <map>
8 
9 #include "base/logging.h"
10 #include "base/stl_util.h"
11 #include "components/keyed_service/content/browser_context_dependency_manager.h"
12 #include "components/keyed_service/core/keyed_service.h"
13 #include "content/public/browser/browser_context.h"
14 
SetTestingFactory(content::BrowserContext * context,TestingFactoryFunction testing_factory)15 void BrowserContextKeyedServiceFactory::SetTestingFactory(
16     content::BrowserContext* context,
17     TestingFactoryFunction testing_factory) {
18   // Destroying the context may cause us to lose data about whether |context|
19   // has our preferences registered on it (since the context object itself
20   // isn't dead). See if we need to readd it once we've gone through normal
21   // destruction.
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   dependency_manager_->MarkBrowserContextLiveForTesting(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 }
43 
SetTestingFactoryAndUse(content::BrowserContext * context,TestingFactoryFunction testing_factory)44 KeyedService* BrowserContextKeyedServiceFactory::SetTestingFactoryAndUse(
45     content::BrowserContext* context,
46     TestingFactoryFunction testing_factory) {
47   DCHECK(testing_factory);
48   SetTestingFactory(context, testing_factory);
49   return GetServiceForBrowserContext(context, true);
50 }
51 
BrowserContextKeyedServiceFactory(const char * name,BrowserContextDependencyManager * manager)52 BrowserContextKeyedServiceFactory::BrowserContextKeyedServiceFactory(
53     const char* name,
54     BrowserContextDependencyManager* manager)
55     : BrowserContextKeyedBaseFactory(name, manager) {}
56 
~BrowserContextKeyedServiceFactory()57 BrowserContextKeyedServiceFactory::~BrowserContextKeyedServiceFactory() {
58   DCHECK(mapping_.empty());
59 }
60 
GetServiceForBrowserContext(content::BrowserContext * context,bool create)61 KeyedService* BrowserContextKeyedServiceFactory::GetServiceForBrowserContext(
62     content::BrowserContext* context,
63     bool create) {
64   context = GetBrowserContextToUse(context);
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 }
97 
Associate(content::BrowserContext * context,KeyedService * service)98 void BrowserContextKeyedServiceFactory::Associate(
99     content::BrowserContext* context,
100     KeyedService* service) {
101   DCHECK(!ContainsKey(mapping_, context));
102   mapping_.insert(std::make_pair(context, service));
103 }
104 
Disassociate(content::BrowserContext * context)105 void BrowserContextKeyedServiceFactory::Disassociate(
106     content::BrowserContext* context) {
107   BrowserContextKeyedServices::iterator it = mapping_.find(context);
108   if (it != mapping_.end()) {
109     delete it->second;
110     mapping_.erase(it);
111   }
112 }
113 
BrowserContextShutdown(content::BrowserContext * context)114 void BrowserContextKeyedServiceFactory::BrowserContextShutdown(
115     content::BrowserContext* context) {
116   BrowserContextKeyedServices::iterator it = mapping_.find(context);
117   if (it != mapping_.end() && it->second)
118     it->second->Shutdown();
119 }
120 
BrowserContextDestroyed(content::BrowserContext * context)121 void BrowserContextKeyedServiceFactory::BrowserContextDestroyed(
122     content::BrowserContext* context) {
123   Disassociate(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 }
133 
SetEmptyTestingFactory(content::BrowserContext * context)134 void BrowserContextKeyedServiceFactory::SetEmptyTestingFactory(
135     content::BrowserContext* context) {
136   SetTestingFactory(context, NULL);
137 }
138 
HasTestingFactory(content::BrowserContext * context)139 bool BrowserContextKeyedServiceFactory::HasTestingFactory(
140     content::BrowserContext* context) {
141   return testing_factories_.find(context) != testing_factories_.end();
142 }
143 
CreateServiceNow(content::BrowserContext * context)144 void BrowserContextKeyedServiceFactory::CreateServiceNow(
145     content::BrowserContext* context) {
146   GetServiceForBrowserContext(context, true);
147 }
148