Chromium Code Reviews| Index: components/favicon/core/large_icon_service.cc |
| diff --git a/components/favicon/core/large_icon_service.cc b/components/favicon/core/large_icon_service.cc |
| index 7d519677c51780055520e90d6e9a6f3a0217b1ff..67f6bdb0ba32a294afca4d28c4c8879c3f1041f2 100644 |
| --- a/components/favicon/core/large_icon_service.cc |
| +++ b/components/favicon/core/large_icon_service.cc |
| @@ -56,13 +56,73 @@ GURL GetIconUrlForGoogleServerV2(const GURL& page_url, |
| page_url.spec().c_str())); |
| } |
| +bool IsDbResultAdequate(const favicon_base::FaviconRawBitmapResult& db_result, |
| + int min_source_size) { |
| + return db_result.is_valid() && |
| + db_result.pixel_size.width() == db_result.pixel_size.height() && |
| + db_result.pixel_size.width() >= min_source_size; |
| +} |
| + |
|
pkotwicz
2017/04/04 02:34:40
Nit: Please add a comment to this function
jkrcal
2017/04/04 09:34:16
Done.
|
| +gfx::Image ResizeLargeIconOnBackgroundThread( |
| + const favicon_base::FaviconRawBitmapResult& db_result, |
| + int desired_size) { |
| + gfx::Image image = gfx::Image::CreateFrom1xPNGBytes( |
| + db_result.bitmap_data->front(), db_result.bitmap_data->size()); |
| + |
| + if (desired_size == 0 || db_result.pixel_size.width() == desired_size) { |
| + return image; |
| + } |
| + |
| + SkBitmap resized = skia::ImageOperations::Resize( |
| + image.AsBitmap(), skia::ImageOperations::RESIZE_LANCZOS3, desired_size, |
| + desired_size); |
| + return gfx::Image::CreateFrom1xBitmap(resized); |
| +} |
| + |
| +void ProcessIconOnBackgroundThread( |
| + const favicon_base::FaviconRawBitmapResult& db_result, |
| + int min_source_size, |
| + int desired_size, |
| + favicon_base::FaviconRawBitmapResult* raw_result, |
| + SkBitmap* bitmap, |
| + favicon_base::FallbackIconStyle* fallback_icon_style) { |
| + gfx::Image image; |
| + if (IsDbResultAdequate(db_result, min_source_size)) { |
| + image = ResizeLargeIconOnBackgroundThread(db_result, desired_size); |
| + } |
| + |
| + if (!image.IsEmpty()) { |
|
pkotwicz
2017/04/04 02:34:40
Nit: You can nest this if() inside of the if(IsDbR
jkrcal
2017/04/04 09:34:16
Done.
|
| + if (raw_result) { |
| + *raw_result = db_result; |
| + if (desired_size != 0) |
| + raw_result->pixel_size = gfx::Size(desired_size, desired_size); |
| + raw_result->bitmap_data = image.As1xPNGBytes(); |
| + } |
| + if (bitmap) { |
| + *bitmap = image.AsBitmap(); |
| + } |
| + return; |
| + } |
| + |
| + if (!fallback_icon_style) |
| + return; |
| + |
| + *fallback_icon_style = favicon_base::FallbackIconStyle(); |
| + if (db_result.is_valid()) { |
| + favicon_base::SetDominantColorAsBackground(db_result.bitmap_data, |
| + fallback_icon_style); |
| + } |
| +} |
| + |
| // Processes the bitmap data returned from the FaviconService as part of a |
| // LargeIconService request. |
| class LargeIconWorker : public base::RefCountedThreadSafe<LargeIconWorker> { |
| public: |
| + // Exactly one of the callbacks is expected to be non-null. |
| LargeIconWorker(int min_source_size_in_pixel, |
| int desired_size_in_pixel, |
| - favicon_base::LargeIconCallback callback, |
| + favicon_base::LargeIconCallback raw_bitmap_callback, |
| + favicon_base::LargeIconImageCallback image_callback, |
| scoped_refptr<base::TaskRunner> background_task_runner, |
| base::CancelableTaskTracker* tracker); |
| @@ -71,39 +131,27 @@ class LargeIconWorker : public base::RefCountedThreadSafe<LargeIconWorker> { |
| // ProcessIconOnBackgroundThread() so we do not perform complex image |
| // operations on the UI thread. |
| void OnIconLookupComplete( |
| - const favicon_base::FaviconRawBitmapResult& bitmap_result); |
| + const favicon_base::FaviconRawBitmapResult& raw_bitmap_result); |
| private: |
| friend class base::RefCountedThreadSafe<LargeIconWorker>; |
| ~LargeIconWorker(); |
| - // Must run on a background thread in production. |
| - // Tries to resize |bitmap_result_| and pass the output to |callback_|. If |
| - // that does not work, computes the icon fallback style and uses it to |
| - // invoke |callback_|. This must be run on a background thread because image |
| - // resizing and dominant color extraction can be expensive. |
| - void ProcessIconOnBackgroundThread(); |
| - |
| - // Must run on a background thread in production. |
| - // If |bitmap_result_| is square and large enough (>= |min_source_in_pixel_|), |
| - // resizes it to |desired_size_in_pixel_| (but if |desired_size_in_pixel_| is |
| - // 0 then don't resize). If successful, stores the resulting bitmap data |
| - // into |resized_bitmap_result| and returns true. |
| - bool ResizeLargeIconOnBackgroundThreadIfValid( |
| - favicon_base::FaviconRawBitmapResult* resized_bitmap_result); |
| - |
| // Must run on the owner (UI) thread in production. |
| // Invoked when ProcessIconOnBackgroundThread() is done. |
| void OnIconProcessingComplete(); |
| int min_source_size_in_pixel_; |
| int desired_size_in_pixel_; |
| - favicon_base::LargeIconCallback callback_; |
| + favicon_base::LargeIconCallback raw_bitmap_callback_; |
| + favicon_base::LargeIconImageCallback image_callback_; |
| scoped_refptr<base::TaskRunner> background_task_runner_; |
| base::CancelableTaskTracker* tracker_; |
| - favicon_base::FaviconRawBitmapResult bitmap_result_; |
| - std::unique_ptr<favicon_base::LargeIconResult> result_; |
| + |
| + favicon_base::FaviconRawBitmapResult raw_bitmap_result_; |
| + SkBitmap image_result_; |
|
pkotwicz
2017/04/04 02:34:41
Nit: Rename this to |bitmap_result_|
jkrcal
2017/04/04 09:34:16
I'd like to keep this as there is an analogy with
pkotwicz
2017/04/04 12:43:42
It is confusing to have a variable which stores an
jkrcal
2017/04/04 14:44:40
Ok, done.
|
| + std::unique_ptr<favicon_base::FallbackIconStyle> fallback_icon_style_; |
|
pkotwicz
2017/04/04 02:34:40
Nit: You might as well make this:
favicon_base::F
jkrcal
2017/04/04 09:34:16
If I drop the unique_ptr, I would have to have a "
pkotwicz
2017/04/04 12:43:42
I understand now
|
| DISALLOW_COPY_AND_ASSIGN(LargeIconWorker); |
| }; |
| @@ -111,87 +159,54 @@ class LargeIconWorker : public base::RefCountedThreadSafe<LargeIconWorker> { |
| LargeIconWorker::LargeIconWorker( |
| int min_source_size_in_pixel, |
| int desired_size_in_pixel, |
| - favicon_base::LargeIconCallback callback, |
| + favicon_base::LargeIconCallback raw_bitmap_callback, |
| + favicon_base::LargeIconImageCallback image_callback, |
| scoped_refptr<base::TaskRunner> background_task_runner, |
| base::CancelableTaskTracker* tracker) |
| : min_source_size_in_pixel_(min_source_size_in_pixel), |
| desired_size_in_pixel_(desired_size_in_pixel), |
| - callback_(callback), |
| + raw_bitmap_callback_(raw_bitmap_callback), |
| + image_callback_(image_callback), |
| background_task_runner_(background_task_runner), |
| - tracker_(tracker) { |
| -} |
| + tracker_(tracker), |
| + fallback_icon_style_( |
| + base::MakeUnique<favicon_base::FallbackIconStyle>()) {} |
| LargeIconWorker::~LargeIconWorker() { |
| } |
| void LargeIconWorker::OnIconLookupComplete( |
| - const favicon_base::FaviconRawBitmapResult& bitmap_result) { |
| - bitmap_result_ = bitmap_result; |
| + const favicon_base::FaviconRawBitmapResult& raw_bitmap_result) { |
|
pkotwicz
2017/04/04 02:34:41
Can you please rename |raw_bitmap_result| to |db_r
jkrcal
2017/04/04 09:34:16
Makes sense! Done.
|
| tracker_->PostTaskAndReply( |
| background_task_runner_.get(), FROM_HERE, |
| - base::Bind(&LargeIconWorker::ProcessIconOnBackgroundThread, this), |
| + base::Bind(&ProcessIconOnBackgroundThread, raw_bitmap_result, |
| + min_source_size_in_pixel_, desired_size_in_pixel_, |
| + raw_bitmap_callback_ ? &raw_bitmap_result_ : nullptr, |
| + image_callback_ ? &image_result_ : nullptr, |
| + fallback_icon_style_.get()), |
| base::Bind(&LargeIconWorker::OnIconProcessingComplete, this)); |
| } |
| -void LargeIconWorker::ProcessIconOnBackgroundThread() { |
| - favicon_base::FaviconRawBitmapResult resized_bitmap_result; |
| - if (ResizeLargeIconOnBackgroundThreadIfValid(&resized_bitmap_result)) { |
| - result_.reset( |
| - new favicon_base::LargeIconResult(resized_bitmap_result)); |
| - } else { |
| - // Failed to resize |bitmap_result_|, so compute fallback icon style. |
| - std::unique_ptr<favicon_base::FallbackIconStyle> fallback_icon_style( |
| - new favicon_base::FallbackIconStyle()); |
| - if (bitmap_result_.is_valid()) { |
| - favicon_base::SetDominantColorAsBackground( |
| - bitmap_result_.bitmap_data, fallback_icon_style.get()); |
| - } |
| - result_.reset( |
| - new favicon_base::LargeIconResult(fallback_icon_style.release())); |
| +void LargeIconWorker::OnIconProcessingComplete() { |
| + // Return the large icon, if we have the image. |
| + if (raw_bitmap_callback_ && raw_bitmap_result_.is_valid()) { |
| + raw_bitmap_callback_.Run(favicon_base::LargeIconResult(raw_bitmap_result_)); |
| + return; |
| + } |
|
pkotwicz
2017/04/04 02:34:41
For the sake of simplicity, perhaps do
if (raw_bi
jkrcal
2017/04/04 09:34:16
Ok, done.
|
| + if (image_callback_ && !image_result_.isNull()) { |
| + image_callback_.Run(favicon_base::LargeIconImageResult( |
| + gfx::Image::CreateFrom1xBitmap(image_result_))); |
| + return; |
| } |
| -} |
| - |
| -bool LargeIconWorker::ResizeLargeIconOnBackgroundThreadIfValid( |
| - favicon_base::FaviconRawBitmapResult* resized_bitmap_result) { |
| - // Require bitmap to be valid and square. |
| - if (!bitmap_result_.is_valid() || |
| - bitmap_result_.pixel_size.width() != bitmap_result_.pixel_size.height()) |
| - return false; |
| - |
| - // Require bitmap to be large enough. It's square, so just check width. |
| - if (bitmap_result_.pixel_size.width() < min_source_size_in_pixel_) |
| - return false; |
| - |
| - *resized_bitmap_result = bitmap_result_; |
| - |
| - // Special case: Can use |bitmap_result_| as is. |
| - if (desired_size_in_pixel_ == 0 || |
| - bitmap_result_.pixel_size.width() == desired_size_in_pixel_) |
| - return true; |
| - |
| - // Resize bitmap: decode PNG, resize, and re-encode PNG. |
| - SkBitmap decoded_bitmap; |
| - if (!gfx::PNGCodec::Decode(bitmap_result_.bitmap_data->front(), |
| - bitmap_result_.bitmap_data->size(), &decoded_bitmap)) |
| - return false; |
| - |
| - SkBitmap resized_bitmap = skia::ImageOperations::Resize( |
| - decoded_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, |
| - desired_size_in_pixel_, desired_size_in_pixel_); |
| - |
| - std::vector<unsigned char> bitmap_data; |
| - if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_bitmap, false, &bitmap_data)) |
| - return false; |
| - |
| - resized_bitmap_result->pixel_size = |
| - gfx::Size(desired_size_in_pixel_, desired_size_in_pixel_); |
| - resized_bitmap_result->bitmap_data = |
| - base::RefCountedBytes::TakeVector(&bitmap_data); |
| - return true; |
| -} |
| -void LargeIconWorker::OnIconProcessingComplete() { |
| - callback_.Run(*result_); |
| + // Return fallback style, otherwise |
| + if (raw_bitmap_callback_) { |
| + raw_bitmap_callback_.Run( |
| + favicon_base::LargeIconResult(fallback_icon_style_.release())); |
| + } else { |
| + image_callback_.Run( |
| + favicon_base::LargeIconImageResult(fallback_icon_style_.release())); |
| + } |
| } |
| void OnFetchIconFromGoogleServerComplete( |
| @@ -242,18 +257,42 @@ LargeIconService::~LargeIconService() { |
| } |
| base::CancelableTaskTracker::TaskId |
| - LargeIconService::GetLargeIconOrFallbackStyle( |
| - const GURL& page_url, |
| - int min_source_size_in_pixel, |
| - int desired_size_in_pixel, |
| - const favicon_base::LargeIconCallback& callback, |
| - base::CancelableTaskTracker* tracker) { |
| +LargeIconService::GetLargeIconOrFallbackStyle( |
| + const GURL& page_url, |
| + int min_source_size_in_pixel, |
| + int desired_size_in_pixel, |
| + const favicon_base::LargeIconCallback& raw_bitmap_callback, |
| + base::CancelableTaskTracker* tracker) { |
| + DCHECK_LE(1, min_source_size_in_pixel); |
| + DCHECK_LE(0, desired_size_in_pixel); |
| + |
| + scoped_refptr<LargeIconWorker> worker = new LargeIconWorker( |
| + min_source_size_in_pixel, desired_size_in_pixel, raw_bitmap_callback, |
| + favicon_base::LargeIconImageCallback(), background_task_runner_, tracker); |
| + |
| + // TODO(beaudoin): For now this is just a wrapper around |
| + // GetLargestRawFaviconForPageURL. Add the logic required to select the best |
| + // possible large icon. Also add logic to fetch-on-demand when the URL of |
| + // a large icon is known but its bitmap is not available. |
| + return favicon_service_->GetLargestRawFaviconForPageURL( |
| + page_url, large_icon_types_, min_source_size_in_pixel, |
| + base::Bind(&LargeIconWorker::OnIconLookupComplete, worker), tracker); |
| +} |
| + |
| +base::CancelableTaskTracker::TaskId |
| +LargeIconService::GetLargeIconImageOrFallbackStyle( |
| + const GURL& page_url, |
| + int min_source_size_in_pixel, |
| + int desired_size_in_pixel, |
| + const favicon_base::LargeIconImageCallback& image_callback, |
| + base::CancelableTaskTracker* tracker) { |
| DCHECK_LE(1, min_source_size_in_pixel); |
| DCHECK_LE(0, desired_size_in_pixel); |
| scoped_refptr<LargeIconWorker> worker = |
| new LargeIconWorker(min_source_size_in_pixel, desired_size_in_pixel, |
| - callback, background_task_runner_, tracker); |
| + favicon_base::LargeIconCallback(), image_callback, |
| + background_task_runner_, tracker); |
| // TODO(beaudoin): For now this is just a wrapper around |
| // GetLargestRawFaviconForPageURL. Add the logic required to select the best |