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

Side by Side 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 Created 4 years 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/favicon/core/favicon_service.h" 5 #include "components/favicon/core/favicon_service.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <algorithm>
8 #include <cmath> 9 #include <cmath>
9 #include <utility> 10 #include <utility>
10 11
11 #include "base/hash.h" 12 #include "base/hash.h"
12 #include "base/single_thread_task_runner.h" 13 #include "base/single_thread_task_runner.h"
14 #include "base/strings/stringprintf.h"
13 #include "base/threading/thread_task_runner_handle.h" 15 #include "base/threading/thread_task_runner_handle.h"
14 #include "base/trace_event/trace_event.h" 16 #include "base/trace_event/trace_event.h"
15 #include "components/favicon/core/favicon_client.h" 17 #include "components/favicon/core/favicon_client.h"
16 #include "components/favicon_base/favicon_util.h" 18 #include "components/favicon_base/favicon_util.h"
17 #include "components/favicon_base/select_favicon_frames.h" 19 #include "components/favicon_base/select_favicon_frames.h"
18 #include "components/history/core/browser/history_service.h" 20 #include "components/history/core/browser/history_service.h"
21 #include "components/image_fetcher/image_fetcher.h"
19 #include "third_party/skia/include/core/SkBitmap.h" 22 #include "third_party/skia/include/core/SkBitmap.h"
20 #include "ui/gfx/codec/png_codec.h" 23 #include "ui/gfx/codec/png_codec.h"
21 #include "ui/gfx/favicon_size.h" 24 #include "ui/gfx/favicon_size.h"
22 #include "ui/gfx/image/image_skia.h" 25 #include "ui/gfx/image/image_skia.h"
23 #include "url/gurl.h" 26 #include "url/gurl.h"
24 27
25 namespace favicon { 28 namespace favicon {
26 namespace { 29 namespace {
27 30
31 const char kGoogleFaviconServiceRequestFormat[] =
32 "https://s2.googleusercontent.com/s2/"
33 "favicons?domain=%s&src=%s&sz=%d&alt=404";
34
35 const int kGoogleFaviconServiceSupportedSizes[] = {16, 24, 32, 48, 64};
36
37 int GetClosestGoogleFaviconServerSupportedSize(int arbitrary_size) {
38 // Take the smallest size larger than arbitrary_size.
pkotwicz 2016/12/20 02:33:01 Nit: arbitrary_size -> |arbitrary_size|
jkrcal 2017/02/06 19:01:22 Done.
39 for (int size : kGoogleFaviconServiceSupportedSizes) {
40 if (size >= arbitrary_size)
41 return size;
42 }
43 // Or at least the largest available size.
44 return kGoogleFaviconServiceSupportedSizes
45 [arraysize(kGoogleFaviconServiceSupportedSizes) - 1];
46 }
47
48 GURL GetGoogleFaviconServerURLForPageURL(GURL page_url,
49 const std::string& client_id,
50 int supported_size) {
51 return GURL(base::StringPrintf(kGoogleFaviconServiceRequestFormat,
52 page_url.spec().c_str(),
53 client_id.c_str(),
54 supported_size));
55 }
56
28 // Helper to run callback with empty results if we cannot get the history 57 // Helper to run callback with empty results if we cannot get the history
29 // service. 58 // service.
30 base::CancelableTaskTracker::TaskId RunWithEmptyResultAsync( 59 base::CancelableTaskTracker::TaskId RunWithEmptyResultAsync(
31 const favicon_base::FaviconResultsCallback& callback, 60 const favicon_base::FaviconResultsCallback& callback,
32 base::CancelableTaskTracker* tracker) { 61 base::CancelableTaskTracker* tracker) {
33 scoped_refptr<base::SingleThreadTaskRunner> thread_runner( 62 scoped_refptr<base::SingleThreadTaskRunner> thread_runner(
34 base::ThreadTaskRunnerHandle::Get()); 63 base::ThreadTaskRunnerHandle::Get());
35 return tracker->PostTask( 64 return tracker->PostTask(
36 thread_runner.get(), FROM_HERE, 65 thread_runner.get(), FROM_HERE,
37 base::Bind(callback, 66 base::Bind(callback,
38 std::vector<favicon_base::FaviconRawBitmapResult>())); 67 std::vector<favicon_base::FaviconRawBitmapResult>()));
39 } 68 }
40 69
41 // Returns a vector of pixel edge sizes from |size_in_dip| and 70 // Returns a vector of pixel edge sizes from |size_in_dip| and
42 // favicon_base::GetFaviconScales(). 71 // favicon_base::GetFaviconScales().
43 std::vector<int> GetPixelSizesForFaviconScales(int size_in_dip) { 72 std::vector<int> GetPixelSizesForFaviconScales(int size_in_dip) {
44 std::vector<float> scales = favicon_base::GetFaviconScales(); 73 std::vector<float> scales = favicon_base::GetFaviconScales();
45 std::vector<int> sizes_in_pixel; 74 std::vector<int> sizes_in_pixel;
46 for (size_t i = 0; i < scales.size(); ++i) { 75 for (size_t i = 0; i < scales.size(); ++i) {
47 sizes_in_pixel.push_back(std::ceil(size_in_dip * scales[i])); 76 sizes_in_pixel.push_back(std::ceil(size_in_dip * scales[i]));
48 } 77 }
49 return sizes_in_pixel; 78 return sizes_in_pixel;
50 } 79 }
51 80
52 } // namespace 81 } // namespace
53 82
54 FaviconService::FaviconService(std::unique_ptr<FaviconClient> favicon_client, 83 FaviconService::FaviconService(
55 history::HistoryService* history_service) 84 std::unique_ptr<FaviconClient> favicon_client,
85 history::HistoryService* history_service,
86 std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher)
56 : favicon_client_(std::move(favicon_client)), 87 : favicon_client_(std::move(favicon_client)),
57 history_service_(history_service) {} 88 history_service_(history_service),
89 image_fetcher_(std::move(image_fetcher)) {}
58 90
59 FaviconService::~FaviconService() { 91 FaviconService::~FaviconService() {
60 } 92 }
61 93
62 // static 94 // static
63 void FaviconService::FaviconResultsCallbackRunner( 95 void FaviconService::FaviconResultsCallbackRunner(
64 const favicon_base::FaviconResultsCallback& callback, 96 const favicon_base::FaviconResultsCallback& callback,
65 const std::vector<favicon_base::FaviconRawBitmapResult>* results) { 97 const std::vector<favicon_base::FaviconRawBitmapResult>* results) {
66 callback.Run(*results); 98 callback.Run(*results);
67 } 99 }
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 TRACE_EVENT0("browser", "FaviconService::GetFaviconForPageURL"); 224 TRACE_EVENT0("browser", "FaviconService::GetFaviconForPageURL");
193 return GetFaviconForPageURLImpl( 225 return GetFaviconForPageURLImpl(
194 page_url, 226 page_url,
195 icon_types, 227 icon_types,
196 GetPixelSizesForFaviconScales(desired_size_in_dip), 228 GetPixelSizesForFaviconScales(desired_size_in_dip),
197 callback, 229 callback,
198 tracker); 230 tracker);
199 } 231 }
200 232
201 base::CancelableTaskTracker::TaskId 233 base::CancelableTaskTracker::TaskId
234 FaviconService::Get1xFaviconForPageURLDownloadFromGoogleServerIfMissing(
235 const GURL& page_url,
236 int minimum_size_in_pixel,
pkotwicz 2016/12/20 02:33:02 Aside: Sorry I did not think about this before. If
jkrcal 2017/02/06 19:01:22 Do you understand it correctly that you suggest th
237 int desired_size_in_pixel,
238 std::string client_id,
239 data_use_measurement::DataUseUserData::ServiceName data_use_service_name,
240 const favicon_base::FaviconImageCallback& callback,
241 base::CancelableTaskTracker* tracker) {
242 TRACE_EVENT0("browser",
243 "FaviconService::"
244 "Get1xFaviconForPageURLDownloadFromGoogleServerIfMissing");
245 std::vector<int> desired_sizes_in_pixel;
246 desired_sizes_in_pixel.push_back(desired_size_in_pixel);
247 return GetFaviconForPageURLImpl(
248 page_url, favicon_base::IconType::FAVICON, desired_sizes_in_pixel,
249 base::Bind(&FaviconService::
250 RunFaviconImageCallbackOrDownloadFromGoogleFaviconServer,
251 base::Unretained(this), page_url, minimum_size_in_pixel,
252 desired_size_in_pixel, client_id, data_use_service_name,
253 callback),
254 tracker);
255 }
256
257 base::CancelableTaskTracker::TaskId
202 FaviconService::UpdateFaviconMappingsAndFetch( 258 FaviconService::UpdateFaviconMappingsAndFetch(
203 const GURL& page_url, 259 const GURL& page_url,
204 const std::vector<GURL>& icon_urls, 260 const std::vector<GURL>& icon_urls,
205 int icon_types, 261 int icon_types,
206 int desired_size_in_dip, 262 int desired_size_in_dip,
207 const favicon_base::FaviconResultsCallback& callback, 263 const favicon_base::FaviconResultsCallback& callback,
208 base::CancelableTaskTracker* tracker) { 264 base::CancelableTaskTracker* tracker) {
209 if (history_service_) { 265 if (history_service_) {
210 return history_service_->UpdateFaviconMappingsAndFetch( 266 return history_service_->UpdateFaviconMappingsAndFetch(
211 page_url, 267 page_url,
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 const favicon_base::FaviconRawBitmapCallback& callback, 397 const favicon_base::FaviconRawBitmapCallback& callback,
342 int desired_size_in_pixel, 398 int desired_size_in_pixel,
343 const std::vector<favicon_base::FaviconRawBitmapResult>& 399 const std::vector<favicon_base::FaviconRawBitmapResult>&
344 favicon_bitmap_results) { 400 favicon_bitmap_results) {
345 TRACE_EVENT0("browser", 401 TRACE_EVENT0("browser",
346 "FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults"); 402 "FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults");
347 callback.Run( 403 callback.Run(
348 ResizeFaviconBitmapResult(favicon_bitmap_results, desired_size_in_pixel)); 404 ResizeFaviconBitmapResult(favicon_bitmap_results, desired_size_in_pixel));
349 } 405 }
350 406
407 void FaviconService::RunFaviconImageCallbackOrDownloadFromGoogleFaviconServer(
408 const GURL& page_url,
409 int minimum_size_in_pixel,
410 int desired_size_in_pixel,
411 std::string client_id,
412 data_use_measurement::DataUseUserData::ServiceName data_use_service_name,
413 const favicon_base::FaviconImageCallback& callback,
414 const std::vector<favicon_base::FaviconRawBitmapResult>&
415 favicon_bitmap_results) {
pkotwicz 2016/12/20 02:33:01 You need to pass CancelableTaskTracker as an argum
jkrcal 2017/02/06 19:01:22 I see the problem. I've spent quite some time thin
pkotwicz 2017/02/07 03:11:44 Solution #1 sounds ok to me. Especially since we l
416 TRACE_EVENT0("browser",
417 "FaviconService::"
418 "RunFaviconImageCallbackOrDownloadFromGoogleFaviconServer");
419
420 // Ensure we do not get an icon upscaled from a smaller png than
421 // |minimum_size_in_pixel|.
422 bool large_enough = false;
423 for (const auto& bitmap : favicon_bitmap_results) {
424 if (minimum_size_in_pixel <= std::max(bitmap.pixel_size_in_db.width(),
425 bitmap.pixel_size_in_db.height())) {
426 large_enough = true;
427 return;
428 }
429 }
430
431 // If there are some cached bitmaps but none is large enough, we cannot return
432 // any of them as the result and we also do not want to overwrite them by an
433 // icon from the Google server. Thus, return an empty result.
434 if (favicon_bitmap_results.size() > 0 && !large_enough) {
435 callback.Run(favicon_base::FaviconImageResult());
436 return;
437 }
438
439 gfx::Image image;
440 image = favicon_base::SelectFaviconFramesFromPNGs(
441 favicon_bitmap_results, {1.0f}, desired_size_in_pixel);
442
443 if (!image.IsEmpty()) {
444 // If a large enough cached bitmap is successfully rescaled, serve it!
445 favicon_base::FaviconImageResult image_result;
446 image_result.image = image;
447 favicon_base::SetFaviconColorSpace(&image_result.image);
448 image_result.icon_url = favicon_bitmap_results[0].icon_url;
449 callback.Run(image_result);
450 return;
451 }
452
453 // No good enough favicon in the cache. Download it from the server.
454
455 if (!image_fetcher_.get()) {
456 // No fetcher available (e.g. in unittests), return an empty result.
457 callback.Run(favicon_base::FaviconImageResult());
458 return;
459 }
460
461 // TODO(jkrcal): When we use the other server backend, require
462 // |minimum_size_in_pixel|.
463 int supported_size =
464 GetClosestGoogleFaviconServerSupportedSize(desired_size_in_pixel);
465 GURL image_url = GetGoogleFaviconServerURLForPageURL(page_url, client_id,
466 supported_size);
467
468 image_fetcher_->SetDataUseServiceName(data_use_service_name);
469 image_fetcher_->StartOrQueueNetworkRequest(
470 image_url.spec(), image_url,
471 base::Bind(&FaviconService::
472 StoreFaviconFromGoogleServerAndRunFaviconImageCallback,
473 base::Unretained(this), callback, page_url,
474 desired_size_in_pixel));
475 }
476
477 void FaviconService::StoreFaviconFromGoogleServerAndRunFaviconImageCallback(
478 const favicon_base::FaviconImageCallback& callback,
479 const GURL& page_url,
480 int desired_size_in_pixel,
481 const std::string& icon_url,
482 const gfx::Image& image) {
483 if (image.IsEmpty())
484 callback.Run(favicon_base::FaviconImageResult());
485
486 SkBitmap icon = image.AsBitmap();
487 SkBitmap icon_resized = favicon_base::ResizeBitmapByDownsamplingIfPossible(
488 {icon}, desired_size_in_pixel);
489
490 favicon_base::FaviconImageResult image_result;
491 image_result.icon_url = GURL(icon_url);
492 image_result.image = gfx::Image::CreateFrom1xBitmap(icon_resized);
493 favicon_base::SetFaviconColorSpace(&image_result.image);
494 SetFavicons(page_url, image_result.icon_url,
495 favicon_base::IconType::FAVICON, image_result.image);
496 // Mark the icons as out-of-date so that they are refetched when we visit the
497 // original page any time in the future.
498 SetFaviconOutOfDateForPage(page_url);
499
500 callback.Run(image_result);
501 }
502
351 } // namespace favicon 503 } // namespace favicon
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698