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