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