1// Copyright 2013 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#ifndef CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_H_
6#define CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_H_
7
8#include <string>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "base/callback.h"
13#include "base/gtest_prod_util.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/memory/weak_ptr.h"
16#include "base/stl_util.h"
17#include "base/time/time.h"
18#include "google_apis/gaia/gaia_oauth_client.h"
19#include "google_apis/gaia/oauth2_token_service.h"
20#include "net/url_request/url_request_context_getter.h"
21
22namespace gaia {
23class GaiaOAuthClient;
24}
25
26namespace net {
27class URLRequestContextGetter;
28}
29
30class PrefRegistrySimple;
31class PrefService;
32
33namespace chromeos {
34
35// DeviceOAuth2TokenService retrieves OAuth2 access tokens for a given
36// set of scopes using the device-level OAuth2 any-api refresh token
37// obtained during enterprise device enrollment.
38//
39// See |OAuth2TokenService| for usage details.
40//
41// When using DeviceOAuth2TokenService, a value of |GetRobotAccountId| should
42// be used in places where API expects |account_id|.
43//
44// Note that requests must be made from the UI thread.
45class DeviceOAuth2TokenService : public OAuth2TokenService,
46                                 public gaia::GaiaOAuthClient::Delegate {
47 public:
48  typedef base::Callback<void(bool)> StatusCallback;
49
50  // Persist the given refresh token on the device. Overwrites any previous
51  // value. Should only be called during initial device setup. Signals
52  // completion via the given callback, passing true if the operation succeeded.
53  void SetAndSaveRefreshToken(const std::string& refresh_token,
54                              const StatusCallback& callback);
55
56  static void RegisterPrefs(PrefRegistrySimple* registry);
57
58  // Implementation of OAuth2TokenService.
59  virtual bool RefreshTokenIsAvailable(const std::string& account_id)
60      const OVERRIDE;
61
62  // Pull the robot account ID from device policy.
63  virtual std::string GetRobotAccountId() const;
64
65  // gaia::GaiaOAuthClient::Delegate implementation.
66  virtual void OnRefreshTokenResponse(const std::string& access_token,
67                                      int expires_in_seconds) OVERRIDE;
68  virtual void OnGetTokenInfoResponse(
69      scoped_ptr<base::DictionaryValue> token_info) OVERRIDE;
70  virtual void OnOAuthError() OVERRIDE;
71  virtual void OnNetworkError(int response_code) OVERRIDE;
72
73 protected:
74  // Implementation of OAuth2TokenService.
75  virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE;
76  virtual void FetchOAuth2Token(RequestImpl* request,
77                                const std::string& account_id,
78                                net::URLRequestContextGetter* getter,
79                                const std::string& client_id,
80                                const std::string& client_secret,
81                                const ScopeSet& scopes) OVERRIDE;
82  virtual OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
83      const std::string& account_id,
84      net::URLRequestContextGetter* getter,
85      OAuth2AccessTokenConsumer* consumer) OVERRIDE;
86
87 private:
88  struct PendingRequest;
89  friend class DeviceOAuth2TokenServiceFactory;
90  friend class DeviceOAuth2TokenServiceTest;
91
92  // Describes the operational state of this object.
93  enum State {
94    // Pending system salt / refresh token load.
95    STATE_LOADING,
96    // No token available.
97    STATE_NO_TOKEN,
98    // System salt loaded, validation not started yet.
99    STATE_VALIDATION_PENDING,
100    // Refresh token validation underway.
101    STATE_VALIDATION_STARTED,
102    // Token validation failed.
103    STATE_TOKEN_INVALID,
104    // Refresh token is valid.
105    STATE_TOKEN_VALID,
106  };
107
108  // Use DeviceOAuth2TokenServiceFactory to get an instance of this class.
109  // Ownership of |token_encryptor| will be taken.
110  explicit DeviceOAuth2TokenService(net::URLRequestContextGetter* getter,
111                                    PrefService* local_state);
112  virtual ~DeviceOAuth2TokenService();
113
114  // Returns the refresh token for account_id.
115  std::string GetRefreshToken(const std::string& account_id) const;
116
117  // Handles completion of the system salt input.
118  void DidGetSystemSalt(const std::string& system_salt);
119
120  // Checks whether |gaia_robot_id| matches the expected account ID indicated in
121  // device settings.
122  void CheckRobotAccountId(const std::string& gaia_robot_id);
123
124  // Encrypts and saves the refresh token. Should only be called when the system
125  // salt is available.
126  void EncryptAndSaveToken();
127
128  // Starts the token validation flow, i.e. token info fetch.
129  void StartValidation();
130
131  // Flushes |pending_requests_|, indicating the specified result.
132  void FlushPendingRequests(bool token_is_valid,
133                            GoogleServiceAuthError::State error);
134
135  // Flushes |token_save_callbacks_|, indicating the specified result.
136  void FlushTokenSaveCallbacks(bool result);
137
138  // Signals failure on the specified request, passing |error| as the reason.
139  void FailRequest(RequestImpl* request, GoogleServiceAuthError::State error);
140
141  // Dependencies.
142  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
143  PrefService* local_state_;
144
145  // Current operational state.
146  State state_;
147
148  // Token save callbacks waiting to be completed.
149  std::vector<StatusCallback> token_save_callbacks_;
150
151  // Currently open requests that are waiting while loading the system salt or
152  // validating the token.
153  std::vector<PendingRequest*> pending_requests_;
154
155  // The system salt for encrypting and decrypting the refresh token.
156  std::string system_salt_;
157
158  int max_refresh_token_validation_retries_;
159
160  // Cache the decrypted refresh token, so we only decrypt once.
161  std::string refresh_token_;
162
163  scoped_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_;
164
165  base::WeakPtrFactory<DeviceOAuth2TokenService> weak_ptr_factory_;
166
167  DISALLOW_COPY_AND_ASSIGN(DeviceOAuth2TokenService);
168};
169
170}  // namespace chromeos
171
172#endif  // CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_H_
173