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