summaryrefslogtreecommitdiffstats
path: root/chrome/browser/profiles/refcounted_profile_keyed_service_factory.cc
blob: d7eab48774e9def0410ed9f98a74ba673b46f7f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/profiles/refcounted_profile_keyed_service_factory.h"

#include "base/logging.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_keyed_service.h"
#include "chrome/browser/profiles/refcounted_profile_keyed_service.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;

void RefcountedProfileKeyedServiceFactory::SetTestingFactory(
    Profile* profile,
    FactoryFunction factory) {
  // Destroying the profile may cause us to lose data about whether |profile|
  // has our preferences registered on it (since the profile object itself
  // isn't dead). See if we need to readd it once we've gone through normal
  // destruction.
  bool add_profile = ArePreferencesSetOn(profile);

  // We have to go through the shutdown and destroy mechanisms because there
  // are unit tests that create a service on a profile and then change the
  // testing service mid-test.
  ProfileShutdown(profile);
  ProfileDestroyed(profile);

  if (add_profile)
    MarkPreferencesSetOn(profile);

  factories_[profile] = factory;
}

scoped_refptr<RefcountedProfileKeyedService>
RefcountedProfileKeyedServiceFactory::SetTestingFactoryAndUse(
    Profile* profile,
    FactoryFunction factory) {
  DCHECK(factory);
  SetTestingFactory(profile, factory);
  return GetServiceForProfile(profile, true);
}

RefcountedProfileKeyedServiceFactory::RefcountedProfileKeyedServiceFactory(
    const char* name,
    ProfileDependencyManager* manager)
    : ProfileKeyedBaseFactory(name, manager) {
}

RefcountedProfileKeyedServiceFactory::~RefcountedProfileKeyedServiceFactory() {
  DCHECK(mapping_.empty());
}

scoped_refptr<RefcountedProfileKeyedService>
RefcountedProfileKeyedServiceFactory::GetServiceForProfile(
    Profile* profile,
    bool create) {
  profile = GetProfileToUse(profile);
  if (!profile)
    return NULL;

  // NOTE: If you modify any of the logic below, make sure to update the
  // non-refcounted version in profile_keyed_service_factory.cc!
  scoped_refptr<RefcountedProfileKeyedService> service;
  RefCountedStorage::const_iterator it = mapping_.find(profile);
  if (it != mapping_.end()) {
    return it->second;
  } else if (create) {
    // Object not found, and we must create it.
    //
    // Check to see if we have a per-Profile testing factory that we should use
    // instead of default behavior.
    std::map<Profile*, FactoryFunction>::iterator jt = factories_.find(profile);
    if (jt != factories_.end()) {
      if (jt->second) {
        if (!profile->IsOffTheRecord())
          RegisterUserPrefsOnProfile(profile);
        service = jt->second(profile);
      } else {
        service = NULL;
      }
    } else {
      service = BuildServiceInstanceFor(profile);
    }
  } else {
    // Object not found, and we're forbidden from creating one.
    return NULL;
  }

  Associate(profile, service);
  return service;
}

void RefcountedProfileKeyedServiceFactory::Associate(
    Profile* profile,
    const scoped_refptr<RefcountedProfileKeyedService>& service) {
  DCHECK(mapping_.find(profile) == mapping_.end());
  mapping_.insert(std::make_pair(profile, service));
}

void RefcountedProfileKeyedServiceFactory::ProfileShutdown(Profile* profile) {
  RefCountedStorage::iterator it = mapping_.find(profile);
  if (it != mapping_.end() && it->second)
    it->second->ShutdownOnUIThread();
}

void RefcountedProfileKeyedServiceFactory::ProfileDestroyed(Profile* profile) {
  RefCountedStorage::iterator it = mapping_.find(profile);
  if (it != mapping_.end()) {
    // We "merely" drop our reference to the service. Hopefully this will cause
    // the service to be destroyed. If not, oh well.
    mapping_.erase(it);
  }

  // For unit tests, we also remove the factory function both so we don't
  // maintain a big map of dead pointers, but also since we may have a second
  // object that lives at the same address (see other comments about unit tests
  // in this file).
  factories_.erase(profile);

  ProfileKeyedBaseFactory::ProfileDestroyed(profile);
}

void RefcountedProfileKeyedServiceFactory::SetEmptyTestingFactory(
    Profile* profile) {
  SetTestingFactory(profile, NULL);
}

void RefcountedProfileKeyedServiceFactory::CreateServiceNow(Profile* profile) {
  GetServiceForProfile(profile, true);
}