Chromium Code Reviews| 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..5ca4cb83d928720f3ce35c492e85b5981818b44f 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,27 @@ 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 std::string type, const base::FilePath file_path) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); |
| + |
| + gfx::Image image; |
| + |
| + std::string data; |
| + bool ret = base::ReadFileToString(file_path, &data); |
| + if (!ret) |
| + return std::string(); |
| + |
| + if (data.size() > kMaxImagePreviewSize) |
|
asanka
2015/06/09 00:13:38
Check the size of the file rather than checking th
yoshiki
2015/06/10 15:05:04
The file size is checked at l.336 in the patchset
|
| + return std::string(); |
| + |
| + return data; |
| +} |
| + |
| } // anonymous namespace |
| // static |
| @@ -77,7 +103,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 +227,8 @@ void DownloadNotificationItem::CloseNotificationByUser() { |
| void DownloadNotificationItem::UpdateNotificationData( |
| NotificationUpdateType type) { |
| + CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| + |
| DownloadItemModel model(item_); |
| DownloadCommands command(item_); |
| @@ -217,7 +246,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 +260,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 +277,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 +298,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 +319,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 +340,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( |
|
asanka
2015/06/09 00:13:38
Use mime_util::IsSupportedImageMimeType()
yoshiki
2015/06/10 15:05:04
Done.
|
| + 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(); |
|
asanka
2015/06/09 00:13:38
Use net::GetMimeTypeFromFile(). Note that this can
yoshiki
2015/06/10 15:05:04
I think we don't need to check the file contents f
|
| + 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::OnImageLoaded, |
| + weak_factory_.GetWeakPtr())); |
| + } |
| + } |
| } |
| void DownloadNotificationItem::OnDownloadOpened(content::DownloadItem* item) { |
| @@ -338,7 +400,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 +408,25 @@ void DownloadNotificationItem::SetNotificationImage(int resource_id) { |
| notification_->set_icon(bundle.GetImageNamed(image_resource_id_)); |
| } |
| +void DownloadNotificationItem::OnImageLoaded(std::string image_data) { |
| + if (image_data.empty()) |
| + return; |
| + |
| + // TODO(yoshiki): Set option to reduce the image size to supress memory usage. |
|
asanka
2015/06/09 00:13:38
No. We should be passing a file handle over to the
yoshiki
2015/06/10 15:05:04
Done. Resizing will be implemented later.
|
| + ImageDecoder::Start(this, image_data); |
|
asanka
2015/06/09 00:13:38
You should call ImageDecoder::Cancel() if the noti
yoshiki
2015/06/10 15:05:04
Done.
|
| +} |
| + |
| +void DownloadNotificationItem::OnImageDecoded(const SkBitmap& decoded_image) { |
| + gfx::Image image = gfx::Image::CreateFrom1xBitmap(decoded_image); |
| + notification_->set_image(image); |
| + UpdateNotificationData(UPDATE_EXISTING); |
| +} |
| + |
| +void DownloadNotificationItem::OnDecodeImageFailed() { |
| + notification_->set_image(gfx::Image()); |
| + UpdateNotificationData(UPDATE_EXISTING); |
| +} |
| + |
| NotificationUIManager* DownloadNotificationItem::notification_ui_manager() |
| const { |
| if (stub_notification_ui_manager_for_testing_) { |