Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1007)

Unified Diff: chrome/browser/download/notification/download_notification_item.cc

Issue 1159363002: [Download Notification] Show preview if downloaded file is image (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase & use embedded server Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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(

Powered by Google App Engine
This is Rietveld 408576698