| 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..a2b64c89702edff33a10a60091c7295c89207fdb 100644
|
| --- a/components/favicon/core/large_icon_service.cc
|
| +++ b/components/favicon/core/large_icon_service.cc
|
| @@ -10,18 +10,44 @@
|
| #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_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"
|
|
|
| +namespace favicon {
|
| namespace {
|
|
|
| +// Type APPLE_TOUCH prefers TOUCH_ICON and TOUCH_PRECOMPOSED_ICON. If neither is
|
| +// available, FAVICON is used as fallback.
|
| +// TODO(crbug.com/698671): Reconsider of type=APPLE_TOUCH should be specific to
|
| +// iOS, and if so expose a method like PreferTouchIcon() in FaviconService.
|
| +const char kGoogleServerV2RequestFormat[] =
|
| + "https://t0.gstatic.com/"
|
| + "faviconV2?user=chrome&url=%s&type=APPLE_TOUCH&size=%d&min_size=%d"
|
| + "&max_size=%d";
|
| +const int kGoogleServerV2MaxSizeInPixel = 256;
|
| +const int kGoogleServerV2DesiredSizeInPixel = 192;
|
| +
|
| +GURL GetIconUrlForGoogleServerV2(const GURL& page_url,
|
| + int min_source_size_in_pixel) {
|
| + return GURL(base::StringPrintf(
|
| + kGoogleServerV2RequestFormat, page_url.spec().c_str(),
|
| + kGoogleServerV2DesiredSizeInPixel, min_source_size_in_pixel,
|
| + kGoogleServerV2MaxSizeInPixel));
|
| +}
|
| +
|
| // Processes the bitmap data returned from the FaviconService as part of a
|
| // LargeIconService request.
|
| class LargeIconWorker : public base::RefCountedThreadSafe<LargeIconWorker> {
|
| @@ -160,15 +186,43 @@ void LargeIconWorker::OnIconProcessingComplete() {
|
| callback_.Run(*result_);
|
| }
|
|
|
| -} // namespace
|
| +void OnFetchIconFromGoogleServerComplete(
|
| + FaviconService* favicon_service,
|
| + const GURL& page_url,
|
| + const base::Callback<void(bool success)>& callback,
|
| + const std::string& icon_url,
|
| + const gfx::Image& image) {
|
| + if (image.IsEmpty()) {
|
| + DLOG(WARNING) << "large icon server fetch empty " << icon_url;
|
| + favicon_service->UnableToDownloadFavicon(GURL(icon_url));
|
| + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
|
| + base::Bind(callback, false));
|
| + return;
|
| + }
|
|
|
| -namespace favicon {
|
| + // TODO(jkrcal): Extract the original icon url from the response headers if
|
| + // available and use it instead of |icon_url|.
|
| +
|
| + // Write fetched icons to FaviconService's cache, but only if no icon was
|
| + // available (clients are encouraged to do this in advance, but meanwhile
|
| + // something else could've been written). By marking the icons initially
|
| + // expired (out-of-date), they will be refetched when we visit the original
|
| + // page any time in the future.
|
| + favicon_service->SetExpiredFaviconsIfNoneKnown(
|
| + page_url, GURL(icon_url), favicon_base::IconType::TOUCH_ICON, image);
|
| + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
|
| + base::Bind(callback, 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) {
|
| + background_task_runner_(background_task_runner),
|
| + image_fetcher_(std::move(image_fetcher)) {
|
| 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);
|
| @@ -201,4 +255,30 @@ base::CancelableTaskTracker::TaskId
|
| tracker);
|
| }
|
|
|
| +void LargeIconService::
|
| + GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
|
| + const GURL& page_url,
|
| + int min_source_size_in_pixel,
|
| + const base::Callback<void(bool success)>& callback) {
|
| + DCHECK_LE(0, min_source_size_in_pixel);
|
| +
|
| + const GURL icon_url =
|
| + GetIconUrlForGoogleServerV2(page_url, min_source_size_in_pixel);
|
| +
|
| + // Do not download if there is a previous cache miss recorded for |icon_url|.
|
| + if (!image_fetcher_ ||
|
| + favicon_service_->WasUnableToDownloadFavicon(icon_url)) {
|
| + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
|
| + base::Bind(callback, false));
|
| + return;
|
| + }
|
| +
|
| + image_fetcher_->SetDataUseServiceName(
|
| + data_use_measurement::DataUseUserData::LARGE_ICON_SERVICE);
|
| + image_fetcher_->StartOrQueueNetworkRequest(
|
| + icon_url.spec(), icon_url,
|
| + base::Bind(&OnFetchIconFromGoogleServerComplete, favicon_service_,
|
| + page_url, callback));
|
| +}
|
| +
|
| } // namespace favicon
|
|
|