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_) { |