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

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: Requiring minimum_size 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
pkotwicz 2016/12/19 00:03:28 Perhaps GetClosestGoogleFaviconServerSupportedSize
jkrcal 2016/12/19 17:07:19 Done.
37 int GetGoogleFaviconServiceSupportedSize(int arbitrary_size) {
38 // Take the smallest size larger than arbitrary_size.
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
pkotwicz 2016/12/19 00:03:28 How about: GetGoogleFaviconServerURLForPageURL()
jkrcal 2016/12/19 17:07:19 Done.
48 GURL GetGoogleFaviconServiceURL(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::GetRawFaviconForPageURLDownloadFromGoogleServerIfNeeded(
pkotwicz 2016/12/19 00:03:28 How about Get1xFaviconForPageURLDownloadFromGoogle
pkotwicz 2016/12/19 00:03:28 We should add a TODO to switch FaviconHelper#ensur
jkrcal 2016/12/19 17:07:19 Done.
235 const GURL& page_url,
236 int minimum_size_in_pixel,
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 "GetRawFaviconForPageURLDownloadFromGoogleServerIfNeeded");
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) {
416 TRACE_EVENT0(
417 "browser",
418 "FaviconService::DownloadFromGoogleServerFaviconImageForPageURL");
pkotwicz 2016/12/19 00:03:28 Shouldn't the second argument be "FaviconService::
jkrcal 2016/12/19 17:07:19 Sure, thanks!
419
420 // Ensure we do not get an icon upscaled from a smaller png than
421 // |minimum_size_in_pixel|.
422 int max_size_in_pixel = 0;
423 for (const auto& bitmap : favicon_bitmap_results) {
pkotwicz 2016/12/19 00:03:28 Can you make |max_size_in_pixel| a boolean and ear
jkrcal 2016/12/19 17:07:19 Done.
424 max_size_in_pixel =
425 std::max(max_size_in_pixel, std::max(bitmap.pixel_size_in_db.width(),
426 bitmap.pixel_size_in_db.height()));
427 }
428
429 // If there are some cached bitmaps but none is large enough, we cannot return
430 // any of them as the result and we also do not want to overwrite them by an
431 // icon from the Google server. Thus, return an empty result.
432 if (max_size_in_pixel > 0 && max_size_in_pixel < minimum_size_in_pixel) {
433 base::ThreadTaskRunnerHandle::Get()->PostTask(
pkotwicz 2016/12/19 00:03:28 What's the reason for posting a task? It looks lik
jkrcal 2016/12/19 17:07:19 Ah, sure, thanks!
434 FROM_HERE, base::Bind(callback, favicon_base::FaviconImageResult()));
435 return;
436 }
437
438 gfx::Image image;
439 image = favicon_base::SelectFaviconFramesFromPNGs(
440 favicon_bitmap_results,
pkotwicz 2016/12/19 00:03:28 You should set the desired scale to be 1.0f and no
jkrcal 2016/12/19 17:07:19 Done.
441 {static_cast<float>(desired_size_in_pixel) / gfx::kFaviconSize},
442 gfx::kFaviconSize);
443
444 if (!image.IsEmpty()) {
445 // If a large enough cached bitmap is successfully rescaled, serve it!
446 favicon_base::FaviconImageResult image_result;
447 image_result.image = image;
448 favicon_base::SetFaviconColorSpace(&image_result.image);
449 image_result.icon_url = favicon_bitmap_results[0].icon_url;
450 callback.Run(image_result);
451 return;
452 }
453
454 // No good enough favicon in the cache. Download it from the server.
455
456 if (!image_fetcher_.get()) {
pkotwicz 2016/12/19 00:03:28 You don't need to post a task
jkrcal 2016/12/19 17:07:19 Done.
457 // No fetcher available (e.g. in unittests), return an empty result.
458 base::ThreadTaskRunnerHandle::Get()->PostTask(
459 FROM_HERE, base::Bind(callback, favicon_base::FaviconImageResult()));
460 return;
461 }
462
463 // TODO(jkrcal): When we use the other server backend, require
464 // |minimum_size_in_pixel|.
465 int supported_size =
466 GetGoogleFaviconServiceSupportedSize(desired_size_in_pixel);
467 GURL image_url = GetGoogleFaviconServiceURL(page_url, client_id,
468 supported_size);
469
470 image_fetcher_->SetDataUseServiceName(data_use_service_name);
471 image_fetcher_->StartOrQueueNetworkRequest(
472 image_url.spec(), image_url,
473 base::Bind(&FaviconService::
474 StoreFaviconFromGoogleServiceAndRunFaviconImageCallback,
475 base::Unretained(this), callback, page_url,
476 desired_size_in_pixel));
477 }
478
479 void FaviconService::StoreFaviconFromGoogleServiceAndRunFaviconImageCallback(
pkotwicz 2016/12/19 00:03:28 How about: StoreFaviconFromGoogleServerAndRunFavic
jkrcal 2016/12/19 17:07:19 Done.
480 const favicon_base::FaviconImageCallback& callback,
481 const GURL& page_url,
482 int desired_size_in_pixel,
483 const std::string& icon_url,
484 const gfx::Image& image) {
485 if (image.IsEmpty())
486 callback.Run(favicon_base::FaviconImageResult());
487
488 // Resize the icon to the desired size.
pkotwicz 2016/12/19 00:03:28 Nuke this comment. What ResizeBitmapByDownsampling
jkrcal 2016/12/19 17:07:19 Done.
489 SkBitmap icon = image.AsBitmap();
490 SkBitmap icon_resized = favicon_base::ResizeBitmapByDownsamplingIfPossible(
491 {icon}, desired_size_in_pixel);
492
493 favicon_base::FaviconImageResult image_result;
494 image_result.icon_url = GURL(icon_url);
495 image_result.image = gfx::Image::CreateFrom1xBitmap(icon_resized);
496 favicon_base::SetFaviconColorSpace(&image_result.image);
497 // Store the favicon in the cache.
pkotwicz 2016/12/19 00:03:28 Nuke this comment. What the function does should b
jkrcal 2016/12/19 17:07:19 Done.
498 SetFavicons(page_url, image_result.icon_url,
499 favicon_base::IconType::FAVICON, image_result.image);
500 // Mark them as out-of-date so that they are refetched when we visit the
pkotwicz 2016/12/19 00:03:28 Nit: "them" -> "the icons"
501 // original page any time in the future.
502 SetFaviconOutOfDateForPage(page_url);
503
504 callback.Run(image_result);
505 }
506
351 } // namespace favicon 507 } // namespace favicon
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698