summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/signin/e2e_tests
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/browser/signin/e2e_tests')
-rw-r--r--chromium/chrome/browser/signin/e2e_tests/live_sign_in_test.cc776
-rw-r--r--chromium/chrome/browser/signin/e2e_tests/live_test.cc61
-rw-r--r--chromium/chrome/browser/signin/e2e_tests/live_test.h33
-rw-r--r--chromium/chrome/browser/signin/e2e_tests/test_accounts_util.cc75
-rw-r--r--chromium/chrome/browser/signin/e2e_tests/test_accounts_util.h46
-rw-r--r--chromium/chrome/browser/signin/e2e_tests/test_accounts_util_unittest.cc100
6 files changed, 1091 insertions, 0 deletions
diff --git a/chromium/chrome/browser/signin/e2e_tests/live_sign_in_test.cc b/chromium/chrome/browser/signin/e2e_tests/live_sign_in_test.cc
new file mode 100644
index 00000000000..3e042e76b87
--- /dev/null
+++ b/chromium/chrome/browser/signin/e2e_tests/live_sign_in_test.cc
@@ -0,0 +1,776 @@
+// Copyright 2019 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 "base/memory/raw_ptr.h"
+#include "base/run_loop.h"
+#include "base/scoped_observation.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/signin/account_reconcilor_factory.h"
+#include "chrome/browser/signin/e2e_tests/live_test.h"
+#include "chrome/browser/signin/e2e_tests/test_accounts_util.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/browser/sync/sync_service_factory.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
+#include "chrome/browser/ui/webui/signin/login_ui_test_utils.h"
+#include "chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/signin/core/browser/account_reconcilor.h"
+#include "components/signin/public/base/consent_level.h"
+#include "components/signin/public/identity_manager/account_capabilities.h"
+#include "components/signin/public/identity_manager/account_info.h"
+#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_test_utils.h"
+#include "components/signin/public/identity_manager/tribool.h"
+#include "components/sync/driver/sync_service.h"
+#include "content/public/test/browser_test.h"
+#include "google_apis/gaia/core_account_id.h"
+#include "google_apis/gaia/gaia_auth_util.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "ui/compositor/scoped_animation_duration_scale_mode.h"
+
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+#include "chrome/browser/sync/sync_ui_util.h"
+#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
+
+namespace signin {
+namespace test {
+
+const base::TimeDelta kDialogTimeout = base::Seconds(10);
+
+// A wrapper importing the settings module when the chrome://settings serve the
+// Polymer 3 version.
+const char kSettingsScriptWrapperFormat[] =
+ "import('./settings.js').then(settings => {%s});";
+
+enum class PrimarySyncAccountWait { kWaitForAdded, kWaitForCleared, kNotWait };
+
+// Observes various sign-in events and allows to wait for a specific state of
+// signed-in accounts.
+class SignInTestObserver : public IdentityManager::Observer,
+ public AccountReconcilor::Observer {
+ public:
+ explicit SignInTestObserver(IdentityManager* identity_manager,
+ AccountReconcilor* reconcilor)
+ : identity_manager_(identity_manager), reconcilor_(reconcilor) {
+ identity_manager_observation_.Observe(identity_manager_.get());
+ account_reconcilor_observation_.Observe(reconcilor_.get());
+ }
+ ~SignInTestObserver() override = default;
+
+ // IdentityManager::Observer:
+ void OnPrimaryAccountChanged(
+ const PrimaryAccountChangeEvent& event) override {
+ if (event.GetEventTypeFor(ConsentLevel::kSync) ==
+ PrimaryAccountChangeEvent::Type::kNone) {
+ return;
+ }
+ QuitIfConditionIsSatisfied();
+ }
+ void OnRefreshTokenUpdatedForAccount(const CoreAccountInfo&) override {
+ QuitIfConditionIsSatisfied();
+ }
+ void OnRefreshTokenRemovedForAccount(const CoreAccountId&) override {
+ QuitIfConditionIsSatisfied();
+ }
+ void OnErrorStateOfRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo&,
+ const GoogleServiceAuthError&) override {
+ QuitIfConditionIsSatisfied();
+ }
+ void OnAccountsInCookieUpdated(const AccountsInCookieJarInfo&,
+ const GoogleServiceAuthError&) override {
+ QuitIfConditionIsSatisfied();
+ }
+
+ // AccountReconcilor::Observer:
+ // TODO(https://crbug.com/1051864): Remove this obsever method once the bug is
+ // fixed.
+ void OnStateChanged(signin_metrics::AccountReconcilorState state) override {
+ if (state == signin_metrics::ACCOUNT_RECONCILOR_OK) {
+ // This will trigger cookie update if accounts are stale.
+ identity_manager_->GetAccountsInCookieJar();
+ }
+ }
+
+ void WaitForAccountChanges(int signed_in_accounts,
+ PrimarySyncAccountWait primary_sync_account_wait) {
+ expected_signed_in_accounts_ = signed_in_accounts;
+ primary_sync_account_wait_ = primary_sync_account_wait;
+ are_expectations_set = true;
+ QuitIfConditionIsSatisfied();
+ run_loop_.Run();
+ }
+
+ private:
+ void QuitIfConditionIsSatisfied() {
+ if (!are_expectations_set)
+ return;
+
+ int accounts_with_valid_refresh_token =
+ CountAccountsWithValidRefreshToken();
+ int accounts_in_cookie = CountSignedInAccountsInCookie();
+
+ if (accounts_with_valid_refresh_token != accounts_in_cookie ||
+ accounts_with_valid_refresh_token != expected_signed_in_accounts_) {
+ return;
+ }
+
+ switch (primary_sync_account_wait_) {
+ case PrimarySyncAccountWait::kWaitForAdded:
+ if (!HasValidPrimarySyncAccount())
+ return;
+ break;
+ case PrimarySyncAccountWait::kWaitForCleared:
+ if (identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSync))
+ return;
+ break;
+ case PrimarySyncAccountWait::kNotWait:
+ break;
+ }
+
+ run_loop_.Quit();
+ }
+
+ int CountAccountsWithValidRefreshToken() const {
+ std::vector<CoreAccountInfo> accounts_with_refresh_tokens =
+ identity_manager_->GetAccountsWithRefreshTokens();
+ int valid_accounts = 0;
+ for (const auto& account_info : accounts_with_refresh_tokens) {
+ if (!identity_manager_->HasAccountWithRefreshTokenInPersistentErrorState(
+ account_info.account_id)) {
+ ++valid_accounts;
+ }
+ }
+ return valid_accounts;
+ }
+
+ int CountSignedInAccountsInCookie() const {
+ signin::AccountsInCookieJarInfo accounts_in_cookie_jar =
+ identity_manager_->GetAccountsInCookieJar();
+ if (!accounts_in_cookie_jar.accounts_are_fresh)
+ return -1;
+
+ return accounts_in_cookie_jar.signed_in_accounts.size();
+ }
+
+ bool HasValidPrimarySyncAccount() const {
+ CoreAccountId primary_account_id =
+ identity_manager_->GetPrimaryAccountId(signin::ConsentLevel::kSync);
+ if (primary_account_id.empty())
+ return false;
+
+ return !identity_manager_->HasAccountWithRefreshTokenInPersistentErrorState(
+ primary_account_id);
+ }
+
+ const raw_ptr<signin::IdentityManager> identity_manager_;
+ const raw_ptr<AccountReconcilor> reconcilor_;
+ base::ScopedObservation<IdentityManager, IdentityManager::Observer>
+ identity_manager_observation_{this};
+ base::ScopedObservation<AccountReconcilor, AccountReconcilor::Observer>
+ account_reconcilor_observation_{this};
+ base::RunLoop run_loop_;
+
+ bool are_expectations_set = false;
+ int expected_signed_in_accounts_ = 0;
+ PrimarySyncAccountWait primary_sync_account_wait_ =
+ PrimarySyncAccountWait::kNotWait;
+};
+
+// Observer class allowing to wait for account capabilities to be known.
+class AccountCapabilitiesObserver : public IdentityManager::Observer {
+ public:
+ explicit AccountCapabilitiesObserver(IdentityManager* identity_manager)
+ : identity_manager_(identity_manager) {
+ identity_manager_observation_.Observe(identity_manager);
+ }
+
+ // IdentityManager::Observer:
+ void OnExtendedAccountInfoUpdated(const AccountInfo& info) override {
+ if (info.account_id != account_id_)
+ return;
+
+ if (info.capabilities.AreAllCapabilitiesKnown())
+ run_loop_.Quit();
+ }
+
+ // This should be called only once per AccountCapabilitiesObserver instance.
+ void WaitForAllCapabilitiesToBeKnown(CoreAccountId account_id) {
+ DCHECK(identity_manager_observation_.IsObservingSource(
+ identity_manager_.get()));
+ AccountInfo info =
+ identity_manager_->FindExtendedAccountInfoByAccountId(account_id);
+ if (info.capabilities.AreAllCapabilitiesKnown())
+ return;
+
+ account_id_ = account_id;
+ run_loop_.Run();
+ identity_manager_observation_.Reset();
+ }
+
+ private:
+ raw_ptr<IdentityManager> identity_manager_ = nullptr;
+ CoreAccountId account_id_;
+ base::RunLoop run_loop_;
+ base::ScopedObservation<IdentityManager, IdentityManager::Observer>
+ identity_manager_observation_{this};
+};
+
+// Live tests for SignIn.
+// These tests can be run with:
+// browser_tests --gtest_filter=LiveSignInTest.* --run-live-tests --run-manual
+class LiveSignInTest : public signin::test::LiveTest {
+ public:
+ LiveSignInTest() = default;
+ ~LiveSignInTest() override = default;
+
+ void SetUp() override {
+ LiveTest::SetUp();
+ // Always disable animation for stability.
+ ui::ScopedAnimationDurationScaleMode disable_animation(
+ ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
+ }
+
+ void SignInFromWeb(const TestAccount& test_account,
+ int previously_signed_in_accounts) {
+ AddTabAtIndex(0, GaiaUrls::GetInstance()->add_account_url(),
+ ui::PageTransition::PAGE_TRANSITION_TYPED);
+ SignInFromCurrentPage(test_account, previously_signed_in_accounts);
+ }
+
+ void SignInFromSettings(const TestAccount& test_account,
+ int previously_signed_in_accounts) {
+ GURL settings_url("chrome://settings");
+ AddTabAtIndex(0, settings_url, ui::PageTransition::PAGE_TRANSITION_TYPED);
+ auto* settings_tab = browser()->tab_strip_model()->GetActiveWebContents();
+ EXPECT_TRUE(content::ExecuteScript(
+ settings_tab,
+ base::StringPrintf(
+ kSettingsScriptWrapperFormat,
+ "settings.SyncBrowserProxyImpl.getInstance().startSignIn();")));
+ SignInFromCurrentPage(test_account, previously_signed_in_accounts);
+ }
+
+ void SignInFromCurrentPage(const TestAccount& test_account,
+ int previously_signed_in_accounts) {
+ SignInTestObserver observer(identity_manager(), account_reconcilor());
+ login_ui_test_utils::ExecuteJsToSigninInSigninFrame(
+ browser(), test_account.user, test_account.password);
+ observer.WaitForAccountChanges(previously_signed_in_accounts + 1,
+ PrimarySyncAccountWait::kNotWait);
+ }
+
+ void TurnOnSync(const TestAccount& test_account,
+ int previously_signed_in_accounts) {
+ SignInFromSettings(test_account, previously_signed_in_accounts);
+
+ SignInTestObserver observer(identity_manager(), account_reconcilor());
+ EXPECT_TRUE(login_ui_test_utils::ConfirmSyncConfirmationDialog(
+ browser(), kDialogTimeout));
+ observer.WaitForAccountChanges(previously_signed_in_accounts + 1,
+ PrimarySyncAccountWait::kWaitForAdded);
+ }
+
+ void SignOutFromWeb() {
+ SignInTestObserver observer(identity_manager(), account_reconcilor());
+ AddTabAtIndex(0, GaiaUrls::GetInstance()->service_logout_url(),
+ ui::PageTransition::PAGE_TRANSITION_TYPED);
+ observer.WaitForAccountChanges(0, PrimarySyncAccountWait::kNotWait);
+ }
+
+ void TurnOffSync() {
+ GURL settings_url("chrome://settings");
+ AddTabAtIndex(0, settings_url, ui::PageTransition::PAGE_TRANSITION_TYPED);
+ SignInTestObserver observer(identity_manager(), account_reconcilor());
+ auto* settings_tab = browser()->tab_strip_model()->GetActiveWebContents();
+ EXPECT_TRUE(content::ExecuteScript(
+ settings_tab,
+ base::StringPrintf(
+ kSettingsScriptWrapperFormat,
+ "settings.SyncBrowserProxyImpl.getInstance().signOut(false)")));
+ observer.WaitForAccountChanges(0, PrimarySyncAccountWait::kWaitForCleared);
+ }
+
+ signin::IdentityManager* identity_manager() {
+ return identity_manager(browser());
+ }
+
+ signin::IdentityManager* identity_manager(Browser* browser) {
+ return IdentityManagerFactory::GetForProfile(browser->profile());
+ }
+
+ syncer::SyncService* sync_service() { return sync_service(browser()); }
+
+ syncer::SyncService* sync_service(Browser* browser) {
+ return SyncServiceFactory::GetForProfile(browser->profile());
+ }
+
+ AccountReconcilor* account_reconcilor() {
+ return account_reconcilor(browser());
+ }
+
+ AccountReconcilor* account_reconcilor(Browser* browser) {
+ return AccountReconcilorFactory::GetForProfile(browser->profile());
+ }
+};
+
+// This test can pass. Marked as manual because it TIMED_OUT on Win7.
+// See crbug.com/1025335.
+// Sings in an account through the settings page and checks that the account is
+// added to Chrome. Sync should be disabled because the test doesn't pass
+// through the Sync confirmation dialog.
+IN_PROC_BROWSER_TEST_F(LiveSignInTest, MANUAL_SimpleSignInFlow) {
+ TestAccount ta;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", ta));
+ SignInFromSettings(ta, 0);
+
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_TRUE(accounts_in_cookie_jar.accounts_are_fresh);
+ ASSERT_EQ(1u, accounts_in_cookie_jar.signed_in_accounts.size());
+ EXPECT_TRUE(accounts_in_cookie_jar.signed_out_accounts.empty());
+ const gaia::ListedAccount& account =
+ accounts_in_cookie_jar.signed_in_accounts[0];
+ EXPECT_TRUE(gaia::AreEmailsSame(ta.user, account.email));
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account.id));
+ EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());
+}
+
+// This test can pass. Marked as manual because it TIMED_OUT on Win7.
+// See crbug.com/1025335.
+// Signs in an account through the settings page and enables Sync. Checks that
+// Sync is enabled.
+// Then, signs out on the web and checks that the account is removed from
+// cookies and Sync paused error is displayed.
+IN_PROC_BROWSER_TEST_F(LiveSignInTest, MANUAL_WebSignOut) {
+ TestAccount test_account;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account));
+ TurnOnSync(test_account, 0);
+
+ const CoreAccountInfo& primary_account =
+ identity_manager()->GetPrimaryAccountInfo(signin::ConsentLevel::kSync);
+ EXPECT_FALSE(primary_account.IsEmpty());
+ EXPECT_TRUE(gaia::AreEmailsSame(test_account.user, primary_account.email));
+ EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
+
+ SignOutFromWeb();
+
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_TRUE(accounts_in_cookie_jar.accounts_are_fresh);
+ ASSERT_TRUE(accounts_in_cookie_jar.signed_in_accounts.empty());
+ ASSERT_EQ(1u, accounts_in_cookie_jar.signed_out_accounts.size());
+ EXPECT_TRUE(gaia::AreEmailsSame(
+ test_account.user, accounts_in_cookie_jar.signed_out_accounts[0].email));
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ primary_account.account_id));
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+ EXPECT_EQ(GetAvatarSyncErrorType(browser()->profile()),
+ AvatarSyncErrorType::kAuthError);
+#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
+}
+
+// This test can pass. Marked as manual because it TIMED_OUT on Win7.
+// See crbug.com/1025335.
+// Sings in two accounts on the web and checks that cookies and refresh tokens
+// are added to Chrome. Sync should be disabled.
+// Then, signs out on the web and checks that accounts are removed from Chrome.
+IN_PROC_BROWSER_TEST_F(LiveSignInTest, MANUAL_WebSignInAndSignOut) {
+ TestAccount test_account_1;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account_1));
+ SignInFromWeb(test_account_1, 0);
+
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_1 =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_TRUE(accounts_in_cookie_jar_1.accounts_are_fresh);
+ ASSERT_EQ(1u, accounts_in_cookie_jar_1.signed_in_accounts.size());
+ EXPECT_TRUE(accounts_in_cookie_jar_1.signed_out_accounts.empty());
+ const gaia::ListedAccount& account_1 =
+ accounts_in_cookie_jar_1.signed_in_accounts[0];
+ EXPECT_TRUE(gaia::AreEmailsSame(test_account_1.user, account_1.email));
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_1.id));
+ EXPECT_FALSE(
+ identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSync));
+
+ TestAccount test_account_2;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_2", test_account_2));
+ SignInFromWeb(test_account_2, 1);
+
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_2 =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_TRUE(accounts_in_cookie_jar_2.accounts_are_fresh);
+ ASSERT_EQ(2u, accounts_in_cookie_jar_2.signed_in_accounts.size());
+ EXPECT_TRUE(accounts_in_cookie_jar_2.signed_out_accounts.empty());
+ EXPECT_EQ(accounts_in_cookie_jar_2.signed_in_accounts[0].id, account_1.id);
+ const gaia::ListedAccount& account_2 =
+ accounts_in_cookie_jar_2.signed_in_accounts[1];
+ EXPECT_TRUE(gaia::AreEmailsSame(test_account_2.user, account_2.email));
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_2.id));
+ EXPECT_FALSE(
+ identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSync));
+
+ SignOutFromWeb();
+
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_3 =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_TRUE(accounts_in_cookie_jar_3.accounts_are_fresh);
+ ASSERT_TRUE(accounts_in_cookie_jar_3.signed_in_accounts.empty());
+ EXPECT_EQ(2u, accounts_in_cookie_jar_3.signed_out_accounts.size());
+ EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
+}
+
+// This test can pass. Marked as manual because it TIMED_OUT on Win7.
+// See crbug.com/1025335.
+// Signs in an account through the settings page and enables Sync. Checks that
+// Sync is enabled. Signs in a second account on the web.
+// Then, turns Sync off from the settings page and checks that both accounts are
+// removed from Chrome and from cookies.
+IN_PROC_BROWSER_TEST_F(LiveSignInTest, MANUAL_TurnOffSync) {
+ TestAccount test_account_1;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account_1));
+ TurnOnSync(test_account_1, 0);
+
+ TestAccount test_account_2;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_2", test_account_2));
+ SignInFromWeb(test_account_2, 1);
+
+ const CoreAccountInfo& primary_account =
+ identity_manager()->GetPrimaryAccountInfo(signin::ConsentLevel::kSync);
+ EXPECT_FALSE(primary_account.IsEmpty());
+ EXPECT_TRUE(gaia::AreEmailsSame(test_account_1.user, primary_account.email));
+ EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
+
+ TurnOffSync();
+
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_2 =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_TRUE(accounts_in_cookie_jar_2.accounts_are_fresh);
+ ASSERT_TRUE(accounts_in_cookie_jar_2.signed_in_accounts.empty());
+ EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
+ EXPECT_FALSE(
+ identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSync));
+}
+
+// In "Sync paused" state, when the primary account is invalid, turns off sync
+// from settings. Checks that the account is removed from Chrome.
+// Regression test for https://crbug.com/1114646
+IN_PROC_BROWSER_TEST_F(LiveSignInTest, MANUAL_TurnOffSyncWhenPaused) {
+ TestAccount test_account_1;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account_1));
+ TurnOnSync(test_account_1, 0);
+
+ // Get in sync paused state.
+ SignOutFromWeb();
+
+ const CoreAccountInfo& primary_account =
+ identity_manager()->GetPrimaryAccountInfo(signin::ConsentLevel::kSync);
+ EXPECT_FALSE(primary_account.IsEmpty());
+ EXPECT_TRUE(gaia::AreEmailsSame(test_account_1.user, primary_account.email));
+ EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
+ EXPECT_TRUE(
+ identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
+ primary_account.account_id));
+
+ TurnOffSync();
+ EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
+ EXPECT_FALSE(
+ identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSync));
+}
+
+// This test can pass. Marked as manual because it TIMED_OUT on Win7.
+// See crbug.com/1025335.
+// Signs in an account on the web. Goes to the Chrome settings to enable Sync
+// but cancels the sync confirmation dialog. Checks that the account is still
+// signed in on the web but Sync is disabled.
+IN_PROC_BROWSER_TEST_F(LiveSignInTest, MANUAL_CancelSyncWithWebAccount) {
+ TestAccount test_account;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account));
+ SignInFromWeb(test_account, 0);
+
+ SignInTestObserver observer(identity_manager(), account_reconcilor());
+ GURL settings_url("chrome://settings");
+ AddTabAtIndex(0, settings_url, ui::PageTransition::PAGE_TRANSITION_TYPED);
+ auto* settings_tab = browser()->tab_strip_model()->GetActiveWebContents();
+ std::string start_syncing_script = base::StringPrintf(
+ "settings.SyncBrowserProxyImpl.getInstance()."
+ "startSyncingWithEmail(\"%s\", true);",
+ test_account.user.c_str());
+ EXPECT_TRUE(content::ExecuteScript(
+ settings_tab, base::StringPrintf(kSettingsScriptWrapperFormat,
+ start_syncing_script.c_str())));
+ EXPECT_TRUE(login_ui_test_utils::CancelSyncConfirmationDialog(
+ browser(), kDialogTimeout));
+ observer.WaitForAccountChanges(1, PrimarySyncAccountWait::kWaitForCleared);
+
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_TRUE(accounts_in_cookie_jar.accounts_are_fresh);
+ ASSERT_EQ(1u, accounts_in_cookie_jar.signed_in_accounts.size());
+ const gaia::ListedAccount& account =
+ accounts_in_cookie_jar.signed_in_accounts[0];
+ EXPECT_TRUE(gaia::AreEmailsSame(test_account.user, account.email));
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account.id));
+ EXPECT_FALSE(
+ identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSync));
+}
+
+// This test can pass. Marked as manual because it TIMED_OUT on Win7.
+// See crbug.com/1025335.
+// Starts the sign in flow from the settings page, enters credentials on the
+// login page but cancels the Sync confirmation dialog. Checks that Sync is
+// disabled and no account was added to Chrome.
+IN_PROC_BROWSER_TEST_F(LiveSignInTest, MANUAL_CancelSync) {
+ TestAccount test_account;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account));
+ SignInFromSettings(test_account, 0);
+
+ SignInTestObserver observer(identity_manager(), account_reconcilor());
+ EXPECT_TRUE(login_ui_test_utils::CancelSyncConfirmationDialog(
+ browser(), kDialogTimeout));
+ observer.WaitForAccountChanges(0, PrimarySyncAccountWait::kWaitForCleared);
+
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_TRUE(accounts_in_cookie_jar.accounts_are_fresh);
+ EXPECT_TRUE(accounts_in_cookie_jar.signed_in_accounts.empty());
+ EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
+ EXPECT_FALSE(
+ identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSync));
+}
+
+// This test can pass. Marked as manual because it TIMED_OUT on Win7.
+// See crbug.com/1025335.
+// Enables and disables sync to account 1. Enables sync to account 2 and clicks
+// on "This wasn't me" in the email confirmation dialog. Checks that the new
+// profile is created. Checks that Sync to account 2 is enabled in the new
+// profile. Checks that account 2 was removed from the original profile.
+IN_PROC_BROWSER_TEST_F(LiveSignInTest,
+ MANUAL_SyncSecondAccount_CreateNewProfile) {
+ // Enable and disable sync for the first account.
+ TestAccount test_account_1;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account_1));
+ TurnOnSync(test_account_1, 0);
+ TurnOffSync();
+
+ // Start enable sync for the second account.
+ TestAccount test_account_2;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_2", test_account_2));
+ SignInFromSettings(test_account_2, 0);
+
+ // Set up an observer for removing the second account from the original
+ // profile.
+ SignInTestObserver original_browser_observer(identity_manager(),
+ account_reconcilor());
+
+ // Check there is only one profile.
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 1U);
+ EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U);
+
+ // Click "This wasn't me" on the email confirmation dialog and wait for a new
+ // browser and profile created.
+ EXPECT_TRUE(login_ui_test_utils::CompleteSigninEmailConfirmationDialog(
+ browser(), kDialogTimeout,
+ SigninEmailConfirmationDialog::CREATE_NEW_USER));
+ Browser* new_browser = ui_test_utils::WaitForBrowserToOpen();
+ EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 2U);
+ EXPECT_EQ(chrome::GetTotalBrowserCount(), 2U);
+ EXPECT_NE(browser()->profile(), new_browser->profile());
+
+ // Confirm sync in the new browser window.
+ SignInTestObserver new_browser_observer(identity_manager(new_browser),
+ account_reconcilor(new_browser));
+ EXPECT_TRUE(login_ui_test_utils::ConfirmSyncConfirmationDialog(
+ new_browser, kDialogTimeout));
+ new_browser_observer.WaitForAccountChanges(
+ 1, PrimarySyncAccountWait::kWaitForAdded);
+
+ // Check accounts in cookies in the new profile.
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar =
+ identity_manager(new_browser)->GetAccountsInCookieJar();
+ EXPECT_TRUE(accounts_in_cookie_jar.accounts_are_fresh);
+ ASSERT_EQ(1u, accounts_in_cookie_jar.signed_in_accounts.size());
+ const gaia::ListedAccount& account =
+ accounts_in_cookie_jar.signed_in_accounts[0];
+ EXPECT_TRUE(gaia::AreEmailsSame(test_account_2.user, account.email));
+
+ // Check the primary account in the new profile is set and syncing.
+ const CoreAccountInfo& primary_account =
+ identity_manager(new_browser)
+ ->GetPrimaryAccountInfo(signin::ConsentLevel::kSync);
+ EXPECT_FALSE(primary_account.IsEmpty());
+ EXPECT_TRUE(gaia::AreEmailsSame(test_account_2.user, primary_account.email));
+ EXPECT_TRUE(identity_manager(new_browser)
+ ->HasAccountWithRefreshToken(primary_account.account_id));
+ EXPECT_TRUE(sync_service(new_browser)->IsSyncFeatureEnabled());
+
+ // Check that the second account was removed from the original profile.
+ original_browser_observer.WaitForAccountChanges(
+ 0, PrimarySyncAccountWait::kWaitForCleared);
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar_2 =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_TRUE(accounts_in_cookie_jar_2.accounts_are_fresh);
+ ASSERT_TRUE(accounts_in_cookie_jar_2.signed_in_accounts.empty());
+ EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
+ EXPECT_FALSE(
+ identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSync));
+}
+
+// This test can pass. Marked as manual because it TIMED_OUT on Win7.
+// See crbug.com/1025335.
+// Enables and disables sync to account 1. Enables sync to account 2 and clicks
+// on "This was me" in the email confirmation dialog. Checks that Sync to
+// account 2 is enabled in the current profile.
+IN_PROC_BROWSER_TEST_F(LiveSignInTest,
+ MANUAL_SyncSecondAccount_InExistingProfile) {
+ // Enable and disable sync for the first account.
+ TestAccount test_account_1;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account_1));
+ TurnOnSync(test_account_1, 0);
+ TurnOffSync();
+
+ // Start enable sync for the second account.
+ TestAccount test_account_2;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_2", test_account_2));
+ SignInFromSettings(test_account_2, 0);
+
+ // Check there is only one profile.
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 1U);
+ EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U);
+
+ // Click "This was me" on the email confirmation dialog, confirm sync and wait
+ // for a primary account to be set.
+ SignInTestObserver observer(identity_manager(), account_reconcilor());
+ EXPECT_TRUE(login_ui_test_utils::CompleteSigninEmailConfirmationDialog(
+ browser(), kDialogTimeout, SigninEmailConfirmationDialog::START_SYNC));
+ EXPECT_TRUE(login_ui_test_utils::ConfirmSyncConfirmationDialog(
+ browser(), kDialogTimeout));
+ observer.WaitForAccountChanges(1, PrimarySyncAccountWait::kWaitForAdded);
+
+ // Check no profile was created.
+ EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 1U);
+ EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U);
+
+ // Check accounts in cookies.
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_TRUE(accounts_in_cookie_jar.accounts_are_fresh);
+ ASSERT_EQ(1u, accounts_in_cookie_jar.signed_in_accounts.size());
+ const gaia::ListedAccount& account =
+ accounts_in_cookie_jar.signed_in_accounts[0];
+ EXPECT_TRUE(gaia::AreEmailsSame(test_account_2.user, account.email));
+
+ // Check the primary account is set and syncing.
+ const CoreAccountInfo& primary_account =
+ identity_manager()->GetPrimaryAccountInfo(signin::ConsentLevel::kSync);
+ EXPECT_FALSE(primary_account.IsEmpty());
+ EXPECT_TRUE(gaia::AreEmailsSame(test_account_2.user, primary_account.email));
+ EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(
+ primary_account.account_id));
+ EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
+}
+
+// This test can pass. Marked as manual because it TIMED_OUT on Win7.
+// See crbug.com/1025335.
+// Enables and disables sync to account 1. Enables sync to account 2 and clicks
+// on "Cancel" in the email confirmation dialog. Checks that the signin flow is
+// canceled and no accounts are added to Chrome.
+IN_PROC_BROWSER_TEST_F(LiveSignInTest,
+ MANUAL_SyncSecondAccount_CancelOnEmailConfirmation) {
+ // Enable and disable sync for the first account.
+ TestAccount test_account_1;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account_1));
+ TurnOnSync(test_account_1, 0);
+ TurnOffSync();
+
+ // Start enable sync for the second account.
+ TestAccount test_account_2;
+ CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_2", test_account_2));
+ SignInFromSettings(test_account_2, 0);
+
+ // Check there is only one profile.
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 1U);
+ EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U);
+
+ // Click "Cancel" on the email confirmation dialog and wait for an account to
+ // removed from Chrome.
+ SignInTestObserver observer(identity_manager(), account_reconcilor());
+ EXPECT_TRUE(login_ui_test_utils::CompleteSigninEmailConfirmationDialog(
+ browser(), kDialogTimeout, SigninEmailConfirmationDialog::CLOSE));
+ observer.WaitForAccountChanges(0, PrimarySyncAccountWait::kWaitForCleared);
+
+ // Check no profile was created.
+ EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 1U);
+ EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U);
+
+ // Check Chrome has no accounts.
+ const AccountsInCookieJarInfo& accounts_in_cookie_jar =
+ identity_manager()->GetAccountsInCookieJar();
+ EXPECT_TRUE(accounts_in_cookie_jar.accounts_are_fresh);
+ EXPECT_TRUE(accounts_in_cookie_jar.signed_in_accounts.empty());
+ EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
+ EXPECT_FALSE(
+ identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSync));
+}
+
+IN_PROC_BROWSER_TEST_F(LiveSignInTest,
+ MANUAL_AccountCapabilities_FetchedOnSignIn) {
+ EnableAccountCapabilitiesFetches(identity_manager());
+
+ // Test primary adult account.
+ {
+ AccountCapabilitiesObserver capabilities_observer(identity_manager());
+
+ TestAccount ta;
+ ASSERT_TRUE(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", ta));
+ SignInFromSettings(ta, 0);
+
+ CoreAccountInfo core_account_info =
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin);
+ ASSERT_TRUE(gaia::AreEmailsSame(core_account_info.email, ta.user));
+
+ capabilities_observer.WaitForAllCapabilitiesToBeKnown(
+ core_account_info.account_id);
+ AccountInfo account_info =
+ identity_manager()->FindExtendedAccountInfoByAccountId(
+ core_account_info.account_id);
+ EXPECT_EQ(account_info.capabilities.can_offer_extended_chrome_sync_promos(),
+ Tribool::kTrue);
+ }
+
+ // Test secondary minor account.
+ {
+ AccountCapabilitiesObserver capabilities_observer(identity_manager());
+
+ TestAccount ta;
+ ASSERT_TRUE(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_MINOR", ta));
+ SignInFromWeb(ta, /*previously_signed_in_accounts=*/1);
+
+ CoreAccountInfo core_account_info =
+ identity_manager()->FindExtendedAccountInfoByEmailAddress(ta.user);
+ ASSERT_FALSE(core_account_info.IsEmpty());
+
+ capabilities_observer.WaitForAllCapabilitiesToBeKnown(
+ core_account_info.account_id);
+ AccountInfo account_info =
+ identity_manager()->FindExtendedAccountInfoByAccountId(
+ core_account_info.account_id);
+ EXPECT_EQ(account_info.capabilities.can_offer_extended_chrome_sync_promos(),
+ Tribool::kFalse);
+ }
+}
+
+} // namespace test
+} // namespace signin
diff --git a/chromium/chrome/browser/signin/e2e_tests/live_test.cc b/chromium/chrome/browser/signin/e2e_tests/live_test.cc
new file mode 100644
index 00000000000..e8d22189e73
--- /dev/null
+++ b/chromium/chrome/browser/signin/e2e_tests/live_test.cc
@@ -0,0 +1,61 @@
+// Copyright 2019 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/signin/e2e_tests/live_test.h"
+
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "net/dns/mock_host_resolver.h"
+
+base::FilePath::StringPieceType kTestAccountFilePath = FILE_PATH_LITERAL(
+ "chrome/browser/internal/resources/signin/test_accounts.json");
+
+const char* kRunLiveTestFlag = "run-live-tests";
+
+namespace signin {
+namespace test {
+
+void LiveTest::SetUpInProcessBrowserTestFixture() {
+ // Whitelists a bunch of hosts.
+ host_resolver()->AllowDirectLookup("*.google.com");
+ host_resolver()->AllowDirectLookup("*.geotrust.com");
+ host_resolver()->AllowDirectLookup("*.gstatic.com");
+ host_resolver()->AllowDirectLookup("*.googleapis.com");
+ // Allows country-specific TLDs.
+ host_resolver()->AllowDirectLookup("accounts.google.*");
+
+ InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
+}
+
+void LiveTest::SetUp() {
+ // Only run live tests when specified.
+ auto* cmd_line = base::CommandLine::ForCurrentProcess();
+ if (!cmd_line->HasSwitch(kRunLiveTestFlag)) {
+ LOG(INFO) << "This test should get skipped.";
+ skip_test_ = true;
+ GTEST_SKIP();
+ }
+ base::FilePath root_path;
+ base::PathService::Get(base::BasePathKey::DIR_SOURCE_ROOT, &root_path);
+ base::FilePath config_path =
+ base::MakeAbsoluteFilePath(root_path.Append(kTestAccountFilePath));
+ test_accounts_.Init(config_path);
+ InProcessBrowserTest::SetUp();
+}
+
+void LiveTest::TearDown() {
+ // This test was skipped, no need to tear down.
+ if (skip_test_)
+ return;
+ InProcessBrowserTest::TearDown();
+}
+
+void LiveTest::PostRunTestOnMainThread() {
+ // This test was skipped. Running PostRunTestOnMainThread can cause
+ // TIMED_OUT on Win7.
+ if (skip_test_)
+ return;
+ InProcessBrowserTest::PostRunTestOnMainThread();
+}
+} // namespace test
+} // namespace signin
diff --git a/chromium/chrome/browser/signin/e2e_tests/live_test.h b/chromium/chrome/browser/signin/e2e_tests/live_test.h
new file mode 100644
index 00000000000..6de9f8f4ded
--- /dev/null
+++ b/chromium/chrome/browser/signin/e2e_tests/live_test.h
@@ -0,0 +1,33 @@
+// Copyright 2019 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_SIGNIN_E2E_TESTS_LIVE_TEST_H_
+#define CHROME_BROWSER_SIGNIN_E2E_TESTS_LIVE_TEST_H_
+
+#include "chrome/browser/signin/e2e_tests/test_accounts_util.h"
+#include "chrome/test/base/in_process_browser_test.h"
+
+namespace signin {
+namespace test {
+
+class LiveTest : public InProcessBrowserTest {
+ protected:
+ void SetUpInProcessBrowserTestFixture() override;
+ void SetUp() override;
+ void TearDown() override;
+ void PostRunTestOnMainThread() override;
+
+ const TestAccountsUtil* GetTestAccountsUtil() const {
+ return &test_accounts_;
+ }
+
+ private:
+ TestAccountsUtil test_accounts_;
+ bool skip_test_ = false;
+};
+
+} // namespace test
+} // namespace signin
+
+#endif // CHROME_BROWSER_SIGNIN_E2E_TESTS_LIVE_TEST_H_
diff --git a/chromium/chrome/browser/signin/e2e_tests/test_accounts_util.cc b/chromium/chrome/browser/signin/e2e_tests/test_accounts_util.cc
new file mode 100644
index 00000000000..c533ea0fb3c
--- /dev/null
+++ b/chromium/chrome/browser/signin/e2e_tests/test_accounts_util.cc
@@ -0,0 +1,75 @@
+// Copyright 2019 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/signin/e2e_tests/test_accounts_util.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/json/json_file_value_serializer.h"
+#include "base/json/json_reader.h"
+#include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
+
+using base::Value;
+
+namespace signin {
+namespace test {
+
+#if defined(OS_WIN)
+std::string kPlatform = "win";
+#elif defined(OS_MAC)
+std::string kPlatform = "mac";
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
+std::string kPlatform = "chromeos";
+#elif defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
+std::string kPlatform = "linux";
+#elif defined(OS_ANDROID)
+std::string kPlatform = "android";
+#else
+std::string kPlatform = "all_platform";
+#endif
+
+TestAccountsUtil::TestAccountsUtil() = default;
+TestAccountsUtil::~TestAccountsUtil() = default;
+
+bool TestAccountsUtil::Init(const base::FilePath& config_path) {
+ int error_code = 0;
+ std::string error_str;
+ JSONFileValueDeserializer deserializer(config_path);
+ std::unique_ptr<Value> content_json =
+ deserializer.Deserialize(&error_code, &error_str);
+ CHECK(error_code == 0) << "Error reading json file. Error code: "
+ << error_code << " " << error_str;
+ CHECK(content_json);
+
+ // Only store platform specific users. If an account does not have
+ // platform specific user, try to use all_platform user.
+ for (auto account : content_json->DictItems()) {
+ const Value* platform_account = account.second.FindDictKey(kPlatform);
+ if (platform_account == nullptr) {
+ platform_account = account.second.FindDictKey("all_platform");
+ if (platform_account == nullptr) {
+ continue;
+ }
+ }
+ TestAccount ta(*(platform_account->FindStringKey("user")),
+ *(platform_account->FindStringKey("password")));
+ all_accounts_.insert(
+ std::pair<std::string, TestAccount>(account.first, ta));
+ }
+ return true;
+}
+
+bool TestAccountsUtil::GetAccount(const std::string& name,
+ TestAccount& out_account) const {
+ auto it = all_accounts_.find(name);
+ if (it == all_accounts_.end()) {
+ return false;
+ }
+ out_account = it->second;
+ return true;
+}
+
+} // namespace test
+} // namespace signin
diff --git a/chromium/chrome/browser/signin/e2e_tests/test_accounts_util.h b/chromium/chrome/browser/signin/e2e_tests/test_accounts_util.h
new file mode 100644
index 00000000000..4f73dd76d32
--- /dev/null
+++ b/chromium/chrome/browser/signin/e2e_tests/test_accounts_util.h
@@ -0,0 +1,46 @@
+// 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_SIGNIN_E2E_TESTS_TEST_ACCOUNTS_UTIL_H_
+#define CHROME_BROWSER_SIGNIN_E2E_TESTS_TEST_ACCOUNTS_UTIL_H_
+
+#include <map>
+#include <string>
+
+namespace base {
+class FilePath;
+}
+
+namespace signin {
+namespace test {
+
+struct TestAccount {
+ std::string user;
+ std::string password;
+ TestAccount() = default;
+ TestAccount(const std::string& user, const std::string& password) {
+ this->user = user;
+ this->password = password;
+ }
+};
+
+class TestAccountsUtil {
+ public:
+ TestAccountsUtil();
+
+ TestAccountsUtil(const TestAccountsUtil&) = delete;
+ TestAccountsUtil& operator=(const TestAccountsUtil&) = delete;
+
+ virtual ~TestAccountsUtil();
+ bool Init(const base::FilePath& config_path);
+ bool GetAccount(const std::string& name, TestAccount& out_account) const;
+
+ private:
+ std::map<std::string, TestAccount> all_accounts_;
+};
+
+} // namespace test
+} // namespace signin
+
+#endif // CHROME_BROWSER_SIGNIN_E2E_TESTS_TEST_ACCOUNTS_UTIL_H_
diff --git a/chromium/chrome/browser/signin/e2e_tests/test_accounts_util_unittest.cc b/chromium/chrome/browser/signin/e2e_tests/test_accounts_util_unittest.cc
new file mode 100644
index 00000000000..7b63dd6128a
--- /dev/null
+++ b/chromium/chrome/browser/signin/e2e_tests/test_accounts_util_unittest.cc
@@ -0,0 +1,100 @@
+// Copyright 2019 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/signin/e2e_tests/test_accounts_util.h"
+#include "base/files/file_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::FilePath;
+
+namespace signin {
+namespace test {
+
+class TestAccountsUtilTest : public testing::Test {};
+
+FilePath WriteContentToTemporaryFile(const char* contents,
+ unsigned int length) {
+ FilePath tmp_file;
+ CHECK(base::CreateTemporaryFile(&tmp_file));
+ unsigned int bytes_written = base::WriteFile(tmp_file, contents, length);
+ CHECK_EQ(bytes_written, length);
+ return tmp_file;
+}
+
+TEST(TestAccountsUtilTest, ParsingJson) {
+ const char contents[] =
+ "{ \n"
+ " \"TEST_ACCOUNT_1\": {\n"
+ " \"win\": {\n"
+ " \"user\": \"user1\",\n"
+ " \"password\": \"pwd1\"\n"
+ " }\n"
+ " }\n"
+ "}";
+ FilePath tmp_file =
+ WriteContentToTemporaryFile(contents, sizeof(contents) - 1);
+ TestAccountsUtil util;
+ util.Init(tmp_file);
+}
+
+TEST(TestAccountsUtilTest, GetAccountForPlatformSpecific) {
+ const char contents[] =
+ "{ \n"
+ " \"TEST_ACCOUNT_1\": {\n"
+ " \"win\": {\n"
+ " \"user\": \"user1\",\n"
+ " \"password\": \"pwd1\"\n"
+ " },\n"
+ " \"mac\": {\n"
+ " \"user\": \"user1\",\n"
+ " \"password\": \"pwd1\"\n"
+ " },\n"
+ " \"linux\": {\n"
+ " \"user\": \"user1\",\n"
+ " \"password\": \"pwd1\"\n"
+ " },\n"
+ " \"chromeos\": {\n"
+ " \"user\": \"user1\",\n"
+ " \"password\": \"pwd1\"\n"
+ " },\n"
+ " \"android\": {\n"
+ " \"user\": \"user1\",\n"
+ " \"password\": \"pwd1\"\n"
+ " }\n"
+ " }\n"
+ "}";
+ FilePath tmp_file =
+ WriteContentToTemporaryFile(contents, sizeof(contents) - 1);
+ TestAccountsUtil util;
+ util.Init(tmp_file);
+ TestAccount ta;
+ bool ret = util.GetAccount("TEST_ACCOUNT_1", ta);
+ ASSERT_TRUE(ret);
+ ASSERT_EQ(ta.user, "user1");
+ ASSERT_EQ(ta.password, "pwd1");
+}
+
+TEST(TestAccountsUtilTest, GetAccountForAllPlatform) {
+ const char contents[] =
+ "{ \n"
+ " \"TEST_ACCOUNT_1\": {\n"
+ " \"all_platform\": {\n"
+ " \"user\": \"user_allplatform\",\n"
+ " \"password\": \"pwd_allplatform\"\n"
+ " }\n"
+ " }\n"
+ "}";
+ FilePath tmp_file =
+ WriteContentToTemporaryFile(contents, sizeof(contents) - 1);
+ TestAccountsUtil util;
+ util.Init(tmp_file);
+ TestAccount ta;
+ bool ret = util.GetAccount("TEST_ACCOUNT_1", ta);
+ ASSERT_TRUE(ret);
+ ASSERT_EQ(ta.user, "user_allplatform");
+ ASSERT_EQ(ta.password, "pwd_allplatform");
+}
+
+} // namespace test
+} // namespace signin