Home | History | Annotate | Download | only in integration
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/sync/test/integration/sync_test.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/basictypes.h"
     10 #include "base/bind.h"
     11 #include "base/command_line.h"
     12 #include "base/memory/ref_counted.h"
     13 #include "base/message_loop/message_loop.h"
     14 #include "base/path_service.h"
     15 #include "base/process/launch.h"
     16 #include "base/strings/string_util.h"
     17 #include "base/strings/stringprintf.h"
     18 #include "base/strings/utf_string_conversions.h"
     19 #include "base/synchronization/waitable_event.h"
     20 #include "base/test/test_timeouts.h"
     21 #include "base/threading/platform_thread.h"
     22 #include "base/values.h"
     23 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
     24 #include "chrome/browser/history/history_service_factory.h"
     25 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
     26 #include "chrome/browser/lifetime/application_lifetime.h"
     27 #include "chrome/browser/profiles/profile.h"
     28 #include "chrome/browser/profiles/profile_manager.h"
     29 #include "chrome/browser/search_engines/template_url_service_factory.h"
     30 #include "chrome/browser/signin/profile_identity_provider.h"
     31 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
     32 #include "chrome/browser/signin/signin_manager_factory.h"
     33 #include "chrome/browser/sync/glue/invalidation_helper.h"
     34 #include "chrome/browser/sync/profile_sync_service.h"
     35 #include "chrome/browser/sync/profile_sync_service_factory.h"
     36 #include "chrome/browser/sync/test/integration/fake_server_invalidation_service.h"
     37 #include "chrome/browser/sync/test/integration/p2p_invalidation_forwarder.h"
     38 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
     39 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
     40 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
     41 #include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
     42 #include "chrome/browser/ui/browser.h"
     43 #include "chrome/browser/ui/browser_finder.h"
     44 #include "chrome/browser/ui/host_desktop.h"
     45 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     46 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
     47 #include "chrome/common/chrome_paths.h"
     48 #include "chrome/common/chrome_switches.h"
     49 #include "chrome/test/base/testing_browser_process.h"
     50 #include "chrome/test/base/ui_test_utils.h"
     51 #include "components/bookmarks/test/bookmark_test_helpers.h"
     52 #include "components/google/core/browser/google_url_tracker.h"
     53 #include "components/invalidation/invalidation_service.h"
     54 #include "components/invalidation/invalidation_switches.h"
     55 #include "components/invalidation/p2p_invalidation_service.h"
     56 #include "components/invalidation/p2p_invalidator.h"
     57 #include "components/invalidation/profile_invalidation_provider.h"
     58 #include "components/keyed_service/core/keyed_service.h"
     59 #include "components/os_crypt/os_crypt.h"
     60 #include "components/search_engines/template_url_service.h"
     61 #include "components/signin/core/browser/signin_manager.h"
     62 #include "content/public/browser/web_contents.h"
     63 #include "content/public/test/test_browser_thread.h"
     64 #include "google_apis/gaia/gaia_urls.h"
     65 #include "net/base/escape.h"
     66 #include "net/base/load_flags.h"
     67 #include "net/base/network_change_notifier.h"
     68 #include "net/cookies/cookie_monster.h"
     69 #include "net/proxy/proxy_config.h"
     70 #include "net/proxy/proxy_config_service_fixed.h"
     71 #include "net/proxy/proxy_service.h"
     72 #include "net/test/spawned_test_server/spawned_test_server.h"
     73 #include "net/url_request/test_url_fetcher_factory.h"
     74 #include "net/url_request/url_fetcher.h"
     75 #include "net/url_request/url_fetcher_delegate.h"
     76 #include "net/url_request/url_request_context.h"
     77 #include "net/url_request/url_request_context_getter.h"
     78 #include "sync/engine/sync_scheduler_impl.h"
     79 #include "sync/protocol/sync.pb.h"
     80 #include "sync/test/fake_server/fake_server.h"
     81 #include "sync/test/fake_server/fake_server_network_resources.h"
     82 #include "url/gurl.h"
     83 
     84 #if defined(OS_CHROMEOS)
     85 #include "chromeos/chromeos_switches.h"
     86 #endif
     87 
     88 using content::BrowserThread;
     89 
     90 namespace switches {
     91 const char kPasswordFileForTest[] = "password-file-for-test";
     92 const char kSyncUserForTest[] = "sync-user-for-test";
     93 const char kSyncPasswordForTest[] = "sync-password-for-test";
     94 const char kSyncServerCommandLine[] = "sync-server-command-line";
     95 }
     96 
     97 namespace {
     98 
     99 // Helper class that checks whether a sync test server is running or not.
    100 class SyncServerStatusChecker : public net::URLFetcherDelegate {
    101  public:
    102   SyncServerStatusChecker() : running_(false) {}
    103 
    104   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
    105     std::string data;
    106     source->GetResponseAsString(&data);
    107     running_ =
    108         (source->GetStatus().status() == net::URLRequestStatus::SUCCESS &&
    109         source->GetResponseCode() == 200 && data.find("ok") == 0);
    110     base::MessageLoop::current()->Quit();
    111   }
    112 
    113   bool running() const { return running_; }
    114 
    115  private:
    116   bool running_;
    117 };
    118 
    119 bool IsEncryptionComplete(const ProfileSyncService* service) {
    120   return service->EncryptEverythingEnabled() && !service->encryption_pending();
    121 }
    122 
    123 // Helper class to wait for encryption to complete.
    124 class EncryptionChecker : public SingleClientStatusChangeChecker {
    125  public:
    126   explicit EncryptionChecker(ProfileSyncService* service)
    127       : SingleClientStatusChangeChecker(service) {}
    128 
    129   virtual bool IsExitConditionSatisfied() OVERRIDE {
    130     return IsEncryptionComplete(service());
    131   }
    132 
    133   virtual std::string GetDebugMessage() const OVERRIDE {
    134     return "Encryption";
    135   }
    136 };
    137 
    138 void SetupNetworkCallback(
    139     base::WaitableEvent* done,
    140     net::URLRequestContextGetter* url_request_context_getter) {
    141   url_request_context_getter->GetURLRequestContext()->
    142       set_cookie_store(new net::CookieMonster(NULL, NULL));
    143   done->Signal();
    144 }
    145 
    146 void SetProxyConfigCallback(
    147     base::WaitableEvent* done,
    148     net::URLRequestContextGetter* url_request_context_getter,
    149     const net::ProxyConfig& proxy_config) {
    150   net::ProxyService* proxy_service =
    151       url_request_context_getter->GetURLRequestContext()->proxy_service();
    152   proxy_service->ResetConfigService(
    153       new net::ProxyConfigServiceFixed(proxy_config));
    154   done->Signal();
    155 }
    156 
    157 KeyedService* BuildFakeServerProfileInvalidationProvider(
    158     content::BrowserContext* context) {
    159   return new invalidation::ProfileInvalidationProvider(
    160       scoped_ptr<invalidation::InvalidationService>(
    161           new fake_server::FakeServerInvalidationService));
    162 }
    163 
    164 KeyedService* BuildP2PProfileInvalidationProvider(
    165     content::BrowserContext* context,
    166     syncer::P2PNotificationTarget notification_target) {
    167   Profile* profile = static_cast<Profile*>(context);
    168   return new invalidation::ProfileInvalidationProvider(
    169       scoped_ptr<invalidation::InvalidationService>(
    170           new invalidation::P2PInvalidationService(
    171               scoped_ptr<IdentityProvider>(new ProfileIdentityProvider(
    172                   SigninManagerFactory::GetForProfile(profile),
    173                   ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
    174                   LoginUIServiceFactory::GetForProfile(profile))),
    175               profile->GetRequestContext(),
    176               notification_target)));
    177 }
    178 
    179 KeyedService* BuildSelfNotifyingP2PProfileInvalidationProvider(
    180     content::BrowserContext* context) {
    181   return BuildP2PProfileInvalidationProvider(context, syncer::NOTIFY_ALL);
    182 }
    183 
    184 KeyedService* BuildRealisticP2PProfileInvalidationProvider(
    185     content::BrowserContext* context) {
    186   return BuildP2PProfileInvalidationProvider(context, syncer::NOTIFY_OTHERS);
    187 }
    188 
    189 }  // namespace
    190 
    191 SyncTest::SyncTest(TestType test_type)
    192     : test_type_(test_type),
    193       server_type_(SERVER_TYPE_UNDECIDED),
    194       num_clients_(-1),
    195       use_verifier_(true),
    196       notifications_enabled_(true),
    197       test_server_handle_(base::kNullProcessHandle) {
    198   sync_datatype_helper::AssociateWithTest(this);
    199   switch (test_type_) {
    200     case SINGLE_CLIENT:
    201     case SINGLE_CLIENT_LEGACY: {
    202       num_clients_ = 1;
    203       break;
    204     }
    205     case TWO_CLIENT:
    206     case TWO_CLIENT_LEGACY: {
    207       num_clients_ = 2;
    208       break;
    209     }
    210     case MULTIPLE_CLIENT: {
    211       num_clients_ = 3;
    212       break;
    213     }
    214   }
    215 }
    216 
    217 SyncTest::~SyncTest() {}
    218 
    219 void SyncTest::SetUp() {
    220   base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
    221   if (cl->HasSwitch(switches::kPasswordFileForTest)) {
    222     ReadPasswordFile();
    223   } else if (cl->HasSwitch(switches::kSyncUserForTest) &&
    224              cl->HasSwitch(switches::kSyncPasswordForTest)) {
    225     username_ = cl->GetSwitchValueASCII(switches::kSyncUserForTest);
    226     password_ = cl->GetSwitchValueASCII(switches::kSyncPasswordForTest);
    227   } else {
    228     username_ = "user (at) gmail.com";
    229     password_ = "password";
    230   }
    231 
    232   if (username_.empty() || password_.empty())
    233     LOG(FATAL) << "Cannot run sync tests without GAIA credentials.";
    234 
    235   // Sets |server_type_| if it wasn't specified by the test.
    236   DecideServerType();
    237 
    238   // Mock the Mac Keychain service.  The real Keychain can block on user input.
    239 #if defined(OS_MACOSX)
    240   OSCrypt::UseMockKeychain(true);
    241 #endif
    242 
    243   // Start up a sync test server if one is needed and setup mock gaia responses.
    244   // Note: This must be done prior to the call to SetupClients() because we want
    245   // the mock gaia responses to be available before GaiaUrls is initialized.
    246   SetUpTestServerIfRequired();
    247 
    248   // Yield control back to the InProcessBrowserTest framework.
    249   InProcessBrowserTest::SetUp();
    250 }
    251 
    252 void SyncTest::TearDown() {
    253   // Clear any mock gaia responses that might have been set.
    254   ClearMockGaiaResponses();
    255 
    256   // Allow the InProcessBrowserTest framework to perform its tear down.
    257   InProcessBrowserTest::TearDown();
    258 
    259   // Stop the local python test server. This is a no-op if one wasn't started.
    260   TearDownLocalPythonTestServer();
    261 
    262   // Stop the local sync test server. This is a no-op if one wasn't started.
    263   TearDownLocalTestServer();
    264 
    265   fake_server_.reset();
    266 }
    267 
    268 void SyncTest::SetUpCommandLine(base::CommandLine* cl) {
    269   AddTestSwitches(cl);
    270   AddOptionalTypesToCommandLine(cl);
    271 
    272 #if defined(OS_CHROMEOS)
    273   cl->AppendSwitch(chromeos::switches::kIgnoreUserProfileMappingForTests);
    274 #endif
    275 }
    276 
    277 void SyncTest::AddTestSwitches(base::CommandLine* cl) {
    278   // Disable non-essential access of external network resources.
    279   if (!cl->HasSwitch(switches::kDisableBackgroundNetworking))
    280     cl->AppendSwitch(switches::kDisableBackgroundNetworking);
    281 
    282   if (!cl->HasSwitch(switches::kSyncShortInitialRetryOverride))
    283     cl->AppendSwitch(switches::kSyncShortInitialRetryOverride);
    284 }
    285 
    286 void SyncTest::AddOptionalTypesToCommandLine(base::CommandLine* cl) {}
    287 
    288 // static
    289 Profile* SyncTest::MakeProfile(const base::FilePath::StringType name) {
    290   base::FilePath path;
    291   PathService::Get(chrome::DIR_USER_DATA, &path);
    292   path = path.Append(name);
    293 
    294   if (!base::PathExists(path))
    295     CHECK(base::CreateDirectory(path));
    296 
    297   Profile* profile =
    298       Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
    299   g_browser_process->profile_manager()->RegisterTestingProfile(profile,
    300                                                                true,
    301                                                                true);
    302   return profile;
    303 }
    304 
    305 Profile* SyncTest::GetProfile(int index) {
    306   if (profiles_.empty())
    307     LOG(FATAL) << "SetupClients() has not yet been called.";
    308   if (index < 0 || index >= static_cast<int>(profiles_.size()))
    309     LOG(FATAL) << "GetProfile(): Index is out of bounds.";
    310   return profiles_[index];
    311 }
    312 
    313 Browser* SyncTest::GetBrowser(int index) {
    314   if (browsers_.empty())
    315     LOG(FATAL) << "SetupClients() has not yet been called.";
    316   if (index < 0 || index >= static_cast<int>(browsers_.size()))
    317     LOG(FATAL) << "GetBrowser(): Index is out of bounds.";
    318   return browsers_[index];
    319 }
    320 
    321 ProfileSyncServiceHarness* SyncTest::GetClient(int index) {
    322   if (clients_.empty())
    323     LOG(FATAL) << "SetupClients() has not yet been called.";
    324   if (index < 0 || index >= static_cast<int>(clients_.size()))
    325     LOG(FATAL) << "GetClient(): Index is out of bounds.";
    326   return clients_[index];
    327 }
    328 
    329 ProfileSyncService* SyncTest::GetSyncService(int index) {
    330   return ProfileSyncServiceFactory::GetForProfile(GetProfile(index));
    331 }
    332 
    333 std::vector<ProfileSyncService*> SyncTest::GetSyncServices() {
    334   std::vector<ProfileSyncService*> services;
    335   for (int i = 0; i < num_clients(); ++i) {
    336     services.push_back(GetSyncService(i));
    337   }
    338   return services;
    339 }
    340 
    341 Profile* SyncTest::verifier() {
    342   if (verifier_ == NULL)
    343     LOG(FATAL) << "SetupClients() has not yet been called.";
    344   return verifier_;
    345 }
    346 
    347 void SyncTest::DisableVerifier() {
    348   use_verifier_ = false;
    349 }
    350 
    351 bool SyncTest::SetupClients() {
    352   if (num_clients_ <= 0)
    353     LOG(FATAL) << "num_clients_ incorrectly initialized.";
    354   if (!profiles_.empty() || !browsers_.empty() || !clients_.empty())
    355     LOG(FATAL) << "SetupClients() has already been called.";
    356 
    357   // Create the required number of sync profiles, browsers and clients.
    358   profiles_.resize(num_clients_);
    359   browsers_.resize(num_clients_);
    360   clients_.resize(num_clients_);
    361   invalidation_forwarders_.resize(num_clients_);
    362   fake_server_invalidation_services_.resize(num_clients_);
    363   for (int i = 0; i < num_clients_; ++i) {
    364     InitializeInstance(i);
    365   }
    366 
    367   // Create the verifier profile.
    368   verifier_ = MakeProfile(FILE_PATH_LITERAL("Verifier"));
    369   test::WaitForBookmarkModelToLoad(
    370       BookmarkModelFactory::GetForProfile(verifier()));
    371   ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
    372       verifier(), Profile::EXPLICIT_ACCESS));
    373   ui_test_utils::WaitForTemplateURLServiceToLoad(
    374       TemplateURLServiceFactory::GetForProfile(verifier()));
    375   return (verifier_ != NULL);
    376 }
    377 
    378 void SyncTest::InitializeInstance(int index) {
    379   profiles_[index] = MakeProfile(
    380       base::StringPrintf(FILE_PATH_LITERAL("Profile%d"), index));
    381   EXPECT_FALSE(GetProfile(index) == NULL) << "Could not create Profile "
    382                                           << index << ".";
    383 
    384   browsers_[index] = new Browser(Browser::CreateParams(
    385       GetProfile(index), chrome::GetActiveDesktop()));
    386   EXPECT_FALSE(GetBrowser(index) == NULL) << "Could not create Browser "
    387                                           << index << ".";
    388 
    389 
    390   // Make sure the ProfileSyncService has been created before creating the
    391   // ProfileSyncServiceHarness - some tests expect the ProfileSyncService to
    392   // already exist.
    393   ProfileSyncService* profile_sync_service =
    394       ProfileSyncServiceFactory::GetForProfile(GetProfile(index));
    395 
    396   SetupNetwork(GetProfile(index)->GetRequestContext());
    397 
    398   if (server_type_ == IN_PROCESS_FAKE_SERVER) {
    399     // TODO(pvalenzuela): Run the fake server via EmbeddedTestServer.
    400     profile_sync_service->OverrideNetworkResourcesForTest(
    401         make_scoped_ptr<syncer::NetworkResources>(
    402             new fake_server::FakeServerNetworkResources(fake_server_.get())));
    403   }
    404 
    405   clients_[index] =
    406       ProfileSyncServiceHarness::Create(
    407           GetProfile(index),
    408           username_,
    409           password_);
    410   EXPECT_FALSE(GetClient(index) == NULL) << "Could not create Client "
    411                                          << index << ".";
    412   InitializeInvalidations(index);
    413 
    414   test::WaitForBookmarkModelToLoad(
    415       BookmarkModelFactory::GetForProfile(GetProfile(index)));
    416   ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
    417       GetProfile(index), Profile::EXPLICIT_ACCESS));
    418   ui_test_utils::WaitForTemplateURLServiceToLoad(
    419       TemplateURLServiceFactory::GetForProfile(GetProfile(index)));
    420 }
    421 
    422 void SyncTest::InitializeInvalidations(int index) {
    423   if (server_type_ == IN_PROCESS_FAKE_SERVER) {
    424     CHECK(fake_server_.get());
    425     fake_server::FakeServerInvalidationService* invalidation_service =
    426         static_cast<fake_server::FakeServerInvalidationService*>(
    427             static_cast<invalidation::ProfileInvalidationProvider*>(
    428                 invalidation::ProfileInvalidationProviderFactory::
    429                     GetInstance()->SetTestingFactoryAndUse(
    430                         GetProfile(index),
    431                         BuildFakeServerProfileInvalidationProvider))->
    432                             GetInvalidationService());
    433     fake_server_->AddObserver(invalidation_service);
    434     if (TestUsesSelfNotifications()) {
    435       invalidation_service->EnableSelfNotifications();
    436     } else {
    437       invalidation_service->DisableSelfNotifications();
    438     }
    439     fake_server_invalidation_services_[index] = invalidation_service;
    440   } else {
    441     invalidation::P2PInvalidationService* p2p_invalidation_service =
    442         static_cast<invalidation::P2PInvalidationService*>(
    443             static_cast<invalidation::ProfileInvalidationProvider*>(
    444                 invalidation::ProfileInvalidationProviderFactory::
    445                     GetInstance()->SetTestingFactoryAndUse(
    446                         GetProfile(index),
    447                         TestUsesSelfNotifications() ?
    448                             BuildSelfNotifyingP2PProfileInvalidationProvider :
    449                             BuildRealisticP2PProfileInvalidationProvider))->
    450                                 GetInvalidationService());
    451     p2p_invalidation_service->UpdateCredentials(username_, password_);
    452     // Start listening for and emitting notifications of commits.
    453     invalidation_forwarders_[index] =
    454         new P2PInvalidationForwarder(clients_[index]->service(),
    455                                      p2p_invalidation_service);
    456   }
    457 }
    458 
    459 bool SyncTest::SetupSync() {
    460   // Create sync profiles and clients if they haven't already been created.
    461   if (profiles_.empty()) {
    462     if (!SetupClients())
    463       LOG(FATAL) << "SetupClients() failed.";
    464   }
    465 
    466   // Sync each of the profiles.
    467   for (int i = 0; i < num_clients_; ++i) {
    468     if (!GetClient(i)->SetupSync())
    469       LOG(FATAL) << "SetupSync() failed.";
    470   }
    471 
    472   // Because clients may modify sync data as part of startup (for example local
    473   // session-releated data is rewritten), we need to ensure all startup-based
    474   // changes have propagated between the clients.
    475   //
    476   // Tests that don't use self-notifications can't await quiescense.  They'll
    477   // have to find their own way of waiting for an initial state if they really
    478   // need such guarantees.
    479   if (TestUsesSelfNotifications()) {
    480     AwaitQuiescence();
    481   }
    482 
    483   return true;
    484 }
    485 
    486 void SyncTest::TearDownOnMainThread() {
    487   for (size_t i = 0; i < clients_.size(); ++i) {
    488     clients_[i]->service()->DisableForUser();
    489   }
    490 
    491   // Some of the pending messages might rely on browser windows still being
    492   // around, so run messages both before and after closing all browsers.
    493   content::RunAllPendingInMessageLoop();
    494   // Close all browser windows.
    495   chrome::CloseAllBrowsers();
    496   content::RunAllPendingInMessageLoop();
    497 
    498   if (fake_server_.get()) {
    499     std::vector<fake_server::FakeServerInvalidationService*>::const_iterator it;
    500     for (it = fake_server_invalidation_services_.begin();
    501          it != fake_server_invalidation_services_.end(); ++it) {
    502       fake_server_->RemoveObserver(*it);
    503     }
    504   }
    505 
    506   // All browsers should be closed at this point, or else we could see memory
    507   // corruption in QuitBrowser().
    508   CHECK_EQ(0U, chrome::GetTotalBrowserCount());
    509   invalidation_forwarders_.clear();
    510   fake_server_invalidation_services_.clear();
    511   clients_.clear();
    512 }
    513 
    514 void SyncTest::SetUpInProcessBrowserTestFixture() {
    515   // We don't take a reference to |resolver|, but mock_host_resolver_override_
    516   // does, so effectively assumes ownership.
    517   net::RuleBasedHostResolverProc* resolver =
    518       new net::RuleBasedHostResolverProc(host_resolver());
    519   resolver->AllowDirectLookup("*.google.com");
    520   // On Linux, we use Chromium's NSS implementation which uses the following
    521   // hosts for certificate verification. Without these overrides, running the
    522   // integration tests on Linux causes error as we make external DNS lookups.
    523   resolver->AllowDirectLookup("*.thawte.com");
    524   resolver->AllowDirectLookup("*.geotrust.com");
    525   resolver->AllowDirectLookup("*.gstatic.com");
    526   mock_host_resolver_override_.reset(
    527       new net::ScopedDefaultHostResolverProc(resolver));
    528 }
    529 
    530 void SyncTest::TearDownInProcessBrowserTestFixture() {
    531   mock_host_resolver_override_.reset();
    532 }
    533 
    534 void SyncTest::ReadPasswordFile() {
    535   base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
    536   password_file_ = cl->GetSwitchValuePath(switches::kPasswordFileForTest);
    537   if (password_file_.empty())
    538     LOG(FATAL) << "Can't run live server test without specifying --"
    539                << switches::kPasswordFileForTest << "=<filename>";
    540   std::string file_contents;
    541   base::ReadFileToString(password_file_, &file_contents);
    542   ASSERT_NE(file_contents, "") << "Password file \""
    543       << password_file_.value() << "\" does not exist.";
    544   std::vector<std::string> tokens;
    545   std::string delimiters = "\r\n";
    546   Tokenize(file_contents, delimiters, &tokens);
    547   ASSERT_EQ(2U, tokens.size()) << "Password file \""
    548       << password_file_.value()
    549       << "\" must contain exactly two lines of text.";
    550   username_ = tokens[0];
    551   password_ = tokens[1];
    552 }
    553 
    554 void SyncTest::SetupMockGaiaResponses() {
    555   factory_.reset(new net::URLFetcherImplFactory());
    556   fake_factory_.reset(new net::FakeURLFetcherFactory(factory_.get()));
    557   fake_factory_->SetFakeResponse(
    558       GaiaUrls::GetInstance()->get_user_info_url(),
    559       "email=user (at) gmail.com\ndisplayEmail=user (at) gmail.com",
    560       net::HTTP_OK,
    561       net::URLRequestStatus::SUCCESS);
    562   fake_factory_->SetFakeResponse(
    563       GaiaUrls::GetInstance()->issue_auth_token_url(),
    564       "auth",
    565       net::HTTP_OK,
    566       net::URLRequestStatus::SUCCESS);
    567   fake_factory_->SetFakeResponse(
    568       GURL(GoogleURLTracker::kSearchDomainCheckURL),
    569       ".google.com",
    570       net::HTTP_OK,
    571       net::URLRequestStatus::SUCCESS);
    572   fake_factory_->SetFakeResponse(
    573       GaiaUrls::GetInstance()->client_login_to_oauth2_url(),
    574       "some_response",
    575       net::HTTP_OK,
    576       net::URLRequestStatus::SUCCESS);
    577   fake_factory_->SetFakeResponse(
    578       GaiaUrls::GetInstance()->oauth2_token_url(),
    579       "{"
    580       "  \"refresh_token\": \"rt1\","
    581       "  \"access_token\": \"at1\","
    582       "  \"expires_in\": 3600,"
    583       "  \"token_type\": \"Bearer\""
    584       "}",
    585       net::HTTP_OK,
    586       net::URLRequestStatus::SUCCESS);
    587   fake_factory_->SetFakeResponse(
    588       GaiaUrls::GetInstance()->oauth_user_info_url(),
    589       "{"
    590       "  \"id\": \"12345\""
    591       "}",
    592       net::HTTP_OK,
    593       net::URLRequestStatus::SUCCESS);
    594   fake_factory_->SetFakeResponse(
    595       GaiaUrls::GetInstance()->oauth1_login_url(),
    596       "SID=sid\nLSID=lsid\nAuth=auth_token",
    597       net::HTTP_OK,
    598       net::URLRequestStatus::SUCCESS);
    599   fake_factory_->SetFakeResponse(
    600       GaiaUrls::GetInstance()->oauth2_revoke_url(),
    601       "",
    602       net::HTTP_OK,
    603       net::URLRequestStatus::SUCCESS);
    604 }
    605 
    606 void SyncTest::SetOAuth2TokenResponse(const std::string& response_data,
    607                                       net::HttpStatusCode response_code,
    608                                       net::URLRequestStatus::Status status) {
    609   ASSERT_TRUE(NULL != fake_factory_.get());
    610   fake_factory_->SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
    611                                  response_data, response_code, status);
    612 }
    613 
    614 void SyncTest::ClearMockGaiaResponses() {
    615   // Clear any mock gaia responses that might have been set.
    616   if (fake_factory_) {
    617     fake_factory_->ClearFakeResponses();
    618     fake_factory_.reset();
    619   }
    620 
    621   // Cancel any outstanding URL fetches and destroy the URLFetcherImplFactory we
    622   // created.
    623   net::URLFetcher::CancelAll();
    624   factory_.reset();
    625 }
    626 
    627 void SyncTest::DecideServerType() {
    628   // Only set |server_type_| if it hasn't already been set. This allows for
    629   // tests to explicitly set this value in each test class if needed.
    630   if (server_type_ == SERVER_TYPE_UNDECIDED) {
    631     base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
    632     if (!cl->HasSwitch(switches::kSyncServiceURL) &&
    633         !cl->HasSwitch(switches::kSyncServerCommandLine)) {
    634       // If neither a sync server URL nor a sync server command line is
    635       // provided, start up a local sync test server and point Chrome
    636       // to its URL.  This is the most common configuration, and the only
    637       // one that makes sense for most developers. FakeServer is the
    638       // current solution but some scenarios are only supported by the
    639       // legacy python server.
    640       switch (test_type_) {
    641         case SINGLE_CLIENT:
    642         case TWO_CLIENT:
    643         case MULTIPLE_CLIENT:
    644           server_type_ = IN_PROCESS_FAKE_SERVER;
    645           break;
    646         default:
    647           server_type_ = LOCAL_PYTHON_SERVER;
    648       }
    649     } else if (cl->HasSwitch(switches::kSyncServiceURL) &&
    650                cl->HasSwitch(switches::kSyncServerCommandLine)) {
    651       // If a sync server URL and a sync server command line are provided,
    652       // start up a local sync server by running the command line. Chrome
    653       // will connect to the server at the URL that was provided.
    654       server_type_ = LOCAL_LIVE_SERVER;
    655     } else if (cl->HasSwitch(switches::kSyncServiceURL) &&
    656                !cl->HasSwitch(switches::kSyncServerCommandLine)) {
    657       // If a sync server URL is provided, but not a server command line,
    658       // it is assumed that the server is already running. Chrome will
    659       // automatically connect to it at the URL provided. There is nothing
    660       // to do here.
    661       server_type_ = EXTERNAL_LIVE_SERVER;
    662     } else {
    663       // If a sync server command line is provided, but not a server URL,
    664       // we flag an error.
    665       LOG(FATAL) << "Can't figure out how to run a server.";
    666     }
    667   }
    668 }
    669 
    670 // Start up a local sync server based on the value of server_type_, which
    671 // was determined from the command line parameters.
    672 void SyncTest::SetUpTestServerIfRequired() {
    673   if (server_type_ == LOCAL_PYTHON_SERVER) {
    674     if (!SetUpLocalPythonTestServer())
    675       LOG(FATAL) << "Failed to set up local python sync and XMPP servers";
    676     SetupMockGaiaResponses();
    677   } else if (server_type_ == LOCAL_LIVE_SERVER) {
    678     // Using mock gaia credentials requires the use of a mock XMPP server.
    679     if (username_ == "user (at) gmail.com" && !SetUpLocalPythonTestServer())
    680       LOG(FATAL) << "Failed to set up local python XMPP server";
    681     if (!SetUpLocalTestServer())
    682       LOG(FATAL) << "Failed to set up local test server";
    683   } else if (server_type_ == IN_PROCESS_FAKE_SERVER) {
    684     fake_server_.reset(new fake_server::FakeServer());
    685     SetupMockGaiaResponses();
    686   } else if (server_type_ == EXTERNAL_LIVE_SERVER) {
    687     // Nothing to do; we'll just talk to the URL we were given.
    688   } else {
    689     LOG(FATAL) << "Don't know which server environment to run test in.";
    690   }
    691 }
    692 
    693 bool SyncTest::SetUpLocalPythonTestServer() {
    694   EXPECT_TRUE(sync_server_.Start())
    695       << "Could not launch local python test server.";
    696 
    697   base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
    698   if (server_type_ == LOCAL_PYTHON_SERVER) {
    699     std::string sync_service_url = sync_server_.GetURL("chromiumsync").spec();
    700     cl->AppendSwitchASCII(switches::kSyncServiceURL, sync_service_url);
    701     DVLOG(1) << "Started local python sync server at " << sync_service_url;
    702   }
    703 
    704   int xmpp_port = 0;
    705   if (!sync_server_.server_data().GetInteger("xmpp_port", &xmpp_port)) {
    706     LOG(ERROR) << "Could not find valid xmpp_port value";
    707     return false;
    708   }
    709   if ((xmpp_port <= 0) || (xmpp_port > kuint16max)) {
    710     LOG(ERROR) << "Invalid xmpp port: " << xmpp_port;
    711     return false;
    712   }
    713 
    714   net::HostPortPair xmpp_host_port_pair(sync_server_.host_port_pair());
    715   xmpp_host_port_pair.set_port(xmpp_port);
    716   xmpp_port_.reset(new net::ScopedPortException(xmpp_port));
    717 
    718   if (!cl->HasSwitch(invalidation::switches::kSyncNotificationHostPort)) {
    719     cl->AppendSwitchASCII(invalidation::switches::kSyncNotificationHostPort,
    720                           xmpp_host_port_pair.ToString());
    721     // The local XMPP server only supports insecure connections.
    722     cl->AppendSwitch(invalidation::switches::kSyncAllowInsecureXmppConnection);
    723   }
    724   DVLOG(1) << "Started local python XMPP server at "
    725            << xmpp_host_port_pair.ToString();
    726 
    727   return true;
    728 }
    729 
    730 bool SyncTest::SetUpLocalTestServer() {
    731   base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
    732   base::CommandLine::StringType server_cmdline_string =
    733       cl->GetSwitchValueNative(switches::kSyncServerCommandLine);
    734   base::CommandLine::StringVector server_cmdline_vector;
    735   base::CommandLine::StringType delimiters(FILE_PATH_LITERAL(" "));
    736   Tokenize(server_cmdline_string, delimiters, &server_cmdline_vector);
    737   base::CommandLine server_cmdline(server_cmdline_vector);
    738   base::LaunchOptions options;
    739 #if defined(OS_WIN)
    740   options.start_hidden = true;
    741 #endif
    742   if (!base::LaunchProcess(server_cmdline, options, &test_server_handle_))
    743     LOG(ERROR) << "Could not launch local test server.";
    744 
    745   const base::TimeDelta kMaxWaitTime = TestTimeouts::action_max_timeout();
    746   const int kNumIntervals = 15;
    747   if (WaitForTestServerToStart(kMaxWaitTime, kNumIntervals)) {
    748     DVLOG(1) << "Started local test server at "
    749              << cl->GetSwitchValueASCII(switches::kSyncServiceURL) << ".";
    750     return true;
    751   } else {
    752     LOG(ERROR) << "Could not start local test server at "
    753                << cl->GetSwitchValueASCII(switches::kSyncServiceURL) << ".";
    754     return false;
    755   }
    756 }
    757 
    758 bool SyncTest::TearDownLocalPythonTestServer() {
    759   if (!sync_server_.Stop()) {
    760     LOG(ERROR) << "Could not stop local python test server.";
    761     return false;
    762   }
    763   xmpp_port_.reset();
    764   return true;
    765 }
    766 
    767 bool SyncTest::TearDownLocalTestServer() {
    768   if (test_server_handle_ != base::kNullProcessHandle) {
    769     EXPECT_TRUE(base::KillProcess(test_server_handle_, 0, false))
    770         << "Could not stop local test server.";
    771     base::CloseProcessHandle(test_server_handle_);
    772     test_server_handle_ = base::kNullProcessHandle;
    773   }
    774   return true;
    775 }
    776 
    777 bool SyncTest::WaitForTestServerToStart(base::TimeDelta wait, int intervals) {
    778   for (int i = 0; i < intervals; ++i) {
    779     if (IsTestServerRunning())
    780       return true;
    781     base::PlatformThread::Sleep(wait / intervals);
    782   }
    783   return false;
    784 }
    785 
    786 bool SyncTest::IsTestServerRunning() {
    787   base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
    788   std::string sync_url = cl->GetSwitchValueASCII(switches::kSyncServiceURL);
    789   GURL sync_url_status(sync_url.append("/healthz"));
    790   SyncServerStatusChecker delegate;
    791   scoped_ptr<net::URLFetcher> fetcher(net::URLFetcher::Create(
    792     sync_url_status, net::URLFetcher::GET, &delegate));
    793   fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE |
    794                         net::LOAD_DO_NOT_SEND_COOKIES |
    795                         net::LOAD_DO_NOT_SAVE_COOKIES);
    796   fetcher->SetRequestContext(g_browser_process->system_request_context());
    797   fetcher->Start();
    798   content::RunMessageLoop();
    799   return delegate.running();
    800 }
    801 
    802 void SyncTest::EnableNetwork(Profile* profile) {
    803   // TODO(pvalenzuela): Remove this restriction when FakeServer's observers
    804   // (namely FakeServerInvaldationService) are aware of a network disconnect.
    805   ASSERT_NE(IN_PROCESS_FAKE_SERVER, server_type_)
    806       << "FakeServer does not support EnableNetwork.";
    807   SetProxyConfig(profile->GetRequestContext(),
    808                  net::ProxyConfig::CreateDirect());
    809   if (notifications_enabled_) {
    810     EnableNotificationsImpl();
    811   }
    812   // TODO(rsimha): Remove this line once http://crbug.com/53857 is fixed.
    813   net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
    814 }
    815 
    816 void SyncTest::DisableNetwork(Profile* profile) {
    817   // TODO(pvalenzuela): Remove this restriction when FakeServer's observers
    818   // (namely FakeServerInvaldationService) are aware of a network disconnect.
    819   ASSERT_NE(IN_PROCESS_FAKE_SERVER, server_type_)
    820       << "FakeServer does not support DisableNetwork.";
    821   DisableNotificationsImpl();
    822   // Set the current proxy configuration to a nonexistent proxy to effectively
    823   // disable networking.
    824   net::ProxyConfig config;
    825   config.proxy_rules().ParseFromString("http=127.0.0.1:0");
    826   SetProxyConfig(profile->GetRequestContext(), config);
    827   // TODO(rsimha): Remove this line once http://crbug.com/53857 is fixed.
    828   net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
    829 }
    830 
    831 bool SyncTest::TestUsesSelfNotifications() {
    832   return true;
    833 }
    834 
    835 bool SyncTest::EnableEncryption(int index) {
    836   ProfileSyncService* service = GetClient(index)->service();
    837 
    838   if (::IsEncryptionComplete(service))
    839     return true;
    840 
    841   service->EnableEncryptEverything();
    842 
    843   // In order to kick off the encryption we have to reconfigure. Just grab the
    844   // currently synced types and use them.
    845   const syncer::ModelTypeSet synced_datatypes =
    846       service->GetPreferredDataTypes();
    847   bool sync_everything = synced_datatypes.Equals(syncer::ModelTypeSet::All());
    848   service->OnUserChoseDatatypes(sync_everything, synced_datatypes);
    849 
    850   return AwaitEncryptionComplete(index);
    851 }
    852 
    853 bool SyncTest::IsEncryptionComplete(int index) {
    854   return ::IsEncryptionComplete(GetClient(index)->service());
    855 }
    856 
    857 bool SyncTest::AwaitEncryptionComplete(int index) {
    858   ProfileSyncService* service = GetClient(index)->service();
    859   EncryptionChecker checker(service);
    860   checker.Wait();
    861   return !checker.TimedOut();
    862 }
    863 
    864 bool SyncTest::AwaitQuiescence() {
    865   return ProfileSyncServiceHarness::AwaitQuiescence(clients());
    866 }
    867 
    868 bool SyncTest::ServerSupportsNotificationControl() const {
    869   EXPECT_NE(SERVER_TYPE_UNDECIDED, server_type_);
    870 
    871   // Supported only if we're using the python testserver.
    872   return server_type_ == LOCAL_PYTHON_SERVER;
    873 }
    874 
    875 void SyncTest::DisableNotificationsImpl() {
    876   ASSERT_TRUE(ServerSupportsNotificationControl());
    877   std::string path = "chromiumsync/disablenotifications";
    878   ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
    879   ASSERT_EQ("Notifications disabled",
    880             base::UTF16ToASCII(
    881                 browser()->tab_strip_model()->GetActiveWebContents()->
    882                     GetTitle()));
    883 }
    884 
    885 void SyncTest::DisableNotifications() {
    886   DisableNotificationsImpl();
    887   notifications_enabled_ = false;
    888 }
    889 
    890 void SyncTest::EnableNotificationsImpl() {
    891   ASSERT_TRUE(ServerSupportsNotificationControl());
    892   std::string path = "chromiumsync/enablenotifications";
    893   ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
    894   ASSERT_EQ("Notifications enabled",
    895             base::UTF16ToASCII(
    896                 browser()->tab_strip_model()->GetActiveWebContents()->
    897                     GetTitle()));
    898 }
    899 
    900 void SyncTest::EnableNotifications() {
    901   EnableNotificationsImpl();
    902   notifications_enabled_ = true;
    903 }
    904 
    905 void SyncTest::TriggerNotification(syncer::ModelTypeSet changed_types) {
    906   ASSERT_TRUE(ServerSupportsNotificationControl());
    907   const std::string& data =
    908       syncer::P2PNotificationData(
    909           "from_server",
    910           syncer::NOTIFY_ALL,
    911           syncer::ObjectIdInvalidationMap::InvalidateAll(
    912               syncer::ModelTypeSetToObjectIdSet(changed_types))).ToString();
    913   const std::string& path =
    914       std::string("chromiumsync/sendnotification?channel=") +
    915       syncer::kSyncP2PNotificationChannel + "&data=" + data;
    916   ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
    917   ASSERT_EQ("Notification sent",
    918             base::UTF16ToASCII(
    919                 browser()->tab_strip_model()->GetActiveWebContents()->
    920                     GetTitle()));
    921 }
    922 
    923 bool SyncTest::ServerSupportsErrorTriggering() const {
    924   EXPECT_NE(SERVER_TYPE_UNDECIDED, server_type_);
    925 
    926   // Supported only if we're using the python testserver.
    927   return server_type_ == LOCAL_PYTHON_SERVER;
    928 }
    929 
    930 void SyncTest::TriggerMigrationDoneError(syncer::ModelTypeSet model_types) {
    931   ASSERT_TRUE(ServerSupportsErrorTriggering());
    932   std::string path = "chromiumsync/migrate";
    933   char joiner = '?';
    934   for (syncer::ModelTypeSet::Iterator it = model_types.First();
    935        it.Good(); it.Inc()) {
    936     path.append(
    937         base::StringPrintf(
    938             "%ctype=%d", joiner,
    939             syncer::GetSpecificsFieldNumberFromModelType(it.Get())));
    940     joiner = '&';
    941   }
    942   ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
    943   ASSERT_EQ("Migration: 200",
    944             base::UTF16ToASCII(
    945                 browser()->tab_strip_model()->GetActiveWebContents()->
    946                     GetTitle()));
    947 }
    948 
    949 void SyncTest::TriggerTransientError() {
    950   ASSERT_TRUE(ServerSupportsErrorTriggering());
    951   std::string path = "chromiumsync/transienterror";
    952   ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
    953   ASSERT_EQ("Transient error",
    954             base::UTF16ToASCII(
    955                 browser()->tab_strip_model()->GetActiveWebContents()->
    956                     GetTitle()));
    957 }
    958 
    959 void SyncTest::TriggerXmppAuthError() {
    960   ASSERT_TRUE(ServerSupportsErrorTriggering());
    961   std::string path = "chromiumsync/xmppcred";
    962   ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
    963 }
    964 
    965 namespace {
    966 
    967 sync_pb::SyncEnums::ErrorType
    968     GetClientToServerResponseErrorType(
    969         syncer::SyncProtocolErrorType error) {
    970   switch (error) {
    971     case syncer::SYNC_SUCCESS:
    972       return sync_pb::SyncEnums::SUCCESS;
    973     case syncer::NOT_MY_BIRTHDAY:
    974       return sync_pb::SyncEnums::NOT_MY_BIRTHDAY;
    975     case syncer::THROTTLED:
    976       return sync_pb::SyncEnums::THROTTLED;
    977     case syncer::CLEAR_PENDING:
    978       return sync_pb::SyncEnums::CLEAR_PENDING;
    979     case syncer::TRANSIENT_ERROR:
    980       return sync_pb::SyncEnums::TRANSIENT_ERROR;
    981     case syncer::MIGRATION_DONE:
    982       return sync_pb::SyncEnums::MIGRATION_DONE;
    983     case syncer::UNKNOWN_ERROR:
    984       return sync_pb::SyncEnums::UNKNOWN;
    985     case syncer::INVALID_CREDENTIAL:
    986       NOTREACHED();   // NOTREACHED() because auth error is not set through
    987                       // error code in sync response.
    988       return sync_pb::SyncEnums::UNKNOWN;
    989     case syncer::DISABLED_BY_ADMIN:
    990       return sync_pb::SyncEnums::DISABLED_BY_ADMIN;
    991     case syncer::USER_ROLLBACK:
    992       return sync_pb::SyncEnums::USER_ROLLBACK;
    993     case syncer::NON_RETRIABLE_ERROR:
    994       return sync_pb::SyncEnums::UNKNOWN;
    995   }
    996   return sync_pb::SyncEnums::UNKNOWN;
    997 }
    998 
    999 sync_pb::SyncEnums::Action GetClientToServerResponseAction(
   1000     const syncer::ClientAction& action) {
   1001   switch (action) {
   1002     case syncer::UPGRADE_CLIENT:
   1003       return sync_pb::SyncEnums::UPGRADE_CLIENT;
   1004     case syncer::CLEAR_USER_DATA_AND_RESYNC:
   1005       return sync_pb::SyncEnums::CLEAR_USER_DATA_AND_RESYNC;
   1006     case syncer::ENABLE_SYNC_ON_ACCOUNT:
   1007       return sync_pb::SyncEnums::ENABLE_SYNC_ON_ACCOUNT;
   1008     case syncer::STOP_AND_RESTART_SYNC:
   1009       return sync_pb::SyncEnums::STOP_AND_RESTART_SYNC;
   1010     case syncer::DISABLE_SYNC_ON_CLIENT:
   1011       return sync_pb::SyncEnums::DISABLE_SYNC_ON_CLIENT;
   1012     case syncer::STOP_SYNC_FOR_DISABLED_ACCOUNT:
   1013     case syncer::DISABLE_SYNC_AND_ROLLBACK:
   1014     case syncer::ROLLBACK_DONE:
   1015       NOTREACHED();   // No corresponding proto action for these. Shouldn't
   1016                       // test.
   1017       return sync_pb::SyncEnums::UNKNOWN_ACTION;
   1018     case syncer::UNKNOWN_ACTION:
   1019       return sync_pb::SyncEnums::UNKNOWN_ACTION;
   1020   }
   1021   return sync_pb::SyncEnums::UNKNOWN_ACTION;
   1022 }
   1023 
   1024 }  // namespace
   1025 
   1026 void SyncTest::TriggerSyncError(const syncer::SyncProtocolError& error,
   1027                                 SyncErrorFrequency frequency) {
   1028   ASSERT_TRUE(ServerSupportsErrorTriggering());
   1029   std::string path = "chromiumsync/error";
   1030   int error_type =
   1031       static_cast<int>(GetClientToServerResponseErrorType(
   1032           error.error_type));
   1033   int action = static_cast<int>(GetClientToServerResponseAction(
   1034       error.action));
   1035 
   1036   path.append(base::StringPrintf("?error=%d", error_type));
   1037   path.append(base::StringPrintf("&action=%d", action));
   1038 
   1039   path.append(base::StringPrintf("&error_description=%s",
   1040                                  error.error_description.c_str()));
   1041   path.append(base::StringPrintf("&url=%s", error.url.c_str()));
   1042   path.append(base::StringPrintf("&frequency=%d", frequency));
   1043 
   1044   ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
   1045   std::string output = base::UTF16ToASCII(
   1046       browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
   1047   ASSERT_TRUE(output.find("SetError: 200") != base::string16::npos);
   1048 }
   1049 
   1050 void SyncTest::TriggerCreateSyncedBookmarks() {
   1051   ASSERT_TRUE(ServerSupportsErrorTriggering());
   1052   std::string path = "chromiumsync/createsyncedbookmarks";
   1053   ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
   1054   ASSERT_EQ("Synced Bookmarks",
   1055             base::UTF16ToASCII(
   1056                 browser()->tab_strip_model()->GetActiveWebContents()->
   1057                     GetTitle()));
   1058 }
   1059 
   1060 void SyncTest::SetupNetwork(net::URLRequestContextGetter* context_getter) {
   1061   base::WaitableEvent done(false, false);
   1062   BrowserThread::PostTask(
   1063       BrowserThread::IO, FROM_HERE,
   1064       base::Bind(&SetupNetworkCallback, &done,
   1065                  make_scoped_refptr(context_getter)));
   1066   done.Wait();
   1067 }
   1068 
   1069 void SyncTest::SetProxyConfig(net::URLRequestContextGetter* context_getter,
   1070                               const net::ProxyConfig& proxy_config) {
   1071   base::WaitableEvent done(false, false);
   1072   BrowserThread::PostTask(
   1073       BrowserThread::IO, FROM_HERE,
   1074       base::Bind(&SetProxyConfigCallback, &done,
   1075                  make_scoped_refptr(context_getter), proxy_config));
   1076   done.Wait();
   1077 }
   1078 
   1079 fake_server::FakeServer* SyncTest::GetFakeServer() const {
   1080   return fake_server_.get();
   1081 }
   1082