Commit da4c5442 authored by David Roger's avatar David Roger Committed by Commit Bot

[signin] Split Dice and Mirror specific logic out of AccountReconcilor

This CL creates a AccountReconcilorDelegate class, with two subclasses
specialized for Mirror and Dice respectively.

Bug: 777774
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: I4bdb4ecee7d4f12e910a2704a09802c383bca9bb
Reviewed-on: https://chromium-review.googlesource.com/766368
Commit-Queue: David Roger <droger@chromium.org>
Reviewed-by: default avatarMihai Sardarescu <msarda@chromium.org>
Cr-Commit-Position: refs/heads/master@{#517347}
parent d081f57b
...@@ -4,12 +4,24 @@ ...@@ -4,12 +4,24 @@
#include "chrome/browser/signin/account_reconcilor_factory.h" #include "chrome/browser/signin/account_reconcilor_factory.h"
#include <utility>
#include "base/logging.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/chrome_signin_client_factory.h" #include "chrome/browser/signin/chrome_signin_client_factory.h"
#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h" #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/signin/signin_manager_factory.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/signin/core/browser/account_reconcilor.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
#include "components/signin/core/browser/mirror_account_reconcilor_delegate.h"
#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/signin_features.h"
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
#include "components/signin/core/browser/dice_account_reconcilor_delegate.h"
#endif
AccountReconcilorFactory::AccountReconcilorFactory() AccountReconcilorFactory::AccountReconcilorFactory()
: BrowserContextKeyedServiceFactory( : BrowserContextKeyedServiceFactory(
...@@ -43,12 +55,41 @@ KeyedService* AccountReconcilorFactory::BuildServiceInstanceFor( ...@@ -43,12 +55,41 @@ KeyedService* AccountReconcilorFactory::BuildServiceInstanceFor(
SigninManagerFactory::GetForProfile(profile), SigninManagerFactory::GetForProfile(profile),
ChromeSigninClientFactory::GetForProfile(profile), ChromeSigninClientFactory::GetForProfile(profile),
GaiaCookieManagerServiceFactory::GetForProfile(profile), GaiaCookieManagerServiceFactory::GetForProfile(profile),
profile->IsNewProfile()); CreateAccountReconcilorDelegate(profile));
reconcilor->Initialize(true /* start_reconcile_if_tokens_available */); reconcilor->Initialize(true /* start_reconcile_if_tokens_available */);
return reconcilor; return reconcilor;
} }
void AccountReconcilorFactory::RegisterProfilePrefs( void AccountReconcilorFactory::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) { user_prefs::PrefRegistrySyncable* registry) {
AccountReconcilor::RegisterProfilePrefs(registry); #if BUILDFLAG(ENABLE_DICE_SUPPORT)
signin::DiceAccountReconcilorDelegate::RegisterProfilePrefs(registry);
#endif
}
// static
std::unique_ptr<signin::AccountReconcilorDelegate>
AccountReconcilorFactory::CreateAccountReconcilorDelegate(Profile* profile) {
std::unique_ptr<signin::AccountReconcilorDelegate> delegate;
switch (signin::GetAccountConsistencyMethod()) {
case signin::AccountConsistencyMethod::kMirror:
delegate = std::make_unique<signin::MirrorAccountReconcilorDelegate>(
SigninManagerFactory::GetForProfile(profile));
break;
case signin::AccountConsistencyMethod::kDisabled:
case signin::AccountConsistencyMethod::kDiceFixAuthErrors:
delegate = std::make_unique<signin::AccountReconcilorDelegate>();
break;
case signin::AccountConsistencyMethod::kDicePrepareMigration:
case signin::AccountConsistencyMethod::kDiceMigration:
case signin::AccountConsistencyMethod::kDice:
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
delegate = std::make_unique<signin::DiceAccountReconcilorDelegate>(
profile->GetPrefs(), profile->IsNewProfile());
#else
NOTREACHED();
#endif
break;
}
return delegate;
} }
...@@ -5,10 +5,16 @@ ...@@ -5,10 +5,16 @@
#ifndef CHROME_BROWSER_SIGNIN_ACCOUNT_RECONCILOR_FACTORY_H_ #ifndef CHROME_BROWSER_SIGNIN_ACCOUNT_RECONCILOR_FACTORY_H_
#define CHROME_BROWSER_SIGNIN_ACCOUNT_RECONCILOR_FACTORY_H_ #define CHROME_BROWSER_SIGNIN_ACCOUNT_RECONCILOR_FACTORY_H_
#include <memory>
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
#include "components/signin/core/browser/account_reconcilor.h"
namespace signin {
class AccountReconcilorDelegate;
}
class AccountReconcilor;
class Profile; class Profile;
// Singleton that owns all AccountReconcilors and associates them with // Singleton that owns all AccountReconcilors and associates them with
...@@ -25,10 +31,15 @@ class AccountReconcilorFactory : public BrowserContextKeyedServiceFactory { ...@@ -25,10 +31,15 @@ class AccountReconcilorFactory : public BrowserContextKeyedServiceFactory {
private: private:
friend struct base::DefaultSingletonTraits<AccountReconcilorFactory>; friend struct base::DefaultSingletonTraits<AccountReconcilorFactory>;
friend class DummyAccountReconcilorWithDelegate; // For testing.
AccountReconcilorFactory(); AccountReconcilorFactory();
~AccountReconcilorFactory() override; ~AccountReconcilorFactory() override;
// Creates the AccountReconcilorDelegate.
static std::unique_ptr<signin::AccountReconcilorDelegate>
CreateAccountReconcilorDelegate(Profile* profile);
// BrowserContextKeyedServiceFactory: // BrowserContextKeyedServiceFactory:
KeyedService* BuildServiceInstanceFor( KeyedService* BuildServiceInstanceFor(
content::BrowserContext* profile) const override; content::BrowserContext* profile) const override;
......
...@@ -42,6 +42,8 @@ static_library("browser") { ...@@ -42,6 +42,8 @@ static_library("browser") {
"account_investigator.h", "account_investigator.h",
"account_reconcilor.cc", "account_reconcilor.cc",
"account_reconcilor.h", "account_reconcilor.h",
"account_reconcilor_delegate.cc",
"account_reconcilor_delegate.h",
"account_tracker_service.cc", "account_tracker_service.cc",
"account_tracker_service.h", "account_tracker_service.h",
"child_account_info_fetcher.cc", "child_account_info_fetcher.cc",
...@@ -52,10 +54,14 @@ static_library("browser") { ...@@ -52,10 +54,14 @@ static_library("browser") {
"child_account_info_fetcher_impl.h", "child_account_info_fetcher_impl.h",
"chrome_connected_header_helper.cc", "chrome_connected_header_helper.cc",
"chrome_connected_header_helper.h", "chrome_connected_header_helper.h",
"dice_account_reconcilor_delegate.cc",
"dice_account_reconcilor_delegate.h",
"dice_header_helper.cc", "dice_header_helper.cc",
"dice_header_helper.h", "dice_header_helper.h",
"gaia_cookie_manager_service.cc", "gaia_cookie_manager_service.cc",
"gaia_cookie_manager_service.h", "gaia_cookie_manager_service.h",
"mirror_account_reconcilor_delegate.cc",
"mirror_account_reconcilor_delegate.h",
"profile_identity_provider.cc", "profile_identity_provider.cc",
"profile_identity_provider.h", "profile_identity_provider.h",
"profile_management_switches.cc", "profile_management_switches.cc",
...@@ -139,6 +145,8 @@ static_library("browser") { ...@@ -139,6 +145,8 @@ static_library("browser") {
if (!enable_dice_support) { if (!enable_dice_support) {
sources -= [ sources -= [
"dice_account_reconcilor_delegate.cc",
"dice_account_reconcilor_delegate.h",
"dice_header_helper.cc", "dice_header_helper.cc",
"dice_header_helper.h", "dice_header_helper.h",
] ]
...@@ -194,6 +202,7 @@ source_set("unit_tests") { ...@@ -194,6 +202,7 @@ source_set("unit_tests") {
"account_info_unittest.cc", "account_info_unittest.cc",
"account_investigator_unittest.cc", "account_investigator_unittest.cc",
"account_tracker_service_unittest.cc", "account_tracker_service_unittest.cc",
"dice_account_reconcilor_delegate_unittest.cc",
"gaia_cookie_manager_service_unittest.cc", "gaia_cookie_manager_service_unittest.cc",
"profile_management_switches_unittest.cc", "profile_management_switches_unittest.cc",
"refresh_token_annotation_request_unittest.cc", "refresh_token_annotation_request_unittest.cc",
...@@ -222,6 +231,10 @@ source_set("unit_tests") { ...@@ -222,6 +231,10 @@ source_set("unit_tests") {
"signin_status_metrics_provider_unittest.cc", "signin_status_metrics_provider_unittest.cc",
] ]
} }
if (!enable_dice_support) {
sources -= [ "dice_account_reconcilor_delegate_unittest.cc" ]
}
} }
if (is_android) { if (is_android) {
......
...@@ -4,11 +4,8 @@ ...@@ -4,11 +4,8 @@
#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_ #ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_ #define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
#include <functional>
#include <memory> #include <memory>
#include <set>
#include <string> #include <string>
#include <utility>
#include <vector> #include <vector>
#include "base/callback_forward.h" #include "base/callback_forward.h"
...@@ -29,18 +26,17 @@ ...@@ -29,18 +26,17 @@
#include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_token_service.h" #include "google_apis/gaia/oauth2_token_service.h"
namespace signin {
class AccountReconcilorDelegate;
}
class ProfileOAuth2TokenService; class ProfileOAuth2TokenService;
class SigninClient; class SigninClient;
namespace user_prefs {
class PrefRegistrySyncable;
}
class AccountReconcilor : public KeyedService, class AccountReconcilor : public KeyedService,
public content_settings::Observer, public content_settings::Observer,
public GaiaCookieManagerService::Observer, public GaiaCookieManagerService::Observer,
public OAuth2TokenService::Observer, public OAuth2TokenService::Observer {
public SigninManagerBase::Observer {
public: public:
// When an instance of this class exists, the account reconcilor is suspended. // When an instance of this class exists, the account reconcilor is suspended.
// It will automatically restart when all instances of Lock have been // It will automatically restart when all instances of Lock have been
...@@ -78,21 +74,21 @@ class AccountReconcilor : public KeyedService, ...@@ -78,21 +74,21 @@ class AccountReconcilor : public KeyedService,
virtual void OnUnblockReconcile() {} virtual void OnUnblockReconcile() {}
}; };
AccountReconcilor(ProfileOAuth2TokenService* token_service, AccountReconcilor(
SigninManagerBase* signin_manager, ProfileOAuth2TokenService* token_service,
SigninClient* client, SigninManagerBase* signin_manager,
GaiaCookieManagerService* cookie_manager_service, SigninClient* client,
bool is_new_profile); GaiaCookieManagerService* cookie_manager_service,
std::unique_ptr<signin::AccountReconcilorDelegate> delegate);
~AccountReconcilor() override; ~AccountReconcilor() override;
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); // Initializes the account reconcilor. Should be called once after
// construction.
void Initialize(bool start_reconcile_if_tokens_available); void Initialize(bool start_reconcile_if_tokens_available);
// Signal that the status of the new_profile_management flag has changed. // Enables and disables the reconciliation.
// Pass the new status as an explicit parameter since disabling the flag void EnableReconcile();
// doesn't remove it from the CommandLine::ForCurrentProcess(). void DisableReconcile(bool logout_all_gaia_accounts);
void OnNewProfileManagementFlagChanged(bool new_flag_status);
// Signal that an X-Chrome-Manage-Accounts was received from GAIA. Pass the // Signal that an X-Chrome-Manage-Accounts was received from GAIA. Pass the
// ServiceType specified by GAIA in the 204 response. // ServiceType specified by GAIA in the 204 response.
...@@ -161,7 +157,6 @@ class AccountReconcilor : public KeyedService, ...@@ -161,7 +157,6 @@ class AccountReconcilor : public KeyedService,
AddAccountToCookieCompletedWithBogusAccount); AddAccountToCookieCompletedWithBogusAccount);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, NoLoopWithBadPrimary); FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, NoLoopWithBadPrimary);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, WontMergeAccountsWithError); FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, WontMergeAccountsWithError);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorMigrationTest, MigrateAtCreation);
bool IsRegisteredWithTokenService() const { bool IsRegisteredWithTokenService() const {
return registered_with_token_service_; return registered_with_token_service_;
...@@ -177,13 +172,6 @@ class AccountReconcilor : public KeyedService, ...@@ -177,13 +172,6 @@ class AccountReconcilor : public KeyedService,
void RegisterWithContentSettings(); void RegisterWithContentSettings();
void UnregisterWithContentSettings(); void UnregisterWithContentSettings();
// The reconcilor is enabled if Sync or Dice is enabled.
bool IsEnabled();
// Returns true if account consistency is enforced (Mirror or Dice).
// If this is false, reconcile is done, but its results are discarded and no
// changes to the accounts are made.
bool IsAccountConsistencyEnforced();
// All actions with side effects, only doing meaningful work if account // All actions with side effects, only doing meaningful work if account
// consistency is enabled. Virtual so that they can be overridden in tests. // consistency is enabled. Virtual so that they can be overridden in tests.
virtual void PerformMergeAction(const std::string& account_id); virtual void PerformMergeAction(const std::string& account_id);
...@@ -199,20 +187,18 @@ class AccountReconcilor : public KeyedService, ...@@ -199,20 +187,18 @@ class AccountReconcilor : public KeyedService,
// Revokes tokens for all accounts in chrome_accounts_ but primary_account_. // Revokes tokens for all accounts in chrome_accounts_ but primary_account_.
void RevokeAllSecondaryTokens(); void RevokeAllSecondaryTokens();
void ValidateAccountsFromTokenService(); // Returns the list of valid accounts from the TokenService.
// The primary account is returned in |out_primary_account| if any.
std::vector<std::string> LoadValidAccountsFromTokenService(
std::string* out_primary_account,
bool* out_is_primary_account_valid) const;
// Note internally that this |account_id| is added to the cookie jar. // Note internally that this |account_id| is added to the cookie jar.
bool MarkAccountAsAddedToCookie(const std::string& account_id); bool MarkAccountAsAddedToCookie(const std::string& account_id);
// The reconcilor only starts when the token service is ready. // The reconcilor only starts when the token service is ready.
bool IsTokenServiceReady(); bool IsTokenServiceReady();
// Returns the first account to add in the Gaia cookie.
// If this returns an empty string, the user must be logged out of all
// accounts.
// |gaia_accounts| are the current accounts in the Gaia cookie.
std::string GetFirstGaiaAccountForReconcile(
const std::vector<gaia::ListedAccount>& gaia_accounts) const;
// Overriden from content_settings::Observer. // Overriden from content_settings::Observer.
void OnContentSettingChanged( void OnContentSettingChanged(
const ContentSettingsPattern& primary_pattern, const ContentSettingsPattern& primary_pattern,
...@@ -233,12 +219,6 @@ class AccountReconcilor : public KeyedService, ...@@ -233,12 +219,6 @@ class AccountReconcilor : public KeyedService,
void OnEndBatchChanges() override; void OnEndBatchChanges() override;
void OnRefreshTokensLoaded() override; void OnRefreshTokensLoaded() override;
// Overriden from SigninManagerBase::Observer.
void GoogleSigninSucceeded(const std::string& account_id,
const std::string& username) override;
void GoogleSignedOut(const std::string& account_id,
const std::string& username) override;
// Lock related methods. // Lock related methods.
void IncrementLockCount(); void IncrementLockCount();
void DecrementLockCount(); void DecrementLockCount();
...@@ -246,11 +226,7 @@ class AccountReconcilor : public KeyedService, ...@@ -246,11 +226,7 @@ class AccountReconcilor : public KeyedService,
void UnblockReconcile(); void UnblockReconcile();
bool IsReconcileBlocked() const; bool IsReconcileBlocked() const;
// Dice migration methods: std::unique_ptr<signin::AccountReconcilorDelegate> delegate_;
// Returns true if migration can happen on the next startup.
bool IsReadyForDiceMigration(bool is_new_profile);
// Schedules migration to happen at next startup.
static void SetDiceMigrationOnStartup(PrefService* prefs, bool migrate);
// The ProfileOAuth2TokenService associated with this reconcilor. // The ProfileOAuth2TokenService associated with this reconcilor.
ProfileOAuth2TokenService* token_service_; ProfileOAuth2TokenService* token_service_;
...@@ -289,8 +265,6 @@ class AccountReconcilor : public KeyedService, ...@@ -289,8 +265,6 @@ class AccountReconcilor : public KeyedService,
std::vector<std::string> chrome_accounts_; std::vector<std::string> chrome_accounts_;
std::vector<std::string> add_to_cookie_; std::vector<std::string> add_to_cookie_;
bool chrome_accounts_changed_; bool chrome_accounts_changed_;
// Last known "first account". Used when cookies are lost as a best guess.
std::string last_known_first_account_;
// Used for the Lock. // Used for the Lock.
// StartReconcile() is blocked while this is > 0. // StartReconcile() is blocked while this is > 0.
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/signin/core/browser/account_reconcilor_delegate.h"
namespace signin {
bool AccountReconcilorDelegate::IsReconcileEnabled() const {
return false;
}
bool AccountReconcilorDelegate::IsAccountConsistencyEnforced() const {
return false;
}
bool AccountReconcilorDelegate::ShouldAbortReconcileIfPrimaryHasError() const {
return false;
}
std::string AccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
const std::vector<std::string>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const std::string& primary_account,
bool first_execution) const {
return std::string();
}
} // namespace signin
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_DELEGATE_H_
#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_DELEGATE_H_
#include <string>
#include <vector>
#include "google_apis/gaia/gaia_auth_util.h"
class AccountReconcilor;
namespace signin {
// Base class for AccountReconcilorDelegate.
class AccountReconcilorDelegate {
public:
virtual ~AccountReconcilorDelegate() {}
// Returns true if the reconcilor should reconcile the profile. Defaults to
// false.
virtual bool IsReconcileEnabled() const;
// Returns true if account consistency is enforced (Mirror or Dice).
// If this is false, reconcile is done, but its results are discarded and no
// changes to the accounts are made. Defaults to false.
virtual bool IsAccountConsistencyEnforced() const;
// Returns true if Reconcile should be aborted when the primary account is in
// error state. Defaults to false.
virtual bool ShouldAbortReconcileIfPrimaryHasError() const;
// Returns the first account to add in the Gaia cookie.
// If this returns an empty string, the user must be logged out of all
// accounts.
virtual std::string GetFirstGaiaAccountForReconcile(
const std::vector<std::string>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const std::string& primary_account,
bool first_execution) const;
// Called when reconcile is finished.
virtual void OnReconcileFinished(const std::string& first_account,
bool reconcile_is_noop) {}
void set_reconcilor(AccountReconcilor* reconcilor) {
reconcilor_ = reconcilor;
}
AccountReconcilor* reconcilor() { return reconcilor_; }
private:
AccountReconcilor* reconcilor_;
};
} // namespace signin
#endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_DELEGATE_H_
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/signin/core/browser/dice_account_reconcilor_delegate.h"
#include <vector>
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/profile_management_switches.h"
namespace signin {
namespace {
// Preference indicating that the Dice migration should happen at the next
// Chrome startup.
const char kDiceMigrationOnStartupPref[] =
"signin.AccountReconcilor.kDiceMigrationOnStartup";
const char kDiceMigrationStatusHistogram[] = "Signin.DiceMigrationStatus";
// Used for UMA histogram kDiceMigrationStatusHistogram.
// Do not remove or re-order values.
enum class DiceMigrationStatus {
kEnabled,
kDisabledReadyForMigration,
kDisabledNotReadyForMigration,
// This is the last value. New values should be inserted above.
kDiceMigrationStatusCount
};
} // namespace
DiceAccountReconcilorDelegate::DiceAccountReconcilorDelegate(
PrefService* user_prefs,
bool is_new_profile)
: user_prefs_(user_prefs) {
DCHECK(user_prefs_);
bool is_ready_for_dice = IsReadyForDiceMigration(is_new_profile);
if (is_ready_for_dice && IsDiceMigrationEnabled()) {
if (!IsDiceEnabledForProfile(user_prefs_))
VLOG(1) << "Profile is migrating to Dice";
MigrateProfileToDice(user_prefs_);
DCHECK(IsDiceEnabledForProfile(user_prefs_));
}
UMA_HISTOGRAM_ENUMERATION(
kDiceMigrationStatusHistogram,
IsDiceEnabledForProfile(user_prefs_)
? DiceMigrationStatus::kEnabled
: (is_ready_for_dice
? DiceMigrationStatus::kDisabledReadyForMigration
: DiceMigrationStatus::kDisabledNotReadyForMigration),
DiceMigrationStatus::kDiceMigrationStatusCount);
}
// static
void DiceAccountReconcilorDelegate::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterBooleanPref(kDiceMigrationOnStartupPref, false);
}
// static
void DiceAccountReconcilorDelegate::SetDiceMigrationOnStartup(
PrefService* prefs,
bool migrate) {
VLOG(1) << "Dice migration on next startup: " << migrate;
prefs->SetBoolean(kDiceMigrationOnStartupPref, migrate);
}
bool DiceAccountReconcilorDelegate::IsReadyForDiceMigration(
bool is_new_profile) {
return is_new_profile || user_prefs_->GetBoolean(kDiceMigrationOnStartupPref);
}
bool DiceAccountReconcilorDelegate::IsReconcileEnabled() const {
return IsDicePrepareMigrationEnabled();
}
bool DiceAccountReconcilorDelegate::IsAccountConsistencyEnforced() const {
return IsDiceEnabledForProfile(user_prefs_);
}
// - On first execution, the candidates are examined in this order:
// 1. The primary account
// 2. The current first Gaia account
// 3. The last known first Gaia account
// 4. The first account in the token service
// - On subsequent executions, the order is:
// 1. The current first Gaia account
// 2. The primary account
// 3. The last known first Gaia account
// 4. The first account in the token service
std::string DiceAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
const std::vector<std::string>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const std::string& primary_account,
bool first_execution) const {
if (chrome_accounts.empty())
return std::string(); // No Chrome account, log out.
bool valid_primary_account =
!primary_account.empty() &&
base::ContainsValue(chrome_accounts, primary_account);
if (gaia_accounts.empty()) {
if (valid_primary_account)
return primary_account;
// Try the last known account. This happens when the cookies are cleared
// while Sync is disabled.
if (base::ContainsValue(chrome_accounts, last_known_first_account_))
return last_known_first_account_;
// As a last resort, use the first Chrome account.
return chrome_accounts[0];
}
const std::string& first_gaia_account = gaia_accounts[0].id;
bool first_gaia_account_is_valid =
gaia_accounts[0].valid &&
base::ContainsValue(chrome_accounts, first_gaia_account);
if (!first_gaia_account_is_valid && (primary_account == first_gaia_account)) {
// The primary account is also the first Gaia account, and is invalid.
// Logout everything.
return std::string();
}
if (first_execution) {
// On first execution, try the primary account, and then the first Gaia
// account.
if (valid_primary_account)
return primary_account;
if (first_gaia_account_is_valid)
return first_gaia_account;
// As a last resort, use the first Chrome account.
return chrome_accounts[0];
}
// While Chrome is running, try the first Gaia account, and then the
// primary account.
if (first_gaia_account_is_valid)
return first_gaia_account;
if (valid_primary_account)
return primary_account;
// Changing the first Gaia account while Chrome is running would be
// confusing for the user. Logout everything.
return std::string();
}
void DiceAccountReconcilorDelegate::OnReconcileFinished(
const std::string& first_account,
bool reconcile_is_noop) {
last_known_first_account_ = first_account;
// Migration happens on startup if the last reconcile was a no-op.
if (IsDicePrepareMigrationEnabled())
SetDiceMigrationOnStartup(user_prefs_, reconcile_is_noop);
}
} // namespace signin
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_DICE_ACCOUNT_RECONCILOR_DELEGATE_H_
#define COMPONENTS_SIGNIN_CORE_BROWSER_DICE_ACCOUNT_RECONCILOR_DELEGATE_H_
#include <string>
#include "base/macros.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
namespace user_prefs {
class PrefRegistrySyncable;
}
class PrefService;
namespace signin {
// AccountReconcilorDelegate specialized for Dice.
class DiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
public:
DiceAccountReconcilorDelegate(PrefService* user_prefs, bool is_new_profile);
~DiceAccountReconcilorDelegate() override {}
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
// Dice migration methods, public for testing:
// Schedules migration to happen at next startup.
static void SetDiceMigrationOnStartup(PrefService* prefs, bool migrate);
// Returns true if migration can happen on the next startup.
bool IsReadyForDiceMigration(bool is_new_profile);
// AccountReconcilorDelegate:
bool IsReconcileEnabled() const override;
bool IsAccountConsistencyEnforced() const override;
std::string GetFirstGaiaAccountForReconcile(
const std::vector<std::string>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const std::string& primary_account,
bool first_execution) const override;
void OnReconcileFinished(const std::string& first_account,
bool reconcile_is_noop) override;
private:
PrefService* user_prefs_;
// Last known "first account". Used when cookies are lost as a best guess.
std::string last_known_first_account_;
DISALLOW_COPY_AND_ASSIGN(DiceAccountReconcilorDelegate);
};
} // namespace signin
#endif // COMPONENTS_SIGNIN_CORE_BROWSER_DICE_ACCOUNT_RECONCILOR_DELEGATE_H_
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/signin/core/browser/dice_account_reconcilor_delegate.h"
#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/scoped_account_consistency.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "testing/gtest/include/gtest/gtest.h"
// Checks that Dice migration happens when the reconcilor is created.
TEST(DiceAccountReconcilorDelegateTest, MigrateAtCreation) {
sync_preferences::TestingPrefServiceSyncable pref_service;
signin::DiceAccountReconcilorDelegate::RegisterProfilePrefs(
pref_service.registry());
signin::RegisterAccountConsistencyProfilePrefs(pref_service.registry());
{
// Migration does not happen if SetDiceMigrationOnStartup() is not called.
signin::ScopedAccountConsistencyDiceMigration scoped_dice_migration;
EXPECT_FALSE(signin::IsDiceEnabledForProfile(&pref_service));
signin::DiceAccountReconcilorDelegate delegate(&pref_service, false);
EXPECT_FALSE(delegate.IsReadyForDiceMigration(false /* is_new_profile */));
EXPECT_FALSE(signin::IsDiceEnabledForProfile(&pref_service));
}
signin::DiceAccountReconcilorDelegate::SetDiceMigrationOnStartup(
&pref_service, true);
{
// Migration does not happen if Dice is not enabled.
signin::ScopedAccountConsistencyDiceFixAuthErrors scoped_dice_fix_errors;
EXPECT_FALSE(signin::IsDiceEnabledForProfile(&pref_service));
signin::DiceAccountReconcilorDelegate delegate(&pref_service, false);
EXPECT_TRUE(delegate.IsReadyForDiceMigration(false /* is_new_profile */));
EXPECT_FALSE(signin::IsDiceEnabledForProfile(&pref_service));
}
{
// Migration happens.
signin::ScopedAccountConsistencyDiceMigration scoped_dice_migration;
EXPECT_FALSE(signin::IsDiceEnabledForProfile(&pref_service));
signin::DiceAccountReconcilorDelegate delegate(&pref_service, false);
EXPECT_TRUE(delegate.IsReadyForDiceMigration(false /* is_new_profile */));
EXPECT_TRUE(signin::IsDiceEnabledForProfile(&pref_service));
}
}
// Checks that new profiles are migrated at creation.
TEST(DiceAccountReconcilorDelegateTest, NewProfile) {
signin::ScopedAccountConsistencyDiceMigration scoped_dice_migration;
sync_preferences::TestingPrefServiceSyncable pref_service;
signin::DiceAccountReconcilorDelegate::RegisterProfilePrefs(
pref_service.registry());
signin::RegisterAccountConsistencyProfilePrefs(pref_service.registry());
EXPECT_FALSE(signin::IsDiceEnabledForProfile(&pref_service));
signin::DiceAccountReconcilorDelegate delegate(&pref_service, true);
EXPECT_TRUE(signin::IsDiceEnabledForProfile(&pref_service));
}
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/signin/core/browser/mirror_account_reconcilor_delegate.h"
#include "base/logging.h"
#include "components/signin/core/browser/account_reconcilor.h"
namespace signin {
MirrorAccountReconcilorDelegate::MirrorAccountReconcilorDelegate(
SigninManagerBase* signin_manager)
: signin_manager_(signin_manager) {
DCHECK(signin_manager_);
signin_manager_->AddObserver(this);
}
MirrorAccountReconcilorDelegate::~MirrorAccountReconcilorDelegate() {
signin_manager_->RemoveObserver(this);
}
bool MirrorAccountReconcilorDelegate::IsReconcileEnabled() const {
return signin_manager_->IsAuthenticated();
}
bool MirrorAccountReconcilorDelegate::IsAccountConsistencyEnforced() const {
return true;
}
bool MirrorAccountReconcilorDelegate::ShouldAbortReconcileIfPrimaryHasError()
const {
return true;
}
std::string MirrorAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
const std::vector<std::string>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const std::string& primary_account,
bool first_execution) const {
// Mirror only uses the primary account, and it is never empty.
DCHECK(!primary_account.empty());
DCHECK(base::ContainsValue(chrome_accounts, primary_account));
return primary_account;
}
void MirrorAccountReconcilorDelegate::GoogleSigninSucceeded(
const std::string& account_id,
const std::string& username) {
reconcilor()->EnableReconcile();
}
void MirrorAccountReconcilorDelegate::GoogleSignedOut(
const std::string& account_id,
const std::string& username) {
reconcilor()->DisableReconcile(true /* logout_all_gaia_accounts */);
}
} // namespace signin
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_MIRROR_ACCOUNT_RECONCILOR_DELEGATE_H_
#define COMPONENTS_SIGNIN_CORE_BROWSER_MIRROR_ACCOUNT_RECONCILOR_DELEGATE_H_
#include "base/macros.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
#include "components/signin/core/browser/signin_manager_base.h"
namespace signin {
// AccountReconcilorDelegate specialized for Mirror.
class MirrorAccountReconcilorDelegate : public AccountReconcilorDelegate,
public SigninManagerBase::Observer {
public:
MirrorAccountReconcilorDelegate(SigninManagerBase* signin_manager);
~MirrorAccountReconcilorDelegate() override;
private:
// AccountReconcilorDelegate:
bool IsReconcileEnabled() const override;
bool IsAccountConsistencyEnforced() const override;
bool ShouldAbortReconcileIfPrimaryHasError() const override;
std::string GetFirstGaiaAccountForReconcile(
const std::vector<std::string>& chrome_accounts,
const std::vector<gaia::ListedAccount>& gaia_accounts,
const std::string& primary_account,
bool first_execution) const override;
// SigninManagerBase::Observer:
void GoogleSigninSucceeded(const std::string& account_id,
const std::string& username) override;
void GoogleSignedOut(const std::string& account_id,
const std::string& username) override;
SigninManagerBase* signin_manager_;
DISALLOW_COPY_AND_ASSIGN(MirrorAccountReconcilorDelegate);
};
} // namespace signin
#endif // COMPONENTS_SIGNIN_CORE_BROWSER_MIRROR_ACCOUNT_RECONCILOR_DELEGATE_H_
...@@ -8,8 +8,11 @@ ...@@ -8,8 +8,11 @@
#include <memory> #include <memory>
#include "base/memory/ptr_util.h" #include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/values.h"
#include "components/signin/core/browser/account_reconcilor.h" #include "components/signin/core/browser/account_reconcilor.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
#include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/fake_signin_manager.h" #include "components/signin/core/browser/fake_signin_manager.h"
#include "components/signin/core/browser/gaia_cookie_manager_service.h" #include "components/signin/core/browser/gaia_cookie_manager_service.h"
...@@ -78,7 +81,12 @@ class FakeAccountConsistencyService : public AccountConsistencyService { ...@@ -78,7 +81,12 @@ class FakeAccountConsistencyService : public AccountConsistencyService {
class MockAccountReconcilor : public AccountReconcilor { class MockAccountReconcilor : public AccountReconcilor {
public: public:
MockAccountReconcilor(SigninClient* client) MockAccountReconcilor(SigninClient* client)
: AccountReconcilor(nullptr, nullptr, client, nullptr, false) {} : AccountReconcilor(
nullptr,
nullptr,
client,
nullptr,
std::make_unique<signin::AccountReconcilorDelegate>()) {}
MOCK_METHOD1(OnReceivedManageAccountsResponse, void(signin::GAIAServiceType)); MOCK_METHOD1(OnReceivedManageAccountsResponse, void(signin::GAIAServiceType));
}; };
...@@ -150,7 +158,7 @@ class AccountConsistencyServiceTest : public PlatformTest { ...@@ -150,7 +158,7 @@ class AccountConsistencyServiceTest : public PlatformTest {
cookie_settings_ = cookie_settings_ =
new content_settings::CookieSettings(settings_map_.get(), &prefs_, ""); new content_settings::CookieSettings(settings_map_.get(), &prefs_, "");
account_reconcilor_ = account_reconcilor_ =
base::MakeUnique<MockAccountReconcilor>(signin_client_.get()); std::make_unique<MockAccountReconcilor>(signin_client_.get());
ResetAccountConsistencyService(); ResetAccountConsistencyService();
} }
......
...@@ -4,11 +4,12 @@ ...@@ -4,11 +4,12 @@
#include "ios/chrome/browser/signin/account_reconcilor_factory.h" #include "ios/chrome/browser/signin/account_reconcilor_factory.h"
#include <utility> #include <memory>
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
#include "components/keyed_service/ios/browser_state_dependency_manager.h" #include "components/keyed_service/ios/browser_state_dependency_manager.h"
#include "components/signin/core/browser/account_reconcilor.h" #include "components/signin/core/browser/account_reconcilor.h"
#include "components/signin/core/browser/mirror_account_reconcilor_delegate.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#include "ios/chrome/browser/signin/gaia_cookie_manager_service_factory.h" #include "ios/chrome/browser/signin/gaia_cookie_manager_service_factory.h"
#include "ios/chrome/browser/signin/oauth2_token_service_factory.h" #include "ios/chrome/browser/signin/oauth2_token_service_factory.h"
...@@ -45,12 +46,15 @@ std::unique_ptr<KeyedService> AccountReconcilorFactory::BuildServiceInstanceFor( ...@@ -45,12 +46,15 @@ std::unique_ptr<KeyedService> AccountReconcilorFactory::BuildServiceInstanceFor(
web::BrowserState* context) const { web::BrowserState* context) const {
ios::ChromeBrowserState* chrome_browser_state = ios::ChromeBrowserState* chrome_browser_state =
ios::ChromeBrowserState::FromBrowserState(context); ios::ChromeBrowserState::FromBrowserState(context);
SigninManager* signin_manager =
SigninManagerFactory::GetForBrowserState(chrome_browser_state);
std::unique_ptr<AccountReconcilor> reconcilor(new AccountReconcilor( std::unique_ptr<AccountReconcilor> reconcilor(new AccountReconcilor(
OAuth2TokenServiceFactory::GetForBrowserState(chrome_browser_state), OAuth2TokenServiceFactory::GetForBrowserState(chrome_browser_state),
SigninManagerFactory::GetForBrowserState(chrome_browser_state), signin_manager,
SigninClientFactory::GetForBrowserState(chrome_browser_state), SigninClientFactory::GetForBrowserState(chrome_browser_state),
GaiaCookieManagerServiceFactory::GetForBrowserState(chrome_browser_state), GaiaCookieManagerServiceFactory::GetForBrowserState(chrome_browser_state),
false /* is_new_profile */)); std::make_unique<signin::MirrorAccountReconcilorDelegate>(
signin_manager)));
reconcilor->Initialize(true /* start_reconcile_if_tokens_available */); reconcilor->Initialize(true /* start_reconcile_if_tokens_available */);
return reconcilor; return reconcilor;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment