summaryrefslogtreecommitdiffstats
path: root/chrome/browser/status_icons
diff options
context:
space:
mode:
authoratwilson@chromium.org <atwilson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-06 22:02:04 +0000
committeratwilson@chromium.org <atwilson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-06 22:02:04 +0000
commitccb55cf5b25fd67078e51b924cf6e694d7374376 (patch)
treeb04cd09754ea2cdc2ee6d333166de81688a97c8e /chrome/browser/status_icons
parent42695f09883e29aa167b79ad75263e3d611dce2d (diff)
downloadchromium_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.h39
-rw-r--r--chrome/browser/status_icons/status_tray.cc40
-rw-r--r--chrome/browser/status_icons/status_tray.h47
-rw-r--r--chrome/browser/status_icons/status_tray_manager.cc63
-rw-r--r--chrome/browser/status_icons/status_tray_manager.h30
-rw-r--r--chrome/browser/status_icons/status_tray_unittest.cc56
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);
+}