summaryrefslogtreecommitdiffstats
path: root/chrome/browser/status_icons
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/status_icons')
-rw-r--r--chrome/browser/status_icons/status_icon.cc18
-rw-r--r--chrome/browser/status_icons/status_icon.h36
-rw-r--r--chrome/browser/status_icons/status_icon_unittest.cc2
-rw-r--r--chrome/browser/status_icons/status_tray.cc26
-rw-r--r--chrome/browser/status_icons/status_tray.h36
-rw-r--r--chrome/browser/status_icons/status_tray_manager.cc56
-rw-r--r--chrome/browser/status_icons/status_tray_manager.h30
-rw-r--r--chrome/browser/status_icons/status_tray_unittest.cc40
8 files changed, 98 insertions, 146 deletions
diff --git a/chrome/browser/status_icons/status_icon.cc b/chrome/browser/status_icons/status_icon.cc
index 9fed83d..baaa6cc 100644
--- a/chrome/browser/status_icons/status_icon.cc
+++ b/chrome/browser/status_icons/status_icon.cc
@@ -4,6 +4,15 @@
#include "chrome/browser/status_icons/status_icon.h"
+#include "app/menus/menu_model.h"
+
+StatusIcon::StatusIcon()
+{
+}
+
+StatusIcon::~StatusIcon() {
+}
+
void StatusIcon::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
@@ -12,6 +21,15 @@ void StatusIcon::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
+bool StatusIcon::HasObservers() {
+ return observers_.size() > 0;
+}
+
void StatusIcon::DispatchClickEvent() {
FOR_EACH_OBSERVER(Observer, observers_, OnClicked());
}
+
+void StatusIcon::SetContextMenu(menus::MenuModel* menu) {
+ context_menu_contents_.reset(menu);
+ UpdatePlatformContextMenu(menu);
+}
diff --git a/chrome/browser/status_icons/status_icon.h b/chrome/browser/status_icons/status_icon.h
index ffe0f5f..5398eb3 100644
--- a/chrome/browser/status_icons/status_icon.h
+++ b/chrome/browser/status_icons/status_icon.h
@@ -4,16 +4,22 @@
#ifndef CHROME_BROWSER_STATUS_ICONS_STATUS_ICON_H_
#define CHROME_BROWSER_STATUS_ICONS_STATUS_ICON_H_
+#pragma once
#include "base/observer_list.h"
+#include "base/scoped_ptr.h"
#include "base/string16.h"
class SkBitmap;
+namespace menus {
+class MenuModel;
+}
+
class StatusIcon {
public:
- StatusIcon() {}
- virtual ~StatusIcon() {}
+ StatusIcon();
+ virtual ~StatusIcon();
// Sets the image associated with this status icon.
virtual void SetImage(const SkBitmap& image) = 0;
@@ -24,23 +30,45 @@ class StatusIcon {
// Sets the hover text for this status icon.
virtual void SetToolTip(const string16& tool_tip) = 0;
+ // Set the context menu for this icon. The icon takes ownership of the passed
+ // context menu. Passing NULL results in no menu at all.
+ void SetContextMenu(menus::MenuModel* menu);
+
class Observer {
public:
virtual ~Observer() {}
- // Called when the user clicks on the system tray icon.
+ // Called when the user clicks on the system tray icon. Clicks that result
+ // in the context menu being displayed will not be passed to this observer
+ // (i.e. if there's a context menu set on this status icon, and the user
+ // right clicks on the icon to display the context menu, OnClicked will not
+ // be called).
virtual void OnClicked() = 0;
};
- // Adds/Removes an observer for status bar events.
+ // Adds/Removes an observer for clicks on the status icon. If an observer is
+ // registered, then left clicks on the status icon will result in the observer
+ // being called, otherwise, both left and right clicks will display the
+ // context menu (if any).
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
+ // Returns true if there are registered click observers.
+ bool HasObservers();
+
// Dispatches a click event to the observers.
void DispatchClickEvent();
+ protected:
+ // Invoked after a call to SetContextMenu() to let the platform-specific
+ // subclass update the native context menu based on the new model. If NULL is
+ // passed, subclass should destroy the native context menu.
+ virtual void UpdatePlatformContextMenu(menus::MenuModel* model) = 0;
+
private:
ObserverList<Observer> observers_;
+ // Context menu, if any.
+ scoped_ptr<menus::MenuModel> context_menu_contents_;
DISALLOW_COPY_AND_ASSIGN(StatusIcon);
};
diff --git a/chrome/browser/status_icons/status_icon_unittest.cc b/chrome/browser/status_icons/status_icon_unittest.cc
index db8c529..48fbc20 100644
--- a/chrome/browser/status_icons/status_icon_unittest.cc
+++ b/chrome/browser/status_icons/status_icon_unittest.cc
@@ -18,6 +18,7 @@ class TestStatusIcon : public StatusIcon {
virtual void SetImage(const SkBitmap& image) {}
virtual void SetPressedImage(const SkBitmap& image) {}
virtual void SetToolTip(const string16& tool_tip) {}
+ virtual void UpdatePlatformContextMenu(menus::MenuModel* menu) {}
};
TEST(StatusIconTest, ObserverAdd) {
@@ -44,4 +45,3 @@ TEST(StatusIconTest, ObserverRemove) {
icon.RemoveObserver(&observer);
icon.DispatchClickEvent();
}
-
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 30a60aa..a0da771 100644
--- a/chrome/browser/status_icons/status_tray.h
+++ b/chrome/browser/status_icons/status_tray.h
@@ -4,9 +4,12 @@
#ifndef CHROME_BROWSER_STATUS_ICONS_STATUS_TRAY_H_
#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;
@@ -15,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 7a8a779..0000000
--- a/chrome/browser/status_icons/status_tray_manager.cc
+++ /dev/null
@@ -1,56 +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 "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() {
-}
-
-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 2a880e4..0000000
--- a/chrome/browser/status_icons/status_tray_manager.h
+++ /dev/null
@@ -1,30 +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_
-
-#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 9b60010..a047689 100644
--- a/chrome/browser/status_icons/status_tray_unittest.cc
+++ b/chrome/browser/status_icons/status_tray_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/status_icons/status_icon.h"
#include "chrome/browser/status_icons/status_tray.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -14,41 +15,34 @@ class MockStatusIcon : public StatusIcon {
virtual void SetImage(const SkBitmap& image) {}
virtual void SetPressedImage(const SkBitmap& image) {}
virtual void SetToolTip(const string16& tool_tip) {}
+ virtual void UpdatePlatformContextMenu(menus::MenuModel* menu) {}
virtual void AddObserver(StatusIcon::Observer* observer) {}
virtual void RemoveObserver(StatusIcon::Observer* observer) {}
};
class TestStatusTray : public StatusTray {
public:
- MOCK_METHOD0(CreateStatusIcon, StatusIcon*());
+ MOCK_METHOD0(CreatePlatformStatusIcon, StatusIcon*());
+ MOCK_METHOD1(UpdatePlatformContextMenu, void(menus::MenuModel*));
};
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);
}