two_client_apps_sync_test.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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 "base/basictypes.h" 6#include "base/strings/utf_string_conversions.h" 7#include "chrome/browser/chrome_notification_types.h" 8#include "chrome/browser/extensions/app_sync_data.h" 9#include "chrome/browser/extensions/bookmark_app_helper.h" 10#include "chrome/browser/extensions/extension_service.h" 11#include "chrome/browser/extensions/extension_sync_service.h" 12#include "chrome/browser/extensions/launch_util.h" 13#include "chrome/browser/profiles/profile.h" 14#include "chrome/browser/sync/test/integration/apps_helper.h" 15#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" 16#include "chrome/browser/sync/test/integration/sync_app_helper.h" 17#include "chrome/browser/sync/test/integration/sync_integration_test_util.h" 18#include "chrome/browser/sync/test/integration/sync_test.h" 19#include "chrome/common/extensions/extension_constants.h" 20#include "content/public/browser/notification_service.h" 21#include "content/public/test/test_utils.h" 22#include "extensions/browser/app_sorting.h" 23#include "extensions/browser/extension_prefs.h" 24#include "extensions/browser/extension_registry.h" 25#include "extensions/browser/extension_system.h" 26#include "sync/api/string_ordinal.h" 27 28using apps_helper::AllProfilesHaveSameAppsAsVerifier; 29using apps_helper::CopyNTPOrdinals; 30using apps_helper::DisableApp; 31using apps_helper::EnableApp; 32using apps_helper::FixNTPOrdinalCollisions; 33using apps_helper::GetAppLaunchOrdinalForApp; 34using apps_helper::HasSameAppsAsVerifier; 35using apps_helper::IncognitoDisableApp; 36using apps_helper::IncognitoEnableApp; 37using apps_helper::InstallApp; 38using apps_helper::InstallPlatformApp; 39using apps_helper::SetAppLaunchOrdinalForApp; 40using apps_helper::SetPageOrdinalForApp; 41using apps_helper::UninstallApp; 42using apps_helper::AwaitAllProfilesHaveSameAppsAsVerifier; 43 44namespace { 45 46extensions::ExtensionRegistry* GetExtensionRegistry(Profile* profile) { 47 return extensions::ExtensionRegistry::Get(profile); 48} 49 50ExtensionService* GetExtensionService(Profile* profile) { 51 return extensions::ExtensionSystem::Get(profile)->extension_service(); 52} 53 54} // namespace 55 56class TwoClientAppsSyncTest : public SyncTest { 57 public: 58 TwoClientAppsSyncTest() : SyncTest(TWO_CLIENT) {} 59 60 virtual ~TwoClientAppsSyncTest() {} 61 62 virtual bool TestUsesSelfNotifications() OVERRIDE { return false; } 63 64 private: 65 DISALLOW_COPY_AND_ASSIGN(TwoClientAppsSyncTest); 66}; 67 68IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, StartWithNoApps) { 69 ASSERT_TRUE(SetupSync()); 70 71 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 72} 73 74IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, StartWithSameApps) { 75 ASSERT_TRUE(SetupClients()); 76 77 const int kNumApps = 5; 78 for (int i = 0; i < kNumApps; ++i) { 79 InstallApp(GetProfile(0), i); 80 InstallApp(GetProfile(1), i); 81 InstallApp(verifier(), i); 82 } 83 84 ASSERT_TRUE(SetupSync()); 85 86 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 87} 88 89// Install some apps on both clients, some on only one client, some on only the 90// other, and sync. Both clients should end up with all apps, and the app and 91// page ordinals should be identical. 92IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, StartWithDifferentApps) { 93 ASSERT_TRUE(SetupClients()); 94 95 int i = 0; 96 97 const int kNumCommonApps = 5; 98 for (int j = 0; j < kNumCommonApps; ++i, ++j) { 99 InstallApp(GetProfile(0), i); 100 InstallApp(GetProfile(1), i); 101 InstallApp(verifier(), i); 102 } 103 104 const int kNumProfile0Apps = 10; 105 for (int j = 0; j < kNumProfile0Apps; ++i, ++j) { 106 InstallApp(GetProfile(0), i); 107 InstallApp(verifier(), i); 108 CopyNTPOrdinals(GetProfile(0), verifier(), i); 109 } 110 111 const int kNumProfile1Apps = 10; 112 for (int j = 0; j < kNumProfile1Apps; ++i, ++j) { 113 InstallApp(GetProfile(1), i); 114 InstallApp(verifier(), i); 115 CopyNTPOrdinals(GetProfile(1), verifier(), i); 116 } 117 118 const int kNumPlatformApps = 5; 119 for (int j = 0; j < kNumPlatformApps; ++i, ++j) { 120 InstallPlatformApp(GetProfile(1), i); 121 InstallPlatformApp(verifier(), i); 122 CopyNTPOrdinals(GetProfile(1), verifier(), i); 123 } 124 125 FixNTPOrdinalCollisions(verifier()); 126 127 ASSERT_TRUE(SetupSync()); 128 129 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 130} 131 132// Install some apps on both clients, then sync. Then install some apps on only 133// one client, some on only the other, and then sync again. Both clients should 134// end up with all apps, and the app and page ordinals should be identical. 135IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, InstallDifferentApps) { 136 ASSERT_TRUE(SetupClients()); 137 138 int i = 0; 139 140 const int kNumCommonApps = 5; 141 for (int j = 0; j < kNumCommonApps; ++i, ++j) { 142 InstallApp(GetProfile(0), i); 143 InstallApp(GetProfile(1), i); 144 InstallApp(verifier(), i); 145 } 146 147 ASSERT_TRUE(SetupSync()); 148 149 const int kNumProfile0Apps = 10; 150 for (int j = 0; j < kNumProfile0Apps; ++i, ++j) { 151 InstallApp(GetProfile(0), i); 152 InstallApp(verifier(), i); 153 CopyNTPOrdinals(GetProfile(0), verifier(), i); 154 } 155 156 const int kNumProfile1Apps = 10; 157 for (int j = 0; j < kNumProfile1Apps; ++i, ++j) { 158 InstallApp(GetProfile(1), i); 159 InstallApp(verifier(), i); 160 CopyNTPOrdinals(GetProfile(1), verifier(), i); 161 } 162 163 FixNTPOrdinalCollisions(verifier()); 164 165 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 166} 167 168// TCM ID - 3711279. 169IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, Add) { 170 ASSERT_TRUE(SetupSync()); 171 ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); 172 173 InstallApp(GetProfile(0), 0); 174 InstallApp(verifier(), 0); 175 176 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 177} 178 179// TCM ID - 3706267. 180IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, Uninstall) { 181 ASSERT_TRUE(SetupSync()); 182 ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); 183 184 InstallApp(GetProfile(0), 0); 185 InstallApp(verifier(), 0); 186 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 187 188 UninstallApp(GetProfile(0), 0); 189 UninstallApp(verifier(), 0); 190 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 191} 192 193// Install an app on one client, then sync. Then uninstall the app on the first 194// client and sync again. Now install a new app on the first client and sync. 195// Both client should only have the second app, with identical app and page 196// ordinals. 197IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, UninstallThenInstall) { 198 ASSERT_TRUE(SetupSync()); 199 200 ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); 201 202 InstallApp(GetProfile(0), 0); 203 InstallApp(verifier(), 0); 204 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 205 206 UninstallApp(GetProfile(0), 0); 207 UninstallApp(verifier(), 0); 208 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 209 210 InstallApp(GetProfile(0), 1); 211 InstallApp(verifier(), 1); 212 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 213} 214 215// TCM ID - 3699295. 216IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, Merge) { 217 ASSERT_TRUE(SetupSync()); 218 ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); 219 220 InstallApp(GetProfile(0), 0); 221 InstallApp(verifier(), 0); 222 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 223 224 UninstallApp(GetProfile(0), 0); 225 UninstallApp(verifier(), 0); 226 227 InstallApp(GetProfile(0), 1); 228 InstallApp(verifier(), 1); 229 230 InstallApp(GetProfile(0), 2); 231 InstallApp(GetProfile(1), 2); 232 InstallApp(verifier(), 2); 233 234 InstallApp(GetProfile(1), 3); 235 InstallApp(verifier(), 3); 236 237 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 238} 239 240// TCM ID - 7723126. 241IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, UpdateEnableDisableApp) { 242 ASSERT_TRUE(SetupSync()); 243 ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); 244 245 InstallApp(GetProfile(0), 0); 246 InstallApp(verifier(), 0); 247 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 248 249 DisableApp(GetProfile(0), 0); 250 DisableApp(verifier(), 0); 251 ASSERT_TRUE(HasSameAppsAsVerifier(0)); 252 ASSERT_FALSE(HasSameAppsAsVerifier(1)); 253 254 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 255 256 EnableApp(GetProfile(1), 0); 257 EnableApp(verifier(), 0); 258 ASSERT_TRUE(HasSameAppsAsVerifier(1)); 259 ASSERT_FALSE(HasSameAppsAsVerifier(0)); 260 261 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 262} 263 264// TCM ID - 7706637. 265IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, UpdateIncognitoEnableDisable) { 266 ASSERT_TRUE(SetupSync()); 267 ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); 268 269 InstallApp(GetProfile(0), 0); 270 InstallApp(verifier(), 0); 271 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 272 273 IncognitoEnableApp(GetProfile(0), 0); 274 IncognitoEnableApp(verifier(), 0); 275 ASSERT_TRUE(HasSameAppsAsVerifier(0)); 276 ASSERT_FALSE(HasSameAppsAsVerifier(1)); 277 278 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 279 280 IncognitoDisableApp(GetProfile(1), 0); 281 IncognitoDisableApp(verifier(), 0); 282 ASSERT_TRUE(HasSameAppsAsVerifier(1)); 283 ASSERT_FALSE(HasSameAppsAsVerifier(0)); 284 285 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 286} 287 288// Install the same app on both clients, then sync. Change the page ordinal on 289// one client and sync. Both clients should have the updated page ordinal for 290// the app. 291IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, UpdatePageOrdinal) { 292 ASSERT_TRUE(SetupSync()); 293 ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); 294 295 syncer::StringOrdinal initial_page = 296 syncer::StringOrdinal::CreateInitialOrdinal(); 297 InstallApp(GetProfile(0), 0); 298 InstallApp(verifier(), 0); 299 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 300 301 syncer::StringOrdinal second_page = initial_page.CreateAfter(); 302 SetPageOrdinalForApp(GetProfile(0), 0, second_page); 303 SetPageOrdinalForApp(verifier(), 0, second_page); 304 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 305} 306 307// Install the same app on both clients, then sync. Change the app launch 308// ordinal on one client and sync. Both clients should have the updated app 309// launch ordinal for the app. 310IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, UpdateAppLaunchOrdinal) { 311 ASSERT_TRUE(SetupSync()); 312 ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); 313 314 InstallApp(GetProfile(0), 0); 315 InstallApp(verifier(), 0); 316 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 317 318 syncer::StringOrdinal initial_position = 319 GetAppLaunchOrdinalForApp(GetProfile(0), 0); 320 321 syncer::StringOrdinal second_position = initial_position.CreateAfter(); 322 SetAppLaunchOrdinalForApp(GetProfile(0), 0, second_position); 323 SetAppLaunchOrdinalForApp(verifier(), 0, second_position); 324 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 325} 326 327// Adjust the CWS location within a page on the first client and sync. Adjust 328// which page the CWS appears on and sync. Both clients should have the same 329// page and app launch ordinal values for the CWS. 330IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, UpdateCWSOrdinals) { 331 ASSERT_TRUE(SetupSync()); 332 ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); 333 334 // Change the app launch ordinal. 335 syncer::StringOrdinal cws_app_launch_ordinal = 336 extensions::ExtensionPrefs::Get(GetProfile(0)) 337 ->app_sorting() 338 ->GetAppLaunchOrdinal(extension_misc::kWebStoreAppId); 339 extensions::ExtensionPrefs::Get(GetProfile(0)) 340 ->app_sorting() 341 ->SetAppLaunchOrdinal(extension_misc::kWebStoreAppId, 342 cws_app_launch_ordinal.CreateAfter()); 343 extensions::ExtensionPrefs::Get(verifier()) 344 ->app_sorting() 345 ->SetAppLaunchOrdinal(extension_misc::kWebStoreAppId, 346 cws_app_launch_ordinal.CreateAfter()); 347 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 348 349 // Change the page ordinal. 350 syncer::StringOrdinal cws_page_ordinal = 351 extensions::ExtensionPrefs::Get(GetProfile(1)) 352 ->app_sorting() 353 ->GetPageOrdinal(extension_misc::kWebStoreAppId); 354 extensions::ExtensionPrefs::Get(GetProfile(1))->app_sorting()->SetPageOrdinal( 355 extension_misc::kWebStoreAppId, cws_page_ordinal.CreateAfter()); 356 extensions::ExtensionPrefs::Get(verifier())->app_sorting()->SetPageOrdinal( 357 extension_misc::kWebStoreAppId, cws_page_ordinal.CreateAfter()); 358 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 359} 360 361// Adjust the launch type on the first client and sync. Both clients should 362// have the same launch type values for the CWS. 363IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, UpdateLaunchType) { 364 ASSERT_TRUE(SetupSync()); 365 ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); 366 367 // Change the launch type to window. 368 extensions::SetLaunchType(GetExtensionService(GetProfile(1)), 369 extension_misc::kWebStoreAppId, 370 extensions::LAUNCH_TYPE_WINDOW); 371 extensions::SetLaunchType(GetExtensionService(verifier()), 372 extension_misc::kWebStoreAppId, 373 extensions::LAUNCH_TYPE_WINDOW); 374 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 375 376 // Change the launch type to regular tab. 377 extensions::SetLaunchType(GetExtensionService(GetProfile(1)), 378 extension_misc::kWebStoreAppId, 379 extensions::LAUNCH_TYPE_REGULAR); 380 ASSERT_FALSE(HasSameAppsAsVerifier(1)); 381 extensions::SetLaunchType(GetExtensionService(verifier()), 382 extension_misc::kWebStoreAppId, 383 extensions::LAUNCH_TYPE_REGULAR); 384 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 385} 386 387IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, UnexpectedLaunchType) { 388 ASSERT_TRUE(SetupSync()); 389 ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); 390 391 extensions::SetLaunchType(GetExtensionService(GetProfile(1)), 392 extension_misc::kWebStoreAppId, 393 extensions::LAUNCH_TYPE_REGULAR); 394 extensions::SetLaunchType(GetExtensionService(verifier()), 395 extension_misc::kWebStoreAppId, 396 extensions::LAUNCH_TYPE_REGULAR); 397 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 398 399 const extensions::Extension* extension = 400 GetExtensionRegistry(GetProfile(1))->GetExtensionById( 401 extension_misc::kWebStoreAppId, 402 extensions::ExtensionRegistry::EVERYTHING); 403 ASSERT_TRUE(extension); 404 405 ExtensionSyncService* extension_sync_service = 406 ExtensionSyncService::Get(GetProfile(1)); 407 408 extensions::AppSyncData original_data( 409 extension_sync_service->GetAppSyncData(*extension)); 410 411 // Create an invalid launch type and ensure it doesn't get down-synced. This 412 // simulates the case of a future launch type being added which old versions 413 // don't yet understand. 414 extensions::AppSyncData invalid_launch_type_data( 415 *extension, 416 original_data.extension_sync_data().enabled(), 417 original_data.extension_sync_data().incognito_enabled(), 418 original_data.extension_sync_data().remote_install(), 419 original_data.app_launch_ordinal(), 420 original_data.page_ordinal(), 421 extensions::NUM_LAUNCH_TYPES); 422 extension_sync_service->ProcessAppSyncData(invalid_launch_type_data); 423 424 // The launch type should remain the same. 425 ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); 426} 427 428IN_PROC_BROWSER_TEST_F(TwoClientAppsSyncTest, BookmarkApp) { 429 ASSERT_TRUE(SetupSync()); 430 ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); 431 432 size_t num_extensions = 433 GetExtensionRegistry(GetProfile(0))->enabled_extensions().size(); 434 435 WebApplicationInfo web_app_info; 436 web_app_info.app_url = GURL("http://www.chromium.org"); 437 web_app_info.title = base::UTF8ToUTF16("Test name"); 438 web_app_info.description = base::UTF8ToUTF16("Test description"); 439 ++num_extensions; 440 { 441 content::WindowedNotificationObserver windowed_observer( 442 extensions::NOTIFICATION_CRX_INSTALLER_DONE, 443 content::NotificationService::AllSources()); 444 extensions::CreateOrUpdateBookmarkApp(GetExtensionService(GetProfile(0)), 445 web_app_info); 446 windowed_observer.Wait(); 447 EXPECT_EQ(num_extensions, 448 GetExtensionRegistry(GetProfile(0))->enabled_extensions().size()); 449 } 450 { 451 content::WindowedNotificationObserver windowed_observer( 452 extensions::NOTIFICATION_CRX_INSTALLER_DONE, 453 content::NotificationService::AllSources()); 454 extensions::CreateOrUpdateBookmarkApp(GetExtensionService(verifier()), 455 web_app_info); 456 windowed_observer.Wait(); 457 EXPECT_EQ(num_extensions, 458 GetExtensionRegistry(verifier())->enabled_extensions().size()); 459 } 460 { 461 // Wait for the synced app to install. 462 content::WindowedNotificationObserver windowed_observer( 463 extensions::NOTIFICATION_CRX_INSTALLER_DONE, 464 base::Bind(&AllProfilesHaveSameAppsAsVerifier)); 465 windowed_observer.Wait(); 466 } 467} 468 469// TODO(akalin): Add tests exercising: 470// - Offline installation/uninstallation behavior 471// - App-specific properties 472