[Cleanup] Used scoped pointers in KeyedServiceFactory's SetTestingFactory functions.
[chromium-blink-merge.git] / chrome / browser / sync / test / integration / sync_test.cc
blob77729564aebf127dd46b39fb291d023bf8d7f579
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.
5 #include "chrome/browser/sync/test/integration/sync_test.h"
7 #include <vector>
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/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/path_service.h"
16 #include "base/process/launch.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/synchronization/waitable_event.h"
21 #include "base/test/test_timeouts.h"
22 #include "base/threading/platform_thread.h"
23 #include "base/values.h"
24 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
25 #include "chrome/browser/chrome_notification_types.h"
26 #include "chrome/browser/history/history_service_factory.h"
27 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
28 #include "chrome/browser/lifetime/application_lifetime.h"
29 #include "chrome/browser/profiles/profile_manager.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/glue/invalidation_helper.h"
35 #include "chrome/browser/sync/profile_sync_service.h"
36 #include "chrome/browser/sync/profile_sync_service_factory.h"
37 #include "chrome/browser/sync/test/integration/fake_server_invalidation_service.h"
38 #include "chrome/browser/sync/test/integration/p2p_invalidation_forwarder.h"
39 #include "chrome/browser/sync/test/integration/p2p_sync_refresher.h"
40 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
41 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
42 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
43 #include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
44 #include "chrome/browser/ui/browser.h"
45 #include "chrome/browser/ui/browser_finder.h"
46 #include "chrome/browser/ui/host_desktop.h"
47 #include "chrome/browser/ui/tabs/tab_strip_model.h"
48 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
49 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
50 #include "chrome/common/chrome_constants.h"
51 #include "chrome/common/chrome_paths.h"
52 #include "chrome/common/chrome_switches.h"
53 #include "chrome/test/base/testing_browser_process.h"
54 #include "chrome/test/base/ui_test_utils.h"
55 #include "components/bookmarks/test/bookmark_test_helpers.h"
56 #include "components/google/core/browser/google_url_tracker.h"
57 #include "components/invalidation/invalidation_service.h"
58 #include "components/invalidation/invalidation_switches.h"
59 #include "components/invalidation/p2p_invalidation_service.h"
60 #include "components/invalidation/p2p_invalidator.h"
61 #include "components/invalidation/profile_invalidation_provider.h"
62 #include "components/keyed_service/core/keyed_service.h"
63 #include "components/os_crypt/os_crypt.h"
64 #include "components/search_engines/template_url_service.h"
65 #include "components/signin/core/browser/signin_manager.h"
66 #include "content/public/browser/notification_service.h"
67 #include "content/public/browser/web_contents.h"
68 #include "content/public/test/test_browser_thread.h"
69 #include "google_apis/gaia/gaia_urls.h"
70 #include "net/base/escape.h"
71 #include "net/base/load_flags.h"
72 #include "net/base/network_change_notifier.h"
73 #include "net/cookies/cookie_monster.h"
74 #include "net/test/spawned_test_server/spawned_test_server.h"
75 #include "net/url_request/test_url_fetcher_factory.h"
76 #include "net/url_request/url_fetcher.h"
77 #include "net/url_request/url_fetcher_delegate.h"
78 #include "net/url_request/url_request_context.h"
79 #include "net/url_request/url_request_context_getter.h"
80 #include "sync/engine/sync_scheduler_impl.h"
81 #include "sync/protocol/sync.pb.h"
82 #include "sync/test/fake_server/fake_server.h"
83 #include "sync/test/fake_server/fake_server_network_resources.h"
84 #include "url/gurl.h"
86 #if defined(OS_CHROMEOS)
87 #include "chromeos/chromeos_switches.h"
88 #endif
90 using content::BrowserThread;
92 namespace switches {
93 const char kPasswordFileForTest[] = "password-file-for-test";
94 const char kSyncUserForTest[] = "sync-user-for-test";
95 const char kSyncPasswordForTest[] = "sync-password-for-test";
96 const char kSyncServerCommandLine[] = "sync-server-command-line";
99 namespace {
101 // Helper class that checks whether a sync test server is running or not.
102 class SyncServerStatusChecker : public net::URLFetcherDelegate {
103 public:
104 SyncServerStatusChecker() : running_(false) {}
106 void OnURLFetchComplete(const net::URLFetcher* source) override {
107 std::string data;
108 source->GetResponseAsString(&data);
109 running_ =
110 (source->GetStatus().status() == net::URLRequestStatus::SUCCESS &&
111 source->GetResponseCode() == 200 && data.find("ok") == 0);
112 base::MessageLoop::current()->Quit();
115 bool running() const { return running_; }
117 private:
118 bool running_;
121 bool IsEncryptionComplete(const ProfileSyncService* service) {
122 return service->EncryptEverythingEnabled() && !service->encryption_pending();
125 // Helper class to wait for encryption to complete.
126 class EncryptionChecker : public SingleClientStatusChangeChecker {
127 public:
128 explicit EncryptionChecker(ProfileSyncService* service)
129 : SingleClientStatusChangeChecker(service) {}
131 bool IsExitConditionSatisfied() override {
132 return IsEncryptionComplete(service());
135 std::string GetDebugMessage() const override { return "Encryption"; }
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();
146 scoped_ptr<KeyedService> BuildFakeServerProfileInvalidationProvider(
147 content::BrowserContext* context) {
148 return make_scoped_ptr(new invalidation::ProfileInvalidationProvider(
149 scoped_ptr<invalidation::InvalidationService>(
150 new fake_server::FakeServerInvalidationService)));
153 scoped_ptr<KeyedService> BuildP2PProfileInvalidationProvider(
154 content::BrowserContext* context,
155 syncer::P2PNotificationTarget notification_target) {
156 Profile* profile = static_cast<Profile*>(context);
157 return make_scoped_ptr(new invalidation::ProfileInvalidationProvider(
158 scoped_ptr<invalidation::InvalidationService>(
159 new invalidation::P2PInvalidationService(
160 scoped_ptr<IdentityProvider>(new ProfileIdentityProvider(
161 SigninManagerFactory::GetForProfile(profile),
162 ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
163 LoginUIServiceFactory::GetForProfile(profile))),
164 profile->GetRequestContext(), notification_target))));
167 scoped_ptr<KeyedService> BuildSelfNotifyingP2PProfileInvalidationProvider(
168 content::BrowserContext* context) {
169 return BuildP2PProfileInvalidationProvider(context, syncer::NOTIFY_ALL);
172 scoped_ptr<KeyedService> BuildRealisticP2PProfileInvalidationProvider(
173 content::BrowserContext* context) {
174 return BuildP2PProfileInvalidationProvider(context, syncer::NOTIFY_OTHERS);
177 } // namespace
179 SyncTest::SyncTest(TestType test_type)
180 : test_type_(test_type),
181 server_type_(SERVER_TYPE_UNDECIDED),
182 num_clients_(-1),
183 use_verifier_(true),
184 notifications_enabled_(true) {
185 sync_datatype_helper::AssociateWithTest(this);
186 switch (test_type_) {
187 case SINGLE_CLIENT:
188 case SINGLE_CLIENT_LEGACY: {
189 num_clients_ = 1;
190 break;
192 case TWO_CLIENT:
193 case TWO_CLIENT_LEGACY: {
194 num_clients_ = 2;
195 break;
197 case MULTIPLE_CLIENT: {
198 num_clients_ = 3;
199 break;
204 SyncTest::~SyncTest() {}
206 void SyncTest::SetUp() {
207 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
208 if (cl->HasSwitch(switches::kPasswordFileForTest)) {
209 ReadPasswordFile();
210 } else if (cl->HasSwitch(switches::kSyncUserForTest) &&
211 cl->HasSwitch(switches::kSyncPasswordForTest)) {
212 username_ = cl->GetSwitchValueASCII(switches::kSyncUserForTest);
213 password_ = cl->GetSwitchValueASCII(switches::kSyncPasswordForTest);
214 } else {
215 username_ = "user@gmail.com";
216 password_ = "password";
219 if (username_.empty() || password_.empty())
220 LOG(FATAL) << "Cannot run sync tests without GAIA credentials.";
222 // Sets |server_type_| if it wasn't specified by the test.
223 DecideServerType();
225 // Mock the Mac Keychain service. The real Keychain can block on user input.
226 #if defined(OS_MACOSX)
227 OSCrypt::UseMockKeychain(true);
228 #endif
230 // Start up a sync test server if one is needed and setup mock gaia responses.
231 // Note: This must be done prior to the call to SetupClients() because we want
232 // the mock gaia responses to be available before GaiaUrls is initialized.
233 SetUpTestServerIfRequired();
235 // Yield control back to the InProcessBrowserTest framework.
236 InProcessBrowserTest::SetUp();
239 void SyncTest::TearDown() {
240 // Clear any mock gaia responses that might have been set.
241 ClearMockGaiaResponses();
243 // Allow the InProcessBrowserTest framework to perform its tear down.
244 InProcessBrowserTest::TearDown();
246 // Stop the local python test server. This is a no-op if one wasn't started.
247 TearDownLocalPythonTestServer();
249 // Stop the local sync test server. This is a no-op if one wasn't started.
250 TearDownLocalTestServer();
252 fake_server_.reset();
255 void SyncTest::SetUpCommandLine(base::CommandLine* cl) {
256 AddTestSwitches(cl);
257 AddOptionalTypesToCommandLine(cl);
259 #if defined(OS_CHROMEOS)
260 cl->AppendSwitch(chromeos::switches::kIgnoreUserProfileMappingForTests);
261 #endif
264 void SyncTest::AddTestSwitches(base::CommandLine* cl) {
265 // Disable non-essential access of external network resources.
266 if (!cl->HasSwitch(switches::kDisableBackgroundNetworking))
267 cl->AppendSwitch(switches::kDisableBackgroundNetworking);
269 if (!cl->HasSwitch(switches::kSyncShortInitialRetryOverride))
270 cl->AppendSwitch(switches::kSyncShortInitialRetryOverride);
273 void SyncTest::AddOptionalTypesToCommandLine(base::CommandLine* cl) {}
275 // Called when the ProfileManager has created a profile.
276 // static
277 void SyncTest::CreateProfileCallback(const base::Closure& quit_closure,
278 Profile* profile,
279 Profile::CreateStatus status) {
280 EXPECT_TRUE(profile);
281 EXPECT_NE(Profile::CREATE_STATUS_LOCAL_FAIL, status);
282 EXPECT_NE(Profile::CREATE_STATUS_REMOTE_FAIL, status);
283 // This will be called multiple times. Wait until the profile is initialized
284 // fully to quit the loop.
285 if (status == Profile::CREATE_STATUS_INITIALIZED)
286 quit_closure.Run();
289 // TODO(shadi): Ideally creating a new profile should not depend on signin
290 // process. We should try to consolidate MakeProfileForUISignin() and
291 // MakeProfile(). Major differences are profile paths and creation methods. For
292 // UI signin we need profiles in unique user data dir's and we need to use
293 // ProfileManager::CreateProfileAsync() for proper profile creation.
294 // static
295 Profile* SyncTest::MakeProfileForUISignin(
296 const base::FilePath::StringType name) {
297 // For multi profile UI signin, profile paths should be outside user data dir.
298 // Otherwise, we get an error that the profile has already signed in on this
299 // device.
300 // Note that prefix |name| is implemented only on Win. On other platforms the
301 // com.google.Chrome.XXXXXX prefix is used.
302 base::FilePath profile_path;
303 CHECK(base::CreateNewTempDirectory(name, &profile_path));
305 ProfileManager* profile_manager = g_browser_process->profile_manager();
306 base::RunLoop run_loop;
307 ProfileManager::CreateCallback create_callback = base::Bind(
308 &CreateProfileCallback, run_loop.QuitClosure());
309 profile_manager->CreateProfileAsync(profile_path,
310 create_callback,
311 base::string16(),
312 base::string16(),
313 std::string());
314 run_loop.Run();
315 return profile_manager->GetProfileByPath(profile_path);
318 Profile* SyncTest::MakeProfile(const base::FilePath::StringType name) {
319 base::FilePath path;
320 // Create new profiles in user data dir so that other profiles can know about
321 // it. This is needed in tests such as supervised user cases which assume
322 // browser->profile() as the custodian profile.
323 PathService::Get(chrome::DIR_USER_DATA, &path);
324 path = path.Append(name);
326 if (!base::PathExists(path))
327 CHECK(base::CreateDirectory(path));
329 if (!preexisting_preferences_file_contents_.empty()) {
330 base::FilePath pref_path(path.Append(chrome::kPreferencesFilename));
331 const char* contents = preexisting_preferences_file_contents_.c_str();
332 size_t contents_length = preexisting_preferences_file_contents_.size();
333 if (!base::WriteFile(pref_path, contents, contents_length)) {
334 LOG(FATAL) << "Preexisting Preferences file could not be written.";
338 Profile* profile =
339 Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
340 g_browser_process->profile_manager()->RegisterTestingProfile(profile,
341 true,
342 true);
343 return profile;
346 Profile* SyncTest::GetProfile(int index) {
347 if (profiles_.empty())
348 LOG(FATAL) << "SetupClients() has not yet been called.";
349 if (index < 0 || index >= static_cast<int>(profiles_.size()))
350 LOG(FATAL) << "GetProfile(): Index is out of bounds.";
351 return profiles_[index];
354 Browser* SyncTest::GetBrowser(int index) {
355 if (browsers_.empty())
356 LOG(FATAL) << "SetupClients() has not yet been called.";
357 if (index < 0 || index >= static_cast<int>(browsers_.size()))
358 LOG(FATAL) << "GetBrowser(): Index is out of bounds.";
359 return browsers_[index];
362 ProfileSyncServiceHarness* SyncTest::GetClient(int index) {
363 if (clients_.empty())
364 LOG(FATAL) << "SetupClients() has not yet been called.";
365 if (index < 0 || index >= static_cast<int>(clients_.size()))
366 LOG(FATAL) << "GetClient(): Index is out of bounds.";
367 return clients_[index];
370 ProfileSyncService* SyncTest::GetSyncService(int index) {
371 return ProfileSyncServiceFactory::GetForProfile(GetProfile(index));
374 std::vector<ProfileSyncService*> SyncTest::GetSyncServices() {
375 std::vector<ProfileSyncService*> services;
376 for (int i = 0; i < num_clients(); ++i) {
377 services.push_back(GetSyncService(i));
379 return services;
382 Profile* SyncTest::verifier() {
383 if (!use_verifier_)
384 LOG(FATAL) << "Verifier account is disabled.";
385 if (verifier_ == NULL)
386 LOG(FATAL) << "SetupClients() has not yet been called.";
387 return verifier_;
390 void SyncTest::DisableVerifier() {
391 use_verifier_ = false;
394 bool SyncTest::SetupClients() {
395 if (num_clients_ <= 0)
396 LOG(FATAL) << "num_clients_ incorrectly initialized.";
397 if (!profiles_.empty() || !browsers_.empty() || !clients_.empty())
398 LOG(FATAL) << "SetupClients() has already been called.";
400 // Create the required number of sync profiles, browsers and clients.
401 profiles_.resize(num_clients_);
402 browsers_.resize(num_clients_);
403 clients_.resize(num_clients_);
404 invalidation_forwarders_.resize(num_clients_);
405 sync_refreshers_.resize(num_clients_);
406 fake_server_invalidation_services_.resize(num_clients_);
407 for (int i = 0; i < num_clients_; ++i) {
408 InitializeInstance(i);
411 // Verifier account is not useful when running against external servers.
412 if (UsingExternalServers())
413 DisableVerifier();
415 // Create the verifier profile.
416 if (use_verifier_) {
417 verifier_ = MakeProfile(FILE_PATH_LITERAL("Verifier"));
418 bookmarks::test::WaitForBookmarkModelToLoad(
419 BookmarkModelFactory::GetForProfile(verifier()));
420 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
421 verifier(), ServiceAccessType::EXPLICIT_ACCESS));
422 ui_test_utils::WaitForTemplateURLServiceToLoad(
423 TemplateURLServiceFactory::GetForProfile(verifier()));
425 // Error cases are all handled by LOG(FATAL) messages. So there is not really
426 // a case that returns false. In case we failed to create a verifier profile,
427 // any call to the verifier() would fail.
428 return true;
431 void SyncTest::InitializeInstance(int index) {
432 base::FilePath::StringType profile_name =
433 base::StringPrintf(FILE_PATH_LITERAL("Profile%d"), index);
434 // If running against an EXTERNAL_LIVE_SERVER, we need to signin profiles
435 // using real GAIA server. This requires creating profiles with no test hooks.
436 if (UsingExternalServers()) {
437 profiles_[index] = MakeProfileForUISignin(profile_name);
438 } else {
439 // Without need of real GAIA authentication, we create new test profiles.
440 profiles_[index] = MakeProfile(profile_name);
443 EXPECT_FALSE(GetProfile(index) == NULL) << "Could not create Profile "
444 << index << ".";
446 // CheckInitialState() assumes that no windows are open at startup.
447 browsers_[index] = new Browser(Browser::CreateParams(
448 GetProfile(index), chrome::GetActiveDesktop()));
450 EXPECT_FALSE(GetBrowser(index) == NULL) << "Could not create Browser "
451 << index << ".";
453 // Make sure the ProfileSyncService has been created before creating the
454 // ProfileSyncServiceHarness - some tests expect the ProfileSyncService to
455 // already exist.
456 ProfileSyncService* profile_sync_service =
457 ProfileSyncServiceFactory::GetForProfile(GetProfile(index));
459 SetupNetwork(GetProfile(index)->GetRequestContext());
461 if (server_type_ == IN_PROCESS_FAKE_SERVER) {
462 // TODO(pvalenzuela): Run the fake server via EmbeddedTestServer.
463 profile_sync_service->OverrideNetworkResourcesForTest(
464 make_scoped_ptr<syncer::NetworkResources>(
465 new fake_server::FakeServerNetworkResources(fake_server_.get())));
468 ProfileSyncServiceHarness::SigninType singin_type = UsingExternalServers()
469 ? ProfileSyncServiceHarness::SigninType::UI_SIGNIN
470 : ProfileSyncServiceHarness::SigninType::FAKE_SIGNIN;
472 clients_[index] =
473 ProfileSyncServiceHarness::Create(GetProfile(index),
474 username_,
475 password_,
476 singin_type);
477 EXPECT_FALSE(GetClient(index) == NULL) << "Could not create Client "
478 << index << ".";
479 InitializeInvalidations(index);
481 bookmarks::test::WaitForBookmarkModelToLoad(
482 BookmarkModelFactory::GetForProfile(GetProfile(index)));
483 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
484 GetProfile(index), ServiceAccessType::EXPLICIT_ACCESS));
485 ui_test_utils::WaitForTemplateURLServiceToLoad(
486 TemplateURLServiceFactory::GetForProfile(GetProfile(index)));
489 void SyncTest::InitializeInvalidations(int index) {
490 if (UsingExternalServers()) {
491 // DO NOTHING. External live sync servers use GCM to notify profiles of any
492 // invalidations in sync'ed data. In this case, to notify other profiles of
493 // invalidations, we use sync refresh notifications instead.
494 } else if (server_type_ == IN_PROCESS_FAKE_SERVER) {
495 CHECK(fake_server_.get());
496 fake_server::FakeServerInvalidationService* invalidation_service =
497 static_cast<fake_server::FakeServerInvalidationService*>(
498 static_cast<invalidation::ProfileInvalidationProvider*>(
499 invalidation::ProfileInvalidationProviderFactory::
500 GetInstance()->SetTestingFactoryAndUse(
501 GetProfile(index),
502 BuildFakeServerProfileInvalidationProvider))->
503 GetInvalidationService());
504 fake_server_->AddObserver(invalidation_service);
505 if (TestUsesSelfNotifications()) {
506 invalidation_service->EnableSelfNotifications();
507 } else {
508 invalidation_service->DisableSelfNotifications();
510 fake_server_invalidation_services_[index] = invalidation_service;
511 } else {
512 invalidation::P2PInvalidationService* p2p_invalidation_service =
513 static_cast<invalidation::P2PInvalidationService*>(
514 static_cast<invalidation::ProfileInvalidationProvider*>(
515 invalidation::ProfileInvalidationProviderFactory::
516 GetInstance()->SetTestingFactoryAndUse(
517 GetProfile(index),
518 TestUsesSelfNotifications() ?
519 BuildSelfNotifyingP2PProfileInvalidationProvider :
520 BuildRealisticP2PProfileInvalidationProvider))->
521 GetInvalidationService());
522 p2p_invalidation_service->UpdateCredentials(username_, password_);
523 // Start listening for and emitting notifications of commits.
524 invalidation_forwarders_[index] =
525 new P2PInvalidationForwarder(clients_[index]->service(),
526 p2p_invalidation_service);
530 bool SyncTest::SetupSync() {
531 // Create sync profiles and clients if they haven't already been created.
532 if (profiles_.empty()) {
533 if (!SetupClients())
534 LOG(FATAL) << "SetupClients() failed.";
537 // Sync each of the profiles.
538 for (int i = 0; i < num_clients_; ++i) {
539 if (!GetClient(i)->SetupSync())
540 LOG(FATAL) << "SetupSync() failed.";
543 // Because clients may modify sync data as part of startup (for example local
544 // session-releated data is rewritten), we need to ensure all startup-based
545 // changes have propagated between the clients.
547 // Tests that don't use self-notifications can't await quiescense. They'll
548 // have to find their own way of waiting for an initial state if they really
549 // need such guarantees.
550 if (TestUsesSelfNotifications()) {
551 AwaitQuiescence();
554 // SyncRefresher is used instead of invalidations to notify other profiles to
555 // do a sync refresh on committed data sets. This is only needed when running
556 // tests against external live server, otherwise invalidation service is used.
557 // With external live servers, the profiles commit data on first sync cycle
558 // automatically after signing in. To avoid misleading sync commit
559 // notifications at start up, we start the SyncRefresher observers post
560 // client set up.
561 if (UsingExternalServers()) {
562 for (int i = 0; i < num_clients_; ++i) {
563 sync_refreshers_[i] = new P2PSyncRefresher(clients_[i]->service());
566 // OneClickSigninSyncStarter observer is created with a real user sign in.
567 // It is deleted on certain conditions which are not satisfied by our tests,
568 // and this causes the SigninTracker observer to stay hanging at shutdown.
569 // Calling LoginUIService::SyncConfirmationUIClosed forces the observer to
570 // be removed. http://crbug.com/484388
571 for (int i = 0; i < num_clients_; ++i) {
572 LoginUIServiceFactory::GetForProfile(GetProfile(i))->
573 SyncConfirmationUIClosed(false /* configure_sync_first */);
577 return true;
580 void SyncTest::TearDownOnMainThread() {
581 for (size_t i = 0; i < clients_.size(); ++i) {
582 clients_[i]->service()->DisableForUser();
585 // Some of the pending messages might rely on browser windows still being
586 // around, so run messages both before and after closing all browsers.
587 content::RunAllPendingInMessageLoop();
588 // Close all browser windows.
589 chrome::CloseAllBrowsers();
590 content::RunAllPendingInMessageLoop();
592 if (fake_server_.get()) {
593 std::vector<fake_server::FakeServerInvalidationService*>::const_iterator it;
594 for (it = fake_server_invalidation_services_.begin();
595 it != fake_server_invalidation_services_.end(); ++it) {
596 fake_server_->RemoveObserver(*it);
600 // All browsers should be closed at this point, or else we could see memory
601 // corruption in QuitBrowser().
602 CHECK_EQ(0U, chrome::GetTotalBrowserCount());
603 invalidation_forwarders_.clear();
604 sync_refreshers_.clear();
605 fake_server_invalidation_services_.clear();
606 clients_.clear();
609 void SyncTest::SetUpInProcessBrowserTestFixture() {
610 // We don't take a reference to |resolver|, but mock_host_resolver_override_
611 // does, so effectively assumes ownership.
612 net::RuleBasedHostResolverProc* resolver =
613 new net::RuleBasedHostResolverProc(host_resolver());
614 resolver->AllowDirectLookup("*.google.com");
615 // On Linux, we use Chromium's NSS implementation which uses the following
616 // hosts for certificate verification. Without these overrides, running the
617 // integration tests on Linux causes error as we make external DNS lookups.
618 resolver->AllowDirectLookup("*.thawte.com");
619 resolver->AllowDirectLookup("*.geotrust.com");
620 resolver->AllowDirectLookup("*.gstatic.com");
621 mock_host_resolver_override_.reset(
622 new net::ScopedDefaultHostResolverProc(resolver));
625 void SyncTest::TearDownInProcessBrowserTestFixture() {
626 mock_host_resolver_override_.reset();
629 void SyncTest::ReadPasswordFile() {
630 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
631 password_file_ = cl->GetSwitchValuePath(switches::kPasswordFileForTest);
632 if (password_file_.empty())
633 LOG(FATAL) << "Can't run live server test without specifying --"
634 << switches::kPasswordFileForTest << "=<filename>";
635 std::string file_contents;
636 base::ReadFileToString(password_file_, &file_contents);
637 ASSERT_NE(file_contents, "") << "Password file \""
638 << password_file_.value() << "\" does not exist.";
639 std::vector<std::string> tokens;
640 std::string delimiters = "\r\n";
641 Tokenize(file_contents, delimiters, &tokens);
642 ASSERT_EQ(2U, tokens.size()) << "Password file \""
643 << password_file_.value()
644 << "\" must contain exactly two lines of text.";
645 username_ = tokens[0];
646 password_ = tokens[1];
649 void SyncTest::SetupMockGaiaResponses() {
650 factory_.reset(new net::URLFetcherImplFactory());
651 fake_factory_.reset(new net::FakeURLFetcherFactory(factory_.get()));
652 fake_factory_->SetFakeResponse(
653 GaiaUrls::GetInstance()->get_user_info_url(),
654 "email=user@gmail.com\ndisplayEmail=user@gmail.com",
655 net::HTTP_OK,
656 net::URLRequestStatus::SUCCESS);
657 fake_factory_->SetFakeResponse(
658 GaiaUrls::GetInstance()->issue_auth_token_url(),
659 "auth",
660 net::HTTP_OK,
661 net::URLRequestStatus::SUCCESS);
662 fake_factory_->SetFakeResponse(
663 GURL(GoogleURLTracker::kSearchDomainCheckURL),
664 ".google.com",
665 net::HTTP_OK,
666 net::URLRequestStatus::SUCCESS);
667 fake_factory_->SetFakeResponse(
668 GaiaUrls::GetInstance()->client_login_to_oauth2_url(),
669 "some_response",
670 net::HTTP_OK,
671 net::URLRequestStatus::SUCCESS);
672 fake_factory_->SetFakeResponse(
673 GaiaUrls::GetInstance()->oauth2_token_url(),
675 " \"refresh_token\": \"rt1\","
676 " \"access_token\": \"at1\","
677 " \"expires_in\": 3600,"
678 " \"token_type\": \"Bearer\""
679 "}",
680 net::HTTP_OK,
681 net::URLRequestStatus::SUCCESS);
682 fake_factory_->SetFakeResponse(
683 GaiaUrls::GetInstance()->oauth_user_info_url(),
685 " \"id\": \"12345\""
686 "}",
687 net::HTTP_OK,
688 net::URLRequestStatus::SUCCESS);
689 fake_factory_->SetFakeResponse(
690 GaiaUrls::GetInstance()->oauth1_login_url(),
691 "SID=sid\nLSID=lsid\nAuth=auth_token",
692 net::HTTP_OK,
693 net::URLRequestStatus::SUCCESS);
694 fake_factory_->SetFakeResponse(
695 GaiaUrls::GetInstance()->oauth2_revoke_url(),
697 net::HTTP_OK,
698 net::URLRequestStatus::SUCCESS);
701 void SyncTest::SetOAuth2TokenResponse(const std::string& response_data,
702 net::HttpStatusCode response_code,
703 net::URLRequestStatus::Status status) {
704 ASSERT_TRUE(NULL != fake_factory_.get());
705 fake_factory_->SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
706 response_data, response_code, status);
709 void SyncTest::ClearMockGaiaResponses() {
710 // Clear any mock gaia responses that might have been set.
711 if (fake_factory_) {
712 fake_factory_->ClearFakeResponses();
713 fake_factory_.reset();
716 // Cancel any outstanding URL fetches and destroy the URLFetcherImplFactory we
717 // created.
718 net::URLFetcher::CancelAll();
719 factory_.reset();
722 void SyncTest::DecideServerType() {
723 // Only set |server_type_| if it hasn't already been set. This allows for
724 // tests to explicitly set this value in each test class if needed.
725 if (server_type_ == SERVER_TYPE_UNDECIDED) {
726 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
727 if (!cl->HasSwitch(switches::kSyncServiceURL) &&
728 !cl->HasSwitch(switches::kSyncServerCommandLine)) {
729 // If neither a sync server URL nor a sync server command line is
730 // provided, start up a local sync test server and point Chrome
731 // to its URL. This is the most common configuration, and the only
732 // one that makes sense for most developers. FakeServer is the
733 // current solution but some scenarios are only supported by the
734 // legacy python server.
735 switch (test_type_) {
736 case SINGLE_CLIENT:
737 case TWO_CLIENT:
738 case MULTIPLE_CLIENT:
739 server_type_ = IN_PROCESS_FAKE_SERVER;
740 break;
741 default:
742 server_type_ = LOCAL_PYTHON_SERVER;
744 } else if (cl->HasSwitch(switches::kSyncServiceURL) &&
745 cl->HasSwitch(switches::kSyncServerCommandLine)) {
746 // If a sync server URL and a sync server command line are provided,
747 // start up a local sync server by running the command line. Chrome
748 // will connect to the server at the URL that was provided.
749 server_type_ = LOCAL_LIVE_SERVER;
750 } else if (cl->HasSwitch(switches::kSyncServiceURL) &&
751 !cl->HasSwitch(switches::kSyncServerCommandLine)) {
752 // If a sync server URL is provided, but not a server command line,
753 // it is assumed that the server is already running. Chrome will
754 // automatically connect to it at the URL provided. There is nothing
755 // to do here.
756 server_type_ = EXTERNAL_LIVE_SERVER;
757 } else {
758 // If a sync server command line is provided, but not a server URL,
759 // we flag an error.
760 LOG(FATAL) << "Can't figure out how to run a server.";
765 // Start up a local sync server based on the value of server_type_, which
766 // was determined from the command line parameters.
767 void SyncTest::SetUpTestServerIfRequired() {
768 if (UsingExternalServers()) {
769 // Nothing to do; we'll just talk to the URL we were given.
770 } else if (server_type_ == LOCAL_PYTHON_SERVER) {
771 if (!SetUpLocalPythonTestServer())
772 LOG(FATAL) << "Failed to set up local python sync and XMPP servers";
773 SetupMockGaiaResponses();
774 } else if (server_type_ == LOCAL_LIVE_SERVER) {
775 // Using mock gaia credentials requires the use of a mock XMPP server.
776 if (username_ == "user@gmail.com" && !SetUpLocalPythonTestServer())
777 LOG(FATAL) << "Failed to set up local python XMPP server";
778 if (!SetUpLocalTestServer())
779 LOG(FATAL) << "Failed to set up local test server";
780 } else if (server_type_ == IN_PROCESS_FAKE_SERVER) {
781 fake_server_.reset(new fake_server::FakeServer());
782 SetupMockGaiaResponses();
783 } else {
784 LOG(FATAL) << "Don't know which server environment to run test in.";
788 bool SyncTest::SetUpLocalPythonTestServer() {
789 EXPECT_TRUE(sync_server_.Start())
790 << "Could not launch local python test server.";
792 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
793 if (server_type_ == LOCAL_PYTHON_SERVER) {
794 std::string sync_service_url = sync_server_.GetURL("chromiumsync").spec();
795 cl->AppendSwitchASCII(switches::kSyncServiceURL, sync_service_url);
796 DVLOG(1) << "Started local python sync server at " << sync_service_url;
799 int xmpp_port = 0;
800 if (!sync_server_.server_data().GetInteger("xmpp_port", &xmpp_port)) {
801 LOG(ERROR) << "Could not find valid xmpp_port value";
802 return false;
804 if ((xmpp_port <= 0) || (xmpp_port > kuint16max)) {
805 LOG(ERROR) << "Invalid xmpp port: " << xmpp_port;
806 return false;
809 net::HostPortPair xmpp_host_port_pair(sync_server_.host_port_pair());
810 xmpp_host_port_pair.set_port(xmpp_port);
811 xmpp_port_.reset(new net::ScopedPortException(xmpp_port));
813 if (!cl->HasSwitch(invalidation::switches::kSyncNotificationHostPort)) {
814 cl->AppendSwitchASCII(invalidation::switches::kSyncNotificationHostPort,
815 xmpp_host_port_pair.ToString());
816 // The local XMPP server only supports insecure connections.
817 cl->AppendSwitch(invalidation::switches::kSyncAllowInsecureXmppConnection);
819 DVLOG(1) << "Started local python XMPP server at "
820 << xmpp_host_port_pair.ToString();
822 return true;
825 bool SyncTest::SetUpLocalTestServer() {
826 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
827 base::CommandLine::StringType server_cmdline_string =
828 cl->GetSwitchValueNative(switches::kSyncServerCommandLine);
829 base::CommandLine::StringVector server_cmdline_vector;
830 base::CommandLine::StringType delimiters(FILE_PATH_LITERAL(" "));
831 Tokenize(server_cmdline_string, delimiters, &server_cmdline_vector);
832 base::CommandLine server_cmdline(server_cmdline_vector);
833 base::LaunchOptions options;
834 #if defined(OS_WIN)
835 options.start_hidden = true;
836 #endif
837 test_server_ = base::LaunchProcess(server_cmdline, options);
838 if (!test_server_.IsValid())
839 LOG(ERROR) << "Could not launch local test server.";
841 const base::TimeDelta kMaxWaitTime = TestTimeouts::action_max_timeout();
842 const int kNumIntervals = 15;
843 if (WaitForTestServerToStart(kMaxWaitTime, kNumIntervals)) {
844 DVLOG(1) << "Started local test server at "
845 << cl->GetSwitchValueASCII(switches::kSyncServiceURL) << ".";
846 return true;
847 } else {
848 LOG(ERROR) << "Could not start local test server at "
849 << cl->GetSwitchValueASCII(switches::kSyncServiceURL) << ".";
850 return false;
854 bool SyncTest::TearDownLocalPythonTestServer() {
855 if (!sync_server_.Stop()) {
856 LOG(ERROR) << "Could not stop local python test server.";
857 return false;
859 xmpp_port_.reset();
860 return true;
863 bool SyncTest::TearDownLocalTestServer() {
864 if (test_server_.IsValid()) {
865 EXPECT_TRUE(test_server_.Terminate(0, false))
866 << "Could not stop local test server.";
867 test_server_.Close();
869 return true;
872 bool SyncTest::WaitForTestServerToStart(base::TimeDelta wait, int intervals) {
873 for (int i = 0; i < intervals; ++i) {
874 if (IsTestServerRunning())
875 return true;
876 base::PlatformThread::Sleep(wait / intervals);
878 return false;
881 bool SyncTest::IsTestServerRunning() {
882 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
883 std::string sync_url = cl->GetSwitchValueASCII(switches::kSyncServiceURL);
884 GURL sync_url_status(sync_url.append("/healthz"));
885 SyncServerStatusChecker delegate;
886 scoped_ptr<net::URLFetcher> fetcher =
887 net::URLFetcher::Create(sync_url_status, net::URLFetcher::GET, &delegate);
888 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE |
889 net::LOAD_DO_NOT_SEND_COOKIES |
890 net::LOAD_DO_NOT_SAVE_COOKIES);
891 fetcher->SetRequestContext(g_browser_process->system_request_context());
892 fetcher->Start();
893 content::RunMessageLoop();
894 return delegate.running();
897 bool SyncTest::TestUsesSelfNotifications() {
898 return true;
901 bool SyncTest::EnableEncryption(int index) {
902 ProfileSyncService* service = GetClient(index)->service();
904 if (::IsEncryptionComplete(service))
905 return true;
907 service->EnableEncryptEverything();
909 // In order to kick off the encryption we have to reconfigure. Just grab the
910 // currently synced types and use them.
911 const syncer::ModelTypeSet synced_datatypes =
912 service->GetPreferredDataTypes();
913 bool sync_everything = synced_datatypes.Equals(syncer::ModelTypeSet::All());
914 service->OnUserChoseDatatypes(sync_everything, synced_datatypes);
916 return AwaitEncryptionComplete(index);
919 bool SyncTest::IsEncryptionComplete(int index) {
920 return ::IsEncryptionComplete(GetClient(index)->service());
923 bool SyncTest::AwaitEncryptionComplete(int index) {
924 ProfileSyncService* service = GetClient(index)->service();
925 EncryptionChecker checker(service);
926 checker.Wait();
927 return !checker.TimedOut();
930 bool SyncTest::AwaitQuiescence() {
931 return ProfileSyncServiceHarness::AwaitQuiescence(clients());
934 bool SyncTest::UsingExternalServers() {
935 return server_type_ == EXTERNAL_LIVE_SERVER;
938 bool SyncTest::ServerSupportsNotificationControl() const {
939 EXPECT_NE(SERVER_TYPE_UNDECIDED, server_type_);
941 // Supported only if we're using the python testserver.
942 return server_type_ == LOCAL_PYTHON_SERVER;
945 void SyncTest::DisableNotificationsImpl() {
946 ASSERT_TRUE(ServerSupportsNotificationControl());
947 std::string path = "chromiumsync/disablenotifications";
948 ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
949 ASSERT_EQ("Notifications disabled",
950 base::UTF16ToASCII(
951 browser()->tab_strip_model()->GetActiveWebContents()->
952 GetTitle()));
955 void SyncTest::DisableNotifications() {
956 DisableNotificationsImpl();
957 notifications_enabled_ = false;
960 void SyncTest::EnableNotificationsImpl() {
961 ASSERT_TRUE(ServerSupportsNotificationControl());
962 std::string path = "chromiumsync/enablenotifications";
963 ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
964 ASSERT_EQ("Notifications enabled",
965 base::UTF16ToASCII(
966 browser()->tab_strip_model()->GetActiveWebContents()->
967 GetTitle()));
970 void SyncTest::EnableNotifications() {
971 EnableNotificationsImpl();
972 notifications_enabled_ = true;
975 void SyncTest::TriggerNotification(syncer::ModelTypeSet changed_types) {
976 ASSERT_TRUE(ServerSupportsNotificationControl());
977 const std::string& data =
978 syncer::P2PNotificationData(
979 "from_server",
980 syncer::NOTIFY_ALL,
981 syncer::ObjectIdInvalidationMap::InvalidateAll(
982 syncer::ModelTypeSetToObjectIdSet(changed_types))).ToString();
983 const std::string& path =
984 std::string("chromiumsync/sendnotification?channel=") +
985 syncer::kSyncP2PNotificationChannel + "&data=" + data;
986 ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
987 ASSERT_EQ("Notification sent",
988 base::UTF16ToASCII(
989 browser()->tab_strip_model()->GetActiveWebContents()->
990 GetTitle()));
993 bool SyncTest::ServerSupportsErrorTriggering() const {
994 EXPECT_NE(SERVER_TYPE_UNDECIDED, server_type_);
996 // Supported only if we're using the python testserver.
997 return server_type_ == LOCAL_PYTHON_SERVER;
1000 void SyncTest::TriggerMigrationDoneError(syncer::ModelTypeSet model_types) {
1001 ASSERT_TRUE(ServerSupportsErrorTriggering());
1002 std::string path = "chromiumsync/migrate";
1003 char joiner = '?';
1004 for (syncer::ModelTypeSet::Iterator it = model_types.First();
1005 it.Good(); it.Inc()) {
1006 path.append(
1007 base::StringPrintf(
1008 "%ctype=%d", joiner,
1009 syncer::GetSpecificsFieldNumberFromModelType(it.Get())));
1010 joiner = '&';
1012 ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
1013 ASSERT_EQ("Migration: 200",
1014 base::UTF16ToASCII(
1015 browser()->tab_strip_model()->GetActiveWebContents()->
1016 GetTitle()));
1019 void SyncTest::TriggerXmppAuthError() {
1020 ASSERT_TRUE(ServerSupportsErrorTriggering());
1021 std::string path = "chromiumsync/xmppcred";
1022 ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
1025 void SyncTest::TriggerCreateSyncedBookmarks() {
1026 ASSERT_TRUE(ServerSupportsErrorTriggering());
1027 std::string path = "chromiumsync/createsyncedbookmarks";
1028 ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
1029 ASSERT_EQ("Synced Bookmarks",
1030 base::UTF16ToASCII(
1031 browser()->tab_strip_model()->GetActiveWebContents()->
1032 GetTitle()));
1035 void SyncTest::SetupNetwork(net::URLRequestContextGetter* context_getter) {
1036 base::WaitableEvent done(false, false);
1037 BrowserThread::PostTask(
1038 BrowserThread::IO, FROM_HERE,
1039 base::Bind(&SetupNetworkCallback, &done,
1040 make_scoped_refptr(context_getter)));
1041 done.Wait();
1044 fake_server::FakeServer* SyncTest::GetFakeServer() const {
1045 return fake_server_.get();
1048 void SyncTest::TriggerSyncForModelTypes(int index,
1049 syncer::ModelTypeSet model_types) {
1050 content::NotificationService::current()->Notify(
1051 chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
1052 content::Source<Profile>(GetProfile(index)),
1053 content::Details<const syncer::ModelTypeSet>(&model_types));
1056 void SyncTest::SetPreexistingPreferencesFileContents(
1057 const std::string& contents) {
1058 preexisting_preferences_file_contents_ = contents;