// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/command_line.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/background/background_mode_manager.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/extensions/extension_function_test_utils.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/profiles/profile_info_cache.h" #include "chrome/browser/status_icons/status_icon_menu_model.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_unittest_util.h" #include "ui/message_center/message_center.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/login/users/user_manager.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/device_settings_service.h" #endif class BackgroundModeManagerTest : public testing::Test { public: BackgroundModeManagerTest() {} virtual ~BackgroundModeManagerTest() {} virtual void SetUp() { command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM)); } scoped_ptr command_line_; protected: scoped_refptr CreateExtension( extensions::Manifest::Location location, const std::string& data, const std::string& id) { scoped_ptr parsed_manifest( extension_function_test_utils::ParseDictionary(data)); return extension_function_test_utils::CreateExtension( location, parsed_manifest.get(), id); } scoped_ptr CreateTestingProfileManager() { scoped_ptr profile_manager (new TestingProfileManager(TestingBrowserProcess::GetGlobal())); EXPECT_TRUE(profile_manager->SetUp()); return profile_manager.Pass(); } // From views::MenuModelAdapter::IsCommandEnabled with modification. bool IsCommandEnabled(ui::MenuModel* model, int id) const { int index = 0; if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) return model->IsEnabledAt(index); return false; } private: DISALLOW_COPY_AND_ASSIGN(BackgroundModeManagerTest); }; class TestBackgroundModeManager : public BackgroundModeManager { public: TestBackgroundModeManager( CommandLine* command_line, ProfileInfoCache* cache, bool enabled) : BackgroundModeManager(command_line, cache), enabled_(enabled), app_count_(0), profile_app_count_(0), have_status_tray_(false), launch_on_startup_(false) { ResumeBackgroundMode(); } virtual void EnableLaunchOnStartup(bool launch) OVERRIDE { launch_on_startup_ = launch; } virtual void DisplayAppInstalledNotification( const extensions::Extension* extension) OVERRIDE {} virtual void CreateStatusTrayIcon() OVERRIDE { have_status_tray_ = true; } virtual void RemoveStatusTrayIcon() OVERRIDE { have_status_tray_ = false; } virtual int GetBackgroundAppCount() const OVERRIDE { return app_count_; } virtual int GetBackgroundAppCountForProfile( Profile* const profile) const OVERRIDE { return profile_app_count_; } virtual bool IsBackgroundModePrefEnabled() const OVERRIDE { return enabled_; } void SetBackgroundAppCount(int count) { app_count_ = count; } void SetBackgroundAppCountForProfile(int count) { profile_app_count_ = count; } void SetEnabled(bool enabled) { enabled_ = enabled; OnBackgroundModeEnabledPrefChanged(); } bool HaveStatusTray() const { return have_status_tray_; } bool IsLaunchOnStartup() const { return launch_on_startup_; } private: bool enabled_; int app_count_; int profile_app_count_; // Flags to track whether we are launching on startup/have a status tray. bool have_status_tray_; bool launch_on_startup_; }; class TestStatusIcon : public StatusIcon { virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE {} virtual void SetPressedImage(const gfx::ImageSkia& image) OVERRIDE {} virtual void SetToolTip(const base::string16& tool_tip) OVERRIDE {} virtual void DisplayBalloon(const gfx::ImageSkia& icon, const base::string16& title, const base::string16& contents) OVERRIDE {} virtual void UpdatePlatformContextMenu( StatusIconMenuModel* menu) OVERRIDE {} }; static void AssertBackgroundModeActive( const TestBackgroundModeManager& manager) { EXPECT_TRUE(chrome::WillKeepAlive()); EXPECT_TRUE(manager.HaveStatusTray()); EXPECT_TRUE(manager.IsLaunchOnStartup()); } static void AssertBackgroundModeInactive( const TestBackgroundModeManager& manager) { EXPECT_FALSE(chrome::WillKeepAlive()); EXPECT_FALSE(manager.HaveStatusTray()); EXPECT_FALSE(manager.IsLaunchOnStartup()); } static void AssertBackgroundModeSuspended( const TestBackgroundModeManager& manager) { EXPECT_FALSE(chrome::WillKeepAlive()); EXPECT_FALSE(manager.HaveStatusTray()); EXPECT_TRUE(manager.IsLaunchOnStartup()); } TEST_F(BackgroundModeManagerTest, BackgroundAppLoadUnload) { scoped_ptr profile_manager = CreateTestingProfileManager(); TestingProfile* profile = profile_manager->CreateTestingProfile("p1"); TestBackgroundModeManager manager( command_line_.get(), profile_manager->profile_info_cache(), true); manager.RegisterProfile(profile); EXPECT_FALSE(chrome::WillKeepAlive()); // Mimic app load. manager.OnBackgroundAppInstalled(NULL); manager.SetBackgroundAppCount(1); manager.OnApplicationListChanged(profile); AssertBackgroundModeActive(manager); manager.SuspendBackgroundMode(); AssertBackgroundModeSuspended(manager); manager.ResumeBackgroundMode(); // Mimic app unload. manager.SetBackgroundAppCount(0); manager.OnApplicationListChanged(profile); AssertBackgroundModeInactive(manager); manager.SuspendBackgroundMode(); AssertBackgroundModeInactive(manager); // Mimic app load while suspended, e.g. from sync. This should enable and // resume background mode. manager.OnBackgroundAppInstalled(NULL); manager.SetBackgroundAppCount(1); manager.OnApplicationListChanged(profile); AssertBackgroundModeActive(manager); } // App installs while background mode is disabled should do nothing. TEST_F(BackgroundModeManagerTest, BackgroundAppInstallUninstallWhileDisabled) { scoped_ptr profile_manager = CreateTestingProfileManager(); TestingProfile* profile = profile_manager->CreateTestingProfile("p1"); TestBackgroundModeManager manager( command_line_.get(), profile_manager->profile_info_cache(), true); manager.RegisterProfile(profile); // Turn off background mode. manager.SetEnabled(false); manager.DisableBackgroundMode(); AssertBackgroundModeInactive(manager); // Status tray icons will not be created, launch on startup status will not // be modified. manager.OnBackgroundAppInstalled(NULL); manager.SetBackgroundAppCount(1); manager.OnApplicationListChanged(profile); AssertBackgroundModeInactive(manager); manager.SetBackgroundAppCount(0); manager.OnApplicationListChanged(profile); AssertBackgroundModeInactive(manager); // Re-enable background mode. manager.SetEnabled(true); manager.EnableBackgroundMode(); AssertBackgroundModeInactive(manager); } // App installs while disabled should do nothing until background mode is // enabled.. TEST_F(BackgroundModeManagerTest, EnableAfterBackgroundAppInstall) { scoped_ptr profile_manager = CreateTestingProfileManager(); TestingProfile* profile = profile_manager->CreateTestingProfile("p1"); TestBackgroundModeManager manager( command_line_.get(), profile_manager->profile_info_cache(), true); manager.RegisterProfile(profile); // Install app, should show status tray icon. manager.OnBackgroundAppInstalled(NULL); // OnBackgroundAppInstalled does not actually add an app to the // BackgroundApplicationListModel which would result in another // call to CreateStatusTray. manager.SetBackgroundAppCount(1); manager.OnApplicationListChanged(profile); AssertBackgroundModeActive(manager); // Turn off background mode - should hide status tray icon. manager.SetEnabled(false); manager.DisableBackgroundMode(); AssertBackgroundModeInactive(manager); // Turn back on background mode - again, no status tray icon // will show up since we didn't actually add anything to the list. manager.SetEnabled(true); manager.EnableBackgroundMode(); AssertBackgroundModeActive(manager); // Uninstall app, should hide status tray icon again. manager.SetBackgroundAppCount(0); manager.OnApplicationListChanged(profile); AssertBackgroundModeInactive(manager); } TEST_F(BackgroundModeManagerTest, MultiProfile) { scoped_ptr profile_manager = CreateTestingProfileManager(); TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1"); TestingProfile* profile2 = profile_manager->CreateTestingProfile("p2"); TestBackgroundModeManager manager( command_line_.get(), profile_manager->profile_info_cache(), true); manager.RegisterProfile(profile1); manager.RegisterProfile(profile2); EXPECT_FALSE(chrome::WillKeepAlive()); // Install app, should show status tray icon. manager.OnBackgroundAppInstalled(NULL); manager.SetBackgroundAppCount(1); manager.OnApplicationListChanged(profile1); AssertBackgroundModeActive(manager); // Install app for other profile, hsould show other status tray icon. manager.OnBackgroundAppInstalled(NULL); manager.SetBackgroundAppCount(2); manager.OnApplicationListChanged(profile2); AssertBackgroundModeActive(manager); // Should hide both status tray icons. manager.SetEnabled(false); manager.DisableBackgroundMode(); AssertBackgroundModeInactive(manager); // Turn back on background mode - should show both status tray icons. manager.SetEnabled(true); manager.EnableBackgroundMode(); AssertBackgroundModeActive(manager); manager.SetBackgroundAppCount(1); manager.OnApplicationListChanged(profile2); // There is still one background app alive AssertBackgroundModeActive(manager); manager.SetBackgroundAppCount(0); manager.OnApplicationListChanged(profile1); AssertBackgroundModeInactive(manager); } TEST_F(BackgroundModeManagerTest, ProfileInfoCacheStorage) { scoped_ptr profile_manager = CreateTestingProfileManager(); TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1"); TestingProfile* profile2 = profile_manager->CreateTestingProfile("p2"); TestBackgroundModeManager manager( command_line_.get(), profile_manager->profile_info_cache(), true); manager.RegisterProfile(profile1); manager.RegisterProfile(profile2); EXPECT_FALSE(chrome::WillKeepAlive()); ProfileInfoCache* cache = profile_manager->profile_info_cache(); EXPECT_EQ(2u, cache->GetNumberOfProfiles()); EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(0)); EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(1)); // Install app, should show status tray icon. manager.OnBackgroundAppInstalled(NULL); manager.SetBackgroundAppCount(1); manager.SetBackgroundAppCountForProfile(1); manager.OnApplicationListChanged(profile1); // Install app for other profile. manager.OnBackgroundAppInstalled(NULL); manager.SetBackgroundAppCount(1); manager.SetBackgroundAppCountForProfile(1); manager.OnApplicationListChanged(profile2); EXPECT_TRUE(cache->GetBackgroundStatusOfProfileAtIndex(0)); EXPECT_TRUE(cache->GetBackgroundStatusOfProfileAtIndex(1)); manager.SetBackgroundAppCountForProfile(0); manager.OnApplicationListChanged(profile1); size_t p1_index = cache->GetIndexOfProfileWithPath(profile1->GetPath()); EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(p1_index)); manager.SetBackgroundAppCountForProfile(0); manager.OnApplicationListChanged(profile2); size_t p2_index = cache->GetIndexOfProfileWithPath(profile1->GetPath()); EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(p2_index)); // Even though neither has background status on, there should still be two // profiles in the cache. EXPECT_EQ(2u, cache->GetNumberOfProfiles()); } TEST_F(BackgroundModeManagerTest, ProfileInfoCacheObserver) { scoped_ptr profile_manager = CreateTestingProfileManager(); TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1"); TestBackgroundModeManager manager( command_line_.get(), profile_manager->profile_info_cache(), true); manager.RegisterProfile(profile1); EXPECT_FALSE(chrome::WillKeepAlive()); // Install app, should show status tray icon. manager.OnBackgroundAppInstalled(NULL); manager.SetBackgroundAppCount(1); manager.SetBackgroundAppCountForProfile(1); manager.OnApplicationListChanged(profile1); manager.OnProfileNameChanged( profile1->GetPath(), manager.GetBackgroundModeData(profile1)->name()); EXPECT_EQ(base::UTF8ToUTF16("p1"), manager.GetBackgroundModeData(profile1)->name()); EXPECT_TRUE(chrome::WillKeepAlive()); TestingProfile* profile2 = profile_manager->CreateTestingProfile("p2"); manager.RegisterProfile(profile2); EXPECT_EQ(2, manager.NumberOfBackgroundModeData()); manager.OnProfileAdded(profile2->GetPath()); EXPECT_EQ(base::UTF8ToUTF16("p2"), manager.GetBackgroundModeData(profile2)->name()); manager.OnProfileWillBeRemoved(profile2->GetPath()); // Should still be in background mode after deleting profile. EXPECT_TRUE(chrome::WillKeepAlive()); EXPECT_EQ(1, manager.NumberOfBackgroundModeData()); // Check that the background mode data we think is in the map actually is. EXPECT_EQ(base::UTF8ToUTF16("p1"), manager.GetBackgroundModeData(profile1)->name()); } TEST_F(BackgroundModeManagerTest, DeleteBackgroundProfile) { // Tests whether deleting the only profile when it is a BG profile works // or not (http://crbug.com/346214). scoped_ptr profile_manager = CreateTestingProfileManager(); TestingProfile* profile = profile_manager->CreateTestingProfile("p1"); TestBackgroundModeManager manager( command_line_.get(), profile_manager->profile_info_cache(), true); manager.RegisterProfile(profile); EXPECT_FALSE(chrome::WillKeepAlive()); // Install app, should show status tray icon. manager.OnBackgroundAppInstalled(NULL); manager.SetBackgroundAppCount(1); manager.SetBackgroundAppCountForProfile(1); manager.OnApplicationListChanged(profile); manager.OnProfileNameChanged( profile->GetPath(), manager.GetBackgroundModeData(profile)->name()); EXPECT_TRUE(chrome::WillKeepAlive()); manager.SetBackgroundAppCount(0); manager.SetBackgroundAppCountForProfile(0); manager.OnProfileWillBeRemoved(profile->GetPath()); EXPECT_FALSE(chrome::WillKeepAlive()); } TEST_F(BackgroundModeManagerTest, DisableBackgroundModeUnderTestFlag) { scoped_ptr profile_manager = CreateTestingProfileManager(); TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1"); command_line_->AppendSwitch(switches::kKeepAliveForTest); TestBackgroundModeManager manager( command_line_.get(), profile_manager->profile_info_cache(), true); manager.RegisterProfile(profile1); EXPECT_TRUE(manager.ShouldBeInBackgroundMode()); manager.SetEnabled(false); EXPECT_FALSE(manager.ShouldBeInBackgroundMode()); } TEST_F(BackgroundModeManagerTest, BackgroundModeDisabledPreventsKeepAliveOnStartup) { scoped_ptr profile_manager = CreateTestingProfileManager(); TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1"); command_line_->AppendSwitch(switches::kKeepAliveForTest); TestBackgroundModeManager manager( command_line_.get(), profile_manager->profile_info_cache(), false); manager.RegisterProfile(profile1); EXPECT_FALSE(manager.ShouldBeInBackgroundMode()); } TEST_F(BackgroundModeManagerTest, BackgroundMenuGeneration) { // Aura clears notifications from the message center at shutdown. message_center::MessageCenter::Initialize(); // Required for extension service. content::TestBrowserThreadBundle thread_bundle; scoped_ptr profile_manager = CreateTestingProfileManager(); // BackgroundModeManager actually affects Chrome start/stop state, // tearing down our thread bundle before we've had chance to clean // everything up. Keeping Chrome alive prevents this. // We aren't interested in if the keep alive works correctly in this test. chrome::IncrementKeepAliveCount(); TestingProfile* profile = profile_manager->CreateTestingProfile("p"); #if defined(OS_CHROMEOS) // ChromeOS needs extra services to run in the following order. chromeos::ScopedTestDeviceSettingsService test_device_settings_service; chromeos::ScopedTestCrosSettings test_cros_settings; chromeos::ScopedTestUserManager test_user_manager; // On ChromeOS shutdown, HandleAppExitingForPlatform will call // chrome::DecrementKeepAliveCount because it assumes the aura shell // called chrome::IncrementKeepAliveCount. Simulate the call here. chrome::IncrementKeepAliveCount(); #endif scoped_refptr component_extension( CreateExtension( extensions::Manifest::COMPONENT, "{\"name\": \"Component Extension\"," "\"version\": \"1.0\"," "\"manifest_version\": 2," "\"permissions\": [\"background\"]}", "ID-1")); scoped_refptr component_extension_with_options( CreateExtension( extensions::Manifest::COMPONENT, "{\"name\": \"Component Extension with Options\"," "\"version\": \"1.0\"," "\"manifest_version\": 2," "\"permissions\": [\"background\"]," "\"options_page\": \"test.html\"}", "ID-2")); scoped_refptr regular_extension( CreateExtension( extensions::Manifest::COMMAND_LINE, "{\"name\": \"Regular Extension\", " "\"version\": \"1.0\"," "\"manifest_version\": 2," "\"permissions\": [\"background\"]}", "ID-3")); scoped_refptr regular_extension_with_options( CreateExtension( extensions::Manifest::COMMAND_LINE, "{\"name\": \"Regular Extension with Options\"," "\"version\": \"1.0\"," "\"manifest_version\": 2," "\"permissions\": [\"background\"]," "\"options_page\": \"test.html\"}", "ID-4")); static_cast( extensions::ExtensionSystem::Get(profile))->CreateExtensionService( CommandLine::ForCurrentProcess(), base::FilePath(), false); ExtensionService* service = profile->GetExtensionService(); service->Init(); service->AddComponentExtension(component_extension); service->AddComponentExtension(component_extension_with_options); service->AddExtension(regular_extension); service->AddExtension(regular_extension_with_options); scoped_ptr manager(new TestBackgroundModeManager( command_line_.get(), profile_manager->profile_info_cache(), true)); manager->RegisterProfile(profile); scoped_ptr menu(new StatusIconMenuModel(NULL)); scoped_ptr submenu(new StatusIconMenuModel(NULL)); BackgroundModeManager::BackgroundModeData* bmd = manager->GetBackgroundModeData(profile); bmd->BuildProfileMenu(submenu.get(), menu.get()); EXPECT_TRUE( submenu->GetLabelAt(0) == base::UTF8ToUTF16("Component Extension")); EXPECT_FALSE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(0))); EXPECT_TRUE( submenu->GetLabelAt(1) == base::UTF8ToUTF16("Component Extension with Options")); EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(1))); EXPECT_TRUE( submenu->GetLabelAt(2) == base::UTF8ToUTF16("Regular Extension")); EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(2))); EXPECT_TRUE( submenu->GetLabelAt(3) == base::UTF8ToUTF16("Regular Extension with Options")); EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(3))); // We have to destroy the profile now because we created it with real thread // state. This causes a lot of machinery to spin up that stops working // when we tear down our thread state at the end of the test. profile_manager->DeleteTestingProfile("p"); // We're getting ready to shutdown the message loop. Clear everything out! base::MessageLoop::current()->RunUntilIdle(); chrome::DecrementKeepAliveCount(); // Matching the above // chrome::IncrementKeepAliveCount(). // TestBackgroundModeManager has dependencies on the infrastructure. // It should get cleared first. manager.reset(); // The Profile Manager references the Browser Process. // The Browser Process references the Notification UI Manager. // The Notification UI Manager references the Message Center. // As a result, we have to clear the browser process state here // before tearing down the Message Center. profile_manager.reset(); // Message Center shutdown must occur after the DecrementKeepAliveCount // because DecrementKeepAliveCount will end up referencing the message // center during cleanup. message_center::MessageCenter::Shutdown(); // Clear the shutdown flag to isolate the remaining effect of this test. browser_shutdown::SetTryingToQuit(false); } TEST_F(BackgroundModeManagerTest, BackgroundMenuGenerationMultipleProfile) { // Aura clears notifications from the message center at shutdown. message_center::MessageCenter::Initialize(); // Required for extension service. content::TestBrowserThreadBundle thread_bundle; scoped_ptr profile_manager = CreateTestingProfileManager(); // BackgroundModeManager actually affects Chrome start/stop state, // tearing down our thread bundle before we've had chance to clean // everything up. Keeping Chrome alive prevents this. // We aren't interested in if the keep alive works correctly in this test. chrome::IncrementKeepAliveCount(); TestingProfile* profile1 = profile_manager->CreateTestingProfile("p1"); TestingProfile* profile2 = profile_manager->CreateTestingProfile("p2"); #if defined(OS_CHROMEOS) // ChromeOS needs extensionsra services to run in the following order. chromeos::ScopedTestDeviceSettingsService test_device_settings_service; chromeos::ScopedTestCrosSettings test_cros_settings; chromeos::ScopedTestUserManager test_user_manager; // On ChromeOS shutdown, HandleAppExitingForPlatform will call // chrome::DecrementKeepAliveCount because it assumes the aura shell // called chrome::IncrementKeepAliveCount. Simulate the call here. chrome::IncrementKeepAliveCount(); #endif scoped_refptr component_extension( CreateExtension( extensions::Manifest::COMPONENT, "{\"name\": \"Component Extension\"," "\"version\": \"1.0\"," "\"manifest_version\": 2," "\"permissions\": [\"background\"]}", "ID-1")); scoped_refptr component_extension_with_options( CreateExtension( extensions::Manifest::COMPONENT, "{\"name\": \"Component Extension with Options\"," "\"version\": \"1.0\"," "\"manifest_version\": 2," "\"permissions\": [\"background\"]," "\"options_page\": \"test.html\"}", "ID-2")); scoped_refptr regular_extension( CreateExtension( extensions::Manifest::COMMAND_LINE, "{\"name\": \"Regular Extension\", " "\"version\": \"1.0\"," "\"manifest_version\": 2," "\"permissions\": [\"background\"]}", "ID-3")); scoped_refptr regular_extension_with_options( CreateExtension( extensions::Manifest::COMMAND_LINE, "{\"name\": \"Regular Extension with Options\"," "\"version\": \"1.0\"," "\"manifest_version\": 2," "\"permissions\": [\"background\"]," "\"options_page\": \"test.html\"}", "ID-4")); static_cast( extensions::ExtensionSystem::Get(profile1))->CreateExtensionService( CommandLine::ForCurrentProcess(), base::FilePath(), false); ExtensionService* service1 = profile1->GetExtensionService(); service1->Init(); service1->AddComponentExtension(component_extension); service1->AddComponentExtension(component_extension_with_options); service1->AddExtension(regular_extension); service1->AddExtension(regular_extension_with_options); static_cast( extensions::ExtensionSystem::Get(profile2))->CreateExtensionService( CommandLine::ForCurrentProcess(), base::FilePath(), false); ExtensionService* service2 = profile2->GetExtensionService(); service2->Init(); service2->AddComponentExtension(component_extension); service2->AddExtension(regular_extension); service2->AddExtension(regular_extension_with_options); scoped_ptr manager(new TestBackgroundModeManager( command_line_.get(), profile_manager->profile_info_cache(), true)); manager->RegisterProfile(profile1); manager->RegisterProfile(profile2); manager->status_icon_ = new TestStatusIcon(); manager->UpdateStatusTrayIconContextMenu(); StatusIconMenuModel* context_menu = manager->context_menu_; EXPECT_TRUE(context_menu != NULL); // Background Profile Enable Checks EXPECT_TRUE(context_menu->GetLabelAt(3) == base::UTF8ToUTF16("p1")); EXPECT_TRUE( context_menu->IsCommandIdEnabled(context_menu->GetCommandIdAt(3))); EXPECT_TRUE(context_menu->GetCommandIdAt(3) == 4); EXPECT_TRUE(context_menu->GetLabelAt(4) == base::UTF8ToUTF16("p2")); EXPECT_TRUE( context_menu->IsCommandIdEnabled(context_menu->GetCommandIdAt(4))); EXPECT_TRUE(context_menu->GetCommandIdAt(4) == 8); // Profile 1 Submenu Checks StatusIconMenuModel* profile1_submenu = static_cast(context_menu->GetSubmenuModelAt(3)); EXPECT_TRUE( profile1_submenu->GetLabelAt(0) == base::UTF8ToUTF16("Component Extension")); EXPECT_FALSE( profile1_submenu->IsCommandIdEnabled( profile1_submenu->GetCommandIdAt(0))); EXPECT_TRUE(profile1_submenu->GetCommandIdAt(0) == 0); EXPECT_TRUE( profile1_submenu->GetLabelAt(1) == base::UTF8ToUTF16("Component Extension with Options")); EXPECT_TRUE( profile1_submenu->IsCommandIdEnabled( profile1_submenu->GetCommandIdAt(1))); EXPECT_TRUE(profile1_submenu->GetCommandIdAt(1) == 1); EXPECT_TRUE( profile1_submenu->GetLabelAt(2) == base::UTF8ToUTF16("Regular Extension")); EXPECT_TRUE( profile1_submenu->IsCommandIdEnabled( profile1_submenu->GetCommandIdAt(2))); EXPECT_TRUE(profile1_submenu->GetCommandIdAt(2) == 2); EXPECT_TRUE( profile1_submenu->GetLabelAt(3) == base::UTF8ToUTF16("Regular Extension with Options")); EXPECT_TRUE( profile1_submenu->IsCommandIdEnabled( profile1_submenu->GetCommandIdAt(3))); EXPECT_TRUE(profile1_submenu->GetCommandIdAt(3) == 3); // Profile 2 Submenu Checks StatusIconMenuModel* profile2_submenu = static_cast(context_menu->GetSubmenuModelAt(4)); EXPECT_TRUE( profile2_submenu->GetLabelAt(0) == base::UTF8ToUTF16("Component Extension")); EXPECT_FALSE( profile2_submenu->IsCommandIdEnabled( profile2_submenu->GetCommandIdAt(0))); EXPECT_TRUE(profile2_submenu->GetCommandIdAt(0) == 5); EXPECT_TRUE( profile2_submenu->GetLabelAt(1) == base::UTF8ToUTF16("Regular Extension")); EXPECT_TRUE( profile2_submenu->IsCommandIdEnabled( profile2_submenu->GetCommandIdAt(1))); EXPECT_TRUE(profile2_submenu->GetCommandIdAt(1) == 6); EXPECT_TRUE( profile2_submenu->GetLabelAt(2) == base::UTF8ToUTF16("Regular Extension with Options")); EXPECT_TRUE( profile2_submenu->IsCommandIdEnabled( profile2_submenu->GetCommandIdAt(2))); EXPECT_TRUE(profile2_submenu->GetCommandIdAt(2) == 7); // Model Adapter Checks for crbug.com/315164 // P1: Profile 1 Menu Item // P2: Profile 2 Menu Item // CE: Component Extension Menu Item // CEO: Component Extenison with Options Menu Item // RE: Regular Extension Menu Item // REO: Regular Extension with Options Menu Item EXPECT_FALSE(IsCommandEnabled(context_menu, 0)); // P1 - CE EXPECT_TRUE(IsCommandEnabled(context_menu, 1)); // P1 - CEO EXPECT_TRUE(IsCommandEnabled(context_menu, 2)); // P1 - RE EXPECT_TRUE(IsCommandEnabled(context_menu, 3)); // P1 - REO EXPECT_TRUE(IsCommandEnabled(context_menu, 4)); // P1 EXPECT_FALSE(IsCommandEnabled(context_menu, 5)); // P2 - CE EXPECT_TRUE(IsCommandEnabled(context_menu, 6)); // P2 - RE EXPECT_TRUE(IsCommandEnabled(context_menu, 7)); // P2 - REO EXPECT_TRUE(IsCommandEnabled(context_menu, 8)); // P2 // Clean up the status icon. If this is not done before profile deletes, // the context menu updates will DCHECK with the now deleted profiles. StatusIcon* status_icon = manager->status_icon_; manager->status_icon_ = NULL; delete status_icon; // We have to destroy the profiles now because we created them with real // thread state. This causes a lot of machinery to spin up that stops working // when we tear down our thread state at the end of the test. profile_manager->DeleteTestingProfile("p2"); profile_manager->DeleteTestingProfile("p1"); // We're getting ready to shutdown the message loop. Clear everything out! base::MessageLoop::current()->RunUntilIdle(); chrome::DecrementKeepAliveCount(); // Matching the above // chrome::IncrementKeepAliveCount(). // TestBackgroundModeManager has dependencies on the infrastructure. // It should get cleared first. manager.reset(); // The Profile Manager references the Browser Process. // The Browser Process references the Notification UI Manager. // The Notification UI Manager references the Message Center. // As a result, we have to clear the browser process state here // before tearing down the Message Center. profile_manager.reset(); // Message Center shutdown must occur after the DecrementKeepAliveCount // because DecrementKeepAliveCount will end up referencing the message // center during cleanup. message_center::MessageCenter::Shutdown(); // Clear the shutdown flag to isolate the remaining effect of this test. browser_shutdown::SetTryingToQuit(false); }