Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(665)

Side by Side Diff: chrome/browser/signin/oauth2_token_service.cc

Issue 17109006: Device robot refresh token integrity validation. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/signin/oauth2_token_service.h" 5 #include "chrome/browser/signin/oauth2_token_service.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/memory/weak_ptr.h" 10 #include "base/memory/weak_ptr.h"
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 // fetching. 77 // fetching.
78 // 78 //
79 // The waiting requests are taken as weak pointers and they can be deleted. The 79 // The waiting requests are taken as weak pointers and they can be deleted. The
80 // waiting requests will be called back with fetching results if they are not 80 // waiting requests will be called back with fetching results if they are not
81 // deleted 81 // deleted
82 // - when the Fetcher completes fetching, if the Fetcher is not destructed 82 // - when the Fetcher completes fetching, if the Fetcher is not destructed
83 // before it completes fetching, or 83 // before it completes fetching, or
84 // - when the Fetcher is destructed if the Fetcher is destructed before it 84 // - when the Fetcher is destructed if the Fetcher is destructed before it
85 // completes fetching (in this case, the waiting requests will be called back 85 // completes fetching (in this case, the waiting requests will be called back
86 // with error). 86 // with error).
87 class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { 87 class OAuth2TokenService::Fetcher : public RefreshTokenValidationConsumer,
88 public OAuth2AccessTokenConsumer {
88 public: 89 public:
89 // Creates a Fetcher and starts fetching an OAuth2 access token for 90 // Creates a Fetcher and starts fetching an OAuth2 access token for
90 // |refresh_token| and |scopes| in the request context obtained by |getter|. 91 // |refresh_token| and |scopes| in the request context obtained by |getter|.
91 // The given |oauth2_token_service| will be informed when fetching is done. 92 // The given |oauth2_token_service| will be informed when fetching is done.
92 static Fetcher* CreateAndStart(OAuth2TokenService* oauth2_token_service, 93 static Fetcher* CreateAndStart(OAuth2TokenService* oauth2_token_service,
93 net::URLRequestContextGetter* getter, 94 net::URLRequestContextGetter* getter,
94 const std::string& refresh_token, 95 const std::string& refresh_token,
95 const OAuth2TokenService::ScopeSet& scopes, 96 const OAuth2TokenService::ScopeSet& scopes,
96 base::WeakPtr<RequestImpl> waiting_request); 97 base::WeakPtr<RequestImpl> waiting_request);
97 virtual ~Fetcher(); 98 virtual ~Fetcher();
98 99
99 // Add a request that is waiting for the result of this Fetcher. 100 // Add a request that is waiting for the result of this Fetcher.
100 void AddWaitingRequest(base::WeakPtr<RequestImpl> waiting_request); 101 void AddWaitingRequest(base::WeakPtr<RequestImpl> waiting_request);
101 102
102 const OAuth2TokenService::ScopeSet& GetScopeSet() const; 103 const OAuth2TokenService::ScopeSet& GetScopeSet() const;
103 const std::string& GetRefreshToken() const; 104 const std::string& GetRefreshToken() const;
104 105
105 // The error result from this fetcher. 106 // The error result from this fetcher.
106 const GoogleServiceAuthError& error() const { return error_; } 107 const GoogleServiceAuthError& error() const { return error_; }
107 108
108 protected: 109 protected:
109 // OAuth2AccessTokenConsumer 110 // OAuth2AccessTokenConsumer
110 virtual void OnGetTokenSuccess(const std::string& access_token, 111 virtual void OnGetTokenSuccess(const std::string& access_token,
111 const base::Time& expiration_date) OVERRIDE; 112 const base::Time& expiration_date) OVERRIDE;
112 virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE; 113 virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE;
113 114
115 // RefreshTokenValidationConsumer
116 virtual void OnRefreshTokenValidationComplete(
117 const std::string& refresh_token,
118 bool is_valid) OVERRIDE;
119
114 private: 120 private:
115 Fetcher(OAuth2TokenService* oauth2_token_service, 121 Fetcher(OAuth2TokenService* oauth2_token_service,
116 net::URLRequestContextGetter* getter, 122 net::URLRequestContextGetter* getter,
117 const std::string& refresh_token, 123 const std::string& refresh_token,
118 const OAuth2TokenService::ScopeSet& scopes, 124 const OAuth2TokenService::ScopeSet& scopes,
119 base::WeakPtr<RequestImpl> waiting_request); 125 base::WeakPtr<RequestImpl> waiting_request);
120 void Start(); 126 void Start();
127 void StartAccessTokenFetch();
121 void InformWaitingRequests(); 128 void InformWaitingRequests();
129 void InformWaitingRequestsAndQuit();
122 static bool ShouldRetry(const GoogleServiceAuthError& error); 130 static bool ShouldRetry(const GoogleServiceAuthError& error);
123 131
124 // |oauth2_token_service_| remains valid for the life of this Fetcher, since 132 // |oauth2_token_service_| remains valid for the life of this Fetcher, since
125 // this Fetcher is destructed in the dtor of the OAuth2TokenService or is 133 // this Fetcher is destructed in the dtor of the OAuth2TokenService or is
126 // scheduled for deletion at the end of OnGetTokenFailure/OnGetTokenSuccess 134 // scheduled for deletion at the end of OnGetTokenFailure/OnGetTokenSuccess
127 // (whichever comes first). 135 // (whichever comes first).
128 OAuth2TokenService* const oauth2_token_service_; 136 OAuth2TokenService* const oauth2_token_service_;
129 scoped_refptr<net::URLRequestContextGetter> getter_; 137 scoped_refptr<net::URLRequestContextGetter> getter_;
130 const std::string refresh_token_; 138 const std::string refresh_token_;
131 const OAuth2TokenService::ScopeSet scopes_; 139 const OAuth2TokenService::ScopeSet scopes_;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 waiting_requests_.push_back(waiting_request); 184 waiting_requests_.push_back(waiting_request);
177 } 185 }
178 186
179 OAuth2TokenService::Fetcher::~Fetcher() { 187 OAuth2TokenService::Fetcher::~Fetcher() {
180 // Inform the waiting requests if it has not done so. 188 // Inform the waiting requests if it has not done so.
181 if (waiting_requests_.size()) 189 if (waiting_requests_.size())
182 InformWaitingRequests(); 190 InformWaitingRequests();
183 } 191 }
184 192
185 void OAuth2TokenService::Fetcher::Start() { 193 void OAuth2TokenService::Fetcher::Start() {
194 if (!oauth2_token_service_->StartRefreshTokenValidation(refresh_token_,
195 this)) {
196 StartAccessTokenFetch();
197 }
198 }
199
200 void OAuth2TokenService::Fetcher::OnRefreshTokenValidationComplete(
201 const std::string& refresh_token,
202 bool is_valid) {
203 DCHECK(refresh_token_ == refresh_token);
204 if (is_valid) {
205 StartAccessTokenFetch();
206 } else {
207 error_ = GoogleServiceAuthError(
208 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
209 InformWaitingRequestsAndQuit();
210 }
211 }
212
213 void OAuth2TokenService::Fetcher::StartAccessTokenFetch() {
186 fetcher_.reset(new OAuth2AccessTokenFetcher(this, getter_.get())); 214 fetcher_.reset(new OAuth2AccessTokenFetcher(this, getter_.get()));
187 fetcher_->Start(GaiaUrls::GetInstance()->oauth2_chrome_client_id(), 215 fetcher_->Start(GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
188 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), 216 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
189 refresh_token_, 217 refresh_token_,
190 std::vector<std::string>(scopes_.begin(), scopes_.end())); 218 std::vector<std::string>(scopes_.begin(), scopes_.end()));
191 retry_timer_.Stop(); 219 retry_timer_.Stop();
192 } 220 }
193 221
194 void OAuth2TokenService::Fetcher::OnGetTokenSuccess( 222 void OAuth2TokenService::Fetcher::OnGetTokenSuccess(
195 const std::string& access_token, 223 const std::string& access_token,
196 const base::Time& expiration_date) { 224 const base::Time& expiration_date) {
197 fetcher_.reset(); 225 fetcher_.reset();
198 226
199 // Fetch completes. 227 // Fetch completes.
200 error_ = GoogleServiceAuthError::AuthErrorNone(); 228 error_ = GoogleServiceAuthError::AuthErrorNone();
201 access_token_ = access_token; 229 access_token_ = access_token;
202 expiration_date_ = expiration_date; 230 expiration_date_ = expiration_date;
203 231
204 // Subclasses may override this method to skip caching in some cases, but 232 // Subclasses may override this method to skip caching in some cases, but
205 // we still inform all waiting Consumers of a successful token fetch below. 233 // we still inform all waiting Consumers of a successful token fetch below.
206 // This is intentional -- some consumers may need the token for cleanup 234 // This is intentional -- some consumers may need the token for cleanup
207 // tasks. https://chromiumcodereview.appspot.com/11312124/ 235 // tasks. https://chromiumcodereview.appspot.com/11312124/
208 oauth2_token_service_->RegisterCacheEntry(refresh_token_, 236 oauth2_token_service_->RegisterCacheEntry(refresh_token_,
209 scopes_, 237 scopes_,
210 access_token_, 238 access_token_,
211 expiration_date_); 239 expiration_date_);
212 // Deregisters itself from the service to prevent more waiting requests to 240 InformWaitingRequestsAndQuit();
213 // be added when it calls back the waiting requests.
214 oauth2_token_service_->OnFetchComplete(this);
215 InformWaitingRequests();
216 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
217 } 241 }
218 242
219 void OAuth2TokenService::Fetcher::OnGetTokenFailure( 243 void OAuth2TokenService::Fetcher::OnGetTokenFailure(
220 const GoogleServiceAuthError& error) { 244 const GoogleServiceAuthError& error) {
221 fetcher_.reset(); 245 fetcher_.reset();
222 246
223 if (ShouldRetry(error) && retry_number_ < kMaxFetchRetryNum) { 247 if (ShouldRetry(error) && retry_number_ < kMaxFetchRetryNum) {
224 int64 backoff = ComputeExponentialBackOffMilliseconds(retry_number_); 248 int64 backoff = ComputeExponentialBackOffMilliseconds(retry_number_);
225 ++retry_number_; 249 ++retry_number_;
226 retry_timer_.Stop(); 250 retry_timer_.Stop();
227 retry_timer_.Start(FROM_HERE, 251 retry_timer_.Start(FROM_HERE,
228 base::TimeDelta::FromMilliseconds(backoff), 252 base::TimeDelta::FromMilliseconds(backoff),
229 this, 253 this,
230 &OAuth2TokenService::Fetcher::Start); 254 &OAuth2TokenService::Fetcher::Start);
231 return; 255 return;
232 } 256 }
233 257
234 // Fetch completes.
235 error_ = error; 258 error_ = error;
236 259 InformWaitingRequestsAndQuit();
237 // Deregisters itself from the service to prevent more waiting requests to be
238 // added when it calls back the waiting requests.
239 oauth2_token_service_->OnFetchComplete(this);
240 InformWaitingRequests();
241 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
242 } 260 }
243 261
244 // static 262 // static
245 bool OAuth2TokenService::Fetcher::ShouldRetry( 263 bool OAuth2TokenService::Fetcher::ShouldRetry(
246 const GoogleServiceAuthError& error) { 264 const GoogleServiceAuthError& error) {
247 GoogleServiceAuthError::State error_state = error.state(); 265 GoogleServiceAuthError::State error_state = error.state();
248 return error_state == GoogleServiceAuthError::CONNECTION_FAILED || 266 return error_state == GoogleServiceAuthError::CONNECTION_FAILED ||
249 error_state == GoogleServiceAuthError::REQUEST_CANCELED || 267 error_state == GoogleServiceAuthError::REQUEST_CANCELED ||
250 error_state == GoogleServiceAuthError::SERVICE_UNAVAILABLE; 268 error_state == GoogleServiceAuthError::SERVICE_UNAVAILABLE;
251 } 269 }
252 270
253 void OAuth2TokenService::Fetcher::InformWaitingRequests() { 271 void OAuth2TokenService::Fetcher::InformWaitingRequests() {
254 std::vector<base::WeakPtr<RequestImpl> >::const_iterator iter = 272 std::vector<base::WeakPtr<RequestImpl> >::const_iterator iter =
255 waiting_requests_.begin(); 273 waiting_requests_.begin();
256 for (; iter != waiting_requests_.end(); ++iter) { 274 for (; iter != waiting_requests_.end(); ++iter) {
257 base::WeakPtr<RequestImpl> waiting_request = *iter; 275 base::WeakPtr<RequestImpl> waiting_request = *iter;
258 if (waiting_request.get()) 276 if (waiting_request.get())
259 waiting_request->InformConsumer(error_, access_token_, expiration_date_); 277 waiting_request->InformConsumer(error_, access_token_, expiration_date_);
260 } 278 }
261 waiting_requests_.clear(); 279 waiting_requests_.clear();
262 } 280 }
263 281
282 void OAuth2TokenService::Fetcher::InformWaitingRequestsAndQuit() {
283 // Deregisters itself from the service to prevent more waiting requests to
284 // be added when it calls back the waiting requests.
285 oauth2_token_service_->OnFetchComplete(this);
286 InformWaitingRequests();
287 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
288 }
289
264 void OAuth2TokenService::Fetcher::AddWaitingRequest( 290 void OAuth2TokenService::Fetcher::AddWaitingRequest(
265 base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) { 291 base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) {
266 waiting_requests_.push_back(waiting_request); 292 waiting_requests_.push_back(waiting_request);
267 } 293 }
268 294
269 const OAuth2TokenService::ScopeSet& OAuth2TokenService::Fetcher::GetScopeSet() 295 const OAuth2TokenService::ScopeSet& OAuth2TokenService::Fetcher::GetScopeSet()
270 const { 296 const {
271 return scopes_; 297 return scopes_;
272 } 298 }
273 299
(...skipping 17 matching lines...) Expand all
291 : request_context_getter_(getter) { 317 : request_context_getter_(getter) {
292 } 318 }
293 319
294 OAuth2TokenService::~OAuth2TokenService() { 320 OAuth2TokenService::~OAuth2TokenService() {
295 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 321 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
296 // Release all the pending fetchers. 322 // Release all the pending fetchers.
297 STLDeleteContainerPairSecondPointers( 323 STLDeleteContainerPairSecondPointers(
298 pending_fetchers_.begin(), pending_fetchers_.end()); 324 pending_fetchers_.begin(), pending_fetchers_.end());
299 } 325 }
300 326
301 bool OAuth2TokenService::RefreshTokenIsAvailable() {
302 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
303 return !GetRefreshToken().empty();
304 }
305
306 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( 327 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest(
307 const OAuth2TokenService::ScopeSet& scopes, 328 const OAuth2TokenService::ScopeSet& scopes,
308 OAuth2TokenService::Consumer* consumer) { 329 OAuth2TokenService::Consumer* consumer) {
309 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 330 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
310 331
311 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); 332 scoped_ptr<RequestImpl> request(new RequestImpl(consumer));
312 333
313 std::string refresh_token = GetRefreshToken(); 334 std::string refresh_token = GetRefreshToken();
314 if (refresh_token.empty()) { 335 if (refresh_token.empty()) {
315 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 336 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
316 &RequestImpl::InformConsumer, 337 &RequestImpl::InformConsumer,
317 request->AsWeakPtr(), 338 request->AsWeakPtr(),
318 GoogleServiceAuthError( 339 GoogleServiceAuthError(
319 GoogleServiceAuthError::USER_NOT_SIGNED_UP), 340 GoogleServiceAuthError::USER_NOT_SIGNED_UP),
320 std::string(), 341 std::string(),
321 base::Time())); 342 base::Time()));
322 return request.PassAs<Request>(); 343 return request.PassAs<Request>();
323 } 344 }
324 345
325 if (HasCacheEntry(scopes)) 346 if (HasCacheEntry(scopes))
326 return StartCacheLookupRequest(scopes, consumer); 347 return StartCacheLookupRequest(scopes, request.Pass());
327 348
328 // Makes sure there is a pending fetcher for |scopes| and |refresh_token|. 349 // If there is already a pending fetcher for |scopes| and |refresh_token|,
329 // Adds |request| to the waiting request list of this fetcher so |request| 350 // simply register this |request| for those results rather than starting
330 // will be called back when this fetcher finishes fetching. 351 // a new fetcher.
331 FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes); 352 FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes);
332 std::map<FetchParameters, Fetcher*>::iterator iter = 353 std::map<FetchParameters, Fetcher*>::iterator iter =
333 pending_fetchers_.find(fetch_parameters); 354 pending_fetchers_.find(fetch_parameters);
334 if (iter != pending_fetchers_.end()) { 355 if (iter != pending_fetchers_.end()) {
335 iter->second->AddWaitingRequest(request->AsWeakPtr()); 356 iter->second->AddWaitingRequest(request->AsWeakPtr());
336 return request.PassAs<Request>(); 357 return request.PassAs<Request>();
337 } 358 }
359
338 pending_fetchers_[fetch_parameters] = 360 pending_fetchers_[fetch_parameters] =
339 Fetcher::CreateAndStart(this, 361 Fetcher::CreateAndStart(this,
340 request_context_getter_.get(), 362 request_context_getter_.get(),
341 refresh_token, 363 refresh_token,
342 scopes, 364 scopes,
343 request->AsWeakPtr()); 365 request->AsWeakPtr());
344 return request.PassAs<Request>(); 366 return request.PassAs<Request>();
345 } 367 }
346 368
347 scoped_ptr<OAuth2TokenService::Request> 369 scoped_ptr<OAuth2TokenService::Request>
348 OAuth2TokenService::StartCacheLookupRequest( 370 OAuth2TokenService::StartCacheLookupRequest(
349 const OAuth2TokenService::ScopeSet& scopes, 371 const OAuth2TokenService::ScopeSet& scopes,
350 OAuth2TokenService::Consumer* consumer) { 372 scoped_ptr<RequestImpl> request) {
351 CHECK(HasCacheEntry(scopes)); 373 CHECK(HasCacheEntry(scopes));
352 const CacheEntry* cache_entry = GetCacheEntry(scopes); 374 const CacheEntry* cache_entry = GetCacheEntry(scopes);
353 scoped_ptr<RequestImpl> request(new RequestImpl(consumer));
354 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 375 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
355 &RequestImpl::InformConsumer, 376 &RequestImpl::InformConsumer,
356 request->AsWeakPtr(), 377 request->AsWeakPtr(),
357 GoogleServiceAuthError(GoogleServiceAuthError::NONE), 378 GoogleServiceAuthError(GoogleServiceAuthError::NONE),
358 cache_entry->access_token, 379 cache_entry->access_token,
359 cache_entry->expiration_date)); 380 cache_entry->expiration_date));
360 return request.PassAs<Request>(); 381 return request.PassAs<Request>();
361 } 382 }
362 383
363 void OAuth2TokenService::InvalidateToken(const ScopeSet& scopes, 384 void OAuth2TokenService::InvalidateToken(const ScopeSet& scopes,
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 const OAuth2TokenService::ScopeSet& scopes, 465 const OAuth2TokenService::ScopeSet& scopes,
445 const std::string& access_token, 466 const std::string& access_token,
446 const base::Time& expiration_date) { 467 const base::Time& expiration_date) {
447 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 468 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
448 469
449 CacheEntry& token = token_cache_[scopes]; 470 CacheEntry& token = token_cache_[scopes];
450 token.access_token = access_token; 471 token.access_token = access_token;
451 token.expiration_date = expiration_date; 472 token.expiration_date = expiration_date;
452 } 473 }
453 474
475 bool OAuth2TokenService::StartRefreshTokenValidation(
476 const std::string refresh_token,
477 RefreshTokenValidationConsumer* consumer) {
478 return false; // No validation needed; use token directly.
479 }
480
454 void OAuth2TokenService::UpdateAuthError(const GoogleServiceAuthError& error) { 481 void OAuth2TokenService::UpdateAuthError(const GoogleServiceAuthError& error) {
455 // Default implementation does nothing. 482 // Default implementation does nothing.
456 } 483 }
457 484
458 void OAuth2TokenService::ClearCache() { 485 void OAuth2TokenService::ClearCache() {
459 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 486 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
460 token_cache_.clear(); 487 token_cache_.clear();
461 } 488 }
462 489
463 int OAuth2TokenService::cache_size_for_testing() const { 490 int OAuth2TokenService::cache_size_for_testing() const {
464 return token_cache_.size(); 491 return token_cache_.size();
465 } 492 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698