sync_test.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
14df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner// Copyright (c) 2012 The Chromium Authors. All rights reserved.
29769ab22265b313171d201b5928688524a01bd87Misha Brukman// Use of this source code is governed by a BSD-style license that can be
36fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell// found in the LICENSE file.
46fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell
56fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell#include "chrome/browser/sync/test/integration/sync_test.h"
66fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell
79769ab22265b313171d201b5928688524a01bd87Misha Brukman#include <vector>
86fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell
94df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "base/basictypes.h"
104df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "base/bind.h"
114df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "base/command_line.h"
121c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "base/message_loop.h"
131c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "base/path_service.h"
144df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "base/string_util.h"
154df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "base/stringprintf.h"
164df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "base/synchronization/waitable_event.h"
174df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "base/test/test_timeouts.h"
184df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "base/threading/platform_thread.h"
191c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "base/utf_string_conversions.h"
201c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "base/values.h"
211c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "chrome/browser/bookmarks/bookmark_model_factory.h"
221c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "chrome/browser/google/google_url_tracker.h"
231c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "chrome/browser/history/history_service_factory.h"
241c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "chrome/browser/lifetime/application_lifetime.h"
251c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "chrome/browser/profiles/profile.h"
261c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "chrome/browser/profiles/profile_manager.h"
271c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "chrome/browser/search_engines/template_url_service.h"
284df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "chrome/browser/search_engines/template_url_service_factory.h"
294df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "chrome/browser/sync/profile_sync_service_factory.h"
304df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "chrome/browser/sync/profile_sync_service_harness.h"
314df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
324df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner#include "chrome/browser/ui/browser.h"
331c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "chrome/browser/ui/browser_finder.h"
342b38c0d94bb54659c8748eca75b4ca64a0f01b78Chris Lattner#include "chrome/browser/ui/host_desktop.h"
35d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke#include "chrome/browser/ui/tabs/tab_strip_model.h"
36d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke#include "chrome/common/chrome_paths.h"
37d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke#include "chrome/common/chrome_switches.h"
381c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "chrome/test/base/testing_browser_process.h"
391c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "chrome/test/base/ui_test_utils.h"
401c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "components/webdata/encryptor/encryptor.h"
411c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "content/public/browser/web_contents.h"
421c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "content/public/test/test_browser_thread.h"
431c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "google_apis/gaia/gaia_urls.h"
44ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner#include "googleurl/src/gurl.h"
45ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner#include "net/base/escape.h"
46ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner#include "net/base/load_flags.h"
471c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "net/base/network_change_notifier.h"
481c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "net/proxy/proxy_config.h"
491c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "net/proxy/proxy_config_service_fixed.h"
501c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "net/proxy/proxy_service.h"
511c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "net/test/spawned_test_server.h"
521c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "net/url_request/test_url_fetcher_factory.h"
539769ab22265b313171d201b5928688524a01bd87Misha Brukman#include "net/url_request/url_fetcher.h"
541c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "net/url_request/url_fetcher_delegate.h"
551c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "net/url_request/url_request_context.h"
561c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "net/url_request/url_request_context_getter.h"
571c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "net/url_request/url_request_status.h"
581c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "sync/engine/sync_scheduler_impl.h"
591c56b730a6313886076d7b293a126ae5576f5288Chris Lattner#include "sync/notifier/p2p_invalidator.h"
60ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner#include "sync/protocol/sync.pb.h"
611c56b730a6313886076d7b293a126ae5576f5288Chris Lattner
621c56b730a6313886076d7b293a126ae5576f5288Chris Lattnerusing content::BrowserThread;
631c56b730a6313886076d7b293a126ae5576f5288Chris Lattner
641c56b730a6313886076d7b293a126ae5576f5288Chris Lattnernamespace switches {
651c56b730a6313886076d7b293a126ae5576f5288Chris Lattnerconst char kPasswordFileForTest[] = "password-file-for-test";
66dd298c8c6eb036baf35bf5a559c59d2afd2c7944Misha Brukmanconst char kSyncUserForTest[] = "sync-user-for-test";
671c56b730a6313886076d7b293a126ae5576f5288Chris Lattnerconst char kSyncPasswordForTest[] = "sync-password-for-test";
684df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattnerconst char kSyncServerCommandLine[] = "sync-server-command-line";
691c56b730a6313886076d7b293a126ae5576f5288Chris Lattner}
701c56b730a6313886076d7b293a126ae5576f5288Chris Lattner
711c56b730a6313886076d7b293a126ae5576f5288Chris Lattner// Helper class that checks whether a sync test server is running or not.
724df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattnerclass SyncServerStatusChecker : public net::URLFetcherDelegate {
73f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner public:
74f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner  SyncServerStatusChecker() : running_(false) {}
75f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner
76f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
77f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner    std::string data;
78f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner    source->GetResponseAsString(&data);
791c56b730a6313886076d7b293a126ae5576f5288Chris Lattner    running_ =
804df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner        (source->GetStatus().status() == net::URLRequestStatus::SUCCESS &&
81f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner        source->GetResponseCode() == 200 && data.find("ok") == 0);
82f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner    MessageLoop::current()->Quit();
83f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner  }
84f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner
85f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner  bool running() const { return running_; }
861c56b730a6313886076d7b293a126ae5576f5288Chris Lattner
87ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner private:
884df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner  bool running_;
8962b5c167de0ca5883a7ad5eb0900eb0c15ad3707Chris Lattner};
9062b5c167de0ca5883a7ad5eb0900eb0c15ad3707Chris Lattner
9162b5c167de0ca5883a7ad5eb0900eb0c15ad3707Chris Lattnervoid SetProxyConfigCallback(
9262b5c167de0ca5883a7ad5eb0900eb0c15ad3707Chris Lattner    base::WaitableEvent* done,
9362b5c167de0ca5883a7ad5eb0900eb0c15ad3707Chris Lattner    net::URLRequestContextGetter* url_request_context_getter,
9462b5c167de0ca5883a7ad5eb0900eb0c15ad3707Chris Lattner    const net::ProxyConfig& proxy_config) {
95ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  net::ProxyService* proxy_service =
9662b5c167de0ca5883a7ad5eb0900eb0c15ad3707Chris Lattner      url_request_context_getter->GetURLRequestContext()->proxy_service();
97762e8e846f0ad50ffea56216c5ea20db1c95b756Chris Lattner  proxy_service->ResetConfigService(
98762e8e846f0ad50ffea56216c5ea20db1c95b756Chris Lattner      new net::ProxyConfigServiceFixed(proxy_config));
99762e8e846f0ad50ffea56216c5ea20db1c95b756Chris Lattner  done->Signal();
100762e8e846f0ad50ffea56216c5ea20db1c95b756Chris Lattner}
101ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner
10262b5c167de0ca5883a7ad5eb0900eb0c15ad3707Chris LattnerSyncTest::SyncTest(TestType test_type)
103248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    : test_type_(test_type),
104248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      server_type_(SERVER_TYPE_UNDECIDED),
105248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      num_clients_(-1),
106248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      use_verifier_(true),
107248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      notifications_enabled_(true),
108248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      test_server_handle_(base::kNullProcessHandle),
109248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      number_of_default_sync_items_(0) {
110248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  sync_datatype_helper::AssociateWithTest(this);
1119769ab22265b313171d201b5928688524a01bd87Misha Brukman  switch (test_type_) {
1129769ab22265b313171d201b5928688524a01bd87Misha Brukman    case SINGLE_CLIENT: {
113248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      num_clients_ = 1;
114248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      break;
115248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    }
116248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    case TWO_CLIENT: {
117248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      num_clients_ = 2;
118248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      break;
119248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    }
120248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    case MULTIPLE_CLIENT: {
121248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      num_clients_ = 3;
122248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      break;
1239769ab22265b313171d201b5928688524a01bd87Misha Brukman    }
124248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  }
125248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner}
126248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner
127248e8ebeff834db9b78917b1531eeee7035eb113Chris LattnerSyncTest::~SyncTest() {}
128248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner
129248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattnervoid SyncTest::SetUp() {
1309769ab22265b313171d201b5928688524a01bd87Misha Brukman  CommandLine* cl = CommandLine::ForCurrentProcess();
131248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  if (cl->HasSwitch(switches::kPasswordFileForTest)) {
132248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    ReadPasswordFile();
133248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  } else if (cl->HasSwitch(switches::kSyncUserForTest) &&
134248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner             cl->HasSwitch(switches::kSyncPasswordForTest)) {
135248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    username_ = cl->GetSwitchValueASCII(switches::kSyncUserForTest);
136248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    password_ = cl->GetSwitchValueASCII(switches::kSyncPasswordForTest);
137248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  } else {
1389769ab22265b313171d201b5928688524a01bd87Misha Brukman    SetupMockGaiaResponses();
139248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  }
140248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner
141248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  if (!cl->HasSwitch(switches::kSyncServiceURL) &&
142248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner      !cl->HasSwitch(switches::kSyncServerCommandLine)) {
143248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    // If neither a sync server URL nor a sync server command line is
1449769ab22265b313171d201b5928688524a01bd87Misha Brukman    // provided, start up a local python sync test server and point Chrome
145248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    // to its URL.  This is the most common configuration, and the only
146248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    // one that makes sense for most developers.
147248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    server_type_ = LOCAL_PYTHON_SERVER;
148248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  } else if (cl->HasSwitch(switches::kSyncServiceURL) &&
1499769ab22265b313171d201b5928688524a01bd87Misha Brukman             cl->HasSwitch(switches::kSyncServerCommandLine)) {
150248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    // If a sync server URL and a sync server command line are provided,
151248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    // start up a local sync server by running the command line. Chrome
152248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    // will connect to the server at the URL that was provided.
153248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    server_type_ = LOCAL_LIVE_SERVER;
154248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  } else if (cl->HasSwitch(switches::kSyncServiceURL) &&
155248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner             !cl->HasSwitch(switches::kSyncServerCommandLine)) {
156248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    // If a sync server URL is provided, but not a server command line,
1579769ab22265b313171d201b5928688524a01bd87Misha Brukman    // it is assumed that the server is already running. Chrome will
158248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    // automatically connect to it at the URL provided. There is nothing
159248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    // to do here.
160248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    server_type_ = EXTERNAL_LIVE_SERVER;
1619769ab22265b313171d201b5928688524a01bd87Misha Brukman  } else {
162248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    // If a sync server command line is provided, but not a server URL,
163248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    // we flag an error.
164248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    LOG(FATAL) << "Can't figure out how to run a server.";
165248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  }
166248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner
167248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  if (username_.empty() || password_.empty())
168248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    LOG(FATAL) << "Cannot run sync tests without GAIA credentials.";
169248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner
170248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  // Mock the Mac Keychain service.  The real Keychain can block on user input.
1719769ab22265b313171d201b5928688524a01bd87Misha Brukman#if defined(OS_MACOSX)
172248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  Encryptor::UseMockKeychain(true);
173248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner#endif
174248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner
1759769ab22265b313171d201b5928688524a01bd87Misha Brukman  // Yield control back to the InProcessBrowserTest framework.
176248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  InProcessBrowserTest::SetUp();
1779769ab22265b313171d201b5928688524a01bd87Misha Brukman}
178248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner
179248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattnervoid SyncTest::TearDown() {
180248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  // Clear any mock gaia responses that might have been set.
181248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  ClearMockGaiaResponses();
1829769ab22265b313171d201b5928688524a01bd87Misha Brukman
1839769ab22265b313171d201b5928688524a01bd87Misha Brukman  // Allow the InProcessBrowserTest framework to perform its tear down.
184248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  InProcessBrowserTest::TearDown();
185248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner
186248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  // Stop the local python test server. This is a no-op if one wasn't started.
187248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  TearDownLocalPythonTestServer();
188fb752ba02ada9349353b256f81405dd6866c1364Chris Lattner
1899769ab22265b313171d201b5928688524a01bd87Misha Brukman  // Stop the local sync test server. This is a no-op if one wasn't started.
1903e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner  TearDownLocalTestServer();
1915cb66e24d42b40d087989199297c369b3f3b2766Chris Lattner}
19294c420da4a10498c1955d837ed11e66ae3c21dcaChris Lattner
19394c420da4a10498c1955d837ed11e66ae3c21dcaChris Lattnervoid SyncTest::SetUpCommandLine(CommandLine* cl) {
1943e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner  AddTestSwitches(cl);
1953e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner  AddOptionalTypesToCommandLine(cl);
1963e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner}
1973e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner
1983e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattnervoid SyncTest::AddTestSwitches(CommandLine* cl) {
1993e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner  // TODO(rsimha): Until we implement a fake Tango server against which tests
2003e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner  // can run, we need to set the --sync-notification-method to "p2p".
201248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner  if (!cl->HasSwitch(switches::kSyncNotificationMethod))
202248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner    cl->AppendSwitchASCII(switches::kSyncNotificationMethod, "p2p");
203248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner
2043e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner  // Disable non-essential access of external network resources.
2053e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner  if (!cl->HasSwitch(switches::kDisableBackgroundNetworking))
20694c420da4a10498c1955d837ed11e66ae3c21dcaChris Lattner    cl->AppendSwitch(switches::kDisableBackgroundNetworking);
20794c420da4a10498c1955d837ed11e66ae3c21dcaChris Lattner
2083e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner  // TODO(sync): remove this once keystore encryption is enabled by default.
2093e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner  if (!cl->HasSwitch(switches::kSyncKeystoreEncryption))
2103e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner    cl->AppendSwitch(switches::kSyncKeystoreEncryption);
2113e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner
2123e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner  if (!cl->HasSwitch(switches::kSyncShortInitialRetryOverride))
2133e295b1b59e47916c8ae5d42eb27a23bd580cabeChris Lattner    cl->AppendSwitch(switches::kSyncShortInitialRetryOverride);
214248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner
215fb752ba02ada9349353b256f81405dd6866c1364Chris Lattner  // TODO(sync): Fix enable_disable_test.cc to play nice with priority
216fb752ba02ada9349353b256f81405dd6866c1364Chris Lattner  // preferences.
2178eec644862251e14add0d2707d655fcce91e8f70Chris Lattner  if (!cl->HasSwitch(switches::kDisableSyncPriorityPreferences))
2188eec644862251e14add0d2707d655fcce91e8f70Chris Lattner    cl->AppendSwitch(switches::kDisableSyncPriorityPreferences);
219248e8ebeff834db9b78917b1531eeee7035eb113Chris Lattner}
2204df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner
2211c56b730a6313886076d7b293a126ae5576f5288Chris Lattnervoid SyncTest::AddOptionalTypesToCommandLine(CommandLine* cl) {}
2221c56b730a6313886076d7b293a126ae5576f5288Chris Lattner
2231c56b730a6313886076d7b293a126ae5576f5288Chris Lattner// static
2241c56b730a6313886076d7b293a126ae5576f5288Chris LattnerProfile* SyncTest::MakeProfile(const base::FilePath::StringType name) {
2251c56b730a6313886076d7b293a126ae5576f5288Chris Lattner  base::FilePath path;
2261c56b730a6313886076d7b293a126ae5576f5288Chris Lattner  PathService::Get(chrome::DIR_USER_DATA, &path);
2271c56b730a6313886076d7b293a126ae5576f5288Chris Lattner  path = path.Append(name);
2281c56b730a6313886076d7b293a126ae5576f5288Chris Lattner
2291c56b730a6313886076d7b293a126ae5576f5288Chris Lattner  if (!file_util::PathExists(path))
2305cb66e24d42b40d087989199297c369b3f3b2766Chris Lattner    CHECK(file_util::CreateDirectory(path));
2311c56b730a6313886076d7b293a126ae5576f5288Chris Lattner
2321c56b730a6313886076d7b293a126ae5576f5288Chris Lattner  Profile* profile =
2331c56b730a6313886076d7b293a126ae5576f5288Chris Lattner      Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
234414c36769aff6ec688c49f493122529394357d05Chris Lattner  g_browser_process->profile_manager()->RegisterTestingProfile(profile,
235414c36769aff6ec688c49f493122529394357d05Chris Lattner                                                               true,
236414c36769aff6ec688c49f493122529394357d05Chris Lattner                                                               true);
2371c56b730a6313886076d7b293a126ae5576f5288Chris Lattner  return profile;
2385cb66e24d42b40d087989199297c369b3f3b2766Chris Lattner}
2391c56b730a6313886076d7b293a126ae5576f5288Chris Lattner
240e40bb915bae2aecdd1578ea356d5e4c8ac31061cChris LattnerProfile* SyncTest::GetProfile(int index) {
241414c36769aff6ec688c49f493122529394357d05Chris Lattner  if (profiles_.empty())
242414c36769aff6ec688c49f493122529394357d05Chris Lattner    LOG(FATAL) << "SetupClients() has not yet been called.";
243414c36769aff6ec688c49f493122529394357d05Chris Lattner  if (index < 0 || index >= static_cast<int>(profiles_.size()))
244414c36769aff6ec688c49f493122529394357d05Chris Lattner    LOG(FATAL) << "GetProfile(): Index is out of bounds.";
245e40bb915bae2aecdd1578ea356d5e4c8ac31061cChris Lattner  return profiles_[index];
246ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner}
247e40bb915bae2aecdd1578ea356d5e4c8ac31061cChris Lattner
2481c56b730a6313886076d7b293a126ae5576f5288Chris LattnerBrowser* SyncTest::GetBrowser(int index) {
2491c56b730a6313886076d7b293a126ae5576f5288Chris Lattner  if (browsers_.empty())
2505cb66e24d42b40d087989199297c369b3f3b2766Chris Lattner    LOG(FATAL) << "SetupClients() has not yet been called.";
2515cb66e24d42b40d087989199297c369b3f3b2766Chris Lattner  if (index < 0 || index >= static_cast<int>(browsers_.size()))
2521c56b730a6313886076d7b293a126ae5576f5288Chris Lattner    LOG(FATAL) << "GetBrowser(): Index is out of bounds.";
2531c56b730a6313886076d7b293a126ae5576f5288Chris Lattner  return browsers_[index];
2545cb66e24d42b40d087989199297c369b3f3b2766Chris Lattner}
2551c56b730a6313886076d7b293a126ae5576f5288Chris Lattner
2561c56b730a6313886076d7b293a126ae5576f5288Chris LattnerProfileSyncServiceHarness* SyncTest::GetClient(int index) {
2571c56b730a6313886076d7b293a126ae5576f5288Chris Lattner  if (clients_.empty())
2581c56b730a6313886076d7b293a126ae5576f5288Chris Lattner    LOG(FATAL) << "SetupClients() has not yet been called.";
2591c56b730a6313886076d7b293a126ae5576f5288Chris Lattner  if (index < 0 || index >= static_cast<int>(clients_.size()))
2601c56b730a6313886076d7b293a126ae5576f5288Chris Lattner    LOG(FATAL) << "GetClient(): Index is out of bounds.";
2611c56b730a6313886076d7b293a126ae5576f5288Chris Lattner  return clients_[index];
2621c56b730a6313886076d7b293a126ae5576f5288Chris Lattner}
2631c56b730a6313886076d7b293a126ae5576f5288Chris Lattner
2641c56b730a6313886076d7b293a126ae5576f5288Chris LattnerProfile* SyncTest::verifier() {
2651c56b730a6313886076d7b293a126ae5576f5288Chris Lattner  if (verifier_ == NULL)
2664df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner    LOG(FATAL) << "SetupClients() has not yet been called.";
267ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  return verifier_;
268ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner}
269ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner
270ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattnervoid SyncTest::DisableVerifier() {
271f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner  use_verifier_ = false;
272f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner}
273f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner
2741c56b730a6313886076d7b293a126ae5576f5288Chris Lattnerbool SyncTest::SetupClients() {
2754df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner  if (num_clients_ <= 0)
276f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner    LOG(FATAL) << "num_clients_ incorrectly initialized.";
277f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner  if (!profiles_.empty() || !browsers_.empty() || !clients_.empty())
278f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner    LOG(FATAL) << "SetupClients() has already been called.";
279f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner
280f12c2c28bd72091f2d7fff5718265c5ad52e7af8Chris Lattner  // Start up a sync test server if one is needed.
2814df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner  SetUpTestServerIfRequired();
2821c56b730a6313886076d7b293a126ae5576f5288Chris Lattner
283ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  // Create the required number of sync profiles, browsers and clients.
284ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  profiles_.resize(num_clients_);
285ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  browsers_.resize(num_clients_);
286ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  clients_.resize(num_clients_);
287ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  for (int i = 0; i < num_clients_; ++i) {
288ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner    InitializeInstance(i);
289ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  }
290ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner
291ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  // Create the verifier profile.
292ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  verifier_ = MakeProfile(FILE_PATH_LITERAL("Verifier"));
293ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  ui_test_utils::WaitForBookmarkModelToLoad(
294ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner      BookmarkModelFactory::GetForProfile(verifier()));
295ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
296ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner      verifier(), Profile::EXPLICIT_ACCESS));
297ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  ui_test_utils::WaitForTemplateURLServiceToLoad(
298ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner      TemplateURLServiceFactory::GetForProfile(verifier()));
299ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  return (verifier_ != NULL);
300ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner}
301ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner
302ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattnervoid SyncTest::InitializeInstance(int index) {
303ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  profiles_[index] = MakeProfile(
304ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner      base::StringPrintf(FILE_PATH_LITERAL("Profile%d"), index));
305ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  EXPECT_FALSE(GetProfile(index) == NULL) << "Could not create Profile "
306ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner                                          << index << ".";
307ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner
308ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  browsers_[index] = new Browser(Browser::CreateParams(
309ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner      GetProfile(index), chrome::HOST_DESKTOP_TYPE_NATIVE));
310ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner  EXPECT_FALSE(GetBrowser(index) == NULL) << "Could not create Browser "
311ab8c565768ff7485f40cbb65e2914f9046e743d4Chris Lattner                                          << index << ".";
3124df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner
3134df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner  // Make sure the ProfileSyncService has been created before creating the
314fc188b95b81332c12043173c7f517341c6ad27a9Brian Gaeke  // ProfileSyncServiceHarness - some tests expect the ProfileSyncService to
315fc188b95b81332c12043173c7f517341c6ad27a9Brian Gaeke  // already exist.
316fc188b95b81332c12043173c7f517341c6ad27a9Brian Gaeke  ProfileSyncServiceFactory::GetForProfile(GetProfile(index));
317fc188b95b81332c12043173c7f517341c6ad27a9Brian Gaeke
318fc188b95b81332c12043173c7f517341c6ad27a9Brian Gaeke  clients_[index] = new ProfileSyncServiceHarness(GetProfile(index),
319fc188b95b81332c12043173c7f517341c6ad27a9Brian Gaeke                                                  username_,
320fc188b95b81332c12043173c7f517341c6ad27a9Brian Gaeke                                                  password_);
321fc188b95b81332c12043173c7f517341c6ad27a9Brian Gaeke  EXPECT_FALSE(GetClient(index) == NULL) << "Could not create Client "
322d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke                                         << index << ".";
323d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
3244df22c0100fe27f19e6f4874f24eedd0742b9cf4Chris Lattner  ui_test_utils::WaitForBookmarkModelToLoad(
325      BookmarkModelFactory::GetForProfile(GetProfile(index)));
326  ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
327      GetProfile(index), Profile::EXPLICIT_ACCESS));
328  ui_test_utils::WaitForTemplateURLServiceToLoad(
329      TemplateURLServiceFactory::GetForProfile(GetProfile(index)));
330}
331
332void SyncTest::RestartSyncService(int index) {
333  DVLOG(1) << "Restarting profile sync service for profile " << index << ".";
334  delete clients_[index];
335  Profile* profile = GetProfile(index);
336  ProfileSyncService* service =
337      ProfileSyncServiceFactory::GetForProfile(profile);
338  service->ResetForTest();
339  clients_[index] = new ProfileSyncServiceHarness(profile,
340                                                  username_,
341                                                  password_);
342  service->Initialize();
343  GetClient(index)->AwaitSyncRestart();
344}
345
346bool SyncTest::SetupSync() {
347  // Create sync profiles and clients if they haven't already been created.
348  if (profiles_.empty()) {
349    if (!SetupClients())
350      LOG(FATAL) << "SetupClients() failed.";
351  }
352
353  // Sync each of the profiles.
354  for (int i = 0; i < num_clients_; ++i) {
355    if (!GetClient(i)->SetupSync())
356      LOG(FATAL) << "SetupSync() failed.";
357  }
358
359  // Because clients may modify sync data as part of startup (for example local
360  // session-releated data is rewritten), we need to ensure all startup-based
361  // changes have propagated between the clients.
362  AwaitQuiescence();
363
364  // The number of default entries is the number of entries existing after
365  // sync startup excluding top level folders and other permanent items.
366  // This value must be updated whenever new permanent items are added (although
367  // this should handle new datatype-specific top level folders).
368  number_of_default_sync_items_ = GetClient(0)->GetNumEntries() -
369                                  GetClient(0)->GetNumDatatypes() - 6;
370  DVLOG(1) << "Setting " << number_of_default_sync_items_ << " as default "
371           << " number of entries.";
372
373  return true;
374}
375
376void SyncTest::CleanUpOnMainThread() {
377  // Some of the pending messages might rely on browser windows still being
378  // around, so run messages both before and after closing all browsers.
379  content::RunAllPendingInMessageLoop();
380  // Close all browser windows.
381  chrome::CloseAllBrowsers();
382  content::RunAllPendingInMessageLoop();
383
384  // All browsers should be closed at this point, or else we could see memory
385  // corruption in QuitBrowser().
386  CHECK_EQ(0U, chrome::GetTotalBrowserCount());
387  clients_.clear();
388}
389
390void SyncTest::SetUpInProcessBrowserTestFixture() {
391  // We don't take a reference to |resolver|, but mock_host_resolver_override_
392  // does, so effectively assumes ownership.
393  net::RuleBasedHostResolverProc* resolver =
394      new net::RuleBasedHostResolverProc(host_resolver());
395  resolver->AllowDirectLookup("*.google.com");
396  // On Linux, we use Chromium's NSS implementation which uses the following
397  // hosts for certificate verification. Without these overrides, running the
398  // integration tests on Linux causes error as we make external DNS lookups.
399  resolver->AllowDirectLookup("*.thawte.com");
400  resolver->AllowDirectLookup("*.geotrust.com");
401  resolver->AllowDirectLookup("*.gstatic.com");
402  mock_host_resolver_override_.reset(
403      new net::ScopedDefaultHostResolverProc(resolver));
404}
405
406void SyncTest::TearDownInProcessBrowserTestFixture() {
407  mock_host_resolver_override_.reset();
408}
409
410void SyncTest::ReadPasswordFile() {
411  CommandLine* cl = CommandLine::ForCurrentProcess();
412  password_file_ = cl->GetSwitchValuePath(switches::kPasswordFileForTest);
413  if (password_file_.empty())
414    LOG(FATAL) << "Can't run live server test without specifying --"
415               << switches::kPasswordFileForTest << "=<filename>";
416  std::string file_contents;
417  file_util::ReadFileToString(password_file_, &file_contents);
418  ASSERT_NE(file_contents, "") << "Password file \""
419      << password_file_.value() << "\" does not exist.";
420  std::vector<std::string> tokens;
421  std::string delimiters = "\r\n";
422  Tokenize(file_contents, delimiters, &tokens);
423  ASSERT_EQ(2U, tokens.size()) << "Password file \""
424      << password_file_.value()
425      << "\" must contain exactly two lines of text.";
426  username_ = tokens[0];
427  password_ = tokens[1];
428}
429
430void SyncTest::SetupMockGaiaResponses() {
431  username_ = "user@gmail.com";
432  password_ = "password";
433  factory_.reset(new net::URLFetcherImplFactory());
434  fake_factory_.reset(new net::FakeURLFetcherFactory(factory_.get()));
435  fake_factory_->SetFakeResponse(
436      GaiaUrls::GetInstance()->client_login_url(),
437      "SID=sid\nLSID=lsid",
438      true);
439  fake_factory_->SetFakeResponse(
440      GaiaUrls::GetInstance()->get_user_info_url(),
441      "email=user@gmail.com\ndisplayEmail=user@gmail.com",
442      true);
443  fake_factory_->SetFakeResponse(
444      GaiaUrls::GetInstance()->issue_auth_token_url(),
445      "auth",
446      true);
447  fake_factory_->SetFakeResponse(
448      GoogleURLTracker::kSearchDomainCheckURL,
449      ".google.com",
450      true);
451  fake_factory_->SetFakeResponse(
452      GaiaUrls::GetInstance()->client_login_to_oauth2_url(),
453      "some_response",
454      true);
455  fake_factory_->SetFakeResponse(
456      GaiaUrls::GetInstance()->oauth2_token_url(),
457      "{"
458      "  \"refresh_token\": \"rt1\","
459      "  \"access_token\": \"at1\","
460      "  \"expires_in\": 3600,"
461      "  \"token_type\": \"Bearer\""
462      "}",
463      true);
464  fake_factory_->SetFakeResponse(
465      GaiaUrls::GetInstance()->oauth1_login_url(),
466      "SID=sid\nLSID=lsid\nAuth=auth_token",
467      true);
468}
469
470void SyncTest::ClearMockGaiaResponses() {
471  // Clear any mock gaia responses that might have been set.
472  if (fake_factory_) {
473    fake_factory_->ClearFakeResponses();
474    fake_factory_.reset();
475  }
476
477  // Cancel any outstanding URL fetches and destroy the URLFetcherImplFactory we
478  // created.
479  net::URLFetcher::CancelAll();
480  factory_.reset();
481}
482
483// Start up a local sync server based on the value of server_type_, which
484// was determined from the command line parameters.
485void SyncTest::SetUpTestServerIfRequired() {
486  if (server_type_ == LOCAL_PYTHON_SERVER) {
487    if (!SetUpLocalPythonTestServer())
488      LOG(FATAL) << "Failed to set up local python sync and XMPP servers";
489  } else if (server_type_ == LOCAL_LIVE_SERVER) {
490    // Using mock gaia credentials requires the use of a mock XMPP server.
491    if (username_ == "user@gmail.com" && !SetUpLocalPythonTestServer())
492      LOG(FATAL) << "Failed to set up local python XMPP server";
493    if (!SetUpLocalTestServer())
494      LOG(FATAL) << "Failed to set up local test server";
495  } else if (server_type_ == EXTERNAL_LIVE_SERVER) {
496    // Nothing to do; we'll just talk to the URL we were given.
497  } else {
498    LOG(FATAL) << "Don't know which server environment to run test in.";
499  }
500}
501
502bool SyncTest::SetUpLocalPythonTestServer() {
503  EXPECT_TRUE(sync_server_.Start())
504      << "Could not launch local python test server.";
505
506  CommandLine* cl = CommandLine::ForCurrentProcess();
507  if (server_type_ == LOCAL_PYTHON_SERVER) {
508    std::string sync_service_url = sync_server_.GetURL("chromiumsync").spec();
509    cl->AppendSwitchASCII(switches::kSyncServiceURL, sync_service_url);
510    DVLOG(1) << "Started local python sync server at " << sync_service_url;
511  }
512
513  int xmpp_port = 0;
514  if (!sync_server_.server_data().GetInteger("xmpp_port", &xmpp_port)) {
515    LOG(ERROR) << "Could not find valid xmpp_port value";
516    return false;
517  }
518  if ((xmpp_port <= 0) || (xmpp_port > kuint16max)) {
519    LOG(ERROR) << "Invalid xmpp port: " << xmpp_port;
520    return false;
521  }
522
523  net::HostPortPair xmpp_host_port_pair(sync_server_.host_port_pair());
524  xmpp_host_port_pair.set_port(xmpp_port);
525  xmpp_port_.reset(new net::ScopedPortException(xmpp_port));
526
527  if (!cl->HasSwitch(switches::kSyncNotificationHostPort)) {
528    cl->AppendSwitchASCII(switches::kSyncNotificationHostPort,
529                          xmpp_host_port_pair.ToString());
530    // The local XMPP server only supports insecure connections.
531    cl->AppendSwitch(switches::kSyncAllowInsecureXmppConnection);
532  }
533  DVLOG(1) << "Started local python XMPP server at "
534           << xmpp_host_port_pair.ToString();
535
536  return true;
537}
538
539bool SyncTest::SetUpLocalTestServer() {
540  CommandLine* cl = CommandLine::ForCurrentProcess();
541  CommandLine::StringType server_cmdline_string = cl->GetSwitchValueNative(
542      switches::kSyncServerCommandLine);
543  CommandLine::StringVector server_cmdline_vector;
544  CommandLine::StringType delimiters(FILE_PATH_LITERAL(" "));
545  Tokenize(server_cmdline_string, delimiters, &server_cmdline_vector);
546  CommandLine server_cmdline(server_cmdline_vector);
547  base::LaunchOptions options;
548#if defined(OS_WIN)
549  options.start_hidden = true;
550#endif
551  if (!base::LaunchProcess(server_cmdline, options, &test_server_handle_))
552    LOG(ERROR) << "Could not launch local test server.";
553
554  const base::TimeDelta kMaxWaitTime = TestTimeouts::action_max_timeout();
555  const int kNumIntervals = 15;
556  if (WaitForTestServerToStart(kMaxWaitTime, kNumIntervals)) {
557    DVLOG(1) << "Started local test server at "
558             << cl->GetSwitchValueASCII(switches::kSyncServiceURL) << ".";
559    return true;
560  } else {
561    LOG(ERROR) << "Could not start local test server at "
562               << cl->GetSwitchValueASCII(switches::kSyncServiceURL) << ".";
563    return false;
564  }
565}
566
567bool SyncTest::TearDownLocalPythonTestServer() {
568  if (!sync_server_.Stop()) {
569    LOG(ERROR) << "Could not stop local python test server.";
570    return false;
571  }
572  xmpp_port_.reset();
573  return true;
574}
575
576bool SyncTest::TearDownLocalTestServer() {
577  if (test_server_handle_ != base::kNullProcessHandle) {
578    EXPECT_TRUE(base::KillProcess(test_server_handle_, 0, false))
579        << "Could not stop local test server.";
580    base::CloseProcessHandle(test_server_handle_);
581    test_server_handle_ = base::kNullProcessHandle;
582  }
583  return true;
584}
585
586bool SyncTest::WaitForTestServerToStart(base::TimeDelta wait, int intervals) {
587  for (int i = 0; i < intervals; ++i) {
588    if (IsTestServerRunning())
589      return true;
590    base::PlatformThread::Sleep(wait / intervals);
591  }
592  return false;
593}
594
595bool SyncTest::IsTestServerRunning() {
596  CommandLine* cl = CommandLine::ForCurrentProcess();
597  std::string sync_url = cl->GetSwitchValueASCII(switches::kSyncServiceURL);
598  GURL sync_url_status(sync_url.append("/healthz"));
599  SyncServerStatusChecker delegate;
600  scoped_ptr<net::URLFetcher> fetcher(net::URLFetcher::Create(
601    sync_url_status, net::URLFetcher::GET, &delegate));
602  fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE |
603                        net::LOAD_DO_NOT_SEND_COOKIES |
604                        net::LOAD_DO_NOT_SAVE_COOKIES);
605  fetcher->SetRequestContext(g_browser_process->system_request_context());
606  fetcher->Start();
607  content::RunMessageLoop();
608  return delegate.running();
609}
610
611void SyncTest::EnableNetwork(Profile* profile) {
612  SetProxyConfig(profile->GetRequestContext(),
613                 net::ProxyConfig::CreateDirect());
614  if (notifications_enabled_) {
615    EnableNotificationsImpl();
616  }
617  // TODO(rsimha): Remove this line once http://crbug.com/53857 is fixed.
618  net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
619}
620
621void SyncTest::DisableNetwork(Profile* profile) {
622  DisableNotificationsImpl();
623  // Set the current proxy configuration to a nonexistent proxy to effectively
624  // disable networking.
625  net::ProxyConfig config;
626  config.proxy_rules().ParseFromString("http=127.0.0.1:0");
627  SetProxyConfig(profile->GetRequestContext(), config);
628  // TODO(rsimha): Remove this line once http://crbug.com/53857 is fixed.
629  net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
630}
631
632bool SyncTest::EnableEncryption(int index, syncer::ModelType type) {
633  return GetClient(index)->EnableEncryptionForType(type);
634}
635
636bool SyncTest::IsEncrypted(int index, syncer::ModelType type) {
637  return GetClient(index)->IsTypeEncrypted(type);
638}
639
640bool SyncTest::AwaitQuiescence() {
641  return ProfileSyncServiceHarness::AwaitQuiescence(clients());
642}
643
644bool SyncTest::ServerSupportsNotificationControl() const {
645  EXPECT_NE(SERVER_TYPE_UNDECIDED, server_type_);
646
647  // Supported only if we're using the python testserver.
648  return server_type_ == LOCAL_PYTHON_SERVER;
649}
650
651void SyncTest::DisableNotificationsImpl() {
652  ASSERT_TRUE(ServerSupportsNotificationControl());
653  std::string path = "chromiumsync/disablenotifications";
654  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
655  ASSERT_EQ("Notifications disabled",
656            UTF16ToASCII(browser()->tab_strip_model()->GetActiveWebContents()->
657                GetTitle()));
658}
659
660void SyncTest::DisableNotifications() {
661  DisableNotificationsImpl();
662  notifications_enabled_ = false;
663}
664
665void SyncTest::EnableNotificationsImpl() {
666  ASSERT_TRUE(ServerSupportsNotificationControl());
667  std::string path = "chromiumsync/enablenotifications";
668  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
669  ASSERT_EQ("Notifications enabled",
670            UTF16ToASCII(browser()->tab_strip_model()->GetActiveWebContents()->
671                GetTitle()));
672}
673
674void SyncTest::EnableNotifications() {
675  EnableNotificationsImpl();
676  notifications_enabled_ = true;
677}
678
679void SyncTest::TriggerNotification(syncer::ModelTypeSet changed_types) {
680  ASSERT_TRUE(ServerSupportsNotificationControl());
681  const std::string& data =
682      syncer::P2PNotificationData(
683          "from_server",
684          syncer::NOTIFY_ALL,
685          syncer::ObjectIdSetToInvalidationMap(
686              syncer::ModelTypeSetToObjectIdSet(changed_types), std::string())
687          ).ToString();
688  const std::string& path =
689      std::string("chromiumsync/sendnotification?channel=") +
690      syncer::kSyncP2PNotificationChannel + "&data=" + data;
691  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
692  ASSERT_EQ("Notification sent",
693            UTF16ToASCII(browser()->tab_strip_model()->GetActiveWebContents()->
694                GetTitle()));
695}
696
697bool SyncTest::ServerSupportsErrorTriggering() const {
698  EXPECT_NE(SERVER_TYPE_UNDECIDED, server_type_);
699
700  // Supported only if we're using the python testserver.
701  return server_type_ == LOCAL_PYTHON_SERVER;
702}
703
704void SyncTest::TriggerMigrationDoneError(syncer::ModelTypeSet model_types) {
705  ASSERT_TRUE(ServerSupportsErrorTriggering());
706  std::string path = "chromiumsync/migrate";
707  char joiner = '?';
708  for (syncer::ModelTypeSet::Iterator it = model_types.First();
709       it.Good(); it.Inc()) {
710    path.append(
711        base::StringPrintf(
712            "%ctype=%d", joiner,
713            syncer::GetSpecificsFieldNumberFromModelType(it.Get())));
714    joiner = '&';
715  }
716  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
717  ASSERT_EQ("Migration: 200",
718            UTF16ToASCII(browser()->tab_strip_model()->GetActiveWebContents()->
719                GetTitle()));
720}
721
722void SyncTest::TriggerBirthdayError() {
723  ASSERT_TRUE(ServerSupportsErrorTriggering());
724  std::string path = "chromiumsync/birthdayerror";
725  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
726  ASSERT_EQ("Birthday error",
727            UTF16ToASCII(browser()->tab_strip_model()->GetActiveWebContents()->
728                GetTitle()));
729}
730
731void SyncTest::TriggerTransientError() {
732  ASSERT_TRUE(ServerSupportsErrorTriggering());
733  std::string path = "chromiumsync/transienterror";
734  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
735  ASSERT_EQ("Transient error",
736            UTF16ToASCII(browser()->tab_strip_model()->GetActiveWebContents()->
737                GetTitle()));
738}
739
740void SyncTest::TriggerAuthError() {
741  ASSERT_TRUE(ServerSupportsErrorTriggering());
742  std::string path = "chromiumsync/cred";
743  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
744}
745
746void SyncTest::TriggerXmppAuthError() {
747  ASSERT_TRUE(ServerSupportsErrorTriggering());
748  std::string path = "chromiumsync/xmppcred";
749  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
750}
751
752namespace {
753
754sync_pb::SyncEnums::ErrorType
755    GetClientToServerResponseErrorType(
756        syncer::SyncProtocolErrorType error) {
757  switch (error) {
758    case syncer::SYNC_SUCCESS:
759      return sync_pb::SyncEnums::SUCCESS;
760    case syncer::NOT_MY_BIRTHDAY:
761      return sync_pb::SyncEnums::NOT_MY_BIRTHDAY;
762    case syncer::THROTTLED:
763      return sync_pb::SyncEnums::THROTTLED;
764    case syncer::CLEAR_PENDING:
765      return sync_pb::SyncEnums::CLEAR_PENDING;
766    case syncer::TRANSIENT_ERROR:
767      return sync_pb::SyncEnums::TRANSIENT_ERROR;
768    case syncer::MIGRATION_DONE:
769      return sync_pb::SyncEnums::MIGRATION_DONE;
770    case syncer::UNKNOWN_ERROR:
771      return sync_pb::SyncEnums::UNKNOWN;
772    default:
773      NOTREACHED();
774      return sync_pb::SyncEnums::UNKNOWN;
775  }
776}
777
778sync_pb::SyncEnums::Action GetClientToServerResponseAction(
779    const syncer::ClientAction& action) {
780  switch (action) {
781    case syncer::UPGRADE_CLIENT:
782      return sync_pb::SyncEnums::UPGRADE_CLIENT;
783    case syncer::CLEAR_USER_DATA_AND_RESYNC:
784      return sync_pb::SyncEnums::CLEAR_USER_DATA_AND_RESYNC;
785    case syncer::ENABLE_SYNC_ON_ACCOUNT:
786      return sync_pb::SyncEnums::ENABLE_SYNC_ON_ACCOUNT;
787    case syncer::STOP_AND_RESTART_SYNC:
788      return sync_pb::SyncEnums::STOP_AND_RESTART_SYNC;
789    case syncer::DISABLE_SYNC_ON_CLIENT:
790      return sync_pb::SyncEnums::DISABLE_SYNC_ON_CLIENT;
791    case syncer::UNKNOWN_ACTION:
792      return sync_pb::SyncEnums::UNKNOWN_ACTION;
793    default:
794      NOTREACHED();
795      return sync_pb::SyncEnums::UNKNOWN_ACTION;
796  }
797}
798
799}  // namespace
800
801void SyncTest::TriggerSyncError(const syncer::SyncProtocolError& error,
802                                SyncErrorFrequency frequency) {
803  ASSERT_TRUE(ServerSupportsErrorTriggering());
804  std::string path = "chromiumsync/error";
805  int error_type =
806      static_cast<int>(GetClientToServerResponseErrorType(
807          error.error_type));
808  int action = static_cast<int>(GetClientToServerResponseAction(
809      error.action));
810
811  path.append(base::StringPrintf("?error=%d", error_type));
812  path.append(base::StringPrintf("&action=%d", action));
813
814  path.append(base::StringPrintf("&error_description=%s",
815                                 error.error_description.c_str()));
816  path.append(base::StringPrintf("&url=%s", error.url.c_str()));
817  path.append(base::StringPrintf("&frequency=%d", frequency));
818
819  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
820  std::string output = UTF16ToASCII(
821      browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
822  ASSERT_TRUE(output.find("SetError: 200") != string16::npos);
823}
824
825void SyncTest::TriggerCreateSyncedBookmarks() {
826  ASSERT_TRUE(ServerSupportsErrorTriggering());
827  std::string path = "chromiumsync/createsyncedbookmarks";
828  ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
829  ASSERT_EQ("Synced Bookmarks",
830            UTF16ToASCII(browser()->tab_strip_model()->GetActiveWebContents()->
831                GetTitle()));
832}
833
834int SyncTest::NumberOfDefaultSyncItems() const {
835  return number_of_default_sync_items_;
836}
837
838void SyncTest::SetProxyConfig(net::URLRequestContextGetter* context_getter,
839                              const net::ProxyConfig& proxy_config) {
840  base::WaitableEvent done(false, false);
841  BrowserThread::PostTask(
842      BrowserThread::IO, FROM_HERE,
843      base::Bind(&SetProxyConfigCallback, &done,
844                 make_scoped_refptr(context_getter), proxy_config));
845  done.Wait();
846}
847