15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/drive/auth_service.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 1158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/location.h" 126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/message_loop/message_loop.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/drive/auth_service_observer.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h" 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace google_apis { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used for success ratio histograms. 0 for failure, 1 for success, 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 2 for no connection (likely offline). 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kSuccessRatioHistogramFailure = 0; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kSuccessRatioHistogramSuccess = 1; 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kSuccessRatioHistogramNoConnection = 2; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kSuccessRatioHistogramTemporaryFailure = 3; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kSuccessRatioHistogramMaxValue = 4; // The max value is exclusive. 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void RecordAuthResultHistogram(int value) { 316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("GData.AuthSuccess", 326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) value, 336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) kSuccessRatioHistogramMaxValue); 346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// OAuth2 authorization token retrieval request. 3758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochclass AuthRequest : public OAuth2TokenService::Consumer { 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 39558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch AuthRequest(OAuth2TokenService* oauth2_token_service, 4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& account_id, 4158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch net::URLRequestContextGetter* url_request_context_getter, 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const AuthStatusCallback& callback, 4358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch const std::vector<std::string>& scopes); 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual ~AuthRequest(); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch private: 4758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch // Overridden from OAuth2TokenService::Consumer: 4858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request, 4958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch const std::string& access_token, 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Time& expiration_time) OVERRIDE; 5158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request, 5258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch const GoogleServiceAuthError& error) OVERRIDE; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AuthStatusCallback callback_; 5558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch scoped_ptr<OAuth2TokenService::Request> request_; 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ThreadChecker thread_checker_; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(AuthRequest); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AuthRequest::AuthRequest( 62558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch OAuth2TokenService* oauth2_token_service, 6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& account_id, 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLRequestContextGetter* url_request_context_getter, 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const AuthStatusCallback& callback, 6658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch const std::vector<std::string>& scopes) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : OAuth2TokenService::Consumer("auth_service"), 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback_(callback) { 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!callback_.is_null()); 70558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch request_ = oauth2_token_service-> 71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) StartRequestWithContext( 7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) account_id, 73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) url_request_context_getter, 74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) OAuth2TokenService::ScopeSet(scopes.begin(), scopes.end()), 75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) this); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AuthRequest::~AuthRequest() {} 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Callback for OAuth2AccessTokenFetcher on success. |access_token| is the token 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// used to start fetching user data. 8258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochvoid AuthRequest::OnGetTokenSuccess(const OAuth2TokenService::Request* request, 8358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch const std::string& access_token, 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const base::Time& expiration_time) { 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) RecordAuthResultHistogram(kSuccessRatioHistogramSuccess); 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_.Run(HTTP_SUCCESS, access_token); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delete this; 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Callback for OAuth2AccessTokenFetcher on failure. 9358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochvoid AuthRequest::OnGetTokenFailure(const OAuth2TokenService::Request* request, 9458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch const GoogleServiceAuthError& error) { 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(WARNING) << "AuthRequest: token request using refresh token failed: " 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << error.ToString(); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // There are many ways to fail, but if the failure is due to connection, 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // it's likely that the device is off-line. We treat the error differently 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // so that the file manager works while off-line. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) { 1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) RecordAuthResultHistogram(kSuccessRatioHistogramNoConnection); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_.Run(GDATA_NO_CONNECTION, std::string()); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE) { 1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) RecordAuthResultHistogram(kSuccessRatioHistogramTemporaryFailure); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_.Run(HTTP_FORBIDDEN, std::string()); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Permanent auth error. 1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) RecordAuthResultHistogram(kSuccessRatioHistogramFailure); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_.Run(HTTP_UNAUTHORIZED, std::string()); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delete this; 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch} // namespace 11858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 1199ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochAuthService::AuthService( 120558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch OAuth2TokenService* oauth2_token_service, 12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& account_id, 1229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch net::URLRequestContextGetter* url_request_context_getter, 1239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const std::vector<std::string>& scopes) 124558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch : oauth2_token_service_(oauth2_token_service), 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) account_id_(account_id), 1269ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch url_request_context_getter_(url_request_context_getter), 1279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scopes_(scopes), 1289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch weak_ptr_factory_(this) { 129558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch DCHECK(oauth2_token_service); 1309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get OAuth2 refresh token (if we have any) and register for its updates. 132558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch oauth2_token_service_->AddObserver(this); 13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) has_refresh_token_ = oauth2_token_service_->RefreshTokenIsAvailable( 13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) account_id_); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AuthService::~AuthService() { 138558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch oauth2_token_service_->RemoveObserver(this); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AuthService::StartAuthentication(const AuthStatusCallback& callback) { 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HasAccessToken()) { 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We already have access token. Give it back to the caller asynchronously. 1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::MessageLoop::current()->PostTask( 1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FROM_HERE, base::Bind(callback, HTTP_SUCCESS, access_token_)); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (HasRefreshToken()) { 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We have refresh token, let's get an access token. 150558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch new AuthRequest(oauth2_token_service_, 15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) account_id_, 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url_request_context_getter_.get(), 15358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch base::Bind(&AuthService::OnAuthCompleted, 15458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch weak_ptr_factory_.GetWeakPtr(), 15558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch callback), 15658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch scopes_); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::MessageLoop::current()->PostTask( 1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FROM_HERE, base::Bind(callback, GDATA_NOT_READY, std::string())); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AuthService::HasAccessToken() const { 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !access_token_.empty(); 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AuthService::HasRefreshToken() const { 16858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch return has_refresh_token_; 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::string& AuthService::access_token() const { 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return access_token_; 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AuthService::ClearAccessToken() { 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) access_token_.clear(); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AuthService::ClearRefreshToken() { 1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) OnHandleRefreshToken(false); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AuthService::OnAuthCompleted(const AuthStatusCallback& callback, 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GDataErrorCode error, 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& access_token) { 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (error == HTTP_SUCCESS) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) access_token_ = access_token; 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (error == HTTP_UNAUTHORIZED) { 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Refreshing access token using the refresh token is failed with 401 error 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // (HTTP_UNAUTHORIZED). This means the current refresh token is invalid for 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Drive, hence we clear the refresh token here to make HasRefreshToken() 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // false, thus the invalidness is clearly observable. 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is not for triggering refetch of the refresh token. UI should 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // show some message to encourage user to log-off and log-in again in order 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to fetch new valid refresh token. 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClearRefreshToken(); 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(error, access_token); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AuthService::AddObserver(AuthServiceObserver* observer) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.AddObserver(observer); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AuthService::RemoveObserver(AuthServiceObserver* observer) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.RemoveObserver(observer); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochvoid AuthService::OnRefreshTokenAvailable(const std::string& account_id) { 2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (account_id == account_id_) 2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) OnHandleRefreshToken(true); 21658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch} 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void AuthService::OnRefreshTokenRevoked(const std::string& account_id) { 2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (account_id == account_id_) 2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) OnHandleRefreshToken(false); 22158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch} 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochvoid AuthService::OnHandleRefreshToken(bool has_refresh_token) { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) access_token_.clear(); 22558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch has_refresh_token_ = has_refresh_token; 22658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(AuthServiceObserver, 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnOAuth2RefreshTokenChanged()); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace google_apis 233