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 "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
6
7#include "base/memory/scoped_ptr.h"
8#include "base/prefs/pref_registry.h"
9#include "chrome/browser/browser_process.h"
10#include "chrome/browser/invalidation/ticl_profile_settings_provider.h"
11#include "chrome/browser/profiles/profile.h"
12#include "chrome/browser/services/gcm/gcm_profile_service.h"
13#include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
14#include "chrome/browser/signin/profile_identity_provider.h"
15#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
16#include "chrome/browser/signin/signin_manager_factory.h"
17#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
18#include "chrome/common/chrome_content_client.h"
19#include "chrome/common/pref_names.h"
20#include "components/invalidation/invalidation_service.h"
21#include "components/invalidation/invalidation_state_tracker.h"
22#include "components/invalidation/invalidator_storage.h"
23#include "components/invalidation/profile_invalidation_provider.h"
24#include "components/invalidation/ticl_invalidation_service.h"
25#include "components/invalidation/ticl_settings_provider.h"
26#include "components/keyed_service/content/browser_context_dependency_manager.h"
27#include "components/pref_registry/pref_registry_syncable.h"
28#include "components/signin/core/browser/profile_oauth2_token_service.h"
29#include "components/signin/core/browser/signin_manager.h"
30#include "net/url_request/url_request_context_getter.h"
31
32#if defined(OS_ANDROID)
33#include "chrome/browser/invalidation/invalidation_controller_android.h"
34#include "chrome/browser/invalidation/invalidation_service_android.h"
35#endif  // defined(OS_ANDROID)
36
37#if defined(OS_CHROMEOS)
38#include "base/files/file_path.h"
39#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
40#include "chrome/browser/chromeos/profiles/profile_helper.h"
41#include "chrome/browser/chromeos/settings/device_identity_provider.h"
42#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
43#include "components/user_manager/user_manager.h"
44#endif
45
46namespace invalidation {
47
48// static
49ProfileInvalidationProvider* ProfileInvalidationProviderFactory::GetForProfile(
50    Profile* profile) {
51#if defined(OS_CHROMEOS)
52  // Using ProfileHelper::GetSigninProfile() here would lead to an infinite loop
53  // when this method is called during the creation of the sign-in profile
54  // itself. Using ProfileHelper::GetSigninProfileDir() is safe because it does
55  // not try to access the sign-in profile.
56  if (profile->GetPath() == chromeos::ProfileHelper::GetSigninProfileDir() ||
57      (user_manager::UserManager::IsInitialized() &&
58       user_manager::UserManager::Get()->IsLoggedInAsGuest())) {
59    // The Chrome OS login and Chrome OS guest profiles do not have GAIA
60    // credentials and do not support invalidation.
61    return NULL;
62  }
63#endif
64  return static_cast<ProfileInvalidationProvider*>(
65      GetInstance()->GetServiceForBrowserContext(profile, true));
66}
67
68// static
69ProfileInvalidationProviderFactory*
70ProfileInvalidationProviderFactory::GetInstance() {
71  return Singleton<ProfileInvalidationProviderFactory>::get();
72}
73
74ProfileInvalidationProviderFactory::ProfileInvalidationProviderFactory()
75    : BrowserContextKeyedServiceFactory(
76        "InvalidationService",
77        BrowserContextDependencyManager::GetInstance()),
78      testing_factory_(NULL) {
79#if !defined(OS_ANDROID)
80  DependsOn(SigninManagerFactory::GetInstance());
81  DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
82  DependsOn(gcm::GCMProfileServiceFactory::GetInstance());
83  DependsOn(LoginUIServiceFactory::GetInstance());
84#endif
85}
86
87ProfileInvalidationProviderFactory::~ProfileInvalidationProviderFactory() {
88}
89
90void ProfileInvalidationProviderFactory::RegisterTestingFactory(
91    TestingFactoryFunction testing_factory) {
92  testing_factory_ = testing_factory;
93}
94
95KeyedService* ProfileInvalidationProviderFactory::BuildServiceInstanceFor(
96    content::BrowserContext* context) const {
97  Profile* profile = static_cast<Profile*>(context);
98
99  if (testing_factory_)
100    return testing_factory_(context);
101
102#if defined(OS_ANDROID)
103  return new ProfileInvalidationProvider(scoped_ptr<InvalidationService>(
104      new InvalidationServiceAndroid(profile,
105                                     new InvalidationControllerAndroid())));
106#else
107
108  scoped_ptr<IdentityProvider> identity_provider;
109
110#if defined(OS_CHROMEOS)
111  policy::BrowserPolicyConnectorChromeOS* connector =
112      g_browser_process->platform_part()->browser_policy_connector_chromeos();
113  if (user_manager::UserManager::IsInitialized() &&
114      user_manager::UserManager::Get()->IsLoggedInAsKioskApp() &&
115      connector->IsEnterpriseManaged()) {
116    identity_provider.reset(new chromeos::DeviceIdentityProvider(
117        chromeos::DeviceOAuth2TokenServiceFactory::Get()));
118  }
119#endif
120
121  if (!identity_provider) {
122    identity_provider.reset(new ProfileIdentityProvider(
123        SigninManagerFactory::GetForProfile(profile),
124        ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
125        LoginUIServiceFactory::GetForProfile(profile)));
126  }
127
128  scoped_ptr<TiclInvalidationService> service(new TiclInvalidationService(
129      GetUserAgent(),
130      identity_provider.Pass(),
131      scoped_ptr<TiclSettingsProvider>(
132          new TiclProfileSettingsProvider(profile)),
133      gcm::GCMProfileServiceFactory::GetForProfile(profile)->driver(),
134      profile->GetRequestContext()));
135  service->Init(scoped_ptr<syncer::InvalidationStateTracker>(
136      new InvalidatorStorage(profile->GetPrefs())));
137
138  return new ProfileInvalidationProvider(service.PassAs<InvalidationService>());
139#endif
140}
141
142void ProfileInvalidationProviderFactory::RegisterProfilePrefs(
143    user_prefs::PrefRegistrySyncable* registry) {
144  registry->RegisterBooleanPref(
145      prefs::kInvalidationServiceUseGCMChannel,
146      true,  // if no value in prefs, use GCM channel.
147      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
148  InvalidatorStorage::RegisterProfilePrefs(registry);
149}
150
151}  // namespace invalidation
152