diff options
36 files changed, 346 insertions, 233 deletions
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd index 4416ca6..4668d4b 100644 --- a/chrome/app/chromium_strings.grd +++ b/chrome/app/chromium_strings.grd @@ -1005,6 +1005,23 @@ Signing in anyway will merge Chromium information like bookmarks, history, and o You can see all your notifications from Chromium apps, extensions, and websites here. </message> </if> + <message name="IDS_MESSAGE_CENTER_TOOLTIP" desc="Tooltip for notification tray icon without unread notifications"> + Chromium - Notifications + </message> + <message name="IDS_MESSAGE_CENTER_TOOLTIP_UNREAD" desc="Tooltip for notification tray icon with unread notifications"> + Chromium - Notifications (<ph name="QUANTITY">$1<ex>3</ex></ph> unread) + </message> + + <!-- MediaStream capture status tray icon --> + <message name="IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_AUDIO_AND_VIDEO" desc="Tool tip for the capture status tray icon when microphone and camera are being used"> + Chromium is using your camera and microphone. + </message> + <message name="IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_AUDIO_ONLY" desc="Tool tip for the capture status tray icon when microphone is being used"> + Chromium is using your microphone. + </message> + <message name="IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_VIDEO_ONLY" desc="Tool tip for the capture status tray icon when camera is being used"> + Chromium is using your camera. + </message> </messages> </release> </grit> diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index d12eb0d..bb002dd 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -15094,17 +15094,6 @@ Some features may be unavailable. Please check that the profile exists and you Deny </message> - <!-- MediaStream capture status tray icon --> - <message name="IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_AUDIO_AND_VIDEO" desc="Tool tip for the capture status tray icon when microphone and camera are being used"> - <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> is using your camera and microphone. - </message> - <message name="IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_AUDIO_ONLY" desc="Tool tip for the capture status tray icon when microphone is being used"> - <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> is using your microphone. - </message> - <message name="IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_VIDEO_ONLY" desc="Tool tip for the capture status tray icon when camera is being used"> - <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> is using your camera. - </message> - <!-- Quota messages --> <if expr="is_android"> <message name="IDS_REQUEST_QUOTA_INFOBAR_QUESTION" desc="Mobile: For Android device. Question asked on the info bar whenever webapp requests new (larger) quota to persistently store data on the device (e.g. for persistent-type filesystem)."> diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd index b9db382..6824d4c 100644 --- a/chrome/app/google_chrome_strings.grd +++ b/chrome/app/google_chrome_strings.grd @@ -930,6 +930,23 @@ Signing in anyway will merge Chrome information like bookmarks, history, and oth You can see all your notifications from Chrome apps, extensions, and websites here. </message> </if> + <message name="IDS_MESSAGE_CENTER_TOOLTIP" desc="Tooltip for notification tray icon without unread notifications"> + Chrome - Notifications + </message> + <message name="IDS_MESSAGE_CENTER_TOOLTIP_UNREAD" desc="Tooltip for notification tray icon with unread notifications"> + Chrome - Notifications (<ph name="QUANTITY">$1<ex>3</ex></ph> unread) + </message> + + <!-- MediaStream capture status tray icon --> + <message name="IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_AUDIO_AND_VIDEO" desc="Tool tip for the capture status tray icon when microphone and camera are being used"> + Google Chrome is using your camera and microphone. + </message> + <message name="IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_AUDIO_ONLY" desc="Tool tip for the capture status tray icon when microphone is being used"> + Google Chrome is using your microphone. + </message> + <message name="IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_VIDEO_ONLY" desc="Tool tip for the capture status tray icon when camera is being used"> + Google Chrome is using your camera. + </message> </messages> </release> </grit> diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc index b925aba..579f031 100644 --- a/chrome/browser/background/background_mode_manager.cc +++ b/chrome/browser/background/background_mode_manager.cc @@ -665,17 +665,16 @@ void BackgroundModeManager::CreateStatusTrayIcon() { if (!status_tray_ || status_icon_) return; - status_icon_ = - status_tray_->CreateStatusIcon(StatusTray::BACKGROUND_MODE_ICON); - if (!status_icon_) - return; - - // Set the image and add ourselves as a click observer on it. // TODO(rlp): Status tray icon should have submenus for each profile. gfx::ImageSkia* image_skia = ui::ResourceBundle::GetSharedInstance(). GetImageSkiaNamed(IDR_STATUS_TRAY_ICON); - status_icon_->SetImage(*image_skia); - status_icon_->SetToolTip(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); + + status_icon_ = status_tray_->CreateStatusIcon( + StatusTray::BACKGROUND_MODE_ICON, + *image_skia, + l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); + if (!status_icon_) + return; UpdateStatusTrayIconContextMenu(); } diff --git a/chrome/browser/extensions/api/system_indicator/system_indicator_manager.cc b/chrome/browser/extensions/api/system_indicator/system_indicator_manager.cc index 4297abe..a7601f0 100644 --- a/chrome/browser/extensions/api/system_indicator/system_indicator_manager.cc +++ b/chrome/browser/extensions/api/system_indicator/system_indicator_manager.cc @@ -5,6 +5,7 @@ #include "chrome/browser/extensions/api/system_indicator/system_indicator_manager.h" #include "base/memory/linked_ptr.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/event_names.h" #include "chrome/browser/extensions/event_router.h" @@ -30,11 +31,10 @@ namespace extensions { class ExtensionIndicatorIcon : public StatusIconObserver, public ExtensionActionIconFactory::Observer { public: - ExtensionIndicatorIcon(const Extension* extension, - const ExtensionAction* action, - Profile* profile, - StatusTray* status_tray, - StatusIcon* status_icon); + static ExtensionIndicatorIcon* Create(const Extension* extension, + const ExtensionAction* action, + Profile* profile, + StatusTray* status_tray); virtual ~ExtensionIndicatorIcon(); // StatusIconObserver implementation. @@ -44,6 +44,11 @@ class ExtensionIndicatorIcon : public StatusIconObserver, virtual void OnIconUpdated() OVERRIDE; private: + ExtensionIndicatorIcon(const Extension* extension, + const ExtensionAction* action, + Profile* profile, + StatusTray* status_tray); + const extensions::Extension* extension_; StatusTray* status_tray_; StatusIcon* icon_; @@ -51,23 +56,27 @@ class ExtensionIndicatorIcon : public StatusIconObserver, ExtensionActionIconFactory icon_factory_; }; -ExtensionIndicatorIcon::ExtensionIndicatorIcon(const Extension* extension, - const ExtensionAction* action, - Profile* profile, - StatusTray* status_tray, - StatusIcon* status_icon) - : extension_(extension), - status_tray_(status_tray), - icon_(status_icon), - profile_(profile), - icon_factory_(profile, extension, action, this) { - icon_->AddObserver(this); - OnIconUpdated(); +ExtensionIndicatorIcon* ExtensionIndicatorIcon::Create( + const Extension* extension, + const ExtensionAction* action, + Profile* profile, + StatusTray* status_tray) { + scoped_ptr<ExtensionIndicatorIcon> extension_icon( + new ExtensionIndicatorIcon(extension, action, profile, status_tray)); + + // Check if a status icon was successfully created. + if (extension_icon->icon_) + return extension_icon.release(); + + // We could not create a status icon. + return NULL; } ExtensionIndicatorIcon::~ExtensionIndicatorIcon() { - icon_->RemoveObserver(this); - status_tray_->RemoveStatusIcon(icon_); + if (icon_) { + icon_->RemoveObserver(this); + status_tray_->RemoveStatusIcon(icon_); + } } void ExtensionIndicatorIcon::OnStatusIconClicked() { @@ -89,10 +98,30 @@ void ExtensionIndicatorIcon::OnIconUpdated() { icon_factory_.GetIcon(ExtensionAction::kDefaultTabId).AsImageSkia()); } +ExtensionIndicatorIcon::ExtensionIndicatorIcon(const Extension* extension, + const ExtensionAction* action, + Profile* profile, + StatusTray* status_tray) + : extension_(extension), + status_tray_(status_tray), + icon_(NULL), + profile_(profile), + icon_factory_(profile, extension, action, this) { + // Get the icon image and tool tip for the status icon. The extension name is + // used as the tool tip. + gfx::ImageSkia icon_image = + icon_factory_.GetIcon(ExtensionAction::kDefaultTabId).AsImageSkia(); + string16 tool_tip = UTF8ToUTF16(extension_->name()); + + icon_ = status_tray_->CreateStatusIcon( + StatusTray::OTHER_ICON, icon_image, tool_tip); + if (icon_) + icon_->AddObserver(this); +} + SystemIndicatorManager::SystemIndicatorManager(Profile* profile, StatusTray* status_tray) - : profile_(profile), - status_tray_(status_tray) { + : profile_(profile), status_tray_(status_tray) { registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, content::Source<Profile>(profile_->GetOriginalProfile())); registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_SYSTEM_INDICATOR_UPDATED, @@ -167,17 +196,10 @@ void SystemIndicatorManager::CreateOrUpdateIndicator( return; } - StatusIcon* indicator_icon = - status_tray_->CreateStatusIcon(StatusTray::OTHER_ICON); - if (indicator_icon != NULL) { - ExtensionIndicatorIcon* status_icon = new ExtensionIndicatorIcon( - extension, - extension_action, - profile_, - status_tray_, - indicator_icon); - system_indicators_[extension->id()] = make_linked_ptr(status_icon); - } + ExtensionIndicatorIcon* extension_icon = ExtensionIndicatorIcon::Create( + extension, extension_action, profile_, status_tray_); + if (extension_icon) + system_indicators_[extension->id()] = make_linked_ptr(extension_icon); } void SystemIndicatorManager::RemoveIndicator(const std::string& extension_id) { diff --git a/chrome/browser/media/media_stream_capture_indicator.cc b/chrome/browser/media/media_stream_capture_indicator.cc index 456fc9d..50e4ea7 100644 --- a/chrome/browser/media/media_stream_capture_indicator.cc +++ b/chrome/browser/media/media_stream_capture_indicator.cc @@ -366,7 +366,8 @@ void MediaStreamCaptureIndicator::UnregisterWebContents( UpdateNotificationUserInterface(); } -void MediaStreamCaptureIndicator::MaybeCreateStatusTrayIcon() { +void MediaStreamCaptureIndicator::MaybeCreateStatusTrayIcon(bool audio, + bool video) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (status_icon_) return; @@ -379,10 +380,16 @@ void MediaStreamCaptureIndicator::MaybeCreateStatusTrayIcon() { if (!status_tray) return; - status_icon_ = - status_tray->CreateStatusIcon(StatusTray::MEDIA_STREAM_CAPTURE_ICON); - EnsureStatusTrayIconResources(); + + gfx::ImageSkia image; + string16 tool_tip; + GetStatusTrayIconInfo(audio, video, &image, &tool_tip); + DCHECK(!image.isNull()); + DCHECK(!tool_tip.empty()); + + status_icon_ = status_tray->CreateStatusIcon( + StatusTray::MEDIA_STREAM_CAPTURE_ICON, image, tool_tip); } void MediaStreamCaptureIndicator::EnsureStatusTrayIconResources() { @@ -481,32 +488,32 @@ void MediaStreamCaptureIndicator::UpdateNotificationUserInterface() { } // The icon will take the ownership of the passed context menu. - MaybeCreateStatusTrayIcon(); + MaybeCreateStatusTrayIcon(audio, video); if (status_icon_) { status_icon_->SetContextMenu(menu.release()); - UpdateStatusTrayIconDisplay(audio, video); } } -void MediaStreamCaptureIndicator::UpdateStatusTrayIconDisplay( - bool audio, bool video) { +void MediaStreamCaptureIndicator::GetStatusTrayIconInfo(bool audio, + bool video, + gfx::ImageSkia* image, + string16* tool_tip) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(audio || video); - DCHECK(status_icon_); + int message_id = 0; if (audio && video) { message_id = IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_AUDIO_AND_VIDEO; - status_icon_->SetImage(*camera_image_); + *image = *camera_image_; } else if (audio && !video) { message_id = IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_AUDIO_ONLY; - status_icon_->SetImage(*mic_image_); + *image = *mic_image_; } else if (!audio && video) { message_id = IDS_MEDIA_STREAM_STATUS_TRAY_TEXT_VIDEO_ONLY; - status_icon_->SetImage(*camera_image_); + *image = *camera_image_; } - status_icon_->SetToolTip(l10n_util::GetStringFUTF16( - message_id, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); + *tool_tip = l10n_util::GetStringUTF16(message_id); } void MediaStreamCaptureIndicator::OnStopScreenCapture( diff --git a/chrome/browser/media/media_stream_capture_indicator.h b/chrome/browser/media/media_stream_capture_indicator.h index 4c311cf..9fc861e 100644 --- a/chrome/browser/media/media_stream_capture_indicator.h +++ b/chrome/browser/media/media_stream_capture_indicator.h @@ -84,9 +84,14 @@ class MediaStreamCaptureIndicator // Helpers to create and destroy status tray icon. Called from // UpdateNotificationUserInterface(). void EnsureStatusTrayIconResources(); - void MaybeCreateStatusTrayIcon(); + void MaybeCreateStatusTrayIcon(bool audio, bool video); void MaybeDestroyStatusTrayIcon(); - void UpdateStatusTrayIconDisplay(bool audio, bool video); + + // Gets the status icon image and the string to use as the tooltip. + void GetStatusTrayIconInfo(bool audio, + bool video, + gfx::ImageSkia* image, + string16* tool_tip); // Callback for ScreenCaptureNotificationUI. void OnStopScreenCapture(const base::Closure& stop); diff --git a/chrome/browser/status_icons/status_icon.cc b/chrome/browser/status_icons/status_icon.cc index 79efafc..00270d2 100644 --- a/chrome/browser/status_icons/status_icon.cc +++ b/chrome/browser/status_icons/status_icon.cc @@ -29,9 +29,6 @@ void StatusIcon::DispatchClickEvent() { FOR_EACH_OBSERVER(StatusIconObserver, observers_, OnStatusIconClicked()); } -void StatusIcon::SetClickActionLabel(const string16& label) { -} - #if defined(OS_WIN) void StatusIcon::DispatchBalloonClickEvent() { FOR_EACH_OBSERVER(StatusIconObserver, observers_, OnBalloonClicked()); diff --git a/chrome/browser/status_icons/status_icon.h b/chrome/browser/status_icons/status_icon.h index 6110c64..ccc8c2e 100644 --- a/chrome/browser/status_icons/status_icon.h +++ b/chrome/browser/status_icons/status_icon.h @@ -31,15 +31,12 @@ class StatusIcon { // Sets the image associated with this status icon when pressed. virtual void SetPressedImage(const gfx::ImageSkia& image) = 0; - // Sets the hover text for this status icon. + // Sets the hover text for this status icon. This is also used as the label + // for the menu item which is created as a replacement for the status icon + // click action on platforms that do not support custom click actions for the + // status icon (e.g. Ubuntu Unity). virtual void SetToolTip(const string16& tool_tip) = 0; - // Sets the label for the menu item which is created as a replacement for the - // status icon click action on platforms that do not support custom click - // actions for the status icon (e.g. Ubuntu Unity). Since only a few platforms - // would need this, the default action is to ignore the call. - virtual void SetClickActionLabel(const string16& label); - // Displays a notification balloon with the specified contents. // Depending on the platform it might not appear by the icon tray. virtual void DisplayBalloon(const gfx::ImageSkia& icon, diff --git a/chrome/browser/status_icons/status_tray.cc b/chrome/browser/status_icons/status_tray.cc index aaa7a57..bdd11da 100644 --- a/chrome/browser/status_icons/status_tray.cc +++ b/chrome/browser/status_icons/status_tray.cc @@ -11,8 +11,10 @@ StatusTray::~StatusTray() { } -StatusIcon* StatusTray::CreateStatusIcon(StatusIconType type) { - StatusIcon* icon = CreatePlatformStatusIcon(type); +StatusIcon* StatusTray::CreateStatusIcon(StatusIconType type, + const gfx::ImageSkia& image, + const string16& tool_tip) { + StatusIcon* icon = CreatePlatformStatusIcon(type, image, tool_tip); if (icon) status_icons_.push_back(icon); return icon; diff --git a/chrome/browser/status_icons/status_tray.h b/chrome/browser/status_icons/status_tray.h index e4f240d..1c4be06 100644 --- a/chrome/browser/status_icons/status_tray.h +++ b/chrome/browser/status_icons/status_tray.h @@ -8,6 +8,11 @@ #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/memory/scoped_vector.h" +#include "base/strings/string16.h" + +namespace gfx { +class ImageSkia; +} class StatusIcon; @@ -32,7 +37,9 @@ class StatusTray { // Creates a new StatusIcon. The StatusTray retains ownership of the // StatusIcon. Returns NULL if the StatusIcon could not be created. - StatusIcon* CreateStatusIcon(StatusIconType type); + StatusIcon* CreateStatusIcon(StatusIconType type, + const gfx::ImageSkia& image, + const string16& tool_tip); // Removes |icon| from this status tray. void RemoveStatusIcon(StatusIcon* icon); @@ -43,7 +50,9 @@ class StatusTray { StatusTray(); // Factory method for creating a status icon for this platform. - virtual StatusIcon* CreatePlatformStatusIcon(StatusIconType type) = 0; + virtual StatusIcon* CreatePlatformStatusIcon(StatusIconType type, + const gfx::ImageSkia& image, + const string16& tool_tip) = 0; // Returns the list of active status icons so subclasses can operate on them. const StatusIcons& status_icons() const { return status_icons_; } diff --git a/chrome/browser/status_icons/status_tray_unittest.cc b/chrome/browser/status_icons/status_tray_unittest.cc index a71fa9a..238d8b7 100644 --- a/chrome/browser/status_icons/status_tray_unittest.cc +++ b/chrome/browser/status_icons/status_tray_unittest.cc @@ -7,10 +7,10 @@ #include "base/strings/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" +#include "grit/chrome_unscaled_resources.h" #include "testing/gtest/include/gtest/gtest.h" - -using testing::Return; +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/image/image_skia.h" class MockStatusIcon : public StatusIcon { virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE {} @@ -24,9 +24,12 @@ class MockStatusIcon : public StatusIcon { class TestStatusTray : public StatusTray { public: - MOCK_METHOD1(CreatePlatformStatusIcon, - StatusIcon*(StatusTray::StatusIconType type)); - MOCK_METHOD1(UpdatePlatformContextMenu, void(ui::MenuModel*)); + virtual StatusIcon* CreatePlatformStatusIcon( + StatusIconType type, + const gfx::ImageSkia& image, + const string16& tool_tip) OVERRIDE { + return new MockStatusIcon(); + } const StatusIcons& GetStatusIconsForTest() const { return status_icons(); } }; @@ -34,17 +37,20 @@ class TestStatusTray : public StatusTray { TEST(StatusTrayTest, Create) { // Check for creation and leaks. TestStatusTray tray; - EXPECT_CALL(tray, CreatePlatformStatusIcon(StatusTray::OTHER_ICON)).WillOnce( - Return(new MockStatusIcon())); - tray.CreateStatusIcon(StatusTray::OTHER_ICON); + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); + gfx::ImageSkia* image = rb.GetImageSkiaNamed(IDR_STATUS_TRAY_ICON); + tray.CreateStatusIcon( + StatusTray::OTHER_ICON, *image, ASCIIToUTF16("tool tip")); + EXPECT_EQ(1U, tray.GetStatusIconsForTest().size()); } // Make sure that removing an icon removes it from the list. TEST(StatusTrayTest, CreateRemove) { TestStatusTray tray; - EXPECT_CALL(tray, CreatePlatformStatusIcon(StatusTray::OTHER_ICON)).WillOnce( - Return(new MockStatusIcon())); - StatusIcon* icon = tray.CreateStatusIcon(StatusTray::OTHER_ICON); + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); + gfx::ImageSkia* image = rb.GetImageSkiaNamed(IDR_STATUS_TRAY_ICON); + StatusIcon* icon = tray.CreateStatusIcon( + StatusTray::OTHER_ICON, *image, ASCIIToUTF16("tool tip")); EXPECT_EQ(1U, tray.GetStatusIconsForTest().size()); tray.RemoveStatusIcon(icon); EXPECT_EQ(0U, tray.GetStatusIconsForTest().size()); diff --git a/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.mm b/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.mm index 405aabf..ff4bac5 100644 --- a/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.mm +++ b/chrome/browser/ui/cocoa/notifications/message_center_tray_bridge.mm @@ -100,15 +100,14 @@ void MessageCenterTrayBridge::UpdateStatusItem() { size_t unread_count = message_center_->UnreadNotificationCount(); [status_item_view_ setUnreadCount:unread_count]; - string16 product_name = l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME); if (unread_count > 0) { string16 unread_count_string = base::FormatNumber(unread_count); [status_item_view_ setToolTip: l10n_util::GetNSStringF(IDS_MESSAGE_CENTER_TOOLTIP_UNREAD, - product_name, unread_count_string)]; + unread_count_string)]; } else { [status_item_view_ setToolTip: - l10n_util::GetNSStringF(IDS_MESSAGE_CENTER_TOOLTIP, product_name)]; + l10n_util::GetNSString(IDS_MESSAGE_CENTER_TOOLTIP)]; } } diff --git a/chrome/browser/ui/cocoa/status_icons/status_tray_mac.h b/chrome/browser/ui/cocoa/status_icons/status_tray_mac.h index 2bb19c4..7325d86 100644 --- a/chrome/browser/ui/cocoa/status_icons/status_tray_mac.h +++ b/chrome/browser/ui/cocoa/status_icons/status_tray_mac.h @@ -14,7 +14,10 @@ class StatusTrayMac : public StatusTray { protected: // Factory method for creating a status icon. - virtual StatusIcon* CreatePlatformStatusIcon(StatusIconType type) OVERRIDE; + virtual StatusIcon* CreatePlatformStatusIcon( + StatusIconType type, + const gfx::ImageSkia& image, + const string16& tool_tip) OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(StatusTrayMac); diff --git a/chrome/browser/ui/cocoa/status_icons/status_tray_mac.mm b/chrome/browser/ui/cocoa/status_icons/status_tray_mac.mm index 7a4324d..50dc797 100644 --- a/chrome/browser/ui/cocoa/status_icons/status_tray_mac.mm +++ b/chrome/browser/ui/cocoa/status_icons/status_tray_mac.mm @@ -13,6 +13,11 @@ StatusTray* StatusTray::Create() { StatusTrayMac::StatusTrayMac() { } -StatusIcon* StatusTrayMac::CreatePlatformStatusIcon(StatusIconType type) { - return new StatusIconMac(); +StatusIcon* StatusTrayMac::CreatePlatformStatusIcon(StatusIconType type, + const gfx::ImageSkia& image, + const string16& tool_tip) { + StatusIcon* icon = new StatusIconMac(); + icon->SetImage(image); + icon->SetToolTip(tool_tip); + return icon; } diff --git a/chrome/browser/ui/gtk/status_icons/status_tray_gtk.cc b/chrome/browser/ui/gtk/status_icons/status_tray_gtk.cc index ecff525..a86f48f 100644 --- a/chrome/browser/ui/gtk/status_icons/status_tray_gtk.cc +++ b/chrome/browser/ui/gtk/status_icons/status_tray_gtk.cc @@ -12,8 +12,13 @@ StatusTrayGtk::StatusTrayGtk() { StatusTrayGtk::~StatusTrayGtk() { } -StatusIcon* StatusTrayGtk::CreatePlatformStatusIcon(StatusIconType type) { - return new StatusIconGtk(); +StatusIcon* StatusTrayGtk::CreatePlatformStatusIcon(StatusIconType type, + const gfx::ImageSkia& image, + const string16& tool_tip) { + StatusIcon* icon = new StatusIconGtk(); + icon->SetImage(image); + icon->SetToolTip(tool_tip); + return icon; } StatusTray* StatusTray::Create() { diff --git a/chrome/browser/ui/gtk/status_icons/status_tray_gtk.h b/chrome/browser/ui/gtk/status_icons/status_tray_gtk.h index 3e010d7..d24d386 100644 --- a/chrome/browser/ui/gtk/status_icons/status_tray_gtk.h +++ b/chrome/browser/ui/gtk/status_icons/status_tray_gtk.h @@ -15,7 +15,10 @@ class StatusTrayGtk : public StatusTray { protected: // Overriden from StatusTray: - virtual StatusIcon* CreatePlatformStatusIcon(StatusIconType type) OVERRIDE; + virtual StatusIcon* CreatePlatformStatusIcon( + StatusIconType type, + const gfx::ImageSkia& image, + const string16& tool_tip) OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(StatusTrayGtk); diff --git a/chrome/browser/ui/gtk/status_icons/status_tray_gtk_unittest.cc b/chrome/browser/ui/gtk/status_icons/status_tray_gtk_unittest.cc index 3cf40d0..3ca1df2 100644 --- a/chrome/browser/ui/gtk/status_icons/status_tray_gtk_unittest.cc +++ b/chrome/browser/ui/gtk/status_icons/status_tray_gtk_unittest.cc @@ -13,6 +13,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/models/simple_menu_model.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/image/image_skia.h" namespace { @@ -29,12 +30,11 @@ TEST(StatusTrayGtkTest, CreateTray) { TEST(StatusTrayGtkTest, CreateIcon) { // Create an icon, set the images and tooltip, then shut it down. StatusTrayGtk tray; - StatusIcon* icon = tray.CreateStatusIcon(StatusTray::OTHER_ICON); ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); gfx::ImageSkia* image = rb.GetImageSkiaNamed(IDR_STATUS_TRAY_ICON); - icon->SetImage(*image); + StatusIcon* icon = tray.CreateStatusIcon( + StatusTray::OTHER_ICON, *image, ASCIIToUTF16("tool tip")); icon->SetPressedImage(*image); - icon->SetToolTip(ASCIIToUTF16("tool tip")); ui::SimpleMenuModel* menu = new ui::SimpleMenuModel(NULL); menu->AddItem(0, ASCIIToUTF16("foo")); icon->SetContextMenu(menu); @@ -43,8 +43,10 @@ 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.CreateStatusIcon(StatusTray::OTHER_ICON)); + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); + gfx::ImageSkia* image = rb.GetImageSkiaNamed(IDR_STATUS_TRAY_ICON); + StatusIconGtk* icon = static_cast<StatusIconGtk*>(tray.CreateStatusIcon( + StatusTray::OTHER_ICON, *image, ASCIIToUTF16("tool tip"))); MockStatusIconObserver observer; icon->AddObserver(&observer); EXPECT_CALL(observer, OnStatusIconClicked()); diff --git a/chrome/browser/ui/libgtk2ui/app_indicator_icon.cc b/chrome/browser/ui/libgtk2ui/app_indicator_icon.cc index ff4b79f..73a4aff 100644 --- a/chrome/browser/ui/libgtk2ui/app_indicator_icon.cc +++ b/chrome/browser/ui/libgtk2ui/app_indicator_icon.cc @@ -124,7 +124,9 @@ void EnsureMethodsLoaded() { namespace libgtk2ui { -AppIndicatorIcon::AppIndicatorIcon(std::string id) +AppIndicatorIcon::AppIndicatorIcon(std::string id, + const gfx::ImageSkia& image, + const string16& tool_tip) : id_(id), icon_(NULL), gtk_menu_(NULL), @@ -133,6 +135,8 @@ AppIndicatorIcon::AppIndicatorIcon(std::string id) block_activation_(false), has_click_action_replacement_(false) { EnsureMethodsLoaded(); + tool_tip_ = UTF16ToUTF8(tool_tip); + SetImage(image); } AppIndicatorIcon::~AppIndicatorIcon() { if (icon_) { @@ -154,22 +158,25 @@ bool AppIndicatorIcon::CouldOpen() { } void AppIndicatorIcon::SetImage(const gfx::ImageSkia& image) { - if (opened) { - ++icon_change_count_; - gfx::ImageSkia safe_image = gfx::ImageSkia(image); - safe_image.MakeThreadSafe(); - base::PostTaskAndReplyWithResult( - content::BrowserThread::GetBlockingPool() - ->GetTaskRunnerWithShutdownBehavior( - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN).get(), - FROM_HERE, - base::Bind(&AppIndicatorIcon::CreateTempImageFile, - safe_image, - icon_change_count_, - id_), - base::Bind(&AppIndicatorIcon::SetImageFromFile, - base::Unretained(this))); - } + if (!opened) + return; + + ++icon_change_count_; + + // We create a deep copy of the image since it may have been freed by the time + // it's accessed in the other thread. + scoped_ptr<gfx::ImageSkia> safe_image(image.DeepCopy()); + base::PostTaskAndReplyWithResult( + content::BrowserThread::GetBlockingPool() + ->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN).get(), + FROM_HERE, + base::Bind(&AppIndicatorIcon::CreateTempImageFile, + safe_image.release(), + icon_change_count_, + id_), + base::Bind(&AppIndicatorIcon::SetImageFromFile, + base::Unretained(this))); } void AppIndicatorIcon::SetPressedImage(const gfx::ImageSkia& image) { @@ -178,27 +185,22 @@ void AppIndicatorIcon::SetPressedImage(const gfx::ImageSkia& image) { } void AppIndicatorIcon::SetToolTip(const string16& tool_tip) { - // App-indicators don't support tool-tips. Ignore call. -} - -void AppIndicatorIcon::SetClickActionLabel(const string16& label) { - click_action_label_ = UTF16ToUTF8(label); + DCHECK(!tool_tip_.empty()); + tool_tip_ = UTF16ToUTF8(tool_tip); - // If the menu item has already been created, then find the menu item and - // change it's label. - if (has_click_action_replacement_) { + // We can set the click action label only if the icon exists. Also we only + // need to update the label if it is shown and it's only shown if we are sure + // that there is a click action or if there is no menu. + if (icon_ && (delegate()->HasClickAction() || menu_model_ == NULL)) { GList* children = gtk_container_get_children(GTK_CONTAINER(gtk_menu_)); for (GList* child = children; child; child = g_list_next(child)) if (g_object_get_data(G_OBJECT(child->data), "click-action-item") != NULL) { gtk_menu_item_set_label(GTK_MENU_ITEM(child->data), - click_action_label_.c_str()); + tool_tip_.c_str()); break; } g_list_free(children); - } else if (icon_) { - CreateClickActionReplacement(); - app_indicator_set_menu(icon_, GTK_MENU(gtk_menu_)); } } @@ -208,13 +210,12 @@ void AppIndicatorIcon::UpdatePlatformContextMenu(ui::MenuModel* model) { if (gtk_menu_) { DestroyMenu(); - has_click_action_replacement_ = false; } menu_model_ = model; - // If icon doesn't exist now it's okay, the menu will be set later along with - // the image. Both an icon and a menu are required to show an app indicator. - if (model && icon_) + // The icon is created asynchronously so it might not exist when the menu is + // set. + if (icon_) SetMenu(); } @@ -234,12 +235,8 @@ void AppIndicatorIcon::SetImageFromFile(base::FilePath icon_file_path) { APP_INDICATOR_CATEGORY_APPLICATION_STATUS, icon_dir.c_str()); app_indicator_set_status(icon_, APP_INDICATOR_STATUS_ACTIVE); - if (menu_model_) { - SetMenu(); - } else if (!click_action_label_.empty()) { - CreateClickActionReplacement(); - app_indicator_set_menu(icon_, GTK_MENU(gtk_menu_)); - } + + SetMenu(); } else { // Currently we are creating a new temp directory every time the icon is // set. So we need to set the directory each time. @@ -256,40 +253,38 @@ void AppIndicatorIcon::SetImageFromFile(base::FilePath icon_file_path) { void AppIndicatorIcon::SetMenu() { gtk_menu_ = gtk_menu_new(); - BuildSubmenuFromModel(menu_model_, - gtk_menu_, - G_CALLBACK(OnMenuItemActivatedThunk), - &block_activation_, - this); - if (!click_action_label_.empty()) + + if (delegate()->HasClickAction() || menu_model_ == NULL) { CreateClickActionReplacement(); - UpdateMenu(); - menu_model_->MenuWillShow(); + if (menu_model_) { + // Add separator before the other menu items. + GtkWidget* menu_item = gtk_separator_menu_item_new(); + gtk_widget_show(menu_item); + gtk_menu_shell_append(GTK_MENU_SHELL(gtk_menu_), menu_item); + } + } + if (menu_model_) { + BuildSubmenuFromModel(menu_model_, + gtk_menu_, + G_CALLBACK(OnMenuItemActivatedThunk), + &block_activation_, + this); + UpdateMenu(); + menu_model_->MenuWillShow(); + } app_indicator_set_menu(icon_, GTK_MENU(gtk_menu_)); } void AppIndicatorIcon::CreateClickActionReplacement() { - GtkWidget* menu_item = NULL; - - // If a menu doesn't exist create one just for the click action replacement. - if (!gtk_menu_) { - gtk_menu_ = gtk_menu_new(); - } else { - // Add separator before the other menu items. - menu_item = gtk_separator_menu_item_new(); - gtk_widget_show(menu_item); - gtk_menu_shell_prepend(GTK_MENU_SHELL(gtk_menu_), menu_item); - } + DCHECK(!tool_tip_.empty()); // Add "click replacement menu item". - menu_item = gtk_menu_item_new_with_mnemonic(click_action_label_.c_str()); + GtkWidget* menu_item = gtk_menu_item_new_with_mnemonic(tool_tip_.c_str()); g_object_set_data( G_OBJECT(menu_item), "click-action-item", GINT_TO_POINTER(1)); g_signal_connect(menu_item, "activate", G_CALLBACK(OnClickThunk), this); gtk_widget_show(menu_item); gtk_menu_shell_prepend(GTK_MENU_SHELL(gtk_menu_), menu_item); - - has_click_action_replacement_ = true; } void AppIndicatorIcon::DestroyMenu() { @@ -300,11 +295,13 @@ void AppIndicatorIcon::DestroyMenu() { menu_model_ = NULL; } -base::FilePath AppIndicatorIcon::CreateTempImageFile(gfx::ImageSkia image, +base::FilePath AppIndicatorIcon::CreateTempImageFile(gfx::ImageSkia* image_ptr, int icon_change_count, std::string id) { + scoped_ptr<gfx::ImageSkia> image(image_ptr); + scoped_refptr<base::RefCountedMemory> png_data = - gfx::Image(image).As1xPNGBytes(); + gfx::Image(*image.get()).As1xPNGBytes(); if (png_data->size() == 0) { // If the bitmap could not be encoded to PNG format, skip it. LOG(WARNING) << "Could not encode icon"; diff --git a/chrome/browser/ui/libgtk2ui/app_indicator_icon.h b/chrome/browser/ui/libgtk2ui/app_indicator_icon.h index 33bfd5e..db1198d 100644 --- a/chrome/browser/ui/libgtk2ui/app_indicator_icon.h +++ b/chrome/browser/ui/libgtk2ui/app_indicator_icon.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_LIBGTK2UI_APP_INDICATOR_ICON_H_ #include "base/files/file_path.h" +#include "base/memory/scoped_ptr.h" #include "chrome/browser/ui/libgtk2ui/gtk2_signal.h" #include "ui/linux_ui/status_icon_linux.h" @@ -22,7 +23,9 @@ class AppIndicatorIcon : public StatusIconLinux { public: // The id uniquely identifies the new status icon from other chrome status // icons. - explicit AppIndicatorIcon(std::string id); + explicit AppIndicatorIcon(std::string id, + const gfx::ImageSkia& image, + const string16& tool_tip); virtual ~AppIndicatorIcon(); // Indicates whether libappindicator so could be opened. @@ -32,7 +35,6 @@ class AppIndicatorIcon : public StatusIconLinux { virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE; virtual void SetPressedImage(const gfx::ImageSkia& image) OVERRIDE; virtual void SetToolTip(const string16& tool_tip) OVERRIDE; - virtual void SetClickActionLabel(const string16& label) OVERRIDE; protected: // Overridden from StatusIcon. @@ -49,7 +51,7 @@ class AppIndicatorIcon : public StatusIconLinux { void CreateClickActionReplacement(); void DestroyMenu(); - static base::FilePath CreateTempImageFile(gfx::ImageSkia image, + static base::FilePath CreateTempImageFile(gfx::ImageSkia* image, int icon_change_count, std::string id); static void DeletePath(base::FilePath icon_file_path); @@ -64,7 +66,7 @@ class AppIndicatorIcon : public StatusIconLinux { CHROMEGTK_CALLBACK_0(AppIndicatorIcon, void, OnMenuItemActivated); std::string id_; - std::string click_action_label_; + std::string tool_tip_; // Gtk status icon wrapper AppIndicator* icon_; diff --git a/chrome/browser/ui/libgtk2ui/gtk2_ui.cc b/chrome/browser/ui/libgtk2ui/gtk2_ui.cc index 4167edc..1376db2 100644 --- a/chrome/browser/ui/libgtk2ui/gtk2_ui.cc +++ b/chrome/browser/ui/libgtk2ui/gtk2_ui.cc @@ -395,11 +395,15 @@ bool Gtk2UI::IsStatusIconSupported() const { return AppIndicatorIcon::CouldOpen(); } -scoped_ptr<StatusIconLinux> Gtk2UI::CreateLinuxStatusIcon() const { +scoped_ptr<StatusIconLinux> Gtk2UI::CreateLinuxStatusIcon( + const gfx::ImageSkia& image, + const string16& tool_tip) const { if (AppIndicatorIcon::CouldOpen()) { ++indicators_count; return scoped_ptr<StatusIconLinux>(new AppIndicatorIcon( - base::StringPrintf("%s%d", kAppIndicatorIdPrefix, indicators_count))); + base::StringPrintf("%s%d", kAppIndicatorIdPrefix, indicators_count), + image, + tool_tip)); } else { return scoped_ptr<StatusIconLinux>(); } diff --git a/chrome/browser/ui/libgtk2ui/gtk2_ui.h b/chrome/browser/ui/libgtk2ui/gtk2_ui.h index 69a7dde..af57462 100644 --- a/chrome/browser/ui/libgtk2ui/gtk2_ui.h +++ b/chrome/browser/ui/libgtk2ui/gtk2_ui.h @@ -48,7 +48,9 @@ class Gtk2UI : public ui::LinuxUI { virtual void SetDownloadCount(int count) const OVERRIDE; virtual void SetProgressFraction(float percentage) const OVERRIDE; virtual bool IsStatusIconSupported() const OVERRIDE; - virtual scoped_ptr<StatusIconLinux> CreateLinuxStatusIcon() const OVERRIDE; + virtual scoped_ptr<StatusIconLinux> CreateLinuxStatusIcon( + const gfx::ImageSkia& image, + const string16& tool_tip) const OVERRIDE; private: typedef std::map<int, SkColor> ColorMap; diff --git a/chrome/browser/ui/views/message_center/web_notification_tray.cc b/chrome/browser/ui/views/message_center/web_notification_tray.cc index f3371d9..00eadd5 100644 --- a/chrome/browser/ui/views/message_center/web_notification_tray.cc +++ b/chrome/browser/ui/views/message_center/web_notification_tray.cc @@ -200,20 +200,22 @@ void WebNotificationTray::UpdateStatusIcon() { should_update_tray_content_ = false; int unread_notifications = message_center()->UnreadNotificationCount(); - StatusIcon* status_icon = GetStatusIcon(); - if (!status_icon) - return; - - status_icon->SetImage(GetIcon(unread_notifications)); - string16 product_name(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); + string16 tool_tip; if (unread_notifications > 0) { string16 str_unread_count = base::FormatNumber(unread_notifications); - status_icon->SetToolTip(l10n_util::GetStringFUTF16( - IDS_MESSAGE_CENTER_TOOLTIP_UNREAD, product_name, str_unread_count)); + tool_tip = l10n_util::GetStringFUTF16(IDS_MESSAGE_CENTER_TOOLTIP_UNREAD, + str_unread_count); + } else { + tool_tip = l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_TOOLTIP); + } + gfx::ImageSkia icon_image = GetIcon(unread_notifications); + + if (status_icon_ == NULL) { + CreateStatusIcon(icon_image, tool_tip); } else { - status_icon->SetToolTip( - l10n_util::GetStringFUTF16(IDS_MESSAGE_CENTER_TOOLTIP, product_name)); + status_icon_->SetImage(icon_image); + status_icon_->SetToolTip(tool_tip); } } @@ -267,24 +269,22 @@ PositionInfo WebNotificationTray::GetPositionInfo() { return pos_info; } -StatusIcon* WebNotificationTray::GetStatusIcon() { +void WebNotificationTray::CreateStatusIcon(const gfx::ImageSkia& image, + const string16& tool_tip) { if (status_icon_) - return status_icon_; + return; StatusTray* status_tray = g_browser_process->status_tray(); if (!status_tray) - return NULL; + return; - StatusIcon* status_icon = - status_tray->CreateStatusIcon(StatusTray::NOTIFICATION_TRAY_ICON); - if (!status_icon) - return NULL; + status_icon_ = status_tray->CreateStatusIcon( + StatusTray::NOTIFICATION_TRAY_ICON, image, tool_tip); + if (!status_icon_) + return; - status_icon_ = status_icon; status_icon_->AddObserver(this); AddQuietModeMenu(status_icon_); - - return status_icon_; } void WebNotificationTray::DestroyStatusIcon() { diff --git a/chrome/browser/ui/views/message_center/web_notification_tray.h b/chrome/browser/ui/views/message_center/web_notification_tray.h index 8d4010d..1bc6fa4 100644 --- a/chrome/browser/ui/views/message_center/web_notification_tray.h +++ b/chrome/browser/ui/views/message_center/web_notification_tray.h @@ -84,7 +84,7 @@ class WebNotificationTray : public message_center::MessageCenterTrayDelegate, PositionInfo GetPositionInfo(); - StatusIcon* GetStatusIcon(); + void CreateStatusIcon(const gfx::ImageSkia& image, const string16& tool_tip); void DestroyStatusIcon(); void AddQuietModeMenu(StatusIcon* status_icon); MessageCenterWidgetDelegate* GetMessageCenterWidgetDelegateForTest(); diff --git a/chrome/browser/ui/views/message_center/web_notification_tray_win.cc b/chrome/browser/ui/views/message_center/web_notification_tray_win.cc index dcc6e25..54a99f4 100644 --- a/chrome/browser/ui/views/message_center/web_notification_tray_win.cc +++ b/chrome/browser/ui/views/message_center/web_notification_tray_win.cc @@ -30,9 +30,9 @@ void WebNotificationTray::OnBalloonClicked() { } void WebNotificationTray::DisplayFirstRunBalloon() { - StatusIcon* status_icon = GetStatusIcon(); - if (!status_icon) - return; + // We should never be calling DisplayFirstRunBalloon without a status icon. + // The status icon must have been created before this call. + DCHECK(status_icon_); base::win::Version win_version = base::win::GetVersion(); if (win_version == base::win::VERSION_PRE_XP) @@ -52,8 +52,7 @@ void WebNotificationTray::DisplayFirstRunBalloon() { scoped_ptr<SkBitmap> sized_app_icon_bitmap = GetAppIconForSize(icon_size); gfx::ImageSkia sized_app_icon_skia = gfx::ImageSkia::CreateFrom1xBitmap(*sized_app_icon_bitmap); - string16 product_name(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME)); - GetStatusIcon()->DisplayBalloon( + status_icon_->DisplayBalloon( sized_app_icon_skia, l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_BALLOON_TITLE), l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_BALLOON_TEXT)); diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc index f257a3f..931abef 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc @@ -23,10 +23,6 @@ void StatusIconLinuxWrapper::SetToolTip(const string16& tool_tip) { status_icon_->SetToolTip(tool_tip); } -void StatusIconLinuxWrapper::SetClickActionLabel(const string16& label) { - status_icon_->SetClickActionLabel(label); -} - void StatusIconLinuxWrapper::DisplayBalloon(const gfx::ImageSkia& icon, const string16& title, const string16& contents) { @@ -37,10 +33,17 @@ void StatusIconLinuxWrapper::OnClick() { DispatchClickEvent(); } -StatusIconLinuxWrapper* StatusIconLinuxWrapper::CreateWrappedStatusIcon() { +bool StatusIconLinuxWrapper::HasClickAction() { + return HasObservers(); +} + +StatusIconLinuxWrapper* StatusIconLinuxWrapper::CreateWrappedStatusIcon( + const gfx::ImageSkia& image, + const string16& tool_tip) { const ui::LinuxUI* linux_ui = ui::LinuxUI::instance(); if (linux_ui) { - scoped_ptr<StatusIconLinux> status_icon = linux_ui->CreateLinuxStatusIcon(); + scoped_ptr<StatusIconLinux> status_icon = + linux_ui->CreateLinuxStatusIcon(image, tool_tip); if (status_icon.get()) return new StatusIconLinuxWrapper(status_icon.release()); } diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h index 5bb7dbf..153ce37 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h @@ -21,15 +21,17 @@ class StatusIconLinuxWrapper : public StatusIcon, virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE; virtual void SetPressedImage(const gfx::ImageSkia& image) OVERRIDE; virtual void SetToolTip(const string16& tool_tip) OVERRIDE; - virtual void SetClickActionLabel(const string16& label) OVERRIDE; virtual void DisplayBalloon(const gfx::ImageSkia& icon, const string16& title, const string16& contents) OVERRIDE; // StatusIconLinux::Delegate overrides: virtual void OnClick() OVERRIDE; + virtual bool HasClickAction() OVERRIDE; - static StatusIconLinuxWrapper* CreateWrappedStatusIcon(); + static StatusIconLinuxWrapper* CreateWrappedStatusIcon( + const gfx::ImageSkia& image, + const string16& tool_tip); protected: // StatusIcon overrides: diff --git a/chrome/browser/ui/views/status_icons/status_tray_linux.cc b/chrome/browser/ui/views/status_icons/status_tray_linux.cc index 2aa06c4..58db07a 100644 --- a/chrome/browser/ui/views/status_icons/status_tray_linux.cc +++ b/chrome/browser/ui/views/status_icons/status_tray_linux.cc @@ -14,8 +14,11 @@ StatusTrayLinux::StatusTrayLinux() { StatusTrayLinux::~StatusTrayLinux() { } -StatusIcon* StatusTrayLinux::CreatePlatformStatusIcon(StatusIconType type) { - return StatusIconLinuxWrapper::CreateWrappedStatusIcon(); +StatusIcon* StatusTrayLinux::CreatePlatformStatusIcon( + StatusIconType type, + const gfx::ImageSkia& image, + const string16& tool_tip) { + return StatusIconLinuxWrapper::CreateWrappedStatusIcon(image, tool_tip); } StatusTray* StatusTray::Create() { diff --git a/chrome/browser/ui/views/status_icons/status_tray_linux.h b/chrome/browser/ui/views/status_icons/status_tray_linux.h index ea38ae5..d1540a5 100644 --- a/chrome/browser/ui/views/status_icons/status_tray_linux.h +++ b/chrome/browser/ui/views/status_icons/status_tray_linux.h @@ -15,7 +15,10 @@ class StatusTrayLinux : public StatusTray { protected: // Overriden from StatusTray: - virtual StatusIcon* CreatePlatformStatusIcon(StatusIconType type) OVERRIDE; + virtual StatusIcon* CreatePlatformStatusIcon( + StatusIconType type, + const gfx::ImageSkia& image, + const string16& tool_tip) OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(StatusTrayLinux); diff --git a/chrome/browser/ui/views/status_icons/status_tray_win.cc b/chrome/browser/ui/views/status_icons/status_tray_win.cc index 8df1cf5..21a00d4 100644 --- a/chrome/browser/ui/views/status_icons/status_tray_win.cc +++ b/chrome/browser/ui/views/status_icons/status_tray_win.cc @@ -120,16 +120,24 @@ StatusTrayWin::~StatusTrayWin() { } StatusIcon* StatusTrayWin::CreatePlatformStatusIcon( - StatusTray::StatusIconType type) { + StatusTray::StatusIconType type, + const gfx::ImageSkia& image, + const string16& tool_tip) { UINT next_icon_id; if (type == StatusTray::OTHER_ICON) next_icon_id = NextIconId(); else next_icon_id = ReservedIconId(type); + StatusIcon* icon = NULL; if (win8::IsSingleWindowMetroMode()) - return new StatusIconMetro(next_icon_id); - return new StatusIconWin(next_icon_id, window_, kStatusIconMessage); + icon = new StatusIconMetro(next_icon_id); + else + icon = new StatusIconWin(next_icon_id, window_, kStatusIconMessage); + + icon->SetImage(image); + icon->SetToolTip(tool_tip); + return icon; } UINT StatusTrayWin::NextIconId() { diff --git a/chrome/browser/ui/views/status_icons/status_tray_win.h b/chrome/browser/ui/views/status_icons/status_tray_win.h index 87974f0..3e2be2f 100644 --- a/chrome/browser/ui/views/status_icons/status_tray_win.h +++ b/chrome/browser/ui/views/status_icons/status_tray_win.h @@ -23,7 +23,10 @@ class StatusTrayWin : public StatusTray { protected: // Overriden from StatusTray: - virtual StatusIcon* CreatePlatformStatusIcon(StatusIconType type) OVERRIDE; + virtual StatusIcon* CreatePlatformStatusIcon( + StatusIconType type, + const gfx::ImageSkia& image, + const string16& tool_tip) OVERRIDE; private: // Static callback invoked when a message comes in to our messaging window. diff --git a/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc b/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc index b42fd96..b021f8c 100644 --- a/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc +++ b/chrome/browser/ui/views/status_icons/status_tray_win_unittest.cc @@ -14,6 +14,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/models/simple_menu_model.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/image/image_skia.h" class FakeStatusIconObserver : public StatusIconObserver { public: @@ -43,12 +44,11 @@ TEST(StatusTrayWinTest, CreateIconAndMenu) { // Create an icon, set the images, tooltip, and context menu, then shut it // down. StatusTrayWin tray; - StatusIcon* icon = tray.CreateStatusIcon(StatusTray::OTHER_ICON); ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); gfx::ImageSkia* image = rb.GetImageSkiaNamed(IDR_STATUS_TRAY_ICON); - icon->SetImage(*image); + StatusIcon* icon = tray.CreateStatusIcon( + StatusTray::OTHER_ICON, *image, ASCIIToUTF16("tool tip")); icon->SetPressedImage(*image); - icon->SetToolTip(ASCIIToUTF16("tool tip")); ui::SimpleMenuModel* menu = new ui::SimpleMenuModel(NULL); menu->AddItem(0, L"foo"); icon->SetContextMenu(menu); @@ -58,8 +58,11 @@ TEST(StatusTrayWinTest, CreateIconAndMenu) { TEST(StatusTrayWinTest, ClickOnIcon) { // Create an icon, send a fake click event, make sure observer is called. StatusTrayWin tray; - StatusIconWin* icon = static_cast<StatusIconWin*>( - tray.CreateStatusIcon(StatusTray::OTHER_ICON)); + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); + gfx::ImageSkia* image = rb.GetImageSkiaNamed(IDR_STATUS_TRAY_ICON); + + StatusIconWin* icon = static_cast<StatusIconWin*>(tray.CreateStatusIcon( + StatusTray::OTHER_ICON, *image, ASCIIToUTF16("tool tip"))); FakeStatusIconObserver observer; icon->AddObserver(&observer); // Mimic a click. @@ -73,8 +76,11 @@ TEST(StatusTrayWinTest, ClickOnIcon) { TEST(StatusTrayWinTest, ClickOnBalloon) { // Create an icon, send a fake click event, make sure observer is called. StatusTrayWin tray; - StatusIconWin* icon = static_cast<StatusIconWin*>( - tray.CreateStatusIcon(StatusTray::OTHER_ICON)); + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); + gfx::ImageSkia* image = rb.GetImageSkiaNamed(IDR_STATUS_TRAY_ICON); + + StatusIconWin* icon = static_cast<StatusIconWin*>(tray.CreateStatusIcon( + StatusTray::OTHER_ICON, *image, ASCIIToUTF16("tool tip"))); FakeStatusIconObserver observer; icon->AddObserver(&observer); // Mimic a click. diff --git a/ui/base/strings/ui_strings.grd b/ui/base/strings/ui_strings.grd index 0e06ca5..21d7001 100644 --- a/ui/base/strings/ui_strings.grd +++ b/ui/base/strings/ui_strings.grd @@ -501,12 +501,6 @@ need to be translated for each locale.--> <message name="IDS_MESSAGE_CENTER_EXPAND_NOTIFICATION_BUTTON_ACCESSIBLE_NAME" desc="The spoken feedback text for the expand button in a notification. Usually 'button' is suffixed to this text automatically."> Notification expand </message> - <message name="IDS_MESSAGE_CENTER_TOOLTIP" desc="Tooltip for notification tray icon without unread notifications"> - <ph name="product">$1<ex>Chrome</ex></ph> - Notifications - </message> - <message name="IDS_MESSAGE_CENTER_TOOLTIP_UNREAD" desc="Tooltip for notification tray icon with unread notifications"> - <ph name="product">$1<ex>Chrome</ex></ph> - Notifications (<ph name="QUANTITY">$2<ex>3</ex></ph> unread) - </message> <message name="IDS_MESSAGE_CENTER_NOTIFIER_SCREENSHOT_NAME" desc="The name of screenshot notifier that is a system componet"> Screenshot </message> diff --git a/ui/linux_ui/OWNERS b/ui/linux_ui/OWNERS new file mode 100644 index 0000000..4733a4f --- /dev/null +++ b/ui/linux_ui/OWNERS @@ -0,0 +1 @@ +erg@chromium.org diff --git a/ui/linux_ui/linux_ui.h b/ui/linux_ui/linux_ui.h index 119f97d..f609e9a 100644 --- a/ui/linux_ui/linux_ui.h +++ b/ui/linux_ui/linux_ui.h @@ -67,7 +67,9 @@ class LINUX_UI_EXPORT LinuxUI : public LinuxShellDialog { virtual bool IsStatusIconSupported() const = 0; // Create a native status icon. - virtual scoped_ptr<StatusIconLinux> CreateLinuxStatusIcon() const = 0; + virtual scoped_ptr<StatusIconLinux> CreateLinuxStatusIcon( + const gfx::ImageSkia& image, + const string16& tool_tip) const = 0; }; } // namespace ui diff --git a/ui/linux_ui/status_icon_linux.h b/ui/linux_ui/status_icon_linux.h index 1accefe..fbbf28f 100644 --- a/ui/linux_ui/status_icon_linux.h +++ b/ui/linux_ui/status_icon_linux.h @@ -25,6 +25,7 @@ class LINUX_UI_EXPORT StatusIconLinux { class Delegate { public: virtual void OnClick() = 0; + virtual bool HasClickAction() = 0; protected: virtual ~Delegate(); @@ -36,7 +37,6 @@ class LINUX_UI_EXPORT StatusIconLinux { virtual void SetImage(const gfx::ImageSkia& image) = 0; virtual void SetPressedImage(const gfx::ImageSkia& image) = 0; virtual void SetToolTip(const string16& tool_tip) = 0; - virtual void SetClickActionLabel(const string16& label) = 0; // Invoked after a call to SetContextMenu() to let the platform-specific // subclass update the native context menu based on the new model. The |