• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_manager.h"
21 #include "google_apis/gaia/gaia_auth_consumer.h"
22 #include "google_apis/gaia/google_service_auth_error.h"
23 #include "google_apis/gaia/merge_session_helper.h"
24 #include "google_apis/gaia/oauth2_token_service.h"
25 
26 class GaiaAuthFetcher;
27 class ProfileOAuth2TokenService;
28 class SigninClient;
29 class SigninOAuthHelper;
30 
31 namespace net {
32 class CanonicalCookie;
33 }
34 
35 class AccountReconcilor : public KeyedService,
36                           public GaiaAuthConsumer,
37                           public MergeSessionHelper::Observer,
38                           public OAuth2TokenService::Consumer,
39                           public OAuth2TokenService::Observer,
40                           public SigninManagerBase::Observer {
41  public:
42   AccountReconcilor(ProfileOAuth2TokenService* token_service,
43                     SigninManagerBase* signin_manager,
44                     SigninClient* client);
45   virtual ~AccountReconcilor();
46 
47   void Initialize(bool start_reconcile_if_tokens_available);
48 
49   // Signal that the status of the new_profile_management flag has changed.
50   // Pass the new status as an explicit parameter since disabling the flag
51   // doesn't remove it from the CommandLine::ForCurrentProcess().
52   void OnNewProfileManagementFlagChanged(bool new_flag_status);
53 
54   // KeyedService implementation.
55   virtual void Shutdown() OVERRIDE;
56 
57   // Add or remove observers for the merge session notification.
58   void AddMergeSessionObserver(MergeSessionHelper::Observer* observer);
59   void RemoveMergeSessionObserver(MergeSessionHelper::Observer* observer);
60 
token_service()61   ProfileOAuth2TokenService* token_service() { return token_service_; }
client()62   SigninClient* client() { return client_; }
63 
64  private:
65   // An std::set<> for use with email addresses that uses
66   // gaia::CanonicalizeEmail() during comparisons.
67   // TODO(rogerta): this is a workaround for the fact that SigninManager and
68   // SigninOAuthHelper use the gaia "email" property when adding accounts to
69   // the token service, whereas gaia::ParseListAccountsData() returns email
70   // addresses that have been passed through gaia::CanonicalizeEmail().  These
71   // two types of email addresses are not directly comparable.
72   class EmailLessFunc : public std::less<std::string> {
73    public:
74     bool operator()(const std::string& s1, const std::string& s2) const;
75   };
76   typedef std::set<std::string, EmailLessFunc> EmailSet;
77 
78   class RefreshTokenFetcher;
79   class UserIdFetcher;
80 
IsRegisteredWithTokenService()81   bool IsRegisteredWithTokenService() const {
82     return registered_with_token_service_;
83   }
84 
AreGaiaAccountsSet()85   bool AreGaiaAccountsSet() const { return are_gaia_accounts_set_; }
86 
87   bool AreAllRefreshTokensChecked() const;
88 
GetGaiaAccountsForTesting()89   const std::vector<std::pair<std::string, bool> >& GetGaiaAccountsForTesting()
90       const {
91     return gaia_accounts_;
92   }
93 
GetValidChromeAccountsForTesting()94   const EmailSet& GetValidChromeAccountsForTesting() const {
95     return valid_chrome_accounts_;
96   }
97 
GetInvalidChromeAccountsForTesting()98   const EmailSet& GetInvalidChromeAccountsForTesting() const {
99     return invalid_chrome_accounts_;
100   }
101 
102   // Used during GetAccountsFromCookie.
103   // Stores a callback for the next action to perform.
104   typedef base::Callback<
105       void(const GoogleServiceAuthError& error,
106            const std::vector<std::pair<std::string, bool> >&)>
107       GetAccountsFromCookieCallback;
108 
109   friend class AccountReconcilorTest;
110   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, SigninManagerRegistration);
111   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, Reauth);
112   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, ProfileAlreadyConnected);
113   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, GetAccountsFromCookieSuccess);
114   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, GetAccountsFromCookieFailure);
115   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, ValidateAccountsFromTokens);
116   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
117                            ValidateAccountsFromTokensFailedUserInfo);
118   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
119                            ValidateAccountsFromTokensFailedTokenRequest);
120   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoop);
121   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoopWithDots);
122   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoopMultiple);
123   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileAddToCookie);
124   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
125                            StartReconcileAddToCookieTwice);
126   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileAddToChrome);
127   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileBadPrimary);
128   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileOnlyOnce);
129   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
130                            StartReconcileWithSessionInfoExpiredDefault);
131 
132   // Register and unregister with dependent services.
133   void RegisterForCookieChanges();
134   void UnregisterForCookieChanges();
135   void RegisterWithSigninManager();
136   void UnregisterWithSigninManager();
137   void RegisterWithTokenService();
138   void UnregisterWithTokenService();
139 
140   bool IsProfileConnected();
141 
142   void DeleteFetchers();
143 
144   // All actions with side effects.  Virtual so that they can be overridden
145   // in tests.
146   virtual void PerformMergeAction(const std::string& account_id);
147   virtual void PerformAddToChromeAction(const std::string& account_id,
148                                         int session_index);
149   virtual void PerformLogoutAllAccountsAction();
150   virtual void PerformAddAccountToTokenService(
151       const std::string& account_id,
152       const std::string& refresh_token);
153 
154   // Used to remove an account from chrome and the cookie jar.
155   virtual void PerformStartRemoveAction(const std::string& account_id);
156   virtual void PerformFinishRemoveAction(
157       const std::string& account_id,
158       const GoogleServiceAuthError& error,
159       const std::vector<std::pair<std::string, bool> >& accounts);
160 
161   // Used during periodic reconciliation.
162   void StartReconcile();
163   void FinishReconcile();
164   void AbortReconcile();
165   void CalculateIfReconcileIsDone();
166   void ScheduleStartReconcileIfChromeAccountsChanged();
167   void HandleSuccessfulAccountIdCheck(const std::string& account_id);
168   void HandleFailedAccountIdCheck(const std::string& account_id);
169   void HandleRefreshTokenFetched(const std::string& account_id,
170                                  const std::string& refresh_token);
171 
172   void GetAccountsFromCookie(GetAccountsFromCookieCallback callback);
173   void ContinueReconcileActionAfterGetGaiaAccounts(
174       const GoogleServiceAuthError& error,
175       const std::vector<std::pair<std::string, bool> >& accounts);
176   void ValidateAccountsFromTokenService();
177   // Note internally that this |account_id| is added to the cookie jar.
178   void MarkAccountAsAddedToCookie(const std::string& account_id);
179   // Note internally that this |account_id| is added to the token service.
180   void MarkAccountAsAddedToChrome(const std::string& account_id);
181 
182   void OnCookieChanged(const net::CanonicalCookie* cookie);
183 
184   // Overriden from GaiaAuthConsumer.
185   virtual void OnListAccountsSuccess(const std::string& data) OVERRIDE;
186   virtual void OnListAccountsFailure(const GoogleServiceAuthError& error)
187       OVERRIDE;
188 
189   // Overriden from MergeSessionHelper::Observer.
190   virtual void MergeSessionCompleted(const std::string& account_id,
191                                      const GoogleServiceAuthError& error)
192       OVERRIDE;
193 
194   // Overriden from OAuth2TokenService::Consumer.
195   virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
196                                  const std::string& access_token,
197                                  const base::Time& expiration_time) OVERRIDE;
198   virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
199                                  const GoogleServiceAuthError& error) OVERRIDE;
200 
201   // Overriden from OAuth2TokenService::Observer.
202   virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE;
203   virtual void OnRefreshTokenRevoked(const std::string& account_id) OVERRIDE;
204   virtual void OnRefreshTokensLoaded() OVERRIDE;
205 
206   // Overriden from SigninManagerBase::Observer.
207   virtual void GoogleSigninSucceeded(const std::string& username,
208                                      const std::string& password) OVERRIDE;
209   virtual void GoogleSignedOut(const std::string& username) OVERRIDE;
210 
211   void MayBeDoNextListAccounts();
212 
213   // The ProfileOAuth2TokenService associated with this reconcilor.
214   ProfileOAuth2TokenService* token_service_;
215 
216   // The SigninManager associated with this reconcilor.
217   SigninManagerBase* signin_manager_;
218 
219   // The SigninClient associated with this reconcilor.
220   SigninClient* client_;
221 
222   MergeSessionHelper merge_session_helper_;
223   scoped_ptr<GaiaAuthFetcher> gaia_fetcher_;
224   bool registered_with_token_service_;
225 
226   // True while the reconcilor is busy checking or managing the accounts in
227   // this profile.
228   bool is_reconcile_started_;
229 
230   // True iff this is the first time the reconcilor is executing.
231   bool first_execution_;
232 
233   // Used during reconcile action.
234   // These members are used used to validate the gaia cookie.  |gaia_accounts_|
235   // holds the state of google accounts in the gaia cookie.  Each element is
236   // a pair that holds the email address of the account and a boolean that
237   // indicates whether the account is valid or not.  The accounts in the vector
238   // are ordered the in same way as the gaia cookie.
239   bool are_gaia_accounts_set_;
240   std::vector<std::pair<std::string, bool> > gaia_accounts_;
241 
242   // Used during reconcile action.
243   // These members are used to validate the tokens in OAuth2TokenService.
244   std::string primary_account_;
245   std::vector<std::string> chrome_accounts_;
246   scoped_ptr<OAuth2TokenService::Request>* requests_;
247   ScopedVector<UserIdFetcher> user_id_fetchers_;
248   ScopedVector<SigninOAuthHelper> refresh_token_fetchers_;
249   EmailSet valid_chrome_accounts_;
250   EmailSet invalid_chrome_accounts_;
251   std::vector<std::string> add_to_cookie_;
252   std::vector<std::pair<std::string, int> > add_to_chrome_;
253 
254   std::deque<GetAccountsFromCookieCallback> get_gaia_accounts_callbacks_;
255 
256   DISALLOW_COPY_AND_ASSIGN(AccountReconcilor);
257 };
258 
259 #endif  // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
260