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 fa42fe4d8f54f4189fc24d6595e9cd38b4369110..c4024e360f8ca1f4906b97a4f21b08df9bcdd85c 100644 |
| --- a/components/favicon/core/large_icon_service.cc |
| +++ b/components/favicon/core/large_icon_service.cc |
| @@ -4,149 +4,251 @@ |
| #include "components/favicon/core/large_icon_service.h" |
| +#include <algorithm> |
| #include <memory> |
| #include "base/bind.h" |
| +#include "base/feature_list.h" |
| #include "base/location.h" |
| #include "base/logging.h" |
| #include "base/macros.h" |
| +#include "base/memory/ptr_util.h" |
| #include "base/memory/ref_counted.h" |
| +#include "base/strings/stringprintf.h" |
| #include "base/task_runner.h" |
| #include "base/threading/sequenced_worker_pool.h" |
| +#include "base/threading/thread_task_runner_handle.h" |
| +#include "components/data_use_measurement/core/data_use_user_data.h" |
| #include "components/favicon/core/favicon_service.h" |
| +#include "components/favicon/core/features.h" |
| #include "components/favicon_base/fallback_icon_style.h" |
| #include "components/favicon_base/favicon_types.h" |
| +#include "components/favicon_base/favicon_util.h" |
| +#include "components/image_fetcher/image_fetcher.h" |
| #include "skia/ext/image_operations.h" |
| #include "ui/gfx/codec/png_codec.h" |
| #include "ui/gfx/geometry/size.h" |
| +using image_fetcher::ImageFetcher; |
| + |
| +namespace favicon { |
| + |
| namespace { |
| -// Processes the bitmap data returned from the FaviconService as part of a |
| +const char kGoogleServer1RequestFormat[] = |
| + "https://s2.googleusercontent.com/s2/" |
| + "favicons?domain=%s&src=chrome_large_icons&sz=%d&alt=404"; |
| +const int kGoogleServer1DesiredSizeInPixel = 32; |
| + |
| +// Type APPLE_TOUCH includes TOUCH_ICONs as well as FAVICONs as fallback. |
| +const char kGoogleServer2RequestFormat[] = |
| + "https://t0.gstatic.com/" |
| + "faviconV2?url=%s&type=APPLE_TOUCH&size=%d&min_size=%d&max_size=%d"; |
| +const int kGoogleServer2MinSizeInPixel = 48; |
| +const int kGoogleServer2MaxSizeInPixel = 256; |
| +const int kGoogleServer2DesiredSizeInPixel = 192; |
| + |
| +// Base class for processing one large icon query. |
| +class LargeIconWorkerBase { |
| + public: |
| + LargeIconWorkerBase(const GURL& page_url, |
| + int min_source_size_in_pixel, |
| + int desired_size_in_pixel, |
| + favicon_base::LargeIconCallback callback, |
| + scoped_refptr<base::TaskRunner> background_task_runner, |
| + base::CancelableTaskTracker* tracker, |
| + FaviconService* favicon_service); |
| + |
| + virtual base::CancelableTaskTracker::TaskId Start() = 0; |
| + |
| + protected: |
| + ~LargeIconWorkerBase() = default; |
| + void PrepareLargeIconResult( |
| + const favicon_base::FaviconRawBitmapResult* bitmap_result, |
| + bool create_bitmap); |
| + |
| + // Must run on the owner (UI) thread in production. |
| + void RunCallback(); |
| + |
| + GURL page_url_; |
| + |
| + int min_source_size_in_pixel_; |
| + int desired_size_in_pixel_; |
| + favicon_base::LargeIconCallback callback_; |
| + scoped_refptr<base::TaskRunner> background_task_runner_; |
| + base::CancelableTaskTracker* tracker_; |
| + FaviconService* favicon_service_; |
| + |
| + // Data constructed on the background thread. |
| + std::unique_ptr<favicon_base::LargeIconResult> result_; |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(LargeIconWorkerBase); |
| +}; |
| + |
| +LargeIconWorkerBase::LargeIconWorkerBase( |
| + const GURL& page_url, |
| + int min_source_size_in_pixel, |
| + int desired_size_in_pixel, |
| + favicon_base::LargeIconCallback callback, |
| + scoped_refptr<base::TaskRunner> background_task_runner, |
| + base::CancelableTaskTracker* tracker, |
| + FaviconService* favicon_service) |
| + : page_url_(page_url), |
| + min_source_size_in_pixel_(std::min(min_source_size_in_pixel_, 32)), |
| + desired_size_in_pixel_(desired_size_in_pixel), |
| + callback_(callback), |
| + background_task_runner_(background_task_runner), |
| + tracker_(tracker), |
| + favicon_service_(favicon_service) {} |
| + |
| +void LargeIconWorkerBase::PrepareLargeIconResult( |
| + const favicon_base::FaviconRawBitmapResult* bitmap_result, |
| + bool create_bitmap) { |
| + if (create_bitmap && bitmap_result && bitmap_result->is_valid()) { |
| + result_ = base::MakeUnique<favicon_base::LargeIconResult>(*bitmap_result); |
| + } else { |
| + // Compute fallback icon style. |
| + std::unique_ptr<favicon_base::FallbackIconStyle> fallback_icon_style = |
| + base::MakeUnique<favicon_base::FallbackIconStyle>(); |
| + if (bitmap_result && bitmap_result->is_valid()) { |
| + favicon_base::SetDominantColorAsBackground(bitmap_result->bitmap_data, |
| + fallback_icon_style.get()); |
| + } |
| + result_ = base::MakeUnique<favicon_base::LargeIconResult>( |
| + std::move(fallback_icon_style)); |
| + } |
| +} |
| + |
| +void LargeIconWorkerBase::RunCallback() { |
| + callback_.Run(*result_); |
| +} |
| + |
| +// Processes the bitmap data returned from a Google favicon server as part of a |
| // LargeIconService request. |
| -class LargeIconWorker : public base::RefCountedThreadSafe<LargeIconWorker> { |
| +class LargeIconCacheWorker |
| + : public LargeIconWorkerBase, |
| + public base::RefCountedThreadSafe<LargeIconCacheWorker> { |
| public: |
| - LargeIconWorker(int min_source_size_in_pixel, |
| - int desired_size_in_pixel, |
| - favicon_base::LargeIconCallback callback, |
| - scoped_refptr<base::TaskRunner> background_task_runner, |
| - base::CancelableTaskTracker* tracker); |
| + LargeIconCacheWorker(const GURL& page_url, |
| + int min_source_size_in_pixel, |
| + int desired_size_in_pixel, |
| + favicon_base::LargeIconCallback callback, |
| + scoped_refptr<base::TaskRunner> background_task_runner, |
| + base::CancelableTaskTracker* tracker, |
| + FaviconService* favicon_service); |
| + |
| + base::CancelableTaskTracker::TaskId Start() override; |
| + |
| + private: |
| + friend class base::RefCountedThreadSafe<LargeIconCacheWorker>; |
| + virtual ~LargeIconCacheWorker(); |
| // Must run on the owner (UI) thread in production. |
| // Intermediate callback for GetLargeIconOrFallbackStyle(). Invokes |
| // ProcessIconOnBackgroundThread() so we do not perform complex image |
| // operations on the UI thread. |
| - void OnIconLookupComplete( |
| + void OnCachedIconLookupComplete( |
| const favicon_base::FaviconRawBitmapResult& 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 |
| + // 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(); |
| + void ProcessCachedIconOnBackgroundThread( |
| + const favicon_base::FaviconRawBitmapResult& bitmap_result); |
| // Must run on a background thread in production. |
| - // If |bitmap_result_| is square and large enough (>= |min_source_in_pixel_|), |
| + // 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( |
| + // into |bitmap_result| and returns true. |
| + bool ResizeCachedIconOnBackgroundThreadIfValid( |
| + const favicon_base::FaviconRawBitmapResult& bitmap_result, |
| 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_; |
| - scoped_refptr<base::TaskRunner> background_task_runner_; |
| - base::CancelableTaskTracker* tracker_; |
| - favicon_base::FaviconRawBitmapResult bitmap_result_; |
| - std::unique_ptr<favicon_base::LargeIconResult> result_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(LargeIconWorker); |
| + DISALLOW_COPY_AND_ASSIGN(LargeIconCacheWorker); |
| }; |
| -LargeIconWorker::LargeIconWorker( |
| +LargeIconCacheWorker::LargeIconCacheWorker( |
| + const GURL& page_url, |
| int min_source_size_in_pixel, |
| int desired_size_in_pixel, |
| favicon_base::LargeIconCallback 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), |
| - background_task_runner_(background_task_runner), |
| - tracker_(tracker) { |
| + base::CancelableTaskTracker* tracker, |
| + FaviconService* favicon_service) |
| + : LargeIconWorkerBase(page_url, |
| + min_source_size_in_pixel, |
| + desired_size_in_pixel, |
| + callback, |
| + background_task_runner, |
| + tracker, |
| + favicon_service) {} |
| + |
| +LargeIconCacheWorker::~LargeIconCacheWorker() {} |
| + |
| +base::CancelableTaskTracker::TaskId LargeIconCacheWorker::Start() { |
| + return favicon_service_->GetRawFaviconForPageURL( |
| + page_url_, |
| + favicon_base::IconType::FAVICON | favicon_base::IconType::TOUCH_ICON | |
| + favicon_base::IconType::TOUCH_PRECOMPOSED_ICON, |
| + desired_size_in_pixel_, |
| + base::Bind(&LargeIconCacheWorker::OnCachedIconLookupComplete, this), |
| + tracker_); |
| } |
| -LargeIconWorker::~LargeIconWorker() { |
| -} |
| - |
| -void LargeIconWorker::OnIconLookupComplete( |
| +void LargeIconCacheWorker::OnCachedIconLookupComplete( |
| const favicon_base::FaviconRawBitmapResult& bitmap_result) { |
| - bitmap_result_ = bitmap_result; |
| + // Prepare the data for the callback and run it. |
| tracker_->PostTaskAndReply( |
| background_task_runner_.get(), FROM_HERE, |
| - base::Bind(&LargeIconWorker::ProcessIconOnBackgroundThread, this), |
| - base::Bind(&LargeIconWorker::OnIconProcessingComplete, this)); |
| + base::Bind(&LargeIconCacheWorker::ProcessCachedIconOnBackgroundThread, |
| + this, bitmap_result), |
| + base::Bind(&LargeIconCacheWorker::RunCallback, this)); |
| } |
| -void LargeIconWorker::ProcessIconOnBackgroundThread() { |
| +void LargeIconCacheWorker::ProcessCachedIconOnBackgroundThread( |
| + const favicon_base::FaviconRawBitmapResult& bitmap_result) { |
| 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())); |
| - } |
| + bool create_bitmap = ResizeCachedIconOnBackgroundThreadIfValid( |
| + bitmap_result, &resized_bitmap_result); |
| + PrepareLargeIconResult(&resized_bitmap_result, create_bitmap); |
| } |
| -bool LargeIconWorker::ResizeLargeIconOnBackgroundThreadIfValid( |
| +bool LargeIconCacheWorker::ResizeCachedIconOnBackgroundThreadIfValid( |
| + const favicon_base::FaviconRawBitmapResult& bitmap_result, |
| 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()) |
| + 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_) |
| + if (bitmap_result.pixel_size.width() < min_source_size_in_pixel_) |
| return false; |
| - *resized_bitmap_result = bitmap_result_; |
| + *resized_bitmap_result = bitmap_result; |
| - // Special case: Can use |bitmap_result_| as is. |
| + // Special case: Can use |bitmap_result| as is. |
| if (desired_size_in_pixel_ == 0 || |
| - bitmap_result_.pixel_size.width() == desired_size_in_pixel_) |
| + 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)) |
| + if (!gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), |
| + bitmap_result.bitmap_data->size(), |
| + &decoded_bitmap)) |
| return false; |
| - SkBitmap resized_bitmap = skia::ImageOperations::Resize( |
| + SkBitmap 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)) |
| + if (!gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bitmap_data)) |
| return false; |
| resized_bitmap_result->pixel_size = |
| @@ -156,49 +258,249 @@ bool LargeIconWorker::ResizeLargeIconOnBackgroundThreadIfValid( |
| return true; |
| } |
| -void LargeIconWorker::OnIconProcessingComplete() { |
| - callback_.Run(*result_); |
| +// Processes the bitmap data returned from the FaviconService as part of a |
| +// LargeIconService request. |
| +class LargeIconGoogleServerWorker |
| + : public LargeIconWorkerBase, |
| + public base::RefCountedThreadSafe<LargeIconGoogleServerWorker> { |
| + public: |
| + LargeIconGoogleServerWorker( |
| + const GURL& page_url, |
| + int min_source_size_in_pixel, |
| + int desired_size_in_pixel, |
| + favicon_base::LargeIconCallback callback, |
| + scoped_refptr<base::TaskRunner> background_task_runner, |
| + base::CancelableTaskTracker* tracker, |
| + FaviconService* favicon_service, |
| + ImageFetcher* image_fetcher); |
| + |
| + base::CancelableTaskTracker::TaskId Start() override; |
| + |
| + private: |
| + friend class base::RefCountedThreadSafe<LargeIconGoogleServerWorker>; |
| + virtual ~LargeIconGoogleServerWorker(); |
| + |
| + void ProcessIconFromGoogleServerOnBackgroundThread(const GURL& icon_url, |
| + const gfx::Image& image); |
| + |
| + // 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 |bitmap_result| and returns true. |
| + bool ResizeIconFromGoogleServerOnBackgroundThreadIfValid( |
| + const GURL& icon_url, |
| + const gfx::Image image, |
| + favicon_base::FaviconRawBitmapResult* resized_bitmap_result); |
| + |
| + // Create the GET URL that requests the desired favicon from a Google favicon |
| + // server (version 1 / version 2). |
| + GURL GetIconUrlForGoogleServer1() const; |
| + GURL GetIconUrlForGoogleServer2() const; |
| + |
| + // Fetches an icon for the given |icon_url| and stores it in the favicon DB. |
| + void FetchIconFromGoogleServer(const GURL& icon_url); |
| + void OnFetchIconFromGoogleServerComplete(const std::string& icon_url, |
| + const gfx::Image& image); |
| + |
| + ImageFetcher* image_fetcher_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(LargeIconGoogleServerWorker); |
| +}; |
| + |
| +LargeIconGoogleServerWorker::LargeIconGoogleServerWorker( |
| + const GURL& page_url, |
| + int min_source_size_in_pixel, |
| + int desired_size_in_pixel, |
| + favicon_base::LargeIconCallback callback, |
| + scoped_refptr<base::TaskRunner> background_task_runner, |
| + base::CancelableTaskTracker* tracker, |
| + FaviconService* favicon_service, |
| + ImageFetcher* image_fetcher) |
| + : LargeIconWorkerBase(page_url, |
| + min_source_size_in_pixel, |
| + desired_size_in_pixel, |
| + callback, |
| + background_task_runner, |
| + tracker, |
| + favicon_service), |
| + image_fetcher_(image_fetcher) {} |
| + |
| +LargeIconGoogleServerWorker::~LargeIconGoogleServerWorker() {} |
| + |
| +base::CancelableTaskTracker::TaskId LargeIconGoogleServerWorker::Start() { |
| + GURL server_url; |
| + if (base::FeatureList::IsEnabled(kFaviconFetchLargeIconFromGoogleServer2)) { |
| + server_url = GetIconUrlForGoogleServer2(); |
| + } else if (min_source_size_in_pixel_ <= 16 && |
| + base::FeatureList::IsEnabled( |
| + kFaviconFetchLargeIconFromGoogleServer1)) { |
| + // Server 1 cannot guarantee that the served icon has original size >=16px |
| + // as it upscales images to fill in empty spots for missing sizes (32px, |
| + // 64px) when indexing. |
| + server_url = GetIconUrlForGoogleServer1(); |
| + } |
| + |
| + return tracker_->PostTask( |
| + background_task_runner_.get(), FROM_HERE, |
| + base::Bind(&LargeIconGoogleServerWorker::FetchIconFromGoogleServer, this, |
| + server_url)); |
| } |
| -} // namespace |
| +GURL LargeIconGoogleServerWorker::GetIconUrlForGoogleServer1() const { |
| + return GURL(base::StringPrintf(kGoogleServer1RequestFormat, |
| + page_url_.spec().c_str(), |
| + kGoogleServer1DesiredSizeInPixel)); |
| +} |
| -namespace favicon { |
| +GURL LargeIconGoogleServerWorker::GetIconUrlForGoogleServer2() const { |
| + // TODO(jkrcal): make the desired/min/max sizes depend on the device (its |
| + // scale factor, etc). |
| + return GURL(base::StringPrintf( |
| + kGoogleServer2RequestFormat, page_url_.GetWithEmptyPath().spec().c_str(), |
| + kGoogleServer2DesiredSizeInPixel, kGoogleServer2MinSizeInPixel, |
| + kGoogleServer2MaxSizeInPixel)); |
| +} |
| + |
| +void LargeIconGoogleServerWorker::FetchIconFromGoogleServer( |
| + const GURL& icon_url) { |
| + if (icon_url.is_empty() // Do not fetch if fetching is disabled. |
| + || favicon_service_->WasUnableToDownloadFavicon(icon_url) |
| + // Do not retry if there is a previous cache miss recorded for |icon_url|. |
| + ) { |
| + PrepareLargeIconResult(nullptr, /*create_bitmap=*/false); |
| + RunCallback(); |
| + return; |
| + } |
| + |
| + image_fetcher_->SetDataUseServiceName( |
| + data_use_measurement::DataUseUserData::LARGE_ICON_SERVICE); |
| + image_fetcher_->StartOrQueueNetworkRequest( |
| + icon_url.spec(), icon_url, |
| + base::Bind( |
| + &LargeIconGoogleServerWorker::OnFetchIconFromGoogleServerComplete, |
| + this)); |
| +} |
| + |
| +void LargeIconGoogleServerWorker::OnFetchIconFromGoogleServerComplete( |
| + const std::string& icon_url, |
| + const gfx::Image& image) { |
| + if (image.IsEmpty()) { |
| + favicon_service_->UnableToDownloadFavicon(GURL(icon_url)); |
| + PrepareLargeIconResult(nullptr, /*create_bitmap=*/false); |
| + RunCallback(); |
| + return; |
| + } |
| + |
| + // TODO(jkrcal): Extract the original icon url from the response headers if |
| + // available and use it instead of |icon_url|. |
| + |
| + // TODO(jkrcal): never overwrite favicons. Fix in this CL! |
|
jkrcal
2017/02/27 17:31:19
This still definitely needs to get addressed in th
|
| + favicon_service_->SetFavicons(page_url_, GURL(icon_url), |
| + favicon_base::IconType::TOUCH_ICON, image); |
| + // Mark the icons as out-of-date so that they are refetched when we visit the |
| + // original page any time in the future. |
| + favicon_service_->SetFaviconOutOfDateForPage(page_url_); |
| + |
| + tracker_->PostTaskAndReply( |
| + background_task_runner_.get(), FROM_HERE, |
| + base::Bind(&LargeIconGoogleServerWorker:: |
| + ProcessIconFromGoogleServerOnBackgroundThread, |
| + this, GURL(icon_url), image), |
| + base::Bind(&LargeIconGoogleServerWorker::RunCallback, this)); |
| +} |
| + |
| +void LargeIconGoogleServerWorker::ProcessIconFromGoogleServerOnBackgroundThread( |
| + const GURL& icon_url, |
| + const gfx::Image& image) { |
| + favicon_base::FaviconRawBitmapResult resized_bitmap_result; |
| + bool create_bitmap = ResizeIconFromGoogleServerOnBackgroundThreadIfValid( |
| + icon_url, image, &resized_bitmap_result); |
| + PrepareLargeIconResult(&resized_bitmap_result, create_bitmap); |
| +} |
| + |
| +bool LargeIconGoogleServerWorker:: |
| + ResizeIconFromGoogleServerOnBackgroundThreadIfValid( |
| + const GURL& icon_url, |
| + const gfx::Image image, |
| + favicon_base::FaviconRawBitmapResult* resized_bitmap_result) { |
| + // Require bitmap to be valid and square. |
| + if (!image.IsEmpty() || image.Width() != image.Height()) |
| + return false; |
| + |
| + // Require bitmap to be large enough. It's square, so just check width. |
| + if (image.Width() < min_source_size_in_pixel_) |
| + return false; |
| + |
| + SkBitmap bitmap = image.AsBitmap(); |
| + |
| + // Resize if necessary. |
| + if (desired_size_in_pixel_ != 0 && image.Width() != desired_size_in_pixel_) { |
| + bitmap = skia::ImageOperations::Resize( |
| + bitmap, skia::ImageOperations::RESIZE_LANCZOS3, desired_size_in_pixel_, |
| + desired_size_in_pixel_); |
| + } |
| + |
| + std::vector<unsigned char> bitmap_data; |
| + if (!gfx::PNGCodec::EncodeBGRASkBitmap(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); |
| + resized_bitmap_result->expired = true; |
| + resized_bitmap_result->icon_url = icon_url; |
| + resized_bitmap_result->icon_type = favicon_base::IconType::TOUCH_ICON; |
| + |
| + return true; |
| +} |
| + |
| +} // namespace |
| LargeIconService::LargeIconService( |
| FaviconService* favicon_service, |
| - const scoped_refptr<base::TaskRunner>& background_task_runner) |
| + const scoped_refptr<base::TaskRunner>& background_task_runner, |
| + std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher) |
| : favicon_service_(favicon_service), |
| - background_task_runner_(background_task_runner) { |
| - large_icon_types_.push_back(favicon_base::IconType::FAVICON); |
| - large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON); |
| - large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON); |
| -} |
| + background_task_runner_(background_task_runner), |
| + image_fetcher_(std::move(image_fetcher)) {} |
| 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) { |
| - DCHECK_LE(1, min_source_size_in_pixel); |
| +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) { |
| + DCHECK_LE(0, min_source_size_in_pixel); |
| + DCHECK_LE(0, desired_size_in_pixel); |
| + |
| + scoped_refptr<LargeIconCacheWorker> worker = new LargeIconCacheWorker( |
| + page_url, min_source_size_in_pixel, desired_size_in_pixel, callback, |
| + background_task_runner_, tracker, favicon_service_); |
| + return worker->Start(); |
| +} |
| + |
| +base::CancelableTaskTracker::TaskId |
| +LargeIconService::GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( |
| + const GURL& page_url, |
| + int min_source_size_in_pixel, |
| + int desired_size_in_pixel, |
| + const favicon_base::LargeIconCallback& callback, |
| + base::CancelableTaskTracker* tracker) { |
| + DCHECK_LE(0, 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); |
| - |
| - // 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); |
| + scoped_refptr<LargeIconGoogleServerWorker> worker = |
| + new LargeIconGoogleServerWorker(page_url, min_source_size_in_pixel, |
| + desired_size_in_pixel, callback, |
| + background_task_runner_, tracker, |
| + favicon_service_, image_fetcher_.get()); |
| + return worker->Start(); |
| } |
| } // namespace favicon |