BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / chrome / browser / sync / test / integration / sync_test.cc
blob9522fd11152da3523a5cb28266c57de9bcb25d3d
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/guid.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/path_service.h"
17 #include "base/process/launch.h"
18 #include "base/strings/string_split.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/synchronization/waitable_event.h"
23 #include "base/test/test_timeouts.h"
24 #include "base/threading/platform_thread.h"
25 #include "base/values.h"
26 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
27 #include "chrome/browser/chrome_notification_types.h"
28 #include "chrome/browser/history/history_service_factory.h"
29 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
30 #include "chrome/browser/lifetime/application_lifetime.h"
31 #include "chrome/browser/profiles/profile_manager.h"
32 #include "chrome/browser/search_engines/template_url_service_factory.h"
33 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
34 #include "chrome/browser/signin/signin_manager_factory.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/views/profiles/profile_chooser_view.h"
49 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
50 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
51 #include "chrome/common/chrome_constants.h"
52 #include "chrome/common/chrome_paths.h"
53 #include "chrome/common/chrome_switches.h"
54 #include "chrome/test/base/testing_browser_process.h"
55 #include "chrome/test/base/ui_test_utils.h"
56 #include "components/bookmarks/test/bookmark_test_helpers.h"
57 #include "components/google/core/browser/google_url_tracker.h"
58 #include "components/invalidation/impl/invalidation_switches.h"
59 #include "components/invalidation/impl/p2p_invalidation_service.h"
60 #include "components/invalidation/impl/p2p_invalidator.h"
61 #include "components/invalidation/impl/profile_invalidation_provider.h"
62 #include "components/invalidation/public/invalidation_service.h"
63 #include "components/keyed_service/core/keyed_service.h"
64 #include "components/os_crypt/os_crypt.h"
65 #include "components/search_engines/template_url_service.h"
66 #include "components/signin/core/browser/profile_identity_provider.h"
67 #include "components/signin/core/browser/signin_manager.h"
68 #include "components/sync_driver/invalidation_helper.h"
69 #include "components/sync_driver/sync_driver_switches.h"
70 #include "content/public/browser/navigation_entry.h"
71 #include "content/public/browser/notification_service.h"
72 #include "content/public/browser/web_contents.h"
73 #include "content/public/test/test_browser_thread.h"
74 #include "google_apis/gaia/gaia_urls.h"
75 #include "net/base/escape.h"
76 #include "net/base/load_flags.h"
77 #include "net/base/network_change_notifier.h"
78 #include "net/base/port_util.h"
79 #include "net/cookies/cookie_monster.h"
80 #include "net/test/spawned_test_server/spawned_test_server.h"
81 #include "net/url_request/test_url_fetcher_factory.h"
82 #include "net/url_request/url_fetcher.h"
83 #include "net/url_request/url_fetcher_delegate.h"
84 #include "net/url_request/url_request_context.h"
85 #include "net/url_request/url_request_context_getter.h"
86 #include "sync/engine/sync_scheduler_impl.h"
87 #include "sync/protocol/sync.pb.h"
88 #include "sync/test/fake_server/fake_server.h"
89 #include "sync/test/fake_server/fake_server_network_resources.h"
90 #include "url/gurl.h"
92 #if defined(OS_CHROMEOS)
93 #include "chromeos/chromeos_switches.h"
94 #endif
96 using content::BrowserThread;
98 namespace switches {
99 const char kPasswordFileForTest[] = "password-file-for-test";
100 const char kSyncUserForTest[] = "sync-user-for-test";
101 const char kSyncPasswordForTest[] = "sync-password-for-test";
102 const char kSyncServerCommandLine[] = "sync-server-command-line";
105 namespace {
107 // Helper class that checks whether a sync test server is running or not.
108 class SyncServerStatusChecker : public net::URLFetcherDelegate {
109 public:
110 SyncServerStatusChecker() : running_(false) {}
112 void OnURLFetchComplete(const net::URLFetcher* source) override {
113 std::string data;
114 source->GetResponseAsString(&data);
115 running_ =
116 (source->GetStatus().status() == net::URLRequestStatus::SUCCESS &&
117 source->GetResponseCode() == 200 && data.find("ok") == 0);
118 base::MessageLoop::current()->Quit();
121 bool running() const { return running_; }
123 private:
124 bool running_;
127 bool IsEncryptionComplete(const ProfileSyncService* service) {
128 return service->IsEncryptEverythingEnabled() &&
129 !service->encryption_pending();
132 // Helper class to wait for encryption to complete.
133 class EncryptionChecker : public SingleClientStatusChangeChecker {
134 public:
135 explicit EncryptionChecker(ProfileSyncService* service)
136 : SingleClientStatusChangeChecker(service) {}
138 bool IsExitConditionSatisfied() override {
139 return IsEncryptionComplete(service());
142 std::string GetDebugMessage() const override { return "Encryption"; }
145 void SetupNetworkCallback(
146 base::WaitableEvent* done,
147 net::URLRequestContextGetter* url_request_context_getter) {
148 url_request_context_getter->GetURLRequestContext()->
149 set_cookie_store(new net::CookieMonster(NULL, NULL));
150 done->Signal();
153 scoped_ptr<KeyedService> BuildFakeServerProfileInvalidationProvider(
154 content::BrowserContext* context) {
155 return make_scoped_ptr(new invalidation::ProfileInvalidationProvider(
156 scoped_ptr<invalidation::InvalidationService>(
157 new fake_server::FakeServerInvalidationService)));
160 scoped_ptr<KeyedService> BuildP2PProfileInvalidationProvider(
161 content::BrowserContext* context,
162 syncer::P2PNotificationTarget notification_target) {
163 Profile* profile = static_cast<Profile*>(context);
164 return make_scoped_ptr(new invalidation::ProfileInvalidationProvider(
165 scoped_ptr<invalidation::InvalidationService>(
166 new invalidation::P2PInvalidationService(
167 scoped_ptr<IdentityProvider>(new ProfileIdentityProvider(
168 SigninManagerFactory::GetForProfile(profile),
169 ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
170 LoginUIServiceFactory::GetShowLoginPopupCallbackForProfile(
171 profile))),
172 profile->GetRequestContext(), notification_target))));
175 scoped_ptr<KeyedService> BuildSelfNotifyingP2PProfileInvalidationProvider(
176 content::BrowserContext* context) {
177 return BuildP2PProfileInvalidationProvider(context, syncer::NOTIFY_ALL);
180 scoped_ptr<KeyedService> BuildRealisticP2PProfileInvalidationProvider(
181 content::BrowserContext* context) {
182 return BuildP2PProfileInvalidationProvider(context, syncer::NOTIFY_OTHERS);
185 } // namespace
187 SyncTest::SyncTest(TestType test_type)
188 : test_type_(test_type),
189 server_type_(SERVER_TYPE_UNDECIDED),
190 num_clients_(-1),
191 use_verifier_(true),
192 notifications_enabled_(true),
193 create_gaia_account_at_runtime_(false) {
194 sync_datatype_helper::AssociateWithTest(this);
195 switch (test_type_) {
196 case SINGLE_CLIENT:
197 case SINGLE_CLIENT_LEGACY: {
198 num_clients_ = 1;
199 break;
201 case TWO_CLIENT:
202 case TWO_CLIENT_LEGACY: {
203 num_clients_ = 2;
204 break;
206 case MULTIPLE_CLIENT: {
207 num_clients_ = 3;
208 break;
213 SyncTest::~SyncTest() {}
215 void SyncTest::SetUp() {
216 // Sets |server_type_| if it wasn't specified by the test.
217 DecideServerType();
219 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
220 if (cl->HasSwitch(switches::kPasswordFileForTest)) {
221 ReadPasswordFile();
222 } else {
223 // Decide on username to use or create one.
224 if (cl->HasSwitch(switches::kSyncUserForTest)) {
225 username_ = cl->GetSwitchValueASCII(switches::kSyncUserForTest);
226 } else if (UsingExternalServers()) {
227 // We assume the need to automatically create a Gaia account which
228 // requires URL navigation and needs to be done outside SetUp() function.
229 create_gaia_account_at_runtime_ = true;
230 username_ = base::GenerateGUID();
231 } else {
232 username_ = "user@gmail.com";
234 // Decide on password to use.
235 password_ = cl->HasSwitch(switches::kSyncPasswordForTest)
236 ? cl->GetSwitchValueASCII(switches::kSyncPasswordForTest)
237 : "password";
240 if (username_.empty() || password_.empty())
241 LOG(FATAL) << "Cannot run sync tests without GAIA credentials.";
243 // Mock the Mac Keychain service. The real Keychain can block on user input.
244 #if defined(OS_MACOSX)
245 OSCrypt::UseMockKeychain(true);
246 #endif
248 // Start up a sync test server if one is needed and setup mock gaia responses.
249 // Note: This must be done prior to the call to SetupClients() because we want
250 // the mock gaia responses to be available before GaiaUrls is initialized.
251 SetUpTestServerIfRequired();
253 // Yield control back to the InProcessBrowserTest framework.
254 InProcessBrowserTest::SetUp();
257 void SyncTest::TearDown() {
258 // Clear any mock gaia responses that might have been set.
259 ClearMockGaiaResponses();
261 // Allow the InProcessBrowserTest framework to perform its tear down.
262 InProcessBrowserTest::TearDown();
264 // Stop the local python test server. This is a no-op if one wasn't started.
265 TearDownLocalPythonTestServer();
267 // Stop the local sync test server. This is a no-op if one wasn't started.
268 TearDownLocalTestServer();
270 fake_server_.reset();
273 void SyncTest::SetUpCommandLine(base::CommandLine* cl) {
274 AddTestSwitches(cl);
275 AddOptionalTypesToCommandLine(cl);
277 #if defined(OS_CHROMEOS)
278 cl->AppendSwitch(chromeos::switches::kIgnoreUserProfileMappingForTests);
279 #endif
282 void SyncTest::AddTestSwitches(base::CommandLine* cl) {
283 // Disable non-essential access of external network resources.
284 if (!cl->HasSwitch(switches::kDisableBackgroundNetworking))
285 cl->AppendSwitch(switches::kDisableBackgroundNetworking);
287 if (!cl->HasSwitch(switches::kSyncShortInitialRetryOverride))
288 cl->AppendSwitch(switches::kSyncShortInitialRetryOverride);
291 void SyncTest::AddOptionalTypesToCommandLine(base::CommandLine* cl) {}
293 bool SyncTest::CreateGaiaAccount(const std::string& username,
294 const std::string& password) {
295 std::string relative_url = base::StringPrintf("/CreateUsers?%s=%s",
296 username.c_str(),
297 password.c_str());
298 GURL create_user_url =
299 GaiaUrls::GetInstance()->gaia_url().Resolve(relative_url);
300 // NavigateToURL blocks until the navigation finishes.
301 ui_test_utils::NavigateToURL(browser(), create_user_url);
302 content::WebContents* contents =
303 browser()->tab_strip_model()->GetActiveWebContents();
304 content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
305 CHECK(entry) << "Could not get a hold on NavigationEntry post URL navigate.";
306 DVLOG(1) << "Create Gaia account request return code = "
307 << entry->GetHttpStatusCode();
308 return entry->GetHttpStatusCode() == 200;
311 // Called when the ProfileManager has created a profile.
312 // static
313 void SyncTest::CreateProfileCallback(const base::Closure& quit_closure,
314 Profile* profile,
315 Profile::CreateStatus status) {
316 EXPECT_TRUE(profile);
317 EXPECT_NE(Profile::CREATE_STATUS_LOCAL_FAIL, status);
318 EXPECT_NE(Profile::CREATE_STATUS_REMOTE_FAIL, status);
319 // This will be called multiple times. Wait until the profile is initialized
320 // fully to quit the loop.
321 if (status == Profile::CREATE_STATUS_INITIALIZED)
322 quit_closure.Run();
325 // TODO(shadi): Ideally creating a new profile should not depend on signin
326 // process. We should try to consolidate MakeProfileForUISignin() and
327 // MakeProfile(). Major differences are profile paths and creation methods. For
328 // UI signin we need profiles in unique user data dir's and we need to use
329 // ProfileManager::CreateProfileAsync() for proper profile creation.
330 // static
331 Profile* SyncTest::MakeProfileForUISignin(
332 const base::FilePath::StringType name) {
333 // For multi profile UI signin, profile paths should be outside user data dir.
334 // Otherwise, we get an error that the profile has already signed in on this
335 // device.
336 // Note that prefix |name| is implemented only on Win. On other platforms the
337 // com.google.Chrome.XXXXXX prefix is used.
338 base::FilePath profile_path;
339 CHECK(base::CreateNewTempDirectory(name, &profile_path));
341 ProfileManager* profile_manager = g_browser_process->profile_manager();
342 base::RunLoop run_loop;
343 ProfileManager::CreateCallback create_callback = base::Bind(
344 &CreateProfileCallback, run_loop.QuitClosure());
345 profile_manager->CreateProfileAsync(profile_path,
346 create_callback,
347 base::string16(),
348 base::string16(),
349 std::string());
350 run_loop.Run();
351 return profile_manager->GetProfileByPath(profile_path);
354 Profile* SyncTest::MakeProfile(const base::FilePath::StringType name) {
355 base::FilePath path;
356 // Create new profiles in user data dir so that other profiles can know about
357 // it. This is needed in tests such as supervised user cases which assume
358 // browser->profile() as the custodian profile.
359 PathService::Get(chrome::DIR_USER_DATA, &path);
360 path = path.Append(name);
362 if (!base::PathExists(path))
363 CHECK(base::CreateDirectory(path));
365 if (!preexisting_preferences_file_contents_.empty()) {
366 base::FilePath pref_path(path.Append(chrome::kPreferencesFilename));
367 const char* contents = preexisting_preferences_file_contents_.c_str();
368 size_t contents_length = preexisting_preferences_file_contents_.size();
369 if (!base::WriteFile(pref_path, contents, contents_length)) {
370 LOG(FATAL) << "Preexisting Preferences file could not be written.";
374 Profile* profile =
375 Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
376 g_browser_process->profile_manager()->RegisterTestingProfile(profile,
377 true,
378 true);
379 return profile;
382 Profile* SyncTest::GetProfile(int index) {
383 if (profiles_.empty())
384 LOG(FATAL) << "SetupClients() has not yet been called.";
385 if (index < 0 || index >= static_cast<int>(profiles_.size()))
386 LOG(FATAL) << "GetProfile(): Index is out of bounds.";
387 return profiles_[index];
390 Browser* SyncTest::GetBrowser(int index) {
391 if (browsers_.empty())
392 LOG(FATAL) << "SetupClients() has not yet been called.";
393 if (index < 0 || index >= static_cast<int>(browsers_.size()))
394 LOG(FATAL) << "GetBrowser(): Index is out of bounds.";
395 return browsers_[index];
398 ProfileSyncServiceHarness* SyncTest::GetClient(int index) {
399 if (clients_.empty())
400 LOG(FATAL) << "SetupClients() has not yet been called.";
401 if (index < 0 || index >= static_cast<int>(clients_.size()))
402 LOG(FATAL) << "GetClient(): Index is out of bounds.";
403 return clients_[index];
406 ProfileSyncService* SyncTest::GetSyncService(int index) {
407 return ProfileSyncServiceFactory::GetForProfile(GetProfile(index));
410 std::vector<ProfileSyncService*> SyncTest::GetSyncServices() {
411 std::vector<ProfileSyncService*> services;
412 for (int i = 0; i < num_clients(); ++i) {
413 services.push_back(GetSyncService(i));
415 return services;
418 Profile* SyncTest::verifier() {
419 if (!use_verifier_)
420 LOG(FATAL) << "Verifier account is disabled.";
421 if (verifier_ == NULL)
422 LOG(FATAL) << "SetupClients() has not yet been called.";
423 return verifier_;
426 void SyncTest::DisableVerifier() {
427 use_verifier_ = false;
430 bool SyncTest::SetupClients() {
431 if (num_clients_ <= 0)
432 LOG(FATAL) << "num_clients_ incorrectly initialized.";
433 if (!profiles_.empty() || !browsers_.empty() || !clients_.empty())
434 LOG(FATAL) << "SetupClients() has already been called.";
436 // Create the required number of sync profiles, browsers and clients.
437 profiles_.resize(num_clients_);
438 browsers_.resize(num_clients_);
439 clients_.resize(num_clients_);
440 invalidation_forwarders_.resize(num_clients_);
441 sync_refreshers_.resize(num_clients_);
442 fake_server_invalidation_services_.resize(num_clients_);
443 for (int i = 0; i < num_clients_; ++i) {
444 InitializeInstance(i);
447 // Verifier account is not useful when running against external servers.
448 if (UsingExternalServers())
449 DisableVerifier();
451 // Create the verifier profile.
452 if (use_verifier_) {
453 verifier_ = MakeProfile(FILE_PATH_LITERAL("Verifier"));
454 bookmarks::test::WaitForBookmarkModelToLoad(
455 BookmarkModelFactory::GetForProfile(verifier()));
456 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
457 verifier(), ServiceAccessType::EXPLICIT_ACCESS));
458 ui_test_utils::WaitForTemplateURLServiceToLoad(
459 TemplateURLServiceFactory::GetForProfile(verifier()));
461 // Error cases are all handled by LOG(FATAL) messages. So there is not really
462 // a case that returns false. In case we failed to create a verifier profile,
463 // any call to the verifier() would fail.
464 return true;
467 void SyncTest::InitializeInstance(int index) {
468 base::FilePath::StringType profile_name =
469 base::StringPrintf(FILE_PATH_LITERAL("Profile%d"), index);
470 // If running against an EXTERNAL_LIVE_SERVER, we need to signin profiles
471 // using real GAIA server. This requires creating profiles with no test hooks.
472 if (UsingExternalServers()) {
473 profiles_[index] = MakeProfileForUISignin(profile_name);
474 } else {
475 // Without need of real GAIA authentication, we create new test profiles.
476 profiles_[index] = MakeProfile(profile_name);
479 EXPECT_FALSE(GetProfile(index) == NULL) << "Could not create Profile "
480 << index << ".";
482 // CheckInitialState() assumes that no windows are open at startup.
483 browsers_[index] = new Browser(Browser::CreateParams(
484 GetProfile(index), chrome::GetActiveDesktop()));
486 EXPECT_FALSE(GetBrowser(index) == NULL) << "Could not create Browser "
487 << index << ".";
489 // Make sure the ProfileSyncService has been created before creating the
490 // ProfileSyncServiceHarness - some tests expect the ProfileSyncService to
491 // already exist.
492 ProfileSyncService* profile_sync_service =
493 ProfileSyncServiceFactory::GetForProfile(GetProfile(index));
495 SetupNetwork(GetProfile(index)->GetRequestContext());
497 if (server_type_ == IN_PROCESS_FAKE_SERVER) {
498 // TODO(pvalenzuela): Run the fake server via EmbeddedTestServer.
499 profile_sync_service->OverrideNetworkResourcesForTest(
500 make_scoped_ptr<syncer::NetworkResources>(
501 new fake_server::FakeServerNetworkResources(
502 fake_server_->AsWeakPtr())));
505 ProfileSyncServiceHarness::SigninType singin_type = UsingExternalServers()
506 ? ProfileSyncServiceHarness::SigninType::UI_SIGNIN
507 : ProfileSyncServiceHarness::SigninType::FAKE_SIGNIN;
509 clients_[index] =
510 ProfileSyncServiceHarness::Create(GetProfile(index),
511 username_,
512 password_,
513 singin_type);
514 EXPECT_FALSE(GetClient(index) == NULL) << "Could not create Client "
515 << index << ".";
516 InitializeInvalidations(index);
518 bookmarks::test::WaitForBookmarkModelToLoad(
519 BookmarkModelFactory::GetForProfile(GetProfile(index)));
520 ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
521 GetProfile(index), ServiceAccessType::EXPLICIT_ACCESS));
522 ui_test_utils::WaitForTemplateURLServiceToLoad(
523 TemplateURLServiceFactory::GetForProfile(GetProfile(index)));
526 void SyncTest::InitializeInvalidations(int index) {
527 if (UsingExternalServers()) {
528 // DO NOTHING. External live sync servers use GCM to notify profiles of any
529 // invalidations in sync'ed data. In this case, to notify other profiles of
530 // invalidations, we use sync refresh notifications instead.
531 } else if (server_type_ == IN_PROCESS_FAKE_SERVER) {
532 CHECK(fake_server_.get());
533 fake_server::FakeServerInvalidationService* invalidation_service =
534 static_cast<fake_server::FakeServerInvalidationService*>(
535 static_cast<invalidation::ProfileInvalidationProvider*>(
536 invalidation::ProfileInvalidationProviderFactory::
537 GetInstance()->SetTestingFactoryAndUse(
538 GetProfile(index),
539 BuildFakeServerProfileInvalidationProvider))->
540 GetInvalidationService());
541 fake_server_->AddObserver(invalidation_service);
542 if (TestUsesSelfNotifications()) {
543 invalidation_service->EnableSelfNotifications();
544 } else {
545 invalidation_service->DisableSelfNotifications();
547 fake_server_invalidation_services_[index] = invalidation_service;
548 } else {
549 invalidation::P2PInvalidationService* p2p_invalidation_service =
550 static_cast<invalidation::P2PInvalidationService*>(
551 static_cast<invalidation::ProfileInvalidationProvider*>(
552 invalidation::ProfileInvalidationProviderFactory::
553 GetInstance()->SetTestingFactoryAndUse(
554 GetProfile(index),
555 TestUsesSelfNotifications() ?
556 BuildSelfNotifyingP2PProfileInvalidationProvider :
557 BuildRealisticP2PProfileInvalidationProvider))->
558 GetInvalidationService());
559 p2p_invalidation_service->UpdateCredentials(username_, password_);
560 // Start listening for and emitting notifications of commits.
561 invalidation_forwarders_[index] =
562 new P2PInvalidationForwarder(clients_[index]->service(),
563 p2p_invalidation_service);
567 bool SyncTest::SetupSync() {
568 if (create_gaia_account_at_runtime_) {
569 CHECK(UsingExternalServers()) <<
570 "Cannot create Gaia accounts without external authentication servers";
571 if (!CreateGaiaAccount(username_, password_))
572 LOG(FATAL) << "Could not create Gaia account.";
574 // Create sync profiles and clients if they haven't already been created.
575 if (profiles_.empty()) {
576 if (!SetupClients())
577 LOG(FATAL) << "SetupClients() failed.";
580 // Sync each of the profiles.
581 for (int i = 0; i < num_clients_; ++i) {
582 if (!GetClient(i)->SetupSync())
583 LOG(FATAL) << "SetupSync() failed.";
586 // Because clients may modify sync data as part of startup (for example local
587 // session-releated data is rewritten), we need to ensure all startup-based
588 // changes have propagated between the clients.
590 // Tests that don't use self-notifications can't await quiescense. They'll
591 // have to find their own way of waiting for an initial state if they really
592 // need such guarantees.
593 if (TestUsesSelfNotifications()) {
594 AwaitQuiescence();
597 // SyncRefresher is used instead of invalidations to notify other profiles to
598 // do a sync refresh on committed data sets. This is only needed when running
599 // tests against external live server, otherwise invalidation service is used.
600 // With external live servers, the profiles commit data on first sync cycle
601 // automatically after signing in. To avoid misleading sync commit
602 // notifications at start up, we start the SyncRefresher observers post
603 // client set up.
604 if (UsingExternalServers()) {
605 for (int i = 0; i < num_clients_; ++i) {
606 sync_refreshers_[i] = new P2PSyncRefresher(clients_[i]->service());
609 // OneClickSigninSyncStarter observer is created with a real user sign in.
610 // It is deleted on certain conditions which are not satisfied by our tests,
611 // and this causes the SigninTracker observer to stay hanging at shutdown.
612 // Calling LoginUIService::SyncConfirmationUIClosed forces the observer to
613 // be removed. http://crbug.com/484388
614 for (int i = 0; i < num_clients_; ++i) {
615 LoginUIServiceFactory::GetForProfile(GetProfile(i))->
616 SyncConfirmationUIClosed(false /* configure_sync_first */);
619 // With external servers, profile paths are created outside user_data_dir.
620 // This causes the ProfileManager to show an avatar bubble without an anchor
621 // view. The bubble is then not destroyed at shutdown, crbug.com/527505.
622 // This is a fix to explicitly close the bubble early on.
623 // ProfileChooserView is available on few platforms including Linux which is
624 // the only supported platform for ExternalServers.
625 #if defined(OS_LINUX)
626 // TODO(shadi): Remove this hack once crbug.com/527505 is fixed.
627 ProfileChooserView::Hide();
628 #endif // defined(OS_LINUX)
631 return true;
634 void SyncTest::TearDownOnMainThread() {
635 for (size_t i = 0; i < clients_.size(); ++i) {
636 clients_[i]->service()->RequestStop(ProfileSyncService::CLEAR_DATA);
639 content::WindowedNotificationObserver observer(
640 chrome::NOTIFICATION_BROWSER_CLOSED,
641 content::NotificationService::AllSources());
642 chrome::CloseAllBrowsers();
644 // Waiting for a single notification mitigates flakiness (related to not all
645 // browsers being closed). If further flakiness is seen
646 // (GetTotalBrowserCount() > 0 after this call), GetTotalBrowserCount()
647 // notifications should be waited on.
648 observer.Wait();
650 if (fake_server_.get()) {
651 std::vector<fake_server::FakeServerInvalidationService*>::const_iterator it;
652 for (it = fake_server_invalidation_services_.begin();
653 it != fake_server_invalidation_services_.end(); ++it) {
654 fake_server_->RemoveObserver(*it);
658 // All browsers should be closed at this point, or else we could see memory
659 // corruption in QuitBrowser().
660 CHECK_EQ(0U, chrome::GetTotalBrowserCount());
661 invalidation_forwarders_.clear();
662 sync_refreshers_.clear();
663 fake_server_invalidation_services_.clear();
664 clients_.clear();
667 void SyncTest::SetUpInProcessBrowserTestFixture() {
668 // We don't take a reference to |resolver|, but mock_host_resolver_override_
669 // does, so effectively assumes ownership.
670 net::RuleBasedHostResolverProc* resolver =
671 new net::RuleBasedHostResolverProc(host_resolver());
672 resolver->AllowDirectLookup("*.google.com");
674 // Allow connection to googleapis.com for oauth token requests in E2E tests.
675 resolver->AllowDirectLookup("*.googleapis.com");
677 // On Linux, we use Chromium's NSS implementation which uses the following
678 // hosts for certificate verification. Without these overrides, running the
679 // integration tests on Linux causes error as we make external DNS lookups.
680 resolver->AllowDirectLookup("*.thawte.com");
681 resolver->AllowDirectLookup("*.geotrust.com");
682 resolver->AllowDirectLookup("*.gstatic.com");
683 mock_host_resolver_override_.reset(
684 new net::ScopedDefaultHostResolverProc(resolver));
687 void SyncTest::TearDownInProcessBrowserTestFixture() {
688 mock_host_resolver_override_.reset();
691 void SyncTest::ReadPasswordFile() {
692 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
693 password_file_ = cl->GetSwitchValuePath(switches::kPasswordFileForTest);
694 if (password_file_.empty())
695 LOG(FATAL) << "Can't run live server test without specifying --"
696 << switches::kPasswordFileForTest << "=<filename>";
697 std::string file_contents;
698 base::ReadFileToString(password_file_, &file_contents);
699 ASSERT_NE(file_contents, "") << "Password file \""
700 << password_file_.value() << "\" does not exist.";
701 std::vector<std::string> tokens = base::SplitString(
702 file_contents, "\r\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
703 ASSERT_EQ(2U, tokens.size()) << "Password file \""
704 << password_file_.value()
705 << "\" must contain exactly two lines of text.";
706 username_ = tokens[0];
707 password_ = tokens[1];
710 void SyncTest::SetupMockGaiaResponses() {
711 factory_.reset(new net::URLFetcherImplFactory());
712 fake_factory_.reset(new net::FakeURLFetcherFactory(factory_.get()));
713 fake_factory_->SetFakeResponse(
714 GaiaUrls::GetInstance()->get_user_info_url(),
715 "email=user@gmail.com\ndisplayEmail=user@gmail.com",
716 net::HTTP_OK,
717 net::URLRequestStatus::SUCCESS);
718 fake_factory_->SetFakeResponse(
719 GaiaUrls::GetInstance()->issue_auth_token_url(),
720 "auth",
721 net::HTTP_OK,
722 net::URLRequestStatus::SUCCESS);
723 fake_factory_->SetFakeResponse(
724 GURL(GoogleURLTracker::kSearchDomainCheckURL),
725 ".google.com",
726 net::HTTP_OK,
727 net::URLRequestStatus::SUCCESS);
728 fake_factory_->SetFakeResponse(
729 GaiaUrls::GetInstance()->client_login_to_oauth2_url(),
730 "some_response",
731 net::HTTP_OK,
732 net::URLRequestStatus::SUCCESS);
733 fake_factory_->SetFakeResponse(
734 GaiaUrls::GetInstance()->oauth2_token_url(),
736 " \"refresh_token\": \"rt1\","
737 " \"access_token\": \"at1\","
738 " \"expires_in\": 3600,"
739 " \"token_type\": \"Bearer\""
740 "}",
741 net::HTTP_OK,
742 net::URLRequestStatus::SUCCESS);
743 fake_factory_->SetFakeResponse(
744 GaiaUrls::GetInstance()->oauth_user_info_url(),
746 " \"id\": \"12345\""
747 "}",
748 net::HTTP_OK,
749 net::URLRequestStatus::SUCCESS);
750 fake_factory_->SetFakeResponse(
751 GaiaUrls::GetInstance()->oauth1_login_url(),
752 "SID=sid\nLSID=lsid\nAuth=auth_token",
753 net::HTTP_OK,
754 net::URLRequestStatus::SUCCESS);
755 fake_factory_->SetFakeResponse(
756 GaiaUrls::GetInstance()->oauth2_revoke_url(),
758 net::HTTP_OK,
759 net::URLRequestStatus::SUCCESS);
762 void SyncTest::SetOAuth2TokenResponse(const std::string& response_data,
763 net::HttpStatusCode response_code,
764 net::URLRequestStatus::Status status) {
765 ASSERT_TRUE(NULL != fake_factory_.get());
766 fake_factory_->SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
767 response_data, response_code, status);
770 void SyncTest::ClearMockGaiaResponses() {
771 // Clear any mock gaia responses that might have been set.
772 if (fake_factory_) {
773 fake_factory_->ClearFakeResponses();
774 fake_factory_.reset();
777 // Cancel any outstanding URL fetches and destroy the URLFetcherImplFactory we
778 // created.
779 net::URLFetcher::CancelAll();
780 factory_.reset();
783 void SyncTest::DecideServerType() {
784 // Only set |server_type_| if it hasn't already been set. This allows for
785 // tests to explicitly set this value in each test class if needed.
786 if (server_type_ == SERVER_TYPE_UNDECIDED) {
787 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
788 if (!cl->HasSwitch(switches::kSyncServiceURL) &&
789 !cl->HasSwitch(switches::kSyncServerCommandLine)) {
790 // If neither a sync server URL nor a sync server command line is
791 // provided, start up a local sync test server and point Chrome
792 // to its URL. This is the most common configuration, and the only
793 // one that makes sense for most developers. FakeServer is the
794 // current solution but some scenarios are only supported by the
795 // legacy python server.
796 switch (test_type_) {
797 case SINGLE_CLIENT:
798 case TWO_CLIENT:
799 case MULTIPLE_CLIENT:
800 server_type_ = IN_PROCESS_FAKE_SERVER;
801 break;
802 default:
803 server_type_ = LOCAL_PYTHON_SERVER;
805 } else if (cl->HasSwitch(switches::kSyncServiceURL) &&
806 cl->HasSwitch(switches::kSyncServerCommandLine)) {
807 // If a sync server URL and a sync server command line are provided,
808 // start up a local sync server by running the command line. Chrome
809 // will connect to the server at the URL that was provided.
810 server_type_ = LOCAL_LIVE_SERVER;
811 } else if (cl->HasSwitch(switches::kSyncServiceURL) &&
812 !cl->HasSwitch(switches::kSyncServerCommandLine)) {
813 // If a sync server URL is provided, but not a server command line,
814 // it is assumed that the server is already running. Chrome will
815 // automatically connect to it at the URL provided. There is nothing
816 // to do here.
817 server_type_ = EXTERNAL_LIVE_SERVER;
818 } else {
819 // If a sync server command line is provided, but not a server URL,
820 // we flag an error.
821 LOG(FATAL) << "Can't figure out how to run a server.";
826 // Start up a local sync server based on the value of server_type_, which
827 // was determined from the command line parameters.
828 void SyncTest::SetUpTestServerIfRequired() {
829 if (UsingExternalServers()) {
830 // Nothing to do; we'll just talk to the URL we were given.
831 } else if (server_type_ == LOCAL_PYTHON_SERVER) {
832 if (!SetUpLocalPythonTestServer())
833 LOG(FATAL) << "Failed to set up local python sync and XMPP servers";
834 SetupMockGaiaResponses();
835 } else if (server_type_ == LOCAL_LIVE_SERVER) {
836 // Using mock gaia credentials requires the use of a mock XMPP server.
837 if (username_ == "user@gmail.com" && !SetUpLocalPythonTestServer())
838 LOG(FATAL) << "Failed to set up local python XMPP server";
839 if (!SetUpLocalTestServer())
840 LOG(FATAL) << "Failed to set up local test server";
841 } else if (server_type_ == IN_PROCESS_FAKE_SERVER) {
842 fake_server_.reset(new fake_server::FakeServer());
843 SetupMockGaiaResponses();
844 } else {
845 LOG(FATAL) << "Don't know which server environment to run test in.";
849 bool SyncTest::SetUpLocalPythonTestServer() {
850 EXPECT_TRUE(sync_server_.Start())
851 << "Could not launch local python test server.";
853 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
854 if (server_type_ == LOCAL_PYTHON_SERVER) {
855 std::string sync_service_url = sync_server_.GetURL("chromiumsync").spec();
856 cl->AppendSwitchASCII(switches::kSyncServiceURL, sync_service_url);
857 DVLOG(1) << "Started local python sync server at " << sync_service_url;
860 int xmpp_port = 0;
861 if (!sync_server_.server_data().GetInteger("xmpp_port", &xmpp_port)) {
862 LOG(ERROR) << "Could not find valid xmpp_port value";
863 return false;
865 if ((xmpp_port <= 0) || (xmpp_port > kuint16max)) {
866 LOG(ERROR) << "Invalid xmpp port: " << xmpp_port;
867 return false;
870 net::HostPortPair xmpp_host_port_pair(sync_server_.host_port_pair());
871 xmpp_host_port_pair.set_port(xmpp_port);
872 xmpp_port_.reset(new net::ScopedPortException(xmpp_port));
874 if (!cl->HasSwitch(invalidation::switches::kSyncNotificationHostPort)) {
875 cl->AppendSwitchASCII(invalidation::switches::kSyncNotificationHostPort,
876 xmpp_host_port_pair.ToString());
877 // The local XMPP server only supports insecure connections.
878 cl->AppendSwitch(invalidation::switches::kSyncAllowInsecureXmppConnection);
880 DVLOG(1) << "Started local python XMPP server at "
881 << xmpp_host_port_pair.ToString();
883 return true;
886 bool SyncTest::SetUpLocalTestServer() {
887 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
888 base::CommandLine::StringType server_cmdline_string =
889 cl->GetSwitchValueNative(switches::kSyncServerCommandLine);
890 base::CommandLine::StringVector server_cmdline_vector = base::SplitString(
891 server_cmdline_string, FILE_PATH_LITERAL(" "),
892 base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
893 base::CommandLine server_cmdline(server_cmdline_vector);
894 base::LaunchOptions options;
895 #if defined(OS_WIN)
896 options.start_hidden = true;
897 #endif
898 test_server_ = base::LaunchProcess(server_cmdline, options);
899 if (!test_server_.IsValid())
900 LOG(ERROR) << "Could not launch local test server.";
902 const base::TimeDelta kMaxWaitTime = TestTimeouts::action_max_timeout();
903 const int kNumIntervals = 15;
904 if (WaitForTestServerToStart(kMaxWaitTime, kNumIntervals)) {
905 DVLOG(1) << "Started local test server at "
906 << cl->GetSwitchValueASCII(switches::kSyncServiceURL) << ".";
907 return true;
908 } else {
909 LOG(ERROR) << "Could not start local test server at "
910 << cl->GetSwitchValueASCII(switches::kSyncServiceURL) << ".";
911 return false;
915 bool SyncTest::TearDownLocalPythonTestServer() {
916 if (!sync_server_.Stop()) {
917 LOG(ERROR) << "Could not stop local python test server.";
918 return false;
920 xmpp_port_.reset();
921 return true;
924 bool SyncTest::TearDownLocalTestServer() {
925 if (test_server_.IsValid()) {
926 EXPECT_TRUE(test_server_.Terminate(0, false))
927 << "Could not stop local test server.";
928 test_server_.Close();
930 return true;
933 bool SyncTest::WaitForTestServerToStart(base::TimeDelta wait, int intervals) {
934 for (int i = 0; i < intervals; ++i) {
935 if (IsTestServerRunning())
936 return true;
937 base::PlatformThread::Sleep(wait / intervals);
939 return false;
942 bool SyncTest::IsTestServerRunning() {
943 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
944 std::string sync_url = cl->GetSwitchValueASCII(switches::kSyncServiceURL);
945 GURL sync_url_status(sync_url.append("/healthz"));
946 SyncServerStatusChecker delegate;
947 scoped_ptr<net::URLFetcher> fetcher =
948 net::URLFetcher::Create(sync_url_status, net::URLFetcher::GET, &delegate);
949 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE |
950 net::LOAD_DO_NOT_SEND_COOKIES |
951 net::LOAD_DO_NOT_SAVE_COOKIES);
952 fetcher->SetRequestContext(g_browser_process->system_request_context());
953 fetcher->Start();
954 content::RunMessageLoop();
955 return delegate.running();
958 bool SyncTest::TestUsesSelfNotifications() {
959 return true;
962 bool SyncTest::EnableEncryption(int index) {
963 ProfileSyncService* service = GetClient(index)->service();
965 if (::IsEncryptionComplete(service))
966 return true;
968 service->EnableEncryptEverything();
970 // In order to kick off the encryption we have to reconfigure. Just grab the
971 // currently synced types and use them.
972 const syncer::ModelTypeSet synced_datatypes =
973 service->GetPreferredDataTypes();
974 bool sync_everything = synced_datatypes.Equals(syncer::ModelTypeSet::All());
975 service->OnUserChoseDatatypes(sync_everything, synced_datatypes);
977 return AwaitEncryptionComplete(index);
980 bool SyncTest::IsEncryptionComplete(int index) {
981 return ::IsEncryptionComplete(GetClient(index)->service());
984 bool SyncTest::AwaitEncryptionComplete(int index) {
985 ProfileSyncService* service = GetClient(index)->service();
986 EncryptionChecker checker(service);
987 checker.Wait();
988 return !checker.TimedOut();
991 bool SyncTest::AwaitQuiescence() {
992 return ProfileSyncServiceHarness::AwaitQuiescence(clients());
995 bool SyncTest::UsingExternalServers() {
996 return server_type_ == EXTERNAL_LIVE_SERVER;
999 bool SyncTest::ServerSupportsNotificationControl() const {
1000 EXPECT_NE(SERVER_TYPE_UNDECIDED, server_type_);
1002 // Supported only if we're using the python testserver.
1003 return server_type_ == LOCAL_PYTHON_SERVER;
1006 void SyncTest::DisableNotificationsImpl() {
1007 ASSERT_TRUE(ServerSupportsNotificationControl());
1008 std::string path = "chromiumsync/disablenotifications";
1009 ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
1010 ASSERT_EQ("Notifications disabled",
1011 base::UTF16ToASCII(
1012 browser()->tab_strip_model()->GetActiveWebContents()->
1013 GetTitle()));
1016 void SyncTest::DisableNotifications() {
1017 DisableNotificationsImpl();
1018 notifications_enabled_ = false;
1021 void SyncTest::EnableNotificationsImpl() {
1022 ASSERT_TRUE(ServerSupportsNotificationControl());
1023 std::string path = "chromiumsync/enablenotifications";
1024 ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
1025 ASSERT_EQ("Notifications enabled",
1026 base::UTF16ToASCII(
1027 browser()->tab_strip_model()->GetActiveWebContents()->
1028 GetTitle()));
1031 void SyncTest::EnableNotifications() {
1032 EnableNotificationsImpl();
1033 notifications_enabled_ = true;
1036 void SyncTest::TriggerNotification(syncer::ModelTypeSet changed_types) {
1037 ASSERT_TRUE(ServerSupportsNotificationControl());
1038 const std::string& data =
1039 syncer::P2PNotificationData(
1040 "from_server",
1041 syncer::NOTIFY_ALL,
1042 syncer::ObjectIdInvalidationMap::InvalidateAll(
1043 syncer::ModelTypeSetToObjectIdSet(changed_types))).ToString();
1044 const std::string& path =
1045 std::string("chromiumsync/sendnotification?channel=") +
1046 syncer::kSyncP2PNotificationChannel + "&data=" + data;
1047 ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
1048 ASSERT_EQ("Notification sent",
1049 base::UTF16ToASCII(
1050 browser()->tab_strip_model()->GetActiveWebContents()->
1051 GetTitle()));
1054 bool SyncTest::ServerSupportsErrorTriggering() const {
1055 EXPECT_NE(SERVER_TYPE_UNDECIDED, server_type_);
1057 // Supported only if we're using the python testserver.
1058 return server_type_ == LOCAL_PYTHON_SERVER;
1061 void SyncTest::TriggerMigrationDoneError(syncer::ModelTypeSet model_types) {
1062 ASSERT_TRUE(ServerSupportsErrorTriggering());
1063 std::string path = "chromiumsync/migrate";
1064 char joiner = '?';
1065 for (syncer::ModelTypeSet::Iterator it = model_types.First();
1066 it.Good(); it.Inc()) {
1067 path.append(
1068 base::StringPrintf(
1069 "%ctype=%d", joiner,
1070 syncer::GetSpecificsFieldNumberFromModelType(it.Get())));
1071 joiner = '&';
1073 ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
1074 ASSERT_EQ("Migration: 200",
1075 base::UTF16ToASCII(
1076 browser()->tab_strip_model()->GetActiveWebContents()->
1077 GetTitle()));
1080 void SyncTest::TriggerXmppAuthError() {
1081 ASSERT_TRUE(ServerSupportsErrorTriggering());
1082 std::string path = "chromiumsync/xmppcred";
1083 ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
1086 void SyncTest::TriggerCreateSyncedBookmarks() {
1087 ASSERT_TRUE(ServerSupportsErrorTriggering());
1088 std::string path = "chromiumsync/createsyncedbookmarks";
1089 ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path));
1090 ASSERT_EQ("Synced Bookmarks",
1091 base::UTF16ToASCII(
1092 browser()->tab_strip_model()->GetActiveWebContents()->
1093 GetTitle()));
1096 void SyncTest::SetupNetwork(net::URLRequestContextGetter* context_getter) {
1097 base::WaitableEvent done(false, false);
1098 BrowserThread::PostTask(
1099 BrowserThread::IO, FROM_HERE,
1100 base::Bind(&SetupNetworkCallback, &done,
1101 make_scoped_refptr(context_getter)));
1102 done.Wait();
1105 fake_server::FakeServer* SyncTest::GetFakeServer() const {
1106 return fake_server_.get();
1109 void SyncTest::TriggerSyncForModelTypes(int index,
1110 syncer::ModelTypeSet model_types) {
1111 content::NotificationService::current()->Notify(
1112 chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
1113 content::Source<Profile>(GetProfile(index)),
1114 content::Details<const syncer::ModelTypeSet>(&model_types));
1117 void SyncTest::SetPreexistingPreferencesFileContents(
1118 const std::string& contents) {
1119 preexisting_preferences_file_contents_ = contents;