diff options
Diffstat (limited to 'chrome/browser')
30 files changed, 471 insertions, 208 deletions
diff --git a/chrome/browser/background_contents_service.cc b/chrome/browser/background_contents_service.cc index 3202bac..edd3219 100644 --- a/chrome/browser/background_contents_service.cc +++ b/chrome/browser/background_contents_service.cc @@ -40,8 +40,7 @@ const char kFrameNameKey[] = "name"; BackgroundContentsService::BackgroundContentsService( Profile* profile, const CommandLine* command_line) - : prefs_(NULL), - always_keep_alive_(command_line->HasSwitch(switches::kKeepAliveForTest)) { + : prefs_(NULL) { // Don't load/store preferences if the proper switch is not enabled, or if // the parent profile is off the record. if (!profile->IsOffTheRecord() && @@ -85,14 +84,6 @@ void BackgroundContentsService::StartObserving(Profile* profile) { // BackgroundContents. registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, Source<Profile>(profile)); - - if (always_keep_alive_ && !profile->IsOffTheRecord()) { - // For testing, keep the browser process alive until there is an explicit - // shutdown. - registrar_.Add(this, NotificationType::APP_TERMINATING, - NotificationService::AllSources()); - BrowserList::StartKeepAlive(); - } } void BackgroundContentsService::Observe(NotificationType type, @@ -121,11 +112,6 @@ void BackgroundContentsService::Observe(NotificationType type, ShutdownAssociatedBackgroundContents( ASCIIToUTF16(Details<Extension>(details)->id())); break; - case NotificationType::APP_TERMINATING: - // Performing an explicit shutdown, so allow the browser process to exit. - DCHECK(always_keep_alive_); - BrowserList::EndKeepAlive(); - break; default: NOTREACHED(); break; diff --git a/chrome/browser/background_contents_service.h b/chrome/browser/background_contents_service.h index 2512c4d..e9d7df0a 100644 --- a/chrome/browser/background_contents_service.h +++ b/chrome/browser/background_contents_service.h @@ -127,10 +127,6 @@ class BackgroundContentsService : private NotificationObserver, typedef std::map<string16, BackgroundContentsInfo> BackgroundContentsMap; BackgroundContentsMap contents_map_; - // If true, should always keep the browser process alive regardless of whether - // there are any BackgroundContents (used for manual/automated testing). - bool always_keep_alive_; - DISALLOW_COPY_AND_ASSIGN(BackgroundContentsService); }; diff --git a/chrome/browser/background_mode_manager.cc b/chrome/browser/background_mode_manager.cc new file mode 100644 index 0000000..44ce468 --- /dev/null +++ b/chrome/browser/background_mode_manager.cc @@ -0,0 +1,201 @@ +// Copyright (c) 2010 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 "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "base/command_line.h" +#include "chrome/browser/background_mode_manager.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/metrics/user_metrics.h" +#include "chrome/browser/pref_service.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/status_icons/status_icon.h" +#include "chrome/browser/status_icons/status_tray.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_type.h" +#include "chrome/common/pref_names.h" +#include "grit/browser_resources.h" +#include "grit/chromium_strings.h" +#include "grit/theme_resources.h" + +BackgroundModeManager::BackgroundModeManager(Profile* profile) + : profile_(profile), + background_app_count_(0), + status_tray_(NULL) { + // If background mode is disabled for unittests, just exit - don't listen for + // any notifications. + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableBackgroundMode)) + return; + + // Only need status icons on windows/linux. ChromeOS doesn't allow exiting + // Chrome and Mac can use the dock icon instead. +#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) + status_tray_ = profile->GetStatusTray(); +#endif + + // If the -keep-alive-for-test flag is passed, then always keep chrome running + // in the background until the user explicitly terminates it. + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kKeepAliveForTest)) { + StartBackgroundMode(); + registrar_.Add(this, NotificationType::APP_TERMINATING, + NotificationService::AllSources()); + } + + // When an extension is installed, make sure launch on startup is properly + // set if appropriate. Likewise, turn off launch on startup when the last + // background app is uninstalled. + registrar_.Add(this, NotificationType::EXTENSION_INSTALLED, + Source<Profile>(profile)); + registrar_.Add(this, NotificationType::EXTENSION_UNINSTALLED, + Source<Profile>(profile)); + // Listen for when extensions are loaded/unloaded so we can track the + // number of background apps. + registrar_.Add(this, NotificationType::EXTENSION_LOADED, + Source<Profile>(profile)); + registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, + Source<Profile>(profile)); + + // Check for the presence of background apps after all extensions have been + // loaded, to handle the case where an extension has been manually removed + // while Chrome was not running. + registrar_.Add(this, NotificationType::EXTENSIONS_READY, + Source<Profile>(profile)); + +} + +BackgroundModeManager::~BackgroundModeManager() { +} + +bool BackgroundModeManager::IsBackgroundModeEnabled() { + return profile_->GetPrefs()->GetBoolean(prefs::kBackgroundModeEnabled); +} + +void BackgroundModeManager::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + switch (type.value) { + case NotificationType::EXTENSIONS_READY: + EnableLaunchOnStartup(IsBackgroundModeEnabled() && + background_app_count_ > 0); + break; + case NotificationType::EXTENSION_LOADED: + if (IsBackgroundApp(Details<Extension>(details).ptr())) + OnBackgroundAppLoaded(); + break; + case NotificationType::EXTENSION_UNLOADED: + if (IsBackgroundApp(Details<Extension>(details).ptr())) + OnBackgroundAppUnloaded(); + break; + case NotificationType::EXTENSION_INSTALLED: + if (IsBackgroundApp(Details<Extension>(details).ptr())) + OnBackgroundAppInstalled(); + break; + case NotificationType::EXTENSION_UNINSTALLED: + if (IsBackgroundApp(Details<Extension>(details).ptr())) + OnBackgroundAppUninstalled(); + break; + case NotificationType::APP_TERMINATING: + // Performing an explicit shutdown, so allow the browser process to exit. + // (we only listen for this notification if the keep-alive-for-test flag + // is passed). + DCHECK(CommandLine::ForCurrentProcess()->HasSwitch( + switches::kKeepAliveForTest)); + EndBackgroundMode(); + break; + default: + NOTREACHED(); + break; + } +} + +bool BackgroundModeManager::IsBackgroundApp(Extension* extension) { + return extension->HasApiPermission(Extension::kBackgroundPermission); +} + +void BackgroundModeManager::OnBackgroundAppLoaded() { + // When a background app loads, increment our count and also enable + // KeepAlive mode if the preference is set. + background_app_count_++; + if (background_app_count_ == 1 && IsBackgroundModeEnabled()) + StartBackgroundMode(); +} + +void BackgroundModeManager::StartBackgroundMode() { + // Put ourselves in KeepAlive mode and create a status tray icon. + BrowserList::StartKeepAlive(); + + // Display a status icon to exit Chrome. + CreateStatusTrayIcon(); +} + +void BackgroundModeManager::OnBackgroundAppUnloaded() { + // When a background app unloads, decrement our count and also end + // KeepAlive mode if appropriate. + background_app_count_--; + DCHECK(background_app_count_ == 0); + if (background_app_count_ == 0 && IsBackgroundModeEnabled()) + EndBackgroundMode(); +} + +void BackgroundModeManager::EndBackgroundMode() { + // End KeepAlive mode and blow away our status tray icon. + BrowserList::EndKeepAlive(); + RemoveStatusTrayIcon(); +} + +void BackgroundModeManager::OnBackgroundAppInstalled() { + // We're installing a background app. If this is the first background app + // being installed, make sure we are set to launch on startup. + if (IsBackgroundModeEnabled() && background_app_count_ == 0) + EnableLaunchOnStartup(true); +} + +void BackgroundModeManager::OnBackgroundAppUninstalled() { + // When uninstalling a background app, disable launch on startup if it's the + // last one. + if (IsBackgroundModeEnabled() && background_app_count_ == 1) + EnableLaunchOnStartup(false); +} + +void BackgroundModeManager::EnableLaunchOnStartup(bool should_launch) { + // TODO(atwilson): Add platform-specific code to enable/disable launch on + // startup. +} + +void BackgroundModeManager::CreateStatusTrayIcon() { + // If the platform doesn't support status icons, or we've already created + // our status icon, just return. + if (!status_tray_ || status_icon_) + return; + status_icon_ = status_tray_->CreateStatusIcon(); + if (!status_icon_) + return; + + // Set the image and add ourselves as a click observer on it + SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_STATUS_TRAY_ICON); + status_icon_->SetImage(*bitmap); + status_icon_->SetToolTip(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); + status_icon_->AddObserver(this); +} + +void BackgroundModeManager::RemoveStatusTrayIcon() { + if (status_icon_) + status_tray_->RemoveStatusIcon(status_icon_); + status_icon_ = NULL; +} + +void BackgroundModeManager::OnClicked() { + UserMetrics::RecordAction(UserMetricsAction("Exit"), profile_); + BrowserList::CloseAllBrowsersAndExit(); +} + +// static +void BackgroundModeManager::RegisterUserPrefs(PrefService* prefs) { + prefs->RegisterBooleanPref(prefs::kBackgroundModeEnabled, true); +} diff --git a/chrome/browser/background_mode_manager.h b/chrome/browser/background_mode_manager.h new file mode 100644 index 0000000..fa5296b --- /dev/null +++ b/chrome/browser/background_mode_manager.h @@ -0,0 +1,117 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_BACKGROUND_MODE_MANAGER_H_ +#define CHROME_BROWSER_BACKGROUND_MODE_MANAGER_H_ +#pragma once + +#include "base/gtest_prod_util.h" +#include "chrome/browser/status_icons/status_icon.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" + +class Extension; +class PrefService; +class Profile; +class StatusIcon; +class StatusTray; + +// BackgroundModeManager is responsible for switching Chrome into and out of +// "background mode" and for providing UI for the user to exit Chrome when there +// are no open browser windows. +// +// Chrome enters background mode whenever there is an application with the +// "background" permission installed and the appropriate user preference is +// set (kBackgroundModeEnabled). This class monitors the set of installed/loaded +// extensions to ensure that Chrome enters/exits background mode at the +// appropriate time. +// +// When Chrome is in background mode, it will continue running even after the +// last browser window is closed, until the user explicitly exits the app. +// Additionally, when in background mode, Chrome will launch on OS login with +// no open windows to allow apps with the "background" permission to run in the +// background. +class BackgroundModeManager + : private NotificationObserver, + private StatusIcon::Observer { + public: + explicit BackgroundModeManager(Profile* profile); + virtual ~BackgroundModeManager(); + + static void RegisterUserPrefs(PrefService* prefs); + private: + friend class TestBackgroundModeManager; + friend class BackgroundModeManagerTest; + FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest, + BackgroundAppLoadUnload); + FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest, + BackgroundAppInstallUninstall); + + // NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // StatusIcon::Observer implementation. + virtual void OnClicked(); + + // Called when an extension is loaded to manage count of background apps. + void OnBackgroundAppLoaded(); + + // Called when an extension is unloaded to manage count of background apps. + void OnBackgroundAppUnloaded(); + + // Invoked when an extension is installed so we can ensure that + // launch-on-startup is enabled if appropriate. + void OnBackgroundAppInstalled(); + + // Invoked when an extension is uninstalled so we can ensure that + // launch-on-startup is disabled if appropriate. + void OnBackgroundAppUninstalled(); + + // Returns true if the passed extension is a background app. + bool IsBackgroundApp(Extension* extension); + + // Returns true if the background mode preference is enabled + bool IsBackgroundModeEnabled(); + + // Called to make sure that our launch-on-startup mode is properly set. + // (virtual so we can override for tests). + virtual void EnableLaunchOnStartup(bool should_launch); + + // Invoked to put Chrome in KeepAlive mode - chrome runs in the background + // and has a status bar icon. + void StartBackgroundMode(); + + // Invoked to take Chrome out of KeepAlive mode - chrome stops running in + // the background and removes its status bar icon. + void EndBackgroundMode(); + + // Create a status tray icon to allow the user to shutdown Chrome when running + // in background mode. Virtual to enable testing. + virtual void CreateStatusTrayIcon(); + + // Removes the status tray icon because we are exiting background mode. + // Virtual to enable testing. + virtual void RemoveStatusTrayIcon(); + + NotificationRegistrar registrar_; + + // The parent profile for this object. + Profile* profile_; + + // The number of background apps currently loaded. + int background_app_count_; + + // Reference to our status tray (owned by our parent profile). If null, the + // platform doesn't support status icons. + StatusTray* status_tray_; + + // Reference to our status icon (if any) - owned by the StatusTray. + StatusIcon* status_icon_; + + DISALLOW_COPY_AND_ASSIGN(BackgroundModeManager); +}; + +#endif // CHROME_BROWSER_BACKGROUND_MODE_MANAGER_H_ diff --git a/chrome/browser/background_mode_manager_unittest.cc b/chrome/browser/background_mode_manager_unittest.cc new file mode 100644 index 0000000..087b4fe --- /dev/null +++ b/chrome/browser/background_mode_manager_unittest.cc @@ -0,0 +1,46 @@ +// Copyright (c) 2010 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 "chrome/browser/background_mode_manager.h" +#include "chrome/browser/browser_list.h" +#include "chrome/test/testing_profile.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +class TestBackgroundModeManager : public BackgroundModeManager { + public: + explicit TestBackgroundModeManager(Profile* profile) + : BackgroundModeManager(profile) { + } + MOCK_METHOD1(EnableLaunchOnStartup, void(bool)); + MOCK_METHOD0(CreateStatusTrayIcon, void()); + MOCK_METHOD0(RemoveStatusTrayIcon, void()); +}; + +TEST(BackgroundModeManagerTest, BackgroundAppLoadUnload) { + TestingProfile profile; + TestBackgroundModeManager manager(&profile); + EXPECT_FALSE(BrowserList::WillKeepAlive()); + // Call to AppLoaded() will cause the status tray to be created, then call to + // unloaded will result in call to remove the icon. + EXPECT_CALL(manager, CreateStatusTrayIcon()); + manager.OnBackgroundAppLoaded(); + EXPECT_TRUE(BrowserList::WillKeepAlive()); + EXPECT_CALL(manager, RemoveStatusTrayIcon()); + manager.OnBackgroundAppUnloaded(); + EXPECT_FALSE(BrowserList::WillKeepAlive()); +} + +TEST(BackgroundModeManagerTest, BackgroundAppInstallUninstall) { + TestingProfile profile; + TestBackgroundModeManager manager(&profile); + // Call to AppInstalled() will cause chrome to be set to launch on startup, + // and call to AppUninstalling() set chrome to not launch on startup. + EXPECT_CALL(manager, EnableLaunchOnStartup(true)); + manager.OnBackgroundAppInstalled(); + manager.OnBackgroundAppLoaded(); + EXPECT_CALL(manager, EnableLaunchOnStartup(false)); + manager.OnBackgroundAppUninstalled(); + manager.OnBackgroundAppUnloaded(); +} diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc index 8dbe4a9..5e1f459 100644 --- a/chrome/browser/browser_init.cc +++ b/chrome/browser/browser_init.cc @@ -41,7 +41,6 @@ #include "chrome/browser/sessions/session_restore.h" #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/shell_integration.h" -#include "chrome/browser/status_icons/status_tray_manager.h" #include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/tab_contents/tab_contents.h" @@ -443,14 +442,6 @@ bool BrowserInit::LaunchBrowser(const CommandLine& command_line, chromeos::SystemKeyEventListener::instance(); } #endif - - if (command_line.HasSwitch(switches::kRestoreBackgroundContents) || - command_line.HasSwitch(switches::kKeepAliveForTest)) { - // Create status icons - StatusTrayManager* tray = g_browser_process->status_tray_manager(); - if (tray) - tray->Init(profile); - } return true; } diff --git a/chrome/browser/browser_prefs.cc b/chrome/browser/browser_prefs.cc index 9c13d88..c6222a7 100644 --- a/chrome/browser/browser_prefs.cc +++ b/chrome/browser/browser_prefs.cc @@ -6,6 +6,7 @@ #include "chrome/browser/autofill/autofill_manager.h" #include "chrome/browser/background_contents_service.h" +#include "chrome/browser/background_mode_manager.h" #include "chrome/browser/bookmarks/bookmark_utils.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_shutdown.h" @@ -101,6 +102,7 @@ void RegisterLocalState(PrefService* local_state) { void RegisterUserPrefs(PrefService* user_prefs) { // User prefs AutoFillManager::RegisterUserPrefs(user_prefs); + BackgroundModeManager::RegisterUserPrefs(user_prefs); SessionStartupPref::RegisterUserPrefs(user_prefs); Browser::RegisterUserPrefs(user_prefs); PasswordManager::RegisterUserPrefs(user_prefs); diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h index 417d333..a853c74 100644 --- a/chrome/browser/browser_process.h +++ b/chrome/browser/browser_process.h @@ -29,7 +29,6 @@ class NotificationUIManager; class PrefService; class ProfileManager; class ResourceDispatcherHost; -class StatusTrayManager; class TabCloseableStateWatcher; class ThumbnailGenerator; @@ -69,10 +68,6 @@ class BrowserProcess { // Returns the manager for desktop notifications. virtual NotificationUIManager* notification_ui_manager() = 0; - // Returns the status tray manager (provides APIs for manipulating status - // icons). - virtual StatusTrayManager* status_tray_manager() = 0; - // Returns the thread that we perform I/O coordination on (network requests, // communication with renderers, etc. // NOTE: You should ONLY use this to pass to IPC or other objects which must diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index a1fbf55..f314388 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc @@ -43,7 +43,6 @@ #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" -#include "chrome/browser/status_icons/status_tray_manager.h" #include "chrome/browser/tab_closeable_state_watcher.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" @@ -359,13 +358,6 @@ NotificationUIManager* BrowserProcessImpl::notification_ui_manager() { return notification_ui_manager_.get(); } -StatusTrayManager* BrowserProcessImpl::status_tray_manager() { - DCHECK(CalledOnValidThread()); - if (!status_tray_manager_.get()) - CreateStatusTrayManager(); - return status_tray_manager_.get(); -} - IconManager* BrowserProcessImpl::icon_manager() { DCHECK(CalledOnValidThread()); if (!created_icon_manager_) @@ -644,11 +636,6 @@ void BrowserProcessImpl::CreateNotificationUIManager() { created_notification_ui_manager_ = true; } -void BrowserProcessImpl::CreateStatusTrayManager() { - DCHECK(status_tray_manager_.get() == NULL); - status_tray_manager_.reset(new StatusTrayManager()); -} - void BrowserProcessImpl::CreateTabCloseableStateWatcher() { DCHECK(tab_closeable_state_watcher_.get() == NULL); tab_closeable_state_watcher_.reset(TabCloseableStateWatcher::Create()); diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index b26127d..9118ff6 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h @@ -51,7 +51,6 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe { virtual DevToolsManager* devtools_manager(); virtual Clipboard* clipboard(); virtual NotificationUIManager* notification_ui_manager(); - virtual StatusTrayManager* status_tray_manager(); virtual IconManager* icon_manager(); virtual ThumbnailGenerator* GetThumbnailGenerator(); virtual AutomationProviderList* InitAutomationProviderList(); @@ -157,9 +156,6 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe { bool created_notification_ui_manager_; scoped_ptr<NotificationUIManager> notification_ui_manager_; - // Manager for status tray. - scoped_ptr<StatusTrayManager> status_tray_manager_; - scoped_ptr<AutomationProviderList> automation_provider_list_; scoped_ptr<GoogleURLTracker> google_url_tracker_; diff --git a/chrome/browser/cocoa/status_icons/status_tray_mac.h b/chrome/browser/cocoa/status_icons/status_tray_mac.h index 074251b..3552db4 100644 --- a/chrome/browser/cocoa/status_icons/status_tray_mac.h +++ b/chrome/browser/cocoa/status_icons/status_tray_mac.h @@ -14,7 +14,7 @@ class StatusTrayMac : public StatusTray { protected: // Factory method for creating a status icon. - virtual StatusIcon* CreateStatusIcon(); + virtual StatusIcon* CreatePlatformStatusIcon(); private: DISALLOW_COPY_AND_ASSIGN(StatusTrayMac); diff --git a/chrome/browser/cocoa/status_icons/status_tray_mac.mm b/chrome/browser/cocoa/status_icons/status_tray_mac.mm index 8c9449b..d4e176f 100644 --- a/chrome/browser/cocoa/status_icons/status_tray_mac.mm +++ b/chrome/browser/cocoa/status_icons/status_tray_mac.mm @@ -13,6 +13,6 @@ StatusTray* StatusTray::Create() { StatusTrayMac::StatusTrayMac() { } -StatusIcon* StatusTrayMac::CreateStatusIcon() { +StatusIcon* StatusTrayMac::CreatePlatformStatusIcon() { return new StatusIconMac(); } diff --git a/chrome/browser/extensions/app_background_page_apitest.cc b/chrome/browser/extensions/app_background_page_apitest.cc index a75fc50..5980921 100644 --- a/chrome/browser/extensions/app_background_page_apitest.cc +++ b/chrome/browser/extensions/app_background_page_apitest.cc @@ -13,6 +13,8 @@ class AppBackgroundPageApiTest : public ExtensionApiTest { void SetUpCommandLine(CommandLine* command_line) { ExtensionApiTest::SetUpCommandLine(command_line); command_line->AppendSwitch(switches::kDisablePopupBlocking); + // Tests rely on chrome exiting, so disable background mode. + command_line->AppendSwitch(switches::kDisableBackgroundMode); } }; diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index ad26fc6..61de28b 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -374,6 +374,12 @@ void ExtensionsService::UninstallExtension(const std::string& extension_id, // Callers should not send us nonexistant extensions. DCHECK(extension); + // Notify interested parties that we're uninstalling this extension. + NotificationService::current()->Notify( + NotificationType::EXTENSION_UNINSTALLED, + Source<Profile>(profile_), + Details<Extension>(extension)); + // Get hold of information we need after unloading, since the extension // pointer will be invalid then. GURL extension_url(extension->url()); diff --git a/chrome/browser/gtk/status_icons/status_tray_gtk.cc b/chrome/browser/gtk/status_icons/status_tray_gtk.cc index 6b2764e..98cf98c 100644 --- a/chrome/browser/gtk/status_icons/status_tray_gtk.cc +++ b/chrome/browser/gtk/status_icons/status_tray_gtk.cc @@ -12,7 +12,7 @@ StatusTrayGtk::StatusTrayGtk() { StatusTrayGtk::~StatusTrayGtk() { } -StatusIcon* StatusTrayGtk::CreateStatusIcon() { +StatusIcon* StatusTrayGtk::CreatePlatformStatusIcon() { return new StatusIconGtk(); } diff --git a/chrome/browser/gtk/status_icons/status_tray_gtk.h b/chrome/browser/gtk/status_icons/status_tray_gtk.h index ec443ca..5e0241b 100644 --- a/chrome/browser/gtk/status_icons/status_tray_gtk.h +++ b/chrome/browser/gtk/status_icons/status_tray_gtk.h @@ -15,7 +15,7 @@ class StatusTrayGtk : public StatusTray { protected: // Overriden from StatusTray: - virtual StatusIcon* CreateStatusIcon(); + virtual StatusIcon* CreatePlatformStatusIcon(); private: DISALLOW_COPY_AND_ASSIGN(StatusTrayGtk); diff --git a/chrome/browser/gtk/status_icons/status_tray_gtk_unittest.cc b/chrome/browser/gtk/status_icons/status_tray_gtk_unittest.cc index 5bc2c2b..89f9524 100644 --- a/chrome/browser/gtk/status_icons/status_tray_gtk_unittest.cc +++ b/chrome/browser/gtk/status_icons/status_tray_gtk_unittest.cc @@ -27,7 +27,7 @@ TEST(StatusTrayGtkTest, CreateTray) { TEST(StatusTrayGtkTest, CreateIcon) { // Create an icon, set the images and tooltip, then shut it down. StatusTrayGtk tray; - StatusIcon* icon = tray.GetStatusIcon(ASCIIToUTF16("test")); + StatusIcon* icon = tray.CreateStatusIcon(); SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed( IDR_STATUS_TRAY_ICON); icon->SetImage(*bitmap); @@ -38,8 +38,7 @@ TEST(StatusTrayGtkTest, CreateIcon) { TEST(StatusTrayGtkTest, ClickOnIcon) { // Create an icon, send a fake click event, make sure observer is called. StatusTrayGtk tray; - StatusIconGtk* icon = static_cast<StatusIconGtk*>( - tray.GetStatusIcon(ASCIIToUTF16("test"))); + StatusIconGtk* icon = static_cast<StatusIconGtk*>(tray.CreateStatusIcon()); MockStatusIconObserver observer; icon->AddObserver(&observer); EXPECT_CALL(observer, OnClicked()); diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index 26392e8..51d74f0 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -203,6 +203,10 @@ class OffTheRecordProfileImpl : public Profile, return background_contents_service_.get(); } + virtual StatusTray* GetStatusTray() { + return GetOriginalProfile()->GetStatusTray(); + } + virtual UserScriptMaster* GetUserScriptMaster() { return GetOriginalProfile()->GetUserScriptMaster(); } diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h index 6403c8f..da63eae 100644 --- a/chrome/browser/profile.h +++ b/chrome/browser/profile.h @@ -35,6 +35,7 @@ class DatabaseTracker; class AutocompleteClassifier; class BackgroundContentsService; +class BackgroundModeManager; class BookmarkModel; class BrowserThemeProvider; class ChromeAppCacheService; @@ -65,6 +66,7 @@ class SessionService; class SpellCheckHost; class SSLConfigServiceManager; class SSLHostState; +class StatusTray; class TransportSecurityPersister; class SQLitePersistentCookieStore; class TabRestoreService; @@ -405,6 +407,11 @@ class Profile { // Returns the service that manages BackgroundContents for this profile. virtual BackgroundContentsService* GetBackgroundContentsService() = 0; + // Returns the StatusTray, which provides an API for displaying status icons + // in the system status tray. Returns NULL if status icons are not supported + // on this platform (or this is a unit test). + virtual StatusTray* GetStatusTray() = 0; + // Marks the profile as cleanly shutdown. // // NOTE: this is invoked internally on a normal shutdown, but is public so diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc index bc11cc5..84a2b17 100644 --- a/chrome/browser/profile_impl.cc +++ b/chrome/browser/profile_impl.cc @@ -17,6 +17,7 @@ #include "chrome/browser/autocomplete/autocomplete_classifier.h" #include "chrome/browser/autofill/personal_data_manager.h" #include "chrome/browser/background_contents_service.h" +#include "chrome/browser/background_mode_manager.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_prefs.h" @@ -56,6 +57,7 @@ #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/tab_restore_service.h" #include "chrome/browser/ssl/ssl_host_state.h" +#include "chrome/browser/status_icons/status_tray.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/profile_sync_factory_impl.h" #include "chrome/browser/tabs/pinned_tab_service.h" @@ -335,6 +337,15 @@ ProfileImpl::ProfileImpl(const FilePath& path) pinned_tab_service_.reset(new PinnedTabService(this)); + // Initialize the BackgroundModeManager - this has to be done here before + // InitExtensions() is called because it relies on receiving notifications + // when extensions are loaded. BackgroundModeManager is not needed under + // ChromeOS because Chrome is always running (no need for special keep-alive + // or launch-on-startup support). +#if !defined(OS_CHROMEOS) + background_mode_manager_.reset(new BackgroundModeManager(this)); +#endif + background_contents_service_.reset( new BackgroundContentsService(this, CommandLine::ForCurrentProcess())); @@ -580,6 +591,12 @@ BackgroundContentsService* ProfileImpl::GetBackgroundContentsService() { return background_contents_service_.get(); } +StatusTray* ProfileImpl::GetStatusTray() { + if (!status_tray_.get()) + status_tray_.reset(StatusTray::Create()); + return status_tray_.get(); +} + UserScriptMaster* ProfileImpl::GetUserScriptMaster() { return user_script_master_.get(); } diff --git a/chrome/browser/profile_impl.h b/chrome/browser/profile_impl.h index 45e3b92..6e2230f 100644 --- a/chrome/browser/profile_impl.h +++ b/chrome/browser/profile_impl.h @@ -87,6 +87,7 @@ class ProfileImpl : public Profile, virtual WebKitContext* GetWebKitContext(); virtual DesktopNotificationService* GetDesktopNotificationService(); virtual BackgroundContentsService* GetBackgroundContentsService(); + virtual StatusTray* GetStatusTray(); virtual void MarkAsCleanShutdown(); virtual void InitExtensions(); virtual NTPResourceCache* GetNTPResourceCache(); @@ -181,6 +182,8 @@ class ProfileImpl : public Profile, scoped_refptr<WebKitContext> webkit_context_; scoped_ptr<DesktopNotificationService> desktop_notification_service_; scoped_ptr<BackgroundContentsService> background_contents_service_; + scoped_ptr<BackgroundModeManager> background_mode_manager_; + scoped_ptr<StatusTray> status_tray_; scoped_refptr<PersonalDataManager> personal_data_manager_; scoped_ptr<PinnedTabService> pinned_tab_service_; bool history_service_created_; diff --git a/chrome/browser/status_icons/status_tray.cc b/chrome/browser/status_icons/status_tray.cc index b7ae49c..8648351 100644 --- a/chrome/browser/status_icons/status_tray.cc +++ b/chrome/browser/status_icons/status_tray.cc @@ -4,6 +4,8 @@ #include "chrome/browser/status_icons/status_tray.h" +#include <algorithm> + #include "base/stl_util-inl.h" #include "chrome/browser/status_icons/status_icon.h" @@ -16,29 +18,23 @@ StatusTray::~StatusTray() { void StatusTray::RemoveAllIcons() { // Walk any active status icons and delete them. - STLDeleteContainerPairSecondPointers(status_icons_.begin(), - status_icons_.end()); + STLDeleteContainerPointers(status_icons_.begin(), status_icons_.end()); status_icons_.clear(); } -StatusIcon* StatusTray::GetStatusIcon(const string16& identifier) { - StatusIconMap::const_iterator iter = status_icons_.find(identifier); - if (iter != status_icons_.end()) - return iter->second; - - // No existing StatusIcon, create a new one. - StatusIcon* icon = CreateStatusIcon(); +StatusIcon* StatusTray::CreateStatusIcon() { + StatusIcon* icon = CreatePlatformStatusIcon(); if (icon) - status_icons_[identifier] = icon; + status_icons_.push_back(icon); return icon; } -void StatusTray::RemoveStatusIcon(const string16& identifier) { - StatusIconMap::iterator iter = status_icons_.find(identifier); +void StatusTray::RemoveStatusIcon(StatusIcon* icon) { + StatusIconList::iterator iter = std::find( + status_icons_.begin(), status_icons_.end(), icon); if (iter != status_icons_.end()) { - // Free the StatusIcon from the map (can't put scoped_ptr in a map, so we - // have to do it manually). - delete iter->second; + // Free the StatusIcon from the list. + delete *iter; status_icons_.erase(iter); } } diff --git a/chrome/browser/status_icons/status_tray.h b/chrome/browser/status_icons/status_tray.h index 6052582..a0da771 100644 --- a/chrome/browser/status_icons/status_tray.h +++ b/chrome/browser/status_icons/status_tray.h @@ -6,8 +6,10 @@ #define CHROME_BROWSER_STATUS_ICONS_STATUS_TRAY_H_ #pragma once -#include "base/hash_tables.h" -#include "base/scoped_ptr.h" +#include <vector> + +#include "base/basictypes.h" +#include "base/gtest_prod_util.h" class StatusIcon; @@ -16,38 +18,37 @@ class StatusIcon; class StatusTray { public: // Static factory method that is implemented separately for each platform to - // produce the appropriate platform-specific instance. + // produce the appropriate platform-specific instance. Returns NULL if this + // platform does not support status icons. static StatusTray* Create(); virtual ~StatusTray(); - // Gets the current status icon associated with this identifier, or creates - // a new one if none exists. The StatusTray retains ownership of the - // StatusIcon. Returns NULL if the status tray icon could not be created. - StatusIcon* GetStatusIcon(const string16& identifier); + // Creates a new StatusIcon. The StatusTray retains ownership of the + // StatusIcon. Returns NULL if the StatusIcon could not be created. + StatusIcon* CreateStatusIcon(); // Removes the current status icon associated with this identifier, if any. - void RemoveStatusIcon(const string16& identifier); + void RemoveStatusIcon(StatusIcon* icon); protected: StatusTray(); - // Factory method for creating a status icon. - virtual StatusIcon* CreateStatusIcon() = 0; + // Factory method for creating a status icon for this platform. + virtual StatusIcon* CreatePlatformStatusIcon() = 0; // Removes all StatusIcons (used by derived classes to clean up in case they // track external state used by the StatusIcons). void RemoveAllIcons(); - typedef base::hash_map<string16, StatusIcon*> StatusIconMap; + typedef std::vector<StatusIcon*> StatusIconList; // Returns the list of active status icons so subclasses can operate on them. - const StatusIconMap& status_icons() { return status_icons_; } + const StatusIconList& status_icons() { return status_icons_; } private: - // Map containing all active StatusIcons. - // Key: String identifiers (passed in to GetStatusIcon) - // Value: The StatusIcon associated with that identifier (strong pointer - - // StatusIcons are freed when the StatusTray destructor is called). - StatusIconMap status_icons_; + FRIEND_TEST_ALL_PREFIXES(StatusTrayTest, CreateRemove); + + // List containing all active StatusIcons. + StatusIconList status_icons_; DISALLOW_COPY_AND_ASSIGN(StatusTray); }; diff --git a/chrome/browser/status_icons/status_tray_manager.cc b/chrome/browser/status_icons/status_tray_manager.cc deleted file mode 100644 index 57b6ed9..0000000 --- a/chrome/browser/status_icons/status_tray_manager.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2010 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 "chrome/browser/status_icons/status_tray_manager.h" - -#include "app/l10n_util.h" -#include "app/resource_bundle.h" -#include "base/logging.h" -#include "base/string_util.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_window.h" -#include "chrome/browser/status_icons/status_tray.h" -#include "grit/browser_resources.h" -#include "grit/chromium_strings.h" -#include "grit/theme_resources.h" - -StatusTrayManager::StatusTrayManager() : profile_(NULL) { -} - -StatusTrayManager::~StatusTrayManager() { -} - -void StatusTrayManager::Init(Profile* profile) { -#if !(defined(OS_LINUX) && defined(TOOLKIT_VIEWS)) - DCHECK(profile); - profile_ = profile; - status_tray_.reset(StatusTray::Create()); - StatusIcon* icon = status_tray_->GetStatusIcon(ASCIIToUTF16("chrome_main")); - if (icon) { - // Create an icon and add ourselves as a click observer on it - SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_STATUS_TRAY_ICON); - SkBitmap* pressed = ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_STATUS_TRAY_ICON_PRESSED); - icon->SetImage(*bitmap); - icon->SetPressedImage(*pressed); - icon->SetToolTip(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); - icon->AddObserver(this); - } -#endif -} - -void StatusTrayManager::OnClicked() { - // When the tray icon is clicked, bring up the extensions page for now. - Browser* browser = BrowserList::GetLastActiveWithProfile(profile_); - if (browser) { - // Bring up the existing browser window and show the extensions tab. - browser->window()->Activate(); - browser->ShowExtensionsTab(); - } else { - // No windows are currently open, so open a new one. - Browser::OpenExtensionsWindow(profile_); - } -} diff --git a/chrome/browser/status_icons/status_tray_manager.h b/chrome/browser/status_icons/status_tray_manager.h deleted file mode 100644 index 6829f94..0000000 --- a/chrome/browser/status_icons/status_tray_manager.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2010 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. - -#ifndef CHROME_BROWSER_STATUS_ICONS_STATUS_TRAY_MANAGER_H_ -#define CHROME_BROWSER_STATUS_ICONS_STATUS_TRAY_MANAGER_H_ -#pragma once - -#include "base/scoped_ptr.h" -#include "chrome/browser/status_icons/status_icon.h" - -class Profile; -class StatusTray; - -// Manages the set of status tray icons and associated UI. -class StatusTrayManager : private StatusIcon::Observer { - public: - StatusTrayManager(); - virtual ~StatusTrayManager(); - - void Init(Profile* profile); - - private: - // Overriden from StatusIcon::Observer: - virtual void OnClicked(); - - scoped_ptr<StatusTray> status_tray_; - Profile* profile_; -}; - -#endif // CHROME_BROWSER_STATUS_ICONS_STATUS_TRAY_MANAGER_H_ diff --git a/chrome/browser/status_icons/status_tray_unittest.cc b/chrome/browser/status_icons/status_tray_unittest.cc index 957faa7..26219bd 100644 --- a/chrome/browser/status_icons/status_tray_unittest.cc +++ b/chrome/browser/status_icons/status_tray_unittest.cc @@ -21,35 +21,26 @@ class MockStatusIcon : public StatusIcon { class TestStatusTray : public StatusTray { public: - MOCK_METHOD0(CreateStatusIcon, StatusIcon*()); + MOCK_METHOD0(CreatePlatformStatusIcon, StatusIcon*()); }; TEST(StatusTrayTest, Create) { // Check for creation and leaks. TestStatusTray tray; - EXPECT_CALL(tray, CreateStatusIcon()).WillOnce(Return(new MockStatusIcon())); - tray.GetStatusIcon(ASCIIToUTF16("test")); + EXPECT_CALL(tray, + CreatePlatformStatusIcon()).WillOnce(Return(new MockStatusIcon())); + tray.CreateStatusIcon(); } -TEST(StatusTrayTest, GetIconTwice) { +// Make sure that removing an icon removes it from the list. +TEST(StatusTrayTest, CreateRemove) { TestStatusTray tray; - string16 id = ASCIIToUTF16("test"); - // We should not try to create a new icon if we get the same ID twice. - EXPECT_CALL(tray, CreateStatusIcon()).WillOnce(Return(new MockStatusIcon())); - StatusIcon* icon = tray.GetStatusIcon(id); - EXPECT_EQ(icon, tray.GetStatusIcon(id)); -} - -TEST(StatusTrayTest, GetIconAfterRemove) { - TestStatusTray tray; - string16 id = ASCIIToUTF16("test"); - EXPECT_CALL(tray, CreateStatusIcon()).Times(2) - .WillOnce(Return(new MockStatusIcon())) - .WillOnce(Return(new MockStatusIcon())); - StatusIcon* icon = tray.GetStatusIcon(id); - EXPECT_EQ(icon, tray.GetStatusIcon(id)); - - // If we remove the icon, then we should create a new one the next time in. - tray.RemoveStatusIcon(id); - tray.GetStatusIcon(id); + EXPECT_CALL(tray, + CreatePlatformStatusIcon()).WillOnce(Return(new MockStatusIcon())); + StatusIcon* icon = tray.CreateStatusIcon(); + EXPECT_EQ(1U, tray.status_icons_.size()); + tray.RemoveStatusIcon(icon); + EXPECT_EQ(0U, tray.status_icons_.size()); + // Calling again should do nothing. + tray.RemoveStatusIcon(icon); } diff --git a/chrome/browser/views/status_icons/status_tray_gtk.cc b/chrome/browser/views/status_icons/status_tray_gtk.cc new file mode 100644 index 0000000..7cd0666 --- /dev/null +++ b/chrome/browser/views/status_icons/status_tray_gtk.cc @@ -0,0 +1,10 @@ +// Copyright (c) 2010 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 "chrome/browser/status_icons/status_tray.h" + +// Status icons are not currently supported on linux/views. +StatusTray* StatusTray::Create() { + return NULL; +} diff --git a/chrome/browser/views/status_icons/status_tray_win.cc b/chrome/browser/views/status_icons/status_tray_win.cc index 8c1a998..5a4587f 100644 --- a/chrome/browser/views/status_icons/status_tray_win.cc +++ b/chrome/browser/views/status_icons/status_tray_win.cc @@ -49,11 +49,10 @@ LRESULT CALLBACK StatusTrayWin::WndProc(HWND hwnd, case WM_LBUTTONDOWN: // Walk our icons, find which one was clicked on, and invoke its // DispatchClickEvent() method. - for (StatusIconMap::const_iterator iter = status_icons().begin(); + for (StatusIconList::const_iterator iter = status_icons().begin(); iter != status_icons().end(); ++iter) { - StatusIconWin* win_icon = - static_cast<StatusIconWin*>(iter->second); + StatusIconWin* win_icon = static_cast<StatusIconWin*>(*iter); if (win_icon->icon_id() == wparam) win_icon->DispatchClickEvent(); } @@ -70,7 +69,7 @@ StatusTrayWin::~StatusTrayWin() { UnregisterClass(chrome::kStatusTrayWindowClass, GetModuleHandle(NULL)); } -StatusIcon* StatusTrayWin::CreateStatusIcon() { +StatusIcon* StatusTrayWin::CreatePlatformStatusIcon() { return new StatusIconWin(next_icon_id_++, window_, kStatusIconMessage); } diff --git a/chrome/browser/views/status_icons/status_tray_win.h b/chrome/browser/views/status_icons/status_tray_win.h index efdb13b..a2e322c 100644 --- a/chrome/browser/views/status_icons/status_tray_win.h +++ b/chrome/browser/views/status_icons/status_tray_win.h @@ -22,7 +22,7 @@ class StatusTrayWin : public StatusTray { LPARAM lparam); protected: // Overriden from StatusTray: - virtual StatusIcon* CreateStatusIcon(); + virtual StatusIcon* CreatePlatformStatusIcon(); private: // Static callback invoked when a message comes in to our messaging window. diff --git a/chrome/browser/views/status_icons/status_tray_win_unittest.cc b/chrome/browser/views/status_icons/status_tray_win_unittest.cc index 635c7df..e5499b9e 100644 --- a/chrome/browser/views/status_icons/status_tray_win_unittest.cc +++ b/chrome/browser/views/status_icons/status_tray_win_unittest.cc @@ -27,7 +27,7 @@ TEST(StatusTrayWinTest, CreateTray) { TEST(StatusTrayWinTest, CreateIcon) { // Create an icon, set the images and tooltip, then shut it down. StatusTrayWin tray; - StatusIcon* icon = tray.GetStatusIcon(ASCIIToUTF16("test")); + StatusIcon* icon = tray.CreateStatusIcon(); SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed( IDR_STATUS_TRAY_ICON); icon->SetImage(*bitmap); @@ -38,8 +38,7 @@ TEST(StatusTrayWinTest, CreateIcon) { TEST(StatusTrayWinTest, ClickOnIcon) { // Create an icon, send a fake click event, make sure observer is called. StatusTrayWin tray; - StatusIconWin* icon = static_cast<StatusIconWin*>( - tray.GetStatusIcon(ASCIIToUTF16("test"))); + StatusIconWin* icon = static_cast<StatusIconWin*>(tray.CreateStatusIcon()); MockStatusIconObserver observer; icon->AddObserver(&observer); EXPECT_CALL(observer, OnClicked()); |