1// Copyright 2014 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#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
5#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
6
7#include <deque>
8#include <functional>
9#include <set>
10#include <string>
11#include <utility>
12#include <vector>
13
14#include "base/basictypes.h"
15#include "base/callback_forward.h"
16#include "base/compiler_specific.h"
17#include "base/memory/scoped_ptr.h"
18#include "base/memory/scoped_vector.h"
19#include "components/keyed_service/core/keyed_service.h"
20#include "components/signin/core/browser/signin_client.h"
21#include "components/signin/core/browser/signin_manager.h"
22#include "google_apis/gaia/gaia_auth_consumer.h"
23#include "google_apis/gaia/google_service_auth_error.h"
24#include "google_apis/gaia/merge_session_helper.h"
25#include "google_apis/gaia/oauth2_token_service.h"
26
27class GaiaAuthFetcher;
28class ProfileOAuth2TokenService;
29class SigninClient;
30
31namespace net {
32class CanonicalCookie;
33}
34
35class AccountReconcilor : public KeyedService,
36                          public GaiaAuthConsumer,
37                          public MergeSessionHelper::Observer,
38                          public OAuth2TokenService::Observer,
39                          public SigninManagerBase::Observer {
40 public:
41  AccountReconcilor(ProfileOAuth2TokenService* token_service,
42                    SigninManagerBase* signin_manager,
43                    SigninClient* client);
44  virtual ~AccountReconcilor();
45
46  void Initialize(bool start_reconcile_if_tokens_available);
47
48  // Signal that the status of the new_profile_management flag has changed.
49  // Pass the new status as an explicit parameter since disabling the flag
50  // doesn't remove it from the CommandLine::ForCurrentProcess().
51  void OnNewProfileManagementFlagChanged(bool new_flag_status);
52
53  // KeyedService implementation.
54  virtual void Shutdown() OVERRIDE;
55
56  // Add or remove observers for the merge session notification.
57  void AddMergeSessionObserver(MergeSessionHelper::Observer* observer);
58  void RemoveMergeSessionObserver(MergeSessionHelper::Observer* observer);
59
60  ProfileOAuth2TokenService* token_service() { return token_service_; }
61  SigninClient* client() { return client_; }
62
63 protected:
64  // Used during GetAccountsFromCookie.
65  // Stores a callback for the next action to perform.
66  typedef base::Callback<
67      void(const GoogleServiceAuthError& error,
68           const std::vector<std::pair<std::string, bool> >&)>
69      GetAccountsFromCookieCallback;
70
71  virtual void GetAccountsFromCookie(GetAccountsFromCookieCallback callback);
72
73 private:
74  bool IsRegisteredWithTokenService() const {
75    return registered_with_token_service_;
76  }
77
78  bool AreGaiaAccountsSet() const { return are_gaia_accounts_set_; }
79
80  const std::vector<std::pair<std::string, bool> >& GetGaiaAccountsForTesting()
81      const {
82    return gaia_accounts_;
83  }
84
85  // Virtual so that it can be overridden in tests.
86  virtual void StartFetchingExternalCcResult();
87
88  friend class AccountReconcilorTest;
89  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, SigninManagerRegistration);
90  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, Reauth);
91  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, ProfileAlreadyConnected);
92  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, GetAccountsFromCookieSuccess);
93  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, GetAccountsFromCookieFailure);
94  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoop);
95  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoopWithDots);
96  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoopMultiple);
97  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileAddToCookie);
98  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
99                           StartReconcileRemoveFromCookie);
100  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
101                           StartReconcileAddToCookieTwice);
102  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileBadPrimary);
103  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileOnlyOnce);
104  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
105                           StartReconcileWithSessionInfoExpiredDefault);
106  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
107                           MergeSessionCompletedWithBogusAccount);
108
109  // Register and unregister with dependent services.
110  void RegisterForCookieChanges();
111  void UnregisterForCookieChanges();
112  void RegisterWithSigninManager();
113  void UnregisterWithSigninManager();
114  void RegisterWithTokenService();
115  void UnregisterWithTokenService();
116
117  bool IsProfileConnected();
118
119  // All actions with side effects.  Virtual so that they can be overridden
120  // in tests.
121  virtual void PerformMergeAction(const std::string& account_id);
122  virtual void PerformLogoutAllAccountsAction();
123
124  // Used during periodic reconciliation.
125  void StartReconcile();
126  void FinishReconcile();
127  void AbortReconcile();
128  void CalculateIfReconcileIsDone();
129  void ScheduleStartReconcileIfChromeAccountsChanged();
130
131  void ContinueReconcileActionAfterGetGaiaAccounts(
132      const GoogleServiceAuthError& error,
133      const std::vector<std::pair<std::string, bool> >& accounts);
134  void ValidateAccountsFromTokenService();
135  // Note internally that this |account_id| is added to the cookie jar.
136  bool MarkAccountAsAddedToCookie(const std::string& account_id);
137
138  void OnCookieChanged(const net::CanonicalCookie* cookie);
139
140  // Overriden from GaiaAuthConsumer.
141  virtual void OnListAccountsSuccess(const std::string& data) OVERRIDE;
142  virtual void OnListAccountsFailure(const GoogleServiceAuthError& error)
143      OVERRIDE;
144
145  // Overriden from MergeSessionHelper::Observer.
146  virtual void MergeSessionCompleted(const std::string& account_id,
147                                     const GoogleServiceAuthError& error)
148      OVERRIDE;
149
150  // Overriden from OAuth2TokenService::Observer.
151  virtual void OnEndBatchChanges() OVERRIDE;
152
153  // Overriden from SigninManagerBase::Observer.
154  virtual void GoogleSigninSucceeded(const std::string& account_id,
155                                     const std::string& username,
156                                     const std::string& password) OVERRIDE;
157  virtual void GoogleSignedOut(const std::string& account_id,
158                               const std::string& username) OVERRIDE;
159
160  void MayBeDoNextListAccounts();
161
162  // The ProfileOAuth2TokenService associated with this reconcilor.
163  ProfileOAuth2TokenService* token_service_;
164
165  // The SigninManager associated with this reconcilor.
166  SigninManagerBase* signin_manager_;
167
168  // The SigninClient associated with this reconcilor.
169  SigninClient* client_;
170
171  MergeSessionHelper merge_session_helper_;
172  scoped_ptr<GaiaAuthFetcher> gaia_fetcher_;
173  bool registered_with_token_service_;
174
175  // True while the reconcilor is busy checking or managing the accounts in
176  // this profile.
177  bool is_reconcile_started_;
178
179  // True iff this is the first time the reconcilor is executing.
180  bool first_execution_;
181
182  // Used during reconcile action.
183  // These members are used to validate the gaia cookie.  |gaia_accounts_|
184  // holds the state of google accounts in the gaia cookie.  Each element is
185  // a pair that holds the email address of the account and a boolean that
186  // indicates whether the account is valid or not.  The accounts in the vector
187  // are ordered the in same way as the gaia cookie.
188  bool are_gaia_accounts_set_;
189  std::vector<std::pair<std::string, bool> > gaia_accounts_;
190
191  // Used during reconcile action.
192  // These members are used to validate the tokens in OAuth2TokenService.
193  std::string primary_account_;
194  std::vector<std::string> chrome_accounts_;
195  std::vector<std::string> add_to_cookie_;
196
197  std::deque<GetAccountsFromCookieCallback> get_gaia_accounts_callbacks_;
198
199  scoped_ptr<SigninClient::CookieChangedCallbackList::Subscription>
200      cookie_changed_subscription_;
201
202  DISALLOW_COPY_AND_ASSIGN(AccountReconcilor);
203};
204
205#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
206