token_service.h revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 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// The TokenService will supply authentication tokens for any service that 6// needs it, such as sync. Whenever the user logs in, a controller watching 7// the token service is expected either to call ClientLogin to derive a new 8// SID and LSID, or to use GAIA OAuth requests to derive an OAuth1 access 9// token for the OAuthLogin scope. Whenever such credentials are available, 10// the TokenService should be updated with new credentials. The controller 11// should then start fetching tokens, which will be written to the database 12// after retrieval, as well as provided to listeners. 13// 14// A token service controller like the ChromiumOS login is expected to: 15// 16// Initialize() // Soon as you can 17// LoadTokensFromDB() // When it's OK to talk to the database 18// UpdateCredentials() // When user logs in 19// StartFetchingTokens() // When it's safe to start fetching 20// 21// Typically a user of the TokenService is expected just to call: 22// 23// if (token_service.HasTokenForService(servicename)) { 24// SetMyToken(token_service.GetTokenForService(servicename)); 25// } 26// RegisterSomeObserver(token_service); 27// 28// Whenever a token update occurs: 29// OnTokenAvailable(...) { 30// if (IsServiceICareAbout(notification.service())) { 31// SetMyToken(notification.token()) 32// } 33// } 34// 35// There is currently no easy way to create a fake TokenService. Tests that want 36// to use TokenService to issue tokens without the use of fake GaiaAuthFetchers 37// or persisting the tokens to disk via WebDataService can do this by 38// creating a TokenService (skipping the Initialize() step to avoid interacting 39// with WebDataService) and calling IssueAuthTokenForTest() to issue new tokens. 40// This will result in the TokenService sending out the appropriate 41// TOKEN_AVAILABLE notification and returning the correct response to future 42// calls to Has/GetTokenForService(). 43 44#ifndef CHROME_BROWSER_SIGNIN_TOKEN_SERVICE_H_ 45#define CHROME_BROWSER_SIGNIN_TOKEN_SERVICE_H_ 46 47#include <map> 48#include <string> 49#include <vector> 50 51#include "base/gtest_prod_util.h" 52#include "base/memory/scoped_ptr.h" 53#include "base/observer_list.h" 54#include "chrome/browser/profiles/profile_keyed_service.h" 55#include "chrome/browser/signin/signin_internals_util.h" 56#include "chrome/browser/webdata/web_data_service.h" 57#include "google_apis/gaia/gaia_auth_consumer.h" 58#include "google_apis/gaia/gaia_auth_fetcher.h" 59#include "google_apis/gaia/google_service_auth_error.h" 60 61class Profile; 62class TokenServiceTest; 63 64namespace net { 65class URLRequestContextGetter; 66} 67 68// The TokenService is a Profile member, so all calls are expected 69// from the UI thread. 70class TokenService : public GaiaAuthConsumer, 71 public ProfileKeyedService, 72 public WebDataServiceConsumer { 73 public: 74 TokenService(); 75 virtual ~TokenService(); 76 77 // Notification classes 78 class TokenAvailableDetails { 79 public: 80 TokenAvailableDetails() {} 81 TokenAvailableDetails(const std::string& service, 82 const std::string& token) 83 : service_(service), token_(token) {} 84 const std::string& service() const { return service_; } 85 const std::string& token() const { return token_; } 86 private: 87 std::string service_; 88 std::string token_; 89 }; 90 91 class TokenRequestFailedDetails { 92 public: 93 TokenRequestFailedDetails() 94 : error_(GoogleServiceAuthError::NONE) {} 95 TokenRequestFailedDetails(const std::string& service, 96 const GoogleServiceAuthError& error) 97 : service_(service), error_(error) {} 98 const std::string& service() const { return service_; } 99 const GoogleServiceAuthError& error() const { return error_; } 100 private: 101 std::string service_; 102 GoogleServiceAuthError error_; 103 }; 104 105 // Methods to register or remove SigninDiagnosticObservers 106 void AddSigninDiagnosticsObserver( 107 signin_internals_util::SigninDiagnosticsObserver* observer); 108 void RemoveSigninDiagnosticsObserver( 109 signin_internals_util::SigninDiagnosticsObserver* observer); 110 111 // Initialize this token service with a request source 112 // (usually from a GaiaAuthConsumer constant), and the profile. 113 // Typically you'd then update the credentials. 114 void Initialize(const char* const source, Profile* profile); 115 116 // Used to determine whether Initialize() has been called. 117 bool Initialized() const { return !source_.empty(); } 118 119 // Add a token not supported by a fetcher. 120 void AddAuthTokenManually(const std::string& service, 121 const std::string& auth_token); 122 123 // Update ClientLogin credentials in the token service. 124 // Afterwards you can StartFetchingTokens. 125 void UpdateCredentials( 126 const GaiaAuthConsumer::ClientLoginResult& credentials); 127 128 // Update credentials in the token service with oauth2 tokens. 129 // Afterwards you can StartFetchingTokens. 130 void UpdateCredentialsWithOAuth2( 131 const GaiaAuthConsumer::ClientOAuthResult& credentials); 132 133 // Terminate any running requests and reset the TokenService to a clean 134 // slate. Resets in memory structures. Does not modify the DB. 135 // When this is done, no tokens will be left in memory and no 136 // user credentials will be left. Useful if a user is logging out. 137 // Initialize doesn't need to be called again but UpdateCredentials does. 138 void ResetCredentialsInMemory(); 139 140 // Async load all tokens for services we know of from the DB. 141 // You should do this at startup. Optionally you can do it again 142 // after you reset in memory credentials. 143 virtual void LoadTokensFromDB(); 144 145 // Clear all DB stored tokens for the current profile. Tokens may still be 146 // available in memory. If a DB load is pending it may still be serviced. 147 void EraseTokensFromDB(); 148 149 // Returns true if tokens have been loaded from the DB. Set when 150 // LoadTokensFromDB() completes, unset when ResetCredentialsInMemory() is 151 // called. 152 bool TokensLoadedFromDB() const; 153 154 // Returns true if the token service has either GAIA credentials or OAuth2 155 // tokens needed to fetch other service tokens. 156 virtual bool AreCredentialsValid() const; 157 158 // Tokens will be fetched for all services(sync, talk) in the background. 159 // Results come back via event channel. Services can also poll before events 160 // are issued. 161 void StartFetchingTokens(); 162 virtual bool HasTokenForService(const char* service) const; 163 const std::string& GetTokenForService(const char* const service) const; 164 165 // OAuth login token is an all-powerful token that allows creating OAuth2 166 // tokens for any other scope (i.e. down-scoping). 167 // Typical use is to create an OAuth2 token for appropriate scope and then 168 // use that token to call a Google API. 169 virtual bool HasOAuthLoginToken() const; 170 virtual const std::string& GetOAuth2LoginRefreshToken() const; 171 172 // For tests only. Doesn't save to the WebDB. 173 void IssueAuthTokenForTest(const std::string& service, 174 const std::string& auth_token); 175 176 // GaiaAuthConsumer implementation. 177 virtual void OnIssueAuthTokenSuccess(const std::string& service, 178 const std::string& auth_token) OVERRIDE; 179 virtual void OnIssueAuthTokenFailure( 180 const std::string& service, 181 const GoogleServiceAuthError& error) OVERRIDE; 182 virtual void OnClientOAuthSuccess(const ClientOAuthResult& result) OVERRIDE; 183 virtual void OnClientOAuthFailure( 184 const GoogleServiceAuthError& error) OVERRIDE; 185 186 // WebDataServiceConsumer implementation. 187 virtual void OnWebDataServiceRequestDone( 188 WebDataService::Handle h, 189 const WDTypedResult* result) OVERRIDE; 190 191 protected: 192 // Saves OAuth2 credentials. 193 void SaveOAuth2Credentials(const ClientOAuthResult& result); 194 195 void set_tokens_loaded(bool loaded) { 196 tokens_loaded_ = loaded; 197 } 198 199 private: 200 201 // Gets the list of all service names for which tokens will be retrieved. 202 // This method is meant only for tests. 203 static void GetServiceNamesForTesting(std::vector<std::string>* names); 204 205 void FireTokenAvailableNotification(const std::string& service, 206 const std::string& auth_token); 207 208 void FireTokenRequestFailedNotification(const std::string& service, 209 const GoogleServiceAuthError& error); 210 211 void LoadTokensIntoMemory( 212 const std::map<std::string, std::string>& db_tokens, 213 std::map<std::string, std::string>* in_memory_tokens); 214 void LoadSingleTokenIntoMemory( 215 const std::map<std::string, std::string>& db_tokens, 216 std::map<std::string, std::string>* in_memory_tokens, 217 const std::string& service); 218 219 void SaveAuthTokenToDB(const std::string& service, 220 const std::string& auth_token); 221 222 // Returns the index of the given service. 223 static int GetServiceIndex(const std::string& service); 224 225 // The profile with which this instance was initialized, or NULL. 226 Profile* profile_; 227 228 // Web data service to access tokens from. 229 scoped_refptr<WebDataService> web_data_service_; 230 // Getter to use for fetchers. 231 scoped_refptr<net::URLRequestContextGetter> getter_; 232 // Request handle to load Gaia tokens from DB. 233 WebDataService::Handle token_loading_query_; 234 // True if token loading has completed (regardless of success). 235 bool tokens_loaded_; 236 237 // Gaia request source for Gaia accounting. 238 std::string source_; 239 // Credentials from ClientLogin for Issuing auth tokens. 240 GaiaAuthConsumer::ClientLoginResult credentials_; 241 242 // A bunch of fetchers suitable for ClientLogin token issuing. We don't care 243 // about the ordering, nor do we care which is for which service. The 244 // number of entries in this array must match the number of entries in the 245 // kServices array declared in the cc file. If not, a compile time error 246 // will occur. 247 scoped_ptr<GaiaAuthFetcher> fetchers_[2]; 248 249 // Map from service to token. 250 std::map<std::string, std::string> token_map_; 251 252 // The list of SigninDiagnosticObservers 253 ObserverList<signin_internals_util::SigninDiagnosticsObserver> 254 signin_diagnostics_observers_; 255 256 friend class TokenServiceTest; 257 FRIEND_TEST_ALL_PREFIXES(TokenServiceTest, LoadTokensIntoMemoryBasic); 258 FRIEND_TEST_ALL_PREFIXES(TokenServiceTest, LoadTokensIntoMemoryAdvanced); 259 FRIEND_TEST_ALL_PREFIXES(TokenServiceTest, FullIntegrationNewServicesAdded); 260 261 DISALLOW_COPY_AND_ASSIGN(TokenService); 262}; 263 264#endif // CHROME_BROWSER_SIGNIN_TOKEN_SERVICE_H_ 265