Home | History | Annotate | Download | only in browser
      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 
     61   ProfileOAuth2TokenService* token_service() { return token_service_; }
     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 
     81   bool IsRegisteredWithTokenService() const {
     82     return registered_with_token_service_;
     83   }
     84 
     85   bool AreGaiaAccountsSet() const { return are_gaia_accounts_set_; }
     86 
     87   bool AreAllRefreshTokensChecked() const;
     88 
     89   const std::vector<std::pair<std::string, bool> >& GetGaiaAccountsForTesting()
     90       const {
     91     return gaia_accounts_;
     92   }
     93 
     94   const EmailSet& GetValidChromeAccountsForTesting() const {
     95     return valid_chrome_accounts_;
     96   }
     97 
     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