diff options
-rw-r--r-- | chrome/app/theme/theme_resources.grd | 2 | ||||
-rw-r--r-- | chrome/browser/browser.cc | 11 | ||||
-rw-r--r-- | chrome/browser/browser.h | 5 | ||||
-rw-r--r-- | chrome/browser/browser_init.cc | 12 | ||||
-rw-r--r-- | chrome/browser/browser_process.h | 5 | ||||
-rw-r--r-- | chrome/browser/browser_process_impl.cc | 6 | ||||
-rw-r--r-- | chrome/browser/browser_process_impl.h | 11 | ||||
-rw-r--r-- | chrome/browser/cocoa/status_icons/status_icon_mac.h | 48 | ||||
-rw-r--r-- | chrome/browser/cocoa/status_icons/status_icon_mac.mm | 95 | ||||
-rw-r--r-- | chrome/browser/cocoa/status_icons/status_icon_mac_unittest.mm | 57 | ||||
-rw-r--r-- | chrome/browser/status_icons/status_icon.h | 39 | ||||
-rw-r--r-- | chrome/browser/status_icons/status_tray.cc | 40 | ||||
-rw-r--r-- | chrome/browser/status_icons/status_tray.h | 47 | ||||
-rw-r--r-- | chrome/browser/status_icons/status_tray_manager.cc | 63 | ||||
-rw-r--r-- | chrome/browser/status_icons/status_tray_manager.h | 30 | ||||
-rw-r--r-- | chrome/browser/status_icons/status_tray_unittest.cc | 56 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 7 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 2 | ||||
-rw-r--r-- | chrome/test/testing_browser_process.h | 4 |
19 files changed, 534 insertions, 6 deletions
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 783af7e..766d7f0 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd @@ -337,6 +337,7 @@ <include name="IDR_WIZARD_ICON_RTL" file="google_chrome/wizard_icon_rtl.png" type="BINDATA" /> <include name="IDR_PRODUCT_ICON_32" file="google_chrome/google_chrome_icon_32.png" type="BINDATA" /> <include name="IDR_INFOBAR_TRANSLATE" file="google_chrome/infobar_translate.png" type="BINDATA" /> + <include name="IDR_STATUS_TRAY_ICON" file="google_chrome/product_logo_22.png" type="BINDATA" /> </if> <if expr="not pp_ifdef('_google_chrome')"> @@ -352,6 +353,7 @@ <include name="IDR_WIZARD_ICON_RTL" file="chromium/wizard_icon_rtl.png" type="BINDATA" /> <include name="IDR_PRODUCT_ICON_32" file="chromium/chromium_icon_32.png" type="BINDATA" /> <include name="IDR_INFOBAR_TRANSLATE" file="chromium/infobar_translate.png" type="BINDATA" /> + <include name="IDR_STATUS_TRAY_ICON" file="chromium/product_logo_22.png" type="BINDATA" /> </if> <if expr="pp_ifdef('chromeos') or pp_ifdef('toolkit_views')"> diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index 40d1072..344a660 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -406,19 +406,20 @@ void Browser::OpenDownloadsWindow(Profile* profile) { } // static -void Browser::OpenExtensionsWindow(Profile* profile) { +void Browser::OpenHelpWindow(Profile* profile) { Browser* browser = Browser::Create(profile); - browser->ShowExtensionsTab(); + browser->OpenHelpTab(); browser->window()->Show(); } +#endif // static -void Browser::OpenHelpWindow(Profile* profile) { +void Browser::OpenExtensionsWindow(Profile* profile) { Browser* browser = Browser::Create(profile); - browser->OpenHelpTab(); + browser->ShowExtensionsTab(); browser->window()->Show(); } -#endif + /////////////////////////////////////////////////////////////////////////////// // Browser, State Storage and Retrieval for UI: diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h index 991f9d4..f8abf95 100644 --- a/chrome/browser/browser.h +++ b/chrome/browser/browser.h @@ -192,10 +192,13 @@ class Browser : public TabStripModelDelegate, // no windows). static void OpenHistoryWindow(Profile* profile); static void OpenDownloadsWindow(Profile* profile); - static void OpenExtensionsWindow(Profile* profile); static void OpenHelpWindow(Profile* profile); #endif + // Opens a window with the extensions tab in it - needed by long-lived + // extensions which may run with no windows open. + static void OpenExtensionsWindow(Profile* profile); + // State Storage and Retrieval for UI /////////////////////////////////////// // Save and restore the window position. diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc index fe1866f..9f92ad8 100644 --- a/chrome/browser/browser_init.cc +++ b/chrome/browser/browser_init.cc @@ -33,6 +33,7 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/browser/net/url_fixer_upper.h" +#include "chrome/browser/status_icons/status_tray_manager.h" #include "chrome/browser/user_data_manager.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" @@ -389,6 +390,17 @@ bool BrowserInit::LaunchBrowser( lib->AddObserver(observe); } #endif +#if defined(OS_MACOSX) + // TODO(atwilson): Status tray UI is currently only supported on the mac + // (http://crbug.com/37375). + if (command_line.HasSwitch(switches::kLongLivedExtensions)) { + // Create status icons + StatusTrayManager* tray = g_browser_process->status_tray_manager(); + if (tray) + tray->Init(profile); + } +#endif + return true; } diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h index 52b7578..675b477 100644 --- a/chrome/browser/browser_process.h +++ b/chrome/browser/browser_process.h @@ -29,6 +29,7 @@ class PrefService; class ProfileManager; class DebuggerWrapper; class ResourceDispatcherHost; +class StatusTrayManager; class SuspendController; class ThumbnailGenerator; class WebAppInstallerService; @@ -76,6 +77,10 @@ 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 f3cb9700..c510336 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc @@ -38,6 +38,7 @@ #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/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" @@ -431,6 +432,11 @@ void BrowserProcessImpl::SetApplicationLocale(const std::string& locale) { extension_l10n_util::SetProcessLocale(locale); } +void BrowserProcessImpl::CreateStatusTrayManager() { + DCHECK(status_tray_manager_.get() == NULL); + status_tray_manager_.reset(new StatusTrayManager()); +} + // The BrowserProcess object must outlive the file thread so we use traits // which don't do any management. template <> diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index 50ab5a2..118400e 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h @@ -140,6 +140,13 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe { return notification_ui_manager_.get(); } + virtual StatusTrayManager* status_tray_manager() { + DCHECK(CalledOnValidThread()); + if (!status_tray_manager_.get()) + CreateStatusTrayManager(); + return status_tray_manager_.get(); + } + virtual IconManager* icon_manager() { DCHECK(CalledOnValidThread()); if (!created_icon_manager_) @@ -235,6 +242,7 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe { void CreateGoogleURLTracker(); void CreateIntranetRedirectDetector(); void CreateNotificationUIManager(); + void CreateStatusTrayManager(); #if defined(IPC_MESSAGE_LOG_ENABLED) void SetIPCLoggingEnabledForChildProcesses(bool enabled); @@ -288,6 +296,9 @@ 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_icon_mac.h b/chrome/browser/cocoa/status_icons/status_icon_mac.h new file mode 100644 index 0000000..d606429 --- /dev/null +++ b/chrome/browser/cocoa/status_icons/status_icon_mac.h @@ -0,0 +1,48 @@ +// 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_COCOA_STATUS_ICONS_STATUS_ICON_MAC_H_ +#define CHROME_BROWSER_COCOA_STATUS_ICONS_STATUS_ICON_MAC_H_ + +#include <vector> + +#import <Cocoa/Cocoa.h> + +#include "base/scoped_nsobject.h" +#include "base/string16.h" +#include "chrome/browser/status_icons/status_icon.h" + +class SkBitmap; +@class NSStatusItem; +@class StatusItemController; + +class StatusIconMac : public StatusIcon { + public: + StatusIconMac(); + virtual ~StatusIconMac(); + + // Sets the image associated with this status icon. + virtual void SetImage(const SkBitmap& image); + + // Sets the hover text for this status icon. + virtual void SetToolTip(const string16& tool_tip); + + // Adds/removes a observer for status bar events. + virtual void AddObserver(StatusIcon::StatusIconObserver* observer); + virtual void RemoveObserver(StatusIcon::StatusIconObserver* observer); + + // Called back if the user clicks on the status bar icon. + void HandleClick(); + + private: + // Getter for item_ that allows lazy initialization. + NSStatusItem* item(); + scoped_nsobject<NSStatusItem> item_; + + scoped_nsobject<StatusItemController> controller_; + std::vector<StatusIcon::StatusIconObserver*> observers_; +}; + + +#endif // CHROME_BROWSER_COCOA_STATUS_ICONS_STATUS_ICON_MAC_H_ diff --git a/chrome/browser/cocoa/status_icons/status_icon_mac.mm b/chrome/browser/cocoa/status_icons/status_icon_mac.mm new file mode 100644 index 0000000..201b6d4 --- /dev/null +++ b/chrome/browser/cocoa/status_icons/status_icon_mac.mm @@ -0,0 +1,95 @@ +// 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/cocoa/status_icons/status_icon_mac.h" + +#include "base/logging.h" +#include "base/sys_string_conversions.h" +#include "skia/ext/skia_utils_mac.h" +#include "third_party/skia/include/core/SkBitmap.h" + +@interface StatusItemController : NSObject { + StatusIconMac* statusIcon_; // weak +} +- initWithIcon:(StatusIconMac*)icon; +- (void)handleClick:(id)sender; + +@end // @interface StatusItemController + +@implementation StatusItemController + +- (id)initWithIcon:(StatusIconMac*)icon { + statusIcon_ = icon; + return self; +} + +- (void)handleClick:(id)sender { + // Pass along the click notification to our owner. + DCHECK(statusIcon_); + statusIcon_->HandleClick(); +} + +@end + +StatusIconMac::StatusIconMac() + : item_(NULL) { + controller_.reset([[StatusItemController alloc] initWithIcon:this]); +} + +StatusIconMac::~StatusIconMac() { + // Remove the status item from the status bar. + if (item_) + [[NSStatusBar systemStatusBar] removeStatusItem:item_]; +} + +NSStatusItem* StatusIconMac::item() { + if (!item_.get()) { + // Create a new status item. + item_.reset([[[NSStatusBar systemStatusBar] + statusItemWithLength:NSSquareStatusItemLength] retain]); + [item_ setEnabled:YES]; + [item_ setTarget:controller_]; + [item_ setAction:@selector(handleClick:)]; + } + return item_.get(); +} + +void StatusIconMac::SetImage(const SkBitmap& bitmap) { + if (!bitmap.isNull()) { + NSImage* image = gfx::SkBitmapToNSImage(bitmap); + if (image) + [item() setImage:image]; + } +} + +void StatusIconMac::SetToolTip(const string16& tool_tip) { + [item() setToolTip:base::SysUTF16ToNSString(tool_tip)]; +} + +void StatusIconMac::AddObserver(StatusIconObserver* observer) { + observers_.push_back(observer); +} + +void StatusIconMac::RemoveObserver(StatusIconObserver* observer) { + std::vector<StatusIconObserver*>::iterator iter = + std::find(observers_.begin(), observers_.end(), observer); + if (iter != observers_.end()) + observers_.erase(iter); +} + +void StatusIconMac::HandleClick() { + // Walk observers, call callback for each one. + for (std::vector<StatusIconObserver*>::const_iterator iter = + observers_.begin(); + iter != observers_.end(); + ++iter) { + StatusIconObserver* observer = *iter; + observer->OnClicked(); + } +} + +// static factory method +StatusIcon* StatusIcon::Create() { + return new StatusIconMac(); +} diff --git a/chrome/browser/cocoa/status_icons/status_icon_mac_unittest.mm b/chrome/browser/cocoa/status_icons/status_icon_mac_unittest.mm new file mode 100644 index 0000000..4a7b284 --- /dev/null +++ b/chrome/browser/cocoa/status_icons/status_icon_mac_unittest.mm @@ -0,0 +1,57 @@ +// 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/resource_bundle.h" +#include "base/string_util.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "chrome/browser/cocoa/status_icons/status_icon_mac.h" +#include "grit/browser_resources.h" +#include "grit/theme_resources.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +class SkBitmap; + +class MockStatusIconObserver : public StatusIcon::StatusIconObserver { + public: + MOCK_METHOD0(OnClicked, void()); +}; + +class StatusIconMacTest : public CocoaTest { +}; + +TEST_F(StatusIconMacTest, Create) { + // Create an icon, set the tool tip, then shut it down (checks for leaks). + scoped_ptr<StatusIcon> icon(new StatusIconMac()); + SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_STATUS_TRAY_ICON); + icon->SetImage(*bitmap); + icon->SetToolTip(ASCIIToUTF16("tool tip")); +} + +TEST_F(StatusIconMacTest, ObserverAdd) { + // Make sure that observers are invoked when we click items. + StatusIconMac icon; + MockStatusIconObserver observer, observer2; + EXPECT_CALL(observer, OnClicked()).Times(2); + EXPECT_CALL(observer2, OnClicked()); + icon.AddObserver(&observer); + icon.HandleClick(); + icon.AddObserver(&observer2); + icon.HandleClick(); + icon.RemoveObserver(&observer); + icon.RemoveObserver(&observer2); +} + +TEST_F(StatusIconMacTest, ObserverRemove) { + // Make sure that observers are no longer invoked after they are removed. + StatusIconMac icon; + MockStatusIconObserver observer; + EXPECT_CALL(observer, OnClicked()); + icon.AddObserver(&observer); + icon.HandleClick(); + icon.RemoveObserver(&observer); + icon.HandleClick(); +} + diff --git a/chrome/browser/status_icons/status_icon.h b/chrome/browser/status_icons/status_icon.h new file mode 100644 index 0000000..aeefdfe --- /dev/null +++ b/chrome/browser/status_icons/status_icon.h @@ -0,0 +1,39 @@ +// 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_ICON_H_ +#define CHROME_BROWSER_STATUS_ICONS_STATUS_ICON_H_ + +#include "base/string16.h" + +class SkBitmap; + +class StatusIcon { + public: + // Creates a new StatusIcon. + static StatusIcon* Create(); + + virtual ~StatusIcon() {} + + // Sets the image associated with this status icon. + virtual void SetImage(const SkBitmap& image) = 0; + + // Sets the hover text for this status icon. + virtual void SetToolTip(const string16& tool_tip) = 0; + + class StatusIconObserver { + public: + virtual ~StatusIconObserver() {} + + // Called when the user clicks on the system tray icon. + virtual void OnClicked() = 0; + }; + + // Adds/removes a observer for status bar events. + virtual void AddObserver(StatusIcon::StatusIconObserver* observer) = 0; + virtual void RemoveObserver(StatusIcon::StatusIconObserver* observer) = 0; +}; + + +#endif // CHROME_BROWSER_STATUS_ICONS_STATUS_ICON_H_ diff --git a/chrome/browser/status_icons/status_tray.cc b/chrome/browser/status_icons/status_tray.cc new file mode 100644 index 0000000..1415babe --- /dev/null +++ b/chrome/browser/status_icons/status_tray.cc @@ -0,0 +1,40 @@ +// 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" + +#include "base/stl_util-inl.h" +#include "chrome/browser/status_icons/status_icon.h" + +StatusTray::StatusTray(StatusIconFactory* factory) + : factory_(factory) { +} + +StatusTray::~StatusTray() { + // Walk any active status icons and delete them. + STLDeleteContainerPairSecondPointers(status_icons_.begin(), + status_icons_.end()); +} + +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 = factory_->CreateIcon(); + if (icon) + status_icons_[identifier] = icon; + return icon; +} + +void StatusTray::RemoveStatusIcon(const string16& identifier) { + StatusIconMap::iterator iter = status_icons_.find(identifier); + 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; + status_icons_.erase(iter); + } +} diff --git a/chrome/browser/status_icons/status_tray.h b/chrome/browser/status_icons/status_tray.h new file mode 100644 index 0000000..663bfa8 --- /dev/null +++ b/chrome/browser/status_icons/status_tray.h @@ -0,0 +1,47 @@ +// 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_H_ +#define CHROME_BROWSER_STATUS_ICONS_STATUS_TRAY_H_ + +#include "base/hash_tables.h" +#include "base/scoped_ptr.h" + +class StatusIcon; + +// Factory interface for creating icons to improve testability. +class StatusIconFactory { + public: + virtual StatusIcon* CreateIcon() = 0; + virtual ~StatusIconFactory() { } +}; + +// Provides a cross-platform interface to the system's status tray, and exposes +// APIs to add/remove icons to the tray and attach context menus. +class StatusTray { + public: + // Takes ownership of |factory|. + explicit StatusTray(StatusIconFactory* factory); + ~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); + + // Removes the current status icon associated with this identifier, if any. + void RemoveStatusIcon(const string16& identifier); + + private: + typedef base::hash_map<string16, StatusIcon*> StatusIconMap; + // 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_; + + scoped_ptr<StatusIconFactory> factory_; +}; + +#endif // CHROME_BROWSER_STATUS_ICONS_STATUS_TRAY_H_ diff --git a/chrome/browser/status_icons/status_tray_manager.cc b/chrome/browser/status_icons/status_tray_manager.cc new file mode 100644 index 0000000..26d0840 --- /dev/null +++ b/chrome/browser/status_icons/status_tray_manager.cc @@ -0,0 +1,63 @@ +// 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/resource_bundle.h" +#include "base/logging.h" +#include "base/string_util.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/theme_resources.h" + +class StatusIconFactoryImpl : public StatusIconFactory { + public: + virtual StatusIcon* CreateIcon(); +}; + +StatusIcon* StatusIconFactoryImpl::CreateIcon() { +#ifdef OS_MACOSX + return StatusIcon::Create(); +#else + // TODO(atwilson): Add support for non-Mac platforms. + return 0; +#endif +} + + +StatusTrayManager::StatusTrayManager() { +} + +StatusTrayManager::~StatusTrayManager() { +} + +void StatusTrayManager::Init(Profile* profile) { + DCHECK(profile); + profile_ = profile; + status_tray_.reset(new StatusTray(new StatusIconFactoryImpl())); + 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); + icon->SetImage(*bitmap); + icon->AddObserver(this); + } +} + +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 new file mode 100644 index 0000000..9f9d2d7 --- /dev/null +++ b/chrome/browser/status_icons/status_tray_manager.h @@ -0,0 +1,30 @@ +// 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_ + +#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::StatusIconObserver { + public: + StatusTrayManager(); + virtual ~StatusTrayManager(); + + void Init(Profile* profile); + + private: + // StatusIcon::StatusIconObserver callbacks + 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 new file mode 100644 index 0000000..01f9c30 --- /dev/null +++ b/chrome/browser/status_icons/status_tray_unittest.cc @@ -0,0 +1,56 @@ +// 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 "base/string_util.h" +#include "chrome/browser/status_icons/status_icon.h" +#include "chrome/browser/status_icons/status_tray.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::Return; + +class MockStatusIcon : public StatusIcon { + virtual void SetImage(const SkBitmap& image) {} + virtual void SetToolTip(const string16& tool_tip) {} + virtual void AddObserver(StatusIcon::StatusIconObserver* observer) {} + virtual void RemoveObserver(StatusIcon::StatusIconObserver* observer) {} +}; + +class TestStatusIconFactory : public StatusIconFactory { + public: + MOCK_METHOD0(CreateIcon, StatusIcon*()); +}; + +TEST(StatusTrayTest, Create) { + // Check for creation and leaks. + TestStatusIconFactory* factory = new TestStatusIconFactory(); + StatusTray tray(factory); + EXPECT_CALL(*factory, CreateIcon()).WillOnce(Return(new MockStatusIcon())); + tray.GetStatusIcon(ASCIIToUTF16("test")); +} + +TEST(StatusTrayTest, GetIconTwice) { + TestStatusIconFactory* factory = new TestStatusIconFactory(); + StatusTray tray(factory); + string16 id = ASCIIToUTF16("test"); + // We should not try to create a new icon if we get the same ID twice. + EXPECT_CALL(*factory, CreateIcon()).WillOnce(Return(new MockStatusIcon())); + StatusIcon* icon = tray.GetStatusIcon(id); + EXPECT_EQ(icon, tray.GetStatusIcon(id)); +} + +TEST(StatusTrayTest, GetIconAfterRemove) { + TestStatusIconFactory* factory = new TestStatusIconFactory(); + StatusTray tray(factory); + string16 id = ASCIIToUTF16("test"); + EXPECT_CALL(*factory, CreateIcon()).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); +} diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 2252f69..7ffacbd 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -690,6 +690,8 @@ 'browser/cocoa/shell_dialogs_mac.mm', 'browser/cocoa/status_bubble_mac.h', 'browser/cocoa/status_bubble_mac.mm', + 'browser/cocoa/status_icons/status_icon_mac.h', + 'browser/cocoa/status_icons/status_icon_mac.mm', 'browser/cocoa/styled_text_field.h', 'browser/cocoa/styled_text_field.mm', 'browser/cocoa/styled_text_field_cell.h', @@ -1798,6 +1800,11 @@ 'browser/ssl/ssl_policy_backend.h', 'browser/ssl/ssl_request_info.h', 'browser/status_bubble.h', + 'browser/status_icons/status_tray.cc', + 'browser/status_icons/status_tray.h', + 'browser/status_icons/status_tray_manager.cc', + 'browser/status_icons/status_tray_manager.h', + 'browser/status_icons/status_icon.h', 'browser/transport_security_persister.cc', 'browser/transport_security_persister.h', 'browser/sync/engine/syncapi.h', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index ad8390d..dd3a75f 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -684,6 +684,7 @@ 'browser/cocoa/search_engine_list_model_unittest.mm', 'browser/cocoa/section_separator_view_unittest.mm', 'browser/cocoa/status_bubble_mac_unittest.mm', + 'browser/cocoa/status_icons/status_icon_mac_unittest.mm', 'browser/cocoa/styled_text_field_test_helper.h', 'browser/cocoa/styled_text_field_test_helper.mm', 'browser/cocoa/styled_text_field_unittest.mm', @@ -841,6 +842,7 @@ 'browser/shell_integration_unittest.cc', 'browser/spellchecker_platform_engine_unittest.cc', 'browser/ssl/ssl_host_state_unittest.cc', + 'browser/status_icons/status_tray_unittest.cc', 'browser/sync/glue/change_processor_mock.h', 'browser/sync/glue/data_type_controller_mock.h', 'browser/sync/glue/data_type_manager_impl_unittest.cc', diff --git a/chrome/test/testing_browser_process.h b/chrome/test/testing_browser_process.h index 690f8af..47a75e1 100644 --- a/chrome/test/testing_browser_process.h +++ b/chrome/test/testing_browser_process.h @@ -110,6 +110,10 @@ class TestingBrowserProcess : public BrowserProcess { return NULL; } + virtual StatusTrayManager* status_tray_manager() { + return NULL; + } + virtual GoogleURLTracker* google_url_tracker() { return NULL; } |