gcm_profile_service.cc revision 1675a649fd7a8b3cb80ffddae2dc181f122353c5
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. 4 5#include "chrome/browser/services/gcm/gcm_profile_service.h" 6 7#include <map> 8 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" 14 15#if defined(OS_ANDROID) 16#include "components/gcm_driver/gcm_driver_android.h" 17#else 18#include "base/bind.h" 19#if defined(OS_CHROMEOS) 20#include "chrome/browser/services/gcm/chromeos_gcm_connection_observer.h" 21#endif 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" 37#endif 38 39namespace gcm { 40 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 44class GCMProfileService::IdentityObserver : public IdentityProvider::Observer { 45 public: 46 IdentityObserver(Profile* profile, GCMDriverDesktop* driver); 47 virtual ~IdentityObserver(); 48 49 // IdentityProvider::Observer: 50 virtual void OnActiveAccountLogin() OVERRIDE; 51 virtual void OnActiveAccountLogout() OVERRIDE; 52 53 std::string SignedInUserName() const; 54 55 // Called to inform IdentityObserver that a list of accounts was updated. 56 // |account_tokens| maps email addresses to OAuth2 access tokens. 57 void AccountsUpdated( 58 const std::map<std::string, std::string>& account_tokens); 59 60 private: 61 Profile* profile_; 62 GCMDriverDesktop* driver_; 63 scoped_ptr<IdentityProvider> identity_provider_; 64 scoped_ptr<GCMAccountTracker> gcm_account_tracker_; 65 66 // The account ID that this service is responsible for. Empty when the service 67 // is not running. 68 std::string account_id_; 69 70 base::WeakPtrFactory<GCMProfileService::IdentityObserver> weak_ptr_factory_; 71 72 DISALLOW_COPY_AND_ASSIGN(IdentityObserver); 73}; 74 75GCMProfileService::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); 83 84 OnActiveAccountLogin(); 85} 86 87GCMProfileService::IdentityObserver::~IdentityObserver() { 88 if (gcm_account_tracker_) 89 gcm_account_tracker_->Shutdown(); 90 identity_provider_->RemoveObserver(this); 91} 92 93void 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_) 97 return; 98 account_id_ = account_id; 99 100 driver_->OnSignedIn(); 101 102 if (!gcm_account_tracker_) { 103 scoped_ptr<gaia::AccountTracker> gaia_account_tracker( 104 new gaia::AccountTracker(identity_provider_.get(), 105 profile_->GetRequestContext())); 106 107 gcm_account_tracker_.reset(new GCMAccountTracker( 108 gaia_account_tracker.Pass(), 109 base::Bind(&GCMProfileService::IdentityObserver::AccountsUpdated, 110 weak_ptr_factory_.GetWeakPtr()))); 111 } 112 113 gcm_account_tracker_->Start(); 114} 115 116void GCMProfileService::IdentityObserver::OnActiveAccountLogout() { 117 account_id_.clear(); 118 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 125 // data. 126 driver_->OnSignedOut(); 127} 128 129std::string GCMProfileService::IdentityObserver::SignedInUserName() const { 130 return driver_->IsStarted() ? account_id_ : std::string(); 131} 132 133void GCMProfileService::IdentityObserver::AccountsUpdated( 134 const std::map<std::string, std::string>& account_tokens) { 135 driver_->SetAccountsForCheckin(account_tokens); 136} 137#endif // !defined(OS_ANDROID) 138 139// static 140bool GCMProfileService::IsGCMEnabled(Profile* profile) { 141 return profile->GetPrefs()->GetBoolean(prefs::kGCMChannelEnabled); 142} 143 144// static 145void GCMProfileService::RegisterProfilePrefs( 146 user_prefs::PrefRegistrySyncable* registry) { 147 registry->RegisterBooleanPref( 148 prefs::kGCMChannelEnabled, 149 true, 150 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 151 PushMessagingServiceImpl::RegisterProfilePrefs(registry); 152} 153 154#if defined(OS_ANDROID) 155GCMProfileService::GCMProfileService(Profile* profile) 156 : profile_(profile), 157 push_messaging_service_(this, profile) { 158 DCHECK(!profile->IsOffTheRecord()); 159 160 driver_.reset(new GCMDriverAndroid); 161} 162#else 163GCMProfileService::GCMProfileService( 164 Profile* profile, 165 scoped_ptr<GCMClientFactory> gcm_client_factory) 166 : profile_(profile), 167 push_messaging_service_(this, profile) { 168 DCHECK(!profile->IsOffTheRecord()); 169 170 driver_ = CreateGCMDriverDesktop( 171 gcm_client_factory.Pass(), 172 profile_->GetPrefs(), 173 profile_->GetPath().Append(chrome::kGCMStoreDirname), 174 profile_->GetRequestContext()); 175 176#if defined(OS_CHROMEOS) 177 chromeos_connection_observer_.reset(new gcm::ChromeOSGCMConnectionObserver); 178 driver_->AddConnectionObserver(chromeos_connection_observer_.get()); 179#endif 180 181 identity_observer_.reset(new IdentityObserver( 182 profile, static_cast<gcm::GCMDriverDesktop*>(driver_.get()))); 183} 184#endif // defined(OS_ANDROID) 185 186GCMProfileService::GCMProfileService() 187 : profile_(NULL), 188 push_messaging_service_(this, NULL) { 189} 190 191GCMProfileService::~GCMProfileService() { 192} 193 194void GCMProfileService::AddAppHandler(const std::string& app_id, 195 GCMAppHandler* handler) { 196 if (driver_) 197 driver_->AddAppHandler(app_id, handler); 198} 199 200void GCMProfileService::RemoveAppHandler(const std::string& app_id) { 201 if (driver_) 202 driver_->RemoveAppHandler(app_id); 203} 204 205void GCMProfileService::Register(const std::string& app_id, 206 const std::vector<std::string>& sender_ids, 207 const GCMDriver::RegisterCallback& callback) { 208 if (driver_) 209 driver_->Register(app_id, sender_ids, callback); 210} 211 212void GCMProfileService::Shutdown() { 213#if !defined(OS_ANDROID) 214 identity_observer_.reset(); 215#endif // !defined(OS_ANDROID) 216 if (driver_) { 217#if defined(OS_CHROMEOS) 218 driver_->RemoveConnectionObserver(chromeos_connection_observer_.get()); 219 chromeos_connection_observer_.reset(); 220#endif 221 driver_->Shutdown(); 222 driver_.reset(); 223 } 224} 225 226std::string GCMProfileService::SignedInUserName() const { 227#if defined(OS_ANDROID) 228 return std::string(); 229#else 230 return identity_observer_ ? identity_observer_->SignedInUserName() 231 : std::string(); 232#endif // defined(OS_ANDROID) 233} 234 235void GCMProfileService::SetDriverForTesting(GCMDriver* driver) { 236 driver_.reset(driver); 237} 238 239} // namespace gcm 240