Chromium Code Reviews| Index: chrome/common/net/gaia/oauth2_api_call_flow.cc |
| =================================================================== |
| --- chrome/common/net/gaia/oauth2_api_call_flow.cc (revision 0) |
| +++ chrome/common/net/gaia/oauth2_api_call_flow.cc (revision 0) |
| @@ -0,0 +1,152 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/common/net/gaia/oauth2_api_call_flow.h" |
| + |
| +#include <string> |
| +#include <vector> |
| + |
| +#include "base/basictypes.h" |
| +#include "chrome/common/net/gaia/gaia_urls.h" |
| +#include "net/base/escape.h" |
| +#include "net/base/load_flags.h" |
| +#include "net/http/http_status_code.h" |
| +#include "net/url_request/url_request_context_getter.h" |
| +#include "net/url_request/url_request_status.h" |
| + |
| +using content::URLFetcher; |
|
msw
2012/03/30 23:56:32
The Google C++ style guide discourages use of 'usi
Munjal (Google)
2012/04/04 19:24:38
I thought that using is fine in .cc files. Not in
|
| +using content::URLFetcherDelegate; |
| +using net::ResponseCookies; |
| +using net::URLRequestContextGetter; |
| +using net::URLRequestStatus; |
| + |
| +OAuth2ApiCallFlow::OAuth2ApiCallFlow( |
| + net::URLRequestContextGetter* context, |
| + const std::string& refresh_token, |
| + const std::string& access_token, |
| + const std::vector<std::string>& scopes) |
| + : context_(context), |
| + refresh_token_(refresh_token), |
| + access_token_(access_token), |
| + scopes_(scopes), |
| + state_(INITIAL), |
| + tried_mint_access_token_(false) { |
| +} |
| + |
| +OAuth2ApiCallFlow::~OAuth2ApiCallFlow() { } |
|
msw
2012/03/30 23:56:32
The Google C++ style guide says "No spaces inside
Munjal (Google)
2012/04/04 19:24:38
Done.
|
| + |
| +void OAuth2ApiCallFlow::Start() { |
| + BeginApiCall(); |
| +} |
| + |
| +void OAuth2ApiCallFlow::BeginApiCall() { |
| + CHECK(state_ == INITIAL || state_ == MINT_ACCESS_TOKEN_DONE); |
| + |
| + // If the access token is empty then directly try to mint one. |
| + if (access_token_.empty()) { |
| + BeginMintAccessToken(); |
| + return; |
|
msw
2012/03/30 23:56:32
nit: either return here and move the else-case to
Munjal (Google)
2012/04/04 19:24:38
Done.
|
| + } else { |
| + state_ = API_CALL_STARTED; |
| + |
| + url_fetcher_.reset(CreateURLFetcher()); |
| + url_fetcher_->Start(); // OnURLFetchComplete will be called. |
| + } |
| +} |
| + |
| +void OAuth2ApiCallFlow::EndApiCall(const URLFetcher* source) { |
| + CHECK_EQ(API_CALL_STARTED, state_); |
| + state_ = API_CALL_DONE; |
| + |
| + URLRequestStatus status = source->GetStatus(); |
| + if (!status.is_success()) { |
| + ProcessApiCallFailure(source); |
|
msw
2012/03/30 23:56:32
Should you set "state_ = ERROR_STATE;"?
Munjal (Google)
2012/04/04 19:24:38
Done.
|
| + return; |
| + } |
| + |
| + // If the response code is 401 Unauthorized then access token may have |
| + // expired. So try generating a new access token. |
| + if (source->GetResponseCode() == net::HTTP_UNAUTHORIZED) { |
| + // If we already tried minting a new access token, don't do it again. |
| + if (tried_mint_access_token_) |
| + ProcessApiCallFailure(source); |
|
msw
2012/03/30 23:56:32
Should you set "state_ = ERROR_STATE;"?
Munjal (Google)
2012/04/04 19:24:38
Done.
|
| + else |
| + BeginMintAccessToken(); |
| + |
| + return; |
| + } |
| + |
| + if (source->GetResponseCode() != net::HTTP_OK) { |
| + ProcessApiCallFailure(source); |
|
msw
2012/03/30 23:56:32
Should you set "state_ = ERROR_STATE;"?
Munjal (Google)
2012/04/04 19:24:38
Done.
|
| + return; |
| + } |
| + |
| + ProcessApiCallSuccess(source); |
| +} |
| + |
| +void OAuth2ApiCallFlow::BeginMintAccessToken() { |
| + CHECK(state_ == INITIAL || state_ == API_CALL_DONE); |
| + CHECK(!tried_mint_access_token_); |
| + state_ = MINT_ACCESS_TOKEN_STARTED; |
| + tried_mint_access_token_ = true; |
| + |
| + oauth2_access_token_fetcher_.reset(CreateAccessTokenFetcher()); |
| + oauth2_access_token_fetcher_->Start( |
| + GaiaUrls::GetInstance()->oauth2_chrome_client_id(), |
| + GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), |
| + refresh_token_, |
| + scopes_); |
| +} |
| + |
| +void OAuth2ApiCallFlow::EndMintAccessToken( |
| + const GoogleServiceAuthError* error) { |
| + CHECK_EQ(MINT_ACCESS_TOKEN_STARTED, state_); |
| + |
| + if (!error) { |
| + state_ = MINT_ACCESS_TOKEN_DONE; |
| + BeginApiCall(); |
| + } else { |
| + state_ = ERROR_STATE; |
| + ProcessMintAccessTokenFailure(*error); |
| + } |
| +} |
| + |
| +OAuth2AccessTokenFetcher* OAuth2ApiCallFlow::CreateAccessTokenFetcher() { |
| + return new OAuth2AccessTokenFetcher(this, context_); |
| +} |
| + |
| +void OAuth2ApiCallFlow::OnURLFetchComplete(const URLFetcher* source) { |
| + CHECK(source); |
| + CHECK_EQ(API_CALL_STARTED, state_); |
| + EndApiCall(source); |
| +} |
| + |
| +void OAuth2ApiCallFlow::OnGetTokenSuccess(const std::string& access_token) { |
| + access_token_ = access_token; |
| + EndMintAccessToken(NULL); |
| +} |
| + |
| +void OAuth2ApiCallFlow::OnGetTokenFailure( |
| + const GoogleServiceAuthError& error) { |
| + EndMintAccessToken(&error); |
| +} |
| + |
| +URLFetcher* OAuth2ApiCallFlow::CreateURLFetcher() { |
| + std::string body = CreateApiCallBody(); |
| + bool empty_body = body.empty(); |
| + URLFetcher* result = URLFetcher::Create( |
| + 0, |
| + CreateApiCallUrl(), |
| + empty_body ? URLFetcher::GET : URLFetcher::POST, |
| + this); |
| + |
| + result->SetRequestContext(context_); |
| + result->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
| + net::LOAD_DO_NOT_SAVE_COOKIES); |
| + |
| + if (!empty_body) |
| + result->SetUploadData("application/x-www-form-urlencoded", body); |
| + |
| + return result; |
| +} |