• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SyncServerStatusChecker()102   SyncServerStatusChecker() : running_(false) {}
103 
OnURLFetchComplete(const net::URLFetcher * source)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 
running() const113   bool running() const { return running_; }
114 
115  private:
116   bool running_;
117 };
118 
IsEncryptionComplete(const ProfileSyncService * service)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:
EncryptionChecker(ProfileSyncService * service)126   explicit EncryptionChecker(ProfileSyncService* service)
127       : SingleClientStatusChangeChecker(service) {}
128 
IsExitConditionSatisfied()129   virtual bool IsExitConditionSatisfied() OVERRIDE {
130     return IsEncryptionComplete(service());
131   }
132 
GetDebugMessage() const133   virtual std::string GetDebugMessage() const OVERRIDE {
134     return "Encryption";
135   }
136 };
137 
SetupNetworkCallback(base::WaitableEvent * done,net::URLRequestContextGetter * url_request_context_getter)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 
SetProxyConfigCallback(base::WaitableEvent * done,net::URLRequestContextGetter * url_request_context_getter,const net::ProxyConfig & proxy_config)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 
BuildFakeServerProfileInvalidationProvider(content::BrowserContext * context)157 KeyedService* BuildFakeServerProfileInvalidationProvider(
158     content::BrowserContext* context) {
159   return new invalidation::ProfileInvalidationProvider(
160       scoped_ptr<invalidation::InvalidationService>(
161           new fake_server::FakeServerInvalidationService));
162 }
163 
BuildP2PProfileInvalidationProvider(content::BrowserContext * context,syncer::P2PNotificationTarget notification_target)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 
BuildSelfNotifyingP2PProfileInvalidationProvider(content::BrowserContext * context)179 KeyedService* BuildSelfNotifyingP2PProfileInvalidationProvider(
180     content::BrowserContext* context) {
181   return BuildP2PProfileInvalidationProvider(context, syncer::NOTIFY_ALL);
182 }
183 
BuildRealisticP2PProfileInvalidationProvider(content::BrowserContext * context)184 KeyedService* BuildRealisticP2PProfileInvalidationProvider(
185     content::BrowserContext* context) {
186   return BuildP2PProfileInvalidationProvider(context, syncer::NOTIFY_OTHERS);
187 }
188 
189 }  // namespace
190 
SyncTest(TestType test_type)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 
~SyncTest()217 SyncTest::~SyncTest() {}
218 
SetUp()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@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 
TearDown()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 
SetUpCommandLine(base::CommandLine * cl)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 
AddTestSwitches(base::CommandLine * cl)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 
AddOptionalTypesToCommandLine(base::CommandLine * cl)286 void SyncTest::AddOptionalTypesToCommandLine(base::CommandLine* cl) {}
287 
288 // static
MakeProfile(const base::FilePath::StringType name)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 
GetProfile(int index)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 
GetBrowser(int index)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 
GetClient(int index)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 
GetSyncService(int index)329 ProfileSyncService* SyncTest::GetSyncService(int index) {
330   return ProfileSyncServiceFactory::GetForProfile(GetProfile(index));
331 }
332 
GetSyncServices()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 
verifier()341 Profile* SyncTest::verifier() {
342   if (verifier_ == NULL)
343     LOG(FATAL) << "SetupClients() has not yet been called.";
344   return verifier_;
345 }
346 
DisableVerifier()347 void SyncTest::DisableVerifier() {
348   use_verifier_ = false;
349 }
350 
SetupClients()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 
InitializeInstance(int index)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 
InitializeInvalidations(int index)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 
SetupSync()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 
TearDownOnMainThread()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 
SetUpInProcessBrowserTestFixture()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 
TearDownInProcessBrowserTestFixture()530 void SyncTest::TearDownInProcessBrowserTestFixture() {
531   mock_host_resolver_override_.reset();
532 }
533 
ReadPasswordFile()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 
SetupMockGaiaResponses()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@gmail.com\ndisplayEmail=user@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 
SetOAuth2TokenResponse(const std::string & response_data,net::HttpStatusCode response_code,net::URLRequestStatus::Status status)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 
ClearMockGaiaResponses()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 
DecideServerType()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.
SetUpTestServerIfRequired()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@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 
SetUpLocalPythonTestServer()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 
SetUpLocalTestServer()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 
TearDownLocalPythonTestServer()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 
TearDownLocalTestServer()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 
WaitForTestServerToStart(base::TimeDelta wait,int intervals)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 
IsTestServerRunning()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 
EnableNetwork(Profile * profile)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 
DisableNetwork(Profile * profile)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 
TestUsesSelfNotifications()831 bool SyncTest::TestUsesSelfNotifications() {
832   return true;
833 }
834 
EnableEncryption(int index)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 
IsEncryptionComplete(int index)853 bool SyncTest::IsEncryptionComplete(int index) {
854   return ::IsEncryptionComplete(GetClient(index)->service());
855 }
856 
AwaitEncryptionComplete(int index)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 
AwaitQuiescence()864 bool SyncTest::AwaitQuiescence() {
865   return ProfileSyncServiceHarness::AwaitQuiescence(clients());
866 }
867 
ServerSupportsNotificationControl() const868 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 
DisableNotificationsImpl()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 
DisableNotifications()885 void SyncTest::DisableNotifications() {
886   DisableNotificationsImpl();
887   notifications_enabled_ = false;
888 }
889 
EnableNotificationsImpl()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 
EnableNotifications()900 void SyncTest::EnableNotifications() {
901   EnableNotificationsImpl();
902   notifications_enabled_ = true;
903 }
904 
TriggerNotification(syncer::ModelTypeSet changed_types)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 
ServerSupportsErrorTriggering() const923 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 
TriggerMigrationDoneError(syncer::ModelTypeSet model_types)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 
TriggerTransientError()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 
TriggerXmppAuthError()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
GetClientToServerResponseErrorType(syncer::SyncProtocolErrorType error)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 
GetClientToServerResponseAction(const syncer::ClientAction & action)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 
TriggerSyncError(const syncer::SyncProtocolError & error,SyncErrorFrequency frequency)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 
TriggerCreateSyncedBookmarks()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 
SetupNetwork(net::URLRequestContextGetter * context_getter)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 
SetProxyConfig(net::URLRequestContextGetter * context_getter,const net::ProxyConfig & proxy_config)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 
GetFakeServer() const1079 fake_server::FakeServer* SyncTest::GetFakeServer() const {
1080   return fake_server_.get();
1081 }
1082