diff options
author | dewittj@chromium.org <dewittj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-08 21:39:18 +0000 |
---|---|---|
committer | dewittj@chromium.org <dewittj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-08 21:39:18 +0000 |
commit | 744411c89138de27e950eecfe4526adf70867844 (patch) | |
tree | 2df3ef72be85d0719e4e3c6d56c7b268d8fefdb4 /chrome/browser/notifications | |
parent | 6ad55bb2e39f944d1aac989b77ca3df03dd35f90 (diff) | |
download | chromium_src-744411c89138de27e950eecfe4526adf70867844.zip chromium_src-744411c89138de27e950eecfe4526adf70867844.tar.gz chromium_src-744411c89138de27e950eecfe4526adf70867844.tar.bz2 |
Add ImageDownload to MessageCenterNotificationManager.
This ports the current icon download functionality from ChromeOS
to the Windows/ChromeOS MessageCenterNotificatioNManager.
BUG=169538
Review URL: https://chromiumcodereview.appspot.com/12194018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@181553 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/notifications')
3 files changed, 190 insertions, 22 deletions
diff --git a/chrome/browser/notifications/message_center_notification_manager.cc b/chrome/browser/notifications/message_center_notification_manager.cc index 44f3352..8fd12db 100644 --- a/chrome/browser/notifications/message_center_notification_manager.cc +++ b/chrome/browser/notifications/message_center_notification_manager.cc @@ -17,6 +17,8 @@ #include "chrome/browser/ui/host_desktop.h" #include "chrome/common/extensions/extension_set.h" #include "chrome/common/pref_names.h" +#include "content/public/browser/web_contents.h" +#include "ui/message_center/message_center_constants.h" #include "ui/message_center/message_center_tray.h" MessageCenterNotificationManager::MessageCenterNotificationManager( @@ -34,6 +36,7 @@ MessageCenterNotificationManager::MessageCenterNotificationManager( MessageCenterNotificationManager::~MessageCenterNotificationManager() { } + //////////////////////////////////////////////////////////////////////////////// // NotificationUIManager @@ -107,7 +110,8 @@ void MessageCenterNotificationManager::CancelAll() { bool MessageCenterNotificationManager::ShowNotification( const Notification& notification, Profile* profile) { // There is always space in MessageCenter, it never rejects Notifications. - AddProfileNotification(new ProfileNotification(profile, notification)); + AddProfileNotification( + new ProfileNotification(profile, notification, message_center_)); return true; } @@ -136,14 +140,15 @@ bool MessageCenterNotificationManager::UpdateNotification( old_notification->notification().Close(false); // Not by user. delete old_notification; profile_notifications_.erase(old_id); - profile_notifications_[notification.notification_id()] = - new ProfileNotification(profile, notification); - + ProfileNotification* new_notification = + new ProfileNotification(profile, notification, message_center_); + profile_notifications_[notification.notification_id()] = new_notification; message_center_->UpdateNotification(old_id, notification.notification_id(), notification.title(), notification.body(), notification.optional_fields()); + new_notification->StartDownloads(); notification.Display(); return true; } @@ -211,15 +216,135 @@ void MessageCenterNotificationManager::OnButtonClicked( } //////////////////////////////////////////////////////////////////////////////// +// ImageDownloads + +MessageCenterNotificationManager::ImageDownloads::ImageDownloads( + message_center::MessageCenter* message_center) + : message_center_(message_center) { +} + +MessageCenterNotificationManager::ImageDownloads::~ImageDownloads() { } + +void MessageCenterNotificationManager::ImageDownloads::StartDownloads( + const Notification& notification) { + // Notification primary icon. + StartDownloadWithImage( + notification, + ¬ification.icon(), + notification.icon_url(), + message_center::kNotificationIconSize, + base::Bind(&message_center::MessageCenter::SetNotificationIcon, + base::Unretained(message_center_), + notification.notification_id())); + + // Notification image. + StartDownloadByKey( + notification, + ui::notifications::kImageUrlKey, + message_center::kNotificationPreferredImageSize, + base::Bind(&message_center::MessageCenter::SetNotificationImage, + base::Unretained(message_center_), + notification.notification_id())); + + // Notification button icons. + StartDownloadByKey( + notification, + ui::notifications::kButtonOneIconUrlKey, + message_center::kNotificationButtonIconSize, + base::Bind(&message_center::MessageCenter::SetNotificationButtonIcon, + base::Unretained(message_center_), + notification.notification_id(), 0)); + StartDownloadByKey( + notification, ui::notifications::kButtonTwoIconUrlKey, + message_center::kNotificationButtonIconSize, + base::Bind(&message_center::MessageCenter::SetNotificationButtonIcon, + base::Unretained(message_center_), + notification.notification_id(), 1)); +} + +void MessageCenterNotificationManager::ImageDownloads::StartDownloadWithImage( + const Notification& notification, + const gfx::ImageSkia* image, + const GURL& url, + int size, + const SetImageCallback& callback) { + // Set the image directly if we have it. + if (image && !image->isNull()) { + callback.Run(*image); + return; + } + + // Leave the image null if there's no URL. + if (url.is_empty()) + return; + + content::RenderViewHost* host = notification.GetRenderViewHost(); + if (!host) { + LOG(WARNING) << "Notification needs an image but has no RenderViewHost"; + return; + } + + content::WebContents* contents = + content::WebContents::FromRenderViewHost(host); + if (!contents) { + LOG(WARNING) << "Notification needs an image but has no WebContents"; + return; + } + + contents->DownloadFavicon( + url, + size, + base::Bind( + &MessageCenterNotificationManager::ImageDownloads::DownloadComplete, + AsWeakPtr(), + callback)); +} + +void MessageCenterNotificationManager::ImageDownloads::StartDownloadByKey( + const Notification& notification, + const char* key, + int size, + const SetImageCallback& callback) { + const base::DictionaryValue* optional_fields = notification.optional_fields(); + if (optional_fields && optional_fields->HasKey(key)) { + string16 url; + optional_fields->GetString(key, &url); + StartDownloadWithImage(notification, NULL, GURL(url), size, callback); + } +} + +void MessageCenterNotificationManager::ImageDownloads::DownloadComplete( + const SetImageCallback& callback, + int download_id, + const GURL& image_url, + int requested_size, + const std::vector<SkBitmap>& bitmaps) { + if (bitmaps.empty()) + return; + gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(bitmaps[0]); + callback.Run(image); +} + +//////////////////////////////////////////////////////////////////////////////// // ProfileNotification MessageCenterNotificationManager::ProfileNotification::ProfileNotification( - Profile* profile, const Notification& notification) - : profile_(profile), - notification_(notification) { + Profile* profile, + const Notification& notification, + message_center::MessageCenter* message_center) + : profile_(profile), + notification_(notification), + downloads_(new ImageDownloads(message_center)) { DCHECK(profile); } +MessageCenterNotificationManager::ProfileNotification::~ProfileNotification() { +} + +void MessageCenterNotificationManager::ProfileNotification::StartDownloads() { + downloads_->StartDownloads(notification_); +} + std::string MessageCenterNotificationManager::ProfileNotification::GetExtensionId() { const ExtensionURLInfo url(notification().origin_url()); @@ -247,6 +372,7 @@ void MessageCenterNotificationManager::AddProfileNotification( notification.display_source(), profile_notification->GetExtensionId(), notification.optional_fields()); + profile_notification->StartDownloads(); notification.Display(); } diff --git a/chrome/browser/notifications/message_center_notification_manager.h b/chrome/browser/notifications/message_center_notification_manager.h index 0f4939b..b837466 100644 --- a/chrome/browser/notifications/message_center_notification_manager.h +++ b/chrome/browser/notifications/message_center_notification_manager.h @@ -53,23 +53,56 @@ class MessageCenterNotificationManager int button_index) OVERRIDE; private: - scoped_ptr<message_center::MessageCenterTrayDelegate> tray_; - message_center::MessageCenter* message_center_; // Weak, global. + typedef base::Callback<void(const gfx::ImageSkia&)> SetImageCallback; + class ImageDownloads + : public base::SupportsWeakPtr<ImageDownloads> { + public: + explicit ImageDownloads(message_center::MessageCenter* message_center); + virtual ~ImageDownloads(); + + void StartDownloads(const Notification& notification); + void StartDownloadWithImage(const Notification& notification, + const gfx::ImageSkia* image, + const GURL& url, + int size, + const SetImageCallback& callback); + void StartDownloadByKey(const Notification& notification, + const char* key, + int size, + const SetImageCallback& callback); + + // FaviconHelper callback. + void DownloadComplete(const SetImageCallback& callback, + int download_id, + const GURL& image_url, + int requested_size, + const std::vector<SkBitmap>& bitmaps); + private: + // Weak reference to global message center. + message_center::MessageCenter* message_center_; + DISALLOW_COPY_AND_ASSIGN(ImageDownloads); + }; -// This class keeps a set of original Notification objects and corresponding -// Profiles, so when MessageCenter calls back with a notification_id, this -// class has necessary mapping to other source info - for example, it calls -// NotificationDelegate supplied by client when someone clicks on a Notification -// in MessageCenter. Likewise, if a Profile or Extension is being removed, the -// map makes it possible to revoke the notifications from MessageCenter. -// To keep that set, we use the private ProfileNotification class that stores -// a superset of all information about a notification. - -// TODO(dimich): Consider merging all 4 types (Notification, QueuedNotification, -// ProfileNotification and NotificationList::Notification) into a single class. + // This class keeps a set of original Notification objects and corresponding + // Profiles, so when MessageCenter calls back with a notification_id, this + // class has necessary mapping to other source info - for example, it calls + // NotificationDelegate supplied by client when someone clicks on a + // Notification in MessageCenter. Likewise, if a Profile or Extension is + // being removed, the map makes it possible to revoke the notifications from + // MessageCenter. To keep that set, we use the private ProfileNotification + // class that stores a superset of all information about a notification. + + // TODO(dimich): Consider merging all 4 types (Notification, + // QueuedNotification, ProfileNotification and NotificationList::Notification) + // into a single class. class ProfileNotification { public: - ProfileNotification(Profile* profile, const Notification& notification); + ProfileNotification(Profile* profile, + const Notification& notification, + message_center::MessageCenter* message_center); + virtual ~ProfileNotification(); + + void StartDownloads(); Profile* profile() const { return profile_; } const Notification& notification() const { return notification_; } @@ -82,8 +115,14 @@ class MessageCenterNotificationManager // Weak, guaranteed not to be used after profile removal by parent class. Profile* profile_; Notification notification_; + // Track the downloads for this notification so the notification can be + // updated properly. + scoped_ptr<ImageDownloads> downloads_; }; + scoped_ptr<message_center::MessageCenterTrayDelegate> tray_; + message_center::MessageCenter* message_center_; // Weak, global. + // Use a map by notification_id since this mapping is the most often used. typedef std::map<std::string, ProfileNotification*> NotificationMap; NotificationMap profile_notifications_; diff --git a/chrome/browser/notifications/notification_ui_manager_impl.cc b/chrome/browser/notifications/notification_ui_manager_impl.cc index e6563ea..fcf56e8 100644 --- a/chrome/browser/notifications/notification_ui_manager_impl.cc +++ b/chrome/browser/notifications/notification_ui_manager_impl.cc @@ -5,6 +5,7 @@ #include "chrome/browser/notifications/notification_ui_manager_impl.h" #include "base/logging.h" +#include "base/memory/linked_ptr.h" #include "base/stl_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/fullscreen.h" @@ -145,7 +146,9 @@ void NotificationUIManagerImpl::CheckUserState() { } } -// TODO(dewittj): Eliminate recursion. +// Attempts to show each notification, leaving any failures in the queue. +// TODO(dewittj): Eliminate recursion when BallonCollection is used to render +// the Notification UI surfaces. void NotificationUIManagerImpl::ShowNotifications() { while (!show_queue_.empty()) { linked_ptr<QueuedNotification> queued_notification(show_queue_.front()); |