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

Unified Diff: components/favicon/core/large_icon_service.cc

Issue 2784233003: [LargeIconService] Allow decoding of images in the service (Closed)
Patch Set: Peter's comments Created 3 years, 9 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: 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

Powered by Google App Engine
This is Rietveld 408576698