Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| 11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
| 12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
| 13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 14 #include "base/time.h" | 14 #include "base/time.h" |
| 15 #include "base/timer.h" | 15 #include "base/timer.h" |
| 16 #include "chrome/browser/profiles/profile.h" | |
| 17 #include "chrome/browser/signin/oauth2_token_service_factory.h" | |
| 18 #include "chrome/browser/signin/signin_manager.h" | |
| 19 #include "chrome/browser/signin/signin_manager_factory.h" | |
| 20 #include "chrome/browser/signin/token_service.h" | |
| 21 #include "chrome/browser/signin/token_service_factory.h" | |
| 22 #include "chrome/common/chrome_notification_types.h" | |
| 23 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
| 24 #include "content/public/browser/notification_details.h" | |
| 25 #include "content/public/browser/notification_source.h" | |
| 26 #include "google_apis/gaia/gaia_constants.h" | |
| 27 #include "google_apis/gaia/gaia_urls.h" | 17 #include "google_apis/gaia/gaia_urls.h" |
| 28 #include "google_apis/gaia/google_service_auth_error.h" | 18 #include "google_apis/gaia/google_service_auth_error.h" |
| 29 #include "google_apis/gaia/oauth2_access_token_consumer.h" | 19 #include "google_apis/gaia/oauth2_access_token_consumer.h" |
| 30 #include "google_apis/gaia/oauth2_access_token_fetcher.h" | 20 #include "google_apis/gaia/oauth2_access_token_fetcher.h" |
| 21 #include "net/url_request/url_request_context_getter.h" | |
| 31 | 22 |
| 32 namespace { | 23 namespace { |
| 33 | 24 |
| 34 // Maximum number of retries in fetching an OAuth2 access token. | 25 // Maximum number of retries in fetching an OAuth2 access token. |
| 35 const int kMaxFetchRetryNum = 5; | 26 const int kMaxFetchRetryNum = 5; |
| 36 | 27 |
| 37 // Returns an exponential backoff in milliseconds including randomness less than | 28 // Returns an exponential backoff in milliseconds including randomness less than |
| 38 // 1000 ms when retrying fetching an OAuth2 access token. | 29 // 1000 ms when retrying fetching an OAuth2 access token. |
| 39 int64 ComputeExponentialBackOffMilliseconds(int retry_num) { | 30 int64 ComputeExponentialBackOffMilliseconds(int retry_num) { |
| 40 DCHECK(retry_num < kMaxFetchRetryNum); | 31 DCHECK(retry_num < kMaxFetchRetryNum); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 74 OAuth2TokenService::RequestImpl::~RequestImpl() { | 65 OAuth2TokenService::RequestImpl::~RequestImpl() { |
| 75 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 66 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 76 } | 67 } |
| 77 | 68 |
| 78 void OAuth2TokenService::RequestImpl::InformConsumer( | 69 void OAuth2TokenService::RequestImpl::InformConsumer( |
| 79 const GoogleServiceAuthError& error, | 70 const GoogleServiceAuthError& error, |
| 80 const std::string& access_token, | 71 const std::string& access_token, |
| 81 const base::Time& expiration_date) { | 72 const base::Time& expiration_date) { |
| 82 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 73 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 83 if (error.state() == GoogleServiceAuthError::NONE) | 74 if (error.state() == GoogleServiceAuthError::NONE) |
| 84 consumer_-> OnGetTokenSuccess(this, access_token, expiration_date); | 75 consumer_-> OnGetTokenSuccess(this, access_token, expiration_date); |
|
Andrew T Wilson (Slow)
2013/03/19 19:58:44
nit: please remove the space after -> here too.
David Roche
2013/03/21 00:12:02
Done.
| |
| 85 else | 76 else |
| 86 consumer_-> OnGetTokenFailure(this, error); | 77 consumer_->OnGetTokenFailure(this, error); |
| 87 } | 78 } |
| 88 | 79 |
| 89 // Class that fetches OAuth2 access tokens for given scopes and refresh token. | 80 // Class that fetches OAuth2 access tokens for given scopes and refresh token. |
| 90 // | 81 // |
| 91 // It aims to meet OAuth2TokenService's requirements on token fetching. Retry | 82 // It aims to meet OAuth2TokenService's requirements on token fetching. Retry |
| 92 // mechanism is used to handle failures. | 83 // mechanism is used to handle failures. |
| 93 // | 84 // |
| 94 // To use this class, call CreateAndStart() to create and start a Fetcher. | 85 // To use this class, call CreateAndStart() to create and start a Fetcher. |
| 95 // | 86 // |
| 96 // The Fetcher will call back the service by calling | 87 // The Fetcher will call back the service by calling |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 110 // deleted | 101 // deleted |
| 111 // - when the Fetcher completes fetching, if the Fetcher is not destructed | 102 // - when the Fetcher completes fetching, if the Fetcher is not destructed |
| 112 // before it completes fetching, or | 103 // before it completes fetching, or |
| 113 // - when the Fetcher is destructed if the Fetcher is destructed before it | 104 // - when the Fetcher is destructed if the Fetcher is destructed before it |
| 114 // completes fetching (in this case, the waiting requests will be called back | 105 // completes fetching (in this case, the waiting requests will be called back |
| 115 // with error). | 106 // with error). |
| 116 class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { | 107 class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { |
| 117 public: | 108 public: |
| 118 // Creates a Fetcher and starts fetching an OAuth2 access token for | 109 // Creates a Fetcher and starts fetching an OAuth2 access token for |
| 119 // |refresh_token| and |scopes| in the request context obtained by |getter|. | 110 // |refresh_token| and |scopes| in the request context obtained by |getter|. |
| 120 // |profile|'s OAuth2TokenService will be informed when fetching is done. | 111 // The given |oauth2_token_service| will be informed when fetching is done. |
| 121 static Fetcher* CreateAndStart(Profile* profile, | 112 static Fetcher* CreateAndStart(OAuth2TokenService* oauth2_token_service, |
| 122 net::URLRequestContextGetter* getter, | 113 net::URLRequestContextGetter* getter, |
| 123 const std::string& refresh_token, | 114 const std::string& refresh_token, |
| 124 const OAuth2TokenService::ScopeSet& scopes, | 115 const OAuth2TokenService::ScopeSet& scopes, |
| 125 base::WeakPtr<RequestImpl> waiting_request); | 116 base::WeakPtr<RequestImpl> waiting_request); |
| 126 virtual ~Fetcher(); | 117 virtual ~Fetcher(); |
| 127 | 118 |
| 128 // Add a request that is waiting for the result of this Fetcher. | 119 // Add a request that is waiting for the result of this Fetcher. |
| 129 void AddWaitingRequest(base::WeakPtr<RequestImpl> waiting_request); | 120 void AddWaitingRequest(base::WeakPtr<RequestImpl> waiting_request); |
| 130 | 121 |
| 131 const OAuth2TokenService::ScopeSet& GetScopeSet() const; | 122 const OAuth2TokenService::ScopeSet& GetScopeSet() const; |
| 132 const std::string& GetRefreshToken() const; | 123 const std::string& GetRefreshToken() const; |
| 133 | 124 |
| 134 // The error result from this fetcher. | 125 // The error result from this fetcher. |
| 135 const GoogleServiceAuthError& error() const { return error_; } | 126 const GoogleServiceAuthError& error() const { return error_; } |
| 136 | 127 |
| 137 protected: | 128 protected: |
| 138 // OAuth2AccessTokenConsumer | 129 // OAuth2AccessTokenConsumer |
| 139 virtual void OnGetTokenSuccess(const std::string& access_token, | 130 virtual void OnGetTokenSuccess(const std::string& access_token, |
| 140 const base::Time& expiration_date) OVERRIDE; | 131 const base::Time& expiration_date) OVERRIDE; |
| 141 virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE; | 132 virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE; |
| 142 | 133 |
| 143 private: | 134 private: |
| 144 Fetcher(Profile* profile, | 135 Fetcher(OAuth2TokenService* oauth2_token_service, |
| 145 net::URLRequestContextGetter* getter, | 136 net::URLRequestContextGetter* getter, |
| 146 const std::string& refresh_token, | 137 const std::string& refresh_token, |
| 147 const OAuth2TokenService::ScopeSet& scopes, | 138 const OAuth2TokenService::ScopeSet& scopes, |
| 148 base::WeakPtr<RequestImpl> waiting_request); | 139 base::WeakPtr<RequestImpl> waiting_request); |
| 149 void Start(); | 140 void Start(); |
| 150 void InformWaitingRequests(); | 141 void InformWaitingRequests(); |
| 151 static bool ShouldRetry(const GoogleServiceAuthError& error); | 142 static bool ShouldRetry(const GoogleServiceAuthError& error); |
| 152 | 143 |
| 153 Profile* const profile_; | 144 // |oauth2_token_service_| remains valid for the life of this Fetcher, since |
| 145 // this Fetcher is destructed in the dtor of the OAuth2TokenService or is | |
| 146 // scheduled for deletion at the end of OnGetTokenFailure/OnGetTokenSuccess | |
| 147 // (whichever comes first). | |
| 148 OAuth2TokenService* const oauth2_token_service_; | |
| 154 scoped_refptr<net::URLRequestContextGetter> getter_; | 149 scoped_refptr<net::URLRequestContextGetter> getter_; |
| 155 const std::string refresh_token_; | 150 const std::string refresh_token_; |
| 156 const OAuth2TokenService::ScopeSet scopes_; | 151 const OAuth2TokenService::ScopeSet scopes_; |
| 157 std::vector<base::WeakPtr<RequestImpl> > waiting_requests_; | 152 std::vector<base::WeakPtr<RequestImpl> > waiting_requests_; |
| 158 | 153 |
| 159 int retry_number_; | 154 int retry_number_; |
| 160 base::OneShotTimer<OAuth2TokenService::Fetcher> retry_timer_; | 155 base::OneShotTimer<OAuth2TokenService::Fetcher> retry_timer_; |
| 161 scoped_ptr<OAuth2AccessTokenFetcher> fetcher_; | 156 scoped_ptr<OAuth2AccessTokenFetcher> fetcher_; |
| 162 | 157 |
| 163 // Variables that store fetch results. | 158 // Variables that store fetch results. |
| 164 // Initialized to be GoogleServiceAuthError::SERVICE_UNAVAILABLE to handle | 159 // Initialized to be GoogleServiceAuthError::SERVICE_UNAVAILABLE to handle |
| 165 // destruction. | 160 // destruction. |
| 166 GoogleServiceAuthError error_; | 161 GoogleServiceAuthError error_; |
| 167 std::string access_token_; | 162 std::string access_token_; |
| 168 base::Time expiration_date_; | 163 base::Time expiration_date_; |
| 169 | 164 |
| 170 DISALLOW_COPY_AND_ASSIGN(Fetcher); | 165 DISALLOW_COPY_AND_ASSIGN(Fetcher); |
| 171 }; | 166 }; |
| 172 | 167 |
| 173 // static | 168 // static |
| 174 OAuth2TokenService::Fetcher* OAuth2TokenService::Fetcher::CreateAndStart( | 169 OAuth2TokenService::Fetcher* OAuth2TokenService::Fetcher::CreateAndStart( |
| 175 Profile* profile, | 170 OAuth2TokenService* oauth2_token_service, |
| 176 net::URLRequestContextGetter* getter, | 171 net::URLRequestContextGetter* getter, |
| 177 const std::string& refresh_token, | 172 const std::string& refresh_token, |
| 178 const OAuth2TokenService::ScopeSet& scopes, | 173 const OAuth2TokenService::ScopeSet& scopes, |
| 179 base::WeakPtr<RequestImpl> waiting_request) { | 174 base::WeakPtr<RequestImpl> waiting_request) { |
| 180 OAuth2TokenService::Fetcher* fetcher = new Fetcher( | 175 OAuth2TokenService::Fetcher* fetcher = new Fetcher( |
| 181 profile, getter, refresh_token, scopes, waiting_request); | 176 oauth2_token_service, getter, refresh_token, scopes, waiting_request); |
| 182 fetcher->Start(); | 177 fetcher->Start(); |
| 183 return fetcher; | 178 return fetcher; |
| 184 } | 179 } |
| 185 | 180 |
| 186 OAuth2TokenService::Fetcher::Fetcher( | 181 OAuth2TokenService::Fetcher::Fetcher( |
| 187 Profile* profile, | 182 OAuth2TokenService* oauth2_token_service, |
| 188 net::URLRequestContextGetter* getter, | 183 net::URLRequestContextGetter* getter, |
| 189 const std::string& refresh_token, | 184 const std::string& refresh_token, |
| 190 const OAuth2TokenService::ScopeSet& scopes, | 185 const OAuth2TokenService::ScopeSet& scopes, |
| 191 base::WeakPtr<RequestImpl> waiting_request) | 186 base::WeakPtr<RequestImpl> waiting_request) |
| 192 : profile_(profile), | 187 : oauth2_token_service_(oauth2_token_service), |
| 193 getter_(getter), | 188 getter_(getter), |
| 194 refresh_token_(refresh_token), | 189 refresh_token_(refresh_token), |
| 195 scopes_(scopes), | 190 scopes_(scopes), |
| 196 retry_number_(0), | 191 retry_number_(0), |
| 197 error_(GoogleServiceAuthError::SERVICE_UNAVAILABLE) { | 192 error_(GoogleServiceAuthError::SERVICE_UNAVAILABLE) { |
| 198 DCHECK(profile_); | 193 DCHECK(oauth2_token_service_); |
| 199 DCHECK(getter_); | 194 DCHECK(getter_); |
| 200 DCHECK(refresh_token_.length()); | 195 DCHECK(refresh_token_.length()); |
| 201 waiting_requests_.push_back(waiting_request); | 196 waiting_requests_.push_back(waiting_request); |
| 202 } | 197 } |
| 203 | 198 |
| 204 OAuth2TokenService::Fetcher::~Fetcher() { | 199 OAuth2TokenService::Fetcher::~Fetcher() { |
| 205 // Inform the waiting requests if it has not done so. | 200 // Inform the waiting requests if it has not done so. |
| 206 if (waiting_requests_.size()) | 201 if (waiting_requests_.size()) |
| 207 InformWaitingRequests(); | 202 InformWaitingRequests(); |
| 208 } | 203 } |
| 209 | 204 |
| 210 void OAuth2TokenService::Fetcher::Start() { | 205 void OAuth2TokenService::Fetcher::Start() { |
| 211 fetcher_.reset(new OAuth2AccessTokenFetcher(this, getter_)); | 206 fetcher_.reset(new OAuth2AccessTokenFetcher(this, getter_)); |
| 212 fetcher_->Start(GaiaUrls::GetInstance()->oauth2_chrome_client_id(), | 207 fetcher_->Start(GaiaUrls::GetInstance()->oauth2_chrome_client_id(), |
| 213 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), | 208 GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), |
| 214 refresh_token_, | 209 refresh_token_, |
| 215 std::vector<std::string>(scopes_.begin(), scopes_.end())); | 210 std::vector<std::string>(scopes_.begin(), scopes_.end())); |
| 216 retry_timer_.Stop(); | 211 retry_timer_.Stop(); |
| 217 } | 212 } |
| 218 | 213 |
| 219 void OAuth2TokenService::Fetcher::OnGetTokenSuccess( | 214 void OAuth2TokenService::Fetcher::OnGetTokenSuccess( |
| 220 const std::string& access_token, | 215 const std::string& access_token, |
| 221 const base::Time& expiration_date) { | 216 const base::Time& expiration_date) { |
| 222 fetcher_.reset(); | 217 fetcher_.reset(); |
| 223 | 218 |
| 224 // Fetch completes. | 219 // Fetch completes. |
| 225 error_ = GoogleServiceAuthError(GoogleServiceAuthError::NONE); | 220 error_ = GoogleServiceAuthError::AuthErrorNone(); |
| 226 access_token_ = access_token; | 221 access_token_ = access_token; |
| 227 expiration_date_ = expiration_date; | 222 expiration_date_ = expiration_date; |
| 228 | 223 |
| 229 // |oauth2_token_service| should not be NULL as this Fetcher is destructed in | 224 // The caching may be skipped if ShouldCacheForRefreshToken() returns |
|
Andrew T Wilson (Slow)
2013/03/19 19:58:44
stale comment: ShouldCacheForRefreshToken() does n
David Roche
2013/03/21 00:12:02
Fixed, thx.
| |
| 230 // the dtor of the OAuth2TokenService that creates it if it is not scheduled | 225 // false. However, we still inform all waiting Consumers of a successful |
| 231 // to be destructed here and in OnGetTokenFailure(). | 226 // token fetch below, even if we skip caching the stale token. This is |
| 232 OAuth2TokenService* oauth2_token_service = | 227 // intentional -- some consumers may need the token for cleanup tasks. |
| 233 OAuth2TokenServiceFactory::GetForProfile(profile_); | 228 // https://chromiumcodereview.appspot.com/11312124/ |
| 234 DCHECK(oauth2_token_service); | 229 oauth2_token_service_->RegisterCacheEntry(refresh_token_, |
| 235 | 230 scopes_, |
| 236 oauth2_token_service->RegisterCacheEntry(refresh_token_, | 231 access_token_, |
| 237 scopes_, | 232 expiration_date_); |
| 238 access_token_, | |
| 239 expiration_date_); | |
| 240 // Deregisters itself from the service to prevent more waiting requests to | 233 // Deregisters itself from the service to prevent more waiting requests to |
| 241 // be added when it calls back the waiting requests. | 234 // be added when it calls back the waiting requests. |
| 242 oauth2_token_service->OnFetchComplete(this); | 235 oauth2_token_service_->OnFetchComplete(this); |
| 243 InformWaitingRequests(); | 236 InformWaitingRequests(); |
| 244 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 237 MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 245 } | 238 } |
| 246 | 239 |
| 247 void OAuth2TokenService::Fetcher::OnGetTokenFailure( | 240 void OAuth2TokenService::Fetcher::OnGetTokenFailure( |
| 248 const GoogleServiceAuthError& error) { | 241 const GoogleServiceAuthError& error) { |
| 249 fetcher_.reset(); | 242 fetcher_.reset(); |
| 250 | 243 |
| 251 if (ShouldRetry(error) && retry_number_ < kMaxFetchRetryNum) { | 244 if (ShouldRetry(error) && retry_number_ < kMaxFetchRetryNum) { |
| 252 int64 backoff = ComputeExponentialBackOffMilliseconds(retry_number_); | 245 int64 backoff = ComputeExponentialBackOffMilliseconds(retry_number_); |
| 253 ++retry_number_; | 246 ++retry_number_; |
| 254 retry_timer_.Stop(); | 247 retry_timer_.Stop(); |
| 255 retry_timer_.Start(FROM_HERE, | 248 retry_timer_.Start(FROM_HERE, |
| 256 base::TimeDelta::FromMilliseconds(backoff), | 249 base::TimeDelta::FromMilliseconds(backoff), |
| 257 this, | 250 this, |
| 258 &OAuth2TokenService::Fetcher::Start); | 251 &OAuth2TokenService::Fetcher::Start); |
| 259 return; | 252 return; |
| 260 } | 253 } |
| 261 | 254 |
| 262 // Fetch completes. | 255 // Fetch completes. |
| 263 error_ = error; | 256 error_ = error; |
| 264 | 257 |
| 265 // |oauth2_token_service| should not be NULL as this Fetcher is destructed in | |
| 266 // the dtor of the OAuth2TokenService that creates it if it is not scheduled | |
| 267 // to be destructed here and in OnGetTokenSuccess(). | |
| 268 OAuth2TokenService* oauth2_token_service = | |
| 269 OAuth2TokenServiceFactory::GetForProfile(profile_); | |
| 270 DCHECK(oauth2_token_service); | |
| 271 // Deregisters itself from the service to prevent more waiting requests to be | 258 // Deregisters itself from the service to prevent more waiting requests to be |
| 272 // added when it calls back the waiting requests. | 259 // added when it calls back the waiting requests. |
| 273 oauth2_token_service->OnFetchComplete(this); | 260 oauth2_token_service_->OnFetchComplete(this); |
| 274 InformWaitingRequests(); | 261 InformWaitingRequests(); |
| 275 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 262 MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 276 } | 263 } |
| 277 | 264 |
| 278 // static | 265 // static |
| 279 bool OAuth2TokenService::Fetcher::ShouldRetry( | 266 bool OAuth2TokenService::Fetcher::ShouldRetry( |
| 280 const GoogleServiceAuthError& error) { | 267 const GoogleServiceAuthError& error) { |
| 281 GoogleServiceAuthError::State error_state = error.state(); | 268 GoogleServiceAuthError::State error_state = error.state(); |
| 282 return error_state == GoogleServiceAuthError::CONNECTION_FAILED || | 269 return error_state == GoogleServiceAuthError::CONNECTION_FAILED || |
| 283 error_state == GoogleServiceAuthError::REQUEST_CANCELED || | 270 error_state == GoogleServiceAuthError::REQUEST_CANCELED || |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 314 | 301 |
| 315 OAuth2TokenService::Request::~Request() { | 302 OAuth2TokenService::Request::~Request() { |
| 316 } | 303 } |
| 317 | 304 |
| 318 OAuth2TokenService::Consumer::Consumer() { | 305 OAuth2TokenService::Consumer::Consumer() { |
| 319 } | 306 } |
| 320 | 307 |
| 321 OAuth2TokenService::Consumer::~Consumer() { | 308 OAuth2TokenService::Consumer::~Consumer() { |
| 322 } | 309 } |
| 323 | 310 |
| 324 OAuth2TokenService::OAuth2TokenService() | 311 OAuth2TokenService::OAuth2TokenService(net::URLRequestContextGetter* getter) |
| 325 : profile_(NULL), | 312 : request_context_getter_(getter) { |
| 326 last_auth_error_(GoogleServiceAuthError::NONE) { | |
| 327 } | 313 } |
| 328 | 314 |
| 329 OAuth2TokenService::~OAuth2TokenService() { | 315 OAuth2TokenService::~OAuth2TokenService() { |
| 330 // Release all the pending fetchers. | 316 // Release all the pending fetchers. |
| 331 STLDeleteContainerPairSecondPointers( | 317 STLDeleteContainerPairSecondPointers( |
| 332 pending_fetchers_.begin(), pending_fetchers_.end()); | 318 pending_fetchers_.begin(), pending_fetchers_.end()); |
| 333 } | 319 } |
| 334 | 320 |
| 335 void OAuth2TokenService::Initialize(Profile* profile) { | 321 bool OAuth2TokenService::RefreshTokenIsAvailable() { |
| 336 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 322 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 337 | 323 return !GetRefreshToken().empty(); |
| 338 DCHECK(profile); | |
| 339 DCHECK(!profile_); | |
| 340 profile_ = profile; | |
| 341 getter_ = profile->GetRequestContext(); | |
| 342 content::Source<TokenService> token_service_source( | |
| 343 TokenServiceFactory::GetForProfile(profile)); | |
| 344 registrar_.Add(this, | |
| 345 chrome::NOTIFICATION_TOKENS_CLEARED, | |
| 346 token_service_source); | |
| 347 registrar_.Add(this, | |
| 348 chrome::NOTIFICATION_TOKEN_AVAILABLE, | |
| 349 token_service_source); | |
| 350 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()-> | |
| 351 AddProvider(this); | |
| 352 } | 324 } |
| 353 | 325 |
| 354 void OAuth2TokenService::Shutdown() { | |
| 355 if (profile_) { | |
| 356 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()-> | |
| 357 RemoveProvider(this); | |
| 358 } | |
| 359 } | |
| 360 | |
| 361 | |
| 362 // static | 326 // static |
| 363 void OAuth2TokenService::InformConsumer( | 327 void OAuth2TokenService::InformConsumer( |
| 364 base::WeakPtr<OAuth2TokenService::RequestImpl> request, | 328 base::WeakPtr<OAuth2TokenService::RequestImpl> request, |
| 365 GoogleServiceAuthError error, | 329 GoogleServiceAuthError error, |
| 366 std::string access_token, | 330 std::string access_token, |
| 367 base::Time expiration_date) { | 331 base::Time expiration_date) { |
| 368 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 332 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 369 | 333 |
| 370 if (request) | 334 if (request) |
| 371 request->InformConsumer(error, access_token, expiration_date); | 335 request->InformConsumer(error, access_token, expiration_date); |
| 372 } | 336 } |
| 373 | 337 |
| 374 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( | 338 scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( |
| 375 const OAuth2TokenService::ScopeSet& scopes, | 339 const OAuth2TokenService::ScopeSet& scopes, |
| 376 OAuth2TokenService::Consumer* consumer) { | 340 OAuth2TokenService::Consumer* consumer) { |
| 377 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 341 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 378 | 342 |
| 379 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); | 343 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); |
| 380 | 344 |
| 381 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | 345 std::string refresh_token = GetRefreshToken(); |
| 382 if (!token_service || !token_service->HasOAuthLoginToken()) { | 346 if (refresh_token.empty()) { |
| 383 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 347 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
| 384 &OAuth2TokenService::InformConsumer, | 348 &OAuth2TokenService::InformConsumer, |
| 385 request->AsWeakPtr(), | 349 request->AsWeakPtr(), |
| 386 GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP), | 350 GoogleServiceAuthError( |
| 351 GoogleServiceAuthError::USER_NOT_SIGNED_UP), | |
| 387 std::string(), | 352 std::string(), |
| 388 base::Time())); | 353 base::Time())); |
| 389 return request.PassAs<Request>(); | 354 return request.PassAs<Request>(); |
| 390 } | 355 } |
| 391 | 356 |
| 392 const CacheEntry* cache_entry = GetCacheEntry(scopes); | 357 const CacheEntry* cache_entry = GetCacheEntry(scopes); |
| 393 if (cache_entry && cache_entry->access_token.length()) { | 358 if (cache_entry && cache_entry->access_token.length()) { |
| 394 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 359 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
| 395 &OAuth2TokenService::InformConsumer, | 360 &OAuth2TokenService::InformConsumer, |
| 396 request->AsWeakPtr(), | 361 request->AsWeakPtr(), |
| 397 GoogleServiceAuthError(GoogleServiceAuthError::NONE), | 362 GoogleServiceAuthError(GoogleServiceAuthError::NONE), |
| 398 cache_entry->access_token, | 363 cache_entry->access_token, |
| 399 cache_entry->expiration_date)); | 364 cache_entry->expiration_date)); |
| 400 return request.PassAs<Request>(); | 365 return request.PassAs<Request>(); |
| 401 } | 366 } |
| 402 | 367 |
| 403 std::string refresh_token = token_service->GetOAuth2LoginRefreshToken(); | |
| 404 if (!refresh_token.length()) { | |
| 405 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | |
| 406 &OAuth2TokenService::InformConsumer, | |
| 407 request->AsWeakPtr(), | |
| 408 GoogleServiceAuthError( | |
| 409 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS), | |
| 410 std::string(), | |
| 411 base::Time())); | |
| 412 return request.PassAs<Request>(); | |
| 413 } | |
| 414 | |
| 415 // Makes sure there is a pending fetcher for |scopes| and |refresh_token|. | 368 // Makes sure there is a pending fetcher for |scopes| and |refresh_token|. |
| 416 // Adds |request| to the waiting request list of this fetcher so |request| | 369 // Adds |request| to the waiting request list of this fetcher so |request| |
| 417 // will be called back when this fetcher finishes fetching. | 370 // will be called back when this fetcher finishes fetching. |
| 418 FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes); | 371 FetchParameters fetch_parameters = std::make_pair(refresh_token, scopes); |
| 419 std::map<FetchParameters, Fetcher*>::iterator iter = | 372 std::map<FetchParameters, Fetcher*>::iterator iter = |
| 420 pending_fetchers_.find(fetch_parameters); | 373 pending_fetchers_.find(fetch_parameters); |
| 421 if (iter != pending_fetchers_.end()) { | 374 if (iter != pending_fetchers_.end()) { |
| 422 iter->second->AddWaitingRequest(request->AsWeakPtr()); | 375 iter->second->AddWaitingRequest(request->AsWeakPtr()); |
| 423 return request.PassAs<Request>(); | 376 return request.PassAs<Request>(); |
| 424 } | 377 } |
| 425 pending_fetchers_[fetch_parameters] = Fetcher::CreateAndStart( | 378 pending_fetchers_[fetch_parameters] = Fetcher::CreateAndStart( |
| 426 profile_, getter_, refresh_token, scopes, request->AsWeakPtr()); | 379 this, request_context_getter_, refresh_token, scopes, |
| 380 request->AsWeakPtr()); | |
| 427 return request.PassAs<Request>(); | 381 return request.PassAs<Request>(); |
| 428 } | 382 } |
| 429 | 383 |
| 430 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { | 384 void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { |
| 431 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 385 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 432 | 386 |
| 433 // Update the auth error state so auth errors are appropriately communicated | 387 // Update the auth error state so auth errors are appropriately communicated |
| 434 // to the user. | 388 // to the user. |
| 435 UpdateAuthError(fetcher->error()); | 389 UpdateAuthError(fetcher->error()); |
| 436 | 390 |
| 437 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh | 391 // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh |
| 438 // token and scope set. This is guaranteed as follows; here a Fetcher is said | 392 // token and scope set. This is guaranteed as follows; here a Fetcher is said |
| 439 // to be uncompleted if it has not finished calling back | 393 // to be uncompleted if it has not finished calling back |
| 440 // OAuth2TokenService::OnFetchComplete(). | 394 // OAuth2TokenService::OnFetchComplete(). |
| 441 // | 395 // |
| 442 // (1) All the live Fetchers are created by this service. | 396 // (1) All the live Fetchers are created by this service. |
| 443 // This is because (1) all the live Fetchers are created by a live | 397 // This is because (1) all the live Fetchers are created by a live |
| 444 // service, as all the fetchers created by a service are destructed in the | 398 // service, as all the fetchers created by a service are destructed in the |
| 445 // service's dtor, and (2) there is at most one live OAuth2TokenSevice for | 399 // service's dtor. |
| 446 // a given profile at a time. | |
| 447 // | 400 // |
| 448 // (2) All the uncompleted Fetchers created by this service are recorded in | 401 // (2) All the uncompleted Fetchers created by this service are recorded in |
| 449 // |pending_fetchers_|. | 402 // |pending_fetchers_|. |
| 450 // This is because (1) all the created Fetchers are added to | 403 // This is because (1) all the created Fetchers are added to |
| 451 // |pending_fetchers_| (in method StartRequest()) and (2) method | 404 // |pending_fetchers_| (in method StartRequest()) and (2) method |
| 452 // OnFetchComplete() is the only place where a Fetcher is erased from | 405 // OnFetchComplete() is the only place where a Fetcher is erased from |
| 453 // |pending_fetchers_|. Note no Fetcher is erased in method | 406 // |pending_fetchers_|. Note no Fetcher is erased in method |
| 454 // StartRequest(). | 407 // StartRequest(). |
| 455 // | 408 // |
| 456 // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its | 409 // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its |
| 457 // refresh token and ScopeSet. This is guaranteed by Fetcher creation in | 410 // refresh token and ScopeSet. This is guaranteed by Fetcher creation in |
| 458 // method StartReuest(). | 411 // method StartRequest(). |
| 459 // | 412 // |
| 460 // When this method is called, |fetcher| is alive and uncompleted. | 413 // When this method is called, |fetcher| is alive and uncompleted. |
| 461 // By (1), |fetcher| is created by this service. | 414 // By (1), |fetcher| is created by this service. |
| 462 // Then by (2), |fetcher| is recorded in |pending_fetchers_|. | 415 // Then by (2), |fetcher| is recorded in |pending_fetchers_|. |
| 463 // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet. | 416 // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet. |
| 464 std::map<FetchParameters, Fetcher*>::iterator iter = | 417 std::map<FetchParameters, Fetcher*>::iterator iter = |
| 465 pending_fetchers_.find(std::make_pair( | 418 pending_fetchers_.find(std::make_pair( |
| 466 fetcher->GetRefreshToken(), fetcher->GetScopeSet())); | 419 fetcher->GetRefreshToken(), fetcher->GetScopeSet())); |
| 467 DCHECK(iter != pending_fetchers_.end()); | 420 DCHECK(iter != pending_fetchers_.end()); |
| 468 DCHECK_EQ(fetcher, iter->second); | 421 DCHECK_EQ(fetcher, iter->second); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 482 return &token_iterator->second; | 435 return &token_iterator->second; |
| 483 } | 436 } |
| 484 | 437 |
| 485 void OAuth2TokenService::RegisterCacheEntry( | 438 void OAuth2TokenService::RegisterCacheEntry( |
| 486 const std::string& refresh_token, | 439 const std::string& refresh_token, |
| 487 const OAuth2TokenService::ScopeSet& scopes, | 440 const OAuth2TokenService::ScopeSet& scopes, |
| 488 const std::string& access_token, | 441 const std::string& access_token, |
| 489 const base::Time& expiration_date) { | 442 const base::Time& expiration_date) { |
| 490 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 443 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 491 | 444 |
| 492 // Only register OAuth2 access tokens for the refresh token held by | |
| 493 // TokenService. | |
| 494 TokenService* token_service = TokenServiceFactory::GetForProfile(profile_); | |
| 495 if (!token_service || | |
| 496 !token_service->HasOAuthLoginToken() || | |
| 497 token_service->GetOAuth2LoginRefreshToken().compare(refresh_token) != 0) { | |
| 498 DLOG(INFO) << | |
| 499 "Received a token with a refresh token not maintained by TokenService."; | |
| 500 return; | |
| 501 } | |
| 502 | |
| 503 CacheEntry& token = token_cache_[scopes]; | 445 CacheEntry& token = token_cache_[scopes]; |
| 504 token.access_token = access_token; | 446 token.access_token = access_token; |
| 505 token.expiration_date = expiration_date; | 447 token.expiration_date = expiration_date; |
| 506 } | 448 } |
| 507 | 449 |
| 508 void OAuth2TokenService::Observe(int type, | 450 void OAuth2TokenService::UpdateAuthError(const GoogleServiceAuthError& error) { |
| 509 const content::NotificationSource& source, | 451 // Default implementation does nothing. |
| 510 const content::NotificationDetails& details) { | |
| 511 DCHECK(type == chrome::NOTIFICATION_TOKENS_CLEARED || | |
| 512 type == chrome::NOTIFICATION_TOKEN_AVAILABLE); | |
| 513 if (type == chrome::NOTIFICATION_TOKEN_AVAILABLE) { | |
| 514 TokenService::TokenAvailableDetails* tok_details = | |
| 515 content::Details<TokenService::TokenAvailableDetails>(details).ptr(); | |
| 516 if (tok_details->service() != GaiaConstants::kGaiaOAuth2LoginRefreshToken) | |
| 517 return; | |
| 518 } | |
| 519 // The GaiaConstants::kGaiaOAuth2LoginRefreshToken token is used to create | |
| 520 // OAuth2 access tokens. If this token either changes or is cleared, any | |
| 521 // available tokens must be invalidated. | |
| 522 token_cache_.clear(); | |
| 523 UpdateAuthError(GoogleServiceAuthError::AuthErrorNone()); | |
| 524 } | 452 } |
| 525 | 453 |
| 526 void OAuth2TokenService::UpdateAuthError(const GoogleServiceAuthError& error) { | 454 void OAuth2TokenService::ClearCache() { |
| 527 // Do not report connection errors as these are not actually auth errors. | 455 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 528 // We also want to avoid masking a "real" auth error just because we | 456 token_cache_.clear(); |
| 529 // subsequently get a transient network error. | |
| 530 if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) | |
| 531 return; | |
| 532 | |
| 533 if (error.state() != last_auth_error_.state()) { | |
| 534 last_auth_error_ = error; | |
| 535 SigninManagerFactory::GetForProfile(profile_)->signin_global_error()-> | |
| 536 AuthStatusChanged(); | |
| 537 } | |
| 538 } | 457 } |
| 539 | 458 |
| 540 GoogleServiceAuthError OAuth2TokenService::GetAuthStatus() const { | 459 int OAuth2TokenService::cache_size() { |
| 541 return last_auth_error_; | 460 return token_cache_.size(); |
| 542 } | 461 } |
| OLD | NEW |