1 // Copyright (c) 2011 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/command_line.h" 6 #include "base/memory/scoped_ptr.h" 7 #include "base/message_loop/message_loop.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "chrome/browser/background/background_mode_manager.h" 10 #include "chrome/browser/browser_shutdown.h" 11 #include "chrome/browser/extensions/extension_function_test_utils.h" 12 #include "chrome/browser/extensions/extension_service.h" 13 #include "chrome/browser/extensions/test_extension_system.h" 14 #include "chrome/browser/lifetime/application_lifetime.h" 15 #include "chrome/browser/profiles/profile_info_cache.h" 16 #include "chrome/browser/status_icons/status_icon_menu_model.h" 17 #include "chrome/common/chrome_switches.h" 18 #include "chrome/test/base/testing_browser_process.h" 19 #include "chrome/test/base/testing_profile.h" 20 #include "chrome/test/base/testing_profile_manager.h" 21 #include "content/public/test/test_browser_thread_bundle.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 #include "ui/gfx/image/image.h" 24 #include "ui/gfx/image/image_unittest_util.h" 25 #include "ui/message_center/message_center.h" 26 27 #if defined(OS_CHROMEOS) 28 #include "chrome/browser/chromeos/login/user_manager.h" 29 #include "chrome/browser/chromeos/settings/cros_settings.h" 30 #include "chrome/browser/chromeos/settings/device_settings_service.h" 31 #endif 32 33 class BackgroundModeManagerTest : public testing::Test { 34 public: 35 BackgroundModeManagerTest() {} 36 virtual ~BackgroundModeManagerTest() {} 37 virtual void SetUp() { 38 command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM)); 39 } 40 scoped_ptr<CommandLine> command_line_; 41 42 protected: 43 scoped_refptr<extensions::Extension> CreateExtension( 44 extensions::Manifest::Location location, 45 const std::string& data, 46 const std::string& id) { 47 scoped_ptr<base::DictionaryValue> parsed_manifest( 48 extension_function_test_utils::ParseDictionary(data)); 49 return extension_function_test_utils::CreateExtension( 50 location, 51 parsed_manifest.get(), 52 id); 53 } 54 55 scoped_ptr<TestingProfileManager> CreateTestingProfileManager() { 56 scoped_ptr<TestingProfileManager> profile_manager 57 (new TestingProfileManager(TestingBrowserProcess::GetGlobal())); 58 EXPECT_TRUE(profile_manager->SetUp()); 59 return profile_manager.Pass(); 60 } 61 62 // From views::MenuModelAdapter::IsCommandEnabled with modification. 63 bool IsCommandEnabled(ui::MenuModel* model, int id) const { 64 int index = 0; 65 if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) 66 return model->IsEnabledAt(index); 67 68 return false; 69 } 70 71 private: 72 DISALLOW_COPY_AND_ASSIGN(BackgroundModeManagerTest); 73 }; 74 75 class TestBackgroundModeManager : public BackgroundModeManager { 76 public: 77 TestBackgroundModeManager( 78 CommandLine* command_line, ProfileInfoCache* cache, bool enabled) 79 : BackgroundModeManager(command_line, cache), 80 enabled_(enabled), 81 app_count_(0), 82 profile_app_count_(0), 83 have_status_tray_(false), 84 launch_on_startup_(false) { 85 ResumeBackgroundMode(); 86 } 87 virtual void EnableLaunchOnStartup(bool launch) OVERRIDE { 88 launch_on_startup_ = launch; 89 } 90 virtual void DisplayAppInstalledNotification( 91 const extensions::Extension* extension) OVERRIDE {} 92 virtual void CreateStatusTrayIcon() OVERRIDE { have_status_tray_ = true; } 93 virtual void RemoveStatusTrayIcon() OVERRIDE { have_status_tray_ = false; } 94 virtual int GetBackgroundAppCount() const OVERRIDE { return app_count_; } 95 virtual int GetBackgroundAppCountForProfile( 96 Profile* const profile) const OVERRIDE { 97 return profile_app_count_; 98 } 99 virtual bool IsBackgroundModePrefEnabled() const OVERRIDE { return enabled_; } 100 void SetBackgroundAppCount(int count) { app_count_ = count; } 101 void SetBackgroundAppCountForProfile(int count) { 102 profile_app_count_ = count; 103 } 104 void SetEnabled(bool enabled) { 105 enabled_ = enabled; 106 OnBackgroundModeEnabledPrefChanged(); 107 } 108 bool HaveStatusTray() const { return have_status_tray_; } 109 bool IsLaunchOnStartup() const { return launch_on_startup_; } 110 private: 111 bool enabled_; 112 int app_count_; 113 int profile_app_count_; 114 115 // Flags to track whether we are launching on startup/have a status tray. 116 bool have_status_tray_; 117 bool launch_on_startup_; 118 }; 119 120 class TestStatusIcon : public StatusIcon { 121 virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE {} 122 virtual void SetPressedImage(const gfx::ImageSkia& image) OVERRIDE {} 123 virtual void SetToolTip(const base::string16& tool_tip) OVERRIDE {} 124 virtual void DisplayBalloon(const gfx::ImageSkia& icon, 125 const base::string16& title, 126 const base::string16& contents) OVERRIDE {} 127 virtual void UpdatePlatformContextMenu( 128 StatusIconMenuModel* menu) OVERRIDE {} 129 }; 130 131 static void AssertBackgroundModeActive( 132 const TestBackgroundModeManager& manager) { 133 EXPECT_TRUE(chrome::WillKeepAlive()); 134 EXPECT_TRUE(manager.HaveStatusTray()); 135 EXPECT_TRUE(manager.IsLaunchOnStartup()); 136 } 137 138 static void AssertBackgroundModeInactive( 139 const TestBackgroundModeManager& manager) { 140 EXPECT_FALSE(chrome::WillKeepAlive()); 141 EXPECT_FALSE(manager.HaveStatusTray()); 142 EXPECT_FALSE(manager.IsLaunchOnStartup()); 143 } 144 145 static void AssertBackgroundModeSuspended( 146 const TestBackgroundModeManager& manager) { 147 EXPECT_FALSE(chrome::WillKeepAlive()); 148 EXPECT_FALSE(manager.HaveStatusTray()); 149 EXPECT_TRUE(manager.IsLaunchOnStartup()); 150 } 151 152 TEST_F(BackgroundModeManagerTest, BackgroundAppLoadUnload) { 153 scoped_ptr<TestingProfileManager> profile_manager = 154 CreateTestingProfileManager(); 155 TestingProfile* profile = profile_manager->CreateTestingProfile("p1"); 156 TestBackgroundModeManager manager( 157 command_line_.get(), profile_manager->profile_info_cache(), true); 158 manager.RegisterProfile(profile); 159 EXPECT_FALSE(chrome::WillKeepAlive()); 160 161 // Mimic app load. 162 manager.OnBackgroundAppInstalled(NULL); 163 manager.SetBackgroundAppCount(1); 164 manager.OnApplicationListChanged(profile); 165 AssertBackgroundModeActive(manager); 166 167 manager.SuspendBackgroundMode(); 168 AssertBackgroundModeSuspended(manager); 169 manager.ResumeBackgroundMode(); 170 171 // Mimic app unload. 172 manager.SetBackgroundAppCount(0); 173 manager.OnApplicationListChanged(profile); 174 AssertBackgroundModeInactive(manager); 175 176 manager.SuspendBackgroundMode(); 177 AssertBackgroundModeInactive(manager); 178 179 // Mimic app load while suspended, e.g. from sync. This should enable and 180 // resume background mode. 181 manager.OnBackgroundAppInstalled(NULL); 182 manager.SetBackgroundAppCount(1); 183 manager.OnApplicationListChanged(profile); 184 AssertBackgroundModeActive(manager); 185 } 186 187 // App installs while background mode is disabled should do nothing. 188 TEST_F(BackgroundModeManagerTest, BackgroundAppInstallUninstallWhileDisabled) { 189 scoped_ptr<TestingProfileManager> profile_manager = 190 CreateTestingProfileManager(); 191 TestingProfile* profile = profile_manager->CreateTestingProfile("p1"); 192 TestBackgroundModeManager manager( 193 command_line_.get(), profile_manager->profile_info_cache(), true); 194 manager.RegisterProfile(profile); 195 // Turn off background mode. 196 manager.SetEnabled(false); 197 manager.DisableBackgroundMode(); 198 AssertBackgroundModeInactive(manager); 199 200 // Status tray icons will not be created, launch on startup status will not 201 // be modified. 202 manager.OnBackgroundAppInstalled(NULL); 203 manager.SetBackgroundAppCount(1); 204 manager.OnApplicationListChanged(profile); 205 AssertBackgroundModeInactive(manager); 206 207 manager.SetBackgroundAppCount(0); 208 manager.OnApplicationListChanged(profile); 209 AssertBackgroundModeInactive(manager); 210 211 // Re-enable background mode. 212 manager.SetEnabled(true); 213 manager.EnableBackgroundMode(); 214 AssertBackgroundModeInactive(manager); 215 } 216 217 218 // App installs while disabled should do nothing until background mode is 219 // enabled.. 220 TEST_F(BackgroundModeManagerTest, EnableAfterBackgroundAppInstall) { 221 scoped_ptr<TestingProfileManager> profile_manager = 222 CreateTestingProfileManager(); 223 TestingProfile* profile = profile_manager->CreateTestingProfile("p1"); 224 TestBackgroundModeManager manager( 225 command_line_.get(), profile_manager->profile_info_cache(), true); 226 manager.RegisterProfile(profile); 227 228 // Install app, should show status tray icon. 229 manager.OnBackgroundAppInstalled(NULL); 230 // OnBackgroundAppInstalled does not actually add an app to the 231 // BackgroundApplicationListModel which would result in another 232 // call to CreateStatusTray. 233 manager.SetBackgroundAppCount(1); 234 manager.OnApplicationListChanged(profile); 235 AssertBackgroundModeActive(manager); 236 237 // Turn off background mode - should hide status tray icon. 238 manager.SetEnabled(false); 239 manager.DisableBackgroundMode(); 240 AssertBackgroundModeInactive(manager); 241 242 // Turn back on background mode - again, no status tray icon 243 // will show up since we didn't actually add anything to the list. 244 manager.SetEnabled(true); 245 manager.EnableBackgroundMode(); 246 AssertBackgroundModeActive(manager); 247 248 // Uninstall app, should hide status tray icon again. 249 manager.SetBackgroundAppCount(0); 250 manager.OnApplicationListChanged(profile); 251 AssertBackgroundModeInactive(manager); 252 } 253 254 TEST_F(BackgroundModeManagerTest, MultiProfile) { 255 scoped_ptr<TestingProfileManager> profile_manager = 256 CreateTestingProfileManager(); 257 TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1"); 258 TestingProfile* profile2 = profile_manager->CreateTestingProfile("p2"); 259 TestBackgroundModeManager manager( 260 command_line_.get(), profile_manager->profile_info_cache(), true); 261 manager.RegisterProfile(profile1); 262 manager.RegisterProfile(profile2); 263 EXPECT_FALSE(chrome::WillKeepAlive()); 264 265 // Install app, should show status tray icon. 266 manager.OnBackgroundAppInstalled(NULL); 267 manager.SetBackgroundAppCount(1); 268 manager.OnApplicationListChanged(profile1); 269 AssertBackgroundModeActive(manager); 270 271 // Install app for other profile, hsould show other status tray icon. 272 manager.OnBackgroundAppInstalled(NULL); 273 manager.SetBackgroundAppCount(2); 274 manager.OnApplicationListChanged(profile2); 275 AssertBackgroundModeActive(manager); 276 277 // Should hide both status tray icons. 278 manager.SetEnabled(false); 279 manager.DisableBackgroundMode(); 280 AssertBackgroundModeInactive(manager); 281 282 // Turn back on background mode - should show both status tray icons. 283 manager.SetEnabled(true); 284 manager.EnableBackgroundMode(); 285 AssertBackgroundModeActive(manager); 286 287 manager.SetBackgroundAppCount(1); 288 manager.OnApplicationListChanged(profile2); 289 // There is still one background app alive 290 AssertBackgroundModeActive(manager); 291 292 manager.SetBackgroundAppCount(0); 293 manager.OnApplicationListChanged(profile1); 294 AssertBackgroundModeInactive(manager); 295 } 296 297 TEST_F(BackgroundModeManagerTest, ProfileInfoCacheStorage) { 298 scoped_ptr<TestingProfileManager> profile_manager = 299 CreateTestingProfileManager(); 300 TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1"); 301 TestingProfile* profile2 = profile_manager->CreateTestingProfile("p2"); 302 TestBackgroundModeManager manager( 303 command_line_.get(), profile_manager->profile_info_cache(), true); 304 manager.RegisterProfile(profile1); 305 manager.RegisterProfile(profile2); 306 EXPECT_FALSE(chrome::WillKeepAlive()); 307 308 ProfileInfoCache* cache = profile_manager->profile_info_cache(); 309 EXPECT_EQ(2u, cache->GetNumberOfProfiles()); 310 311 EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(0)); 312 EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(1)); 313 314 // Install app, should show status tray icon. 315 manager.OnBackgroundAppInstalled(NULL); 316 manager.SetBackgroundAppCount(1); 317 manager.SetBackgroundAppCountForProfile(1); 318 manager.OnApplicationListChanged(profile1); 319 320 // Install app for other profile. 321 manager.OnBackgroundAppInstalled(NULL); 322 manager.SetBackgroundAppCount(1); 323 manager.SetBackgroundAppCountForProfile(1); 324 manager.OnApplicationListChanged(profile2); 325 326 EXPECT_TRUE(cache->GetBackgroundStatusOfProfileAtIndex(0)); 327 EXPECT_TRUE(cache->GetBackgroundStatusOfProfileAtIndex(1)); 328 329 manager.SetBackgroundAppCountForProfile(0); 330 manager.OnApplicationListChanged(profile1); 331 332 size_t p1_index = cache->GetIndexOfProfileWithPath(profile1->GetPath()); 333 EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(p1_index)); 334 335 manager.SetBackgroundAppCountForProfile(0); 336 manager.OnApplicationListChanged(profile2); 337 338 size_t p2_index = cache->GetIndexOfProfileWithPath(profile1->GetPath()); 339 EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(p2_index)); 340 341 // Even though neither has background status on, there should still be two 342 // profiles in the cache. 343 EXPECT_EQ(2u, cache->GetNumberOfProfiles()); 344 } 345 346 TEST_F(BackgroundModeManagerTest, ProfileInfoCacheObserver) { 347 scoped_ptr<TestingProfileManager> profile_manager = 348 CreateTestingProfileManager(); 349 TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1"); 350 TestBackgroundModeManager manager( 351 command_line_.get(), profile_manager->profile_info_cache(), true); 352 manager.RegisterProfile(profile1); 353 EXPECT_FALSE(chrome::WillKeepAlive()); 354 355 // Install app, should show status tray icon. 356 manager.OnBackgroundAppInstalled(NULL); 357 manager.SetBackgroundAppCount(1); 358 manager.SetBackgroundAppCountForProfile(1); 359 manager.OnApplicationListChanged(profile1); 360 361 manager.OnProfileNameChanged( 362 profile1->GetPath(), 363 manager.GetBackgroundModeData(profile1)->name()); 364 365 EXPECT_EQ(UTF8ToUTF16("p1"), 366 manager.GetBackgroundModeData(profile1)->name()); 367 368 TestingProfile* profile2 = profile_manager->CreateTestingProfile("p2"); 369 manager.RegisterProfile(profile2); 370 EXPECT_EQ(2, manager.NumberOfBackgroundModeData()); 371 372 manager.OnProfileAdded(profile2->GetPath()); 373 EXPECT_EQ(UTF8ToUTF16("p2"), 374 manager.GetBackgroundModeData(profile2)->name()); 375 376 manager.OnProfileWillBeRemoved(profile2->GetPath()); 377 EXPECT_EQ(1, manager.NumberOfBackgroundModeData()); 378 379 // Check that the background mode data we think is in the map actually is. 380 EXPECT_EQ(UTF8ToUTF16("p1"), 381 manager.GetBackgroundModeData(profile1)->name()); 382 } 383 384 TEST_F(BackgroundModeManagerTest, DisableBackgroundModeUnderTestFlag) { 385 scoped_ptr<TestingProfileManager> profile_manager = 386 CreateTestingProfileManager(); 387 TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1"); 388 command_line_->AppendSwitch(switches::kKeepAliveForTest); 389 TestBackgroundModeManager manager( 390 command_line_.get(), profile_manager->profile_info_cache(), true); 391 manager.RegisterProfile(profile1); 392 EXPECT_TRUE(manager.ShouldBeInBackgroundMode()); 393 manager.SetEnabled(false); 394 EXPECT_FALSE(manager.ShouldBeInBackgroundMode()); 395 } 396 397 TEST_F(BackgroundModeManagerTest, 398 BackgroundModeDisabledPreventsKeepAliveOnStartup) { 399 scoped_ptr<TestingProfileManager> profile_manager = 400 CreateTestingProfileManager(); 401 TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1"); 402 command_line_->AppendSwitch(switches::kKeepAliveForTest); 403 TestBackgroundModeManager manager( 404 command_line_.get(), profile_manager->profile_info_cache(), false); 405 manager.RegisterProfile(profile1); 406 EXPECT_FALSE(manager.ShouldBeInBackgroundMode()); 407 } 408 409 TEST_F(BackgroundModeManagerTest, BackgroundMenuGeneration) { 410 // Aura clears notifications from the message center at shutdown. 411 message_center::MessageCenter::Initialize(); 412 413 // Required for extension service. 414 content::TestBrowserThreadBundle thread_bundle; 415 416 scoped_ptr<TestingProfileManager> profile_manager = 417 CreateTestingProfileManager(); 418 419 // BackgroundModeManager actually affects Chrome start/stop state, 420 // tearing down our thread bundle before we've had chance to clean 421 // everything up. Keeping Chrome alive prevents this. 422 // We aren't interested in if the keep alive works correctly in this test. 423 chrome::StartKeepAlive(); 424 TestingProfile* profile = profile_manager->CreateTestingProfile("p"); 425 426 #if defined(OS_CHROMEOS) 427 // ChromeOS needs extra services to run in the following order. 428 chromeos::ScopedTestDeviceSettingsService test_device_settings_service; 429 chromeos::ScopedTestCrosSettings test_cros_settings; 430 chromeos::ScopedTestUserManager test_user_manager; 431 432 // On ChromeOS shutdown, HandleAppExitingForPlatform will call 433 // chrome::EndKeepAlive because it assumes the aura shell 434 // called chrome::StartKeepAlive. Simulate the call here. 435 chrome::StartKeepAlive(); 436 #endif 437 438 scoped_refptr<extensions::Extension> component_extension( 439 CreateExtension( 440 extensions::Manifest::COMPONENT, 441 "{\"name\": \"Component Extension\"," 442 "\"version\": \"1.0\"," 443 "\"manifest_version\": 2," 444 "\"permissions\": [\"background\"]}", 445 "ID-1")); 446 447 scoped_refptr<extensions::Extension> component_extension_with_options( 448 CreateExtension( 449 extensions::Manifest::COMPONENT, 450 "{\"name\": \"Component Extension with Options\"," 451 "\"version\": \"1.0\"," 452 "\"manifest_version\": 2," 453 "\"permissions\": [\"background\"]," 454 "\"options_page\": \"test.html\"}", 455 "ID-2")); 456 457 scoped_refptr<extensions::Extension> regular_extension( 458 CreateExtension( 459 extensions::Manifest::COMMAND_LINE, 460 "{\"name\": \"Regular Extension\", " 461 "\"version\": \"1.0\"," 462 "\"manifest_version\": 2," 463 "\"permissions\": [\"background\"]}", 464 "ID-3")); 465 466 scoped_refptr<extensions::Extension> regular_extension_with_options( 467 CreateExtension( 468 extensions::Manifest::COMMAND_LINE, 469 "{\"name\": \"Regular Extension with Options\"," 470 "\"version\": \"1.0\"," 471 "\"manifest_version\": 2," 472 "\"permissions\": [\"background\"]," 473 "\"options_page\": \"test.html\"}", 474 "ID-4")); 475 476 static_cast<extensions::TestExtensionSystem*>( 477 extensions::ExtensionSystem::Get(profile))->CreateExtensionService( 478 CommandLine::ForCurrentProcess(), 479 base::FilePath(), 480 false); 481 ExtensionService* service = profile->GetExtensionService(); 482 service->Init(); 483 484 service->AddComponentExtension(component_extension); 485 service->AddComponentExtension(component_extension_with_options); 486 service->AddExtension(regular_extension); 487 service->AddExtension(regular_extension_with_options); 488 489 scoped_ptr<TestBackgroundModeManager> manager(new TestBackgroundModeManager( 490 command_line_.get(), profile_manager->profile_info_cache(), true)); 491 manager->RegisterProfile(profile); 492 493 scoped_ptr<StatusIconMenuModel> menu(new StatusIconMenuModel(NULL)); 494 scoped_ptr<StatusIconMenuModel> submenu(new StatusIconMenuModel(NULL)); 495 BackgroundModeManager::BackgroundModeData* bmd = 496 manager->GetBackgroundModeData(profile); 497 bmd->BuildProfileMenu(submenu.get(), menu.get()); 498 EXPECT_TRUE( 499 submenu->GetLabelAt(0) == 500 UTF8ToUTF16("Component Extension")); 501 EXPECT_FALSE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(0))); 502 EXPECT_TRUE( 503 submenu->GetLabelAt(1) == 504 UTF8ToUTF16("Component Extension with Options")); 505 EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(1))); 506 EXPECT_TRUE( 507 submenu->GetLabelAt(2) == 508 UTF8ToUTF16("Regular Extension")); 509 EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(2))); 510 EXPECT_TRUE( 511 submenu->GetLabelAt(3) == 512 UTF8ToUTF16("Regular Extension with Options")); 513 EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(3))); 514 515 // We have to destroy the profile now because we created it with real thread 516 // state. This causes a lot of machinery to spin up that stops working 517 // when we tear down our thread state at the end of the test. 518 profile_manager->DeleteTestingProfile("p"); 519 520 // We're getting ready to shutdown the message loop. Clear everything out! 521 base::MessageLoop::current()->RunUntilIdle(); 522 chrome::EndKeepAlive(); // Matching the above chrome::StartKeepAlive(). 523 524 // TestBackgroundModeManager has dependencies on the infrastructure. 525 // It should get cleared first. 526 manager.reset(); 527 528 // The Profile Manager references the Browser Process. 529 // The Browser Process references the Notification UI Manager. 530 // The Notification UI Manager references the Message Center. 531 // As a result, we have to clear the browser process state here 532 // before tearing down the Message Center. 533 profile_manager.reset(); 534 535 // Message Center shutdown must occur after the EndKeepAlive because 536 // EndKeepAlive will end up referencing the message center during cleanup. 537 message_center::MessageCenter::Shutdown(); 538 539 // Clear the shutdown flag to isolate the remaining effect of this test. 540 browser_shutdown::SetTryingToQuit(false); 541 } 542 543 TEST_F(BackgroundModeManagerTest, BackgroundMenuGenerationMultipleProfile) { 544 // Aura clears notifications from the message center at shutdown. 545 message_center::MessageCenter::Initialize(); 546 547 // Required for extension service. 548 content::TestBrowserThreadBundle thread_bundle; 549 550 scoped_ptr<TestingProfileManager> profile_manager = 551 CreateTestingProfileManager(); 552 553 // BackgroundModeManager actually affects Chrome start/stop state, 554 // tearing down our thread bundle before we've had chance to clean 555 // everything up. Keeping Chrome alive prevents this. 556 // We aren't interested in if the keep alive works correctly in this test. 557 chrome::StartKeepAlive(); 558 TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1"); 559 TestingProfile* profile2 = profile_manager->CreateTestingProfile("p2"); 560 561 #if defined(OS_CHROMEOS) 562 // ChromeOS needs extensionsra services to run in the following order. 563 chromeos::ScopedTestDeviceSettingsService test_device_settings_service; 564 chromeos::ScopedTestCrosSettings test_cros_settings; 565 chromeos::ScopedTestUserManager test_user_manager; 566 567 // On ChromeOS shutdown, HandleAppExitingForPlatform will call 568 // chrome::EndKeepAlive because it assumes the aura shell 569 // called chrome::StartKeepAlive. Simulate the call here. 570 chrome::StartKeepAlive(); 571 #endif 572 573 scoped_refptr<extensions::Extension> component_extension( 574 CreateExtension( 575 extensions::Manifest::COMPONENT, 576 "{\"name\": \"Component Extension\"," 577 "\"version\": \"1.0\"," 578 "\"manifest_version\": 2," 579 "\"permissions\": [\"background\"]}", 580 "ID-1")); 581 582 scoped_refptr<extensions::Extension> component_extension_with_options( 583 CreateExtension( 584 extensions::Manifest::COMPONENT, 585 "{\"name\": \"Component Extension with Options\"," 586 "\"version\": \"1.0\"," 587 "\"manifest_version\": 2," 588 "\"permissions\": [\"background\"]," 589 "\"options_page\": \"test.html\"}", 590 "ID-2")); 591 592 scoped_refptr<extensions::Extension> regular_extension( 593 CreateExtension( 594 extensions::Manifest::COMMAND_LINE, 595 "{\"name\": \"Regular Extension\", " 596 "\"version\": \"1.0\"," 597 "\"manifest_version\": 2," 598 "\"permissions\": [\"background\"]}", 599 "ID-3")); 600 601 scoped_refptr<extensions::Extension> regular_extension_with_options( 602 CreateExtension( 603 extensions::Manifest::COMMAND_LINE, 604 "{\"name\": \"Regular Extension with Options\"," 605 "\"version\": \"1.0\"," 606 "\"manifest_version\": 2," 607 "\"permissions\": [\"background\"]," 608 "\"options_page\": \"test.html\"}", 609 "ID-4")); 610 611 static_cast<extensions::TestExtensionSystem*>( 612 extensions::ExtensionSystem::Get(profile1))->CreateExtensionService( 613 CommandLine::ForCurrentProcess(), 614 base::FilePath(), 615 false); 616 ExtensionService* service1 = profile1->GetExtensionService(); 617 service1->Init(); 618 619 service1->AddComponentExtension(component_extension); 620 service1->AddComponentExtension(component_extension_with_options); 621 service1->AddExtension(regular_extension); 622 service1->AddExtension(regular_extension_with_options); 623 624 static_cast<extensions::TestExtensionSystem*>( 625 extensions::ExtensionSystem::Get(profile2))->CreateExtensionService( 626 CommandLine::ForCurrentProcess(), 627 base::FilePath(), 628 false); 629 ExtensionService* service2 = profile2->GetExtensionService(); 630 service2->Init(); 631 632 service2->AddComponentExtension(component_extension); 633 service2->AddExtension(regular_extension); 634 service2->AddExtension(regular_extension_with_options); 635 636 scoped_ptr<TestBackgroundModeManager> manager(new TestBackgroundModeManager( 637 command_line_.get(), profile_manager->profile_info_cache(), true)); 638 manager->RegisterProfile(profile1); 639 manager->RegisterProfile(profile2); 640 641 manager->status_icon_ = new TestStatusIcon(); 642 manager->UpdateStatusTrayIconContextMenu(); 643 StatusIconMenuModel* context_menu = manager->context_menu_; 644 EXPECT_TRUE(context_menu != NULL); 645 646 // Background Profile Enable Checks 647 EXPECT_TRUE(context_menu->GetLabelAt(3) == UTF8ToUTF16("p1")); 648 EXPECT_TRUE( 649 context_menu->IsCommandIdEnabled(context_menu->GetCommandIdAt(3))); 650 EXPECT_TRUE(context_menu->GetCommandIdAt(3) == 4); 651 652 EXPECT_TRUE(context_menu->GetLabelAt(4) == UTF8ToUTF16("p2")); 653 EXPECT_TRUE( 654 context_menu->IsCommandIdEnabled(context_menu->GetCommandIdAt(4))); 655 EXPECT_TRUE(context_menu->GetCommandIdAt(4) == 8); 656 657 // Profile 1 Submenu Checks 658 StatusIconMenuModel* profile1_submenu = 659 static_cast<StatusIconMenuModel*>(context_menu->GetSubmenuModelAt(3)); 660 EXPECT_TRUE( 661 profile1_submenu->GetLabelAt(0) == 662 UTF8ToUTF16("Component Extension")); 663 EXPECT_FALSE( 664 profile1_submenu->IsCommandIdEnabled( 665 profile1_submenu->GetCommandIdAt(0))); 666 EXPECT_TRUE(profile1_submenu->GetCommandIdAt(0) == 0); 667 EXPECT_TRUE( 668 profile1_submenu->GetLabelAt(1) == 669 UTF8ToUTF16("Component Extension with Options")); 670 EXPECT_TRUE( 671 profile1_submenu->IsCommandIdEnabled( 672 profile1_submenu->GetCommandIdAt(1))); 673 EXPECT_TRUE(profile1_submenu->GetCommandIdAt(1) == 1); 674 EXPECT_TRUE( 675 profile1_submenu->GetLabelAt(2) == 676 UTF8ToUTF16("Regular Extension")); 677 EXPECT_TRUE( 678 profile1_submenu->IsCommandIdEnabled( 679 profile1_submenu->GetCommandIdAt(2))); 680 EXPECT_TRUE(profile1_submenu->GetCommandIdAt(2) == 2); 681 EXPECT_TRUE( 682 profile1_submenu->GetLabelAt(3) == 683 UTF8ToUTF16("Regular Extension with Options")); 684 EXPECT_TRUE( 685 profile1_submenu->IsCommandIdEnabled( 686 profile1_submenu->GetCommandIdAt(3))); 687 EXPECT_TRUE(profile1_submenu->GetCommandIdAt(3) == 3); 688 689 // Profile 2 Submenu Checks 690 StatusIconMenuModel* profile2_submenu = 691 static_cast<StatusIconMenuModel*>(context_menu->GetSubmenuModelAt(4)); 692 EXPECT_TRUE( 693 profile2_submenu->GetLabelAt(0) == 694 UTF8ToUTF16("Component Extension")); 695 EXPECT_FALSE( 696 profile2_submenu->IsCommandIdEnabled( 697 profile2_submenu->GetCommandIdAt(0))); 698 EXPECT_TRUE(profile2_submenu->GetCommandIdAt(0) == 5); 699 EXPECT_TRUE( 700 profile2_submenu->GetLabelAt(1) == 701 UTF8ToUTF16("Regular Extension")); 702 EXPECT_TRUE( 703 profile2_submenu->IsCommandIdEnabled( 704 profile2_submenu->GetCommandIdAt(1))); 705 EXPECT_TRUE(profile2_submenu->GetCommandIdAt(1) == 6); 706 EXPECT_TRUE( 707 profile2_submenu->GetLabelAt(2) == 708 UTF8ToUTF16("Regular Extension with Options")); 709 EXPECT_TRUE( 710 profile2_submenu->IsCommandIdEnabled( 711 profile2_submenu->GetCommandIdAt(2))); 712 EXPECT_TRUE(profile2_submenu->GetCommandIdAt(2) == 7); 713 714 // Model Adapter Checks for crbug.com/315164 715 // P1: Profile 1 Menu Item 716 // P2: Profile 2 Menu Item 717 // CE: Component Extension Menu Item 718 // CEO: Component Extenison with Options Menu Item 719 // RE: Regular Extension Menu Item 720 // REO: Regular Extension with Options Menu Item 721 EXPECT_FALSE(IsCommandEnabled(context_menu, 0)); // P1 - CE 722 EXPECT_TRUE(IsCommandEnabled(context_menu, 1)); // P1 - CEO 723 EXPECT_TRUE(IsCommandEnabled(context_menu, 2)); // P1 - RE 724 EXPECT_TRUE(IsCommandEnabled(context_menu, 3)); // P1 - REO 725 EXPECT_TRUE(IsCommandEnabled(context_menu, 4)); // P1 726 EXPECT_FALSE(IsCommandEnabled(context_menu, 5)); // P2 - CE 727 EXPECT_TRUE(IsCommandEnabled(context_menu, 6)); // P2 - RE 728 EXPECT_TRUE(IsCommandEnabled(context_menu, 7)); // P2 - REO 729 EXPECT_TRUE(IsCommandEnabled(context_menu, 8)); // P2 730 731 // Clean up the status icon. If this is not done before profile deletes, 732 // the context menu updates will DCHECK with the now deleted profiles. 733 StatusIcon* status_icon = manager->status_icon_; 734 manager->status_icon_ = NULL; 735 delete status_icon; 736 737 // We have to destroy the profiles now because we created them with real 738 // thread state. This causes a lot of machinery to spin up that stops working 739 // when we tear down our thread state at the end of the test. 740 profile_manager->DeleteTestingProfile("p2"); 741 profile_manager->DeleteTestingProfile("p1"); 742 743 // We're getting ready to shutdown the message loop. Clear everything out! 744 base::MessageLoop::current()->RunUntilIdle(); 745 chrome::EndKeepAlive(); // Matching the above chrome::StartKeepAlive(). 746 747 // TestBackgroundModeManager has dependencies on the infrastructure. 748 // It should get cleared first. 749 manager.reset(); 750 751 // The Profile Manager references the Browser Process. 752 // The Browser Process references the Notification UI Manager. 753 // The Notification UI Manager references the Message Center. 754 // As a result, we have to clear the browser process state here 755 // before tearing down the Message Center. 756 profile_manager.reset(); 757 758 // Message Center shutdown must occur after the EndKeepAlive because 759 // EndKeepAlive will end up referencing the message center during cleanup. 760 message_center::MessageCenter::Shutdown(); 761 762 // Clear the shutdown flag to isolate the remaining effect of this test. 763 browser_shutdown::SetTryingToQuit(false); 764 } 765