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

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

Issue 2347173002: Extend FaviconService to support fetching favicons from a Google server (Closed)
Patch Set: Peter's comments #2 Created 3 years, 10 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/favicon_service.cc
diff --git a/components/favicon/core/favicon_service.cc b/components/favicon/core/favicon_service.cc
index 57a29deaf5fe69c7250a85ef799d064bab7ffe7a..9cac40343bb501ec99f5eae4d2264c2498195f15 100644
--- a/components/favicon/core/favicon_service.cc
+++ b/components/favicon/core/favicon_service.cc
@@ -5,17 +5,20 @@
#include "components/favicon/core/favicon_service.h"
#include <stddef.h>
+#include <algorithm>
#include <cmath>
#include <utility>
#include "base/hash.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "components/favicon/core/favicon_client.h"
#include "components/favicon_base/favicon_util.h"
#include "components/favicon_base/select_favicon_frames.h"
#include "components/history/core/browser/history_service.h"
+#include "components/image_fetcher/image_fetcher.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/favicon_size.h"
@@ -25,6 +28,32 @@
namespace favicon {
namespace {
+const char kGoogleFaviconServiceRequestFormat[] =
+ "https://s2.googleusercontent.com/s2/"
+ "favicons?domain=%s&src=%s&sz=%d&alt=404";
+
+const int kGoogleFaviconServiceSupportedSizes[] = {16, 24, 32, 48, 64};
+
+int GetClosestGoogleFaviconServerSupportedSize(int arbitrary_size) {
+ // Take the smallest size larger than |arbitrary_size|.
+ for (int size : kGoogleFaviconServiceSupportedSizes) {
+ if (size >= arbitrary_size)
+ return size;
+ }
+ // Or at least the largest available size.
+ return kGoogleFaviconServiceSupportedSizes
+ [arraysize(kGoogleFaviconServiceSupportedSizes) - 1];
+}
+
+GURL GetGoogleFaviconServerURLForPageURL(GURL page_url,
+ const std::string& client_id,
+ int supported_size) {
+ return GURL(base::StringPrintf(kGoogleFaviconServiceRequestFormat,
+ page_url.spec().c_str(),
+ client_id.c_str(),
+ supported_size));
+}
+
// Helper to run callback with empty results if we cannot get the history
// service.
base::CancelableTaskTracker::TaskId RunWithEmptyResultAsync(
@@ -51,10 +80,13 @@ std::vector<int> GetPixelSizesForFaviconScales(int size_in_dip) {
} // namespace
-FaviconService::FaviconService(std::unique_ptr<FaviconClient> favicon_client,
- history::HistoryService* history_service)
+FaviconService::FaviconService(
+ std::unique_ptr<FaviconClient> favicon_client,
+ history::HistoryService* history_service,
+ std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher)
: favicon_client_(std::move(favicon_client)),
- history_service_(history_service) {}
+ history_service_(history_service),
+ image_fetcher_(std::move(image_fetcher)) {}
FaviconService::~FaviconService() {
}
@@ -199,6 +231,30 @@ base::CancelableTaskTracker::TaskId FaviconService::GetFaviconForPageURL(
}
base::CancelableTaskTracker::TaskId
+FaviconService::Get1xFaviconForPageURLDownloadFromGoogleServerIfMissing(
+ const GURL& page_url,
+ int minimum_size_in_pixel,
+ int desired_size_in_pixel,
+ std::string client_id,
+ data_use_measurement::DataUseUserData::ServiceName data_use_service_name,
+ const favicon_base::FaviconImageCallback& callback,
+ base::CancelableTaskTracker* tracker) {
+ TRACE_EVENT0("browser",
+ "FaviconService::"
+ "Get1xFaviconForPageURLDownloadFromGoogleServerIfMissing");
+ std::vector<int> desired_sizes_in_pixel;
+ desired_sizes_in_pixel.push_back(desired_size_in_pixel);
+ return GetFaviconForPageURLImpl(
+ page_url, favicon_base::IconType::FAVICON, desired_sizes_in_pixel,
+ base::Bind(&FaviconService::
+ RunFaviconImageCallbackOrDownloadFromGoogleFaviconServer,
+ base::Unretained(this), page_url, minimum_size_in_pixel,
+ desired_size_in_pixel, client_id, data_use_service_name,
+ callback),
+ tracker);
+}
+
+base::CancelableTaskTracker::TaskId
FaviconService::UpdateFaviconMappingsAndFetch(
const GURL& page_url,
const std::vector<GURL>& icon_urls,
@@ -348,4 +404,100 @@ void FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults(
ResizeFaviconBitmapResult(favicon_bitmap_results, desired_size_in_pixel));
}
+void FaviconService::RunFaviconImageCallbackOrDownloadFromGoogleFaviconServer(
+ const GURL& page_url,
+ int minimum_size_in_pixel,
+ int desired_size_in_pixel,
+ std::string client_id,
+ data_use_measurement::DataUseUserData::ServiceName data_use_service_name,
+ const favicon_base::FaviconImageCallback& callback,
+ const std::vector<favicon_base::FaviconRawBitmapResult>&
+ favicon_bitmap_results) {
+ TRACE_EVENT0("browser",
+ "FaviconService::"
+ "RunFaviconImageCallbackOrDownloadFromGoogleFaviconServer");
+
+ // Ensure we do not get an icon upscaled from a smaller png than
+ // |minimum_size_in_pixel|.
+ bool large_enough = false;
+ for (const auto& bitmap : favicon_bitmap_results) {
+ if (minimum_size_in_pixel <= std::max(bitmap.pixel_size_in_db.width(),
+ bitmap.pixel_size_in_db.height())) {
+ large_enough = true;
+ break;
jkrcal 2017/02/06 19:01:22 This was obviously wrong :)
+ }
+ }
+
+ // If there are some cached bitmaps but none is large enough, we cannot return
pkotwicz 2017/02/07 04:55:55 Nit: 'is' -> 'are'
+ // any of them as the result and we also do not want to overwrite them by an
+ // icon from the Google server. Thus, return an empty result.
+ if (favicon_bitmap_results.size() > 0 && !large_enough) {
pkotwicz 2017/02/07 04:55:55 Nit: !favicon_bitmap_results.empty()
+ callback.Run(favicon_base::FaviconImageResult());
+ return;
+ }
+
+ gfx::Image image;
+ image = favicon_base::SelectFaviconFramesFromPNGs(
+ favicon_bitmap_results, {1.0f}, desired_size_in_pixel);
+
+ if (!image.IsEmpty()) {
+ // If a large enough cached bitmap is successfully rescaled, serve it!
+ favicon_base::FaviconImageResult image_result;
+ image_result.image = image;
+ favicon_base::SetFaviconColorSpace(&image_result.image);
+ image_result.icon_url = favicon_bitmap_results[0].icon_url;
+ callback.Run(image_result);
+ return;
+ }
+
+ // No good enough favicon in the cache. Download it from the server.
+
+ if (!image_fetcher_.get()) {
+ // No fetcher available (e.g. in unittests), return an empty result.
+ callback.Run(favicon_base::FaviconImageResult());
+ return;
+ }
+
+ // TODO(jkrcal): When we use the other server backend, require
+ // |minimum_size_in_pixel|.
pkotwicz 2017/02/07 04:55:55 I think that it makes sense to enforce |minimum_si
+ int supported_size =
+ GetClosestGoogleFaviconServerSupportedSize(desired_size_in_pixel);
+ GURL image_url = GetGoogleFaviconServerURLForPageURL(page_url, client_id,
+ supported_size);
+
+ image_fetcher_->SetDataUseServiceName(data_use_service_name);
+ image_fetcher_->StartOrQueueNetworkRequest(
+ image_url.spec(), image_url,
+ base::Bind(&FaviconService::
+ StoreFaviconFromGoogleServerAndRunFaviconImageCallback,
+ base::Unretained(this), callback, page_url,
+ desired_size_in_pixel));
+}
+
+void FaviconService::StoreFaviconFromGoogleServerAndRunFaviconImageCallback(
+ const favicon_base::FaviconImageCallback& callback,
+ const GURL& page_url,
+ int desired_size_in_pixel,
+ const std::string& icon_url,
+ const gfx::Image& image) {
+ if (image.IsEmpty())
+ callback.Run(favicon_base::FaviconImageResult());
+
+ SkBitmap icon = image.AsBitmap();
+ SkBitmap icon_resized = favicon_base::ResizeBitmapByDownsamplingIfPossible(
+ {icon}, desired_size_in_pixel);
+
+ favicon_base::FaviconImageResult image_result;
+ image_result.icon_url = GURL(icon_url);
+ image_result.image = gfx::Image::CreateFrom1xBitmap(icon_resized);
+ favicon_base::SetFaviconColorSpace(&image_result.image);
+ SetFavicons(page_url, image_result.icon_url,
+ favicon_base::IconType::FAVICON, image_result.image);
+ // Mark the icons as out-of-date so that they are refetched when we visit the
+ // original page any time in the future.
+ SetFaviconOutOfDateForPage(page_url);
+
+ callback.Run(image_result);
+}
+
} // namespace favicon

Powered by Google App Engine
This is Rietveld 408576698