| Index: chrome/browser/download/notification/download_notification_item.cc
|
| diff --git a/chrome/browser/download/notification/download_notification_item.cc b/chrome/browser/download/notification/download_notification_item.cc
|
| index fd2bad562d50e3433c8904f9e2f2e14d14cdea70..714de6f086f8fc5cffac67d191225dd8f977ffcf 100644
|
| --- a/chrome/browser/download/notification/download_notification_item.cc
|
| +++ b/chrome/browser/download/notification/download_notification_item.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "chrome/browser/download/notification/download_notification_item.h"
|
|
|
| +#include "base/files/file_util.h"
|
| #include "chrome/browser/browser_process.h"
|
| #include "chrome/browser/download/download_crx_util.h"
|
| #include "chrome/browser/download/download_item_model.h"
|
| @@ -15,6 +16,7 @@
|
| #include "chrome/common/url_constants.h"
|
| #include "chrome/grit/chromium_strings.h"
|
| #include "chrome/grit/generated_resources.h"
|
| +#include "components/mime_util/mime_util.h"
|
| #include "content/public/browser/browser_context.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/download_interrupt_reasons.h"
|
| @@ -22,8 +24,11 @@
|
| #include "content/public/browser/page_navigator.h"
|
| #include "content/public/browser/web_contents.h"
|
| #include "grit/theme_resources.h"
|
| +#include "net/base/mime_util.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
| #include "ui/base/resource/resource_bundle.h"
|
| +#include "ui/gfx/codec/jpeg_codec.h"
|
| +#include "ui/gfx/image/image.h"
|
| #include "ui/message_center/message_center.h"
|
|
|
| namespace {
|
| @@ -31,12 +36,30 @@ namespace {
|
| const char kDownloadNotificationNotifierId[] =
|
| "chrome://downloads/notification/id-notifier";
|
|
|
| +// Maximum size of preview image. If the image exceeds this size, don't show the
|
| +// preview image.
|
| +const int64 kMaxImagePreviewSize = 10 * 1024 * 1024; // 10 MB
|
| +
|
| +std::string ReadNotificationImage(const base::FilePath& file_path) {
|
| + DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
|
| +
|
| + std::string data;
|
| + bool ret = base::ReadFileToString(file_path, &data);
|
| + if (!ret)
|
| + return std::string();
|
| +
|
| + DCHECK_LE(data.size(), static_cast<size_t>(kMaxImagePreviewSize));
|
| +
|
| + return data;
|
| +}
|
| +
|
| } // anonymous namespace
|
|
|
| DownloadNotificationItem::DownloadNotificationItem(
|
| content::DownloadItem* item,
|
| DownloadNotificationManagerForProfile* manager)
|
| - : item_(item) {
|
| + : item_(item),
|
| + weak_factory_(this) {
|
| ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
|
|
|
| message_center::RichNotificationData data;
|
| @@ -59,10 +82,17 @@ DownloadNotificationItem::DownloadNotificationItem(
|
| }
|
|
|
| DownloadNotificationItem::~DownloadNotificationItem() {
|
| + if (image_decode_status_ == IN_PROGRESS)
|
| + ImageDecoder::Cancel(this);
|
| }
|
|
|
| void DownloadNotificationItem::OnNotificationClose() {
|
| visible_ = false;
|
| +
|
| + if (image_decode_status_ == IN_PROGRESS) {
|
| + image_decode_status_ = NOT_STARTED;
|
| + ImageDecoder::Cancel(this);
|
| + }
|
| }
|
|
|
| void DownloadNotificationItem::OnNotificationClick() {
|
| @@ -186,6 +216,8 @@ void DownloadNotificationItem::Update() {
|
|
|
| void DownloadNotificationItem::UpdateNotificationData(
|
| NotificationUpdateType type) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| +
|
| DownloadItemModel model(item_);
|
| DownloadCommands command(item_);
|
|
|
| @@ -195,7 +227,7 @@ void DownloadNotificationItem::UpdateNotificationData(
|
| notification_->set_message(GetWarningText());
|
|
|
| // Show icon.
|
| - SetNotificationImage(IDR_DOWNLOAD_NOTIFICATION_MALICIOUS);
|
| + SetNotificationIcon(IDR_DOWNLOAD_NOTIFICATION_MALICIOUS);
|
| } else {
|
| notification_->set_title(GetTitle());
|
| notification_->set_message(model.GetStatusText());
|
| @@ -209,9 +241,9 @@ void DownloadNotificationItem::UpdateNotificationData(
|
| notification_->set_progress(item_->PercentComplete());
|
| if (is_off_the_record) {
|
| // TODO(yoshiki): Replace the tentative image.
|
| - SetNotificationImage(IDR_DOWNLOAD_NOTIFICATION_INCOGNITO);
|
| + SetNotificationIcon(IDR_DOWNLOAD_NOTIFICATION_INCOGNITO);
|
| } else {
|
| - SetNotificationImage(IDR_DOWNLOAD_NOTIFICATION_DOWNLOADING);
|
| + SetNotificationIcon(IDR_DOWNLOAD_NOTIFICATION_DOWNLOADING);
|
| }
|
| break;
|
| case content::DownloadItem::COMPLETE:
|
| @@ -232,9 +264,9 @@ void DownloadNotificationItem::UpdateNotificationData(
|
|
|
| if (is_off_the_record) {
|
| // TODO(yoshiki): Replace the tentative image.
|
| - SetNotificationImage(IDR_DOWNLOAD_NOTIFICATION_INCOGNITO);
|
| + SetNotificationIcon(IDR_DOWNLOAD_NOTIFICATION_INCOGNITO);
|
| } else {
|
| - SetNotificationImage(IDR_DOWNLOAD_NOTIFICATION_DOWNLOADING);
|
| + SetNotificationIcon(IDR_DOWNLOAD_NOTIFICATION_DOWNLOADING);
|
| }
|
| break;
|
| case content::DownloadItem::CANCELLED:
|
| @@ -257,7 +289,7 @@ void DownloadNotificationItem::UpdateNotificationData(
|
| }
|
|
|
| notification_->set_progress(0);
|
| - SetNotificationImage(IDR_DOWNLOAD_NOTIFICATION_WARNING);
|
| + SetNotificationIcon(IDR_DOWNLOAD_NOTIFICATION_WARNING);
|
| break;
|
| case content::DownloadItem::MAX_DOWNLOAD_STATE: // sentinel
|
| NOTREACHED();
|
| @@ -278,10 +310,6 @@ void DownloadNotificationItem::UpdateNotificationData(
|
| }
|
| notification_->set_buttons(notification_actions);
|
|
|
| - if (item_->IsDone()) {
|
| - // TODO(yoshiki): If the downloaded file is an image, show the thumbnail.
|
| - }
|
| -
|
| if (type == ADD) {
|
| g_browser_process->notification_ui_manager()->
|
| Add(*notification_, profile());
|
| @@ -299,6 +327,41 @@ void DownloadNotificationItem::UpdateNotificationData(
|
| } else {
|
| NOTREACHED();
|
| }
|
| +
|
| + if (item_->IsDone() && image_decode_status_ == NOT_STARTED) {
|
| + // TODO(yoshiki): Add an UMA to collect statistics of image file sizes.
|
| +
|
| + if (item_->GetReceivedBytes() > kMaxImagePreviewSize)
|
| + return;
|
| +
|
| + DCHECK(notification_->image().IsEmpty());
|
| +
|
| + image_decode_status_ = IN_PROGRESS;
|
| +
|
| + bool maybe_image = false;
|
| + if (mime_util::IsSupportedImageMimeType(item_->GetMimeType())) {
|
| + maybe_image = true;
|
| + } else {
|
| + std::string mime;
|
| + base::FilePath::StringType extension_with_dot =
|
| + item_->GetTargetFilePath().FinalExtension();
|
| + if (!extension_with_dot.empty() &&
|
| + net::GetWellKnownMimeTypeFromExtension(extension_with_dot.substr(1),
|
| + &mime) &&
|
| + mime_util::IsSupportedImageMimeType(mime)) {
|
| + maybe_image = true;
|
| + }
|
| + }
|
| +
|
| + if (maybe_image) {
|
| + base::FilePath file_path = item_->GetFullPath();
|
| + base::PostTaskAndReplyWithResult(
|
| + content::BrowserThread::GetBlockingPool(), FROM_HERE,
|
| + base::Bind(&ReadNotificationImage, file_path),
|
| + base::Bind(&DownloadNotificationItem::OnImageLoaded,
|
| + weak_factory_.GetWeakPtr()));
|
| + }
|
| + }
|
| }
|
|
|
| void DownloadNotificationItem::OnDownloadRemoved(content::DownloadItem* item) {
|
| @@ -314,7 +377,7 @@ void DownloadNotificationItem::OnDownloadRemoved(content::DownloadItem* item) {
|
| item_ = nullptr;
|
| }
|
|
|
| -void DownloadNotificationItem::SetNotificationImage(int resource_id) {
|
| +void DownloadNotificationItem::SetNotificationIcon(int resource_id) {
|
| if (image_resource_id_ == resource_id)
|
| return;
|
| ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
|
| @@ -322,6 +385,28 @@ void DownloadNotificationItem::SetNotificationImage(int resource_id) {
|
| notification_->set_icon(bundle.GetImageNamed(image_resource_id_));
|
| }
|
|
|
| +void DownloadNotificationItem::OnImageLoaded(const std::string& image_data) {
|
| + if (image_data.empty())
|
| + return;
|
| +
|
| + // TODO(yoshiki): Set option to reduce the image size to supress memory usage.
|
| + ImageDecoder::Start(this, image_data);
|
| +}
|
| +
|
| +void DownloadNotificationItem::OnImageDecoded(const SkBitmap& decoded_image) {
|
| + gfx::Image image = gfx::Image::CreateFrom1xBitmap(decoded_image);
|
| + notification_->set_image(image);
|
| + image_decode_status_ = DONE;
|
| + UpdateNotificationData(UPDATE);
|
| +}
|
| +
|
| +void DownloadNotificationItem::OnDecodeImageFailed() {
|
| + DCHECK(notification_->image().IsEmpty());
|
| +
|
| + image_decode_status_ = FAILED;
|
| + UpdateNotificationData(UPDATE);
|
| +}
|
| +
|
| scoped_ptr<std::vector<DownloadCommands::Command>>
|
| DownloadNotificationItem::GetExtraActions() const {
|
| scoped_ptr<std::vector<DownloadCommands::Command>> actions(
|
|
|