Handle ListAccount fetches and watching the GAIA cookies from within the GaiaCookieManagerService.

This CL only implements non-ChromeOS features; AboutSigninInterals and the AccountReconcilor. ChromeOS features will come later, as they require more support. This CL also removes the ReconcilorSource as a parameter to ListAccounts. Changes the observed cookie from the LSID cookie to the APISID cookie at nickk@'s suggestion.

Design doc: https://docs.google.com/document/d/1FfmSS7M87L_2tkVuHO3NuruborFm6qHXe2VdktZg-HQ/

BUG=466799, 463611, 471210

Review URL: https://codereview.chromium.org/1075273002

Cr-Commit-Position: refs/heads/master@{#326846}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index c6925c3..709fd0c 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -948,10 +948,10 @@
     "sessions/session_restore_test_helper.h",
     "sessions/session_service_test_helper.cc",
     "sessions/session_service_test_helper.h",
-    "signin/fake_account_reconcilor.cc",
-    "signin/fake_account_reconcilor.h",
     "signin/fake_account_tracker_service.cc",
     "signin/fake_account_tracker_service.h",
+    "signin/fake_gaia_cookie_manager_service.cc",
+    "signin/fake_gaia_cookie_manager_service.h",
     "signin/fake_profile_oauth2_token_service.cc",
     "signin/fake_profile_oauth2_token_service.h",
     "signin/fake_profile_oauth2_token_service_builder.cc",
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index 1d4ba1e..2debe5b0 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -19,12 +19,12 @@
 #include "chrome/browser/extensions/extension_function_test_utils.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/account_reconcilor_factory.h"
 #include "chrome/browser/signin/account_tracker_service_factory.h"
-#include "chrome/browser/signin/fake_account_reconcilor.h"
+#include "chrome/browser/signin/fake_gaia_cookie_manager_service.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
+#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
@@ -555,8 +555,8 @@
         context, &FakeSigninManagerBase::Build);
     ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
         context, &BuildFakeProfileOAuth2TokenService);
-    AccountReconcilorFactory::GetInstance()->SetTestingFactory(
-        context, &FakeAccountReconcilor::Build);
+    GaiaCookieManagerServiceFactory::GetInstance()->SetTestingFactory(
+        context, &FakeGaiaCookieManagerService::Build);
   }
 
   void SetUpOnMainThread() override {
@@ -570,6 +570,8 @@
         ProfileOAuth2TokenServiceFactory::GetInstance()->GetForProfile(
             profile()));
     ASSERT_TRUE(token_service_);
+    GaiaCookieManagerServiceFactory::GetInstance()->GetForProfile(profile())
+        ->Init();
   }
 
  protected:
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 6ccb91d..b20c703 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -39,6 +39,7 @@
 #include "chrome/browser/profiles/startup_task_runner_service_factory.h"
 #include "chrome/browser/signin/account_reconcilor_factory.h"
 #include "chrome/browser/signin/account_tracker_service_factory.h"
+#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
@@ -56,6 +57,7 @@
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/core/common/profile_management_switches.h"
 #include "content/public/browser/browser_thread.h"
@@ -1053,6 +1055,7 @@
   DataReductionProxyChromeSettingsFactory::GetForBrowserContext(profile)->
       MaybeActivateDataReductionProxy(true);
 
+  GaiaCookieManagerServiceFactory::GetForProfile(profile)->Init();
   AccountTrackerServiceFactory::GetForProfile(profile)->EnableNetworkFetches();
   AccountReconcilorFactory::GetForProfile(profile);
 }
diff --git a/chrome/browser/signin/about_signin_internals_factory.cc b/chrome/browser/signin/about_signin_internals_factory.cc
index 1236d9e..e2091824 100644
--- a/chrome/browser/signin/about_signin_internals_factory.cc
+++ b/chrome/browser/signin/about_signin_internals_factory.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
+#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_error_controller_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -27,6 +28,7 @@
         BrowserContextDependencyManager::GetInstance()) {
   DependsOn(AccountTrackerServiceFactory::GetInstance());
   DependsOn(ChromeSigninClientFactory::GetInstance());
+  DependsOn(GaiaCookieManagerServiceFactory::GetInstance());
   DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
   DependsOn(SigninErrorControllerFactory::GetInstance());
   DependsOn(SigninManagerFactory::GetInstance());
@@ -85,7 +87,8 @@
       ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
       AccountTrackerServiceFactory::GetForProfile(profile),
       SigninManagerFactory::GetForProfile(profile),
-      SigninErrorControllerFactory::GetForProfile(profile));
+      SigninErrorControllerFactory::GetForProfile(profile),
+      GaiaCookieManagerServiceFactory::GetForProfile(profile));
   service->Initialize(ChromeSigninClientFactory::GetForProfile(profile));
   return service;
 }
diff --git a/chrome/browser/signin/account_reconcilor_unittest.cc b/chrome/browser/signin/account_reconcilor_unittest.cc
index 7d6e9c5a..73d79c1de 100644
--- a/chrome/browser/signin/account_reconcilor_unittest.cc
+++ b/chrome/browser/signin/account_reconcilor_unittest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/signin/account_reconcilor_factory.h"
 #include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
+#include "chrome/browser/signin/fake_gaia_cookie_manager_service.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
@@ -88,6 +89,9 @@
   FakeProfileOAuth2TokenService* token_service() { return token_service_; }
   TestSigninClient* test_signin_client() { return test_signin_client_; }
   AccountTrackerService* account_tracker() { return account_tracker_; }
+  FakeGaiaCookieManagerService* cookie_manager_service() {
+    return cookie_manager_service_;
+  }
   base::HistogramTester* histogram_tester() { return &histogram_tester_; }
 
   void SetFakeResponse(const std::string& url,
@@ -114,7 +118,6 @@
       content_settings::Observer* observer,
       const ContentSettingsPattern& primary_pattern);
 
-  GURL list_accounts_url() { return list_accounts_url_; }
   GURL get_check_connection_info_url() {
     return get_check_connection_info_url_;
   }
@@ -126,11 +129,11 @@
   FakeProfileOAuth2TokenService* token_service_;
   TestSigninClient* test_signin_client_;
   AccountTrackerService* account_tracker_;
+  FakeGaiaCookieManagerService* cookie_manager_service_;
   MockAccountReconcilor* mock_reconcilor_;
   net::FakeURLFetcherFactory url_fetcher_factory_;
   scoped_ptr<TestingProfileManager> testing_profile_manager_;
   base::HistogramTester histogram_tester_;
-  GURL list_accounts_url_;
   GURL get_check_connection_info_url_;
 
   DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTest);
@@ -140,6 +143,7 @@
     : signin_manager_(NULL),
       token_service_(NULL),
       test_signin_client_(NULL),
+      cookie_manager_service_(NULL),
       mock_reconcilor_(NULL),
       url_fetcher_factory_(NULL) {}
 
@@ -151,16 +155,10 @@
         switches::kEnableNewProfileManagement);
   }
 
-  list_accounts_url_ = GaiaUrls::GetInstance()->ListAccountsURLWithSource(
-      GaiaConstants::kReconcilorSource);
   get_check_connection_info_url_ =
       GaiaUrls::GetInstance()->GetCheckConnectionInfoURLWithSource(
           GaiaConstants::kChromeSource);
 
-  // Specific tests may set a response that includes specific accounts.
-  SetFakeResponse(list_accounts_url().spec(), "",
-      net::HTTP_NOT_FOUND, net::URLRequestStatus::SUCCESS);
-
   testing_profile_manager_.reset(
       new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
   ASSERT_TRUE(testing_profile_manager_.get()->SetUp());
@@ -171,6 +169,9 @@
   factories.push_back(std::make_pair(
       ProfileOAuth2TokenServiceFactory::GetInstance(),
       BuildFakeProfileOAuth2TokenService));
+  factories.push_back(std::make_pair(
+      GaiaCookieManagerServiceFactory::GetInstance(),
+      FakeGaiaCookieManagerService::Build));
   factories.push_back(std::make_pair(SigninManagerFactory::GetInstance(),
       FakeSigninManagerBase::Build));
   factories.push_back(std::make_pair(AccountReconcilorFactory::GetInstance(),
@@ -195,6 +196,17 @@
   signin_manager_ =
       static_cast<FakeSigninManagerForTesting*>(
           SigninManagerFactory::GetForProfile(profile()));
+
+  test_signin_client_ =
+      static_cast<TestSigninClient*>(
+          ChromeSigninClientFactory::GetForProfile(profile()));
+
+  cookie_manager_service_ =
+      static_cast<FakeGaiaCookieManagerService*>(
+        GaiaCookieManagerServiceFactory::GetForProfile(profile()));
+  cookie_manager_service_->Init(&url_fetcher_factory_);
+
+  cookie_manager_service_->SetListAccountsResponseHttpNotFound();
 }
 
 MockAccountReconcilor* AccountReconcilorTest::GetMockReconcilor() {
@@ -303,41 +315,37 @@
 TEST_F(AccountReconcilorTest, GetAccountsFromCookieSuccess) {
   const std::string account_id =
       ConnectProfileToAccount("12345", "[email protected]");
+  cookie_manager_service()->SetListAccountsResponseOneAccountWithExpiry(
+      "[email protected]", true);
   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
 
   AccountReconcilor* reconcilor =
       AccountReconcilorFactory::GetForProfile(profile());
   ASSERT_TRUE(reconcilor);
 
-  SetFakeResponse(list_accounts_url().spec(),
-      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 0]]]",
-      net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-
   reconcilor->StartReconcile();
-  ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
-
   base::RunLoop().RunUntilIdle();
-  ASSERT_TRUE(reconcilor->AreGaiaAccountsSet());
-  const std::vector<std::pair<std::string, bool> >& accounts =
-      reconcilor->GetGaiaAccountsForTesting();
+
+  std::vector<std::pair<std::string, bool> > accounts;
+  ASSERT_TRUE(cookie_manager_service()->ListAccounts(&accounts));
   ASSERT_EQ(1u, accounts.size());
   ASSERT_EQ(account_id, accounts[0].first);
 }
 
 TEST_F(AccountReconcilorTest, GetAccountsFromCookieFailure) {
   ConnectProfileToAccount("12345", "[email protected]");
+  cookie_manager_service()->SetListAccountsResponseHttpNotFound();
+
   AccountReconcilor* reconcilor =
       AccountReconcilorFactory::GetForProfile(profile());
   ASSERT_TRUE(reconcilor);
 
-  SetFakeResponse(list_accounts_url().spec(), "",
-      net::HTTP_NOT_FOUND, net::URLRequestStatus::SUCCESS);
-
   reconcilor->StartReconcile();
-  ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
-
   base::RunLoop().RunUntilIdle();
-  ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
+
+  std::vector<std::pair<std::string, bool> > accounts;
+  ASSERT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
+  ASSERT_EQ(0u, accounts.size());
 }
 
 TEST_P(AccountReconcilorTest, StartReconcileNoop) {
@@ -348,13 +356,10 @@
       AccountReconcilorFactory::GetForProfile(profile());
   ASSERT_TRUE(reconcilor);
 
-  SetFakeResponse(list_accounts_url().spec(),
-      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1]]]",
-      net::HTTP_OK, net::URLRequestStatus::SUCCESS);
+  cookie_manager_service()->SetListAccountsResponseOneAccount("[email protected]");
 
   reconcilor->StartReconcile();
   ASSERT_TRUE(reconcilor->is_reconcile_started_);
-  ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
 
   base::RunLoop().RunUntilIdle();
   ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -379,9 +384,11 @@
 
   reconcilor->StartReconcile();
   ASSERT_FALSE(reconcilor->is_reconcile_started_);
-  ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
 
   base::RunLoop().RunUntilIdle();
+  std::vector<std::pair<std::string, bool> > accounts;
+  // This will be the first call to ListAccounts.
+  ASSERT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
   ASSERT_FALSE(reconcilor->is_reconcile_started_);
 }
 
@@ -468,17 +475,13 @@
 
   const std::string account_id =
       ConnectProfileToAccount("12345", "[email protected]");
+  cookie_manager_service()->SetListAccountsResponseOneAccount(
+      "[email protected]");
   AccountReconcilor* reconcilor =
       AccountReconcilorFactory::GetForProfile(profile());
   ASSERT_TRUE(reconcilor);
 
-  SetFakeResponse(list_accounts_url().spec(),
-      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1]]]",
-      net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-
   reconcilor->StartReconcile();
-  ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
-
   base::RunLoop().RunUntilIdle();
   ASSERT_FALSE(reconcilor->is_reconcile_started_);
 
@@ -493,19 +496,15 @@
       ConnectProfileToAccount("12345", "[email protected]");
   const std::string account_id2 =
       PickAccountIdForAccount("67890", "[email protected]");
+  cookie_manager_service()->SetListAccountsResponseTwoAccounts(
+      "[email protected]", "[email protected]");
   token_service()->UpdateCredentials(account_id2, "refresh_token");
 
   AccountReconcilor* reconcilor =
       AccountReconcilorFactory::GetForProfile(profile());
   ASSERT_TRUE(reconcilor);
 
-  SetFakeResponse(list_accounts_url().spec(),
-      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1], "
-               "[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1]]]",
-      net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-
   reconcilor->StartReconcile();
-  ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
   base::RunLoop().RunUntilIdle();
   ASSERT_FALSE(reconcilor->is_reconcile_started_);
 
@@ -521,6 +520,8 @@
   const std::string account_id =
       ConnectProfileToAccount("12345", "[email protected]");
   token_service()->UpdateCredentials(account_id, "refresh_token");
+  cookie_manager_service()->SetListAccountsResponseOneAccount(
+      "[email protected]");
 
   const std::string account_id2 =
       PickAccountIdForAccount("67890", "[email protected]");
@@ -528,10 +529,6 @@
 
   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
 
-  SetFakeResponse(list_accounts_url().spec(),
-      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1]]]",
-      net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-
   AccountReconcilor* reconcilor = GetMockReconcilor();
   reconcilor->StartReconcile();
 
@@ -555,15 +552,12 @@
   const std::string account_id =
       ConnectProfileToAccount("12345", "[email protected]");
   token_service()->UpdateCredentials(account_id, "refresh_token");
+  cookie_manager_service()->SetListAccountsResponseTwoAccounts(
+      "[email protected]", "[email protected]");
 
   EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
 
-  SetFakeResponse(list_accounts_url().spec(),
-      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1], "
-               "[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1]]]",
-      net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-
   AccountReconcilor* reconcilor = GetMockReconcilor();
   reconcilor->StartReconcile();
   ASSERT_TRUE(reconcilor->is_reconcile_started_);
@@ -591,17 +585,13 @@
   const std::string account_id3 =
       PickAccountIdForAccount("34567", "[email protected]");
 
+  cookie_manager_service()->SetListAccountsResponseOneAccount(
+      "[email protected]");
   token_service()->UpdateCredentials(account_id2, "refresh_token");
 
   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id3));
 
-  SetFakeResponse(
-      list_accounts_url().spec(),
-      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1]]]",
-      net::HTTP_OK,
-      net::URLRequestStatus::SUCCESS);
-
   AccountReconcilor* reconcilor = GetMockReconcilor();
   reconcilor->StartReconcile();
 
@@ -621,13 +611,10 @@
       "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
 
   // Do another pass after I've added a third account to the token service
+  cookie_manager_service()->SetListAccountsResponseTwoAccounts(
+      "[email protected]", "[email protected]");
+  cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
 
-  SetFakeResponse(
-      list_accounts_url().spec(),
-      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1], "
-      "[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1]]]",
-      net::HTTP_OK,
-      net::URLRequestStatus::SUCCESS);
   // This will cause the reconcilor to fire.
   token_service()->UpdateCredentials(account_id3, "refresh_token");
   base::RunLoop().RunUntilIdle();
@@ -662,16 +649,13 @@
       PickAccountIdForAccount("67890", "[email protected]");
 
   token_service()->UpdateCredentials(account_id2, "refresh_token");
+  cookie_manager_service()->SetListAccountsResponseTwoAccounts(
+      "[email protected]", "[email protected]");
 
   EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
 
-  SetFakeResponse(list_accounts_url().spec(),
-      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1], "
-               "[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1]]]",
-      net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-
   AccountReconcilor* reconcilor = GetMockReconcilor();
   reconcilor->StartReconcile();
 
@@ -697,15 +681,13 @@
 TEST_P(AccountReconcilorTest, StartReconcileOnlyOnce) {
   const std::string account_id =
       ConnectProfileToAccount("12345", "[email protected]");
+  cookie_manager_service()->SetListAccountsResponseOneAccount(
+      "[email protected]");
 
   AccountReconcilor* reconcilor =
       AccountReconcilorFactory::GetForProfile(profile());
   ASSERT_TRUE(reconcilor);
 
-  SetFakeResponse(list_accounts_url().spec(),
-      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1]]]",
-      net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-
   ASSERT_FALSE(reconcilor->is_reconcile_started_);
   reconcilor->StartReconcile();
   ASSERT_TRUE(reconcilor->is_reconcile_started_);
@@ -720,14 +702,11 @@
   const std::string account_id2 =
       PickAccountIdForAccount("67890", "[email protected]");
   token_service()->UpdateCredentials(account_id2, "refresh_token");
+  cookie_manager_service()->SetListAccountsResponseTwoAccountsWithExpiry(
+      "[email protected]", true, "[email protected]", false);
 
   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
 
-  SetFakeResponse(list_accounts_url().spec(),
-      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 0],"
-               "[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1]]]",
-      net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-
   AccountReconcilor* reconcilor =
       AccountReconcilorFactory::GetForProfile(profile());
   ASSERT_TRUE(reconcilor);
@@ -745,13 +724,11 @@
 TEST_F(AccountReconcilorTest, AddAccountToCookieCompletedWithBogusAccount) {
   const std::string account_id =
       ConnectProfileToAccount("12345", "[email protected]");
+  cookie_manager_service()->SetListAccountsResponseOneAccountWithExpiry(
+      "[email protected]", true);
 
   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
 
-  SetFakeResponse(list_accounts_url().spec(),
-      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 0]]]",
-      net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-
   AccountReconcilor* reconcilor =
       AccountReconcilorFactory::GetForProfile(profile());
   ASSERT_TRUE(reconcilor);
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc
index debf8eca4..90ddd804 100644
--- a/chrome/browser/signin/chrome_signin_client.cc
+++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -61,8 +61,10 @@
 bool ChromeSigninClient::SettingsAllowSigninCookies(
     CookieSettings* cookie_settings) {
   GURL gaia_url = GaiaUrls::GetInstance()->gaia_url();
+  GURL google_url = GaiaUrls::GetInstance()->google_url();
   return cookie_settings &&
-         cookie_settings->IsSettingCookieAllowed(gaia_url, gaia_url);
+         cookie_settings->IsSettingCookieAllowed(gaia_url, gaia_url) &&
+         cookie_settings->IsSettingCookieAllowed(google_url, google_url);
 }
 
 PrefService* ChromeSigninClient::GetPrefs() { return profile_->GetPrefs(); }
diff --git a/chrome/browser/signin/fake_account_reconcilor.cc b/chrome/browser/signin/fake_account_reconcilor.cc
deleted file mode 100644
index ea1573ef..0000000
--- a/chrome/browser/signin/fake_account_reconcilor.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 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/fake_account_reconcilor.h"
-
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/chrome_signin_client_factory.h"
-#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
-
-FakeAccountReconcilor::FakeAccountReconcilor(
-    ProfileOAuth2TokenService* token_service,
-    SigninManagerBase* signin_manager,
-    SigninClient* client,
-    GaiaCookieManagerService* cookie_manager_service) :
-  AccountReconcilor(
-      token_service, signin_manager, client, cookie_manager_service) {}
-
-
-// static
-KeyedService* FakeAccountReconcilor::Build(content::BrowserContext* context) {
-  Profile* profile = Profile::FromBrowserContext(context);
-  AccountReconcilor* reconcilor = new FakeAccountReconcilor(
-      ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
-      SigninManagerFactory::GetForProfile(profile),
-      ChromeSigninClientFactory::GetForProfile(profile),
-      GaiaCookieManagerServiceFactory::GetForProfile(profile));
-  reconcilor->Initialize(true /* start_reconcile_if_tokens_available */);
-  return reconcilor;
-}
-
-void FakeAccountReconcilor::GetAccountsFromCookie(
-    GetAccountsFromCookieCallback callback) {
-  std::vector<std::pair<std::string, bool> > gaia_accounts;
-  callback.Run(GoogleServiceAuthError::AuthErrorNone(), gaia_accounts);
-}
diff --git a/chrome/browser/signin/fake_account_reconcilor.h b/chrome/browser/signin/fake_account_reconcilor.h
deleted file mode 100644
index 405fda2..0000000
--- a/chrome/browser/signin/fake_account_reconcilor.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 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_FAKE_ACCOUNT_RECONCILOR_H_
-#define CHROME_BROWSER_SIGNIN_FAKE_ACCOUNT_RECONCILOR_H_
-
-#include "components/signin/core/browser/account_reconcilor.h"
-
-namespace content {
-class BrowserContext;
-}
-
-class FakeAccountReconcilor : public AccountReconcilor {
- public:
-  FakeAccountReconcilor(ProfileOAuth2TokenService* token_service,
-                        SigninManagerBase* signin_manager,
-                        SigninClient* client,
-                        GaiaCookieManagerService* cookie_manager_service);
-
-  // Helper function to be used with KeyedService::SetTestingFactory().
-  static KeyedService* Build(content::BrowserContext* context);
-
- protected:
-  // Override this method to perform no network call, instead the callback
-  // is called immediately
-  void GetAccountsFromCookie(GetAccountsFromCookieCallback callback) override;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeAccountReconcilor);
-};
-
-#endif  // CHROME_BROWSER_SIGNIN_FAKE_ACCOUNT_RECONCILOR_H_
diff --git a/chrome/browser/signin/fake_gaia_cookie_manager_service.cc b/chrome/browser/signin/fake_gaia_cookie_manager_service.cc
new file mode 100644
index 0000000..430f8abb
--- /dev/null
+++ b/chrome/browser/signin/fake_gaia_cookie_manager_service.cc
@@ -0,0 +1,112 @@
+// Copyright 2015 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/fake_gaia_cookie_manager_service.h"
+
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/gaia_urls.h"
+
+FakeGaiaCookieManagerService::FakeGaiaCookieManagerService(
+    OAuth2TokenService* token_service,
+    const std::string& source,
+    SigninClient* client) :
+        GaiaCookieManagerService(token_service, source, client),
+        url_fetcher_factory_(NULL) {}
+
+void FakeGaiaCookieManagerService::Init(
+    net::FakeURLFetcherFactory* url_fetcher_factory) {
+  url_fetcher_factory_ = url_fetcher_factory;
+}
+
+void FakeGaiaCookieManagerService::SetListAccountsResponseHttpNotFound() {
+  DCHECK(url_fetcher_factory_);
+  url_fetcher_factory_->SetFakeResponse(
+      GaiaUrls::GetInstance()->ListAccountsURLWithSource(
+          GaiaConstants::kChromeSource),
+      "",
+      net::HTTP_NOT_FOUND,
+      net::URLRequestStatus::SUCCESS);
+}
+
+void FakeGaiaCookieManagerService::SetListAccountsResponseNoAccounts() {
+  DCHECK(url_fetcher_factory_);
+  url_fetcher_factory_->SetFakeResponse(
+      GaiaUrls::GetInstance()->ListAccountsURLWithSource(
+          GaiaConstants::kChromeSource),
+      "[\"f\", []]",
+      net::HTTP_OK,
+      net::URLRequestStatus::SUCCESS);
+}
+
+void FakeGaiaCookieManagerService::SetListAccountsResponseOneAccount(
+    const char* account) {
+  DCHECK(url_fetcher_factory_);
+  url_fetcher_factory_->SetFakeResponse(
+      GaiaUrls::GetInstance()->ListAccountsURLWithSource(
+          GaiaConstants::kChromeSource),
+      base::StringPrintf(
+          "[\"f\", [[\"b\", 0, \"n\", \"%s\", \"p\", 0, 0, 0, 0, 1]]]",
+          account),
+      net::HTTP_OK,
+      net::URLRequestStatus::SUCCESS);
+}
+
+void FakeGaiaCookieManagerService::SetListAccountsResponseOneAccountWithExpiry(
+    const char* account, bool expired) {
+  DCHECK(url_fetcher_factory_);
+  url_fetcher_factory_->SetFakeResponse(
+      GaiaUrls::GetInstance()->ListAccountsURLWithSource(
+          GaiaConstants::kChromeSource),
+      base::StringPrintf(
+          "[\"f\", [[\"b\", 0, \"n\", \"%s\", \"p\", 0, 0, 0, 0, %d]]]",
+          account, expired ? 0 : 1),
+      net::HTTP_OK,
+      net::URLRequestStatus::SUCCESS);
+}
+
+void FakeGaiaCookieManagerService::SetListAccountsResponseTwoAccounts(
+    const char* account1, const char* account2) {
+  DCHECK(url_fetcher_factory_);
+  url_fetcher_factory_->SetFakeResponse(
+      GaiaUrls::GetInstance()->ListAccountsURLWithSource(
+          GaiaConstants::kChromeSource),
+      base::StringPrintf(
+          "[\"f\", [[\"b\", 0, \"n\", \"%s\", \"p\", 0, 0, 0, 0, 1], "
+          "[\"b\", 0, \"n\", \"%s\", \"p\", 0, 0, 0, 0, 1]]]",
+          account1, account2),
+      net::HTTP_OK,
+      net::URLRequestStatus::SUCCESS);
+}
+
+void FakeGaiaCookieManagerService::SetListAccountsResponseTwoAccountsWithExpiry(
+    const char* account1, bool account1_expired,
+    const char* account2, bool account2_expired) {
+  DCHECK(url_fetcher_factory_);
+  url_fetcher_factory_->SetFakeResponse(
+      GaiaUrls::GetInstance()->ListAccountsURLWithSource(
+          GaiaConstants::kChromeSource),
+      base::StringPrintf(
+          "[\"f\", [[\"b\", 0, \"n\", \"%s\", \"p\", 0, 0, 0, 0, %d], "
+          "[\"b\", 0, \"n\", \"%s\", \"p\", 0, 0, 0, 0, %d]]]",
+          account1, account1_expired ? 0 : 1,
+          account2, account2_expired ? 0 : 1),
+      net::HTTP_OK,
+      net::URLRequestStatus::SUCCESS);
+}
+
+// static
+KeyedService* FakeGaiaCookieManagerService::Build(
+    content::BrowserContext* context) {
+  Profile* profile = Profile::FromBrowserContext(context);
+  FakeGaiaCookieManagerService* service = new FakeGaiaCookieManagerService(
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
+      GaiaConstants::kChromeSource,
+      ChromeSigninClientFactory::GetForProfile(profile));
+  return service;
+}
diff --git a/chrome/browser/signin/fake_gaia_cookie_manager_service.h b/chrome/browser/signin/fake_gaia_cookie_manager_service.h
new file mode 100644
index 0000000..b03750c9
--- /dev/null
+++ b/chrome/browser/signin/fake_gaia_cookie_manager_service.h
@@ -0,0 +1,44 @@
+// Copyright 2015 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_FAKE_GAIA_COOKIE_MANAGER_SERVICE_H_
+#define CHROME_BROWSER_SIGNIN_FAKE_GAIA_COOKIE_MANAGER_SERVICE_H_
+
+#include "components/signin/core/browser/gaia_cookie_manager_service.h"
+
+#include "net/url_request/test_url_fetcher_factory.h"
+
+namespace content {
+class BrowserContext;
+}
+
+class FakeGaiaCookieManagerService : public GaiaCookieManagerService {
+ public:
+  FakeGaiaCookieManagerService(OAuth2TokenService* token_service,
+                               const std::string& source,
+                               SigninClient* client);
+
+  void Init(net::FakeURLFetcherFactory* url_fetcher_factory);
+
+  void SetListAccountsResponseHttpNotFound();
+  void SetListAccountsResponseNoAccounts();
+  void SetListAccountsResponseOneAccount(const char* account);
+  void SetListAccountsResponseOneAccountWithExpiry(
+      const char* account, bool expired);
+  void SetListAccountsResponseTwoAccounts(const char* account1,
+                                          const char* account2);
+  void SetListAccountsResponseTwoAccountsWithExpiry(
+      const char* account1, bool account1_expired,
+      const char* account2, bool account2_expired);
+
+  // Helper function to be used with KeyedService::SetTestingFactory().
+  static KeyedService* Build(content::BrowserContext* context);
+
+ private:
+  // Provide a fake response for calls to /ListAccounts.
+  net::FakeURLFetcherFactory* url_fetcher_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeGaiaCookieManagerService);
+};
+
+#endif  // CHROME_BROWSER_SIGNIN_FAKE_GAIA_COOKIE_MANAGER_SERVICE_H_
diff --git a/chrome/browser/signin/signin_tracker_factory.cc b/chrome/browser/signin/signin_tracker_factory.cc
index 0c9f3da..0e1a5372 100644
--- a/chrome/browser/signin/signin_tracker_factory.cc
+++ b/chrome/browser/signin/signin_tracker_factory.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/signin/signin_tracker_factory.h"
 
-#include "chrome/browser/signin/account_reconcilor_factory.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
@@ -18,15 +17,9 @@
 scoped_ptr<SigninTracker> SigninTrackerFactory::CreateForProfile(
     Profile* profile,
     SigninTracker::Observer* observer) {
-  // Determine whether to use the AccountReconcilor.
-  AccountReconcilor* account_reconcilor = NULL;
-  if (switches::IsEnableAccountConsistency())
-    account_reconcilor = AccountReconcilorFactory::GetForProfile(profile);
-
   return scoped_ptr<SigninTracker>(new SigninTracker(
       ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
       SigninManagerFactory::GetForProfile(profile),
-      account_reconcilor,
       GaiaCookieManagerServiceFactory::GetForProfile(profile),
       ChromeSigninClientFactory::GetForProfile(profile),
       observer));
diff --git a/chrome/browser/ui/webui/signin_internals_ui.cc b/chrome/browser/ui/webui/signin_internals_ui.cc
index f01cac7..a709e406 100644
--- a/chrome/browser/ui/webui/signin_internals_ui.cc
+++ b/chrome/browser/ui/webui/signin_internals_ui.cc
@@ -8,8 +8,10 @@
 #include "base/profiler/scoped_tracker.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/about_signin_internals_factory.h"
+#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
 #include "chrome/common/url_constants.h"
 #include "components/signin/core/browser/about_signin_internals.h"
+#include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "grit/signin_internals_resources.h"
@@ -70,7 +72,15 @@
       web_ui()->CallJavascriptFunction(
           "chrome.signin.getSigninInfo.handleReply",
           *about_signin_internals->GetSigninStatus());
-      about_signin_internals->GetCookieAccountsAsync();
+
+      std::vector<std::pair<std::string, bool>> cookie_accounts;
+      GaiaCookieManagerService* cookie_manager_service =
+          GaiaCookieManagerServiceFactory::GetForProfile(profile);
+      if (cookie_manager_service->ListAccounts(&cookie_accounts)) {
+        about_signin_internals->OnGaiaAccountsInCookieUpdated(
+            cookie_accounts,
+            GoogleServiceAuthError(GoogleServiceAuthError::NONE));
+      }
 
       return true;
     }
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index a5ac421..26b63fa 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -1687,10 +1687,10 @@
         'browser/sessions/session_restore_test_helper.h',
         'browser/sessions/session_service_test_helper.cc',
         'browser/sessions/session_service_test_helper.h',
-        'browser/signin/fake_account_reconcilor.cc',
-        'browser/signin/fake_account_reconcilor.h',
         'browser/signin/fake_account_tracker_service.cc',
         'browser/signin/fake_account_tracker_service.h',
+        'browser/signin/fake_gaia_cookie_manager_service.cc',
+        'browser/signin/fake_gaia_cookie_manager_service.h',
         'browser/signin/fake_profile_oauth2_token_service.cc',
         'browser/signin/fake_profile_oauth2_token_service.h',
         'browser/signin/fake_profile_oauth2_token_service_builder.cc',
diff --git a/components/signin/core/browser/about_signin_internals.cc b/components/signin/core/browser/about_signin_internals.cc
index 81a7e614..74c3979 100644
--- a/components/signin/core/browser/about_signin_internals.cc
+++ b/components/signin/core/browser/about_signin_internals.cc
@@ -20,11 +20,6 @@
 #include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/core/common/profile_management_switches.h"
 #include "components/signin/core/common/signin_switches.h"
-#include "google_apis/gaia/gaia_auth_fetcher.h"
-#include "google_apis/gaia/gaia_auth_util.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "net/cookies/canonical_cookie.h"
 
 using base::Time;
 using namespace signin_internals_util;
@@ -135,12 +130,14 @@
     ProfileOAuth2TokenService* token_service,
     AccountTrackerService* account_tracker,
     SigninManagerBase* signin_manager,
-    SigninErrorController* signin_error_controller)
+    SigninErrorController* signin_error_controller,
+    GaiaCookieManagerService* cookie_manager_service)
     : token_service_(token_service),
       account_tracker_(account_tracker),
       signin_manager_(signin_manager),
       client_(NULL),
-      signin_error_controller_(signin_error_controller) {}
+      signin_error_controller_(signin_error_controller),
+      cookie_manager_service_(cookie_manager_service) {}
 
 AboutSigninInternals::~AboutSigninInternals() {}
 
@@ -211,18 +208,14 @@
   signin_error_controller_->AddObserver(this);
   signin_manager_->AddSigninDiagnosticsObserver(this);
   token_service_->AddDiagnosticsObserver(this);
-  cookie_changed_subscription_ = client_->AddCookieChangedCallback(
-      GaiaUrls::GetInstance()->gaia_url(),
-      "LSID",
-      base::Bind(&AboutSigninInternals::OnCookieChanged,
-                 base::Unretained(this)));
+  cookie_manager_service_->AddObserver(this);
 }
 
 void AboutSigninInternals::Shutdown() {
   signin_error_controller_->RemoveObserver(this);
   signin_manager_->RemoveSigninDiagnosticsObserver(this);
   token_service_->RemoveDiagnosticsObserver(this);
-  cookie_changed_subscription_.reset();
+  cookie_manager_service_->RemoveObserver(this);
 }
 
 void AboutSigninInternals::NotifyObservers() {
@@ -329,48 +322,10 @@
   NotifySigninValueChanged(AUTHENTICATION_RESULT_RECEIVED, status);
 }
 
-void AboutSigninInternals::OnCookieChanged(const net::CanonicalCookie& cookie,
-                                           bool removed) {
-  DCHECK_EQ("LSID", cookie.Name());
-  DCHECK_EQ(GaiaUrls::GetInstance()->gaia_url().host(), cookie.Domain());
-  if (cookie.IsSecure() && cookie.IsHttpOnly()) {
-    GetCookieAccountsAsync();
-  }
-}
-
 void AboutSigninInternals::OnErrorChanged() {
   NotifyObservers();
 }
 
-void AboutSigninInternals::GetCookieAccountsAsync() {
-  // Don't bother calling /ListAccounts if no one will observe the response.
-  if (!gaia_fetcher_ && signin_observers_.might_have_observers()) {
-    // There is no list account request in flight.
-    gaia_fetcher_.reset(new GaiaAuthFetcher(
-        this, GaiaConstants::kChromeSource, client_->GetURLRequestContext()));
-    gaia_fetcher_->StartListAccounts();
-  }
-}
-
-void AboutSigninInternals::OnListAccountsSuccess(const std::string& data) {
-  gaia_fetcher_.reset();
-
-  // Get account information from response data.
-  std::vector<std::pair<std::string, bool> > gaia_accounts;
-  bool valid_json = gaia::ParseListAccountsData(data, &gaia_accounts);
-  if (!valid_json) {
-    VLOG(1) << "AboutSigninInternals::OnListAccountsSuccess: parsing error";
-  } else {
-    OnListAccountsComplete(gaia_accounts);
-  }
-}
-
-void AboutSigninInternals::OnListAccountsFailure(
-    const GoogleServiceAuthError& error) {
-  gaia_fetcher_.reset();
-  VLOG(1) << "AboutSigninInternals::OnListAccountsFailure:" << error.ToString();
-}
-
 void AboutSigninInternals::GoogleSigninFailed(
     const GoogleServiceAuthError& error) {
   NotifyObservers();
@@ -387,8 +342,12 @@
   NotifyObservers();
 }
 
-void AboutSigninInternals::OnListAccountsComplete(
-    std::vector<std::pair<std::string, bool> >& gaia_accounts) {
+void AboutSigninInternals::OnGaiaAccountsInCookieUpdated(
+    const std::vector<std::pair<std::string, bool> >& gaia_accounts,
+    const GoogleServiceAuthError& error) {
+  if (error.state() != GoogleServiceAuthError::NONE)
+    return;
+
   base::DictionaryValue cookie_status;
   base::ListValue* cookie_info = new base::ListValue();
   cookie_status.Set("cookie_info", cookie_info);
diff --git a/components/signin/core/browser/about_signin_internals.h b/components/signin/core/browser/about_signin_internals.h
index e5850d1..a2c1d23 100644
--- a/components/signin/core/browser/about_signin_internals.h
+++ b/components/signin/core/browser/about_signin_internals.h
@@ -13,11 +13,11 @@
 #include "base/observer_list.h"
 #include "base/values.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "components/signin/core/browser/signin_client.h"
 #include "components/signin/core/browser/signin_error_controller.h"
 #include "components/signin/core/browser/signin_internals_util.h"
 #include "components/signin/core/browser/signin_manager.h"
-#include "google_apis/gaia/gaia_auth_consumer.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 
 class AccountTrackerService;
@@ -35,7 +35,7 @@
     : public KeyedService,
       public signin_internals_util::SigninDiagnosticsObserver,
       public OAuth2TokenService::DiagnosticsObserver,
-      public GaiaAuthConsumer,
+      public GaiaCookieManagerService::Observer,
       SigninManagerBase::Observer,
       SigninErrorController::Observer {
  public:
@@ -52,7 +52,8 @@
   AboutSigninInternals(ProfileOAuth2TokenService* token_service,
                        AccountTrackerService* account_tracker,
                        SigninManagerBase* signin_manager,
-                       SigninErrorController* signin_error_controller);
+                       SigninErrorController* signin_error_controller,
+                       GaiaCookieManagerService* cookie_manager_service);
   ~AboutSigninInternals() override;
 
   // Each instance of SigninInternalsUI adds itself as an observer to be
@@ -87,9 +88,10 @@
   //  }
   scoped_ptr<base::DictionaryValue> GetSigninStatus();
 
-  // Triggers a ListAccounts call to acquire a list of the email addresses
-  // corresponding to the cookies residing on the current cookie jar.
-  void GetCookieAccountsAsync();
+  // GaiaCookieManagerService::Observer implementations.
+  void OnGaiaAccountsInCookieUpdated(
+      const std::vector<std::pair<std::string, bool> >& gaia_accounts,
+      const GoogleServiceAuthError& error) override;
 
  private:
   // Encapsulates diagnostic information about tokens for different services.
@@ -173,10 +175,6 @@
   void OnTokenRemoved(const std::string& account_id,
                       const OAuth2TokenService::ScopeSet& scopes) override;
 
-  // GaiaAuthConsumer implementations.
-  void OnListAccountsSuccess(const std::string& data) override;
-  void OnListAccountsFailure(const GoogleServiceAuthError& error) override;
-
   // SigninManagerBase::Observer implementations.
   void GoogleSigninFailed(const GoogleServiceAuthError& error) override;
   void GoogleSigninSucceeded(const std::string& account_id,
@@ -187,15 +185,6 @@
 
   void NotifyObservers();
 
-  // Callback for ListAccounts. Once the email addresses are fetched from GAIA,
-  // they are pushed to the signin_internals_ui.
-  void OnListAccountsComplete(
-      std::vector<std::pair<std::string, bool> >& gaia_accounts);
-
-  // Called when a cookie changes. If the cookie relates to a GAIA LSID cookie,
-  // then we call ListAccounts and update the UI element.
-  void OnCookieChanged(const net::CanonicalCookie& cookie, bool removed);
-
   // SigninErrorController::Observer implementation
   void OnErrorChanged() override;
 
@@ -214,8 +203,8 @@
   // Weak pointer to the SigninErrorController
   SigninErrorController* signin_error_controller_;
 
-  // Fetcher for information about accounts in the cookie jar from GAIA.
-  scoped_ptr<GaiaAuthFetcher> gaia_fetcher_;
+  // Weak pointer to the GaiaCookieManagerService
+  GaiaCookieManagerService* cookie_manager_service_;
 
   // Encapsulates the actual signin and token related values.
   // Most of the values are mirrored in the prefs for persistence.
@@ -223,9 +212,6 @@
 
   ObserverList<Observer> signin_observers_;
 
-  scoped_ptr<SigninClient::CookieChangedSubscription>
-      cookie_changed_subscription_;
-
   DISALLOW_COPY_AND_ASSIGN(AboutSigninInternals);
 };
 
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc
index efe594db..aecbe9b1 100644
--- a/components/signin/core/browser/account_reconcilor.cc
+++ b/components/signin/core/browser/account_reconcilor.cc
@@ -16,12 +16,9 @@
 #include "components/signin/core/browser/signin_client.h"
 #include "components/signin/core/browser/signin_metrics.h"
 #include "components/signin/core/common/profile_management_switches.h"
-#include "google_apis/gaia/gaia_auth_fetcher.h"
 #include "google_apis/gaia/gaia_auth_util.h"
-#include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
 #include "google_apis/gaia/gaia_urls.h"
-#include "net/cookies/canonical_cookie.h"
 
 
 namespace {
@@ -67,7 +64,6 @@
       registered_with_content_settings_(false),
       is_reconcile_started_(false),
       first_execution_(true),
-      are_gaia_accounts_set_(false),
       chrome_accounts_changed_(false) {
   VLOG(1) << "AccountReconcilor::AccountReconcilor";
 }
@@ -87,7 +83,6 @@
   // wait for signin.
   if (IsProfileConnected()) {
     RegisterWithCookieManagerService();
-    RegisterForCookieChanges();
     RegisterWithContentSettings();
     RegisterWithTokenService();
 
@@ -101,29 +96,12 @@
 
 void AccountReconcilor::Shutdown() {
   VLOG(1) << "AccountReconcilor::Shutdown";
-  gaia_fetcher_.reset();
-  get_gaia_accounts_callbacks_.clear();
   UnregisterWithCookieManagerService();
   UnregisterWithSigninManager();
   UnregisterWithTokenService();
-  UnregisterForCookieChanges();
   UnregisterWithContentSettings();
 }
 
-void AccountReconcilor::RegisterForCookieChanges() {
-  // First clear any existing registration to avoid DCHECKs that can otherwise
-  // go off in some embedders on reauth (e.g., ChromeSigninClient).
-  UnregisterForCookieChanges();
-  cookie_changed_subscription_ = client_->AddCookieChangedCallback(
-      GaiaUrls::GetInstance()->gaia_url(),
-      "LSID",
-      base::Bind(&AccountReconcilor::OnCookieChanged, base::Unretained(this)));
-}
-
-void AccountReconcilor::UnregisterForCookieChanges() {
-  cookie_changed_subscription_.reset();
-}
-
 void AccountReconcilor::RegisterWithSigninManager() {
   signin_manager_->AddObserver(this);
 }
@@ -198,24 +176,6 @@
   return signin_manager_->IsAuthenticated();
 }
 
-void AccountReconcilor::OnCookieChanged(const net::CanonicalCookie& cookie,
-                                        bool removed) {
-  DCHECK_EQ("LSID", cookie.Name());
-  DCHECK_EQ(GaiaUrls::GetInstance()->gaia_url().host(), cookie.Domain());
-  if (cookie.IsSecure() && cookie.IsHttpOnly()) {
-    VLOG(1) << "AccountReconcilor::OnCookieChanged: LSID changed";
-
-    // It is possible that O2RT is not available at this moment.
-    if (!token_service_->GetAccounts().size()) {
-      VLOG(1) << "AccountReconcilor::OnCookieChanged: cookie change is ingored"
-                 "because O2RT is not available yet.";
-      return;
-    }
-
-    StartReconcile();
-  }
-}
-
 void AccountReconcilor::OnContentSettingChanged(
     const ContentSettingsPattern& primary_pattern,
     const ContentSettingsPattern& secondary_pattern,
@@ -249,7 +209,6 @@
                                               const std::string& password) {
   VLOG(1) << "AccountReconcilor::GoogleSigninSucceeded: signed in";
   RegisterWithCookieManagerService();
-  RegisterForCookieChanges();
   RegisterWithContentSettings();
   RegisterWithTokenService();
 }
@@ -257,12 +216,9 @@
 void AccountReconcilor::GoogleSignedOut(const std::string& account_id,
                                         const std::string& username) {
   VLOG(1) << "AccountReconcilor::GoogleSignedOut: signed out";
-  gaia_fetcher_.reset();
-  get_gaia_accounts_callbacks_.clear();
   AbortReconcile();
   UnregisterWithCookieManagerService();
   UnregisterWithTokenService();
-  UnregisterForCookieChanges();
   UnregisterWithContentSettings();
   PerformLogoutAllAccountsAction();
 }
@@ -289,13 +245,12 @@
     return;
   }
 
-  if (is_reconcile_started_ || get_gaia_accounts_callbacks_.size() > 0)
+  if (is_reconcile_started_)
     return;
 
   is_reconcile_started_ = true;
 
   // Reset state for validating gaia cookie.
-  are_gaia_accounts_set_ = false;
   gaia_accounts_.clear();
 
   // Reset state for validating oauth2 tokens.
@@ -304,78 +259,24 @@
   add_to_cookie_.clear();
   ValidateAccountsFromTokenService();
 
-  GetAccountsFromCookie(base::Bind(
-      &AccountReconcilor::ContinueReconcileActionAfterGetGaiaAccounts,
-      base::Unretained(this)));
-}
-
-void AccountReconcilor::GetAccountsFromCookie(
-    GetAccountsFromCookieCallback callback) {
-  get_gaia_accounts_callbacks_.push_back(callback);
-  if (!gaia_fetcher_)
-    MayBeDoNextListAccounts();
-}
-
-void AccountReconcilor::OnListAccountsSuccess(const std::string& data) {
-  gaia_fetcher_.reset();
-
-  // Get account information from response data.
-  std::vector<std::pair<std::string, bool> > gaia_accounts;
-  bool valid_json = gaia::ParseListAccountsData(data, &gaia_accounts);
-  if (!valid_json) {
-    VLOG(1) << "AccountReconcilor::OnListAccountsSuccess: parsing error";
-  } else if (gaia_accounts.size() > 0) {
-    VLOG(1) << "AccountReconcilor::OnListAccountsSuccess: "
-            << "Gaia " << gaia_accounts.size() << " accounts, "
-            << "Primary is '" << gaia_accounts[0].first << "'";
-  } else {
-    VLOG(1) << "AccountReconcilor::OnListAccountsSuccess: No accounts";
-  }
-
-  // There must be at least one callback waiting for result.
-  DCHECK(!get_gaia_accounts_callbacks_.empty());
-
-  GoogleServiceAuthError error =
-      !valid_json ? GoogleServiceAuthError(
-                        GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE)
-                  : GoogleServiceAuthError::AuthErrorNone();
-  get_gaia_accounts_callbacks_.front().Run(error, gaia_accounts);
-  get_gaia_accounts_callbacks_.pop_front();
-
-  MayBeDoNextListAccounts();
-}
-
-void AccountReconcilor::OnListAccountsFailure(
-    const GoogleServiceAuthError& error) {
-  gaia_fetcher_.reset();
-  VLOG(1) << "AccountReconcilor::OnListAccountsFailure: " << error.ToString();
-  std::vector<std::pair<std::string, bool> > empty_accounts;
-
-  // There must be at least one callback waiting for result.
-  DCHECK(!get_gaia_accounts_callbacks_.empty());
-
-  get_gaia_accounts_callbacks_.front().Run(error, empty_accounts);
-  get_gaia_accounts_callbacks_.pop_front();
-
-  MayBeDoNextListAccounts();
-}
-
-void AccountReconcilor::MayBeDoNextListAccounts() {
-  if (!get_gaia_accounts_callbacks_.empty()) {
-    gaia_fetcher_.reset(new GaiaAuthFetcher(
-        this, GaiaConstants::kReconcilorSource,
-        client_->GetURLRequestContext()));
-    gaia_fetcher_->StartListAccounts();
+  // Rely on the GCMS to manage calls to and responses from ListAccounts.
+  if (cookie_manager_service_->ListAccounts(&gaia_accounts_)) {
+    OnGaiaAccountsInCookieUpdated(
+        gaia_accounts_, GoogleServiceAuthError(GoogleServiceAuthError::NONE));
   }
 }
 
-void AccountReconcilor::ContinueReconcileActionAfterGetGaiaAccounts(
-    const GoogleServiceAuthError& error,
-    const std::vector<std::pair<std::string, bool> >& accounts) {
+void AccountReconcilor::OnGaiaAccountsInCookieUpdated(
+        const std::vector<std::pair<std::string, bool> >& accounts,
+        const GoogleServiceAuthError& error) {
   if (error.state() == GoogleServiceAuthError::NONE) {
     gaia_accounts_ = accounts;
-    are_gaia_accounts_set_ = true;
-    FinishReconcile();
+
+    // It is possible that O2RT is not available at this moment.
+    if (token_service_->GetAccounts().empty())
+      return;
+
+    is_reconcile_started_ ? FinishReconcile() : StartReconcile();
   } else {
     AbortReconcile();
   }
@@ -407,7 +308,6 @@
 
 void AccountReconcilor::FinishReconcile() {
   VLOG(1) << "AccountReconcilor::FinishReconcile";
-  DCHECK(are_gaia_accounts_set_);
   DCHECK(add_to_cookie_.empty());
   int number_gaia_accounts = gaia_accounts_.size();
   bool are_primaries_equal = number_gaia_accounts > 0 &&
diff --git a/components/signin/core/browser/account_reconcilor.h b/components/signin/core/browser/account_reconcilor.h
index 1350aa3a..8dbe06c 100644
--- a/components/signin/core/browser/account_reconcilor.h
+++ b/components/signin/core/browser/account_reconcilor.h
@@ -23,7 +23,6 @@
 #include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "components/signin/core/browser/signin_client.h"
 #include "components/signin/core/browser/signin_manager.h"
-#include "google_apis/gaia/gaia_auth_consumer.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 
@@ -37,7 +36,6 @@
 
 class AccountReconcilor : public KeyedService,
                           public content_settings::Observer,
-                          public GaiaAuthConsumer,
                           public GaiaCookieManagerService::Observer,
                           public OAuth2TokenService::Observer,
                           public SigninManagerBase::Observer {
@@ -58,23 +56,11 @@
   // KeyedService implementation.
   void Shutdown() override;
 
- protected:
-  // Used during GetAccountsFromCookie.
-  // Stores a callback for the next action to perform.
-  typedef base::Callback<
-      void(const GoogleServiceAuthError& error,
-           const std::vector<std::pair<std::string, bool> >&)>
-      GetAccountsFromCookieCallback;
-
-  virtual void GetAccountsFromCookie(GetAccountsFromCookieCallback callback);
-
  private:
   bool IsRegisteredWithTokenService() const {
     return registered_with_token_service_;
   }
 
-  bool AreGaiaAccountsSet() const { return are_gaia_accounts_set_; }
-
   const std::vector<std::pair<std::string, bool> >& GetGaiaAccountsForTesting()
       const {
     return gaia_accounts_;
@@ -112,8 +98,6 @@
                            AddAccountToCookieCompletedWithBogusAccount);
 
   // Register and unregister with dependent services.
-  void RegisterForCookieChanges();
-  void UnregisterForCookieChanges();
   void RegisterWithSigninManager();
   void UnregisterWithSigninManager();
   void RegisterWithTokenService();
@@ -137,15 +121,10 @@
   void CalculateIfReconcileIsDone();
   void ScheduleStartReconcileIfChromeAccountsChanged();
 
-  void ContinueReconcileActionAfterGetGaiaAccounts(
-      const GoogleServiceAuthError& error,
-      const std::vector<std::pair<std::string, bool> >& accounts);
   void ValidateAccountsFromTokenService();
   // Note internally that this |account_id| is added to the cookie jar.
   bool MarkAccountAsAddedToCookie(const std::string& account_id);
 
-  void OnCookieChanged(const net::CanonicalCookie& cookie, bool removed);
-
   // Overriden from content_settings::Observer.
   void OnContentSettingChanged(
       const ContentSettingsPattern& primary_pattern,
@@ -153,14 +132,13 @@
       ContentSettingsType content_type,
       std::string resource_identifier) override;
 
-  // Overriden from GaiaAuthConsumer.
-  void OnListAccountsSuccess(const std::string& data) override;
-  void OnListAccountsFailure(const GoogleServiceAuthError& error) override;
-
-  // Overriden from MergeSessionHelper::Observer.
+  // Overriden from GaiaGookieManagerService::Observer.
   void OnAddAccountToCookieCompleted(
       const std::string& account_id,
       const GoogleServiceAuthError& error) override;
+  void OnGaiaAccountsInCookieUpdated(
+        const std::vector<std::pair<std::string, bool> >& accounts,
+        const GoogleServiceAuthError& error) override;
 
   // Overriden from OAuth2TokenService::Observer.
   void OnEndBatchChanges() override;
@@ -172,8 +150,6 @@
   void GoogleSignedOut(const std::string& account_id,
                        const std::string& username) override;
 
-  void MayBeDoNextListAccounts();
-
   // The ProfileOAuth2TokenService associated with this reconcilor.
   ProfileOAuth2TokenService* token_service_;
 
@@ -186,7 +162,6 @@
   // The GaiaCookieManagerService associated with this reconcilor.
   GaiaCookieManagerService* cookie_manager_service_;
 
-  scoped_ptr<GaiaAuthFetcher> gaia_fetcher_;
   bool registered_with_token_service_;
   bool registered_with_cookie_manager_service_;
   bool registered_with_content_settings_;
@@ -205,7 +180,6 @@
   // a pair that holds the email address of the account and a boolean that
   // indicates whether the account is valid or not.  The accounts in the vector
   // are ordered the in same way as the gaia cookie.
-  bool are_gaia_accounts_set_;
   std::vector<std::pair<std::string, bool> > gaia_accounts_;
 
   // Used during reconcile action.
@@ -215,11 +189,6 @@
   std::vector<std::string> add_to_cookie_;
   bool chrome_accounts_changed_;
 
-  std::deque<GetAccountsFromCookieCallback> get_gaia_accounts_callbacks_;
-
-  scoped_ptr<SigninClient::CookieChangedSubscription>
-      cookie_changed_subscription_;
-
   DISALLOW_COPY_AND_ASSIGN(AccountReconcilor);
 };
 
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.cc b/components/signin/core/browser/gaia_cookie_manager_service.cc
index 1aef48f..ccea52aa 100644
--- a/components/signin/core/browser/gaia_cookie_manager_service.cc
+++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -15,6 +15,7 @@
 #include "base/values.h"
 #include "components/signin/core/browser/signin_metrics.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/oauth2_token_service.h"
@@ -72,12 +73,9 @@
 
 GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest(
     GaiaCookieRequestType request_type,
-    const std::string& account_id,
-    const GaiaCookieManagerService::ListAccountsCallback&
-        list_accounts_callback)
+    const std::string& account_id)
   : request_type_(request_type),
-    account_id_(account_id),
-    list_accounts_callback_(list_accounts_callback) {}
+    account_id_(account_id) {}
 
 GaiaCookieManagerService::GaiaCookieRequest::~GaiaCookieRequest() {
 }
@@ -87,28 +85,21 @@
 GaiaCookieManagerService::GaiaCookieRequest::CreateAddAccountRequest(
       const std::string& account_id) {
   return GaiaCookieManagerService::GaiaCookieRequest(
-      GaiaCookieManagerService::GaiaCookieRequestType::ADD_ACCOUNT,
-      account_id,
-      GaiaCookieManagerService::ListAccountsCallback());
+      GaiaCookieManagerService::GaiaCookieRequestType::ADD_ACCOUNT, account_id);
 }
 
 // static
 GaiaCookieManagerService::GaiaCookieRequest
 GaiaCookieManagerService::GaiaCookieRequest::CreateLogOutRequest() {
   return GaiaCookieManagerService::GaiaCookieRequest(
-      GaiaCookieManagerService::GaiaCookieRequestType::LOG_OUT,
-      std::string(),
-      GaiaCookieManagerService::ListAccountsCallback());
+      GaiaCookieManagerService::GaiaCookieRequestType::LOG_OUT, std::string());
 }
 
 GaiaCookieManagerService::GaiaCookieRequest
-GaiaCookieManagerService::GaiaCookieRequest::CreateListAccountsRequest(
-    const GaiaCookieManagerService::ListAccountsCallback&
-        list_accounts_callback) {
+GaiaCookieManagerService::GaiaCookieRequest::CreateListAccountsRequest() {
   return GaiaCookieManagerService::GaiaCookieRequest(
       GaiaCookieManagerService::GaiaCookieRequestType::LIST_ACCOUNTS,
-      std::string(),
-      list_accounts_callback);
+      std::string());
 }
 
 GaiaCookieManagerService::ExternalCcResultFetcher::ExternalCcResultFetcher(
@@ -295,7 +286,8 @@
       gaia_auth_fetcher_backoff_(&kBackoffPolicy),
       gaia_auth_fetcher_retries_(0),
       source_(source),
-      external_cc_result_fetched_(false) {
+      external_cc_result_fetched_(false),
+      list_accounts_fetched_once_(false) {
 }
 
 GaiaCookieManagerService::~GaiaCookieManagerService() {
@@ -303,8 +295,26 @@
   DCHECK(requests_.empty());
 }
 
+void GaiaCookieManagerService::Init() {
+  cookie_changed_subscription_ = signin_client_->AddCookieChangedCallback(
+      GaiaUrls::GetInstance()->google_url(),
+      "APISID",
+      base::Bind(&GaiaCookieManagerService::OnCookieChanged,
+                 base::Unretained(this)));
+}
+
+void GaiaCookieManagerService::Shutdown() {
+  cookie_changed_subscription_.reset();
+}
+
 void GaiaCookieManagerService::AddAccountToCookie(
     const std::string& account_id) {
+  if (!signin_client_->AreSigninCookiesAllowed()) {
+    SignalComplete(account_id,
+        GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+    return;
+  }
+
   DCHECK(!account_id.empty());
   VLOG(1) << "GaiaCookieManagerService::AddAccountToCookie: " << account_id;
   requests_.push_back(GaiaCookieRequest::CreateAddAccountRequest(account_id));
@@ -312,25 +322,26 @@
     StartFetchingUbertoken();
 }
 
-void GaiaCookieManagerService::ListAccounts(
-    const ListAccountsCallback& callback) {
-  // Not implemented yet.
-  NOTREACHED();
+bool GaiaCookieManagerService::ListAccounts(
+    std::vector<std::pair<std::string,bool> >* accounts) {
+  DCHECK(accounts);
+  accounts->clear();
 
-  // TODO(mlerman): Once this service listens to all GAIA cookie changes, cache
-  // the results of ListAccounts, and return them here if the GAIA cookie
-  // hasn't changed since the last call.
+  // There is a fetch currently executing (the results being provided in the
+  // parameter don't align with the fetches that have been started), or the list
+  // of accounts haven't been fetched even once.
+  if (!requests_.empty())
+    return false;
 
-  // If there's a GAIA call being executed, wait for it to complete. If it was
-  // another /ListAccounts then we'll use the results it caches.
-  if (gaia_auth_fetcher_)
-    return;
+  if (!list_accounts_fetched_once_) {
+    gaia_auth_fetcher_retries_ = 0;
+    requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest());
+    StartFetchingListAccounts();
+    return false;
+  }
 
-  VLOG(1) << "GaiaCookieManagerService::ListAccounts";
-  gaia_auth_fetcher_.reset(
-      new GaiaAuthFetcher(this, source_,
-                          signin_client_->GetURLRequestContext()));
-  gaia_auth_fetcher_->StartListAccounts();
+  accounts->assign(listed_accounts_.begin(), listed_accounts_.end());
+  return true;
 }
 
 void GaiaCookieManagerService::LogOutAllAccounts() {
@@ -394,6 +405,41 @@
   gaia_auth_fetcher_timer_.Stop();
 }
 
+// It is unknown if the cookie was changed because of processing initiated by
+// this class or other (such as the user clearing all cookies or a cookie being
+// evicted).
+void GaiaCookieManagerService::OnCookieChanged(
+    const net::CanonicalCookie& cookie,
+    bool removed) {
+  DCHECK_EQ("APISID", cookie.Name());
+  DCHECK_EQ(GaiaUrls::GetInstance()->google_url().host(), cookie.Domain());
+  gaia_auth_fetcher_retries_ = 0;
+  if (requests_.empty()) {
+    requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest());
+    StartFetchingListAccounts();
+  } else {
+    // Remove all pending ListAccount calls; for efficiency, only call
+    // after all pending requests are processed.
+    // Track requests to keep; all other unstarted requests will be removed.
+    std::vector<GaiaCookieRequest> requests_to_keep;
+
+    // Check all pending, non-executing requests.
+    for (auto it = requests_.begin() + 1; it != requests_.end(); ++it) {
+      // Keep all requests except for LIST_ACCOUNTS.
+      if (it->request_type() != GaiaCookieRequestType::LIST_ACCOUNTS)
+        requests_to_keep.push_back(*it);
+    }
+
+    // Remove all but the executing request. Re-add all requests being kept.
+    if (requests_.size() > 1) {
+      requests_.erase(requests_.begin() + 1, requests_.end());
+      requests_.insert(
+          requests_.end(), requests_to_keep.begin(), requests_to_keep.end());
+    }
+    requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest());
+  }
+}
+
 void GaiaCookieManagerService::SignalComplete(
     const std::string& account_id,
     const GoogleServiceAuthError& error) {
@@ -446,6 +492,8 @@
 void GaiaCookieManagerService::OnMergeSessionSuccess(const std::string& data) {
   VLOG(1) << "MergeSession successful account="
           << requests_.front().account_id();
+  DCHECK(requests_.front().request_type() ==
+         GaiaCookieRequestType::ADD_ACCOUNT);
   const std::string account_id = requests_.front().account_id();
   HandleNextRequest();
   SignalComplete(account_id, GoogleServiceAuthError::AuthErrorNone());
@@ -456,10 +504,11 @@
 
 void GaiaCookieManagerService::OnMergeSessionFailure(
     const GoogleServiceAuthError& error) {
+  DCHECK(requests_.front().request_type() ==
+         GaiaCookieRequestType::ADD_ACCOUNT);
   VLOG(1) << "Failed MergeSession"
           << " account=" << requests_.front().account_id()
           << " error=" << error.ToString();
-
   if (++gaia_auth_fetcher_retries_ < kMaxGaiaAuthFetcherRetries &&
       IsTransientError(error)) {
     gaia_auth_fetcher_backoff_.InformOfRequest(false);
@@ -475,6 +524,46 @@
   SignalComplete(account_id, error);
 }
 
+void GaiaCookieManagerService::OnListAccountsSuccess(const std::string& data) {
+  VLOG(1) << "ListAccounts successful";
+  DCHECK(requests_.front().request_type() ==
+         GaiaCookieRequestType::LIST_ACCOUNTS);
+  gaia_auth_fetcher_backoff_.InformOfRequest(true);
+
+  if (!gaia::ParseListAccountsData(data, &listed_accounts_)) {
+    listed_accounts_.clear();
+    OnListAccountsFailure(GoogleServiceAuthError(
+        GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE));
+    return;
+  }
+
+  list_accounts_fetched_once_ = true;
+  FOR_EACH_OBSERVER(Observer, observer_list_,
+      OnGaiaAccountsInCookieUpdated(
+          listed_accounts_,
+          GoogleServiceAuthError(GoogleServiceAuthError::NONE)));
+  HandleNextRequest();
+}
+
+void GaiaCookieManagerService::OnListAccountsFailure(
+    const GoogleServiceAuthError& error) {
+  VLOG(1) << "ListAccounts failed";
+  DCHECK(requests_.front().request_type() ==
+         GaiaCookieRequestType::LIST_ACCOUNTS);
+  if (++gaia_auth_fetcher_retries_ < kMaxGaiaAuthFetcherRetries &&
+      IsTransientError(error)) {
+    gaia_auth_fetcher_backoff_.InformOfRequest(false);
+    gaia_auth_fetcher_timer_.Start(
+        FROM_HERE, gaia_auth_fetcher_backoff_.GetTimeUntilRelease(), this,
+        &GaiaCookieManagerService::StartFetchingListAccounts);
+    return;
+  }
+
+  FOR_EACH_OBSERVER(Observer, observer_list_,
+      OnGaiaAccountsInCookieUpdated(listed_accounts_, error));
+  HandleNextRequest();
+}
+
 void GaiaCookieManagerService::StartFetchingUbertoken() {
   VLOG(1) << "GaiaCookieManagerService::StartFetching account_id="
           << requests_.front().account_id();
@@ -494,6 +583,14 @@
       external_cc_result_fetcher_.GetExternalCcResult());
 }
 
+void GaiaCookieManagerService::StartFetchingListAccounts() {
+  VLOG(1) << "GaiaCookieManagerService::ListAccounts";
+  gaia_auth_fetcher_.reset(
+      new GaiaAuthFetcher(this, source_,
+                          signin_client_->GetURLRequestContext()));
+  gaia_auth_fetcher_->StartListAccounts();
+}
+
 void GaiaCookieManagerService::OnURLFetchComplete(
     const net::URLFetcher* source) {
   DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT);
@@ -503,8 +600,20 @@
 
 void GaiaCookieManagerService::HandleNextRequest() {
   VLOG(1) << "GaiaCookieManagerService::HandleNextRequest";
-  requests_.pop_front();
+  if (requests_.front().request_type() ==
+      GaiaCookieRequestType::LIST_ACCOUNTS) {
+    // This and any directly subsequent list accounts would return the same.
+    while (!requests_.empty() && requests_.front().request_type() ==
+           GaiaCookieRequestType::LIST_ACCOUNTS) {
+      requests_.pop_front();
+    }
+  } else {
+    // Pop the completed request.
+    requests_.pop_front();
+  }
+
   gaia_auth_fetcher_.reset();
+  gaia_auth_fetcher_retries_ = 0;
   if (requests_.empty()) {
     VLOG(1) << "GaiaCookieManagerService::HandleNextRequest: no more";
     uber_token_fetcher_.reset();
@@ -517,6 +626,8 @@
         StartLogOutUrlFetch();
         break;
       case GaiaCookieRequestType::LIST_ACCOUNTS:
+        uber_token_fetcher_.reset();
+        StartFetchingListAccounts();
         break;
     };
   }
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.h b/components/signin/core/browser/gaia_cookie_manager_service.h
index ff9d4b0..74df85d 100644
--- a/components/signin/core/browser/gaia_cookie_manager_service.h
+++ b/components/signin/core/browser/gaia_cookie_manager_service.h
@@ -16,6 +16,7 @@
 #include "net/url_request/url_fetcher_delegate.h"
 
 class GaiaAuthFetcher;
+class GaiaCookieRequest;
 class GoogleServiceAuthError;
 class OAuth2TokenService;
 
@@ -36,11 +37,6 @@
                                  public UbertokenConsumer,
                                  public net::URLFetcherDelegate {
  public:
-  typedef base::Callback<void(const std::string& data,
-                              const GoogleServiceAuthError& error)>
-      ListAccountsCallback;
-
-
   enum GaiaCookieRequestType {
     ADD_ACCOUNT,
     LOG_OUT,
@@ -54,28 +50,19 @@
 
     GaiaCookieRequestType request_type() const { return request_type_; }
     const std::string& account_id() const {return account_id_; }
-    const GaiaCookieManagerService::ListAccountsCallback&
-        list_accounts_callback() const {
-      return list_accounts_callback_;
-    }
 
     static GaiaCookieRequest CreateAddAccountRequest(
         const std::string& account_id);
     static GaiaCookieRequest CreateLogOutRequest();
-    static GaiaCookieRequest CreateListAccountsRequest(
-        const GaiaCookieManagerService::ListAccountsCallback&
-            list_accounts_callback);
+    static GaiaCookieRequest CreateListAccountsRequest();
 
    private:
     GaiaCookieRequest(
         GaiaCookieRequestType request_type,
-        const std::string& account_id,
-        const GaiaCookieManagerService::ListAccountsCallback&
-            list_accounts_callback);
+        const std::string& account_id);
 
     GaiaCookieRequestType request_type_;
     std::string account_id_;
-    GaiaCookieManagerService::ListAccountsCallback list_accounts_callback_;
   };
 
   class Observer {
@@ -85,7 +72,18 @@
     // GoogleServiceAuthError::AuthErrorNone() then the merge succeeeded.
     virtual void OnAddAccountToCookieCompleted(
         const std::string& account_id,
-        const GoogleServiceAuthError& error) = 0;
+        const GoogleServiceAuthError& error) {}
+
+    // Called whenever the GaiaCookieManagerService's list of GAIA accounts is
+    // updated. The GCMS monitors the APISID cookie and triggers a /ListAccounts
+    // call on change. The GCMS will also call ListAccounts upon the first call
+    // to ListAccounts(). The GCMS will delay calling ListAccounts if other
+    // requests are in queue that would modify the APISID cookie.
+    // If the ListAccounts call fails and the GCMS cannot recover, the reason
+    // is passed in |error|.
+    virtual void OnGaiaAccountsInCookieUpdated(
+        const std::vector<std::pair<std::string, bool> >& accounts,
+        const GoogleServiceAuthError& error) {}
 
    protected:
     virtual ~Observer() {}
@@ -158,9 +156,16 @@
                            SigninClient* signin_client);
   ~GaiaCookieManagerService() override;
 
+  void Init();
+  void Shutdown() override;
+
   void AddAccountToCookie(const std::string& account_id);
 
-  void ListAccounts(const ListAccountsCallback& callback);
+  // Returns if the listed accounts are up to date or not (ignore the out
+  // parameter if return is false). The parameter will be assigned the current
+  // cached accounts. If the accounts are not up to date, a ListAccounts fetch
+  // is sent GAIA and Observer::OnGaiaAccountsInCookieUpdated will be called.
+  bool ListAccounts(std::vector<std::pair<std::string,bool> >* accounts);
 
   // Add or remove observers of this helper.
   void AddObserver(Observer* observer);
@@ -186,11 +191,19 @@
     return &external_cc_result_fetcher_;
   }
 
+  void set_list_accounts_fetched_once_for_testing(bool fetched) {
+    list_accounts_fetched_once_ = fetched;
+  }
+
  private:
   net::URLRequestContextGetter* request_context() {
     return signin_client_->GetURLRequestContext();
   }
 
+  // Called when a cookie changes. If the cookie relates to a GAIA APISID
+  // cookie, then we call ListAccounts and fire OnGaiaAccountsInCookieUpdated.
+  void OnCookieChanged(const net::CanonicalCookie& cookie, bool removed);
+
   // Overridden from UbertokenConsumer.
   void OnUbertokenSuccess(const std::string& token) override;
   void OnUbertokenFailure(const GoogleServiceAuthError& error) override;
@@ -198,6 +211,8 @@
   // Overridden from GaiaAuthConsumer.
   void OnMergeSessionSuccess(const std::string& data) override;
   void OnMergeSessionFailure(const GoogleServiceAuthError& error) override;
+  void OnListAccountsSuccess(const std::string& data) override;
+  void OnListAccountsFailure(const GoogleServiceAuthError& error) override;
 
   // Starts the proess of fetching the uber token and performing a merge session
   // for the next account.  Virtual so that it can be overriden in tests.
@@ -209,6 +224,9 @@
   // Virtual for testing purpose.
   virtual void StartLogOutUrlFetch();
 
+  // Virtual for testing purposes.
+  virtual void StartFetchingListAccounts();
+
   // Start the next request, if needed.
   void HandleNextRequest();
 
@@ -229,6 +247,10 @@
   // The last fetched ubertoken, for use in MergeSession retries.
   std::string uber_token_;
 
+  // Subscription to be called whenever the GAIA cookies change.
+  scoped_ptr<SigninClient::CookieChangedSubscription>
+      cookie_changed_subscription_;
+
   // A worklist for this class. Stores any pending requests that couldn't be
   // executed right away, since this class only permits one request to be
   // executed at a time.
@@ -244,6 +266,10 @@
   // True once the ExternalCCResultFetcher has completed once.
   bool external_cc_result_fetched_;
 
+  std::vector<std::pair<std::string, bool> > listed_accounts_;
+
+  bool list_accounts_fetched_once_;
+
   DISALLOW_COPY_AND_ASSIGN(GaiaCookieManagerService);
 };
 
diff --git a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
index cc04452..170a17a 100644
--- a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
+++ b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
@@ -31,8 +31,9 @@
 
   MOCK_METHOD2(OnAddAccountToCookieCompleted,
                void(const std::string&, const GoogleServiceAuthError&));
-  MOCK_METHOD1(GetCheckConnectionInfoCompleted, void(bool));
-
+  MOCK_METHOD2(OnGaiaAccountsInCookieUpdated,
+               void(const std::vector<std::pair<std::string, bool> >&,
+                    const GoogleServiceAuthError&));
  private:
   GaiaCookieManagerService* helper_;
 
@@ -59,6 +60,7 @@
   virtual ~InstrumentedGaiaCookieManagerService() { total--; }
 
   MOCK_METHOD0(StartFetchingUbertoken, void());
+  MOCK_METHOD0(StartFetchingListAccounts, void());
   MOCK_METHOD0(StartFetchingMergeSession, void());
   MOCK_METHOD0(StartLogOutUrlFetch, void());
 
@@ -74,7 +76,7 @@
         canceled_(GoogleServiceAuthError::REQUEST_CANCELED) {}
 
   OAuth2TokenService* token_service() { return &token_service_; }
-  SigninClient* signin_client() { return &signin_client_; }
+  TestSigninClient* signin_client() { return &signin_client_; }
 
   void SimulateUbertokenSuccess(UbertokenConsumer* consumer,
                                 const std::string& uber_token) {
@@ -96,6 +98,11 @@
     consumer->OnMergeSessionFailure(error);
   }
 
+  void SimulateListAccountsSuccess(GaiaAuthConsumer* consumer,
+                                   const std::string& data) {
+    consumer->OnListAccountsSuccess(data);
+  }
+
   void SimulateLogoutSuccess(net::URLFetcherDelegate* consumer) {
     consumer->OnURLFetchComplete(NULL);
   }
@@ -164,6 +171,17 @@
   DCHECK(!helper.is_running());
 }
 
+TEST_F(GaiaCookieManagerServiceTest, AddAccountCookiesDisabled) {
+  InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
+  MockObserver observer(&helper);
+  signin_client()->set_are_signin_cookies_allowed(false);
+
+  EXPECT_CALL(observer, OnAddAccountToCookieCompleted("[email protected]",
+                                                      canceled()));
+
+  helper.AddAccountToCookie("[email protected]");
+}
+
 TEST_F(GaiaCookieManagerServiceTest, MergeSessionRetried) {
   InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
   MockObserver observer(&helper);
@@ -378,7 +396,6 @@
   EXPECT_CALL(helper, StartLogOutUrlFetch());
   EXPECT_CALL(observer, OnAddAccountToCookieCompleted("[email protected]",
                                                       no_error()));
-
   helper.AddAccountToCookie("[email protected]");
   SimulateMergeSessionSuccess(&helper, "token1");
 
@@ -445,8 +462,6 @@
   InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
   MockObserver observer(&helper);
 
-  std::vector<std::string> current_accounts;
-
   EXPECT_CALL(helper, StartFetchingUbertoken());
   EXPECT_CALL(observer, OnAddAccountToCookieCompleted("[email protected]",
                                                       canceled()));
@@ -462,6 +477,37 @@
   SimulateLogoutSuccess(&helper);
 }
 
+TEST_F(GaiaCookieManagerServiceTest, ListAccountsFirstReturnsEmpty) {
+  InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
+  MockObserver observer(&helper);
+
+  std::vector<std::pair<std::string, bool> > list_accounts;
+
+  EXPECT_CALL(helper, StartFetchingListAccounts());
+
+  ASSERT_FALSE(helper.ListAccounts(&list_accounts));
+  ASSERT_TRUE(list_accounts.empty());
+}
+
+TEST_F(GaiaCookieManagerServiceTest, ListAccountsFindsOneAccount) {
+  InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
+  MockObserver observer(&helper);
+
+  std::vector<std::pair<std::string, bool> > list_accounts;
+  std::vector<std::pair<std::string, bool> > expected_accounts;
+  expected_accounts.push_back(std::pair<std::string, bool>(
+      "[email protected]", true));
+
+  EXPECT_CALL(helper, StartFetchingListAccounts());
+  EXPECT_CALL(observer, OnGaiaAccountsInCookieUpdated(expected_accounts,
+                                                      no_error()));
+
+  ASSERT_FALSE(helper.ListAccounts(&list_accounts));
+
+  SimulateListAccountsSuccess(&helper,
+      "[\"f\", [[\"b\", 0, \"n\", \"[email protected]\", \"p\", 0, 0, 0, 0, 1]]]");
+}
+
 TEST_F(GaiaCookieManagerServiceTest, ExternalCcResultFetcher) {
   InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
   GaiaCookieManagerService::ExternalCcResultFetcher result_fetcher(&helper);
diff --git a/components/signin/core/browser/signin_tracker.cc b/components/signin/core/browser/signin_tracker.cc
index ad5954f6..9e76b86 100644
--- a/components/signin/core/browser/signin_tracker.cc
+++ b/components/signin/core/browser/signin_tracker.cc
@@ -4,7 +4,6 @@
 
 #include "components/signin/core/browser/signin_tracker.h"
 
-#include "components/signin/core/browser/account_reconcilor.h"
 #include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/signin/core/browser/signin_client.h"
@@ -12,13 +11,11 @@
 
 SigninTracker::SigninTracker(ProfileOAuth2TokenService* token_service,
                              SigninManagerBase* signin_manager,
-                             AccountReconcilor* account_reconcilor,
                              GaiaCookieManagerService* cookie_manager_service,
                              SigninClient* client,
                              Observer* observer)
     : token_service_(token_service),
       signin_manager_(signin_manager),
-      account_reconcilor_(account_reconcilor),
       cookie_manager_service_(cookie_manager_service),
       client_(client),
       observer_(observer) {
diff --git a/components/signin/core/browser/signin_tracker.h b/components/signin/core/browser/signin_tracker.h
index 2dcd5c91..5f82bd00 100644
--- a/components/signin/core/browser/signin_tracker.h
+++ b/components/signin/core/browser/signin_tracker.h
@@ -10,7 +10,6 @@
 #include "components/signin/core/browser/signin_manager.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 
-class AccountReconcilor;
 class ProfileOAuth2TokenService;
 class SigninClient;
 
@@ -75,7 +74,6 @@
   // non-null.
   SigninTracker(ProfileOAuth2TokenService* token_service,
                 SigninManagerBase* signin_manager,
-                AccountReconcilor* account_reconcilor,
                 GaiaCookieManagerService* cookie_manager_service,
                 SigninClient* client,
                 Observer* observer);
@@ -100,7 +98,6 @@
   // The classes whose collective signin status we are tracking.
   ProfileOAuth2TokenService* token_service_;
   SigninManagerBase* signin_manager_;
-  AccountReconcilor* account_reconcilor_;
   GaiaCookieManagerService* cookie_manager_service_;
 
   // The client associated with this instance.
diff --git a/components/signin/ios/browser/merge_session_observer_bridge.h b/components/signin/ios/browser/merge_session_observer_bridge.h
index 6703ab72..8137dbbf1 100644
--- a/components/signin/ios/browser/merge_session_observer_bridge.h
+++ b/components/signin/ios/browser/merge_session_observer_bridge.h
@@ -12,7 +12,6 @@
 #include "base/macros.h"
 #include "components/signin/core/browser/gaia_cookie_manager_service.h"
 
-class AccountReconcilor;
 class GoogleServiceAuthError;
 
 @protocol MergeSessionObserverBridgeDelegate
diff --git a/google_apis/gaia/gaia_constants.cc b/google_apis/gaia/gaia_constants.cc
index 4c00536..d3d0cd9 100644
--- a/google_apis/gaia/gaia_constants.cc
+++ b/google_apis/gaia/gaia_constants.cc
@@ -11,7 +11,6 @@
 // Gaia uses this for accounting where login is coming from.
 const char kChromeOSSource[] = "chromeos";
 const char kChromeSource[] = "ChromiumBrowser";
-const char kReconcilorSource[] = "ChromiumReconcilor";
 
 // Service name for Gaia.  Used to convert to cookie auth.
 const char kGaiaService[] = "gaia";
diff --git a/google_apis/gaia/gaia_constants.h b/google_apis/gaia/gaia_constants.h
index d7ffb97..4786ac88 100644
--- a/google_apis/gaia/gaia_constants.h
+++ b/google_apis/gaia/gaia_constants.h
@@ -12,7 +12,6 @@
 // Gaia sources for accounting
 extern const char kChromeOSSource[];
 extern const char kChromeSource[];
-extern const char kReconcilorSource[];
 
 // Gaia services for requesting
 extern const char kGaiaService[];  // uber token
diff --git a/google_apis/gaia/gaia_switches.cc b/google_apis/gaia/gaia_switches.cc
index a1879d1..3e46829 100644
--- a/google_apis/gaia/gaia_switches.cc
+++ b/google_apis/gaia/gaia_switches.cc
@@ -6,6 +6,7 @@
 
 namespace switches {
 
+const char kGoogleUrl[]                     = "google-url";
 const char kGaiaUrl[]                       = "gaia-url";
 const char kGoogleApisUrl[]                 = "google-apis-url";
 const char kLsoUrl[]                        = "lso-url";
diff --git a/google_apis/gaia/gaia_switches.h b/google_apis/gaia/gaia_switches.h
index bc69ebe..63921a04 100644
--- a/google_apis/gaia/gaia_switches.h
+++ b/google_apis/gaia/gaia_switches.h
@@ -7,6 +7,10 @@
 
 namespace switches {
 
+// Specifies the domain of the APISID cookie. The default value is
+// "http://.google.com".
+extern const char kGoogleUrl[];
+
 // Specifies the path for GAIA authentication URL. The default value is
 // "https://accounts.google.com".
 extern const char kGaiaUrl[];
diff --git a/google_apis/gaia/gaia_urls.cc b/google_apis/gaia/gaia_urls.cc
index 6545d564..95d5245 100644
--- a/google_apis/gaia/gaia_urls.cc
+++ b/google_apis/gaia/gaia_urls.cc
@@ -13,6 +13,7 @@
 namespace {
 
 // Gaia service constants
+const char kDefaultGoogleUrl[] = "http://.google.com";
 const char kDefaultGaiaUrl[] = "https://accounts.google.com";
 const char kDefaultGoogleApisBaseUrl[] = "https://www.googleapis.com";
 
@@ -76,6 +77,8 @@
 }
 
 GaiaUrls::GaiaUrls() {
+  google_url_ = GetURLSwitchValueWithDefault(switches::kGoogleUrl,
+                                             kDefaultGoogleUrl);
   gaia_url_ = GetURLSwitchValueWithDefault(switches::kGaiaUrl, kDefaultGaiaUrl);
   lso_origin_url_ =
       GetURLSwitchValueWithDefault(switches::kLsoUrl, kDefaultGaiaUrl);
@@ -137,6 +140,10 @@
 GaiaUrls::~GaiaUrls() {
 }
 
+const GURL& GaiaUrls::google_url() const {
+  return google_url_;
+}
+
 const GURL& GaiaUrls::gaia_url() const {
   return gaia_url_;
 }
diff --git a/google_apis/gaia/gaia_urls.h b/google_apis/gaia/gaia_urls.h
index b5453f2..bbb21177 100644
--- a/google_apis/gaia/gaia_urls.h
+++ b/google_apis/gaia/gaia_urls.h
@@ -16,6 +16,7 @@
   static GaiaUrls* GetInstance();
 
   // The URLs for different calls in the Google Accounts programmatic login API.
+  const GURL& google_url() const;
   const GURL& gaia_url() const;
   const GURL& captcha_base_url() const;
   const GURL& client_login_url() const;
@@ -57,6 +58,7 @@
 
   friend struct DefaultSingletonTraits<GaiaUrls>;
 
+  GURL google_url_;
   GURL gaia_url_;
   GURL captcha_base_url_;