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_SIGNIN_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
6#define CHROME_BROWSER_SIGNIN_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
7
8#include <string>
9#include <vector>
10
11#include "base/compiler_specific.h"
12#include "base/memory/weak_ptr.h"
13
14#if defined(OS_ANDROID)
15#include "chrome/browser/signin/android_profile_oauth2_token_service.h"
16#else
17#include "components/signin/core/browser/profile_oauth2_token_service.h"
18#endif
19
20// Helper class to simplify writing unittests that depend on an instance of
21// ProfileOAuth2TokenService.
22//
23// Tests would typically do something like the following:
24//
25// FakeProfileOAuth2TokenService service;
26// ...
27// service.IssueRefreshToken("token");  // Issue refresh token/notify observers
28// ...
29// // Confirm that there is at least one active request.
30// EXPECT_GT(0U, service.GetPendingRequests().size());
31// ...
32// // Make any pending token fetches for a given scope succeed.
33// ScopeSet scopes;
34// scopes.insert(GaiaConstants::kYourServiceScope);
35// IssueTokenForScope(scopes, "access_token", base::Time()::Max());
36// ...
37// // ...or make them fail...
38// IssueErrorForScope(scopes, GoogleServiceAuthError(INVALID_GAIA_CREDENTIALS));
39//
40class FakeProfileOAuth2TokenService
41#if defined(OS_ANDROID)
42  : public AndroidProfileOAuth2TokenService {
43#else
44  : public ProfileOAuth2TokenService {
45#endif
46 public:
47  struct PendingRequest {
48    PendingRequest();
49    ~PendingRequest();
50
51    std::string account_id;
52    std::string client_id;
53    std::string client_secret;
54    ScopeSet scopes;
55    base::WeakPtr<RequestImpl> request;
56  };
57
58  FakeProfileOAuth2TokenService();
59  virtual ~FakeProfileOAuth2TokenService();
60
61  // Overriden to make sure it works on Android.
62  virtual bool RefreshTokenIsAvailable(
63      const std::string& account_id) const OVERRIDE;
64
65  // Overriden to make sure it works on iOS.
66  virtual void LoadCredentials(const std::string& primary_account_id) OVERRIDE;
67
68  virtual std::vector<std::string> GetAccounts() OVERRIDE;
69
70  // Overriden to make sure it works on Android.  Simply calls
71  // IssueRefreshToken().
72  virtual void UpdateCredentials(const std::string& account_id,
73                                 const std::string& refresh_token) OVERRIDE;
74
75  // Sets the current refresh token. If |token| is non-empty, this will invoke
76  // OnRefreshTokenAvailable() on all Observers, otherwise this will invoke
77  // OnRefreshTokenRevoked().
78  void IssueRefreshToken(const std::string& token);
79
80  // TODO(fgorski,rogerta): Merge with UpdateCredentials when this class fully
81  // supports multiple accounts.
82  void IssueRefreshTokenForUser(const std::string& account_id,
83                                const std::string& token);
84
85  // Fire OnRefreshTokensLoaded on all observers.
86  void IssueAllRefreshTokensLoaded();
87
88  // Gets a list of active requests (can be used by tests to validate that the
89  // correct request has been issued).
90  std::vector<PendingRequest> GetPendingRequests();
91
92  // Helper routines to issue tokens for pending requests.
93  void IssueAllTokensForAccount(const std::string& account_id,
94                                const std::string& access_token,
95                                const base::Time& expiration);
96
97  void IssueErrorForAllPendingRequestsForAccount(
98      const std::string& account_id,
99      const GoogleServiceAuthError& error);
100
101  void IssueTokenForScope(const ScopeSet& scopes,
102                          const std::string& access_token,
103                          const base::Time& expiration);
104
105  void IssueErrorForScope(const ScopeSet& scopes,
106                          const GoogleServiceAuthError& error);
107
108  void IssueTokenForAllPendingRequests(const std::string& access_token,
109                                       const base::Time& expiration);
110
111  void IssueErrorForAllPendingRequests(const GoogleServiceAuthError& error);
112
113  void set_auto_post_fetch_response_on_message_loop(bool auto_post_response) {
114    auto_post_fetch_response_on_message_loop_ = auto_post_response;
115  }
116
117 protected:
118  // OAuth2TokenService overrides.
119  virtual void FetchOAuth2Token(RequestImpl* request,
120                                const std::string& account_id,
121                                net::URLRequestContextGetter* getter,
122                                const std::string& client_id,
123                                const std::string& client_secret,
124                                const ScopeSet& scopes) OVERRIDE;
125
126  virtual OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
127      const std::string& account_id,
128      net::URLRequestContextGetter* getter,
129      OAuth2AccessTokenConsumer* consumer) OVERRIDE;
130
131  virtual void InvalidateOAuth2Token(const std::string& account_id,
132                                     const std::string& client_id,
133                                     const ScopeSet& scopes,
134                                     const std::string& access_token) OVERRIDE;
135
136  virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE;
137
138 private:
139  // Helper function to complete pending requests - if |all_scopes| is true,
140  // then all pending requests are completed, otherwise, only those requests
141  // matching |scopes| are completed.  If |account_id| is empty, then pending
142  // requests for all accounts are completed, otherwise only requests for the
143  // given account.
144  void CompleteRequests(const std::string& account_id,
145                        bool all_scopes,
146                        const ScopeSet& scopes,
147                        const GoogleServiceAuthError& error,
148                        const std::string& access_token,
149                        const base::Time& expiration);
150
151  std::string GetRefreshToken(const std::string& account_id) const;
152
153  std::vector<PendingRequest> pending_requests_;
154
155  // Maps account ids to their refresh token strings.
156  std::map<std::string, std::string> refresh_tokens_;
157
158  // If true, then this fake service will post responses to
159  // |FetchOAuth2Token| on the current run loop. There is no need to call
160  // |IssueTokenForScope| in this case.
161  bool auto_post_fetch_response_on_message_loop_;
162
163  base::WeakPtrFactory<FakeProfileOAuth2TokenService> weak_ptr_factory_;
164
165  DISALLOW_COPY_AND_ASSIGN(FakeProfileOAuth2TokenService);
166};
167
168#endif  // CHROME_BROWSER_SIGNIN_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
169