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 13void 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 34scoped_refptr<RefcountedBrowserContextKeyedService> 35RefcountedBrowserContextKeyedServiceFactory::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 43RefcountedBrowserContextKeyedServiceFactory:: 44 RefcountedBrowserContextKeyedServiceFactory( 45 const char* name, 46 BrowserContextDependencyManager* manager) 47 : BrowserContextKeyedBaseFactory(name, manager) {} 48 49RefcountedBrowserContextKeyedServiceFactory:: 50 ~RefcountedBrowserContextKeyedServiceFactory() { 51 DCHECK(mapping_.empty()); 52} 53 54scoped_refptr<RefcountedBrowserContextKeyedService> 55RefcountedBrowserContextKeyedServiceFactory::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 92void 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 99void 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 106void 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 121void RefcountedBrowserContextKeyedServiceFactory::SetEmptyTestingFactory( 122 content::BrowserContext* context) { 123 SetTestingFactory(context, NULL); 124} 125 126bool RefcountedBrowserContextKeyedServiceFactory::HasTestingFactory( 127 content::BrowserContext* context) { 128 return testing_factories_.find(context) != testing_factories_.end(); 129} 130 131void RefcountedBrowserContextKeyedServiceFactory::CreateServiceNow( 132 content::BrowserContext* context) { 133 GetServiceForBrowserContext(context, true); 134} 135