• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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/browser_context_keyed_service/refcounted_browser_context_keyed_service_factory.h"
6 
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "content/public/browser/browser_context.h"
10 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
11 #include "components/browser_context_keyed_service/refcounted_browser_context_keyed_service.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 
50 RefcountedBrowserContextKeyedServiceFactory::
~RefcountedBrowserContextKeyedServiceFactory()51 ~RefcountedBrowserContextKeyedServiceFactory() {
52   DCHECK(mapping_.empty());
53 }
54 
55 scoped_refptr<RefcountedBrowserContextKeyedService>
GetServiceForBrowserContext(content::BrowserContext * context,bool create)56 RefcountedBrowserContextKeyedServiceFactory::GetServiceForBrowserContext(
57     content::BrowserContext* context,
58     bool create) {
59   context = GetBrowserContextToUse(context);
60   if (!context)
61     return NULL;
62 
63   // NOTE: If you modify any of the logic below, make sure to update the
64   // non-refcounted version in context_keyed_service_factory.cc!
65   RefCountedStorage::const_iterator it = mapping_.find(context);
66   if (it != mapping_.end())
67     return it->second;
68 
69   // Object not found.
70   if (!create)
71     return NULL;  // And we're forbidden from creating one.
72 
73   // Create new object.
74   // Check to see if we have a per-BrowserContext testing factory that we should
75   // use instead of default behavior.
76   scoped_refptr<RefcountedBrowserContextKeyedService> service;
77   BrowserContextOverriddenTestingFunctions::const_iterator jt =
78       testing_factories_.find(context);
79   if (jt != testing_factories_.end()) {
80     if (jt->second) {
81       if (!context->IsOffTheRecord())
82         RegisterUserPrefsOnBrowserContextForTest(context);
83       service = jt->second(context);
84     }
85   } else {
86     service = BuildServiceInstanceFor(context);
87   }
88 
89   Associate(context, service);
90   return service;
91 }
92 
Associate(content::BrowserContext * context,const scoped_refptr<RefcountedBrowserContextKeyedService> & service)93 void RefcountedBrowserContextKeyedServiceFactory::Associate(
94     content::BrowserContext* context,
95     const scoped_refptr<RefcountedBrowserContextKeyedService>& service) {
96   DCHECK(!ContainsKey(mapping_, context));
97   mapping_.insert(std::make_pair(context, service));
98 }
99 
BrowserContextShutdown(content::BrowserContext * context)100 void RefcountedBrowserContextKeyedServiceFactory::BrowserContextShutdown(
101     content::BrowserContext* context) {
102   RefCountedStorage::iterator it = mapping_.find(context);
103   if (it != mapping_.end() && it->second.get())
104     it->second->ShutdownOnUIThread();
105 }
106 
BrowserContextDestroyed(content::BrowserContext * context)107 void RefcountedBrowserContextKeyedServiceFactory::BrowserContextDestroyed(
108     content::BrowserContext* context) {
109   // We "merely" drop our reference to the service. Hopefully this will cause
110   // the service to be destroyed. If not, oh well.
111   mapping_.erase(context);
112 
113   // For unit tests, we also remove the factory function both so we don't
114   // maintain a big map of dead pointers, but also since we may have a second
115   // object that lives at the same address (see other comments about unit tests
116   // in this file).
117   testing_factories_.erase(context);
118 
119   BrowserContextKeyedBaseFactory::BrowserContextDestroyed(context);
120 }
121 
SetEmptyTestingFactory(content::BrowserContext * context)122 void RefcountedBrowserContextKeyedServiceFactory::SetEmptyTestingFactory(
123     content::BrowserContext* context) {
124   SetTestingFactory(context, NULL);
125 }
126 
CreateServiceNow(content::BrowserContext * context)127 void RefcountedBrowserContextKeyedServiceFactory::CreateServiceNow(
128     content::BrowserContext* context) {
129   GetServiceForBrowserContext(context, true);
130 }
131