1 // Copyright (c) 2013 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.
5 #include "chrome/browser/services/gcm/gcm_profile_service.h"
9 #include "base/logging.h"
10 #include "base/prefs/pref_service.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/common/pref_names.h"
13 #include "components/pref_registry/pref_registry_syncable.h"
15 #if defined(OS_ANDROID)
16 #include "components/gcm_driver/gcm_driver_android.h"
18 #include "base/bind.h"
19 #if defined(OS_CHROMEOS)
20 #include "chrome/browser/services/gcm/chromeos_gcm_connection_observer.h"
22 #include "base/files/file_path.h"
23 #include "base/memory/weak_ptr.h"
24 #include "chrome/browser/services/gcm/gcm_account_tracker.h"
25 #include "chrome/browser/services/gcm/gcm_desktop_utils.h"
26 #include "chrome/browser/signin/profile_identity_provider.h"
27 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
28 #include "chrome/browser/signin/signin_manager_factory.h"
29 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
30 #include "chrome/common/chrome_constants.h"
31 #include "components/gcm_driver/gcm_client_factory.h"
32 #include "components/gcm_driver/gcm_driver_desktop.h"
33 #include "components/signin/core/browser/signin_manager.h"
34 #include "google_apis/gaia/account_tracker.h"
35 #include "google_apis/gaia/identity_provider.h"
36 #include "net/url_request/url_request_context_getter.h"
41 #if !defined(OS_ANDROID)
42 // Identity observer only has actual work to do when the user is actually signed
43 // in. It ensures that account tracker is taking
44 class GCMProfileService::IdentityObserver
: public IdentityProvider::Observer
{
46 IdentityObserver(Profile
* profile
, GCMDriverDesktop
* driver
);
47 virtual ~IdentityObserver();
49 // IdentityProvider::Observer:
50 virtual void OnActiveAccountLogin() OVERRIDE
;
51 virtual void OnActiveAccountLogout() OVERRIDE
;
53 std::string
SignedInUserName() const;
55 // Called to inform IdentityObserver that a list of accounts was updated.
56 // |account_tokens| maps email addresses to OAuth2 access tokens.
58 const std::map
<std::string
, std::string
>& account_tokens
);
62 GCMDriverDesktop
* driver_
;
63 scoped_ptr
<IdentityProvider
> identity_provider_
;
64 scoped_ptr
<GCMAccountTracker
> gcm_account_tracker_
;
66 // The account ID that this service is responsible for. Empty when the service
68 std::string account_id_
;
70 base::WeakPtrFactory
<GCMProfileService::IdentityObserver
> weak_ptr_factory_
;
72 DISALLOW_COPY_AND_ASSIGN(IdentityObserver
);
75 GCMProfileService::IdentityObserver::IdentityObserver(Profile
* profile
,
76 GCMDriverDesktop
* driver
)
77 : profile_(profile
), driver_(driver
), weak_ptr_factory_(this) {
78 identity_provider_
.reset(new ProfileIdentityProvider(
79 SigninManagerFactory::GetForProfile(profile
),
80 ProfileOAuth2TokenServiceFactory::GetForProfile(profile
),
81 LoginUIServiceFactory::GetForProfile(profile
)));
82 identity_provider_
->AddObserver(this);
84 OnActiveAccountLogin();
87 GCMProfileService::IdentityObserver::~IdentityObserver() {
88 if (gcm_account_tracker_
)
89 gcm_account_tracker_
->Shutdown();
90 identity_provider_
->RemoveObserver(this);
93 void GCMProfileService::IdentityObserver::OnActiveAccountLogin() {
94 // This might be called multiple times when the password changes.
95 const std::string account_id
= identity_provider_
->GetActiveAccountId();
96 if (account_id
== account_id_
)
98 account_id_
= account_id
;
100 driver_
->OnSignedIn();
102 if (!gcm_account_tracker_
) {
103 scoped_ptr
<gaia::AccountTracker
> gaia_account_tracker(
104 new gaia::AccountTracker(identity_provider_
.get(),
105 profile_
->GetRequestContext()));
107 gcm_account_tracker_
.reset(new GCMAccountTracker(
108 gaia_account_tracker
.Pass(),
109 base::Bind(&GCMProfileService::IdentityObserver::AccountsUpdated
,
110 weak_ptr_factory_
.GetWeakPtr())));
113 gcm_account_tracker_
->Start();
116 void GCMProfileService::IdentityObserver::OnActiveAccountLogout() {
119 // Check is necessary to not crash browser_tests.
120 if (gcm_account_tracker_
)
121 gcm_account_tracker_
->Stop();
122 // When sign-in enforcement is not dropped, OnSignedOut will also clear all
123 // the GCM data and a new GCM ID will be retrieved after the user signs in
124 // again. Otherwise, the user sign-out will not affect the existing GCM
126 driver_
->OnSignedOut();
129 std::string
GCMProfileService::IdentityObserver::SignedInUserName() const {
130 return driver_
->IsStarted() ? account_id_
: std::string();
133 void GCMProfileService::IdentityObserver::AccountsUpdated(
134 const std::map
<std::string
, std::string
>& account_tokens
) {
135 driver_
->SetAccountsForCheckin(account_tokens
);
137 #endif // !defined(OS_ANDROID)
140 bool GCMProfileService::IsGCMEnabled(Profile
* profile
) {
141 return profile
->GetPrefs()->GetBoolean(prefs::kGCMChannelEnabled
);
145 void GCMProfileService::RegisterProfilePrefs(
146 user_prefs::PrefRegistrySyncable
* registry
) {
147 registry
->RegisterBooleanPref(
148 prefs::kGCMChannelEnabled
,
150 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
151 PushMessagingServiceImpl::RegisterProfilePrefs(registry
);
154 #if defined(OS_ANDROID)
155 GCMProfileService::GCMProfileService(Profile
* profile
)
157 push_messaging_service_(this, profile
) {
158 DCHECK(!profile
->IsOffTheRecord());
160 driver_
.reset(new GCMDriverAndroid
);
163 GCMProfileService::GCMProfileService(
165 scoped_ptr
<GCMClientFactory
> gcm_client_factory
)
167 push_messaging_service_(this, profile
) {
168 DCHECK(!profile
->IsOffTheRecord());
170 driver_
= CreateGCMDriverDesktop(
171 gcm_client_factory
.Pass(),
172 profile_
->GetPath().Append(chrome::kGCMStoreDirname
),
173 profile_
->GetRequestContext());
176 chromeos_connection_observer_
.reset(new gcm::ChromeOSGCMConnectionObserver
);
177 driver_
->AddConnectionObserver(chromeos_connection_observer_
.get());
180 identity_observer_
.reset(new IdentityObserver(
181 profile
, static_cast<gcm::GCMDriverDesktop
*>(driver_
.get())));
183 #endif // defined(OS_ANDROID)
185 GCMProfileService::GCMProfileService()
187 push_messaging_service_(this, NULL
) {
190 GCMProfileService::~GCMProfileService() {
193 void GCMProfileService::AddAppHandler(const std::string
& app_id
,
194 GCMAppHandler
* handler
) {
196 driver_
->AddAppHandler(app_id
, handler
);
199 void GCMProfileService::RemoveAppHandler(const std::string
& app_id
) {
201 driver_
->RemoveAppHandler(app_id
);
204 void GCMProfileService::Register(const std::string
& app_id
,
205 const std::vector
<std::string
>& sender_ids
,
206 const GCMDriver::RegisterCallback
& callback
) {
208 driver_
->Register(app_id
, sender_ids
, callback
);
211 void GCMProfileService::Shutdown() {
212 #if !defined(OS_ANDROID)
213 identity_observer_
.reset();
214 #endif // !defined(OS_ANDROID)
215 #if defined(OS_CHROMEOS)
216 driver_
->RemoveConnectionObserver(chromeos_connection_observer_
.get());
217 chromeos_connection_observer_
.reset();
226 std::string
GCMProfileService::SignedInUserName() const {
227 #if defined(OS_ANDROID)
228 return std::string();
230 return identity_observer_
? identity_observer_
->SignedInUserName()
232 #endif // defined(OS_ANDROID)
235 void GCMProfileService::SetDriverForTesting(GCMDriver
* driver
) {
236 driver_
.reset(driver
);