• 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/refcounted_browser_context_keyed_service_factory.h"
6 
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "components/keyed_service/content/refcounted_browser_context_keyed_service.h"
10 #include "components/keyed_service/core/keyed_service.h"
11 #include "content/public/browser/browser_context.h"
12 
SetTestingFactory(content::BrowserContext * context,TestingFactoryFunction testing_factory)13 void RefcountedBrowserContextKeyedServiceFactory::SetTestingFactory(
14     content::BrowserContext* context,
15     TestingFactoryFunction testing_factory) {
16   // Destroying the context may cause us to lose data about whether |context|
17   // has our preferences registered on it (since the context object itself
18   // isn't dead). See if we need to readd it once we've gone through normal
19   // destruction.
20   bool add_context = ArePreferencesSetOn(context);
21 
22   // We have to go through the shutdown and destroy mechanisms because there
23   // are unit tests that create a service on a context and then change the
24   // testing service mid-test.
25   BrowserContextShutdown(context);
26   BrowserContextDestroyed(context);
27 
28   if (add_context)
29     MarkPreferencesSetOn(context);
30 
31   testing_factories_[context] = testing_factory;
32 }
33 
34 scoped_refptr<RefcountedBrowserContextKeyedService>
SetTestingFactoryAndUse(content::BrowserContext * context,TestingFactoryFunction testing_factory)35 RefcountedBrowserContextKeyedServiceFactory::SetTestingFactoryAndUse(
36     content::BrowserContext* context,
37     TestingFactoryFunction testing_factory) {
38   DCHECK(testing_factory);
39   SetTestingFactory(context, testing_factory);
40   return GetServiceForBrowserContext(context, true);
41 }
42 
43 RefcountedBrowserContextKeyedServiceFactory::
RefcountedBrowserContextKeyedServiceFactory(const char * name,BrowserContextDependencyManager * manager)44     RefcountedBrowserContextKeyedServiceFactory(
45         const char* name,
46         BrowserContextDependencyManager* manager)
47     : BrowserContextKeyedBaseFactory(name, manager) {}
48 
49 RefcountedBrowserContextKeyedServiceFactory::
~RefcountedBrowserContextKeyedServiceFactory()50     ~RefcountedBrowserContextKeyedServiceFactory() {
51   DCHECK(mapping_.empty());
52 }
53 
54 scoped_refptr<RefcountedBrowserContextKeyedService>
GetServiceForBrowserContext(content::BrowserContext * context,bool create)55 RefcountedBrowserContextKeyedServiceFactory::GetServiceForBrowserContext(
56     content::BrowserContext* context,
57     bool create) {
58   context = GetBrowserContextToUse(context);
59   if (!context)
60     return NULL;
61 
62   // NOTE: If you modify any of the logic below, make sure to update the
63   // non-refcounted version in context_keyed_service_factory.cc!
64   RefCountedStorage::const_iterator it = mapping_.find(context);
65   if (it != mapping_.end())
66     return it->second;
67 
68   // Object not found.
69   if (!create)
70     return NULL;  // And we're forbidden from creating one.
71 
72   // Create new object.
73   // Check to see if we have a per-BrowserContext testing factory that we should
74   // use instead of default behavior.
75   scoped_refptr<RefcountedBrowserContextKeyedService> service;
76   BrowserContextOverriddenTestingFunctions::const_iterator jt =
77       testing_factories_.find(context);
78   if (jt != testing_factories_.end()) {
79     if (jt->second) {
80       if (!context->IsOffTheRecord())
81         RegisterUserPrefsOnBrowserContextForTest(context);
82       service = jt->second(context);
83     }
84   } else {
85     service = BuildServiceInstanceFor(context);
86   }
87 
88   Associate(context, service);
89   return service;
90 }
91 
Associate(content::BrowserContext * context,const scoped_refptr<RefcountedBrowserContextKeyedService> & service)92 void RefcountedBrowserContextKeyedServiceFactory::Associate(
93     content::BrowserContext* context,
94     const scoped_refptr<RefcountedBrowserContextKeyedService>& service) {
95   DCHECK(!ContainsKey(mapping_, context));
96   mapping_.insert(std::make_pair(context, service));
97 }
98 
BrowserContextShutdown(content::BrowserContext * context)99 void RefcountedBrowserContextKeyedServiceFactory::BrowserContextShutdown(
100     content::BrowserContext* context) {
101   RefCountedStorage::iterator it = mapping_.find(context);
102   if (it != mapping_.end() && it->second.get())
103     it->second->ShutdownOnUIThread();
104 }
105 
BrowserContextDestroyed(content::BrowserContext * context)106 void RefcountedBrowserContextKeyedServiceFactory::BrowserContextDestroyed(
107     content::BrowserContext* context) {
108   // We "merely" drop our reference to the service. Hopefully this will cause
109   // the service to be destroyed. If not, oh well.
110   mapping_.erase(context);
111 
112   // For unit tests, we also remove the factory function both so we don't
113   // maintain a big map of dead pointers, but also since we may have a second
114   // object that lives at the same address (see other comments about unit tests
115   // in this file).
116   testing_factories_.erase(context);
117 
118   BrowserContextKeyedBaseFactory::BrowserContextDestroyed(context);
119 }
120 
SetEmptyTestingFactory(content::BrowserContext * context)121 void RefcountedBrowserContextKeyedServiceFactory::SetEmptyTestingFactory(
122     content::BrowserContext* context) {
123   SetTestingFactory(context, NULL);
124 }
125 
HasTestingFactory(content::BrowserContext * context)126 bool RefcountedBrowserContextKeyedServiceFactory::HasTestingFactory(
127     content::BrowserContext* context) {
128   return testing_factories_.find(context) != testing_factories_.end();
129 }
130 
CreateServiceNow(content::BrowserContext * context)131 void RefcountedBrowserContextKeyedServiceFactory::CreateServiceNow(
132     content::BrowserContext* context) {
133   GetServiceForBrowserContext(context, true);
134 }
135