OLD | NEW |
(Empty) | |
| 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 "base/bind.h" |
| 6 #include "base/location.h" |
| 7 #include "base/single_thread_task_runner.h" |
| 8 #include "base/thread_task_runner_handle.h" |
| 9 #include "chrome/browser/invalidation/gcm_invalidation_bridge.h" |
| 10 #include "chrome/browser/services/gcm/gcm_profile_service.h" |
| 11 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" |
| 12 #include "chrome/browser/signin/profile_oauth2_token_service.h" |
| 13 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" |
| 14 #include "chrome/browser/signin/signin_manager.h" |
| 15 #include "chrome/browser/signin/signin_manager_factory.h" |
| 16 #include "google_apis/gaia/gaia_constants.h" |
| 17 |
| 18 namespace invalidation { |
| 19 namespace { |
| 20 // For 3rd party developers SenderId should come from application dashboard when |
| 21 // server side application is registered with Google. Android invalidations use |
| 22 // legacy format where gmail account can be specificed. Below value is copied |
| 23 // from Android. |
| 24 const char kInvalidationsSenderId[] = "ipc.invalidation@gmail.com"; |
| 25 // In Android world AppId is provided by operating system and should |
| 26 // match package name and hash of application. In desktop world these values |
| 27 // are arbitrary and not verified/enforced by registration service (yet). |
| 28 const char kInvalidationsAppId[] = "com.google.chrome.invalidations"; |
| 29 |
| 30 } // namespace |
| 31 |
| 32 // Core should be very simple class that implements GCMNetwrokChannelDelegate |
| 33 // and passes all calls to GCMInvalidationBridge. All calls should be serialized |
| 34 // through GCMInvalidationBridge to avoid race conditions. |
| 35 class GCMInvalidationBridge::Core : public syncer::GCMNetworkChannelDelegate, |
| 36 public base::NonThreadSafe { |
| 37 public: |
| 38 Core(base::WeakPtr<GCMInvalidationBridge> bridge, |
| 39 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner); |
| 40 virtual ~Core(); |
| 41 |
| 42 // syncer::GCMNetworkChannelDelegate implementation. |
| 43 virtual void Initialize() OVERRIDE; |
| 44 virtual void RequestToken(RequestTokenCallback callback) OVERRIDE; |
| 45 virtual void InvalidateToken(const std::string& token) OVERRIDE; |
| 46 virtual void Register(RegisterCallback callback) OVERRIDE; |
| 47 |
| 48 void RequestTokenFinished(RequestTokenCallback callback, |
| 49 const GoogleServiceAuthError& error, |
| 50 const std::string& token); |
| 51 |
| 52 void RegisterFinished(RegisterCallback callback, |
| 53 const std::string& registration_id, |
| 54 gcm::GCMClient::Result result); |
| 55 |
| 56 private: |
| 57 base::WeakPtr<GCMInvalidationBridge> bridge_; |
| 58 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_; |
| 59 |
| 60 base::WeakPtrFactory<Core> weak_factory_; |
| 61 |
| 62 DISALLOW_COPY_AND_ASSIGN(Core); |
| 63 }; |
| 64 |
| 65 GCMInvalidationBridge::Core::Core( |
| 66 base::WeakPtr<GCMInvalidationBridge> bridge, |
| 67 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) |
| 68 : bridge_(bridge), |
| 69 ui_thread_task_runner_(ui_thread_task_runner), |
| 70 weak_factory_(this) { |
| 71 // Core is created on UI thread but all calls happen on IO thread. |
| 72 DetachFromThread(); |
| 73 } |
| 74 |
| 75 GCMInvalidationBridge::Core::~Core() {} |
| 76 |
| 77 void GCMInvalidationBridge::Core::Initialize() { |
| 78 DCHECK(CalledOnValidThread()); |
| 79 // Pass core WeapPtr and TaskRunner to GCMInvalidationBridge for it to be able |
| 80 // to post back. |
| 81 ui_thread_task_runner_->PostTask( |
| 82 FROM_HERE, |
| 83 base::Bind(&GCMInvalidationBridge::CoreInitializationDone, |
| 84 bridge_, |
| 85 weak_factory_.GetWeakPtr(), |
| 86 base::ThreadTaskRunnerHandle::Get())); |
| 87 } |
| 88 |
| 89 void GCMInvalidationBridge::Core::RequestToken(RequestTokenCallback callback) { |
| 90 DCHECK(CalledOnValidThread()); |
| 91 ui_thread_task_runner_->PostTask( |
| 92 FROM_HERE, |
| 93 base::Bind(&GCMInvalidationBridge::RequestToken, bridge_, callback)); |
| 94 } |
| 95 |
| 96 void GCMInvalidationBridge::Core::InvalidateToken(const std::string& token) { |
| 97 DCHECK(CalledOnValidThread()); |
| 98 ui_thread_task_runner_->PostTask( |
| 99 FROM_HERE, |
| 100 base::Bind(&GCMInvalidationBridge::InvalidateToken, bridge_, token)); |
| 101 } |
| 102 |
| 103 void GCMInvalidationBridge::Core::Register(RegisterCallback callback) { |
| 104 DCHECK(CalledOnValidThread()); |
| 105 ui_thread_task_runner_->PostTask( |
| 106 FROM_HERE, |
| 107 base::Bind(&GCMInvalidationBridge::Register, bridge_, callback)); |
| 108 } |
| 109 |
| 110 void GCMInvalidationBridge::Core::RequestTokenFinished( |
| 111 RequestTokenCallback callback, |
| 112 const GoogleServiceAuthError& error, |
| 113 const std::string& token) { |
| 114 DCHECK(CalledOnValidThread()); |
| 115 callback.Run(error, token); |
| 116 } |
| 117 |
| 118 void GCMInvalidationBridge::Core::RegisterFinished( |
| 119 RegisterCallback callback, |
| 120 const std::string& registration_id, |
| 121 gcm::GCMClient::Result result) { |
| 122 DCHECK(CalledOnValidThread()); |
| 123 callback.Run(registration_id, result); |
| 124 } |
| 125 |
| 126 GCMInvalidationBridge::GCMInvalidationBridge(Profile* profile) |
| 127 : OAuth2TokenService::Consumer("gcm_network_channel"), |
| 128 profile_(profile), |
| 129 weak_factory_(this) {} |
| 130 |
| 131 GCMInvalidationBridge::~GCMInvalidationBridge() {} |
| 132 |
| 133 scoped_ptr<syncer::GCMNetworkChannelDelegate> |
| 134 GCMInvalidationBridge::CreateDelegate() { |
| 135 DCHECK(CalledOnValidThread()); |
| 136 scoped_ptr<syncer::GCMNetworkChannelDelegate> core(new Core( |
| 137 weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get())); |
| 138 return core.Pass(); |
| 139 } |
| 140 |
| 141 void GCMInvalidationBridge::CoreInitializationDone( |
| 142 base::WeakPtr<Core> core, |
| 143 scoped_refptr<base::SingleThreadTaskRunner> core_thread_task_runner) { |
| 144 DCHECK(CalledOnValidThread()); |
| 145 core_ = core; |
| 146 core_thread_task_runner_ = core_thread_task_runner; |
| 147 } |
| 148 |
| 149 void GCMInvalidationBridge::RequestToken( |
| 150 syncer::GCMNetworkChannelDelegate::RequestTokenCallback callback) { |
| 151 DCHECK(CalledOnValidThread()); |
| 152 if (access_token_request_ != NULL) { |
| 153 // Report previous request as cancelled. |
| 154 GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); |
| 155 std::string access_token; |
| 156 core_thread_task_runner_->PostTask( |
| 157 FROM_HERE, |
| 158 base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished, |
| 159 core_, |
| 160 request_token_callback_, |
| 161 error, |
| 162 access_token)); |
| 163 } |
| 164 ProfileOAuth2TokenService* token_service = |
| 165 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); |
| 166 request_token_callback_ = callback; |
| 167 SigninManagerBase* signin_manager = |
| 168 SigninManagerFactory::GetForProfile(profile_); |
| 169 std::string account_id = signin_manager->GetAuthenticatedAccountId(); |
| 170 OAuth2TokenService::ScopeSet scopes; |
| 171 scopes.insert(GaiaConstants::kGoogleTalkOAuth2Scope); |
| 172 access_token_request_ = token_service->StartRequest(account_id, scopes, this); |
| 173 } |
| 174 |
| 175 void GCMInvalidationBridge::OnGetTokenSuccess( |
| 176 const OAuth2TokenService::Request* request, |
| 177 const std::string& access_token, |
| 178 const base::Time& expiration_time) { |
| 179 DCHECK(CalledOnValidThread()); |
| 180 DCHECK_EQ(access_token_request_, request); |
| 181 core_thread_task_runner_->PostTask( |
| 182 FROM_HERE, |
| 183 base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished, |
| 184 core_, |
| 185 request_token_callback_, |
| 186 GoogleServiceAuthError::AuthErrorNone(), |
| 187 access_token)); |
| 188 request_token_callback_.Reset(); |
| 189 access_token_request_.reset(); |
| 190 } |
| 191 |
| 192 void GCMInvalidationBridge::OnGetTokenFailure( |
| 193 const OAuth2TokenService::Request* request, |
| 194 const GoogleServiceAuthError& error) { |
| 195 DCHECK(CalledOnValidThread()); |
| 196 DCHECK_EQ(access_token_request_, request); |
| 197 core_thread_task_runner_->PostTask( |
| 198 FROM_HERE, |
| 199 base::Bind(&GCMInvalidationBridge::Core::RequestTokenFinished, |
| 200 core_, |
| 201 request_token_callback_, |
| 202 error, |
| 203 std::string())); |
| 204 request_token_callback_.Reset(); |
| 205 access_token_request_.reset(); |
| 206 } |
| 207 |
| 208 void GCMInvalidationBridge::InvalidateToken(const std::string& token) { |
| 209 ProfileOAuth2TokenService* token_service = |
| 210 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); |
| 211 DCHECK(CalledOnValidThread()); |
| 212 SigninManagerBase* signin_manager = |
| 213 SigninManagerFactory::GetForProfile(profile_); |
| 214 std::string account_id = signin_manager->GetAuthenticatedAccountId(); |
| 215 OAuth2TokenService::ScopeSet scopes; |
| 216 scopes.insert(GaiaConstants::kGoogleTalkOAuth2Scope); |
| 217 token_service->InvalidateToken(account_id, scopes, token); |
| 218 } |
| 219 |
| 220 void GCMInvalidationBridge::Register( |
| 221 syncer::GCMNetworkChannelDelegate::RegisterCallback callback) { |
| 222 DCHECK(CalledOnValidThread()); |
| 223 // No-op if GCMClient is disabled. |
| 224 gcm::GCMProfileService* gcm_profile_service = |
| 225 gcm::GCMProfileServiceFactory::GetForProfile(profile_); |
| 226 if (gcm_profile_service == NULL) |
| 227 return; |
| 228 |
| 229 std::vector<std::string> sender_ids; |
| 230 sender_ids.push_back(kInvalidationsSenderId); |
| 231 gcm_profile_service->Register( |
| 232 kInvalidationsAppId, |
| 233 sender_ids, |
| 234 base::Bind(&GCMInvalidationBridge::RegisterFinished, |
| 235 weak_factory_.GetWeakPtr(), |
| 236 callback)); |
| 237 } |
| 238 |
| 239 void GCMInvalidationBridge::RegisterFinished( |
| 240 syncer::GCMNetworkChannelDelegate::RegisterCallback callback, |
| 241 const std::string& registration_id, |
| 242 gcm::GCMClient::Result result) { |
| 243 DCHECK(CalledOnValidThread()); |
| 244 core_thread_task_runner_->PostTask( |
| 245 FROM_HERE, |
| 246 base::Bind(&GCMInvalidationBridge::Core::RegisterFinished, |
| 247 core_, |
| 248 callback, |
| 249 registration_id, |
| 250 result)); |
| 251 } |
| 252 |
| 253 } // namespace invalidation |
OLD | NEW |