diff options
author | atwilson@chromium.org <atwilson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-06 22:02:04 +0000 |
---|---|---|
committer | atwilson@chromium.org <atwilson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-06 22:02:04 +0000 |
commit | ccb55cf5b25fd67078e51b924cf6e694d7374376 (patch) | |
tree | b04cd09754ea2cdc2ee6d333166de81688a97c8e /chrome/browser/status_icons | |
parent | 42695f09883e29aa167b79ad75263e3d611dce2d (diff) | |
download | chromium_src-ccb55cf5b25fd67078e51b924cf6e694d7374376.zip chromium_src-ccb55cf5b25fd67078e51b924cf6e694d7374376.tar.gz chromium_src-ccb55cf5b25fd67078e51b924cf6e694d7374376.tar.bz2 |
Initial implementation of status tray functionality (mac-only, currently).
Added Mac implementation of StatusIcon, and added a simple click callback that
displays the "extensions" tab when clicked on, to allow us to dogfood long-lived
extensions.
BUG=37375
Review URL: http://codereview.chromium.org/661454
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40847 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/status_icons')
-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 |
6 files changed, 275 insertions, 0 deletions
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); +} |