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