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