Chromium Code Reviews| Index: chrome/browser/ui/views/balloon_view_win.cc |
| diff --git a/chrome/browser/ui/views/balloon_view_win.cc b/chrome/browser/ui/views/balloon_view_win.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c849f6057ec11aef703d851f84708bbfd65d498d |
| --- /dev/null |
| +++ b/chrome/browser/ui/views/balloon_view_win.cc |
| @@ -0,0 +1,199 @@ |
| +// Copyright (c) 2013 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/balloon_view_win.h" |
| + |
| +#include "base/logging.h" |
| +#include "base/memory/weak_ptr.h" |
| +#include "base/values.h" |
| +#include "chrome/browser/favicon/favicon_util.h" |
| +#include "chrome/browser/notifications/balloon_collection.h" |
| +#include "chrome/browser/notifications/notification.h" |
| +#include "chrome/browser/ui/views/message_center/web_notification_tray_win.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 "ui/message_center/message_center.h" |
| +#include "ui/message_center/message_center_constants.h" |
| +#include "webkit/glue/image_resource_fetcher.h" |
| + |
| +namespace { |
| + |
| +typedef base::Callback<void(const gfx::ImageSkia&)> SetImageCallback; |
| + |
| +const int kPrimaryIconImageSize = 64; |
| +const int kSecondaryIconImageSize = 15; |
| + |
|
Pete Williamson
2013/01/23 19:52:16
Once again, this file is very similar to balloon_v
dewittj
2013/01/23 22:07:51
File gone.
|
| +// static |
| +message_center::MessageCenter* GetMessageCenter() { |
| + return ui::WebNotificationTrayWin::GetInstance()->message_center(); |
| +} |
| + |
| +} // namespace |
| + |
| +// TODO(dharcourt): Delay showing the notification until all images are |
| +// downloaded, and return an error to the notification creator/API caller |
| +// instead of showing a partial notification if any image download fails. |
| +class BalloonViewWin::ImageDownload |
| + : public base::SupportsWeakPtr<ImageDownload> { |
| + public: |
| + // Note that the setter callback passed in will not be called if the image |
| + // download fails for any reason. |
| + ImageDownload(const Notification& notification, |
| + const GURL& url, |
| + int size, |
| + const SetImageCallback& callback); |
| + virtual ~ImageDownload(); |
| + |
| + private: |
| + // FaviconHelper callback. |
| + virtual void Downloaded(int download_id, |
| + const GURL& image_url, |
| + int requested_size, |
| + const std::vector<SkBitmap>& bitmaps); |
| + |
| + const GURL& url_; |
| + int size_; |
| + SetImageCallback callback_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ImageDownload); |
| +}; |
| + |
| +BalloonViewWin::ImageDownload::ImageDownload(const Notification& notification, |
| + const GURL& url, |
| + int size, |
| + const SetImageCallback& callback) |
| + : url_(url), |
| + size_(size), |
| + callback_(callback) { |
| + 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(&ImageDownload::Downloaded, |
| + AsWeakPtr())); |
| +} |
| + |
| +BalloonViewWin::ImageDownload::~ImageDownload() { |
| +} |
| + |
| +void BalloonViewWin::ImageDownload::Downloaded( |
| + int download_id, |
| + const GURL& image_url, |
| + int requested_size, |
| + const std::vector<SkBitmap>& bitmaps) { |
| + if (bitmaps.empty()) |
| + return; |
| + gfx::ImageSkia image(bitmaps[0]); |
| + callback_.Run(image); |
| +} |
| + |
| +BalloonViewWin::BalloonViewWin(BalloonCollection* collection) |
| + : collection_(collection), |
| + balloon_(NULL) { |
| +} |
| + |
| +BalloonViewWin::~BalloonViewWin() { |
| +} |
| + |
| +// BalloonView interface. |
| +void BalloonViewWin::Show(Balloon* balloon) { |
| + balloon_ = balloon; |
| + const Notification& notification = balloon_->notification(); |
| + notification_id_ = notification.notification_id(); |
| + GetMessageCenter()->AddNotification(notification.type(), |
| + notification_id_, |
| + notification.title(), |
| + notification.body(), |
| + notification.display_source(), |
| + balloon->GetExtensionId(), |
| + notification.optional_fields()); |
| + DownloadImages(notification); |
| +} |
| + |
| +void BalloonViewWin::Update() { |
| + std::string previous_notification_id = notification_id_; |
| + const Notification& notification = balloon_->notification(); |
| + notification_id_ = notification.notification_id(); |
| + GetMessageCenter()->UpdateNotification(previous_notification_id, |
| + notification_id_, |
| + notification.title(), |
| + notification.body(), |
| + notification.optional_fields()); |
| + DownloadImages(notification); |
| +} |
| + |
| +void BalloonViewWin::RepositionToBalloon() { |
| +} |
| + |
| +void BalloonViewWin::Close(bool by_user) { |
| + Notification notification(balloon_->notification()); |
| + collection_->OnBalloonClosed(balloon_); // Deletes balloon. |
| + notification.Close(by_user); |
| + GetMessageCenter()->RemoveNotification(notification.notification_id()); |
| +} |
| + |
| +gfx::Size BalloonViewWin::GetSize() const { |
| + return gfx::Size(); |
| +} |
| + |
| +BalloonHost* BalloonViewWin::GetHost() const { |
| + return NULL; |
| +} |
| + |
| +void BalloonViewWin::SetNotificationIcon(const std::string& id, |
| + const gfx::ImageSkia& image) { |
| + GetMessageCenter()->SetNotificationPrimaryIcon(id, image); |
| +} |
| + |
| +void BalloonViewWin::SetNotificationImage(const std::string& id, |
| + const gfx::ImageSkia& image) { |
| + GetMessageCenter()->SetNotificationImage(id, image); |
| +} |
| + |
| +void BalloonViewWin::DownloadImages(const Notification& notification) { |
| + // Cancel any previous downloads. |
| + downloads_.clear(); |
| + |
| + // Set the notification's primary icon, or start a download for it. |
| + if (!notification.icon().isNull()) { |
| + SetNotificationIcon(notification_id_, notification.icon()); |
| + } else if (!notification.icon_url().is_empty()) { |
| + downloads_.push_back(linked_ptr<ImageDownload>(new ImageDownload( |
| + notification, notification.icon_url(), |
| + message_center::kNotificationIconWidth, |
| + base::Bind(&BalloonViewWin::SetNotificationIcon, |
| + base::Unretained(this), notification.notification_id())))); |
| + } |
| + |
| + // Start a download for the notification's image if appropriate. |
| + const base::DictionaryValue* optional_fields = notification.optional_fields(); |
| + if (optional_fields && |
| + optional_fields->HasKey(ui::notifications::kImageUrlKey)) { |
| + string16 url; |
| + optional_fields->GetString(ui::notifications::kImageUrlKey, &url); |
| + if (!url.empty()) { |
| + downloads_.push_back(linked_ptr<ImageDownload>(new ImageDownload( |
| + notification, GURL(url), |
| + message_center::kNotificationPreferredImageSize, |
| + base::Bind(&BalloonViewWin::SetNotificationImage, |
| + base::Unretained(this), notification.notification_id())))); |
| + } |
| + } |
| +} |