diff options
author | qsr@chromium.org <qsr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-19 09:37:18 +0000 |
---|---|---|
committer | qsr@chromium.org <qsr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-19 09:37:18 +0000 |
commit | cc4dbe2b5fc29dd70f88272da7fc2a536de7ce51 (patch) | |
tree | 17a9de632df4287e98d2ca076a319a9f74675ada /chrome/common/net | |
parent | d24b8c1e56e34a4e1040083189e5faf635154580 (diff) | |
download | chromium_src-cc4dbe2b5fc29dd70f88272da7fc2a536de7ce51.zip chromium_src-cc4dbe2b5fc29dd70f88272da7fc2a536de7ce51.tar.gz chromium_src-cc4dbe2b5fc29dd70f88272da7fc2a536de7ce51.tar.bz2 |
Update API of OAuth2AccessTokenFetcher to return an expiration date.
OAuth2 access token have an expiration date that is returned by the
server. Until now, we were not retrieving this information and had no
way to reuse the tokens correctly. This change updates the API so this
information is available to the caller.
This is a reland of revision 147199.
Original review: https://chromiumcodereview.appspot.com/10694154
TEST=None
BUG=None
TBR=munjal, kalman, Miranda Callahan, Ben Goodger (Google)
R=tbarzic
Review URL: https://chromiumcodereview.appspot.com/10796006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@147416 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/net')
7 files changed, 68 insertions, 22 deletions
diff --git a/chrome/common/net/gaia/oauth2_access_token_consumer.h b/chrome/common/net/gaia/oauth2_access_token_consumer.h index 0670d80..2c5d2a1 100644 --- a/chrome/common/net/gaia/oauth2_access_token_consumer.h +++ b/chrome/common/net/gaia/oauth2_access_token_consumer.h @@ -9,11 +9,19 @@ class GoogleServiceAuthError; +namespace base { +class Time; +} + // An interface that defines the callbacks for consumers to which // OAuth2AccessTokenFetcher can return results. class OAuth2AccessTokenConsumer { public: - virtual void OnGetTokenSuccess(const std::string& access_token) {} + // Success callback. |access_token| will contain a valid OAuth2 access token. + // |expiration_time| is the date until which the token can be used. This + // value has a built-in safety margin, so it can be used as-is. + virtual void OnGetTokenSuccess(const std::string& access_token, + const base::Time& expiration_time) {} virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) {} protected: diff --git a/chrome/common/net/gaia/oauth2_access_token_fetcher.cc b/chrome/common/net/gaia/oauth2_access_token_fetcher.cc index 595ecae..e3d0180 100644 --- a/chrome/common/net/gaia/oauth2_access_token_fetcher.cc +++ b/chrome/common/net/gaia/oauth2_access_token_fetcher.cc @@ -11,6 +11,7 @@ #include "base/json/json_reader.h" #include "base/string_util.h" #include "base/stringprintf.h" +#include "base/time.h" #include "base/values.h" #include "chrome/common/net/gaia/gaia_urls.h" #include "chrome/common/net/gaia/google_service_auth_error.h" @@ -42,6 +43,7 @@ static const char kGetAccessTokenBodyWithScopeFormat[] = "scope=%s"; static const char kAccessTokenKey[] = "access_token"; +static const char kExpiresInKey[] = "expires_in"; static GoogleServiceAuthError CreateAuthError(URLRequestStatus status) { CHECK(!status.is_success()); @@ -129,15 +131,26 @@ void OAuth2AccessTokenFetcher::EndGetAccessToken( } // The request was successfully fetched and it returned OK. - // Parse out the access token. + // Parse out the access token and the expiration time. std::string access_token; - ParseGetAccessTokenResponse(source, &access_token); - OnGetTokenSuccess(access_token); + int expires_in; + if (!ParseGetAccessTokenResponse(source, &access_token, &expires_in)) { + DLOG(WARNING) << "Response doesn't match expected format"; + OnGetTokenFailure( + GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)); + return; + } + // The token will expire in |expires_in| seconds. Take a 10% error margin to + // prevent reusing a token too close to its expiration date. + OnGetTokenSuccess( + access_token, + base::Time::Now() + base::TimeDelta::FromSeconds(9 * expires_in / 10)); } void OAuth2AccessTokenFetcher::OnGetTokenSuccess( - const std::string& access_token) { - consumer_->OnGetTokenSuccess(access_token); + const std::string& access_token, + const base::Time& expiration_time) { + consumer_->OnGetTokenSuccess(access_token, expiration_time); } void OAuth2AccessTokenFetcher::OnGetTokenFailure( @@ -189,7 +202,8 @@ std::string OAuth2AccessTokenFetcher::MakeGetAccessTokenBody( // static bool OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse( const net::URLFetcher* source, - std::string* access_token) { + std::string* access_token, + int* expires_in) { CHECK(source); CHECK(access_token); std::string data; @@ -199,5 +213,6 @@ bool OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse( return false; DictionaryValue* dict = static_cast<DictionaryValue*>(value.get()); - return dict->GetString(kAccessTokenKey, access_token); + return dict->GetString(kAccessTokenKey, access_token) && + dict->GetInteger(kExpiresInKey, expires_in); } diff --git a/chrome/common/net/gaia/oauth2_access_token_fetcher.h b/chrome/common/net/gaia/oauth2_access_token_fetcher.h index 61b7530..3242e62 100644 --- a/chrome/common/net/gaia/oauth2_access_token_fetcher.h +++ b/chrome/common/net/gaia/oauth2_access_token_fetcher.h @@ -16,6 +16,10 @@ class OAuth2AccessTokenFetcherTest; +namespace base { +class Time; +} + namespace net { class URLFetcher; class URLRequestContextGetter; @@ -75,7 +79,8 @@ class OAuth2AccessTokenFetcher : public net::URLFetcherDelegate { void EndGetAccessToken(const net::URLFetcher* source); // Helper mehtods for reporting back results. - void OnGetTokenSuccess(const std::string& access_token); + void OnGetTokenSuccess(const std::string& access_token, + const base::Time& expiration_time); void OnGetTokenFailure(const GoogleServiceAuthError& error); // Other helpers. @@ -86,7 +91,8 @@ class OAuth2AccessTokenFetcher : public net::URLFetcherDelegate { const std::string& refresh_token, const std::vector<std::string>& scopes); static bool ParseGetAccessTokenResponse(const net::URLFetcher* source, - std::string* access_token); + std::string* access_token, + int* expires_in); // State that is set during construction. OAuth2AccessTokenConsumer* const consumer_; diff --git a/chrome/common/net/gaia/oauth2_access_token_fetcher_unittest.cc b/chrome/common/net/gaia/oauth2_access_token_fetcher_unittest.cc index 013f23c..22b12a4 100644 --- a/chrome/common/net/gaia/oauth2_access_token_fetcher_unittest.cc +++ b/chrome/common/net/gaia/oauth2_access_token_fetcher_unittest.cc @@ -73,7 +73,8 @@ class MockOAuth2AccessTokenConsumer : public OAuth2AccessTokenConsumer { MockOAuth2AccessTokenConsumer() {} ~MockOAuth2AccessTokenConsumer() {} - MOCK_METHOD1(OnGetTokenSuccess, void(const std::string& access_token)); + MOCK_METHOD2(OnGetTokenSuccess, void(const std::string& access_token, + const base::Time& expiration_time)); MOCK_METHOD1(OnGetTokenFailure, void(const GoogleServiceAuthError& error)); }; @@ -137,7 +138,7 @@ TEST_F(OAuth2AccessTokenFetcherTest, TEST_F(OAuth2AccessTokenFetcherTest, DISABLED_Success) { TestURLFetcher* url_fetcher = SetupGetAccessToken( true, net::HTTP_OK, kValidTokenResponse); - EXPECT_CALL(consumer_, OnGetTokenSuccess("at1")).Times(1); + EXPECT_CALL(consumer_, OnGetTokenSuccess("at1", _)).Times(1); fetcher_.Start("client_id", "client_secret", "refresh_token", ScopeList()); fetcher_.OnURLFetchComplete(url_fetcher); } @@ -195,8 +196,9 @@ TEST_F(OAuth2AccessTokenFetcherTest, MAYBE_ParseGetAccessTokenResponse) { TestURLFetcher url_fetcher(0, GURL("www.google.com"), NULL); std::string at; + int expires_in; EXPECT_FALSE(OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse( - &url_fetcher, &at)); + &url_fetcher, &at, &expires_in)); EXPECT_TRUE(at.empty()); } { // Bad json. @@ -204,8 +206,9 @@ TEST_F(OAuth2AccessTokenFetcherTest, MAYBE_ParseGetAccessTokenResponse) { url_fetcher.SetResponseString("foo"); std::string at; + int expires_in; EXPECT_FALSE(OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse( - &url_fetcher, &at)); + &url_fetcher, &at, &expires_in)); EXPECT_TRUE(at.empty()); } { // Valid json: access token missing. @@ -213,8 +216,9 @@ TEST_F(OAuth2AccessTokenFetcherTest, MAYBE_ParseGetAccessTokenResponse) { url_fetcher.SetResponseString(kTokenResponseNoAccessToken); std::string at; + int expires_in; EXPECT_FALSE(OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse( - &url_fetcher, &at)); + &url_fetcher, &at, &expires_in)); EXPECT_TRUE(at.empty()); } { // Valid json: all good. @@ -222,8 +226,10 @@ TEST_F(OAuth2AccessTokenFetcherTest, MAYBE_ParseGetAccessTokenResponse) { url_fetcher.SetResponseString(kValidTokenResponse); std::string at; + int expires_in; EXPECT_TRUE(OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse( - &url_fetcher, &at)); + &url_fetcher, &at, &expires_in)); EXPECT_EQ("at1", at); + EXPECT_EQ(3600, expires_in); } } diff --git a/chrome/common/net/gaia/oauth2_api_call_flow.cc b/chrome/common/net/gaia/oauth2_api_call_flow.cc index 6426d7e..4d43e51 100644 --- a/chrome/common/net/gaia/oauth2_api_call_flow.cc +++ b/chrome/common/net/gaia/oauth2_api_call_flow.cc @@ -135,7 +135,8 @@ void OAuth2ApiCallFlow::OnURLFetchComplete(const net::URLFetcher* source) { EndApiCall(source); } -void OAuth2ApiCallFlow::OnGetTokenSuccess(const std::string& access_token) { +void OAuth2ApiCallFlow::OnGetTokenSuccess(const std::string& access_token, + const base::Time& expiration_time) { access_token_ = access_token; EndMintAccessToken(NULL); } diff --git a/chrome/common/net/gaia/oauth2_api_call_flow.h b/chrome/common/net/gaia/oauth2_api_call_flow.h index 6db2cba..c53aa45 100644 --- a/chrome/common/net/gaia/oauth2_api_call_flow.h +++ b/chrome/common/net/gaia/oauth2_api_call_flow.h @@ -53,7 +53,8 @@ class OAuth2ApiCallFlow virtual void Start(); // OAuth2AccessTokenFetcher implementation. - virtual void OnGetTokenSuccess(const std::string& access_token) OVERRIDE; + virtual void OnGetTokenSuccess(const std::string& access_token, + const base::Time& expiration_time) OVERRIDE; virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE; // net::URLFetcherDelegate implementation. diff --git a/chrome/common/net/gaia/oauth2_api_call_flow_unittest.cc b/chrome/common/net/gaia/oauth2_api_call_flow_unittest.cc index 5df058a..b042f3b 100644 --- a/chrome/common/net/gaia/oauth2_api_call_flow_unittest.cc +++ b/chrome/common/net/gaia/oauth2_api_call_flow_unittest.cc @@ -8,6 +8,7 @@ #include <vector> #include "base/memory/scoped_ptr.h" +#include "base/time.h" #include "chrome/common/net/gaia/gaia_urls.h" #include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/net/gaia/oauth2_access_token_consumer.h" @@ -194,7 +195,9 @@ TEST_F(OAuth2ApiCallFlowTest, SecondApiCallSucceeds) { flow_->OnURLFetchComplete(url_fetcher1); TestURLFetcher* url_fetcher2 = SetupApiCall(true, net::HTTP_OK); EXPECT_CALL(*flow_, ProcessApiCallSuccess(url_fetcher2)); - flow_->OnGetTokenSuccess(at); + flow_->OnGetTokenSuccess( + at, + base::Time::Now() + base::TimeDelta::FromMinutes(3600)); flow_->OnURLFetchComplete(url_fetcher2); } @@ -210,7 +213,9 @@ TEST_F(OAuth2ApiCallFlowTest, SecondApiCallFails) { flow_->OnURLFetchComplete(url_fetcher1); TestURLFetcher* url_fetcher2 = SetupApiCall(false, net::HTTP_UNAUTHORIZED); EXPECT_CALL(*flow_, ProcessApiCallFailure(url_fetcher2)); - flow_->OnGetTokenSuccess(at); + flow_->OnGetTokenSuccess( + at, + base::Time::Now() + base::TimeDelta::FromMinutes(3600)); flow_->OnURLFetchComplete(url_fetcher2); } @@ -240,7 +245,9 @@ TEST_F(OAuth2ApiCallFlowTest, EmptyAccessTokenFirstApiCallSucceeds) { TestURLFetcher* url_fetcher = SetupApiCall(true, net::HTTP_OK); EXPECT_CALL(*flow_, ProcessApiCallSuccess(url_fetcher)); flow_->Start(); - flow_->OnGetTokenSuccess(at); + flow_->OnGetTokenSuccess( + at, + base::Time::Now() + base::TimeDelta::FromMinutes(3600)); flow_->OnURLFetchComplete(url_fetcher); } @@ -254,7 +261,9 @@ TEST_F(OAuth2ApiCallFlowTest, EmptyAccessTokenApiCallFails) { TestURLFetcher* url_fetcher = SetupApiCall(false, net::HTTP_BAD_GATEWAY); EXPECT_CALL(*flow_, ProcessApiCallFailure(url_fetcher)); flow_->Start(); - flow_->OnGetTokenSuccess(at); + flow_->OnGetTokenSuccess( + at, + base::Time::Now() + base::TimeDelta::FromMinutes(3600)); flow_->OnURLFetchComplete(url_fetcher); } |