token_service.h revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 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 to call ClientLogin to derive a new SID and
8// LSID. Whenever such credentials are available, the TokenService should be
9// updated with new credentials. The controller should then start fetching
10// tokens, which will be written to the database after retrieval, as well as
11// provided to listeners.
12//
13// A token service controller like the ChromiumOS login is expected to:
14//
15// Initialize()  // Soon as you can
16// LoadTokensFromDB()  // When it's OK to talk to the database
17// UpdateCredentials()  // When user logs in
18// StartFetchingTokens()  // When it's safe to start fetching
19//
20// Typically a user of the TokenService is expected just to call:
21//
22// if (token_service.HasTokenForService(servicename)) {
23//   SetMyToken(token_service.GetTokenForService(servicename));
24// }
25// RegisterSomeObserver(token_service);
26//
27// Whenever a token update occurs:
28// OnTokenAvailable(...) {
29//   if (IsServiceICareAbout(notification.service())) {
30//     SetMyToken(notification.token())
31//   }
32// }
33
34#ifndef CHROME_BROWSER_NET_GAIA_TOKEN_SERVICE_H_
35#define CHROME_BROWSER_NET_GAIA_TOKEN_SERVICE_H_
36#pragma once
37
38#include <map>
39#include <string>
40
41#include "base/gtest_prod_util.h"
42#include "base/scoped_ptr.h"
43#include "chrome/browser/webdata/web_data_service.h"
44#include "chrome/common/net/gaia/gaia_auth_consumer.h"
45#include "chrome/common/net/gaia/gaia_authenticator2.h"
46#include "chrome/common/net/gaia/google_service_auth_error.h"
47#include "chrome/common/notification_observer.h"
48#include "chrome/common/notification_registrar.h"
49
50class URLRequestContextGetter;
51class Profile;
52
53// The TokenService is a Profile member, so all calls are expected
54// from the UI thread.
55class TokenService : public GaiaAuthConsumer,
56                     public WebDataServiceConsumer,
57                     public NotificationObserver {
58 public:
59   TokenService();
60   virtual ~TokenService();
61
62  // Notification classes
63  class TokenAvailableDetails {
64   public:
65    TokenAvailableDetails() {}
66    TokenAvailableDetails(const std::string& service,
67                          const std::string& token)
68        : service_(service), token_(token) {}
69    const std::string& service() const { return service_; }
70    const std::string& token() const { return token_; }
71   private:
72    std::string service_;
73    std::string token_;
74  };
75
76  class TokenRequestFailedDetails {
77   public:
78    TokenRequestFailedDetails()
79        : error_(GoogleServiceAuthError::NONE) {}
80    TokenRequestFailedDetails(const std::string& service,
81                              const GoogleServiceAuthError& error)
82        : service_(service), error_(error) {}
83    const std::string& service() const { return service_; }
84    const GoogleServiceAuthError& error() const { return error_; }
85   private:
86    std::string service_;
87    GoogleServiceAuthError error_;
88  };
89
90  // Initialize this token service with a request source
91  // (usually from a GaiaAuthConsumer constant), and the profile.
92  // Typically you'd then update the credentials.
93  void Initialize(const char* const source, Profile* profile);
94
95  // Update the credentials in the token service.
96  // Afterwards you can StartFetchingTokens.
97  void UpdateCredentials(
98      const GaiaAuthConsumer::ClientLoginResult& credentials);
99
100  // Terminate any running requests and reset the TokenService to a clean
101  // slate. Resets in memory structures. Does not modify the DB.
102  // When this is done, no tokens will be left in memory and no
103  // user credentials will be left. Useful if a user is logging out.
104  // Initialize doesn't need to be called again but UpdateCredentials does.
105  void ResetCredentialsInMemory();
106
107  // Async load all tokens for services we know of from the DB.
108  // You should do this at startup. Optionally you can do it again
109  // after you reset in memory credentials.
110  void LoadTokensFromDB();
111
112  // Clear all DB stored tokens for the current profile. Tokens may still be
113  // available in memory. If a DB load is pending it may still be serviced.
114  void EraseTokensFromDB();
115
116  // For legacy services with their own auth routines, they can just read
117  // the LSID out directly. Deprecated.
118  bool HasLsid() const;
119  const std::string& GetLsid() const;
120  // Did we get a proper LSID?
121  bool AreCredentialsValid() const;
122
123  // Tokens will be fetched for all services(sync, talk) in the background.
124  // Results come back via event channel. Services can also poll before events
125  // are issued.
126  void StartFetchingTokens();
127  bool HasTokenForService(const char* const service) const;
128  const std::string& GetTokenForService(const char* const service) const;
129
130  // For tests only. Doesn't save to the WebDB.
131  void IssueAuthTokenForTest(const std::string& service,
132                             const std::string& auth_token);
133
134  // GaiaAuthConsumer implementation.
135  virtual void OnIssueAuthTokenSuccess(const std::string& service,
136                                       const std::string& auth_token);
137  virtual void OnIssueAuthTokenFailure(const std::string& service,
138                                       const GoogleServiceAuthError& error);
139
140  // WebDataServiceConsumer implementation.
141  virtual void OnWebDataServiceRequestDone(WebDataService::Handle h,
142                                           const WDTypedResult* result);
143
144  // NotificationObserver implementation.
145  virtual void Observe(NotificationType type,
146                       const NotificationSource& source,
147                       const NotificationDetails& details);
148
149 private:
150
151  void FireTokenAvailableNotification(const std::string& service,
152                                      const std::string& auth_token);
153
154  void FireTokenRequestFailedNotification(const std::string& service,
155                                          const GoogleServiceAuthError& error);
156
157  void LoadTokensIntoMemory(const std::map<std::string, std::string>& in_toks,
158                            std::map<std::string, std::string>* out_toks);
159
160  void SaveAuthTokenToDB(const std::string& service,
161                         const std::string& auth_token);
162
163  // Web data service to access tokens from.
164  scoped_refptr<WebDataService> web_data_service_;
165  // Getter to use for fetchers.
166  scoped_refptr<URLRequestContextGetter> getter_;
167  // Request handle to load Gaia tokens from DB.
168  WebDataService::Handle token_loading_query_;
169
170  // Gaia request source for Gaia accounting.
171  std::string source_;
172  // Credentials from ClientLogin for Issuing auth tokens.
173  GaiaAuthConsumer::ClientLoginResult credentials_;
174
175  // Size of array of services (must be defined here).
176  static const int kNumServices = 2;
177  // List of services that we're performing operations for.
178  static const char* kServices[kNumServices];
179  // A bunch of fetchers suitable for token issuing. We don't care about
180  // the ordering, nor do we care which is for which service.
181  scoped_ptr<GaiaAuthenticator2> fetchers_[kNumServices];
182  // Map from service to token.
183  std::map<std::string, std::string> token_map_;
184
185  NotificationRegistrar registrar_;
186
187  FRIEND_TEST_ALL_PREFIXES(TokenServiceTest, LoadTokensIntoMemoryBasic);
188  FRIEND_TEST_ALL_PREFIXES(TokenServiceTest, LoadTokensIntoMemoryAdvanced);
189
190  DISALLOW_COPY_AND_ASSIGN(TokenService);
191};
192
193#endif  // CHROME_BROWSER_NET_GAIA_TOKEN_SERVICE_H_
194