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

[Dice] Split DiceTurnSyncOnHelper and add unittests

The UI code is moved out of DiceTurnSyncOnHelper into
DiceTurnSyncOnHelper::Delegate, to make the code easier to
test.

Change-Id: I5d4fd9a94a64a05f5c1a63ccd593b3260eea8421
Reviewed-on: https://chromium-review.googlesource.com/870595Reviewed-by: default avatarJulian Pastarmov <pastarmovj@chromium.org>
Reviewed-by: default avatarMihai Sardarescu <msarda@chromium.org>
Commit-Queue: David Roger <droger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#531922}
parent b8d512a4
...@@ -55,7 +55,8 @@ class UserPolicySigninService : public UserPolicySigninServiceBase, ...@@ -55,7 +55,8 @@ class UserPolicySigninService : public UserPolicySigninServiceBase,
// Registers a CloudPolicyClient for fetching policy for a user. |username| is // Registers a CloudPolicyClient for fetching policy for a user. |username| is
// explicitly passed because the user is not yet authenticated, but the token // explicitly passed because the user is not yet authenticated, but the token
// service has a refresh token available for |account_id|. // service has a refresh token available for |account_id|.
void RegisterForPolicyWithAccountId( // Virtual for testing.
virtual void RegisterForPolicyWithAccountId(
const std::string& username, const std::string& username,
const std::string& account_id, const std::string& account_id,
const PolicyRegistrationCallback& callback); const PolicyRegistrationCallback& callback);
......
...@@ -75,7 +75,8 @@ class UserPolicySigninServiceBase : public KeyedService, ...@@ -75,7 +75,8 @@ class UserPolicySigninServiceBase : public KeyedService,
// |client_id| fetched via RegisterForPolicyXXX(). |callback| is invoked // |client_id| fetched via RegisterForPolicyXXX(). |callback| is invoked
// once the policy fetch is complete, passing true if the policy fetch // once the policy fetch is complete, passing true if the policy fetch
// succeeded. // succeeded.
void FetchPolicyForSignedInUser( // Virtual for testing.
virtual void FetchPolicyForSignedInUser(
const std::string& username, const std::string& username,
const std::string& dm_token, const std::string& dm_token,
const std::string& client_id, const std::string& client_id,
......
...@@ -1681,6 +1681,8 @@ split_static_library("ui") { ...@@ -1681,6 +1681,8 @@ split_static_library("ui") {
sources += [ sources += [
"webui/signin/dice_turn_sync_on_helper.cc", "webui/signin/dice_turn_sync_on_helper.cc",
"webui/signin/dice_turn_sync_on_helper.h", "webui/signin/dice_turn_sync_on_helper.h",
"webui/signin/dice_turn_sync_on_helper_delegate_impl.cc",
"webui/signin/dice_turn_sync_on_helper_delegate_impl.h",
"webui/signin/signin_dice_internals_handler.cc", "webui/signin/signin_dice_internals_handler.cc",
"webui/signin/signin_dice_internals_handler.h", "webui/signin/signin_dice_internals_handler.h",
] ]
......
...@@ -16,25 +16,13 @@ ...@@ -16,25 +16,13 @@
#include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_attributes_storage.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h" #include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_window.h"
#include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/signin/account_tracker_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 "chrome/browser/signin/signin_util.h" #include "chrome/browser/signin/signin_util.h"
#include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/startup/startup_types.h"
#include "chrome/browser/ui/tab_dialogs.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/browser/ui/webui/signin/signin_utils_desktop.h" #include "chrome/browser/ui/webui/signin/signin_utils_desktop.h"
#include "chrome/common/url_constants.h"
#include "components/browser_sync/profile_sync_service.h" #include "components/browser_sync/profile_sync_service.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "components/signin/core/browser/account_info.h" #include "components/signin/core/browser/account_info.h"
...@@ -48,117 +36,32 @@ ...@@ -48,117 +36,32 @@
namespace { namespace {
// UMA histogram for tracking what users do when presented with the signin
// screen.
// Hence,
// (a) existing enumerated constants should never be deleted or reordered, and
// (b) new constants should only be appended at the end of the enumeration.
//
// Keep this in sync with SigninChoice in histograms.xml.
enum SigninChoice {
SIGNIN_CHOICE_CANCEL = 0,
SIGNIN_CHOICE_CONTINUE = 1,
SIGNIN_CHOICE_NEW_PROFILE = 2,
// SIGNIN_CHOICE_SIZE should always be last - this is a count of the number
// of items in this enum.
SIGNIN_CHOICE_SIZE,
};
void SetUserChoiceHistogram(SigninChoice choice) {
UMA_HISTOGRAM_ENUMERATION("Enterprise.UserSigninChoice", choice,
SIGNIN_CHOICE_SIZE);
}
AccountInfo GetAccountInfo(Profile* profile, const std::string& account_id) { AccountInfo GetAccountInfo(Profile* profile, const std::string& account_id) {
return AccountTrackerServiceFactory::GetForProfile(profile)->GetAccountInfo( return AccountTrackerServiceFactory::GetForProfile(profile)->GetAccountInfo(
account_id); account_id);
} }
// If the |browser| argument is non-null, returns the pointer directly.
// Otherwise creates a new browser for the given profile on the given desktop,
// adds an empty tab and makes sure the browser is visible.
Browser* EnsureBrowser(Browser* browser, Profile* profile) {
if (!browser) {
// The user just created a new profile or has closed the browser that
// we used previously. Grab the most recently active browser or else
// create a new one.
browser = chrome::FindLastActiveWithProfile(profile);
if (!browser) {
browser = new Browser(Browser::CreateParams(profile, true));
chrome::AddTabAt(browser, GURL(), -1, true);
}
browser->window()->Show();
}
return browser;
}
void StartNewSigninInNewProfile(Profile* new_profile,
const std::string& username) {
profiles::FindOrCreateNewWindowForProfile(
new_profile, chrome::startup::IS_PROCESS_STARTUP,
chrome::startup::IS_FIRST_RUN, false);
Browser* browser = chrome::FindTabbedBrowser(new_profile, false);
browser->signin_view_controller()->ShowDiceSigninTab(
profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN, browser,
signin_metrics::AccessPoint::ACCESS_POINT_START_PAGE, username);
}
} // namespace } // namespace
DiceTurnSyncOnHelper::SigninDialogDelegate::SigninDialogDelegate(
base::WeakPtr<DiceTurnSyncOnHelper> sync_starter)
: sync_starter_(sync_starter) {}
DiceTurnSyncOnHelper::SigninDialogDelegate::~SigninDialogDelegate() {}
void DiceTurnSyncOnHelper::SigninDialogDelegate::OnCancelSignin() {
SetUserChoiceHistogram(SIGNIN_CHOICE_CANCEL);
base::RecordAction(
base::UserMetricsAction("Signin_EnterpriseAccountPrompt_Cancel"));
if (sync_starter_)
sync_starter_->AbortAndDelete();
}
void DiceTurnSyncOnHelper::SigninDialogDelegate::OnContinueSignin() {
SetUserChoiceHistogram(SIGNIN_CHOICE_CONTINUE);
base::RecordAction(
base::UserMetricsAction("Signin_EnterpriseAccountPrompt_ImportData"));
if (sync_starter_)
sync_starter_->LoadPolicyWithCachedCredentials();
}
void DiceTurnSyncOnHelper::SigninDialogDelegate::OnSigninWithNewProfile() {
SetUserChoiceHistogram(SIGNIN_CHOICE_NEW_PROFILE);
base::RecordAction(
base::UserMetricsAction("Signin_EnterpriseAccountPrompt_DontImportData"));
if (sync_starter_)
sync_starter_->CreateNewSignedInProfile();
}
DiceTurnSyncOnHelper::DiceTurnSyncOnHelper( DiceTurnSyncOnHelper::DiceTurnSyncOnHelper(
Profile* profile, Profile* profile,
Browser* browser,
signin_metrics::AccessPoint signin_access_point, signin_metrics::AccessPoint signin_access_point,
signin_metrics::Reason signin_reason, signin_metrics::Reason signin_reason,
const std::string& account_id, const std::string& account_id,
SigninAbortedMode signin_aborted_mode) SigninAbortedMode signin_aborted_mode,
: profile_(profile), std::unique_ptr<Delegate> delegate)
browser_(browser), : delegate_(std::move(delegate)),
profile_(profile),
signin_manager_(SigninManagerFactory::GetForProfile(profile)), signin_manager_(SigninManagerFactory::GetForProfile(profile)),
token_service_(ProfileOAuth2TokenServiceFactory::GetForProfile(profile)), token_service_(ProfileOAuth2TokenServiceFactory::GetForProfile(profile)),
signin_access_point_(signin_access_point), signin_access_point_(signin_access_point),
signin_reason_(signin_reason), signin_reason_(signin_reason),
signin_aborted_mode_(signin_aborted_mode), signin_aborted_mode_(signin_aborted_mode),
account_info_(GetAccountInfo(profile, account_id)), account_info_(GetAccountInfo(profile, account_id)),
scoped_browser_list_observer_(this),
scoped_login_ui_service_observer_(this),
weak_pointer_factory_(this) { weak_pointer_factory_(this) {
DCHECK(delegate_);
DCHECK(signin::IsDicePrepareMigrationEnabled()); DCHECK(signin::IsDicePrepareMigrationEnabled());
DCHECK(profile_); DCHECK(profile_);
DCHECK(browser_);
DCHECK(!account_info_.gaia.empty()); DCHECK(!account_info_.gaia.empty());
DCHECK(!account_info_.email.empty()); DCHECK(!account_info_.email.empty());
// Should not start syncing if the profile is already authenticated // Should not start syncing if the profile is already authenticated
...@@ -181,22 +84,33 @@ DiceTurnSyncOnHelper::DiceTurnSyncOnHelper( ...@@ -181,22 +84,33 @@ DiceTurnSyncOnHelper::DiceTurnSyncOnHelper(
// last authenticated account of the current profile, then Chrome will show a // last authenticated account of the current profile, then Chrome will show a
// confirmation dialog before starting sync. // confirmation dialog before starting sync.
// TODO(skym): Warn for high risk upgrade scenario (https://crbug.com/572754). // TODO(skym): Warn for high risk upgrade scenario (https://crbug.com/572754).
content::WebContents* web_contents =
browser_->tab_strip_model()->GetActiveWebContents();
std::string last_email = std::string last_email =
profile_->GetPrefs()->GetString(prefs::kGoogleServicesLastUsername); profile_->GetPrefs()->GetString(prefs::kGoogleServicesLastUsername);
SigninEmailConfirmationDialog::AskForConfirmation( delegate_->ShowMergeSyncDataConfirmation(
web_contents, profile_, last_email, account_info_.email, last_email, account_info_.email,
base::Bind(&DiceTurnSyncOnHelper::ConfirmEmailAction, base::BindOnce(&DiceTurnSyncOnHelper::OnMergeAccountConfirmation,
weak_pointer_factory_.GetWeakPtr())); weak_pointer_factory_.GetWeakPtr()));
} }
DiceTurnSyncOnHelper::DiceTurnSyncOnHelper(
Profile* profile,
Browser* browser,
signin_metrics::AccessPoint signin_access_point,
signin_metrics::Reason signin_reason,
const std::string& account_id,
SigninAbortedMode signin_aborted_mode)
: DiceTurnSyncOnHelper(
profile,
signin_access_point,
signin_reason,
account_id,
signin_aborted_mode,
std::make_unique<DiceTurnSyncOnHelperDelegateImpl>(browser)) {}
DiceTurnSyncOnHelper::~DiceTurnSyncOnHelper() { DiceTurnSyncOnHelper::~DiceTurnSyncOnHelper() {
DCHECK(!scoped_login_ui_service_observer_.IsObservingSources());
} }
bool DiceTurnSyncOnHelper::HasCanOfferSigninError() { bool DiceTurnSyncOnHelper::HasCanOfferSigninError() {
DCHECK(browser_);
std::string error_msg; std::string error_msg;
bool can_offer = bool can_offer =
CanOfferSignin(profile_, CAN_OFFER_SIGNIN_FOR_ALL_ACCOUNTS, CanOfferSignin(profile_, CAN_OFFER_SIGNIN_FOR_ALL_ACCOUNTS,
...@@ -205,36 +119,62 @@ bool DiceTurnSyncOnHelper::HasCanOfferSigninError() { ...@@ -205,36 +119,62 @@ bool DiceTurnSyncOnHelper::HasCanOfferSigninError() {
return false; return false;
// Display the error message // Display the error message
LoginUIServiceFactory::GetForProfile(profile_)->DisplayLoginResult( delegate_->ShowLoginError(account_info_.email, error_msg);
browser_, base::UTF8ToUTF16(error_msg),
base::UTF8ToUTF16(account_info_.email));
return true; return true;
} }
void DiceTurnSyncOnHelper::ConfirmEmailAction( void DiceTurnSyncOnHelper::OnMergeAccountConfirmation(SigninChoice choice) {
SigninEmailConfirmationDialog::Action action) { switch (choice) {
switch (action) { case SIGNIN_CHOICE_NEW_PROFILE:
case SigninEmailConfirmationDialog::CREATE_NEW_USER:
base::RecordAction( base::RecordAction(
base::UserMetricsAction("Signin_ImportDataPrompt_DontImport")); base::UserMetricsAction("Signin_ImportDataPrompt_DontImport"));
TurnSyncOnWithProfileMode(ProfileMode::NEW_PROFILE); TurnSyncOnWithProfileMode(ProfileMode::NEW_PROFILE);
break; break;
case SigninEmailConfirmationDialog::START_SYNC: case SIGNIN_CHOICE_CONTINUE:
base::RecordAction( base::RecordAction(
base::UserMetricsAction("Signin_ImportDataPrompt_ImportData")); base::UserMetricsAction("Signin_ImportDataPrompt_ImportData"));
TurnSyncOnWithProfileMode(ProfileMode::CURRENT_PROFILE); TurnSyncOnWithProfileMode(ProfileMode::CURRENT_PROFILE);
break; break;
case SigninEmailConfirmationDialog::CLOSE: case SIGNIN_CHOICE_CANCEL:
base::RecordAction( base::RecordAction(
base::UserMetricsAction("Signin_ImportDataPrompt_Cancel")); base::UserMetricsAction("Signin_ImportDataPrompt_Cancel"));
AbortAndDelete(); AbortAndDelete();
break; break;
case SIGNIN_CHOICE_SIZE:
NOTREACHED();
AbortAndDelete();
break;
} }
} }
void DiceTurnSyncOnHelper::TurnSyncOnWithProfileMode(ProfileMode profile_mode) { void DiceTurnSyncOnHelper::OnEnterpriseAccountConfirmation(
scoped_browser_list_observer_.Add(BrowserList::GetInstance()); SigninChoice choice) {
UMA_HISTOGRAM_ENUMERATION("Enterprise.UserSigninChoice", choice,
DiceTurnSyncOnHelper::SIGNIN_CHOICE_SIZE);
switch (choice) {
case SIGNIN_CHOICE_CANCEL:
base::RecordAction(
base::UserMetricsAction("Signin_EnterpriseAccountPrompt_Cancel"));
AbortAndDelete();
break;
case SIGNIN_CHOICE_CONTINUE:
base::RecordAction(
base::UserMetricsAction("Signin_EnterpriseAccountPrompt_ImportData"));
LoadPolicyWithCachedCredentials();
break;
case SIGNIN_CHOICE_NEW_PROFILE:
base::RecordAction(base::UserMetricsAction(
"Signin_EnterpriseAccountPrompt_DontImportData"));
CreateNewSignedInProfile();
break;
case SIGNIN_CHOICE_SIZE:
NOTREACHED();
AbortAndDelete();
break;
}
}
void DiceTurnSyncOnHelper::TurnSyncOnWithProfileMode(ProfileMode profile_mode) {
// Make sure the syncing is requested, otherwise the SigninManager // Make sure the syncing is requested, otherwise the SigninManager
// will not be able to complete successfully. // will not be able to complete successfully.
syncer::SyncPrefs sync_prefs(profile_->GetPrefs()); syncer::SyncPrefs sync_prefs(profile_->GetPrefs());
...@@ -282,20 +222,10 @@ void DiceTurnSyncOnHelper::OnRegisteredForPolicy(const std::string& dm_token, ...@@ -282,20 +222,10 @@ void DiceTurnSyncOnHelper::OnRegisteredForPolicy(const std::string& dm_token,
client_id_ = client_id; client_id_ = client_id;
// Allow user to create a new profile before continuing with sign-in. // Allow user to create a new profile before continuing with sign-in.
browser_ = EnsureBrowser(browser_, profile_); delegate_->ShowEnterpriseAccountConfirmation(
content::WebContents* web_contents = account_info_.email,
browser_->tab_strip_model()->GetActiveWebContents(); base::BindOnce(&DiceTurnSyncOnHelper::OnEnterpriseAccountConfirmation,
if (!web_contents) { weak_pointer_factory_.GetWeakPtr()));
AbortAndDelete();
return;
}
base::RecordAction(
base::UserMetricsAction("Signin_Show_EnterpriseAccountPrompt"));
TabDialogs::FromWebContents(web_contents)
->ShowProfileSigninConfirmation(browser_, profile_, account_info_.email,
std::make_unique<SigninDialogDelegate>(
weak_pointer_factory_.GetWeakPtr()));
} }
void DiceTurnSyncOnHelper::LoadPolicyWithCachedCredentials() { void DiceTurnSyncOnHelper::LoadPolicyWithCachedCredentials() {
...@@ -349,7 +279,7 @@ void DiceTurnSyncOnHelper::CompleteInitForNewProfile( ...@@ -349,7 +279,7 @@ void DiceTurnSyncOnHelper::CompleteInitForNewProfile(
break; break;
case Profile::CREATE_STATUS_INITIALIZED: case Profile::CREATE_STATUS_INITIALIZED:
// The user needs to sign in to the new profile in order to enable sync. // The user needs to sign in to the new profile in order to enable sync.
StartNewSigninInNewProfile(new_profile, account_info_.email); delegate_->ShowSigninPageInNewProfile(new_profile, account_info_.email);
AbortAndDelete(); AbortAndDelete();
break; break;
case Profile::CREATE_STATUS_REMOTE_FAIL: case Profile::CREATE_STATUS_REMOTE_FAIL:
...@@ -377,19 +307,16 @@ void DiceTurnSyncOnHelper::SigninAndShowSyncConfirmationUI() { ...@@ -377,19 +307,16 @@ void DiceTurnSyncOnHelper::SigninAndShowSyncConfirmationUI() {
base::RecordAction(base::UserMetricsAction("Signin_Signin_Succeed")); base::RecordAction(base::UserMetricsAction("Signin_Signin_Succeed"));
// Show Sync confirmation. // Show Sync confirmation.
scoped_login_ui_service_observer_.Add( delegate_->ShowSyncConfirmation(
LoginUIServiceFactory::GetForProfile(profile_)); base::BindOnce(&DiceTurnSyncOnHelper::FinishSyncSetupAndDelete,
browser_ = EnsureBrowser(browser_, profile_); weak_pointer_factory_.GetWeakPtr()));
browser_->signin_view_controller()->ShowModalSyncConfirmationDialog(browser_);
} }
void DiceTurnSyncOnHelper::OnSyncConfirmationUIClosed( void DiceTurnSyncOnHelper::FinishSyncSetupAndDelete(
LoginUIService::SyncConfirmationUIClosedResult result) { LoginUIService::SyncConfirmationUIClosedResult result) {
scoped_login_ui_service_observer_.RemoveAll();
switch (result) { switch (result) {
case LoginUIService::CONFIGURE_SYNC_FIRST: case LoginUIService::CONFIGURE_SYNC_FIRST:
browser_ = EnsureBrowser(browser_, profile_); delegate_->ShowSyncSettings();
chrome::ShowSettingsSubPage(browser_, chrome::kSyncSetupSubPage);
break; break;
case LoginUIService::SYNC_WITH_DEFAULT_SETTINGS: { case LoginUIService::SYNC_WITH_DEFAULT_SETTINGS: {
browser_sync::ProfileSyncService* sync_service = GetProfileSyncService(); browser_sync::ProfileSyncService* sync_service = GetProfileSyncService();
...@@ -407,11 +334,6 @@ void DiceTurnSyncOnHelper::OnSyncConfirmationUIClosed( ...@@ -407,11 +334,6 @@ void DiceTurnSyncOnHelper::OnSyncConfirmationUIClosed(
delete this; delete this;
} }
void DiceTurnSyncOnHelper::OnBrowserRemoved(Browser* browser) {
if (browser == browser_)
browser_ = nullptr;
}
void DiceTurnSyncOnHelper::AbortAndDelete() { void DiceTurnSyncOnHelper::AbortAndDelete() {
if (signin_aborted_mode_ == SigninAbortedMode::REMOVE_ACCOUNT) { if (signin_aborted_mode_ == SigninAbortedMode::REMOVE_ACCOUNT) {
// Revoke the token, and the AccountReconcilor and/or the Gaia server will // Revoke the token, and the AccountReconcilor and/or the Gaia server will
......
...@@ -5,20 +5,18 @@ ...@@ -5,20 +5,18 @@
#ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_TURN_SYNC_ON_HELPER_H_ #ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_TURN_SYNC_ON_HELPER_H_
#define CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_TURN_SYNC_ON_HELPER_H_ #define CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_TURN_SYNC_ON_HELPER_H_
#include <memory>
#include <string> #include <string>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h" #include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h"
#include "components/signin/core/browser/account_info.h" #include "components/signin/core/browser/account_info.h"
#include "components/signin/core/browser/signin_metrics.h" #include "components/signin/core/browser/signin_metrics.h"
class Browser; class Browser;
class BrowserList;
class ProfileOAuth2TokenService; class ProfileOAuth2TokenService;
class SigninManager; class SigninManager;
...@@ -28,8 +26,7 @@ class ProfileSyncService; ...@@ -28,8 +26,7 @@ class ProfileSyncService;
// Handles details of signing the user in with SigninManager and turning on // Handles details of signing the user in with SigninManager and turning on
// sync for an account that is already present in the token service. // sync for an account that is already present in the token service.
class DiceTurnSyncOnHelper : public BrowserListObserver, class DiceTurnSyncOnHelper {
public LoginUIService::Observer {
public: public:
// Behavior when the signin is aborted (by an error or cancelled by the user). // Behavior when the signin is aborted (by an error or cancelled by the user).
enum class SigninAbortedMode { enum class SigninAbortedMode {
...@@ -39,8 +36,66 @@ class DiceTurnSyncOnHelper : public BrowserListObserver, ...@@ -39,8 +36,66 @@ class DiceTurnSyncOnHelper : public BrowserListObserver,
KEEP_ACCOUNT KEEP_ACCOUNT
}; };
// User choice when signing in.
// Used for UMA histograms, Hence, constants should never be deleted or
// reordered, and new constants should only be appended at the end.
// Keep this in sync with SigninChoice in histograms.xml.
enum SigninChoice {
SIGNIN_CHOICE_CANCEL = 0, // Signin is cancelled.
SIGNIN_CHOICE_CONTINUE = 1, // Signin continues in the current profile.
SIGNIN_CHOICE_NEW_PROFILE = 2, // Signin continues in a new profile.
// SIGNIN_CHOICE_SIZE should always be last.
SIGNIN_CHOICE_SIZE,
};
using SigninChoiceCallback = base::OnceCallback<void(SigninChoice)>;
// Delegate implementing the UI prompts.
class Delegate {
public:
virtual ~Delegate() {}
// Shows a login error to the user.
virtual void ShowLoginError(const std::string& email,
const std::string& error_message) = 0;
// Shows a confirmation dialog when the user was previously signed in with a
// different account in the same profile. |callback| must be called.
virtual void ShowMergeSyncDataConfirmation(
const std::string& previous_email,
const std::string& new_email,
SigninChoiceCallback callback) = 0;
// Shows a confirmation dialog when the user is signing in a managed
// account. |callback| must be called.
virtual void ShowEnterpriseAccountConfirmation(
const std::string& email,
SigninChoiceCallback callback) = 0;
// Shows a sync confirmation screen offering to open the Sync settings.
// |callback| must be called.
virtual void ShowSyncConfirmation(
base::OnceCallback<void(LoginUIService::SyncConfirmationUIClosedResult)>
callback) = 0;
// Opens the Sync settings page.
virtual void ShowSyncSettings() = 0;
// Opens the signin page in a new profile.
virtual void ShowSigninPageInNewProfile(Profile* new_profile,
const std::string& username) = 0;
};
// Create a helper that turns sync on for an account that is already present // Create a helper that turns sync on for an account that is already present
// in the token service. // in the token service.
DiceTurnSyncOnHelper(Profile* profile,
signin_metrics::AccessPoint signin_access_point,
signin_metrics::Reason signin_reason,
const std::string& account_id,
SigninAbortedMode signin_aborted_mode,
std::unique_ptr<Delegate> delegate);
// Convenience constructor using the default delegate.
DiceTurnSyncOnHelper(Profile* profile, DiceTurnSyncOnHelper(Profile* profile,
Browser* browser, Browser* browser,
signin_metrics::AccessPoint signin_access_point, signin_metrics::AccessPoint signin_access_point,
...@@ -60,30 +115,18 @@ class DiceTurnSyncOnHelper : public BrowserListObserver, ...@@ -60,30 +115,18 @@ class DiceTurnSyncOnHelper : public BrowserListObserver,
NEW_PROFILE NEW_PROFILE
}; };
// User input handler for the signin confirmation dialog.
class SigninDialogDelegate : public ui::ProfileSigninConfirmationDelegate {
public:
explicit SigninDialogDelegate(
base::WeakPtr<DiceTurnSyncOnHelper> sync_starter);
~SigninDialogDelegate() override;
void OnCancelSignin() override;
void OnContinueSignin() override;
void OnSigninWithNewProfile() override;
private:
base::WeakPtr<DiceTurnSyncOnHelper> sync_starter_;
};
friend class SigninDialogDelegate;
// DiceTurnSyncOnHelper deletes itself. // DiceTurnSyncOnHelper deletes itself.
~DiceTurnSyncOnHelper() override; ~DiceTurnSyncOnHelper();
// Handles can offer sign-in errors. It returns true if there is an error, // Handles can offer sign-in errors. It returns true if there is an error,
// and false otherwise. // and false otherwise.
bool HasCanOfferSigninError(); bool HasCanOfferSigninError();
// Callback used with ConfirmEmailDialogDelegate. // Used as callback for ShowMergeSyncDataConfirmation().
void ConfirmEmailAction(SigninEmailConfirmationDialog::Action action); void OnMergeAccountConfirmation(SigninChoice choice);
// Used as callback for ShowEnterpriseAccountConfirmation().
void OnEnterpriseAccountConfirmation(SigninChoice choice);
// Turns sync on with the current profile or a new profile. // Turns sync on with the current profile or a new profile.
void TurnSyncOnWithProfileMode(ProfileMode profile_mode); void TurnSyncOnWithProfileMode(ProfileMode profile_mode);
...@@ -117,18 +160,16 @@ class DiceTurnSyncOnHelper : public BrowserListObserver, ...@@ -117,18 +160,16 @@ class DiceTurnSyncOnHelper : public BrowserListObserver,
// UI. // UI.
void SigninAndShowSyncConfirmationUI(); void SigninAndShowSyncConfirmationUI();
// LoginUIService::Observer override. Deletes this object. // Handles the user input from the sync confirmation UI and deletes this
void OnSyncConfirmationUIClosed( // object.
LoginUIService::SyncConfirmationUIClosedResult result) override; void FinishSyncSetupAndDelete(
LoginUIService::SyncConfirmationUIClosedResult result);
// BrowserListObserver override.
void OnBrowserRemoved(Browser* browser) override;
// Aborts the flow and deletes this object. // Aborts the flow and deletes this object.
void AbortAndDelete(); void AbortAndDelete();
std::unique_ptr<Delegate> delegate_;
Profile* profile_; Profile* profile_;
Browser* browser_;
SigninManager* signin_manager_; SigninManager* signin_manager_;
ProfileOAuth2TokenService* token_service_; ProfileOAuth2TokenService* token_service_;
const signin_metrics::AccessPoint signin_access_point_; const signin_metrics::AccessPoint signin_access_point_;
...@@ -145,11 +186,6 @@ class DiceTurnSyncOnHelper : public BrowserListObserver, ...@@ -145,11 +186,6 @@ class DiceTurnSyncOnHelper : public BrowserListObserver,
std::string dm_token_; std::string dm_token_;
std::string client_id_; std::string client_id_;
ScopedObserver<BrowserList, BrowserListObserver>
scoped_browser_list_observer_;
ScopedObserver<LoginUIService, LoginUIService::Observer>
scoped_login_ui_service_observer_;
base::WeakPtrFactory<DiceTurnSyncOnHelper> weak_pointer_factory_; base::WeakPtrFactory<DiceTurnSyncOnHelper> weak_pointer_factory_;
DISALLOW_COPY_AND_ASSIGN(DiceTurnSyncOnHelper); DISALLOW_COPY_AND_ASSIGN(DiceTurnSyncOnHelper);
}; };
......
// Copyright 2018 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 "chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.h"
#include "base/logging.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/profiles/profile_window.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/startup/startup_types.h"
#include "chrome/browser/ui/tab_dialogs.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h"
#include "chrome/common/url_constants.h"
namespace {
// If the |browser| argument is non-null, returns the pointer directly.
// Otherwise creates a new browser for the profile, adds an empty tab and makes
// sure the browser is visible.
Browser* EnsureBrowser(Browser* browser, Profile* profile) {
if (!browser) {
// The user just created a new profile or has closed the browser that
// we used previously. Grab the most recently active browser or else
// create a new one.
browser = chrome::FindLastActiveWithProfile(profile);
if (!browser) {
browser = new Browser(Browser::CreateParams(profile, true));
chrome::AddTabAt(browser, GURL(), -1, true);
}
browser->window()->Show();
}
return browser;
}
// Converts SigninEmailConfirmationDialog::Action to
// DiceTurnSyncOnHelper::SigninChoice and invokes |callback| on it.
void OnEmailConfirmation(DiceTurnSyncOnHelper::SigninChoiceCallback callback,
SigninEmailConfirmationDialog::Action action) {
DCHECK(callback) << "This function should be called only once.";
switch (action) {
case SigninEmailConfirmationDialog::START_SYNC:
std::move(callback).Run(DiceTurnSyncOnHelper::SIGNIN_CHOICE_CONTINUE);
return;
case SigninEmailConfirmationDialog::CREATE_NEW_USER:
std::move(callback).Run(DiceTurnSyncOnHelper::SIGNIN_CHOICE_NEW_PROFILE);
return;
case SigninEmailConfirmationDialog::CLOSE:
std::move(callback).Run(DiceTurnSyncOnHelper::SIGNIN_CHOICE_CANCEL);
return;
}
NOTREACHED();
}
} // namespace
DiceTurnSyncOnHelperDelegateImpl::SigninDialogDelegate::SigninDialogDelegate(
DiceTurnSyncOnHelper::SigninChoiceCallback callback)
: callback_(std::move(callback)) {
DCHECK(callback_);
}
DiceTurnSyncOnHelperDelegateImpl::SigninDialogDelegate::
~SigninDialogDelegate() = default;
void DiceTurnSyncOnHelperDelegateImpl::SigninDialogDelegate::OnCancelSignin() {
DCHECK(callback_);
std::move(callback_).Run(DiceTurnSyncOnHelper::SIGNIN_CHOICE_CANCEL);
}
void DiceTurnSyncOnHelperDelegateImpl::SigninDialogDelegate::
OnContinueSignin() {
DCHECK(callback_);
std::move(callback_).Run(DiceTurnSyncOnHelper::SIGNIN_CHOICE_CONTINUE);
}
void DiceTurnSyncOnHelperDelegateImpl::SigninDialogDelegate::
OnSigninWithNewProfile() {
DCHECK(callback_);
std::move(callback_).Run(DiceTurnSyncOnHelper::SIGNIN_CHOICE_NEW_PROFILE);
}
DiceTurnSyncOnHelperDelegateImpl::DiceTurnSyncOnHelperDelegateImpl(
Browser* browser)
: browser_(browser),
profile_(browser_->profile()),
scoped_browser_list_observer_(this),
scoped_login_ui_service_observer_(this) {
DCHECK(browser);
DCHECK(profile_);
scoped_browser_list_observer_.Add(BrowserList::GetInstance());
}
DiceTurnSyncOnHelperDelegateImpl::~DiceTurnSyncOnHelperDelegateImpl() {}
void DiceTurnSyncOnHelperDelegateImpl::ShowLoginError(
const std::string& email,
const std::string& error_message) {
LoginUIServiceFactory::GetForProfile(profile_)->DisplayLoginResult(
browser_, base::UTF8ToUTF16(error_message), base::UTF8ToUTF16(email));
}
void DiceTurnSyncOnHelperDelegateImpl::ShowEnterpriseAccountConfirmation(
const std::string& email,
DiceTurnSyncOnHelper::SigninChoiceCallback callback) {
DCHECK(callback);
browser_ = EnsureBrowser(browser_, profile_);
content::WebContents* web_contents =
browser_->tab_strip_model()->GetActiveWebContents();
if (!web_contents) {
std::move(callback).Run(DiceTurnSyncOnHelper::SIGNIN_CHOICE_CANCEL);
return;
}
base::RecordAction(
base::UserMetricsAction("Signin_Show_EnterpriseAccountPrompt"));
TabDialogs::FromWebContents(web_contents)
->ShowProfileSigninConfirmation(
browser_, profile_, email,
std::make_unique<SigninDialogDelegate>(std::move(callback)));
}
void DiceTurnSyncOnHelperDelegateImpl::ShowSyncConfirmation(
base::OnceCallback<void(LoginUIService::SyncConfirmationUIClosedResult)>
callback) {
DCHECK(callback);
sync_confirmation_callback_ = std::move(callback);
scoped_login_ui_service_observer_.Add(
LoginUIServiceFactory::GetForProfile(profile_));
browser_ = EnsureBrowser(browser_, profile_);
browser_->signin_view_controller()->ShowModalSyncConfirmationDialog(browser_);
}
void DiceTurnSyncOnHelperDelegateImpl::ShowMergeSyncDataConfirmation(
const std::string& previous_email,
const std::string& new_email,
DiceTurnSyncOnHelper::SigninChoiceCallback callback) {
DCHECK(callback);
content::WebContents* web_contents =
browser_->tab_strip_model()->GetActiveWebContents();
// TODO(droger): Replace Bind with BindOnce once the
// SigninEmailConfirmationDialog supports it.
SigninEmailConfirmationDialog::AskForConfirmation(
web_contents, profile_, previous_email, new_email,
base::Bind(&OnEmailConfirmation, base::Passed(std::move(callback))));
}
void DiceTurnSyncOnHelperDelegateImpl::ShowSyncSettings() {
browser_ = EnsureBrowser(browser_, profile_);
chrome::ShowSettingsSubPage(browser_, chrome::kSyncSetupSubPage);
}
void DiceTurnSyncOnHelperDelegateImpl::ShowSigninPageInNewProfile(
Profile* new_profile,
const std::string& username) {
profiles::FindOrCreateNewWindowForProfile(
new_profile, chrome::startup::IS_PROCESS_STARTUP,
chrome::startup::IS_FIRST_RUN, false);
Browser* browser = chrome::FindTabbedBrowser(new_profile, false);
browser->signin_view_controller()->ShowDiceSigninTab(
profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN, browser,
signin_metrics::AccessPoint::ACCESS_POINT_START_PAGE, username);
}
void DiceTurnSyncOnHelperDelegateImpl::OnSyncConfirmationUIClosed(
LoginUIService::SyncConfirmationUIClosedResult result) {
DCHECK(sync_confirmation_callback_);
std::move(sync_confirmation_callback_).Run(result);
}
void DiceTurnSyncOnHelperDelegateImpl::OnBrowserRemoved(Browser* browser) {
if (browser == browser_)
browser_ = nullptr;
}
// Copyright 2018 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 CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_TURN_SYNC_ON_HELPER_DELEGATE_IMPL_H_
#define CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_TURN_SYNC_ON_HELPER_DELEGATE_IMPL_H_
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/scoped_observer.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
#include "chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
class Browser;
class BrowserList;
class Profile;
// Default implementation for DiceTurnSyncOnHelper::Delegate.
class DiceTurnSyncOnHelperDelegateImpl : public DiceTurnSyncOnHelper::Delegate,
public BrowserListObserver,
public LoginUIService::Observer {
public:
explicit DiceTurnSyncOnHelperDelegateImpl(Browser* browser);
~DiceTurnSyncOnHelperDelegateImpl() override;
private:
// User input handler for the signin confirmation dialog.
class SigninDialogDelegate : public ui::ProfileSigninConfirmationDelegate {
public:
explicit SigninDialogDelegate(
DiceTurnSyncOnHelper::SigninChoiceCallback callback);
~SigninDialogDelegate() override;
void OnCancelSignin() override;
void OnContinueSignin() override;
void OnSigninWithNewProfile() override;
private:
DiceTurnSyncOnHelper::SigninChoiceCallback callback_;
DISALLOW_COPY_AND_ASSIGN(SigninDialogDelegate);
};
// DiceTurnSyncOnHelper::Delegate:
void ShowLoginError(const std::string& email,
const std::string& error_message) override;
void ShowMergeSyncDataConfirmation(
const std::string& previous_email,
const std::string& new_email,
DiceTurnSyncOnHelper::SigninChoiceCallback callback) override;
void ShowEnterpriseAccountConfirmation(
const std::string& email,
DiceTurnSyncOnHelper::SigninChoiceCallback callback) override;
void ShowSyncConfirmation(
base::OnceCallback<void(LoginUIService::SyncConfirmationUIClosedResult)>
callback) override;
void ShowSyncSettings() override;
void ShowSigninPageInNewProfile(Profile* new_profile,
const std::string& username) override;
// LoginUIService::Observer:
void OnSyncConfirmationUIClosed(
LoginUIService::SyncConfirmationUIClosedResult result) override;
// BrowserListObserver:
void OnBrowserRemoved(Browser* browser) override;
Browser* browser_;
Profile* profile_;
base::OnceCallback<void(LoginUIService::SyncConfirmationUIClosedResult)>
sync_confirmation_callback_;
ScopedObserver<BrowserList, BrowserListObserver>
scoped_browser_list_observer_;
ScopedObserver<LoginUIService, LoginUIService::Observer>
scoped_login_ui_service_observer_;
DISALLOW_COPY_AND_ASSIGN(DiceTurnSyncOnHelperDelegateImpl);
};
#endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_DICE_TURN_SYNC_ON_HELPER_DELEGATE_IMPL_H_
// Copyright 2018 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 "chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/policy/cloud/user_policy_signin_service.h"
#include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/account_tracker_service_factory.h"
#include "chrome/browser/signin/chrome_signin_client_factory.h"
#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
#include "chrome/browser/signin/fake_signin_manager_builder.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/signin/test_signin_client_builder.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/sync/profile_sync_test_util.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/browser_sync/test_profile_sync_service.h"
#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/scoped_account_consistency.h"
#include "components/signin/core/browser/signin_metrics.h"
#include "components/signin/core/browser/signin_pref_names.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
class DiceTurnSyncOnHelperTest;
namespace {
const char kEmail[] = "email@foo.com";
const char kPreviousEmail[] = "notme@bar.com";
const char kGaiaID[] = "gaia_id";
const signin_metrics::AccessPoint kAccessPoint =
signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER;
const signin_metrics::Reason kSigninReason =
signin_metrics::Reason::REASON_REAUTHENTICATION;
// Dummy delegate forwarding all the calls the test fixture.
// Owned by the DiceTurnOnSyncHelper.
class TestDiceTurnSyncOnHelperDelegate : public DiceTurnSyncOnHelper::Delegate {
public:
explicit TestDiceTurnSyncOnHelperDelegate(
DiceTurnSyncOnHelperTest* test_fixture);
~TestDiceTurnSyncOnHelperDelegate() override;
private:
// DiceTurnSyncOnHelper::Delegate:
void ShowLoginError(const std::string& email,
const std::string& error_message) override;
void ShowMergeSyncDataConfirmation(
const std::string& previous_email,
const std::string& new_email,
DiceTurnSyncOnHelper::SigninChoiceCallback callback) override;
void ShowEnterpriseAccountConfirmation(
const std::string& email,
DiceTurnSyncOnHelper::SigninChoiceCallback callback) override;
void ShowSyncConfirmation(
base::OnceCallback<void(LoginUIService::SyncConfirmationUIClosedResult)>
callback) override;
void ShowSyncSettings() override;
void ShowSigninPageInNewProfile(Profile* new_profile,
const std::string& username) override;
DiceTurnSyncOnHelperTest* test_fixture_;
};
// Simple ProfileManager creating testing profiles.
class UnittestProfileManager : public ProfileManagerWithoutInit {
public:
explicit UnittestProfileManager(const base::FilePath& user_data_dir)
: ProfileManagerWithoutInit(user_data_dir) {}
protected:
Profile* CreateProfileHelper(const base::FilePath& file_path) override {
if (!base::PathExists(file_path) && !base::CreateDirectory(file_path))
return nullptr;
return new TestingProfile(file_path, nullptr);
}
Profile* CreateProfileAsyncHelper(const base::FilePath& path,
Delegate* delegate) override {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(base::IgnoreResult(&base::CreateDirectory), path));
return new TestingProfile(path, this);
}
};
// Fake user policy signin service immediately invoking the callbacks.
class FakeUserPolicySigninService : public policy::UserPolicySigninService {
public:
// Static method to use with BrowserContextKeyedServiceFactory.
static std::unique_ptr<KeyedService> Build(content::BrowserContext* context) {
Profile* profile = Profile::FromBrowserContext(context);
return std::make_unique<FakeUserPolicySigninService>(
profile, SigninManagerFactory::GetForProfile(profile),
ProfileOAuth2TokenServiceFactory::GetForProfile(profile));
}
FakeUserPolicySigninService(Profile* profile,
SigninManager* signin_manager,
ProfileOAuth2TokenService* oauth2_token_service)
: UserPolicySigninService(profile,
nullptr,
nullptr,
nullptr,
signin_manager,
nullptr,
oauth2_token_service) {}
void set_dm_token(const std::string& dm_token) { dm_token_ = dm_token; }
void set_client_id(const std::string& client_id) { client_id_ = client_id; }
void set_account_id(const std::string& account_id) {
account_id_ = account_id;
}
// policy::UserPolicySigninService:
void RegisterForPolicyWithAccountId(
const std::string& username,
const std::string& account_id,
const PolicyRegistrationCallback& callback) override {
EXPECT_EQ(kEmail, username);
EXPECT_EQ(account_id_, account_id);
callback.Run(dm_token_, client_id_);
}
// policy::UserPolicySigninServiceBase:
void FetchPolicyForSignedInUser(
const std::string& username,
const std::string& dm_token,
const std::string& client_id,
scoped_refptr<net::URLRequestContextGetter> profile_request_context,
const PolicyFetchCallback& callback) override {
callback.Run(true);
}
private:
std::string dm_token_;
std::string client_id_;
std::string account_id_;
};
// Builds a fake sync service.
std::unique_ptr<KeyedService> BuildFakeSyncService(
content::BrowserContext* context) {
return std::make_unique<browser_sync::TestProfileSyncService>(
CreateProfileSyncServiceParamsForTest(
Profile::FromBrowserContext(context)));
}
} // namespace
class DiceTurnSyncOnHelperTest : public testing::Test {
public:
DiceTurnSyncOnHelperTest()
: local_state_(TestingBrowserProcess::GetGlobal()) {
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
TestingBrowserProcess::GetGlobal()->SetProfileManager(
new UnittestProfileManager(temp_dir_.GetPath()));
TestingProfile::Builder profile_builder;
profile_builder.AddTestingFactory(
ProfileOAuth2TokenServiceFactory::GetInstance(),
BuildFakeProfileOAuth2TokenService);
profile_builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
BuildFakeSigninManagerBase);
profile_builder.AddTestingFactory(ChromeSigninClientFactory::GetInstance(),
signin::BuildTestSigninClient);
profile_builder.AddTestingFactory(ProfileSyncServiceFactory::GetInstance(),
&BuildFakeSyncService);
profile_builder.AddTestingFactory(
policy::UserPolicySigninServiceFactory::GetInstance(),
&FakeUserPolicySigninService::Build);
profile_ = profile_builder.Build();
account_id_ =
AccountTrackerServiceFactory::GetForProfile(profile())->SeedAccountInfo(
kGaiaID, kEmail);
user_policy_signin_service_ = static_cast<FakeUserPolicySigninService*>(
policy::UserPolicySigninServiceFactory::GetForProfile(profile()));
user_policy_signin_service_->set_account_id(account_id_);
token_service_ = ProfileOAuth2TokenServiceFactory::GetForProfile(profile());
token_service_->UpdateCredentials(account_id_, "refresh_token");
signin_manager_ = SigninManagerFactory::GetForProfile(profile());
EXPECT_TRUE(token_service_->RefreshTokenIsAvailable(account_id_));
}
~DiceTurnSyncOnHelperTest() override {
DCHECK(delegate_destroyed_);
// Destroy extra profiles.
TestingBrowserProcess::GetGlobal()->SetProfileManager(nullptr);
base::RunLoop().RunUntilIdle();
}
// Basic accessors.
Profile* profile() { return profile_.get(); }
ProfileOAuth2TokenService* token_service() { return token_service_; }
SigninManager* signin_manager() { return signin_manager_; }
const std::string& account_id() { return account_id_; }
FakeUserPolicySigninService* user_policy_signin_service() {
return user_policy_signin_service_;
}
DiceTurnSyncOnHelper* CreateDiceTurnOnSyncHelper(
DiceTurnSyncOnHelper::SigninAbortedMode mode) {
return new DiceTurnSyncOnHelper(
profile(), kAccessPoint, kSigninReason, account_id_, mode,
std::make_unique<TestDiceTurnSyncOnHelperDelegate>(this));
}
void CheckDelegateCalls() {
EXPECT_EQ(expected_login_error_email_, login_error_email_);
EXPECT_EQ(expected_login_error_message_, login_error_message_);
EXPECT_EQ(expected_merge_data_previous_email_, merge_data_previous_email_);
EXPECT_EQ(expected_merge_data_new_email_, merge_data_new_email_);
EXPECT_EQ(expected_enterprise_confirmation_email_,
enterprise_confirmation_email_);
EXPECT_EQ(expected_new_profile_username_, new_profile_username_);
EXPECT_EQ(expected_sync_confirmation_shown_, sync_confirmation_shown_);
EXPECT_EQ(expected_sync_settings_shown_, sync_settings_shown_);
}
// Functions called by the DiceTurnSyncOnHelper::Delegate:
void OnShowLoginError(const std::string& email,
const std::string& error_message) {
EXPECT_FALSE(sync_confirmation_shown_);
EXPECT_FALSE(email.empty());
EXPECT_TRUE(login_error_email_.empty())
<< "Login error should be shown only once.";
login_error_email_ = email;
login_error_message_ = error_message; // May be empty.
}
void OnShowMergeSyncDataConfirmation(
const std::string& previous_email,
const std::string& new_email,
DiceTurnSyncOnHelper::SigninChoiceCallback callback) {
EXPECT_FALSE(sync_confirmation_shown_);
EXPECT_FALSE(previous_email.empty());
EXPECT_FALSE(new_email.empty());
EXPECT_TRUE(merge_data_previous_email_.empty())
<< "Merge data confirmation should be shown only once";
EXPECT_TRUE(merge_data_new_email_.empty())
<< "Merge data confirmation should be shown only once";
merge_data_previous_email_ = previous_email;
merge_data_new_email_ = new_email;
std::move(callback).Run(merge_data_choice_);
}
void OnShowEnterpriseAccountConfirmation(
const std::string& email,
DiceTurnSyncOnHelper::SigninChoiceCallback callback) {
EXPECT_FALSE(sync_confirmation_shown_);
EXPECT_FALSE(email.empty());
EXPECT_TRUE(enterprise_confirmation_email_.empty())
<< "Enterprise confirmation should be shown only once.";
enterprise_confirmation_email_ = email;
std::move(callback).Run(enterprise_choice_);
}
void OnShowSyncConfirmation(
base::OnceCallback<void(LoginUIService::SyncConfirmationUIClosedResult)>
callback) {
EXPECT_FALSE(sync_confirmation_shown_)
<< "Sync confirmation should be shown only once.";
sync_confirmation_shown_ = true;
std::move(callback).Run(sync_confirmation_result_);
}
void OnShowSyncSettings() {
EXPECT_TRUE(sync_confirmation_shown_)
<< "Must show sync confirmation first";
EXPECT_FALSE(sync_settings_shown_);
sync_settings_shown_ = true;
}
void OnShowSigninPageInNewProfile(Profile* new_profile,
const std::string& username) {
EXPECT_TRUE(new_profile);
EXPECT_NE(profile(), new_profile)
<< "new_profile should not be the existing profile";
EXPECT_FALSE(username.empty());
EXPECT_TRUE(new_profile_username_.empty())
<< "Signin page should be shown only once";
new_profile_username_ = username;
}
void OnDelegateDestroyed() { delegate_destroyed_ = true; }
protected:
// Delegate behavior.
DiceTurnSyncOnHelper::SigninChoice merge_data_choice_ =
DiceTurnSyncOnHelper::SIGNIN_CHOICE_CANCEL;
DiceTurnSyncOnHelper::SigninChoice enterprise_choice_ =
DiceTurnSyncOnHelper::SIGNIN_CHOICE_CANCEL;
LoginUIService::SyncConfirmationUIClosedResult sync_confirmation_result_ =
LoginUIService::SyncConfirmationUIClosedResult::ABORT_SIGNIN;
// Expected delegate calls.
std::string expected_login_error_email_;
std::string expected_login_error_message_;
std::string expected_enterprise_confirmation_email_;
std::string expected_merge_data_previous_email_;
std::string expected_merge_data_new_email_;
std::string expected_new_profile_username_;
bool expected_sync_confirmation_shown_ = false;
bool expected_sync_settings_shown_ = false;
private:
signin::ScopedAccountConsistencyDicePrepareMigration scoped_dice;
content::TestBrowserThreadBundle thread_bundle_;
base::ScopedTempDir temp_dir_;
ScopedTestingLocalState local_state_;
std::string account_id_;
std::unique_ptr<TestingProfile> profile_;
ProfileOAuth2TokenService* token_service_ = nullptr;
SigninManager* signin_manager_ = nullptr;
FakeUserPolicySigninService* user_policy_signin_service_ = nullptr;
// State of the delegate calls.
bool delegate_destroyed_ = false;
std::string login_error_email_;
std::string login_error_message_;
std::string enterprise_confirmation_email_;
std::string merge_data_previous_email_;
std::string merge_data_new_email_;
std::string new_profile_username_;
bool sync_confirmation_shown_ = false;
bool sync_settings_shown_ = false;
};
// TestDiceTurnSyncOnHelperDelegate implementation.
TestDiceTurnSyncOnHelperDelegate::TestDiceTurnSyncOnHelperDelegate(
DiceTurnSyncOnHelperTest* test_fixture)
: test_fixture_(test_fixture) {}
TestDiceTurnSyncOnHelperDelegate::~TestDiceTurnSyncOnHelperDelegate() {
test_fixture_->OnDelegateDestroyed();
}
void TestDiceTurnSyncOnHelperDelegate::ShowLoginError(
const std::string& email,
const std::string& error_message) {
test_fixture_->OnShowLoginError(email, error_message);
}
void TestDiceTurnSyncOnHelperDelegate::ShowMergeSyncDataConfirmation(
const std::string& previous_email,
const std::string& new_email,
DiceTurnSyncOnHelper::SigninChoiceCallback callback) {
test_fixture_->OnShowMergeSyncDataConfirmation(previous_email, new_email,
std::move(callback));
}
void TestDiceTurnSyncOnHelperDelegate::ShowEnterpriseAccountConfirmation(
const std::string& email,
DiceTurnSyncOnHelper::SigninChoiceCallback callback) {
test_fixture_->OnShowEnterpriseAccountConfirmation(email,
std::move(callback));
}
void TestDiceTurnSyncOnHelperDelegate::ShowSyncConfirmation(
base::OnceCallback<void(LoginUIService::SyncConfirmationUIClosedResult)>
callback) {
test_fixture_->OnShowSyncConfirmation(std::move(callback));
}
void TestDiceTurnSyncOnHelperDelegate::ShowSyncSettings() {
test_fixture_->OnShowSyncSettings();
}
void TestDiceTurnSyncOnHelperDelegate::ShowSigninPageInNewProfile(
Profile* new_profile,
const std::string& username) {
test_fixture_->OnShowSigninPageInNewProfile(new_profile, username);
}
// Tests that the login error is displayed and that the account is kept.
TEST_F(DiceTurnSyncOnHelperTest, CanOfferSigninErrorKeepAccount) {
// Set expectations.
expected_login_error_email_ = kEmail;
// Configure the test.
profile()->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false);
// Signin flow.
CreateDiceTurnOnSyncHelper(
DiceTurnSyncOnHelper::SigninAbortedMode::KEEP_ACCOUNT);
// Check expectations.
EXPECT_FALSE(signin_manager()->IsAuthenticated());
EXPECT_TRUE(token_service()->RefreshTokenIsAvailable(account_id()));
CheckDelegateCalls();
}
// Tests that the login error is displayed and that the account is removed.
TEST_F(DiceTurnSyncOnHelperTest, CanOfferSigninErrorRemoveAccount) {
// Set expectations.
expected_login_error_email_ = kEmail;
// Configure the test.
profile()->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false);
// Signin flow.
CreateDiceTurnOnSyncHelper(
DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT);
// Check expectations.
EXPECT_FALSE(signin_manager()->IsAuthenticated());
EXPECT_FALSE(token_service()->RefreshTokenIsAvailable(account_id()));
CheckDelegateCalls();
}
// Aborts the flow after the cross account dialog.
TEST_F(DiceTurnSyncOnHelperTest, CrossAccountAbort) {
// Set expectations.
expected_merge_data_previous_email_ = kPreviousEmail;
expected_merge_data_new_email_ = kEmail;
// Configure the test.
profile()->GetPrefs()->SetString(prefs::kGoogleServicesLastUsername,
kPreviousEmail);
// Signin flow.
CreateDiceTurnOnSyncHelper(
DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT);
// Check expectations.
EXPECT_FALSE(signin_manager()->IsAuthenticated());
EXPECT_FALSE(token_service()->RefreshTokenIsAvailable(account_id()));
CheckDelegateCalls();
}
// Merge data after the cross account dialog.
TEST_F(DiceTurnSyncOnHelperTest, CrossAccountContinue) {
// Set expectations.
expected_merge_data_previous_email_ = kPreviousEmail;
expected_merge_data_new_email_ = kEmail;
expected_sync_confirmation_shown_ = true;
// Configure the test.
merge_data_choice_ = DiceTurnSyncOnHelper::SIGNIN_CHOICE_CONTINUE;
profile()->GetPrefs()->SetString(prefs::kGoogleServicesLastUsername,
kPreviousEmail);
// Signin flow.
CreateDiceTurnOnSyncHelper(
DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT);
// Check expectations.
EXPECT_FALSE(signin_manager()->IsAuthenticated());
EXPECT_FALSE(token_service()->RefreshTokenIsAvailable(account_id()));
CheckDelegateCalls();
}
// Create a new profile after the cross account dialog and show the signin page.
TEST_F(DiceTurnSyncOnHelperTest, CrossAccountNewProfile) {
// Set expectations.
expected_merge_data_previous_email_ = kPreviousEmail;
expected_merge_data_new_email_ = kEmail;
expected_new_profile_username_ = kEmail;
// Configure the test.
merge_data_choice_ = DiceTurnSyncOnHelper::SIGNIN_CHOICE_NEW_PROFILE;
profile()->GetPrefs()->SetString(prefs::kGoogleServicesLastUsername,
kPreviousEmail);
// Signin flow.
CreateDiceTurnOnSyncHelper(
DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT);
// Check expectations.
base::RunLoop().RunUntilIdle(); // Profile creation is asynchronous.
EXPECT_FALSE(signin_manager()->IsAuthenticated());
EXPECT_FALSE(token_service()->RefreshTokenIsAvailable(account_id()));
CheckDelegateCalls();
}
// Abort after the enterprise confirmation prompt.
TEST_F(DiceTurnSyncOnHelperTest, EnterpriseConfirmationAbort) {
// Set expectations.
expected_enterprise_confirmation_email_ = kEmail;
// Configure the test.
user_policy_signin_service()->set_dm_token("foo");
user_policy_signin_service()->set_client_id("bar");
// Signin flow.
CreateDiceTurnOnSyncHelper(
DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT);
// Check expectations.
EXPECT_FALSE(signin_manager()->IsAuthenticated());
EXPECT_FALSE(token_service()->RefreshTokenIsAvailable(account_id()));
CheckDelegateCalls();
}
// Continue after the enterprise confirmation prompt.
TEST_F(DiceTurnSyncOnHelperTest, EnterpriseConfirmationContinue) {
// Set expectations.
expected_enterprise_confirmation_email_ = kEmail;
expected_sync_confirmation_shown_ = true;
// Configure the test.
user_policy_signin_service()->set_dm_token("foo");
user_policy_signin_service()->set_client_id("bar");
enterprise_choice_ = DiceTurnSyncOnHelper::SIGNIN_CHOICE_CONTINUE;
// Signin flow.
CreateDiceTurnOnSyncHelper(
DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT);
// Check expectations.
EXPECT_FALSE(signin_manager()->IsAuthenticated());
EXPECT_FALSE(token_service()->RefreshTokenIsAvailable(account_id()));
CheckDelegateCalls();
}
// Continue with a new profile after the enterprise confirmation prompt.
TEST_F(DiceTurnSyncOnHelperTest, EnterpriseConfirmationNewProfile) {
// Set expectations.
expected_enterprise_confirmation_email_ = kEmail;
expected_new_profile_username_ = kEmail;
// Configure the test.
user_policy_signin_service()->set_dm_token("foo");
user_policy_signin_service()->set_client_id("bar");
enterprise_choice_ = DiceTurnSyncOnHelper::SIGNIN_CHOICE_NEW_PROFILE;
// Signin flow.
CreateDiceTurnOnSyncHelper(
DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT);
// Check expectations.
base::RunLoop().RunUntilIdle(); // Profile creation is asynchronous.
EXPECT_FALSE(signin_manager()->IsAuthenticated());
EXPECT_FALSE(token_service()->RefreshTokenIsAvailable(account_id()));
CheckDelegateCalls();
}
// Tests that the sync confirmation is shown and the user can abort.
TEST_F(DiceTurnSyncOnHelperTest, UndoSync) {
// Set expectations.
expected_sync_confirmation_shown_ = true;
// Signin flow.
browser_sync::ProfileSyncService* sync_service =
ProfileSyncServiceFactory::GetForProfile(profile());
EXPECT_FALSE(signin_manager()->IsAuthenticated());
EXPECT_FALSE(sync_service->IsFirstSetupComplete());
CreateDiceTurnOnSyncHelper(
DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT);
// Check expectations.
EXPECT_FALSE(signin_manager()->IsAuthenticated());
EXPECT_FALSE(token_service()->RefreshTokenIsAvailable(account_id()));
EXPECT_FALSE(sync_service->IsFirstSetupComplete());
CheckDelegateCalls();
}
// Tests that the sync settings page is shown.
TEST_F(DiceTurnSyncOnHelperTest, ConfigureSync) {
// Set expectations.
expected_sync_confirmation_shown_ = true;
expected_sync_settings_shown_ = true;
// Configure the test.
sync_confirmation_result_ =
LoginUIService::SyncConfirmationUIClosedResult::CONFIGURE_SYNC_FIRST;
// Signin flow.
browser_sync::ProfileSyncService* sync_service =
ProfileSyncServiceFactory::GetForProfile(profile());
EXPECT_FALSE(signin_manager()->IsAuthenticated());
EXPECT_FALSE(sync_service->IsFirstSetupComplete());
CreateDiceTurnOnSyncHelper(
DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT);
// Check expectations.
EXPECT_TRUE(signin_manager()->IsAuthenticated());
EXPECT_FALSE(sync_service->IsFirstSetupComplete());
EXPECT_TRUE(token_service()->RefreshTokenIsAvailable(account_id()));
CheckDelegateCalls();
}
// Tests that the user is signed in and Sync configuration is complete.
TEST_F(DiceTurnSyncOnHelperTest, StartSync) {
// Set expectations.
expected_sync_confirmation_shown_ = true;
// Configure the test.
sync_confirmation_result_ = LoginUIService::SyncConfirmationUIClosedResult::
SYNC_WITH_DEFAULT_SETTINGS;
// Signin flow.
browser_sync::ProfileSyncService* sync_service =
ProfileSyncServiceFactory::GetForProfile(profile());
EXPECT_FALSE(signin_manager()->IsAuthenticated());
EXPECT_FALSE(sync_service->IsFirstSetupComplete());
CreateDiceTurnOnSyncHelper(
DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT);
// Check expectations.
EXPECT_TRUE(token_service()->RefreshTokenIsAvailable(account_id()));
EXPECT_EQ(account_id(), signin_manager()->GetAuthenticatedAccountId());
EXPECT_TRUE(sync_service->IsFirstSetupComplete());
CheckDelegateCalls();
}
...@@ -2720,6 +2720,7 @@ test("unit_tests") { ...@@ -2720,6 +2720,7 @@ test("unit_tests") {
"../browser/signin/dice_response_handler_unittest.cc", "../browser/signin/dice_response_handler_unittest.cc",
"../browser/signin/dice_tab_helper_unittest.cc", "../browser/signin/dice_tab_helper_unittest.cc",
"../browser/signin/process_dice_header_delegate_impl_unittest.cc", "../browser/signin/process_dice_header_delegate_impl_unittest.cc",
"../browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc",
] ]
} }
......
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