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.
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.
14 // A token service controller like the ChromiumOS login is expected to:
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
21 // Typically a user of the TokenService is expected just to call:
23 // if (token_service.HasTokenForService(servicename)) {
24 // SetMyToken(token_service.GetTokenForService(servicename));
26 // RegisterSomeObserver(token_service);
28 // Whenever a token update occurs:
29 // OnTokenAvailable(...) {
30 // if (IsServiceICareAbout(notification.service())) {
31 // SetMyToken(notification.token())
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().
44 #ifndef CHROME_BROWSER_SIGNIN_TOKEN_SERVICE_H_
45 #define CHROME_BROWSER_SIGNIN_TOKEN_SERVICE_H_
51 #include "base/gtest_prod_util.h"
52 #include "base/memory/scoped_ptr.h"
53 #include "base/observer_list.h"
54 #include "chrome/browser/signin/signin_internals_util.h"
55 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
56 #include "components/webdata/common/web_data_service_base.h"
57 #include "components/webdata/common/web_data_service_consumer.h"
58 #include "google_apis/gaia/gaia_auth_consumer.h"
59 #include "google_apis/gaia/gaia_auth_fetcher.h"
60 #include "google_apis/gaia/google_service_auth_error.h"
63 class TokenServiceTest;
67 class URLRequestContextGetter;
70 // The TokenService is a Profile member, so all calls are expected
71 // from the UI thread.
72 class TokenService : public GaiaAuthConsumer,
73 public BrowserContextKeyedService,
74 public WebDataServiceConsumer {
77 virtual ~TokenService();
79 // Notification classes
80 class TokenAvailableDetails {
82 TokenAvailableDetails() {}
83 TokenAvailableDetails(const std::string& service,
84 const std::string& token)
85 : service_(service), token_(token) {}
86 const std::string& service() const { return service_; }
87 const std::string& token() const { return token_; }
93 class TokenRequestFailedDetails {
95 TokenRequestFailedDetails()
96 : error_(GoogleServiceAuthError::NONE) {}
97 TokenRequestFailedDetails(const std::string& service,
98 const GoogleServiceAuthError& error)
99 : service_(service), error_(error) {}
100 const std::string& service() const { return service_; }
101 const GoogleServiceAuthError& error() const { return error_; }
103 std::string service_;
104 GoogleServiceAuthError error_;
107 // BrowserContextKeyedService implementation.
108 virtual void Shutdown() OVERRIDE;
110 // Methods to register or remove SigninDiagnosticObservers
111 void AddSigninDiagnosticsObserver(
112 signin_internals_util::SigninDiagnosticsObserver* observer);
113 void RemoveSigninDiagnosticsObserver(
114 signin_internals_util::SigninDiagnosticsObserver* observer);
116 // Initialize this token service with a request source
117 // (usually from a GaiaAuthConsumer constant), and the profile.
118 // Typically you'd then update the credentials.
119 void Initialize(const char* const source, Profile* profile);
121 // Used to determine whether Initialize() has been called.
122 bool Initialized() const { return !source_.empty(); }
124 // Add a token not supported by a fetcher.
125 void AddAuthTokenManually(const std::string& service,
126 const std::string& auth_token);
128 // Update ClientLogin credentials in the token service.
129 // Afterwards you can StartFetchingTokens.
130 void UpdateCredentials(
131 const GaiaAuthConsumer::ClientLoginResult& credentials);
133 // Update credentials in the token service with oauth2 tokens.
134 // Afterwards you can StartFetchingTokens.
135 void UpdateCredentialsWithOAuth2(
136 const GaiaAuthConsumer::ClientOAuthResult& credentials);
138 // Terminate any running requests and reset the TokenService to a clean
139 // slate. Resets in memory structures. Does not modify the DB.
140 // When this is done, no tokens will be left in memory and no
141 // user credentials will be left. Useful if a user is logging out.
142 // Initialize doesn't need to be called again but UpdateCredentials does.
143 void ResetCredentialsInMemory();
145 // Async load all tokens for services we know of from the DB.
146 // You should do this at startup. Optionally you can do it again
147 // after you reset in memory credentials.
148 virtual void LoadTokensFromDB();
150 // Clear all DB stored tokens for the current profile. Tokens may still be
151 // available in memory. If a DB load is pending it may still be serviced.
152 void EraseTokensFromDB();
154 // Returns true if tokens have been loaded from the DB. Set when
155 // LoadTokensFromDB() completes, unset when ResetCredentialsInMemory() is
157 bool TokensLoadedFromDB() const;
159 // Returns true if the token service has either GAIA credentials or OAuth2
160 // tokens needed to fetch other service tokens.
161 virtual bool AreCredentialsValid() const;
163 // Tokens will be fetched for all services(sync, talk) in the background.
164 // Results come back via event channel. Services can also poll before events
166 void StartFetchingTokens();
167 virtual bool HasTokenForService(const char* service) const;
168 const std::string& GetTokenForService(const char* const service) const;
170 // OAuth login token is an all-powerful token that allows creating OAuth2
171 // tokens for any other scope (i.e. down-scoping).
172 // Typical use is to create an OAuth2 token for appropriate scope and then
173 // use that token to call a Google API.
174 virtual bool HasOAuthLoginToken() const;
175 virtual const std::string& GetOAuth2LoginRefreshToken() const;
177 // For tests only. Doesn't save to the WebDB.
178 void IssueAuthTokenForTest(const std::string& service,
179 const std::string& auth_token);
181 // GaiaAuthConsumer implementation.
182 virtual void OnIssueAuthTokenSuccess(const std::string& service,
183 const std::string& auth_token) OVERRIDE;
184 virtual void OnIssueAuthTokenFailure(
185 const std::string& service,
186 const GoogleServiceAuthError& error) OVERRIDE;
187 virtual void OnClientOAuthSuccess(const ClientOAuthResult& result) OVERRIDE;
188 virtual void OnClientOAuthFailure(
189 const GoogleServiceAuthError& error) OVERRIDE;
191 // WebDataServiceConsumer implementation.
192 virtual void OnWebDataServiceRequestDone(
193 WebDataServiceBase::Handle h,
194 const WDTypedResult* result) OVERRIDE;
196 // Gets the list of all service names for which tokens will be retrieved.
197 static void GetServiceNames(std::vector<std::string>* names);
200 // Saves OAuth2 credentials.
201 void SaveOAuth2Credentials(const ClientOAuthResult& result);
203 void set_tokens_loaded(bool loaded) {
204 tokens_loaded_ = loaded;
208 void FireTokenAvailableNotification(const std::string& service,
209 const std::string& auth_token);
211 void FireTokenRequestFailedNotification(const std::string& service,
212 const GoogleServiceAuthError& error);
214 void LoadTokensIntoMemory(
215 const std::map<std::string, std::string>& db_tokens,
216 std::map<std::string, std::string>* in_memory_tokens);
217 void LoadSingleTokenIntoMemory(
218 const std::map<std::string, std::string>& db_tokens,
219 std::map<std::string, std::string>* in_memory_tokens,
220 const std::string& service);
222 void SaveAuthTokenToDB(const std::string& service,
223 const std::string& auth_token);
225 // Returns the index of the given service.
226 static int GetServiceIndex(const std::string& service);
228 // The profile with which this instance was initialized, or NULL.
231 // Web data service to access tokens from.
232 scoped_refptr<TokenWebData> token_web_data_;
233 // Getter to use for fetchers.
234 scoped_refptr<net::URLRequestContextGetter> getter_;
235 // Request handle to load Gaia tokens from DB.
236 WebDataServiceBase::Handle token_loading_query_;
237 // True if token loading has completed (regardless of success).
240 // Gaia request source for Gaia accounting.
242 // Credentials from ClientLogin for Issuing auth tokens.
243 GaiaAuthConsumer::ClientLoginResult credentials_;
245 // A bunch of fetchers suitable for ClientLogin token issuing. We don't care
246 // about the ordering, nor do we care which is for which service. The
247 // number of entries in this array must match the number of entries in the
248 // kServices array declared in the cc file. If not, a compile time error
250 scoped_ptr<GaiaAuthFetcher> fetchers_[1];
252 // Map from service to token.
253 std::map<std::string, std::string> token_map_;
255 // The list of SigninDiagnosticObservers
256 ObserverList<signin_internals_util::SigninDiagnosticsObserver>
257 signin_diagnostics_observers_;
259 friend class TokenServiceTest;
260 FRIEND_TEST_ALL_PREFIXES(TokenServiceTest, LoadTokensIntoMemoryBasic);
261 FRIEND_TEST_ALL_PREFIXES(TokenServiceTest, LoadTokensIntoMemoryAdvanced);
262 FRIEND_TEST_ALL_PREFIXES(TokenServiceTest, FullIntegrationNewServicesAdded);
264 DISALLOW_COPY_AND_ASSIGN(TokenService);
267 #endif // CHROME_BROWSER_SIGNIN_TOKEN_SERVICE_H_