1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <map>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/stl_util.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/keyed_service/content/browser_context_dependency_manager.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/keyed_service/core/keyed_service.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/public/browser/browser_context.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void BrowserContextKeyedServiceFactory::SetTestingFactory(
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    content::BrowserContext* context,
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TestingFactoryFunction testing_factory) {
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Destroying the context may cause us to lose data about whether |context|
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // has our preferences registered on it (since the context object itself
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // isn't dead). See if we need to readd it once we've gone through normal
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // destruction.
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool add_context = ArePreferencesSetOn(context);
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef NDEBUG
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Ensure that |context| is not marked as stale (e.g., due to it aliasing an
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // instance that was destroyed in an earlier test) in order to avoid accesses
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // to |context| in |BrowserContextShutdown| from causing
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |AssertBrowserContextWasntDestroyed| to raise an error.
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dependency_manager_->MarkBrowserContextLiveForTesting(context);
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // We have to go through the shutdown and destroy mechanisms because there
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // are unit tests that create a service on a context and then change the
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // testing service mid-test.
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  BrowserContextShutdown(context);
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  BrowserContextDestroyed(context);
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (add_context)
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    MarkPreferencesSetOn(context);
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  testing_factories_[context] = testing_factory;
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)KeyedService* BrowserContextKeyedServiceFactory::SetTestingFactoryAndUse(
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    content::BrowserContext* context,
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    TestingFactoryFunction testing_factory) {
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(testing_factory);
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SetTestingFactory(context, testing_factory);
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return GetServiceForBrowserContext(context, true);
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)BrowserContextKeyedServiceFactory::BrowserContextKeyedServiceFactory(
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const char* name,
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BrowserContextDependencyManager* manager)
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : BrowserContextKeyedBaseFactory(name, manager) {}
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)BrowserContextKeyedServiceFactory::~BrowserContextKeyedServiceFactory() {
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(mapping_.empty());
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)KeyedService* BrowserContextKeyedServiceFactory::GetServiceForBrowserContext(
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    content::BrowserContext* context,
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    bool create) {
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  context = GetBrowserContextToUse(context);
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!context)
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return NULL;
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // NOTE: If you modify any of the logic below, make sure to update the
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // refcounted version in refcounted_context_keyed_service_factory.cc!
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  BrowserContextKeyedServices::const_iterator it = mapping_.find(context);
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (it != mapping_.end())
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return it->second;
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Object not found.
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!create)
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return NULL;  // And we're forbidden from creating one.
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Create new object.
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check to see if we have a per-BrowserContext testing factory that we should
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // use instead of default behavior.
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  KeyedService* service = NULL;
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BrowserContextOverriddenTestingFunctions::const_iterator jt =
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      testing_factories_.find(context);
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (jt != testing_factories_.end()) {
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (jt->second) {
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!context->IsOffTheRecord())
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        RegisterUserPrefsOnBrowserContextForTest(context);
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      service = jt->second(context);
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    service = BuildServiceInstanceFor(context);
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Associate(context, service);
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return service;
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void BrowserContextKeyedServiceFactory::Associate(
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    content::BrowserContext* context,
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    KeyedService* service) {
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!ContainsKey(mapping_, context));
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mapping_.insert(std::make_pair(context, service));
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void BrowserContextKeyedServiceFactory::Disassociate(
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::BrowserContext* context) {
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BrowserContextKeyedServices::iterator it = mapping_.find(context);
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (it != mapping_.end()) {
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    delete it->second;
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    mapping_.erase(it);
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void BrowserContextKeyedServiceFactory::BrowserContextShutdown(
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    content::BrowserContext* context) {
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  BrowserContextKeyedServices::iterator it = mapping_.find(context);
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (it != mapping_.end() && it->second)
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    it->second->Shutdown();
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void BrowserContextKeyedServiceFactory::BrowserContextDestroyed(
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    content::BrowserContext* context) {
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Disassociate(context);
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // For unit tests, we also remove the factory function both so we don't
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // maintain a big map of dead pointers, but also since we may have a second
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // object that lives at the same address (see other comments about unit tests
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // in this file).
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  testing_factories_.erase(context);
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  BrowserContextKeyedBaseFactory::BrowserContextDestroyed(context);
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void BrowserContextKeyedServiceFactory::SetEmptyTestingFactory(
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    content::BrowserContext* context) {
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetTestingFactory(context, NULL);
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool BrowserContextKeyedServiceFactory::HasTestingFactory(
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::BrowserContext* context) {
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return testing_factories_.find(context) != testing_factories_.end();
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void BrowserContextKeyedServiceFactory::CreateServiceNow(
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    content::BrowserContext* context) {
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GetServiceForBrowserContext(context, true);
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
148