// Copyright (c) 2012 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/sync/test/integration/sync_test.h"

#include <stddef.h>
#include <stdint.h>

#include <limits>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/run_loop.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/bind_test_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.h"
#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/signin/chrome_signin_client_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/sync/test/integration/fake_server_invalidation_service.h"
#include "chrome/browser/sync/test/integration/p2p_invalidation_forwarder.h"
#include "chrome/browser/sync/test/integration/p2p_sync_refresher.h"
#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
#include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/search_test_utils.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/bookmarks/test/bookmark_test_helpers.h"
#include "components/browser_sync/profile_sync_service.h"
#include "components/google/core/browser/google_url_tracker.h"
#include "components/invalidation/impl/invalidation_switches.h"
#include "components/invalidation/impl/p2p_invalidation_service.h"
#include "components/invalidation/impl/p2p_invalidator.h"
#include "components/invalidation/impl/profile_identity_provider.h"
#include "components/invalidation/impl/profile_invalidation_provider.h"
#include "components/invalidation/public/invalidation_service.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/os_crypt/os_crypt_mocker.h"
#include "components/search_engines/template_url_service.h"
#include "components/sync/base/invalidation_helper.h"
#include "components/sync/driver/sync_driver_switches.h"
#include "components/sync/driver/sync_user_settings.h"
#include "components/sync/engine_impl/sync_scheduler_impl.h"
#include "components/sync/protocol/sync.pb.h"
#include "components/sync/test/fake_server/fake_server_network_resources.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_browser_thread.h"
#include "google_apis/gaia/gaia_urls.h"
#include "jingle/glue/network_service_config_test_util.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/base/network_change_notifier.h"
#include "net/base/port_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_fetcher.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "url/gurl.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/sync/test/integration/printers_helper.h"
#include "chrome/browser/sync/test/integration/sync_arc_package_helper.h"
#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
#include "chromeos/constants/chromeos_switches.h"
#include "components/arc/arc_util.h"
#endif  // defined(OS_CHROMEOS)

#if BUILDFLAG(ENABLE_APP_LIST)
#include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h"
#endif  // BUILDFLAG(ENABLE_APP_LIST)

using browser_sync::ProfileSyncService;
using content::BrowserThread;

namespace switches {
const char kPasswordFileForTest[] = "password-file-for-test";
const char kSyncUserForTest[] = "sync-user-for-test";
const char kSyncPasswordForTest[] = "sync-password-for-test";
}

namespace {

// Helper class to ensure a profile is registered before the manager is
// notified of creation.
class SyncProfileDelegate : public Profile::Delegate {
 public:
  explicit SyncProfileDelegate(
      const base::Callback<void(Profile*)>& on_profile_created_callback)
      : on_profile_created_callback_(on_profile_created_callback) {}
  ~SyncProfileDelegate() override {}

  void OnProfileCreated(Profile* profile,
                        bool success,
                        bool is_new_profile) override {
    g_browser_process->profile_manager()->RegisterTestingProfile(profile,
                                                                 true,
                                                                 false);

    // Perform any custom work needed before the profile is initialized.
    if (!on_profile_created_callback_.is_null())
      on_profile_created_callback_.Run(profile);

    g_browser_process->profile_manager()->OnProfileCreated(profile, success,
                                                           is_new_profile);
  }

 private:
  base::Callback<void(Profile*)> on_profile_created_callback_;

  DISALLOW_COPY_AND_ASSIGN(SyncProfileDelegate);
};

bool IsEncryptionComplete(const ProfileSyncService* service) {
  return service->GetUserSettings()->IsEncryptEverythingEnabled() &&
         !service->encryption_pending();
}

// Helper class to wait for encryption to complete.
class EncryptionChecker : public SingleClientStatusChangeChecker {
 public:
  explicit EncryptionChecker(ProfileSyncService* service)
      : SingleClientStatusChangeChecker(service) {}

  bool IsExitConditionSatisfied() override {
    return IsEncryptionComplete(service());
  }

  std::string GetDebugMessage() const override { return "Encryption"; }
};

std::unique_ptr<KeyedService> BuildFakeServerProfileInvalidationProvider(
    content::BrowserContext* context) {
  Profile* profile = static_cast<Profile*>(context);
  return std::make_unique<invalidation::ProfileInvalidationProvider>(
      std::make_unique<fake_server::FakeServerInvalidationService>(),
      std::make_unique<invalidation::ProfileIdentityProvider>(
          IdentityManagerFactory::GetForProfile(profile)));
}

std::unique_ptr<KeyedService> BuildP2PProfileInvalidationProvider(
    content::BrowserContext* context,
    syncer::P2PNotificationTarget notification_target) {
  Profile* profile = static_cast<Profile*>(context);
  auto config_helper =
      std::make_unique<jingle_glue::NetworkServiceConfigTestUtil>(
          profile->GetRequestContext());
  return std::make_unique<invalidation::ProfileInvalidationProvider>(
      std::make_unique<invalidation::P2PInvalidationService>(
          std::move(config_helper), content::GetNetworkConnectionTracker(),
          notification_target),
      std::make_unique<invalidation::ProfileIdentityProvider>(
          IdentityManagerFactory::GetForProfile(profile)));
}

std::unique_ptr<KeyedService> BuildSelfNotifyingP2PProfileInvalidationProvider(
    content::BrowserContext* context) {
  return BuildP2PProfileInvalidationProvider(context, syncer::NOTIFY_ALL);
}

std::unique_ptr<KeyedService> BuildRealisticP2PProfileInvalidationProvider(
    content::BrowserContext* context) {
  return BuildP2PProfileInvalidationProvider(context, syncer::NOTIFY_OTHERS);
}

}  // namespace

SyncTest::SyncTest(TestType test_type)
    : test_type_(test_type),
      server_type_(SERVER_TYPE_UNDECIDED),
      previous_profile_(nullptr),
      num_clients_(-1),
      use_verifier_(true),
      create_gaia_account_at_runtime_(false),
      test_shared_url_loader_factory_(
          base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
              &test_url_loader_factory_)) {
  sync_datatype_helper::AssociateWithTest(this);
  switch (test_type_) {
    case SINGLE_CLIENT:
    case SINGLE_CLIENT_LEGACY: {
      num_clients_ = 1;
      break;
    }
    case TWO_CLIENT:
    case TWO_CLIENT_LEGACY: {
      num_clients_ = 2;
      break;
    }
    default:
      NOTREACHED() << "Invalid test type specified.";
  }
}

SyncTest::~SyncTest() {}

void SyncTest::SetUp() {
  // Sets |server_type_| if it wasn't specified by the test.
  DecideServerType();

  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
  if (cl->HasSwitch(switches::kPasswordFileForTest)) {
    ReadPasswordFile();
  } else {
    // Decide on username to use or create one.
    if (cl->HasSwitch(switches::kSyncUserForTest)) {
      username_ = cl->GetSwitchValueASCII(switches::kSyncUserForTest);
    } else if (UsingExternalServers()) {
      // We assume the need to automatically create a Gaia account which
      // requires URL navigation and needs to be done outside SetUp() function.
      create_gaia_account_at_runtime_ = true;
      username_ = base::GenerateGUID();
    } else {
      username_ = "user@gmail.com";
    }
    // Decide on password to use.
    password_ = cl->HasSwitch(switches::kSyncPasswordForTest)
                    ? cl->GetSwitchValueASCII(switches::kSyncPasswordForTest)
                    : "password";
  }

  if (username_.empty() || password_.empty())
    LOG(FATAL) << "Cannot run sync tests without GAIA credentials.";

  // Mock the Mac Keychain service.  The real Keychain can block on user input.
  OSCryptMocker::SetUp();

  // Yield control back to the InProcessBrowserTest framework.
  InProcessBrowserTest::SetUp();
}

void SyncTest::TearDown() {
  // Clear any mock gaia responses that might have been set.
  ClearMockGaiaResponses();

  // Allow the InProcessBrowserTest framework to perform its tear down.
  InProcessBrowserTest::TearDown();

  // Stop the local python test server. This is a no-op if one wasn't started.
  TearDownLocalPythonTestServer();

  // Stop the local sync test server. This is a no-op if one wasn't started.
  TearDownLocalTestServer();

  // Return OSCrypt to its real behaviour
  OSCryptMocker::TearDown();

  test_shared_url_loader_factory_->Detach();
  fake_server_.reset();
}

void SyncTest::SetUpCommandLine(base::CommandLine* cl) {
  AddTestSwitches(cl);
  AddOptionalTypesToCommandLine(cl);

#if defined(OS_CHROMEOS)
  cl->AppendSwitch(chromeos::switches::kIgnoreUserProfileMappingForTests);
  arc::SetArcAvailableCommandLineForTesting(cl);
#endif
}

void SyncTest::AddTestSwitches(base::CommandLine* cl) {
  // Disable non-essential access of external network resources.
  if (!cl->HasSwitch(switches::kDisableBackgroundNetworking))
    cl->AppendSwitch(switches::kDisableBackgroundNetworking);

  if (!cl->HasSwitch(switches::kSyncShortInitialRetryOverride))
    cl->AppendSwitch(switches::kSyncShortInitialRetryOverride);

  if (!cl->HasSwitch(switches::kSyncShortNudgeDelayForTest))
    cl->AppendSwitch(switches::kSyncShortNudgeDelayForTest);
}

void SyncTest::AddOptionalTypesToCommandLine(base::CommandLine* cl) {}

bool SyncTest::CreateGaiaAccount(const std::string& username,
                                 const std::string& password) {
  std::string relative_url = base::StringPrintf("/CreateUsers?%s=%s",
                                                username.c_str(),
                                                password.c_str());
  GURL create_user_url =
      GaiaUrls::GetInstance()->gaia_url().Resolve(relative_url);
  // NavigateToURL blocks until the navigation finishes.
  ui_test_utils::NavigateToURL(browser(), create_user_url);
  content::WebContents* contents =
      browser()->tab_strip_model()->GetActiveWebContents();
  content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
  EXPECT_TRUE(entry)
      << "Could not get a hold on NavigationEntry post URL navigate.";
  DVLOG(1) << "Create Gaia account request return code = "
      << entry->GetHttpStatusCode();
  return entry->GetHttpStatusCode() == 200;
}

void SyncTest::BeforeSetupClient(int index) {}

bool SyncTest::CreateProfile(int index) {
  base::FilePath profile_path;

  base::ScopedAllowBlockingForTesting allow_blocking;
  if (UsingExternalServers() && num_clients_ > 1) {
    scoped_temp_dirs_.push_back(std::make_unique<base::ScopedTempDir>());
    // For multi profile UI signin, profile paths should be outside user data
    // dir to allow signing-in multiple profiles to same account. Otherwise, we
    // get an error that the profile has already signed in on this device.
    // Note: Various places in Chrome assume that all profiles are within the
    // user data dir. We violate that assumption here, which can lead to weird
    // issues, see https://crbug.com/801569 and the workaround in
    // TearDownOnMainThread.
    if (!scoped_temp_dirs_.back()->CreateUniqueTempDir()) {
      ADD_FAILURE();
      return false;
    }

    profile_path = scoped_temp_dirs_.back()->GetPath();
  } else {
    base::FilePath user_data_dir;
    base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);

    // Create new profiles in user data dir so that other profiles can know
    // about it. This is needed in tests such as supervised user cases which
    // assume browser->profile() as the custodian profile. Instead of creating
    // a new directory, we use a deterministic name such that PRE_ tests (i.e.
    // test that span browser restarts) can reuse the same directory and carry
    // over state.
    profile_path = user_data_dir.AppendASCII(
        base::StringPrintf("SyncIntegrationTestClient%d", index));
  }

  if (UsingExternalServers()) {
    // If running against an EXTERNAL_LIVE_SERVER, we signin profiles using real
    // GAIA server. This requires creating profiles with no test hooks.
    InitializeProfile(index, MakeProfileForUISignin(profile_path));
  } else {
    // Without need of real GAIA authentication, we create new test profiles.
    // For test profiles, a custom delegate needs to be used to do the
    // initialization work before the profile is registered.
    profile_delegates_[index] =
        std::make_unique<SyncProfileDelegate>(base::Bind(
            &SyncTest::InitializeProfile, base::Unretained(this), index));
    Profile* profile = MakeTestProfile(profile_path, index);
    ChromeSigninClient* signin_client = static_cast<ChromeSigninClient*>(
        ChromeSigninClientFactory::GetForProfile(profile));
    signin_client->SetURLLoaderFactoryForTest(test_shared_url_loader_factory_);
  }

  // Once profile initialization has kicked off, wait for it to finish.
  WaitForDataModels(GetProfile(index));
  return true;
}

// Called when the ProfileManager has created a profile.
// static
void SyncTest::CreateProfileCallback(const base::Closure& quit_closure,
                                     Profile* profile,
                                     Profile::CreateStatus status) {
  EXPECT_TRUE(profile);
  EXPECT_NE(Profile::CREATE_STATUS_LOCAL_FAIL, status);
  EXPECT_NE(Profile::CREATE_STATUS_REMOTE_FAIL, status);
  // This will be called multiple times. Wait until the profile is initialized
  // fully to quit the loop.
  if (status == Profile::CREATE_STATUS_INITIALIZED)
    quit_closure.Run();
}

// TODO(shadi): Ideally creating a new profile should not depend on signin
// process. We should try to consolidate MakeProfileForUISignin() and
// MakeProfile(). Major differences are profile paths and creation methods. For
// UI signin we need profiles in unique user data dir's and we need to use
// ProfileManager::CreateProfileAsync() for proper profile creation.
// static
Profile* SyncTest::MakeProfileForUISignin(base::FilePath profile_path) {
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  base::RunLoop run_loop;
  ProfileManager::CreateCallback create_callback = base::Bind(
      &CreateProfileCallback, run_loop.QuitClosure());
  profile_manager->CreateProfileAsync(profile_path,
                                      create_callback,
                                      base::string16(),
                                      std::string());
  run_loop.Run();
  return profile_manager->GetProfileByPath(profile_path);
}

Profile* SyncTest::MakeTestProfile(base::FilePath profile_path, int index) {
  const auto& preference_contents_it =
      preexisting_preferences_file_contents_.find(index);
  if (preference_contents_it != preexisting_preferences_file_contents_.end() &&
      !preference_contents_it->second.empty()) {
    // The profile directory might not exist yet (e.g. for the verifier_
    // profile).
    if (!base::PathExists(profile_path) &&
        !base::CreateDirectory(profile_path)) {
      LOG(FATAL) << "Could not create profile directory: " << profile_path;
    }
    base::FilePath pref_path(profile_path.Append(chrome::kPreferencesFilename));
    int write_result =
        base::WriteFile(pref_path, preference_contents_it->second.c_str(),
                        preference_contents_it->second.size());
    if (write_result !=
        static_cast<int>(preference_contents_it->second.size())) {
      LOG(FATAL) << "Preexisting Preferences file could not be written to "
                 << pref_path;
    }
  }

  Profile* profile =
      Profile::CreateProfile(profile_path, profile_delegates_[index].get(),
                             Profile::CREATE_MODE_SYNCHRONOUS);
  return profile;
}

Profile* SyncTest::GetProfile(int index) {
  EXPECT_FALSE(profiles_.empty()) << "SetupClients() has not yet been called.";
  EXPECT_FALSE(index < 0 || index >= static_cast<int>(profiles_.size()))
      << "GetProfile(): Index is out of bounds.";

  Profile* profile = profiles_[index];
  EXPECT_NE(nullptr, profile) << "No profile found at index: " << index;

  return profile;
}

std::vector<Profile*> SyncTest::GetAllProfiles() {
  std::vector<Profile*> profiles;
  if (use_verifier()) {
    profiles.push_back(verifier());
  }
  for (int i = 0; i < num_clients(); ++i) {
    profiles.push_back(GetProfile(i));
  }
  return profiles;
}

Browser* SyncTest::GetBrowser(int index) {
  EXPECT_FALSE(browsers_.empty()) << "SetupClients() has not yet been called.";
  EXPECT_FALSE(index < 0 || index >= static_cast<int>(browsers_.size()))
      << "GetBrowser(): Index is out of bounds.";

  Browser* browser = browsers_[index];
  EXPECT_NE(browser, nullptr);

  return browsers_[index];
}

Browser* SyncTest::AddBrowser(int profile_index) {
  Profile* profile = GetProfile(profile_index);
  browsers_.push_back(new Browser(Browser::CreateParams(profile, true)));
  profiles_.push_back(profile);

  return browsers_[browsers_.size() - 1];
}

ProfileSyncServiceHarness* SyncTest::GetClient(int index) {
  if (clients_.empty())
    LOG(FATAL) << "SetupClients() has not yet been called.";
  if (index < 0 || index >= static_cast<int>(clients_.size()))
    LOG(FATAL) << "GetClient(): Index is out of bounds.";
  return clients_[index].get();
}

std::vector<ProfileSyncServiceHarness*> SyncTest::GetSyncClients() {
  std::vector<ProfileSyncServiceHarness*> clients(clients_.size());
  for (size_t i = 0; i < clients_.size(); ++i)
    clients[i] = clients_[i].get();
  return clients;
}

ProfileSyncService* SyncTest::GetSyncService(int index) {
  return ProfileSyncServiceFactory::GetForProfile(GetProfile(index));
}

std::vector<ProfileSyncService*> SyncTest::GetSyncServices() {
  std::vector<ProfileSyncService*> services;
  for (int i = 0; i < num_clients(); ++i) {
    services.push_back(GetSyncService(i));
  }
  return services;
}

Profile* SyncTest::verifier() {
  if (!use_verifier_)
    LOG(FATAL) << "Verifier account is disabled.";
  if (verifier_ == nullptr)
    LOG(FATAL) << "SetupClients() has not yet been called.";
  return verifier_;
}

void SyncTest::DisableVerifier() {
  use_verifier_ = false;
}

bool SyncTest::SetupClients() {
  previous_profile_ =
      g_browser_process->profile_manager()->GetLastUsedProfile();

  base::ScopedAllowBlockingForTesting allow_blocking;
  if (num_clients_ <= 0)
    LOG(FATAL) << "num_clients_ incorrectly initialized.";
  if (!profiles_.empty() || !browsers_.empty() || !clients_.empty())
    LOG(FATAL) << "SetupClients() has already been called.";

  // Create the required number of sync profiles, browsers and clients.
  profiles_.resize(num_clients_);
  profile_delegates_.resize(num_clients_ + 1);  // + 1 for the verifier.
  clients_.resize(num_clients_);
  invalidation_forwarders_.resize(num_clients_);
  sync_refreshers_.resize(num_clients_);
  fake_server_invalidation_services_.resize(num_clients_);

  if (create_gaia_account_at_runtime_) {
    if (!UsingExternalServers()) {
      ADD_FAILURE() << "Cannot create Gaia accounts without external "
                       "authentication servers.";
      return false;
    }
    if (!CreateGaiaAccount(username_, password_))
      LOG(FATAL) << "Could not create Gaia account.";
  }

  auto* cl = base::CommandLine::ForCurrentProcess();
  if (!cl->HasSwitch(switches::kSyncDeferredStartupTimeoutSeconds)) {
    cl->AppendSwitchASCII(switches::kSyncDeferredStartupTimeoutSeconds, "1");
  }

#if defined(OS_CHROMEOS)
  // ARC_PACKAGE do not support supervised users, switches::kSupervisedUserId
  // need to be set in SetUpCommandLine() when a test will use supervise users.
  if (!cl->HasSwitch(switches::kSupervisedUserId)) {
    // Sets Arc flags, need to be called before create test profiles.
    ArcAppListPrefsFactory::SetFactoryForSyncTest();
  }

  // Uses a fake app list model updater to avoid interacting with Ash.
  model_updater_factory_ = std::make_unique<
      app_list::AppListSyncableService::ScopedModelUpdaterFactoryForTest>(
      base::Bind([]() -> std::unique_ptr<AppListModelUpdater> {
        return std::make_unique<FakeAppListModelUpdater>();
      }));
#endif

  for (int i = 0; i < num_clients_; ++i) {
    BeforeSetupClient(i);
    if (!CreateProfile(i)) {
      return false;
    }
  }

  // Verifier account is not useful when running against external servers.
  if (UsingExternalServers())
    DisableVerifier();

  // Create the verifier profile.
  if (use_verifier_) {
    base::FilePath user_data_dir;
    base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
    profile_delegates_[num_clients_] =
        std::make_unique<SyncProfileDelegate>(base::Callback<void(Profile*)>());
    verifier_ = MakeTestProfile(
        user_data_dir.Append(FILE_PATH_LITERAL("Verifier")), num_clients_);
    WaitForDataModels(verifier());
  }

#if defined(OS_CHROMEOS)
  if (ArcAppListPrefsFactory::IsFactorySetForSyncTest()) {
    // Init SyncArcPackageHelper to ensure that the arc services are initialized
    // for each Profile, only can be called after test profiles are created.
    if (!sync_arc_helper())
      return false;
  }
#endif

  return true;
}

void SyncTest::InitializeProfile(int index, Profile* profile) {
  DCHECK(profile);
  profiles_[index] = profile;

  SetUpInvalidations(index);
  AddBrowser(index);

  // Make sure the ProfileSyncService has been created before creating the
  // ProfileSyncServiceHarness - some tests expect the ProfileSyncService to
  // already exist.
  ProfileSyncService* profile_sync_service =
      ProfileSyncServiceFactory::GetForProfile(GetProfile(index));

  if (server_type_ == IN_PROCESS_FAKE_SERVER) {
    // TODO(pvalenzuela): Run the fake server via EmbeddedTestServer.
    profile_sync_service->OverrideNetworkResourcesForTest(
        base::WrapUnique<syncer::NetworkResources>(
            new fake_server::FakeServerNetworkResources(
                fake_server_->AsWeakPtr())));
  }

  ProfileSyncServiceHarness::SigninType singin_type = UsingExternalServers()
          ? ProfileSyncServiceHarness::SigninType::UI_SIGNIN
          : ProfileSyncServiceHarness::SigninType::FAKE_SIGNIN;

  DCHECK(!clients_[index]);
  clients_[index] = ProfileSyncServiceHarness::Create(
      GetProfile(index), username_, password_, singin_type);
  EXPECT_NE(nullptr, GetClient(index)) << "Could not create Client " << index;
  InitializeInvalidations(index);
}

void SyncTest::DisableNotificationsForClient(int index) {
  fake_server_->RemoveObserver(fake_server_invalidation_services_[index]);
}

void SyncTest::SetEncryptionPassphraseForClient(int index,
                                                const std::string& passphrase) {
  // Must be called before client initialization.
  DCHECK(clients_.empty());
  client_encryption_passphrases_[index] = passphrase;
}

void SyncTest::SetDecryptionPassphraseForClient(int index,
                                                const std::string& passphrase) {
  // Must be called before client initialization.
  DCHECK(clients_.empty());
  client_decryption_passphrases_[index] = passphrase;
}

void SyncTest::SetupMockGaiaResponsesForProfile(Profile* profile) {
  ChromeSigninClient* signin_client = static_cast<ChromeSigninClient*>(
      ChromeSigninClientFactory::GetForProfile(profile));
  signin_client->SetURLLoaderFactoryForTest(test_shared_url_loader_factory_);
}

void SyncTest::SetUpInvalidations(int index) {
  bool fcm_invalidations_enabled =
      base::FeatureList::IsEnabled(invalidation::switches::kFCMInvalidations);
  switch (server_type_) {
    case EXTERNAL_LIVE_SERVER:
      // DO NOTHING. External live sync servers use GCM to notify profiles of
      // any invalidations in sync'ed data. In this case, to notify other
      // profiles of invalidations, we use sync refresh notifications instead.
      break;

    case IN_PROCESS_FAKE_SERVER: {
      KeyedService* test_factory;
      if (fcm_invalidations_enabled) {
        test_factory =
            invalidation::ProfileInvalidationProviderFactory::GetInstance()
                ->SetTestingFactoryAndUse(
                    GetProfile(index),
                    base::BindRepeating(
                        &BuildFakeServerProfileInvalidationProvider));

      } else {
        test_factory =
            invalidation::DeprecatedProfileInvalidationProviderFactory::
                GetInstance()
                    ->SetTestingFactoryAndUse(
                        GetProfile(index),
                        base::BindRepeating(
                            &BuildFakeServerProfileInvalidationProvider));
      }
      invalidation::InvalidationService* invalidation_service =
          static_cast<invalidation::ProfileInvalidationProvider*>(test_factory)
              ->GetInvalidationService();
      auto* fake_invalidation_service =
          static_cast<fake_server::FakeServerInvalidationService*>(
              invalidation_service);

      fake_server_->AddObserver(fake_invalidation_service);
      if (TestUsesSelfNotifications())
        fake_invalidation_service->EnableSelfNotifications();
      else
        fake_invalidation_service->DisableSelfNotifications();
      fake_server_invalidation_services_[index] = fake_invalidation_service;
      break;
    }
    case SERVER_TYPE_UNDECIDED:
    case LOCAL_PYTHON_SERVER:
      BrowserContextKeyedServiceFactory::TestingFactory invalidation_provider =
          base::BindRepeating(
              TestUsesSelfNotifications()
                  ? &BuildSelfNotifyingP2PProfileInvalidationProvider
                  : &BuildRealisticP2PProfileInvalidationProvider);
      if (fcm_invalidations_enabled) {
        invalidation::ProfileInvalidationProviderFactory::GetInstance()
            ->SetTestingFactoryAndUse(GetProfile(index),
                                      std::move(invalidation_provider));
      } else {
        invalidation::DeprecatedProfileInvalidationProviderFactory::
            GetInstance()
                ->SetTestingFactoryAndUse(GetProfile(index),
                                          std::move(invalidation_provider));
      }
  }
}

void SyncTest::InitializeInvalidations(int index) {
  // Lazily create |configuration_refresher_| the first time we get here (or the
  // first time after a previous call to StopConfigurationRefresher).
  if (!configuration_refresher_) {
    configuration_refresher_ = std::make_unique<ConfigurationRefresher>();
  }

  switch (server_type_) {
    case EXTERNAL_LIVE_SERVER:
      // DO NOTHING. External live sync servers use GCM to notify profiles of
      // any invalidations in sync'ed data. In this case, to notify other
      // profiles of invalidations, we use sync refresh notifications instead.
      break;
    case IN_PROCESS_FAKE_SERVER: {
      configuration_refresher_->Observe(
          ProfileSyncServiceFactory::GetForProfile(GetProfile(index)));
      break;
    }
    case SERVER_TYPE_UNDECIDED:
    case LOCAL_PYTHON_SERVER:
      bool fcm_invalidations_enabled = base::FeatureList::IsEnabled(
          invalidation::switches::kFCMInvalidations);
      invalidation::InvalidationService* invalidation_service;
      if (fcm_invalidations_enabled) {
        invalidation_service =
            invalidation::ProfileInvalidationProviderFactory::GetForProfile(
                GetProfile(index))
                ->GetInvalidationService();
      } else {
        invalidation_service =
            invalidation::DeprecatedProfileInvalidationProviderFactory::
                GetForProfile(GetProfile(index))
                    ->GetInvalidationService();
      }
      invalidation::P2PInvalidationService* p2p_invalidation_service =
          static_cast<invalidation::P2PInvalidationService*>(
              invalidation_service);
      p2p_invalidation_service->UpdateCredentials(username_, password_);
      // Start listening for and emitting notifications of commits.
      DCHECK(!invalidation_forwarders_[index]);
      invalidation_forwarders_[index] =
          std::make_unique<P2PInvalidationForwarder>(clients_[index]->service(),
                                                     p2p_invalidation_service);
  }
}

bool SyncTest::SetupSync() {
  base::ScopedAllowBlockingForTesting allow_blocking;
  // Create sync profiles and clients if they haven't already been created.
  if (profiles_.empty()) {
    if (!SetupClients()) {
      LOG(FATAL) << "SetupClients() failed.";
      return false;
    }
  }

  int clientIndex = 0;
  // If we're using external servers, clear server data so the account starts
  // with a clean slate.
  if (UsingExternalServers()) {
    if (!SetupAndClearClient(clientIndex++)) {
      LOG(FATAL) << "Setting up and clearing data for client "
                 << clientIndex - 1 << " failed";
      return false;
    }
  }

  // Sync each of the profiles.
  for (; clientIndex < num_clients_; clientIndex++) {
    ProfileSyncServiceHarness* client = GetClient(clientIndex);
    DVLOG(1) << "Setting up " << clientIndex << " client";

    auto decryption_passphrase_it =
        client_decryption_passphrases_.find(clientIndex);
    auto encryption_passphrase_it =
        client_encryption_passphrases_.find(clientIndex);
    bool decryption_passphrase_provided =
        (decryption_passphrase_it != client_decryption_passphrases_.end());
    bool encryption_passphrase_provided =
        (encryption_passphrase_it != client_encryption_passphrases_.end());
    if (decryption_passphrase_provided && encryption_passphrase_provided) {
      LOG(FATAL) << "Both an encryption and decryption passphrase were "
                    "provided for the client. This is disallowed.";
      return false;
    }

    bool setup_succeeded;
    if (encryption_passphrase_provided) {
      setup_succeeded = client->SetupSyncWithEncryptionPassphrase(
          syncer::UserSelectableTypes(), encryption_passphrase_it->second);
    } else if (decryption_passphrase_provided) {
      setup_succeeded = client->SetupSyncWithDecryptionPassphrase(
          syncer::UserSelectableTypes(), decryption_passphrase_it->second);
    } else {
      setup_succeeded = client->SetupSync(syncer::UserSelectableTypes());
    }

    if (!setup_succeeded) {
      LOG(FATAL) << "SetupSync() failed.";
      return false;
    }
  }

  // Because clients may modify sync data as part of startup (for example local
  // session-releated data is rewritten), we need to ensure all startup-based
  // changes have propagated between the clients.
  //
  // Tests that don't use self-notifications can't await quiescense.  They'll
  // have to find their own way of waiting for an initial state if they really
  // need such guarantees.
  if (TestUsesSelfNotifications()) {
    if (!AwaitQuiescence()) {
      LOG(FATAL) << "AwaitQuiescence() failed.";
      return false;
    }
  }

  // SyncRefresher is used instead of invalidations to notify other profiles to
  // do a sync refresh on committed data sets. This is only needed when running
  // tests against external live server, otherwise invalidation service is used.
  // With external live servers, the profiles commit data on first sync cycle
  // automatically after signing in. To avoid misleading sync commit
  // notifications at start up, we start the SyncRefresher observers post
  // client set up.
  if (UsingExternalServers()) {
    for (int i = 0; i < num_clients_; ++i) {
      DCHECK(!sync_refreshers_[i]);
      sync_refreshers_[i] = std::make_unique<P2PSyncRefresher>(
          GetProfile(i), clients_[i]->service());
    }

    // OneClickSigninSyncStarter observer is created with a real user sign in.
    // It is deleted on certain conditions which are not satisfied by our tests,
    // and this causes the SigninTracker observer to stay hanging at shutdown.
    // Calling LoginUIService::SyncConfirmationUIClosed forces the observer to
    // be removed. http://crbug.com/484388
    for (int i = 0; i < num_clients_; ++i) {
      LoginUIServiceFactory::GetForProfile(GetProfile(i))->
          SyncConfirmationUIClosed(LoginUIService::SYNC_WITH_DEFAULT_SETTINGS);
    }
  }

  return true;
}

bool SyncTest::SetupAndClearClient(size_t index) {
  // Setup the first client so the sync engine is initialized, which is
  // required to clear server data.
  DVLOG(1) << "Setting up first client for clear.";
  if (!GetClient(index)->SetupSyncForClearingServerData()) {
    LOG(FATAL) << "SetupSync() failed.";
    return false;
  }

  DVLOG(1) << "Done setting up first client for clear.";
  if (!ClearServerData(GetClient(index++))) {
    LOG(FATAL) << "ClearServerData failed.";
    return false;
  }
  return true;
}

void SyncTest::TearDownOnMainThread() {
  // Workaround for https://crbug.com/801569: |prefs::kProfileLastUsed| stores
  // the profile path relative to the user dir, but our testing profiles are
  // outside the user dir (see CreateProfile). So code trying to access the last
  // used profile by path will fail. To work around that, set the last used
  // profile back to the originally created default profile (which does live in
  // the user data dir, and which we don't use otherwise).
  if (previous_profile_) {
    profiles::SetLastUsedProfile(
        previous_profile_->GetPath().BaseName().MaybeAsASCII());
  }

  // Closing all browsers created by this test. The calls here block until
  // they are closed. Other browsers created outside SyncTest setup should be
  // closed by the creator of that browser.
  size_t init_browser_count = chrome::GetTotalBrowserCount();
  for (size_t i = 0; i < browsers_.size(); ++i) {
    CloseBrowserSynchronously(browsers_[i]);
  }
  ASSERT_EQ(chrome::GetTotalBrowserCount(),
            init_browser_count - browsers_.size());

  if (fake_server_.get()) {
    std::vector<fake_server::FakeServerInvalidationService*>::const_iterator it;
    for (it = fake_server_invalidation_services_.begin();
         it != fake_server_invalidation_services_.end(); ++it) {
      fake_server_->RemoveObserver(*it);
    }
  }

  // Delete things that unsubscribe in destructor before their targets are gone.
  invalidation_forwarders_.clear();
  sync_refreshers_.clear();
  configuration_refresher_.reset();
}

void SyncTest::SetUpOnMainThread() {
  // Start up a sync test server if one is needed and setup mock gaia responses.
  // Note: This must be done prior to the call to SetupClients() because we want
  // the mock gaia responses to be available before GaiaUrls is initialized.
  SetUpTestServerIfRequired();

  if (!UsingExternalServers())
    SetupMockGaiaResponsesForProfile(ProfileManager::GetActiveUserProfile());

  // Allows google.com as well as country-specific TLDs.
  host_resolver()->AllowDirectLookup("*.google.com");
  host_resolver()->AllowDirectLookup("accounts.google.*");

  // Allow connection to googleapis.com for oauth token requests in E2E tests.
  host_resolver()->AllowDirectLookup("*.googleapis.com");

  // On Linux, we use Chromium's NSS implementation which uses the following
  // hosts for certificate verification. Without these overrides, running the
  // integration tests on Linux causes error as we make external DNS lookups.
  host_resolver()->AllowDirectLookup("*.thawte.com");
  host_resolver()->AllowDirectLookup("*.geotrust.com");
  host_resolver()->AllowDirectLookup("*.gstatic.com");
}

void SyncTest::WaitForDataModels(Profile* profile) {
  bookmarks::test::WaitForBookmarkModelToLoad(
      BookmarkModelFactory::GetForBrowserContext(profile));
  ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
      profile, ServiceAccessType::EXPLICIT_ACCESS));
  search_test_utils::WaitForTemplateURLServiceToLoad(
      TemplateURLServiceFactory::GetForProfile(profile));
#if defined(OS_CHROMEOS)
  printers_helper::WaitForPrinterStoreToLoad(profile);
#endif
}

void SyncTest::ReadPasswordFile() {
  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
  password_file_ = cl->GetSwitchValuePath(switches::kPasswordFileForTest);
  if (password_file_.empty())
    LOG(FATAL) << "Can't run live server test without specifying --"
               << switches::kPasswordFileForTest << "=<filename>";
  std::string file_contents;
  base::ReadFileToString(password_file_, &file_contents);
  ASSERT_NE(file_contents, "") << "Password file \""
      << password_file_.value() << "\" does not exist.";
  std::vector<std::string> tokens = base::SplitString(
      file_contents, "\r\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  ASSERT_EQ(2U, tokens.size()) << "Password file \""
      << password_file_.value()
      << "\" must contain exactly two lines of text.";
  username_ = tokens[0];
  password_ = tokens[1];
}

void SyncTest::SetupMockGaiaResponses() {
  test_url_loader_factory_.AddResponse(
      GaiaUrls::GetInstance()->get_user_info_url().spec(),
      "email=user@gmail.com\ndisplayEmail=user@gmail.com");
  test_url_loader_factory_.AddResponse(GoogleURLTracker::kSearchDomainCheckURL,
                                       ".google.com");
  test_url_loader_factory_.AddResponse(
      GaiaUrls::GetInstance()->oauth2_token_url().spec(),
      R"({
            "refresh_token": "rt1",
            "access_token": "at1",
            "expires_in": 3600,
            "token_type": "Bearer"
         })");
  test_url_loader_factory_.AddResponse(
      GaiaUrls::GetInstance()->oauth_user_info_url().spec(),
      "{ \"id\": \"12345\" }");
  test_url_loader_factory_.AddResponse(
      GaiaUrls::GetInstance()->oauth1_login_url().spec(),
      "SID=sid\nLSID=lsid\nAuth=auth_token");
  test_url_loader_factory_.AddResponse(
      GaiaUrls::GetInstance()->oauth2_revoke_url().spec(), "");
}

void SyncTest::SetOAuth2TokenResponse(const std::string& response_data,
                                      net::HttpStatusCode status_code,
                                      net::URLRequestStatus::Status status) {
  network::URLLoaderCompletionStatus completion_status(status);
  completion_status.decoded_body_length = response_data.size();

  std::string response = base::StringPrintf("HTTP/1.1 %d %s\r\n", status_code,
                                            GetHttpReasonPhrase(status_code));
  network::ResourceResponseHead resource_response;
  resource_response.headers =
      base::MakeRefCounted<net::HttpResponseHeaders>(response);
  test_url_loader_factory_.AddResponse(
      GaiaUrls::GetInstance()->oauth2_token_url(), resource_response,
      response_data, completion_status);
  base::RunLoop().RunUntilIdle();
}

void SyncTest::ClearMockGaiaResponses() {
  // Clear any mock gaia responses that might have been set.
  test_url_loader_factory_.ClearResponses();
}

void SyncTest::DecideServerType() {
  // Only set |server_type_| if it hasn't already been set. This allows for
  // tests to explicitly set this value in each test class if needed.
  if (server_type_ == SERVER_TYPE_UNDECIDED) {
    base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
    if (!cl->HasSwitch(switches::kSyncServiceURL)) {
      // If no sync server URL is provided, start up a local sync test server
      // and point Chrome to its URL. This is the most common configuration,
      // and the only one that makes sense for most developers. FakeServer is
      // the current solution but some scenarios are only supported by the
      // legacy python server.
      switch (test_type_) {
        case SINGLE_CLIENT:
        case TWO_CLIENT:
          server_type_ = IN_PROCESS_FAKE_SERVER;
          break;
        case SINGLE_CLIENT_LEGACY:
        case TWO_CLIENT_LEGACY:
          server_type_ = LOCAL_PYTHON_SERVER;
      }
      DCHECK_NE(server_type_, SERVER_TYPE_UNDECIDED);
    } else {
      // If a sync server URL is provided, it is assumed that the server is
      // already running. Chrome will automatically connect to it at the URL
      // provided. There is nothing to do here.
      server_type_ = EXTERNAL_LIVE_SERVER;
    }
  }
}

// Start up a local sync server based on the value of server_type_, which
// was determined from the command line parameters.
void SyncTest::SetUpTestServerIfRequired() {
  if (UsingExternalServers()) {
    // Nothing to do; we'll just talk to the URL we were given.
  } else if (server_type_ == LOCAL_PYTHON_SERVER) {
    if (!SetUpLocalPythonTestServer())
      LOG(FATAL) << "Failed to set up local python sync and XMPP servers";
    SetupMockGaiaResponses();
  } else if (server_type_ == IN_PROCESS_FAKE_SERVER) {
    base::FilePath user_data_dir;
    base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
    fake_server_ = std::make_unique<fake_server::FakeServer>(user_data_dir);
    SetupMockGaiaResponses();
  } else {
    LOG(FATAL) << "Don't know which server environment to run test in.";
  }
}

bool SyncTest::SetUpLocalPythonTestServer() {
  EXPECT_TRUE(sync_server_.Start())
      << "Could not launch local python test server.";

  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
  if (server_type_ == LOCAL_PYTHON_SERVER) {
    std::string sync_service_url = sync_server_.GetURL("chromiumsync").spec();
    cl->AppendSwitchASCII(switches::kSyncServiceURL, sync_service_url);
    DVLOG(1) << "Started local python sync server at " << sync_service_url;
  }

  int xmpp_port = 0;
  if (!sync_server_.server_data().GetInteger("xmpp_port", &xmpp_port)) {
    LOG(ERROR) << "Could not find valid xmpp_port value";
    return false;
  }
  if ((xmpp_port <= 0) || (xmpp_port > std::numeric_limits<uint16_t>::max())) {
    LOG(ERROR) << "Invalid xmpp port: " << xmpp_port;
    return false;
  }

  net::HostPortPair xmpp_host_port_pair(sync_server_.host_port_pair());
  xmpp_host_port_pair.set_port(xmpp_port);
  xmpp_port_ = std::make_unique<net::ScopedPortException>(xmpp_port);

  if (!cl->HasSwitch(invalidation::switches::kSyncNotificationHostPort)) {
    cl->AppendSwitchASCII(invalidation::switches::kSyncNotificationHostPort,
                          xmpp_host_port_pair.ToString());
    // The local XMPP server only supports insecure connections.
    cl->AppendSwitch(invalidation::switches::kSyncAllowInsecureXmppConnection);
  }
  DVLOG(1) << "Started local python XMPP server at "
           << xmpp_host_port_pair.ToString();

  return true;
}

bool SyncTest::TearDownLocalPythonTestServer() {
  if (!sync_server_.Stop()) {
    LOG(ERROR) << "Could not stop local python test server.";
    return false;
  }
  xmpp_port_.reset();
  return true;
}

bool SyncTest::TearDownLocalTestServer() {
  if (test_server_.IsValid()) {
    EXPECT_TRUE(test_server_.Terminate(0, false))
        << "Could not stop local test server.";
    test_server_.Close();
  }
  return true;
}

bool SyncTest::WaitForTestServerToStart(base::TimeDelta wait, int intervals) {
  for (int i = 0; i < intervals; ++i) {
    if (IsTestServerRunning())
      return true;
    base::PlatformThread::Sleep(wait / intervals);
  }
  return false;
}

bool SyncTest::IsTestServerRunning() {
  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
  std::string sync_url = cl->GetSwitchValueASCII(switches::kSyncServiceURL);
  GURL sync_url_status(sync_url.append("/healthz"));
  auto resource_request = std::make_unique<network::ResourceRequest>();
  resource_request->url = sync_url_status;
  resource_request->load_flags = net::LOAD_DISABLE_CACHE |
                                 net::LOAD_DO_NOT_SEND_COOKIES |
                                 net::LOAD_DO_NOT_SAVE_COOKIES;
  std::unique_ptr<network::SimpleURLLoader> simple_url_loader =
      network::SimpleURLLoader::Create(std::move(resource_request),
                                       TRAFFIC_ANNOTATION_FOR_TESTS);
  bool server_running = false;
  base::RunLoop run_loop;
  simple_url_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
      g_browser_process->system_network_context_manager()
          ->GetURLLoaderFactory(),
      base::BindLambdaForTesting(
          [&server_running,
           &run_loop](std::unique_ptr<std::string> response_body) {
            server_running =
                response_body && base::StartsWith(*response_body, "ok",
                                                  base::CompareCase::SENSITIVE);
            run_loop.Quit();
          }));
  return server_running;
}

bool SyncTest::TestUsesSelfNotifications() {
  // Default is True unless we are running against external servers.
  return !UsingExternalServers();
}

bool SyncTest::EnableEncryption(int index) {
  ProfileSyncService* service = GetClient(index)->service();

  if (::IsEncryptionComplete(service))
    return true;

  service->GetUserSettings()->EnableEncryptEverything();

  // In order to kick off the encryption we have to reconfigure. Just grab the
  // currently synced types and use them.
  syncer::ModelTypeSet synced_datatypes =
      service->GetUserSettings()->GetChosenDataTypes();
  bool sync_everything = (synced_datatypes == syncer::UserSelectableTypes());
  service->GetUserSettings()->SetChosenDataTypes(sync_everything,
                                                 synced_datatypes);

  return AwaitEncryptionComplete(index);
}

bool SyncTest::IsEncryptionComplete(int index) {
  return ::IsEncryptionComplete(GetClient(index)->service());
}

bool SyncTest::AwaitEncryptionComplete(int index) {
  ProfileSyncService* service = GetClient(index)->service();
  return EncryptionChecker(service).Wait();
}

bool SyncTest::AwaitQuiescence() {
  return ProfileSyncServiceHarness::AwaitQuiescence(GetSyncClients());
}

bool SyncTest::UsingExternalServers() {
  return server_type_ == EXTERNAL_LIVE_SERVER;
}

bool SyncTest::ServerSupportsNotificationControl() const {
  EXPECT_NE(SERVER_TYPE_UNDECIDED, server_type_);

  // Supported only if we're using the python testserver.
  return server_type_ == LOCAL_PYTHON_SERVER;
}

void SyncTest::DisableNotificationsImpl() {
  ASSERT_TRUE(ServerSupportsNotificationControl());
  std::string path = "chromiumsync/disablenotifications";
  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
  ASSERT_EQ("Notifications disabled",
            base::UTF16ToASCII(
                browser()->tab_strip_model()->GetActiveWebContents()->
                    GetTitle()));
}

void SyncTest::DisableNotifications() {
  DisableNotificationsImpl();
}

void SyncTest::EnableNotificationsImpl() {
  ASSERT_TRUE(ServerSupportsNotificationControl());
  std::string path = "chromiumsync/enablenotifications";
  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
  ASSERT_EQ("Notifications enabled",
            base::UTF16ToASCII(
                browser()->tab_strip_model()->GetActiveWebContents()->
                    GetTitle()));
}

void SyncTest::EnableNotifications() {
  EnableNotificationsImpl();
}

void SyncTest::TriggerNotification(syncer::ModelTypeSet changed_types) {
  ASSERT_TRUE(ServerSupportsNotificationControl());
  const std::string& data =
      syncer::P2PNotificationData(
          "from_server",
          syncer::NOTIFY_ALL,
          syncer::ObjectIdInvalidationMap::InvalidateAll(
              syncer::ModelTypeSetToObjectIdSet(changed_types))).ToString();
  const std::string& path =
      std::string("chromiumsync/sendnotification?channel=") +
      syncer::kSyncP2PNotificationChannel + "&data=" + data;
  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
  ASSERT_EQ("Notification sent",
            base::UTF16ToASCII(
                browser()->tab_strip_model()->GetActiveWebContents()->
                    GetTitle()));
}

bool SyncTest::ServerSupportsErrorTriggering() const {
  EXPECT_NE(SERVER_TYPE_UNDECIDED, server_type_);

  // Supported only if we're using the python testserver.
  return server_type_ == LOCAL_PYTHON_SERVER;
}

void SyncTest::TriggerMigrationDoneError(syncer::ModelTypeSet model_types) {
  ASSERT_TRUE(ServerSupportsErrorTriggering());
  std::string path = "chromiumsync/migrate";
  char joiner = '?';
  for (syncer::ModelType type : model_types) {
    path.append(
        base::StringPrintf("%ctype=%d", joiner,
                           syncer::GetSpecificsFieldNumberFromModelType(type)));
    joiner = '&';
  }
  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
  ASSERT_EQ("Migration: 200",
            base::UTF16ToASCII(
                browser()->tab_strip_model()->GetActiveWebContents()->
                    GetTitle()));
}

fake_server::FakeServer* SyncTest::GetFakeServer() const {
  return fake_server_.get();
}

void SyncTest::TriggerSyncForModelTypes(int index,
                                        syncer::ModelTypeSet model_types) {
  GetSyncService(index)->TriggerRefresh(model_types);
}

void SyncTest::StopConfigurationRefresher() {
  configuration_refresher_.reset();
}

arc::SyncArcPackageHelper* SyncTest::sync_arc_helper() {
#if defined(OS_CHROMEOS)
  return arc::SyncArcPackageHelper::GetInstance();
#else
  return nullptr;
#endif
}

void SyncTest::SetPreexistingPreferencesFileContents(
    int index,
    const std::string& contents) {
  preexisting_preferences_file_contents_[index] = contents;
}

bool SyncTest::ClearServerData(ProfileSyncServiceHarness* harness) {
  // At this point our birthday is good.
  base::RunLoop run_loop;
  harness->service()->ClearServerDataForTest(run_loop.QuitClosure());
  run_loop.Run();

  // Our birthday is invalidated on the server here so restart sync to get
  // the new birthday from the server.
  harness->StopSyncServiceAndClearData();
  return harness->StartSyncService();
}
