Home | History | Annotate | Download | only in policy
      1 // Copyright (c) 2013 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 "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/logging.h"
     11 #include "base/strings/string_util.h"
     12 #include "content/public/browser/browser_thread.h"
     13 #include "google_apis/gaia/gaia_auth_fetcher.h"
     14 #include "google_apis/gaia/gaia_constants.h"
     15 #include "google_apis/gaia/gaia_urls.h"
     16 #include "google_apis/gaia/google_service_auth_error.h"
     17 #include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
     18 #include "net/url_request/url_request_context_getter.h"
     19 
     20 using content::BrowserThread;
     21 
     22 namespace policy {
     23 
     24 namespace {
     25 
     26 // Max retry count for token fetching requests.
     27 const int kMaxRequestAttemptCount = 5;
     28 
     29 // OAuth token request retry delay in milliseconds.
     30 const int kRequestRestartDelay = 3000;
     31 
     32 }  // namespace
     33 
     34 PolicyOAuth2TokenFetcher::PolicyOAuth2TokenFetcher(
     35     net::URLRequestContextGetter* auth_context_getter,
     36     net::URLRequestContextGetter* system_context_getter,
     37     const TokenCallback& callback)
     38     : auth_context_getter_(auth_context_getter),
     39       system_context_getter_(system_context_getter),
     40       retry_count_(0),
     41       failed_(false),
     42       callback_(callback) {}
     43 
     44 PolicyOAuth2TokenFetcher::~PolicyOAuth2TokenFetcher() {}
     45 
     46 void PolicyOAuth2TokenFetcher::Start() {
     47   retry_count_ = 0;
     48   StartFetchingRefreshToken();
     49 }
     50 
     51 void PolicyOAuth2TokenFetcher::StartFetchingRefreshToken() {
     52   refresh_token_fetcher_.reset(new GaiaAuthFetcher(
     53       this, GaiaConstants::kChromeSource, auth_context_getter_.get()));
     54   refresh_token_fetcher_->StartCookieForOAuthLoginTokenExchange(std::string());
     55 }
     56 
     57 void PolicyOAuth2TokenFetcher::StartFetchingAccessToken() {
     58   std::vector<std::string> scopes;
     59   scopes.push_back(GaiaConstants::kDeviceManagementServiceOAuth);
     60   scopes.push_back(GaiaConstants::kOAuthWrapBridgeUserInfoScope);
     61   access_token_fetcher_.reset(
     62       new OAuth2AccessTokenFetcherImpl(this,
     63                                        system_context_getter_.get(),
     64                                        oauth2_refresh_token_));
     65   access_token_fetcher_->Start(
     66       GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
     67       GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
     68       scopes);
     69 }
     70 
     71 void PolicyOAuth2TokenFetcher::OnClientOAuthSuccess(
     72     const GaiaAuthConsumer::ClientOAuthResult& oauth2_tokens) {
     73   VLOG(1) << "OAuth2 tokens for policy fetching succeeded.";
     74   oauth2_refresh_token_ = oauth2_tokens.refresh_token;
     75   retry_count_ = 0;
     76   StartFetchingAccessToken();
     77 }
     78 
     79 void PolicyOAuth2TokenFetcher::OnClientOAuthFailure(
     80     const GoogleServiceAuthError& error) {
     81   VLOG(1) << "OAuth2 tokens fetch for policy fetch failed!";
     82   RetryOnError(error,
     83                base::Bind(&PolicyOAuth2TokenFetcher::StartFetchingRefreshToken,
     84                           AsWeakPtr()));
     85 }
     86 
     87 void PolicyOAuth2TokenFetcher::OnGetTokenSuccess(
     88     const std::string& access_token,
     89     const base::Time& expiration_time) {
     90   VLOG(1) << "OAuth2 access token (device management) fetching succeeded.";
     91   oauth2_access_token_ = access_token;
     92   ForwardPolicyToken(access_token,
     93                      GoogleServiceAuthError(GoogleServiceAuthError::NONE));
     94 }
     95 
     96 void PolicyOAuth2TokenFetcher::OnGetTokenFailure(
     97     const GoogleServiceAuthError& error) {
     98   LOG(ERROR) << "OAuth2 access token (device management) fetching failed!";
     99   RetryOnError(error,
    100                base::Bind(&PolicyOAuth2TokenFetcher::StartFetchingAccessToken,
    101                           AsWeakPtr()));
    102 }
    103 
    104 void PolicyOAuth2TokenFetcher::RetryOnError(const GoogleServiceAuthError& error,
    105                                             const base::Closure& task) {
    106   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    107   if ((error.state() == GoogleServiceAuthError::CONNECTION_FAILED ||
    108        error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE ||
    109        error.state() == GoogleServiceAuthError::REQUEST_CANCELED) &&
    110       retry_count_ < kMaxRequestAttemptCount) {
    111     retry_count_++;
    112     BrowserThread::PostDelayedTask(
    113         BrowserThread::UI, FROM_HERE, task,
    114         base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
    115     return;
    116   }
    117   LOG(ERROR) << "Unrecoverable error or retry count max reached.";
    118   failed_ = true;
    119   // Invoking the |callback_| signals to the owner of this object that it has
    120   // completed, and the owner may delete this object on the callback method.
    121   // So don't rely on |this| still being valid after ForwardPolicyToken()
    122   // returns i.e. don't write to |failed_| or other fields.
    123   ForwardPolicyToken(std::string(), error);
    124 }
    125 
    126 void PolicyOAuth2TokenFetcher::ForwardPolicyToken(
    127     const std::string& token,
    128     const GoogleServiceAuthError& error) {
    129   if (!callback_.is_null())
    130     callback_.Run(token, error);
    131 }
    132 
    133 }  // namespace policy
    134