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

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: Created 5 years, 7 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 0e3c98ab060cade1e85b81d3e788889a9baa4817..a5f4a2ec34e59a0f9de5460544d47ecb3107533b 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 "base/strings/string_number_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/download/download_crx_util.h"
@@ -22,8 +23,12 @@
#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 "third_party/skia/include/core/SkBitmap.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,6 +36,44 @@ 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
+
+gfx::Image ReadNotificationImage(
+ const std::string type, const base::FilePath file_path) {
+ CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
asanka 2015/06/03 03:02:04 Use DCHECK_CURRENTLY_ON instead.
yoshiki 2015/06/04 04:13:22 Done.
+
+ gfx::Image image;
+
+ std::string data;
+ bool ret = base::ReadFileToString(file_path, &data);
+ if (!ret)
+ return image;
+
+ if (data.size() > kMaxImagePreviewSize)
+ return image;
+
+ if (type == "png") {
+ image = gfx::Image::CreateFrom1xPNGBytes(
+ reinterpret_cast<const unsigned char*>(data.data()),
+ data.length());
+ } else if (type == "jpg" || type == "jpeg") {
+ scoped_ptr<SkBitmap> decoded_jpeg(gfx::JPEGCodec::Decode(
+ reinterpret_cast<const unsigned char*>(data.data()),
+ data.length()));
+ if (decoded_jpeg) {
+ image = gfx::Image::CreateFrom1xBitmap(*decoded_jpeg);
+ }
+ } else {
+ NOTREACHED(); // Type should have been checked in the caller.
+ }
+
+ // TODO(yoshiki): Shrink the image for saving memory.
+
+ return image;
+}
+
} // anonymous namespace
// static
@@ -77,7 +120,8 @@ DownloadNotificationItem::DownloadNotificationItem(content::DownloadItem* item,
: profile_(profile),
watcher_(new NotificationWatcher(this)),
item_(item),
- delegate_(delegate) {
+ delegate_(delegate),
+ weak_factory_(this) {
item->AddObserver(this);
// Notify that the instance is just created.
@@ -200,6 +244,8 @@ void DownloadNotificationItem::CloseNotificationByUser() {
void DownloadNotificationItem::UpdateNotificationData(
NotificationUpdateType type) {
+ CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
DownloadItemModel model(item_);
DownloadCommands command(item_);
@@ -217,7 +263,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());
@@ -231,9 +277,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:
@@ -248,9 +294,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:
@@ -269,7 +315,7 @@ void DownloadNotificationItem::UpdateNotificationData(
// be updated. (same as the case of type = COMPLETE)
notification_->set_type(message_center::NOTIFICATION_TYPE_PROGRESS);
notification_->set_progress(0);
- SetNotificationImage(IDR_DOWNLOAD_NOTIFICATION_WARNING);
+ SetNotificationIcon(IDR_DOWNLOAD_NOTIFICATION_WARNING);
break;
case content::DownloadItem::MAX_DOWNLOAD_STATE: // sentinel
NOTREACHED();
@@ -290,10 +336,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_NEW) {
notification_ui_manager()->Add(*notification_, profile_);
} else if (type == UPDATE_EXISTING) {
@@ -315,6 +357,43 @@ void DownloadNotificationItem::UpdateNotificationData(
}
previous_download_state_ = item_->GetState();
+
+ if (item_->IsDone() && !set_image_ &&
+ item_->GetTotalBytes() <= kMaxImagePreviewSize) {
+ DCHECK(notification_->image().IsEmpty());
+
+ set_image_ = true;
+
+ std::string type;
+ std::string mime_topleveltype;
+ std::string mime_subtype;
+ if (net::ParseMimeTypeWithoutParameter(
+ item_->GetMimeType(), &mime_topleveltype, &mime_subtype) &&
+ mime_topleveltype == "image" &&
+ (mime_subtype == "png" || mime_subtype == "jpg" ||
+ mime_subtype == "jpeg")) {
+ type = mime_subtype;
+ } else {
+ std::string dot_extension = item_->GetTargetFilePath().FinalExtension();
+ if (!dot_extension.empty()) {
+ std::string extension = dot_extension.substr(1);
+ if (extension == "png" || extension == "jpg" || extension == "jpeg")
+ type = extension;
+ }
+ }
+
+ if (!type.empty()) {
+ base::FilePath file_path = item_->GetFullPath();
+ content::BrowserThread::PostTaskAndReplyWithResult(
+ content::BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&ReadNotificationImage,
+ type,
+ file_path),
+ base::Bind(&DownloadNotificationItem::SetNotificationImage,
+ weak_factory_.GetWeakPtr()));
+ }
+ }
}
void DownloadNotificationItem::OnDownloadOpened(content::DownloadItem* item) {
@@ -338,7 +417,7 @@ void DownloadNotificationItem::OnDownloadDestroyed(
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();
@@ -346,6 +425,13 @@ void DownloadNotificationItem::SetNotificationImage(int resource_id) {
notification_->set_icon(bundle.GetImageNamed(image_resource_id_));
}
+void DownloadNotificationItem::SetNotificationImage(gfx::Image image) {
+ if (image.IsEmpty())
+ return;
+ notification_->set_image(image);
+ UpdateNotificationData(UPDATE_EXISTING);
+}
+
NotificationUIManager* DownloadNotificationItem::notification_ui_manager()
const {
if (stub_notification_ui_manager_for_testing_) {

Powered by Google App Engine
This is Rietveld 408576698