diff options
author | stevenjb@google.com <stevenjb@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-14 18:10:36 +0000 |
---|---|---|
committer | stevenjb@google.com <stevenjb@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-14 18:10:36 +0000 |
commit | fe12aaa20a8327bd0473dc39c5a742d0cc8a19ba (patch) | |
tree | 9f1d4eb9603fb07bae10a27aa57536b585a4adf7 | |
parent | d7646cb9b871b988d91a1d702f4d490cbbcf434f (diff) | |
download | chromium_src-fe12aaa20a8327bd0473dc39c5a742d0cc8a19ba.zip chromium_src-fe12aaa20a8327bd0473dc39c5a742d0cc8a19ba.tar.gz chromium_src-fe12aaa20a8327bd0473dc39c5a742d0cc8a19ba.tar.bz2 |
Add support for Ash to Notifications
* Adds BalloonViewAsh and moves/renames related classes.
* Adds support for image icons to Notification class
* Adds GetRenderViewHost() method to NotificationDelegate for fetching images
BUG=124914
TEST=Tests pass. No visual changes to notifications on non-ash platforms. Web notifications show up in new tray on Ash with --ash-notify.
For CloudPrintProxyService:
TBR=scottbyer@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10537158
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@142172 0039d316-1c4b-4281-b951-d872f2087c98
23 files changed, 463 insertions, 49 deletions
diff --git a/chrome/browser/background/background_contents_service.cc b/chrome/browser/background/background_contents_service.cc index 909ef7a..c1edaba 100644 --- a/chrome/browser/background/background_contents_service.cc +++ b/chrome/browser/background/background_contents_service.cc @@ -64,13 +64,13 @@ class CrashNotificationDelegate : public NotificationDelegate { extension_id_(extension->id()) { } - void Display() {} + virtual void Display() OVERRIDE {} - void Error() {} + virtual void Error() OVERRIDE {} - void Close(bool by_user) {} + virtual void Close(bool by_user) OVERRIDE {} - void Click() { + virtual void Click() OVERRIDE { if (is_hosted_app_) { // There can be a race here: user clicks the balloon, and simultaneously // reloads the sad tab for the app. So we check here to be safe before @@ -88,10 +88,14 @@ class CrashNotificationDelegate : public NotificationDelegate { ScheduleCloseBalloon(extension_id_); } - std::string id() const { + virtual std::string id() const OVERRIDE { return kNotificationPrefix + extension_id_; } + virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE { + return NULL; + } + private: virtual ~CrashNotificationDelegate() {} diff --git a/chrome/browser/chromeos/locale_change_guard.cc b/chrome/browser/chromeos/locale_change_guard.cc index 8365677..4ceb92b 100644 --- a/chrome/browser/chromeos/locale_change_guard.cc +++ b/chrome/browser/chromeos/locale_change_guard.cc @@ -36,11 +36,14 @@ namespace chromeos { class LocaleChangeGuard::Delegate : public NotificationDelegate { public: explicit Delegate(chromeos::LocaleChangeGuard* master) : master_(master) {} - void Close(bool by_user); - void Display() {} - void Error() {} - void Click() {} - std::string id() const; + virtual void Close(bool by_user) OVERRIDE; + virtual void Display() OVERRIDE {} + virtual void Error() OVERRIDE {} + virtual void Click() OVERRIDE {} + virtual std::string id() const OVERRIDE; + virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE { + return NULL; + } private: chromeos::LocaleChangeGuard* master_; diff --git a/chrome/browser/chromeos/notifications/system_notification.cc b/chrome/browser/chromeos/notifications/system_notification.cc index ba01260..efaaa1d 100644 --- a/chrome/browser/chromeos/notifications/system_notification.cc +++ b/chrome/browser/chromeos/notifications/system_notification.cc @@ -136,4 +136,9 @@ std::string SystemNotification::Delegate::id() const { return id_; } +content::RenderViewHost* +SystemNotification::Delegate::GetRenderViewHost() const { + return NULL; +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/notifications/system_notification.h b/chrome/browser/chromeos/notifications/system_notification.h index 3c930ba..40d97de 100644 --- a/chrome/browser/chromeos/notifications/system_notification.h +++ b/chrome/browser/chromeos/notifications/system_notification.h @@ -77,6 +77,7 @@ class SystemNotification : public PowerManagerClient::Observer { virtual void Close(bool by_user) OVERRIDE {} virtual void Click() OVERRIDE {} virtual std::string id() const OVERRIDE; + virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE; private: std::string id_; diff --git a/chrome/browser/notifications/OWNERS b/chrome/browser/notifications/OWNERS index 967c65c..05f7e95d 100644 --- a/chrome/browser/notifications/OWNERS +++ b/chrome/browser/notifications/OWNERS @@ -1 +1 @@ -johnnyg@chromium.org +stevenjb@chormium.org diff --git a/chrome/browser/notifications/balloon_collection_base.cc b/chrome/browser/notifications/balloon_collection_base.cc index 278f4a9..d66d7e92 100644 --- a/chrome/browser/notifications/balloon_collection_base.cc +++ b/chrome/browser/notifications/balloon_collection_base.cc @@ -75,14 +75,17 @@ void BalloonCollectionBase::CloseAll() { (*iter)->CloseByScript(); } -Balloon* BalloonCollectionBase::FindBalloon( - const Notification& notification) { +Balloon* BalloonCollectionBase::FindBalloonById( + const std::string& notification_id) { Balloons::iterator iter; for (iter = balloons_.begin(); iter != balloons_.end(); ++iter) { - if ((*iter)->notification().notification_id() == - notification.notification_id()) { + if ((*iter)->notification().notification_id() == notification_id) { return *iter; } } return NULL; } + +Balloon* BalloonCollectionBase::FindBalloon(const Notification& notification) { + return FindBalloonById(notification.notification_id()); +} diff --git a/chrome/browser/notifications/balloon_collection_base.h b/chrome/browser/notifications/balloon_collection_base.h index 578c76e..bc5a291 100644 --- a/chrome/browser/notifications/balloon_collection_base.h +++ b/chrome/browser/notifications/balloon_collection_base.h @@ -48,6 +48,10 @@ class BalloonCollectionBase { const Balloons& balloons() const { return balloons_; } + // Returns the balloon matching the given notification id, or + // NULL if there is no matching balloon. + Balloon* FindBalloonById(const std::string& notification_id); + // Returns the balloon matching the given notification, or // NULL if there is no matching balloon. Balloon* FindBalloon(const Notification& notification); diff --git a/chrome/browser/notifications/desktop_notification_service_win.cc b/chrome/browser/notifications/desktop_notification_service_win.cc index 3cba517..3f9bd29 100644 --- a/chrome/browser/notifications/desktop_notification_service_win.cc +++ b/chrome/browser/notifications/desktop_notification_service_win.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/win/metro.h" #include "chrome/browser/notifications/notification.h" +#include "chrome/browser/notifications/notification_object_proxy.h" #include "chrome/browser/notifications/notification_ui_manager.h" #include "chrome/browser/notifications/notification_ui_manager.h" @@ -54,5 +55,3 @@ void DesktopNotificationService::ShowNotification( } GetUIManager()->Add(notification, profile_); } - - diff --git a/chrome/browser/notifications/notification.cc b/chrome/browser/notifications/notification.cc index 8af6ba1..282ccbd 100644 --- a/chrome/browser/notifications/notification.cc +++ b/chrome/browser/notifications/notification.cc @@ -28,6 +28,7 @@ Notification::Notification(const GURL& origin_url, const string16& replace_id, NotificationDelegate* delegate) : origin_url_(origin_url), + icon_url_(icon_url), is_html_(false), title_(title), body_(body), @@ -39,8 +40,28 @@ Notification::Notification(const GURL& origin_url, icon_url, title, body, dir)); } +Notification::Notification(const GURL& origin_url, + const gfx::ImageSkia& icon, + const string16& title, + const string16& body, + WebKit::WebTextDirection dir, + const string16& display_source, + const string16& replace_id, + NotificationDelegate* delegate) + : origin_url_(origin_url), + icon_(icon), + is_html_(false), + title_(title), + body_(body), + display_source_(display_source), + replace_id_(replace_id), + delegate_(delegate) { +} + Notification::Notification(const Notification& notification) : origin_url_(notification.origin_url()), + icon_(notification.icon()), + icon_url_(notification.icon_url()), is_html_(notification.is_html()), content_url_(notification.content_url()), title_(notification.title()), @@ -54,6 +75,8 @@ Notification::~Notification() {} Notification& Notification::operator=(const Notification& notification) { origin_url_ = notification.origin_url(); + icon_ = notification.icon_; + icon_url_ = notification.icon_url(); is_html_ = notification.is_html(); content_url_ = notification.content_url(); title_ = notification.title(); diff --git a/chrome/browser/notifications/notification.h b/chrome/browser/notifications/notification.h index f6b41d4..5868dea 100644 --- a/chrome/browser/notifications/notification.h +++ b/chrome/browser/notifications/notification.h @@ -10,15 +10,15 @@ #include "base/basictypes.h" #include "base/string16.h" -#include "chrome/browser/notifications/notification_object_proxy.h" +#include "chrome/browser/notifications/notification_delegate.h" #include "googleurl/src/gurl.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebTextDirection.h" +#include "ui/gfx/image/image_skia.h" -class NotificationDelegate; - -// Representation of an notification to be shown to the user. All -// notifications at this level are HTML, although they may be -// data: URLs representing simple text+icon notifications. +// Representation of a notification to be shown to the user. +// On non-Ash platforms these are rendered as HTML, sometimes described by a +// data url converted from text + icon data. On Ash they are rendered as +// formated text and icon data. class Notification { public: // Initializes a notification with HTML content. @@ -27,9 +27,9 @@ class Notification { const string16& display_source, const string16& replace_id, NotificationDelegate* delegate); - // Initializes a notification with text content, and then creates a - // HTML representation of it for display (satisfying the invariant outlined - // at the top of this class). + + // Initializes a notification with text content. On non-ash platforms, this + // creates an HTML representation using a data: URL for display. Notification(const GURL& origin_url, const GURL& icon_url, const string16& title, @@ -38,6 +38,18 @@ class Notification { const string16& display_source, const string16& replace_id, NotificationDelegate* delegate); + + // Initializes a notification with text content and an icon image. Currently + // only used on Ash. Does not generate content_url_. + Notification(const GURL& origin_url, + const gfx::ImageSkia& icon, + const string16& title, + const string16& body, + WebKit::WebTextDirection dir, + const string16& display_source, + const string16& replace_id, + NotificationDelegate* delegate); + Notification(const Notification& notification); ~Notification(); Notification& operator=(const Notification& notification); @@ -48,16 +60,23 @@ class Notification { // The URL (may be data:) containing the contents for the notification. const GURL& content_url() const { return content_url_; } - // Parameters for text-only notifications. + // Title and message text of the notification. const string16& title() const { return title_; } const string16& body() const { return body_; } // The origin URL of the script which requested the notification. const GURL& origin_url() const { return origin_url_; } + // A url for the icon to be shown (optional). + const GURL& icon_url() const { return icon_url_; } + + // An image for the icon to be shown (optional). + const gfx::ImageSkia& icon() const { return icon_; } + // A display string for the source of the notification. const string16& display_source() const { return display_source_; } + // A unique identifier used to update (replace) or remove a notification. const string16& replace_id() const { return replace_id_; } void Display() const { delegate()->Display(); } @@ -67,12 +86,23 @@ class Notification { std::string notification_id() const { return delegate()->id(); } + content::RenderViewHost* GetRenderViewHost() const { + return delegate()->GetRenderViewHost(); + } + private: NotificationDelegate* delegate() const { return delegate_.get(); } // The Origin of the page/worker which created this notification. GURL origin_url_; + // Image data for the associated icon, used by Ash when available. + gfx::ImageSkia icon_; + + // URL for the icon associated with the notification. Requires delegate_ + // to have a non NULL RenderViewHost. + GURL icon_url_; + // If this is a HTML notification, the content is in |content_url_|. If // false, the data is in |title_| and |body_|. bool is_html_; diff --git a/chrome/browser/notifications/notification_delegate.h b/chrome/browser/notifications/notification_delegate.h index 81a4a00f..2434af5 100644 --- a/chrome/browser/notifications/notification_delegate.h +++ b/chrome/browser/notifications/notification_delegate.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -10,6 +10,10 @@ #include "base/memory/ref_counted.h" +namespace content { +class RenderViewHost; +} + // Delegate for a notification. This class has two role, to implement // callback methods for notification, and provides an identify of // the associated notification. @@ -33,6 +37,9 @@ class NotificationDelegate // Returns unique id of the notification. virtual std::string id() const = 0; + // Returns the RenderViewHost that generated the notification, or NULL. + virtual content::RenderViewHost* GetRenderViewHost() const = 0; + protected: virtual ~NotificationDelegate() {} diff --git a/chrome/browser/notifications/notification_object_proxy.cc b/chrome/browser/notifications/notification_object_proxy.cc index 6c838df..f918724 100644 --- a/chrome/browser/notifications/notification_object_proxy.cc +++ b/chrome/browser/notifications/notification_object_proxy.cc @@ -49,3 +49,7 @@ std::string NotificationObjectProxy::id() const { return StringPrintf("%d:%d:%d:%d", process_id_, route_id_, notification_id_, worker_); } + +RenderViewHost* NotificationObjectProxy::GetRenderViewHost() const { + return RenderViewHost::FromID(process_id_, route_id_); +} diff --git a/chrome/browser/notifications/notification_object_proxy.h b/chrome/browser/notifications/notification_object_proxy.h index 6373a11..a9c93f4 100644 --- a/chrome/browser/notifications/notification_object_proxy.h +++ b/chrome/browser/notifications/notification_object_proxy.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -27,6 +27,7 @@ class NotificationObjectProxy virtual void Close(bool by_user) OVERRIDE; virtual void Click() OVERRIDE; virtual std::string id() const OVERRIDE; + virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE; protected: friend class base::RefCountedThreadSafe<NotificationObjectProxy>; diff --git a/chrome/browser/notifications/notification_test_util.cc b/chrome/browser/notifications/notification_test_util.cc index 1803c67..89dca71 100644 --- a/chrome/browser/notifications/notification_test_util.cc +++ b/chrome/browser/notifications/notification_test_util.cc @@ -14,6 +14,10 @@ std::string MockNotificationDelegate::id() const { return id_; } +content::RenderViewHost* MockNotificationDelegate::GetRenderViewHost() const { + return NULL; +} + void MockBalloonView::Close(bool by_user) { balloon_->OnClose(by_user); } diff --git a/chrome/browser/notifications/notification_test_util.h b/chrome/browser/notifications/notification_test_util.h index 7ea3ac7..418f672 100644 --- a/chrome/browser/notifications/notification_test_util.h +++ b/chrome/browser/notifications/notification_test_util.h @@ -24,6 +24,7 @@ class MockNotificationDelegate : public NotificationDelegate { virtual void Close(bool by_user) OVERRIDE {} virtual void Click() OVERRIDE {} virtual std::string id() const OVERRIDE; + virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE; private: virtual ~MockNotificationDelegate(); @@ -47,24 +48,28 @@ class LoggingNotificationDelegate : public NotificationDelegate { } // NotificationObjectProxy override - virtual void Display() { + virtual void Display() OVERRIDE { Logger::log("notification displayed\n"); } - virtual void Error() { + virtual void Error() OVERRIDE { Logger::log("notification error\n"); } - virtual void Click() { + virtual void Click() OVERRIDE { Logger::log("notification clicked\n"); } - virtual void Close(bool by_user) { + virtual void Close(bool by_user) OVERRIDE { if (by_user) Logger::log("notification closed by user\n"); else Logger::log("notification closed by script\n"); } - virtual std::string id() const { + virtual std::string id() const OVERRIDE { return notification_id_; } + virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE { + return NULL; + } + private: std::string notification_id_; diff --git a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc index ef27791..e171b00 100644 --- a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc +++ b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc @@ -38,21 +38,27 @@ class CloudPrintProxyService::TokenExpiredNotificationDelegate : cloud_print_service_(cloud_print_service) { } - void Display() {} + virtual void Display() OVERRIDE {} - void Error() { + virtual void Error() OVERRIDE { cloud_print_service_->OnTokenExpiredNotificationError(); } - void Close(bool by_user) { + virtual void Close(bool by_user) OVERRIDE { cloud_print_service_->OnTokenExpiredNotificationClosed(by_user); } - void Click() { + virtual void Click() OVERRIDE { cloud_print_service_->OnTokenExpiredNotificationClick(); } - std::string id() const { return "cloudprint.tokenexpired"; } + virtual std::string id() const OVERRIDE { + return "cloudprint.tokenexpired"; + } + + virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE { + return NULL; + } private: virtual ~TokenExpiredNotificationDelegate() {} diff --git a/chrome/browser/status_icons/desktop_notification_balloon.cc b/chrome/browser/status_icons/desktop_notification_balloon.cc index 70d46ee..d49a8bb 100644 --- a/chrome/browser/status_icons/desktop_notification_balloon.cc +++ b/chrome/browser/status_icons/desktop_notification_balloon.cc @@ -49,6 +49,9 @@ class DummyNotificationDelegate : public NotificationDelegate { virtual void Close(bool by_user) OVERRIDE {} virtual void Click() OVERRIDE {} virtual std::string id() const OVERRIDE { return id_; } + virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE { + return NULL; + } private: virtual ~DummyNotificationDelegate() {} diff --git a/chrome/browser/ui/cocoa/notifications/balloon_controller_unittest.mm b/chrome/browser/ui/cocoa/notifications/balloon_controller_unittest.mm index 1832517..1b9bd25 100644 --- a/chrome/browser/ui/cocoa/notifications/balloon_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/notifications/balloon_controller_unittest.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -7,6 +7,7 @@ #include "chrome/browser/notifications/balloon.h" #include "chrome/browser/notifications/balloon_collection.h" #include "chrome/browser/notifications/notification.h" +#include "chrome/browser/notifications/notification_object_proxy.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/cocoa/cocoa_test_helper.h" #include "chrome/browser/ui/cocoa/notifications/balloon_controller.h" diff --git a/chrome/browser/ui/views/ash/balloon_collection_impl_ash.cc b/chrome/browser/ui/views/ash/balloon_collection_impl_ash.cc index 646af7d..bc9de45 100644 --- a/chrome/browser/ui/views/ash/balloon_collection_impl_ash.cc +++ b/chrome/browser/ui/views/ash/balloon_collection_impl_ash.cc @@ -4,17 +4,103 @@ #include "chrome/browser/ui/views/ash/balloon_collection_impl_ash.h" +#include "ash/ash_switches.h" +#include "ash/shell.h" +#include "ash/system/status_area_widget.h" +#include "base/command_line.h" +#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/notifications/balloon.h" +#include "chrome/browser/notifications/desktop_notification_service.h" +#include "chrome/browser/notifications/desktop_notification_service_factory.h" #include "chrome/browser/notifications/notification.h" -#include "chrome/browser/ui/views/notifications/balloon_view_views.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/views/ash/balloon_view_ash.h" #include "chrome/browser/ui/views/notifications/balloon_view_host.h" +#include "chrome/browser/ui/views/notifications/balloon_view_views.h" + +namespace { + +bool IsAshNotifyEnabled() { + return CommandLine::ForCurrentProcess()->HasSwitch(ash::switches::kAshNotify); +} + +} // namespace BalloonCollectionImplAsh::BalloonCollectionImplAsh() { + if (IsAshNotifyEnabled()) { + ash::Shell::GetInstance()->status_area_widget()-> + web_notification_tray()->SetDelegate(this); + } } BalloonCollectionImplAsh::~BalloonCollectionImplAsh() { } +bool BalloonCollectionImplAsh::HasSpace() const { + if (!IsAshNotifyEnabled()) + return BalloonCollectionImpl::HasSpace(); + return true; // Overflow is handled by ash::WebNotificationTray. +} + +void BalloonCollectionImplAsh::Add(const Notification& notification, + Profile* profile) { + if (IsAshNotifyEnabled()) { + if (notification.is_html()) + return; // HTML notifications are not supported in Ash. + if (notification.title().empty() && notification.body().empty()) + return; // Empty notification, don't show. + } + return BalloonCollectionImpl::Add(notification, profile); +} + +void BalloonCollectionImplAsh::DisableExtension( + const std::string& notifcation_id) { + Balloon* balloon = base().FindBalloonById(notifcation_id); + if (!balloon) + return; + ExtensionService* extension_service = + balloon->profile()->GetExtensionService(); + const GURL& origin = balloon->notification().origin_url(); + const extensions::Extension* extension = + extension_service->extensions()->GetExtensionOrAppByURL( + ExtensionURLInfo(origin)); + if (!extension) + return; + extension_service->DisableExtension( + extension->id(), extensions::Extension::DISABLE_USER_ACTION); +} + +void BalloonCollectionImplAsh::DisableNotificationsFromSource( + const std::string& notifcation_id) { + Balloon* balloon = base().FindBalloonById(notifcation_id); + if (!balloon) + return; + DesktopNotificationService* service = + DesktopNotificationServiceFactory::GetForProfile(balloon->profile()); + service->DenyPermission(balloon->notification().origin_url()); +} + +void BalloonCollectionImplAsh::NotificationRemoved( + const std::string& notifcation_id) { + RemoveById(notifcation_id); +} + +void BalloonCollectionImplAsh::ShowSettings(const std::string& notifcation_id) { + Balloon* balloon = base().FindBalloonById(notifcation_id); + Profile* profile = + balloon ? balloon->profile() : ProfileManager::GetDefaultProfile(); + Browser* browser = browser::FindOrCreateTabbedBrowser(profile); + browser->ShowContentSettingsPage(CONTENT_SETTINGS_TYPE_NOTIFICATIONS); +} + +void BalloonCollectionImplAsh::OnClicked(const std::string& notifcation_id) { + Balloon* balloon = base().FindBalloonById(notifcation_id); + if (!balloon) + return; + balloon->OnClick(); +} + bool BalloonCollectionImplAsh::AddWebUIMessageCallback( const Notification& notification, const std::string& message, @@ -65,13 +151,18 @@ bool BalloonCollectionImplAsh::UpdateAndShowNotification( Balloon* BalloonCollectionImplAsh::MakeBalloon( const Notification& notification, Profile* profile) { Balloon* balloon = new Balloon(notification, profile, this); - ::BalloonViewImpl* balloon_view = new ::BalloonViewImpl(this); - if (system_notifications_.find(notification.notification_id()) != - system_notifications_.end()) - balloon_view->set_enable_web_ui(true); - balloon->set_view(balloon_view); - gfx::Size size(layout().min_balloon_width(), layout().min_balloon_height()); - balloon->set_content_size(size); + if (!IsAshNotifyEnabled()) { + ::BalloonViewImpl* balloon_view = new ::BalloonViewImpl(this); + if (system_notifications_.find(notification.notification_id()) != + system_notifications_.end()) + balloon_view->set_enable_web_ui(true); + balloon->set_view(balloon_view); + gfx::Size size(layout().min_balloon_width(), layout().min_balloon_height()); + balloon->set_content_size(size); + } else { + BalloonViewAsh* balloon_view = new BalloonViewAsh(this); + balloon->set_view(balloon_view); + } return balloon; } diff --git a/chrome/browser/ui/views/ash/balloon_collection_impl_ash.h b/chrome/browser/ui/views/ash/balloon_collection_impl_ash.h index d457d6d..e590ce1 100644 --- a/chrome/browser/ui/views/ash/balloon_collection_impl_ash.h +++ b/chrome/browser/ui/views/ash/balloon_collection_impl_ash.h @@ -8,16 +8,31 @@ #include <set> +#include "ash/system/web_notification/web_notification_tray.h" #include "chrome/browser/chromeos/notifications/balloon_view_host_chromeos.h" // MessageCallback #include "chrome/browser/notifications/balloon_collection_impl.h" // Wrapper on top of ::BalloonCollectionImpl to provide an interface for // chromeos::SystemNotification. -class BalloonCollectionImplAsh : public ::BalloonCollectionImpl { +class BalloonCollectionImplAsh : public BalloonCollectionImpl, + public ash::WebNotificationTray::Delegate { public: BalloonCollectionImplAsh(); virtual ~BalloonCollectionImplAsh(); + // Overridden from BalloonCollectionImpl. + virtual void Add(const Notification& notification, + Profile* profile) OVERRIDE; + virtual bool HasSpace() const OVERRIDE; + + // Overridden from WebNotificationTray::Delegate. + virtual void NotificationRemoved(const std::string& notifcation_id) OVERRIDE; + virtual void DisableExtension(const std::string& notifcation_id) OVERRIDE; + virtual void DisableNotificationsFromSource( + const std::string& notifcation_id) OVERRIDE; + virtual void ShowSettings(const std::string& notifcation_id) OVERRIDE; + virtual void OnClicked(const std::string& notifcation_id) OVERRIDE; + // Adds a callback for WebUI message. Returns true if the callback // is succssfully registered, or false otherwise. It fails to add if // there is no notification that matches NotificationDelegate::id(), diff --git a/chrome/browser/ui/views/ash/balloon_view_ash.cc b/chrome/browser/ui/views/ash/balloon_view_ash.cc new file mode 100644 index 0000000..3b8b4be --- /dev/null +++ b/chrome/browser/ui/views/ash/balloon_view_ash.cc @@ -0,0 +1,165 @@ +// Copyright (c) 2012 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/ui/views/ash/balloon_view_ash.h" + +#include "ash/shell.h" +#include "ash/system/status_area_widget.h" +#include "ash/system/web_notification/web_notification_tray.h" +#include "base/logging.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/notifications/balloon_collection.h" +#include "chrome/browser/notifications/notification.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/icon_messages.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/site_instance.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" +#include "content/public/browser/web_contents_observer.h" +#include "ipc/ipc_message.h" +#include "ipc/ipc_message_macros.h" +#include "ui/gfx/image/image_skia.h" +#include "webkit/glue/image_resource_fetcher.h" + +namespace { + +const int kNotificationIconImageSize = 32; + +ash::WebNotificationTray* GetWebNotificationTray() { + return ash::Shell::GetInstance()-> + status_area_widget()->web_notification_tray(); +} + +} // namespace + +class BalloonViewAsh::IconFetcher : public content::WebContentsObserver { + public: + IconFetcher(content::WebContents* web_contents, + const std::string& notification_id, + const GURL& icon_url) + : content::WebContentsObserver(web_contents), + request_id_(0), + notification_id_(notification_id), + icon_url_(icon_url) { + Observe(web_contents); + content::RenderViewHost* host = web_contents->GetRenderViewHost(); + host->Send(new IconMsg_DownloadFavicon(host->GetRoutingID(), + ++request_id_, + icon_url, + kNotificationIconImageSize)); + } + + // content::WebContentsObserver override. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { + bool message_handled = false; // Allow other handlers to receive these. + IPC_BEGIN_MESSAGE_MAP(IconFetcher, message) + IPC_MESSAGE_HANDLER(IconHostMsg_DidDownloadFavicon, OnDidDownloadFavicon) + IPC_MESSAGE_UNHANDLED(message_handled = false) + IPC_END_MESSAGE_MAP() + return message_handled; + } + + void OnDidDownloadFavicon(int id, + const GURL& image_url, + bool errored, + const SkBitmap& bitmap) { + if (image_url != icon_url_ || id != request_id_) + return; + GetWebNotificationTray()->SetNotificationImage( + notification_id_, gfx::ImageSkia(bitmap)); + } + + private: + int request_id_; + std::string notification_id_; + GURL icon_url_; + + DISALLOW_COPY_AND_ASSIGN(IconFetcher); +}; + +BalloonViewAsh::BalloonViewAsh(BalloonCollection* collection) + : collection_(collection), + balloon_(NULL) { +} + +BalloonViewAsh::~BalloonViewAsh() { +} + +// BalloonView interface. +void BalloonViewAsh::Show(Balloon* balloon) { + balloon_ = balloon; + const Notification& notification = balloon_->notification(); + std::string extension_id = GetExtensionId(balloon); + GetWebNotificationTray()->AddNotification(notification.notification_id(), + notification.title(), + notification.body(), + notification.display_source(), + extension_id); + FetchIcon(notification); +} + +void BalloonViewAsh::Update() { + const Notification& notification = balloon_->notification(); + GetWebNotificationTray()->UpdateNotification(notification.notification_id(), + notification.title(), + notification.body()); + FetchIcon(notification); +} + +void BalloonViewAsh::RepositionToBalloon() { +} + +void BalloonViewAsh::Close(bool by_user) { + Notification notification(balloon_->notification()); // Copy notification + collection_->OnBalloonClosed(balloon_); // Deletes balloon. + notification.Close(by_user); + GetWebNotificationTray()->RemoveNotification(notification.notification_id()); +} + +gfx::Size BalloonViewAsh::GetSize() const { + return gfx::Size(); +} + +BalloonHost* BalloonViewAsh::GetHost() const { + return NULL; +} + +void BalloonViewAsh::FetchIcon(const Notification& notification) { + if (!notification.icon().empty()) { + ash::Shell::GetInstance()->status_area_widget()-> + web_notification_tray()->SetNotificationImage( + notification.notification_id(), notification.icon()); + return; + } + if (notification.icon_url().is_empty()) + return; + content::RenderViewHost* rvh = notification.GetRenderViewHost(); + if (!rvh) { + LOG(WARNING) << "Notification has icon url but no RenderViewHost"; + return; + } + content::WebContents* web_contents = + content::WebContents::FromRenderViewHost(rvh); + if (!web_contents) { + LOG(WARNING) << "Notification has icon url but no WebContents"; + return; + } + icon_fetcher_.reset(new IconFetcher(web_contents, + notification.notification_id(), + notification.icon_url())); +} + +std::string BalloonViewAsh::GetExtensionId(Balloon* balloon) { + ExtensionService* extension_service = + balloon_->profile()->GetExtensionService(); + const GURL& origin = balloon_->notification().origin_url(); + const extensions::Extension* extension = + extension_service->extensions()->GetExtensionOrAppByURL( + ExtensionURLInfo(origin)); + if (extension) + return extension->id(); + return std::string(); +} diff --git a/chrome/browser/ui/views/ash/balloon_view_ash.h b/chrome/browser/ui/views/ash/balloon_view_ash.h new file mode 100644 index 0000000..2fe20f2 --- /dev/null +++ b/chrome/browser/ui/views/ash/balloon_view_ash.h @@ -0,0 +1,38 @@ +// Copyright (c) 2012 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_UI_VIEWS_ASH_BALLOON_VIEW_ASH_H_ +#define CHROME_BROWSER_UI_VIEWS_ASH_BALLOON_VIEW_ASH_H_ +#pragma once + +#include "chrome/browser/notifications/balloon.h" + +// On Ash, a "BalloonView" is just a wrapper for ash notification entries. +class BalloonViewAsh : public BalloonView { + public: + explicit BalloonViewAsh(BalloonCollection* collection); + virtual ~BalloonViewAsh(); + + // BalloonView interface. + virtual void Show(Balloon* balloon) OVERRIDE; + virtual void Update() OVERRIDE; + virtual void RepositionToBalloon() OVERRIDE; + virtual void Close(bool by_user) OVERRIDE; + virtual gfx::Size GetSize() const OVERRIDE; + virtual BalloonHost* GetHost() const OVERRIDE; + + private: + class IconFetcher; + + void FetchIcon(const Notification& notification); + std::string GetExtensionId(Balloon* balloon); + + BalloonCollection* collection_; + Balloon* balloon_; + scoped_ptr<IconFetcher> icon_fetcher_; + + DISALLOW_COPY_AND_ASSIGN(BalloonViewAsh); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_ASH_BALLOON_VIEW_ASH_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index e39bd85..45588c4 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -3351,6 +3351,8 @@ 'browser/ui/views/ash/app_list/search_builder.h', 'browser/ui/views/ash/balloon_collection_impl_ash.cc', 'browser/ui/views/ash/balloon_collection_impl_ash.h', + 'browser/ui/views/ash/balloon_view_ash.cc', + 'browser/ui/views/ash/balloon_view_ash.h', 'browser/ui/views/ash/brightness_controller_chromeos.cc', 'browser/ui/views/ash/brightness_controller_chromeos.h', 'browser/ui/views/ash/browser_non_client_frame_view_ash.h', |