diff options
author | fgorski@chromium.org <fgorski@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-20 05:40:55 +0000 |
---|---|---|
committer | fgorski@chromium.org <fgorski@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-20 05:40:55 +0000 |
commit | abe8e7cb022cc7638bfa6936a883476b0cf9228b (patch) | |
tree | 8863558ab00553261c000f09652adbb8812ed6a0 /google_apis | |
parent | 41687d27af1b72f2c533c8ff8da16a591cae4d45 (diff) | |
download | chromium_src-abe8e7cb022cc7638bfa6936a883476b0cf9228b.zip chromium_src-abe8e7cb022cc7638bfa6936a883476b0cf9228b.tar.gz chromium_src-abe8e7cb022cc7638bfa6936a883476b0cf9228b.tar.bz2 |
Making OAuth2TokenService multi-login aware:
* Adding account_id as a parameter to public methods, like: StartRequestXX, RefreshTokenIsAvailable, GetRefreshToken, InvalidateToken,
* Updating callers and derived classes,
* Updating cache handling for the OAuth2 access tokens in OAuth2TokenService
BUG=277149
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=224031
Review URL: https://chromiumcodereview.appspot.com/23382008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@224294 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'google_apis')
-rw-r--r-- | google_apis/gaia/oauth2_token_service.cc | 197 | ||||
-rw-r--r-- | google_apis/gaia/oauth2_token_service.h | 141 | ||||
-rw-r--r-- | google_apis/gaia/oauth2_token_service_unittest.cc | 241 |
3 files changed, 325 insertions, 254 deletions
diff --git a/google_apis/gaia/oauth2_token_service.cc b/google_apis/gaia/oauth2_token_service.cc index 828f4cc6..3259e28 100644 --- a/google_apis/gaia/oauth2_token_service.cc +++ b/google_apis/gaia/oauth2_token_service.cc @@ -19,48 +19,28 @@ int OAuth2TokenService::max_fetch_retry_num_ = 5; -OAuth2TokenService::ClientScopeSet::ClientScopeSet( +OAuth2TokenService::RequestParameters::RequestParameters( const std::string& client_id, + const std::string& account_id, const ScopeSet& scopes) : client_id(client_id), + account_id(account_id), scopes(scopes) { } -OAuth2TokenService::ClientScopeSet::~ClientScopeSet() { +OAuth2TokenService::RequestParameters::~RequestParameters() { } -bool OAuth2TokenService::ClientScopeSet::operator<( - const ClientScopeSet& s) const { - if (client_id < s.client_id) - return true; - else if (s.client_id < client_id) - return false; - - return scopes < s.scopes; -} - -OAuth2TokenService::FetchParameters::FetchParameters( - const std::string& client_id, - const std::string& refresh_token, - const ScopeSet& scopes) - : client_id(client_id), - refresh_token(refresh_token), - scopes(scopes) { -} - -OAuth2TokenService::FetchParameters::~FetchParameters() { -} - -bool OAuth2TokenService::FetchParameters::operator<( - const FetchParameters& p) const { +bool OAuth2TokenService::RequestParameters::operator<( + const RequestParameters& p) const { if (client_id < p.client_id) return true; else if (p.client_id < client_id) return false; - if (refresh_token < p.refresh_token) + if (account_id < p.account_id) return true; - else if (p.refresh_token < refresh_token) + else if (p.account_id < account_id) return false; return scopes < p.scopes; @@ -122,6 +102,7 @@ class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { // |refresh_token| and |scopes| in the request context obtained by |getter|. // The given |oauth2_token_service| will be informed when fetching is done. static Fetcher* CreateAndStart(OAuth2TokenService* oauth2_token_service, + const std::string& account_id, net::URLRequestContextGetter* getter, const std::string& client_id, const std::string& client_secret, @@ -141,6 +122,7 @@ class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { const ScopeSet& GetScopeSet() const; const std::string& GetRefreshToken() const; const std::string& GetClientId() const; + const std::string& GetAccountId() const; // The error result from this fetcher. const GoogleServiceAuthError& error() const { return error_; } @@ -154,6 +136,7 @@ class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { private: Fetcher(OAuth2TokenService* oauth2_token_service, + const std::string& account_id, net::URLRequestContextGetter* getter, const std::string& client_id, const std::string& client_secret, @@ -172,6 +155,7 @@ class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { // (whichever comes first). OAuth2TokenService* const oauth2_token_service_; scoped_refptr<net::URLRequestContextGetter> getter_; + const std::string account_id_; const std::string refresh_token_; const ScopeSet scopes_; std::vector<base::WeakPtr<RequestImpl> > waiting_requests_; @@ -197,6 +181,7 @@ class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { // static OAuth2TokenService::Fetcher* OAuth2TokenService::Fetcher::CreateAndStart( OAuth2TokenService* oauth2_token_service, + const std::string& account_id, net::URLRequestContextGetter* getter, const std::string& client_id, const std::string& client_secret, @@ -205,6 +190,7 @@ OAuth2TokenService::Fetcher* OAuth2TokenService::Fetcher::CreateAndStart( base::WeakPtr<RequestImpl> waiting_request) { OAuth2TokenService::Fetcher* fetcher = new Fetcher( oauth2_token_service, + account_id, getter, client_id, client_secret, @@ -217,6 +203,7 @@ OAuth2TokenService::Fetcher* OAuth2TokenService::Fetcher::CreateAndStart( OAuth2TokenService::Fetcher::Fetcher( OAuth2TokenService* oauth2_token_service, + const std::string& account_id, net::URLRequestContextGetter* getter, const std::string& client_id, const std::string& client_secret, @@ -225,6 +212,7 @@ OAuth2TokenService::Fetcher::Fetcher( base::WeakPtr<RequestImpl> waiting_request) : oauth2_token_service_(oauth2_token_service), getter_(getter), + account_id_(account_id), refresh_token_(refresh_token), scopes_(scopes), retry_number_(0), @@ -267,7 +255,7 @@ void OAuth2TokenService::Fetcher::OnGetTokenSuccess( // This is intentional -- some consumers may need the token for cleanup // tasks. https://chromiumcodereview.appspot.com/11312124/ oauth2_token_service_->RegisterCacheEntry(client_id_, - refresh_token_, + account_id_, scopes_, access_token_, expiration_date_); @@ -360,6 +348,10 @@ const std::string& OAuth2TokenService::Fetcher::GetClientId() const { return client_id_; } +const std::string& OAuth2TokenService::Fetcher::GetAccountId() const { + return account_id_; +} + OAuth2TokenService::Request::Request() { } @@ -389,14 +381,22 @@ void OAuth2TokenService::RemoveObserver(Observer* observer) { observer_list_.RemoveObserver(observer); } -bool OAuth2TokenService::RefreshTokenIsAvailable() { - return !GetRefreshToken().empty(); +bool OAuth2TokenService::RefreshTokenIsAvailable( + const std::string& account_id) { + DCHECK(CalledOnValidThread()); + return !GetRefreshToken(account_id).empty(); +} + +std::vector<std::string> OAuth2TokenService::GetAccounts() { + return std::vector<std::string>(); } scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( + const std::string& account_id, const OAuth2TokenService::ScopeSet& scopes, OAuth2TokenService::Consumer* consumer) { return StartRequestForClientWithContext( + account_id, GetRequestContext(), GaiaUrls::GetInstance()->oauth2_chrome_client_id(), GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), @@ -406,11 +406,13 @@ scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequestForClient( + const std::string& account_id, const std::string& client_id, const std::string& client_secret, const OAuth2TokenService::ScopeSet& scopes, OAuth2TokenService::Consumer* consumer) { return StartRequestForClientWithContext( + account_id, GetRequestContext(), client_id, client_secret, @@ -420,10 +422,12 @@ OAuth2TokenService::StartRequestForClient( scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequestWithContext( + const std::string& account_id, net::URLRequestContextGetter* getter, const ScopeSet& scopes, Consumer* consumer) { return StartRequestForClientWithContext( + account_id, getter, GaiaUrls::GetInstance()->oauth2_chrome_client_id(), GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), @@ -433,6 +437,7 @@ OAuth2TokenService::StartRequestWithContext( scoped_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequestForClientWithContext( + const std::string& account_id, net::URLRequestContextGetter* getter, const std::string& client_id, const std::string& client_secret, @@ -442,7 +447,7 @@ OAuth2TokenService::StartRequestForClientWithContext( scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); - if (!RefreshTokenIsAvailable()) { + if (!RefreshTokenIsAvailable(account_id)) { base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( &RequestImpl::InformConsumer, request->AsWeakPtr(), @@ -452,11 +457,14 @@ OAuth2TokenService::StartRequestForClientWithContext( return request.PassAs<Request>(); } - ClientScopeSet client_scopes(client_id, scopes); - if (HasCacheEntry(client_scopes)) { - StartCacheLookupRequest(request.get(), client_scopes, consumer); + RequestParameters request_parameters(client_id, + account_id, + scopes); + if (HasCacheEntry(request_parameters)) { + StartCacheLookupRequest(request.get(), request_parameters, consumer); } else { FetchOAuth2Token(request.get(), + account_id, getter, client_id, client_secret, @@ -466,27 +474,29 @@ OAuth2TokenService::StartRequestForClientWithContext( } void OAuth2TokenService::FetchOAuth2Token(RequestImpl* request, + const std::string& account_id, net::URLRequestContextGetter* getter, const std::string& client_id, const std::string& client_secret, const ScopeSet& scopes) { - std::string refresh_token = GetRefreshToken(); + std::string refresh_token = GetRefreshToken(account_id); - // If there is already a pending fetcher for |scopes| and |refresh_token|, + // If there is already a pending fetcher for |scopes| and |account_id|, // simply register this |request| for those results rather than starting // a new fetcher. - FetchParameters fetch_parameters = FetchParameters(client_id, - refresh_token, - scopes); - std::map<FetchParameters, Fetcher*>::iterator iter = - pending_fetchers_.find(fetch_parameters); + RequestParameters request_parameters = RequestParameters(client_id, + account_id, + scopes); + std::map<RequestParameters, Fetcher*>::iterator iter = + pending_fetchers_.find(request_parameters); if (iter != pending_fetchers_.end()) { iter->second->AddWaitingRequest(request->AsWeakPtr()); return; } - pending_fetchers_[fetch_parameters] = + pending_fetchers_[request_parameters] = Fetcher::CreateAndStart(this, + account_id, getter, client_id, client_secret, @@ -497,10 +507,10 @@ void OAuth2TokenService::FetchOAuth2Token(RequestImpl* request, void OAuth2TokenService::StartCacheLookupRequest( RequestImpl* request, - const OAuth2TokenService::ClientScopeSet& client_scopes, + const OAuth2TokenService::RequestParameters& request_parameters, OAuth2TokenService::Consumer* consumer) { - CHECK(HasCacheEntry(client_scopes)); - const CacheEntry* cache_entry = GetCacheEntry(client_scopes); + CHECK(HasCacheEntry(request_parameters)); + const CacheEntry* cache_entry = GetCacheEntry(request_parameters); base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( &RequestImpl::InformConsumer, request->AsWeakPtr(), @@ -509,13 +519,34 @@ void OAuth2TokenService::StartCacheLookupRequest( cache_entry->expiration_date)); } -void OAuth2TokenService::InvalidateToken(const ScopeSet& scopes, - const std::string& invalid_token) { +void OAuth2TokenService::InvalidateToken(const std::string& account_id, + const ScopeSet& scopes, + const std::string& access_token) { + InvalidateOAuth2Token(account_id, + GaiaUrls::GetInstance()->oauth2_chrome_client_id(), + scopes, + access_token); +} + +void OAuth2TokenService::InvalidateTokenForClient( + const std::string& account_id, + const std::string& client_id, + const ScopeSet& scopes, + const std::string& access_token) { + InvalidateOAuth2Token(account_id, client_id, scopes, access_token); +} + +void OAuth2TokenService::InvalidateOAuth2Token( + const std::string& account_id, + const std::string& client_id, + const ScopeSet& scopes, + const std::string& access_token) { DCHECK(CalledOnValidThread()); RemoveCacheEntry( - ClientScopeSet(GaiaUrls::GetInstance()->oauth2_chrome_client_id(), - scopes), - invalid_token); + RequestParameters(client_id, + account_id, + scopes), + access_token); } void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { @@ -523,7 +554,7 @@ void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { // Update the auth error state so auth errors are appropriately communicated // to the user. - UpdateAuthError(fetcher->error()); + UpdateAuthError(fetcher->GetAccountId(), fetcher->error()); // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh // token and scope set. This is guaranteed as follows; here a Fetcher is said @@ -551,10 +582,10 @@ void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { // By (1), |fetcher| is created by this service. // Then by (2), |fetcher| is recorded in |pending_fetchers_|. // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet. - std::map<FetchParameters, Fetcher*>::iterator iter = - pending_fetchers_.find(FetchParameters( + std::map<RequestParameters, Fetcher*>::iterator iter = + pending_fetchers_.find(RequestParameters( fetcher->GetClientId(), - fetcher->GetRefreshToken(), + fetcher->GetAccountId(), fetcher->GetScopeSet())); DCHECK(iter != pending_fetchers_.end()); DCHECK_EQ(fetcher, iter->second); @@ -562,15 +593,15 @@ void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { } bool OAuth2TokenService::HasCacheEntry( - const ClientScopeSet& client_scopes) { - const CacheEntry* cache_entry = GetCacheEntry(client_scopes); + const RequestParameters& request_parameters) { + const CacheEntry* cache_entry = GetCacheEntry(request_parameters); return cache_entry && cache_entry->access_token.length(); } const OAuth2TokenService::CacheEntry* OAuth2TokenService::GetCacheEntry( - const ClientScopeSet& client_scopes) { + const RequestParameters& request_parameters) { DCHECK(CalledOnValidThread()); - TokenCache::iterator token_iterator = token_cache_.find(client_scopes); + TokenCache::iterator token_iterator = token_cache_.find(request_parameters); if (token_iterator == token_cache_.end()) return NULL; if (token_iterator->second.expiration_date <= base::Time::Now()) { @@ -581,10 +612,10 @@ const OAuth2TokenService::CacheEntry* OAuth2TokenService::GetCacheEntry( } bool OAuth2TokenService::RemoveCacheEntry( - const ClientScopeSet& client_scopes, + const RequestParameters& request_parameters, const std::string& token_to_remove) { DCHECK(CalledOnValidThread()); - TokenCache::iterator token_iterator = token_cache_.find(client_scopes); + TokenCache::iterator token_iterator = token_cache_.find(request_parameters); if (token_iterator != token_cache_.end() && token_iterator->second.access_token == token_to_remove) { token_cache_.erase(token_iterator); @@ -595,19 +626,22 @@ bool OAuth2TokenService::RemoveCacheEntry( void OAuth2TokenService::RegisterCacheEntry( const std::string& client_id, - const std::string& refresh_token, + const std::string& account_id, const OAuth2TokenService::ScopeSet& scopes, const std::string& access_token, const base::Time& expiration_date) { DCHECK(CalledOnValidThread()); - CacheEntry& token = token_cache_[ClientScopeSet(client_id, - scopes)]; + CacheEntry& token = token_cache_[RequestParameters(client_id, + account_id, + scopes)]; token.access_token = access_token; token.expiration_date = expiration_date; } -void OAuth2TokenService::UpdateAuthError(const GoogleServiceAuthError& error) { +void OAuth2TokenService::UpdateAuthError( + const std::string& account_id, + const GoogleServiceAuthError& error) { // Default implementation does nothing. } @@ -616,9 +650,22 @@ void OAuth2TokenService::ClearCache() { token_cache_.clear(); } +void OAuth2TokenService::ClearCacheForAccount(const std::string& account_id) { + DCHECK(CalledOnValidThread()); + for (TokenCache::iterator iter = token_cache_.begin(); + iter != token_cache_.end(); + /* iter incremented in body */) { + if (iter->first.account_id == account_id) { + token_cache_.erase(iter++); + } else { + ++iter; + } + } +} + void OAuth2TokenService::CancelAllRequests() { std::vector<Fetcher*> fetchers_to_cancel; - for (std::map<FetchParameters, Fetcher*>::iterator iter = + for (std::map<RequestParameters, Fetcher*>::iterator iter = pending_fetchers_.begin(); iter != pending_fetchers_.end(); ++iter) { @@ -627,14 +674,14 @@ void OAuth2TokenService::CancelAllRequests() { CancelFetchers(fetchers_to_cancel); } -void OAuth2TokenService::CancelRequestsForToken( - const std::string& refresh_token) { +void OAuth2TokenService::CancelRequestsForAccount( + const std::string& account_id) { std::vector<Fetcher*> fetchers_to_cancel; - for (std::map<FetchParameters, Fetcher*>::iterator iter = + for (std::map<RequestParameters, Fetcher*>::iterator iter = pending_fetchers_.begin(); iter != pending_fetchers_.end(); ++iter) { - if (iter->first.refresh_token == refresh_token) + if (iter->first.account_id == account_id) fetchers_to_cancel.push_back(iter->second); } CancelFetchers(fetchers_to_cancel); @@ -666,10 +713,6 @@ void OAuth2TokenService::FireRefreshTokensLoaded() { FOR_EACH_OBSERVER(Observer, observer_list_, OnRefreshTokensLoaded()); } -void OAuth2TokenService::FireRefreshTokensCleared() { - FOR_EACH_OBSERVER(Observer, observer_list_, OnRefreshTokensCleared()); -} - int OAuth2TokenService::cache_size_for_testing() const { return token_cache_.size(); } @@ -682,12 +725,12 @@ void OAuth2TokenService::set_max_authorization_token_fetch_retries_for_testing( size_t OAuth2TokenService::GetNumPendingRequestsForTesting( const std::string& client_id, - const std::string& refresh_token, + const std::string& account_id, const ScopeSet& scopes) const { PendingFetcherMap::const_iterator iter = pending_fetchers_.find( - OAuth2TokenService::FetchParameters( + OAuth2TokenService::RequestParameters( client_id, - refresh_token, + account_id, scopes)); return iter == pending_fetchers_.end() ? 0 : iter->second->GetWaitingRequestCount(); diff --git a/google_apis/gaia/oauth2_token_service.h b/google_apis/gaia/oauth2_token_service.h index b58c563..d092430 100644 --- a/google_apis/gaia/oauth2_token_service.h +++ b/google_apis/gaia/oauth2_token_service.h @@ -29,7 +29,8 @@ class GoogleServiceAuthError; // Abstract base class for a service that fetches and caches OAuth2 access // tokens. Concrete subclasses should implement GetRefreshToken to return -// the appropriate refresh token. +// the appropriate refresh token. Derived services might maintain refresh tokens +// for multiple accounts. // // All calls are expected from the UI thread. // @@ -76,8 +77,6 @@ class OAuth2TokenService : public base::NonThreadSafe { // Classes that want to listen for token availability should implement this // interface and register with the AddObserver() call. - // TODO(rogerta): may get rid of |error| argument for OnRefreshTokenRevoked() - // once we stop supporting ClientLogin. Need to evaluate if its still useful. class Observer { public: // Called whenever a new login-scoped refresh token is available for @@ -91,8 +90,6 @@ class OAuth2TokenService : public base::NonThreadSafe { // Called after all refresh tokens are loaded during OAuth2TokenService // startup. virtual void OnRefreshTokensLoaded() {} - // Called after all refresh tokens are removed from OAuth2TokenService. - virtual void OnRefreshTokensCleared() {} protected: virtual ~Observer() {} }; @@ -107,21 +104,24 @@ class OAuth2TokenService : public base::NonThreadSafe { void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); - // Checks in the cache for a valid access token, and if not found starts - // a request for an OAuth2 access token using the OAuth2 refresh token - // maintained by this instance. The caller owns the returned Request. + // Checks in the cache for a valid access token for a specified |account_id| + // and |scopes|, and if not found starts a request for an OAuth2 access token + // using the OAuth2 refresh token maintained by this instance for that + // |account_id|. The caller owns the returned Request. // |scopes| is the set of scopes to get an access token for, |consumer| is // the object that will be called back with results if the returned request // is not deleted. // TODO(atwilson): Make this non-virtual when we change // ProfileOAuth2TokenServiceRequestTest to use FakeProfileOAuth2TokenService. - virtual scoped_ptr<Request> StartRequest(const ScopeSet& scopes, + virtual scoped_ptr<Request> StartRequest(const std::string& account_id, + const ScopeSet& scopes, Consumer* consumer); // This method does the same as |StartRequest| except it uses |client_id| and // |client_secret| to identify OAuth client app instead of using // Chrome's default values. scoped_ptr<Request> StartRequestForClient( + const std::string& account_id, const std::string& client_id, const std::string& client_secret, const ScopeSet& scopes, @@ -131,20 +131,35 @@ class OAuth2TokenService : public base::NonThreadSafe { // context given by |getter| instead of using the one returned by // |GetRequestContext| implemented by derived classes. scoped_ptr<Request> StartRequestWithContext( + const std::string& account_id, net::URLRequestContextGetter* getter, const ScopeSet& scopes, Consumer* consumer); - // Returns true if a refresh token exists. If false, calls to + // Lists account IDs of all accounts with a refresh token maintained by this + // instance. + virtual std::vector<std::string> GetAccounts(); + + // Returns true if a refresh token exists for |account_id|. If false, calls to // |StartRequest| will result in a Consumer::OnGetTokenFailure callback. - virtual bool RefreshTokenIsAvailable(); + virtual bool RefreshTokenIsAvailable(const std::string& account_id); + + // Mark an OAuth2 |access_token| issued for |account_id| and |scopes| as + // invalid. This should be done if the token was received from this class, + // but was not accepted by the server (e.g., the server returned + // 401 Unauthorized). The token will be removed from the cache for the given + // scopes. + void InvalidateToken(const std::string& account_id, + const ScopeSet& scopes, + const std::string& access_token); + + // Like |InvalidateToken| except is uses |client_id| to identity OAuth2 client + // app that issued the request instead of Chrome's default values. + void InvalidateTokenForClient(const std::string& account_id, + const std::string& client_id, + const ScopeSet& scopes, + const std::string& access_token); - // Mark an OAuth2 access token as invalid. This should be done if the token - // was received from this class, but was not accepted by the server (e.g., - // the server returned 401 Unauthorized). The token will be removed from the - // cache for the given scopes. - virtual void InvalidateToken(const ScopeSet& scopes, - const std::string& invalid_token); // Return the current number of entries in the cache. int cache_size_for_testing() const; @@ -152,20 +167,10 @@ class OAuth2TokenService : public base::NonThreadSafe { // Returns the current number of pending fetchers matching given params. size_t GetNumPendingRequestsForTesting( const std::string& client_id, - const std::string& refresh_token, + const std::string& account_id, const ScopeSet& scopes) const; protected: - struct ClientScopeSet { - ClientScopeSet(const std::string& client_id, - const ScopeSet& scopes); - ~ClientScopeSet(); - bool operator<(const ClientScopeSet& set) const; - - std::string client_id; - ScopeSet scopes; - }; - // Implements a cancelable |OAuth2TokenService::Request|, which should be // operated on the UI thread. // TODO(davidroche): move this out of header file. @@ -187,75 +192,81 @@ class OAuth2TokenService : public base::NonThreadSafe { Consumer* const consumer_; }; - // Subclasses should return the refresh token maintained. + // Subclasses should return the maintained refresh token for |account_id|. // If no token is available, return an empty string. - virtual std::string GetRefreshToken() = 0; + virtual std::string GetRefreshToken(const std::string& account_id) = 0; // Subclasses can override if they want to report errors to the user. - virtual void UpdateAuthError(const GoogleServiceAuthError& error); + virtual void UpdateAuthError( + const std::string& account_id, + const GoogleServiceAuthError& error); // Add a new entry to the cache. // Subclasses can override if there are implementation-specific reasons // that an access token should ever not be cached. virtual void RegisterCacheEntry(const std::string& client_id, - const std::string& refresh_token, + const std::string& account_id, const ScopeSet& scopes, const std::string& access_token, const base::Time& expiration_date); - // Returns true if GetCacheEntry would return a valid cache entry for the - // given scopes. - bool HasCacheEntry(const ClientScopeSet& client_scopes); - - // Posts a task to fire the Consumer callback with the cached token. Must - // Must only be called if HasCacheEntry() returns true. - void StartCacheLookupRequest(RequestImpl* request, - const ClientScopeSet& client_scopes, - Consumer* consumer); - // Clears the internal token cache. void ClearCache(); + // Clears all of the tokens belonging to |account_id| from the internal token + // cache. It does not matter what other parameters, like |client_id| were + // used to request the tokens. + void ClearCacheForAccount(const std::string& account_id); + // Cancels all requests that are currently in progress. void CancelAllRequests(); - // Cancels all requests related to a given refresh token. - void CancelRequestsForToken(const std::string& refresh_token); + // Cancels all requests related to a given |account_id|. + void CancelRequestsForAccount(const std::string& account_id); // Called by subclasses to notify observers. void FireRefreshTokenAvailable(const std::string& account_id); void FireRefreshTokenRevoked(const std::string& account_id); void FireRefreshTokensLoaded(); - void FireRefreshTokensCleared(); // Fetches an OAuth token for the specified client/scopes. Virtual so it can // be overridden for tests and for platform-specific behavior on Android. virtual void FetchOAuth2Token(RequestImpl* request, + const std::string& account_id, net::URLRequestContextGetter* getter, const std::string& client_id, const std::string& client_secret, const ScopeSet& scopes); + + // Invalidates the |access_token| issued for |account_id|, |client_id| and + // |scopes|. Virtual so it can be overriden for tests and for platform- + // specifc behavior. + virtual void InvalidateOAuth2Token(const std::string& account_id, + const std::string& client_id, + const ScopeSet& scopes, + const std::string& access_token); + private: class Fetcher; friend class Fetcher; // The parameters used to fetch an OAuth2 access token. - struct FetchParameters { - FetchParameters(const std::string& client_id, - const std::string& refresh_token, - const ScopeSet& scopes); - ~FetchParameters(); - bool operator<(const FetchParameters& params) const; + struct RequestParameters { + RequestParameters(const std::string& client_id, + const std::string& account_id, + const ScopeSet& scopes); + ~RequestParameters(); + bool operator<(const RequestParameters& params) const; // OAuth2 client id. std::string client_id; - // Refresh token used for minting access tokens within this request. - std::string refresh_token; + // Account id for which the request is made. + std::string account_id; // URL scopes for the requested access token. ScopeSet scopes; }; - typedef std::map<FetchParameters, Fetcher*> PendingFetcherMap; + typedef std::map<RequestParameters, Fetcher*> PendingFetcherMap; // Derived classes must provide a request context used for fetching access // tokens with the |StartRequest| method. @@ -271,25 +282,34 @@ class OAuth2TokenService : public base::NonThreadSafe { // uses |client_id| and |client_secret| to identify OAuth // client app instead of using Chrome's default values. scoped_ptr<Request> StartRequestForClientWithContext( + const std::string& account_id, net::URLRequestContextGetter* getter, const std::string& client_id, const std::string& client_secret, const ScopeSet& scopes, Consumer* consumer); + // Returns true if GetCacheEntry would return a valid cache entry for the + // given scopes. + bool HasCacheEntry(const RequestParameters& client_scopes); + + // Posts a task to fire the Consumer callback with the cached token. Must + // Must only be called if HasCacheEntry() returns true. + void StartCacheLookupRequest(RequestImpl* request, + const RequestParameters& client_scopes, + Consumer* consumer); + // Returns a currently valid OAuth2 access token for the given set of scopes, // or NULL if none have been cached. Note the user of this method should // ensure no entry with the same |client_scopes| is added before the usage of // the returned entry is done. - const CacheEntry* GetCacheEntry(const ClientScopeSet& client_scopes); - + const CacheEntry* GetCacheEntry(const RequestParameters& client_scopes); // Removes an access token for the given set of scopes from the cache. // Returns true if the entry was removed, otherwise false. - bool RemoveCacheEntry(const ClientScopeSet& client_scopes, + bool RemoveCacheEntry(const RequestParameters& client_scopes, const std::string& token_to_remove); - // Called when |fetcher| finishes fetching. void OnFetchComplete(Fetcher* fetcher); @@ -297,7 +317,7 @@ class OAuth2TokenService : public base::NonThreadSafe { void CancelFetchers(std::vector<Fetcher*> fetchers_to_cancel); // The cache of currently valid tokens. - typedef std::map<ClientScopeSet, CacheEntry> TokenCache; + typedef std::map<RequestParameters, CacheEntry> TokenCache; TokenCache token_cache_; // A map from fetch parameters to a fetcher that is fetching an OAuth2 access @@ -311,8 +331,7 @@ class OAuth2TokenService : public base::NonThreadSafe { // Maximum number of retries in fetching an OAuth2 access token. static int max_fetch_retry_num_; - FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, ClientScopeSetOrderTest); - FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, FetchParametersOrderTest); + FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, RequestParametersOrderTest); FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, SameScopesRequestedForDifferentClients); diff --git a/google_apis/gaia/oauth2_token_service_unittest.cc b/google_apis/gaia/oauth2_token_service_unittest.cc index 979b616..dcd21b1 100644 --- a/google_apis/gaia/oauth2_token_service_unittest.cc +++ b/google_apis/gaia/oauth2_token_service_unittest.cc @@ -23,18 +23,21 @@ class RetryingTestingOAuth2TokenServiceConsumer : public TestingOAuth2TokenServiceConsumer { public: RetryingTestingOAuth2TokenServiceConsumer( - OAuth2TokenService* oauth2_service) - : oauth2_service_(oauth2_service) {} + OAuth2TokenService* oauth2_service, + const std::string& account_id) + : oauth2_service_(oauth2_service), + account_id_(account_id) {} virtual ~RetryingTestingOAuth2TokenServiceConsumer() {} virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request, const GoogleServiceAuthError& error) OVERRIDE { TestingOAuth2TokenServiceConsumer::OnGetTokenFailure(request, error); request_.reset(oauth2_service_->StartRequest( - std::set<std::string>(), this).release()); + account_id_, OAuth2TokenService::ScopeSet(), this).release()); } OAuth2TokenService* oauth2_service_; + std::string account_id_; scoped_ptr<OAuth2TokenService::Request> request_; }; @@ -46,17 +49,21 @@ class TestOAuth2TokenService : public OAuth2TokenService { void CancelAllRequestsForTest() { CancelAllRequests(); } - void CancelRequestsForTokenForTest(const std::string& refresh_token) { - CancelRequestsForToken(refresh_token); + void CancelRequestsForAccountForTest(const std::string& account_id) { + CancelRequestsForAccount(account_id); } // For testing: set the refresh token to be used. - void set_refresh_token(const std::string& refresh_token) { - refresh_token_ = refresh_token; + void set_refresh_token(const std::string& account_id, + const std::string& refresh_token) { + refresh_tokens_[account_id] = refresh_token; } protected: - virtual std::string GetRefreshToken() OVERRIDE { return refresh_token_; } + virtual std::string GetRefreshToken(const std::string& account_id) OVERRIDE { + // account_id explicitly ignored. + return refresh_tokens_[account_id]; + } private: // OAuth2TokenService implementation. @@ -64,7 +71,7 @@ class TestOAuth2TokenService : public OAuth2TokenService { return request_context_getter_.get(); } - std::string refresh_token_; + std::map<std::string, std::string> refresh_tokens_; scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; }; @@ -74,6 +81,7 @@ class OAuth2TokenServiceTest : public testing::Test { oauth2_service_.reset( new TestOAuth2TokenService(new net::TestURLRequestContextGetter( message_loop_.message_loop_proxy()))); + account_id_ = "test_user@gmail.com"; } virtual void TearDown() OVERRIDE { @@ -85,12 +93,14 @@ class OAuth2TokenServiceTest : public testing::Test { base::MessageLoopForIO message_loop_; // net:: stuff needs IO message loop. net::TestURLFetcherFactory factory_; scoped_ptr<TestOAuth2TokenService> oauth2_service_; + std::string account_id_; TestingOAuth2TokenServiceConsumer consumer_; }; TEST_F(OAuth2TokenServiceTest, NoOAuth2RefreshToken) { scoped_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(std::set<std::string>(), &consumer_)); + oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), + &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); @@ -98,9 +108,11 @@ TEST_F(OAuth2TokenServiceTest, NoOAuth2RefreshToken) { } TEST_F(OAuth2TokenServiceTest, FailureShouldNotRetry) { - oauth2_service_->set_refresh_token("refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); scoped_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(std::set<std::string>(), &consumer_)); + oauth2_service_->StartRequest(account_id_, + OAuth2TokenService::ScopeSet(), + &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); @@ -116,9 +128,11 @@ TEST_F(OAuth2TokenServiceTest, FailureShouldNotRetry) { } TEST_F(OAuth2TokenServiceTest, SuccessWithoutCaching) { - oauth2_service_->set_refresh_token("refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); scoped_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(std::set<std::string>(), &consumer_)); + oauth2_service_->StartRequest(account_id_, + OAuth2TokenService::ScopeSet(), + &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); @@ -134,20 +148,20 @@ TEST_F(OAuth2TokenServiceTest, SuccessWithoutCaching) { } TEST_F(OAuth2TokenServiceTest, SuccessWithCaching) { - std::set<std::string> scopes1; + OAuth2TokenService::ScopeSet scopes1; scopes1.insert("s1"); scopes1.insert("s2"); - std::set<std::string> scopes1_same; + OAuth2TokenService::ScopeSet scopes1_same; scopes1_same.insert("s2"); scopes1_same.insert("s1"); - std::set<std::string> scopes2; + OAuth2TokenService::ScopeSet scopes2; scopes2.insert("s3"); - oauth2_service_->set_refresh_token("refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); // First request. - scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest( - scopes1, &consumer_)); + scoped_ptr<OAuth2TokenService::Request> request( + oauth2_service_->StartRequest(account_id_, scopes1, &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); @@ -164,7 +178,7 @@ TEST_F(OAuth2TokenServiceTest, SuccessWithCaching) { // Second request to the same set of scopes, should return the same token // without needing a network request. scoped_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(scopes1_same, &consumer_)); + oauth2_service_->StartRequest(account_id_, scopes1_same, &consumer_)); base::RunLoop().RunUntilIdle(); // No new network fetcher. @@ -174,7 +188,7 @@ TEST_F(OAuth2TokenServiceTest, SuccessWithCaching) { // Third request to a new set of scopes, should return another token. scoped_ptr<OAuth2TokenService::Request> request3( - oauth2_service_->StartRequest(scopes2, &consumer_)); + oauth2_service_->StartRequest(account_id_, scopes2, &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(2, consumer_.number_of_successful_tokens_); EXPECT_EQ(0, consumer_.number_of_errors_); @@ -189,11 +203,13 @@ TEST_F(OAuth2TokenServiceTest, SuccessWithCaching) { } TEST_F(OAuth2TokenServiceTest, SuccessAndExpirationAndFailure) { - oauth2_service_->set_refresh_token("refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); // First request. - scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest( - std::set<std::string>(), &consumer_)); + scoped_ptr<OAuth2TokenService::Request> request( + oauth2_service_->StartRequest(account_id_, + OAuth2TokenService::ScopeSet(), + &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); EXPECT_EQ(0, consumer_.number_of_errors_); @@ -208,7 +224,9 @@ TEST_F(OAuth2TokenServiceTest, SuccessAndExpirationAndFailure) { // Second request must try to access the network as the token has expired. scoped_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(std::set<std::string>(), &consumer_)); + oauth2_service_->StartRequest(account_id_, + OAuth2TokenService::ScopeSet(), + &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, consumer_.number_of_successful_tokens_); EXPECT_EQ(0, consumer_.number_of_errors_); @@ -224,11 +242,13 @@ TEST_F(OAuth2TokenServiceTest, SuccessAndExpirationAndFailure) { } TEST_F(OAuth2TokenServiceTest, SuccessAndExpirationAndSuccess) { - oauth2_service_->set_refresh_token("refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); // First request. - scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest( - std::set<std::string>(), &consumer_)); + scoped_ptr<OAuth2TokenService::Request> request( + oauth2_service_->StartRequest(account_id_, + OAuth2TokenService::ScopeSet(), + &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); EXPECT_EQ(0, consumer_.number_of_errors_); @@ -243,7 +263,9 @@ TEST_F(OAuth2TokenServiceTest, SuccessAndExpirationAndSuccess) { // Second request must try to access the network as the token has expired. scoped_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(std::set<std::string>(), &consumer_)); + oauth2_service_->StartRequest(account_id_, + OAuth2TokenService::ScopeSet(), + &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, consumer_.number_of_successful_tokens_); EXPECT_EQ(0, consumer_.number_of_errors_); @@ -259,10 +281,12 @@ TEST_F(OAuth2TokenServiceTest, SuccessAndExpirationAndSuccess) { } TEST_F(OAuth2TokenServiceTest, RequestDeletedBeforeCompletion) { - oauth2_service_->set_refresh_token("refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); - scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest( - std::set<std::string>(), &consumer_)); + scoped_ptr<OAuth2TokenService::Request> request( + oauth2_service_->StartRequest(account_id_, + OAuth2TokenService::ScopeSet(), + &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); EXPECT_EQ(0, consumer_.number_of_errors_); @@ -279,10 +303,10 @@ TEST_F(OAuth2TokenServiceTest, RequestDeletedBeforeCompletion) { } TEST_F(OAuth2TokenServiceTest, RequestDeletedAfterCompletion) { - oauth2_service_->set_refresh_token("refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest( - std::set<std::string>(), &consumer_)); + account_id_, OAuth2TokenService::ScopeSet(), &consumer_)); base::RunLoop().RunUntilIdle(); net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher); @@ -301,13 +325,14 @@ TEST_F(OAuth2TokenServiceTest, RequestDeletedAfterCompletion) { } TEST_F(OAuth2TokenServiceTest, MultipleRequestsForTheSameScopesWithOneDeleted) { - oauth2_service_->set_refresh_token("refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest( - std::set<std::string>(), &consumer_)); + account_id_, OAuth2TokenService::ScopeSet(), &consumer_)); base::RunLoop().RunUntilIdle(); scoped_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(std::set<std::string>(), &consumer_)); + oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), + &consumer_)); base::RunLoop().RunUntilIdle(); request.reset(); @@ -323,9 +348,9 @@ TEST_F(OAuth2TokenServiceTest, MultipleRequestsForTheSameScopesWithOneDeleted) { TEST_F(OAuth2TokenServiceTest, ClearedRefreshTokenFailsSubsequentRequests) { // We have a valid refresh token; the first request is successful. - oauth2_service_->set_refresh_token("refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest( - std::set<std::string>(), &consumer_)); + account_id_, OAuth2TokenService::ScopeSet(), &consumer_)); base::RunLoop().RunUntilIdle(); net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher); @@ -337,8 +362,9 @@ TEST_F(OAuth2TokenServiceTest, ClearedRefreshTokenFailsSubsequentRequests) { EXPECT_EQ("token", consumer_.last_token_); // The refresh token is no longer available; subsequent requests fail. - oauth2_service_->set_refresh_token(""); - request = oauth2_service_->StartRequest(std::set<std::string>(), &consumer_); + oauth2_service_->set_refresh_token(account_id_, ""); + request = oauth2_service_->StartRequest(account_id_, + OAuth2TokenService::ScopeSet(), &consumer_); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, consumer_.number_of_successful_tokens_); EXPECT_EQ(1, consumer_.number_of_errors_); @@ -346,25 +372,28 @@ TEST_F(OAuth2TokenServiceTest, ClearedRefreshTokenFailsSubsequentRequests) { TEST_F(OAuth2TokenServiceTest, ChangedRefreshTokenDoesNotAffectInFlightRequests) { - oauth2_service_->set_refresh_token("first refreshToken"); - std::set<std::string> scopes; + oauth2_service_->set_refresh_token(account_id_, "first refreshToken"); + OAuth2TokenService::ScopeSet scopes; scopes.insert("s1"); scopes.insert("s2"); + OAuth2TokenService::ScopeSet scopes1; + scopes.insert("s3"); + scopes.insert("s4"); scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest( - scopes, &consumer_)); + account_id_, scopes, &consumer_)); base::RunLoop().RunUntilIdle(); net::TestURLFetcher* fetcher1 = factory_.GetFetcherByID(0); ASSERT_TRUE(fetcher1); // Note |request| is still pending when the refresh token changes. - oauth2_service_->set_refresh_token("second refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "second refreshToken"); // A 2nd request (using the new refresh token) that occurs and completes // while the 1st request is in flight is successful. TestingOAuth2TokenServiceConsumer consumer2; scoped_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(scopes, &consumer2)); + oauth2_service_->StartRequest(account_id_, scopes1, &consumer2)); base::RunLoop().RunUntilIdle(); net::TestURLFetcher* fetcher2 = factory_.GetFetcherByID(0); @@ -384,9 +413,9 @@ TEST_F(OAuth2TokenServiceTest, } TEST_F(OAuth2TokenServiceTest, ServiceShutDownBeforeFetchComplete) { - oauth2_service_->set_refresh_token("refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest( - std::set<std::string>(), &consumer_)); + account_id_, OAuth2TokenService::ScopeSet(), &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); EXPECT_EQ(0, consumer_.number_of_errors_); @@ -399,10 +428,11 @@ TEST_F(OAuth2TokenServiceTest, ServiceShutDownBeforeFetchComplete) { } TEST_F(OAuth2TokenServiceTest, RetryingConsumer) { - oauth2_service_->set_refresh_token("refreshToken"); - RetryingTestingOAuth2TokenServiceConsumer consumer(oauth2_service_.get()); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); + RetryingTestingOAuth2TokenServiceConsumer consumer(oauth2_service_.get(), + account_id_); scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest( - std::set<std::string>(), &consumer)); + account_id_, OAuth2TokenService::ScopeSet(), &consumer)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, consumer.number_of_successful_tokens_); EXPECT_EQ(0, consumer.number_of_errors_); @@ -425,12 +455,12 @@ TEST_F(OAuth2TokenServiceTest, RetryingConsumer) { } TEST_F(OAuth2TokenServiceTest, InvalidateToken) { - std::set<std::string> scopes; - oauth2_service_->set_refresh_token("refreshToken"); + OAuth2TokenService::ScopeSet scopes; + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); // First request. scoped_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(scopes, &consumer_)); + oauth2_service_->StartRequest(account_id_, scopes, &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); @@ -447,7 +477,7 @@ TEST_F(OAuth2TokenServiceTest, InvalidateToken) { // Second request, should return the same token without needing a network // request. scoped_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(scopes, &consumer_)); + oauth2_service_->StartRequest(account_id_, scopes, &consumer_)); base::RunLoop().RunUntilIdle(); // No new network fetcher. @@ -456,9 +486,9 @@ TEST_F(OAuth2TokenServiceTest, InvalidateToken) { EXPECT_EQ("token", consumer_.last_token_); // Invalidating the token should return a new token on the next request. - oauth2_service_->InvalidateToken(scopes, consumer_.last_token_); + oauth2_service_->InvalidateToken(account_id_, scopes, consumer_.last_token_); scoped_ptr<OAuth2TokenService::Request> request3( - oauth2_service_->StartRequest(scopes, &consumer_)); + oauth2_service_->StartRequest(account_id_, scopes, &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(2, consumer_.number_of_successful_tokens_); EXPECT_EQ(0, consumer_.number_of_errors_); @@ -473,13 +503,15 @@ TEST_F(OAuth2TokenServiceTest, InvalidateToken) { } TEST_F(OAuth2TokenServiceTest, CancelAllRequests) { - oauth2_service_->set_refresh_token("refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); scoped_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(std::set<std::string>(), &consumer_)); + oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), + &consumer_)); - oauth2_service_->set_refresh_token("refreshToken2"); + oauth2_service_->set_refresh_token("account_id_2", "refreshToken2"); scoped_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(std::set<std::string>(), &consumer_)); + oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), + &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); @@ -491,33 +523,35 @@ TEST_F(OAuth2TokenServiceTest, CancelAllRequests) { EXPECT_EQ(2, consumer_.number_of_errors_); } -TEST_F(OAuth2TokenServiceTest, CancelRequestsForToken) { - std::set<std::string> scope_set_1; +TEST_F(OAuth2TokenServiceTest, CancelRequestsForAccount) { + OAuth2TokenService::ScopeSet scope_set_1; scope_set_1.insert("scope1"); scope_set_1.insert("scope2"); - std::set<std::string> scope_set_2(scope_set_1.begin(), scope_set_1.end()); + OAuth2TokenService::ScopeSet scope_set_2(scope_set_1.begin(), + scope_set_1.end()); scope_set_2.insert("scope3"); - oauth2_service_->set_refresh_token("refreshToken"); + oauth2_service_->set_refresh_token(account_id_, "refreshToken"); scoped_ptr<OAuth2TokenService::Request> request1( - oauth2_service_->StartRequest(scope_set_1, &consumer_)); + oauth2_service_->StartRequest(account_id_, scope_set_1, &consumer_)); scoped_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(scope_set_2, &consumer_)); + oauth2_service_->StartRequest(account_id_, scope_set_2, &consumer_)); - oauth2_service_->set_refresh_token("refreshToken2"); + std::string account_id_2("account_id_2"); + oauth2_service_->set_refresh_token(account_id_2, "refreshToken2"); scoped_ptr<OAuth2TokenService::Request> request3( - oauth2_service_->StartRequest(scope_set_1, &consumer_)); + oauth2_service_->StartRequest(account_id_2, scope_set_1, &consumer_)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); EXPECT_EQ(0, consumer_.number_of_errors_); - oauth2_service_->CancelRequestsForTokenForTest("refreshToken"); + oauth2_service_->CancelRequestsForAccountForTest(account_id_); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); EXPECT_EQ(2, consumer_.number_of_errors_); - oauth2_service_->CancelRequestsForTokenForTest("refreshToken2"); + oauth2_service_->CancelRequestsForAccountForTest(account_id_2); EXPECT_EQ(0, consumer_.number_of_successful_tokens_); EXPECT_EQ(3, consumer_.number_of_errors_); @@ -533,21 +567,24 @@ TEST_F(OAuth2TokenServiceTest, SameScopesRequestedForDifferentClients) { scope_set.insert("scope2"); std::string refresh_token("refreshToken"); - oauth2_service_->set_refresh_token(refresh_token); + oauth2_service_->set_refresh_token(account_id_, refresh_token); scoped_ptr<OAuth2TokenService::Request> request1( - oauth2_service_->StartRequestForClient(client_id_1, + oauth2_service_->StartRequestForClient(account_id_, + client_id_1, client_secret_1, scope_set, &consumer_)); scoped_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequestForClient(client_id_2, + oauth2_service_->StartRequestForClient(account_id_, + client_id_2, client_secret_2, scope_set, &consumer_)); // Start a request that should be duplicate of |request1|. scoped_ptr<OAuth2TokenService::Request> request3( - oauth2_service_->StartRequestForClient(client_id_1, + oauth2_service_->StartRequestForClient(account_id_, + client_id_1, client_secret_1, scope_set, &consumer_)); @@ -556,57 +593,29 @@ TEST_F(OAuth2TokenServiceTest, SameScopesRequestedForDifferentClients) { ASSERT_EQ(2U, oauth2_service_->GetNumPendingRequestsForTesting( client_id_1, - refresh_token, + account_id_, scope_set)); ASSERT_EQ(1U, oauth2_service_->GetNumPendingRequestsForTesting( client_id_2, - refresh_token, + account_id_, scope_set)); } -TEST_F(OAuth2TokenServiceTest, ClientScopeSetOrderTest) { - OAuth2TokenService::ScopeSet set_0; - OAuth2TokenService::ScopeSet set_1; - set_1.insert("1"); - - OAuth2TokenService::ClientScopeSet sets[] = { - OAuth2TokenService::ClientScopeSet("0", set_0), - OAuth2TokenService::ClientScopeSet("0", set_1), - OAuth2TokenService::ClientScopeSet("1", set_0), - OAuth2TokenService::ClientScopeSet("1", set_1), - }; - - for (size_t i = 0; i < arraysize(sets); i++) { - for (size_t j = 0; j < arraysize(sets); j++) { - if (i == j) { - EXPECT_FALSE(sets[i] < sets[j]) << " i=" << i << ", j=" << j; - EXPECT_FALSE(sets[j] < sets[i]) << " i=" << i << ", j=" << j; - } else if (i < j) { - EXPECT_TRUE(sets[i] < sets[j]) << " i=" << i << ", j=" << j; - EXPECT_FALSE(sets[j] < sets[i]) << " i=" << i << ", j=" << j; - } else { - EXPECT_TRUE(sets[j] < sets[i]) << " i=" << i << ", j=" << j; - EXPECT_FALSE(sets[i] < sets[j]) << " i=" << i << ", j=" << j; - } - } - } -} - -TEST_F(OAuth2TokenServiceTest, FetchParametersOrderTest) { +TEST_F(OAuth2TokenServiceTest, RequestParametersOrderTest) { OAuth2TokenService::ScopeSet set_0; OAuth2TokenService::ScopeSet set_1; set_1.insert("1"); - OAuth2TokenService::FetchParameters params[] = { - OAuth2TokenService::FetchParameters("0", "0", set_0), - OAuth2TokenService::FetchParameters("0", "0", set_1), - OAuth2TokenService::FetchParameters("0", "1", set_0), - OAuth2TokenService::FetchParameters("0", "1", set_1), - OAuth2TokenService::FetchParameters("1", "0", set_0), - OAuth2TokenService::FetchParameters("1", "0", set_1), - OAuth2TokenService::FetchParameters("1", "1", set_0), - OAuth2TokenService::FetchParameters("1", "1", set_1), + OAuth2TokenService::RequestParameters params[] = { + OAuth2TokenService::RequestParameters("0", "0", set_0), + OAuth2TokenService::RequestParameters("0", "0", set_1), + OAuth2TokenService::RequestParameters("0", "1", set_0), + OAuth2TokenService::RequestParameters("0", "1", set_1), + OAuth2TokenService::RequestParameters("1", "0", set_0), + OAuth2TokenService::RequestParameters("1", "0", set_1), + OAuth2TokenService::RequestParameters("1", "1", set_0), + OAuth2TokenService::RequestParameters("1", "1", set_1), }; for (size_t i = 0; i < arraysize(params); i++) { |