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

Side by Side Diff: components/favicon/core/large_icon_service.cc

Issue 2685173002: Extend LargeIconService to fetch missing favicons from a Google server (Closed)
Patch Set: Minor cleanup Created 3 years, 9 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 unified diff | Download patch
« no previous file with comments | « components/favicon/core/large_icon_service.h ('k') | components/favicon_base/favicon_types.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/large_icon_service.h" 5 #include "components/favicon/core/large_icon_service.h"
6 6
7 #include <algorithm>
7 #include <memory> 8 #include <memory>
8 9
9 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/feature_list.h"
10 #include "base/location.h" 12 #include "base/location.h"
11 #include "base/logging.h" 13 #include "base/logging.h"
12 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h"
13 #include "base/memory/ref_counted.h" 16 #include "base/memory/ref_counted.h"
17 #include "base/strings/stringprintf.h"
14 #include "base/task_runner.h" 18 #include "base/task_runner.h"
15 #include "base/threading/sequenced_worker_pool.h" 19 #include "base/threading/sequenced_worker_pool.h"
20 #include "base/threading/thread_task_runner_handle.h"
21 #include "components/data_use_measurement/core/data_use_user_data.h"
16 #include "components/favicon/core/favicon_service.h" 22 #include "components/favicon/core/favicon_service.h"
23 #include "components/favicon/core/features.h"
17 #include "components/favicon_base/fallback_icon_style.h" 24 #include "components/favicon_base/fallback_icon_style.h"
18 #include "components/favicon_base/favicon_types.h" 25 #include "components/favicon_base/favicon_types.h"
26 #include "components/favicon_base/favicon_util.h"
27 #include "components/image_fetcher/image_fetcher.h"
19 #include "skia/ext/image_operations.h" 28 #include "skia/ext/image_operations.h"
20 #include "ui/gfx/codec/png_codec.h" 29 #include "ui/gfx/codec/png_codec.h"
21 #include "ui/gfx/geometry/size.h" 30 #include "ui/gfx/geometry/size.h"
22 31
32 using image_fetcher::ImageFetcher;
33
34 namespace favicon {
35
23 namespace { 36 namespace {
24 37
25 // Processes the bitmap data returned from the FaviconService as part of a 38 const char kGoogleServer1RequestFormat[] =
26 // LargeIconService request. 39 "https://s2.googleusercontent.com/s2/"
27 class LargeIconWorker : public base::RefCountedThreadSafe<LargeIconWorker> { 40 "favicons?domain=%s&src=chrome_large_icons&sz=%d&alt=404";
41 const int kGoogleServer1DesiredSizeInPixel = 32;
42
43 // Type APPLE_TOUCH includes TOUCH_ICONs as well as FAVICONs as fallback.
44 const char kGoogleServer2RequestFormat[] =
45 "https://t0.gstatic.com/"
46 "faviconV2?url=%s&type=APPLE_TOUCH&size=%d&min_size=%d&max_size=%d";
47 const int kGoogleServer2MinSizeInPixel = 48;
48 const int kGoogleServer2MaxSizeInPixel = 256;
49 const int kGoogleServer2DesiredSizeInPixel = 192;
50
51 // Base class for processing one large icon query.
52 class LargeIconWorkerBase {
28 public: 53 public:
29 LargeIconWorker(int min_source_size_in_pixel, 54 LargeIconWorkerBase(const GURL& page_url,
30 int desired_size_in_pixel, 55 int min_source_size_in_pixel,
31 favicon_base::LargeIconCallback callback, 56 int desired_size_in_pixel,
32 scoped_refptr<base::TaskRunner> background_task_runner, 57 favicon_base::LargeIconCallback callback,
33 base::CancelableTaskTracker* tracker); 58 scoped_refptr<base::TaskRunner> background_task_runner,
59 base::CancelableTaskTracker* tracker,
60 FaviconService* favicon_service);
61
62 virtual base::CancelableTaskTracker::TaskId Start() = 0;
63
64 protected:
65 ~LargeIconWorkerBase() = default;
66 void PrepareLargeIconResult(
67 const favicon_base::FaviconRawBitmapResult* bitmap_result,
68 bool create_bitmap);
34 69
35 // Must run on the owner (UI) thread in production. 70 // Must run on the owner (UI) thread in production.
36 // Intermediate callback for GetLargeIconOrFallbackStyle(). Invokes 71 void RunCallback();
37 // ProcessIconOnBackgroundThread() so we do not perform complex image 72
38 // operations on the UI thread. 73 GURL page_url_;
39 void OnIconLookupComplete(
40 const favicon_base::FaviconRawBitmapResult& bitmap_result);
41
42 private:
43 friend class base::RefCountedThreadSafe<LargeIconWorker>;
44
45 ~LargeIconWorker();
46
47 // Must run on a background thread in production.
48 // Tries to resize |bitmap_result_| and pass the output to |callback_|. If
49 // that does not work, computes the icon fallback style and uses it to
50 // invoke |callback_|. This must be run on a background thread because image
51 // resizing and dominant color extraction can be expensive.
52 void ProcessIconOnBackgroundThread();
53
54 // Must run on a background thread in production.
55 // If |bitmap_result_| is square and large enough (>= |min_source_in_pixel_|),
56 // resizes it to |desired_size_in_pixel_| (but if |desired_size_in_pixel_| is
57 // 0 then don't resize). If successful, stores the resulting bitmap data
58 // into |resized_bitmap_result| and returns true.
59 bool ResizeLargeIconOnBackgroundThreadIfValid(
60 favicon_base::FaviconRawBitmapResult* resized_bitmap_result);
61
62 // Must run on the owner (UI) thread in production.
63 // Invoked when ProcessIconOnBackgroundThread() is done.
64 void OnIconProcessingComplete();
65 74
66 int min_source_size_in_pixel_; 75 int min_source_size_in_pixel_;
67 int desired_size_in_pixel_; 76 int desired_size_in_pixel_;
68 favicon_base::LargeIconCallback callback_; 77 favicon_base::LargeIconCallback callback_;
69 scoped_refptr<base::TaskRunner> background_task_runner_; 78 scoped_refptr<base::TaskRunner> background_task_runner_;
70 base::CancelableTaskTracker* tracker_; 79 base::CancelableTaskTracker* tracker_;
71 favicon_base::FaviconRawBitmapResult bitmap_result_; 80 FaviconService* favicon_service_;
81
82 // Data constructed on the background thread.
72 std::unique_ptr<favicon_base::LargeIconResult> result_; 83 std::unique_ptr<favicon_base::LargeIconResult> result_;
73 84
74 DISALLOW_COPY_AND_ASSIGN(LargeIconWorker); 85 private:
86 DISALLOW_COPY_AND_ASSIGN(LargeIconWorkerBase);
75 }; 87 };
76 88
77 LargeIconWorker::LargeIconWorker( 89 LargeIconWorkerBase::LargeIconWorkerBase(
pkotwicz 2017/02/28 01:51:56 I am not much of a fan of LargeIconWorkerBase. We
jkrcal 2017/03/01 09:32:06 Done.
90 const GURL& page_url,
78 int min_source_size_in_pixel, 91 int min_source_size_in_pixel,
79 int desired_size_in_pixel, 92 int desired_size_in_pixel,
80 favicon_base::LargeIconCallback callback, 93 favicon_base::LargeIconCallback callback,
81 scoped_refptr<base::TaskRunner> background_task_runner, 94 scoped_refptr<base::TaskRunner> background_task_runner,
82 base::CancelableTaskTracker* tracker) 95 base::CancelableTaskTracker* tracker,
83 : min_source_size_in_pixel_(min_source_size_in_pixel), 96 FaviconService* favicon_service)
97 : page_url_(page_url),
98 min_source_size_in_pixel_(std::min(min_source_size_in_pixel_, 32)),
84 desired_size_in_pixel_(desired_size_in_pixel), 99 desired_size_in_pixel_(desired_size_in_pixel),
85 callback_(callback), 100 callback_(callback),
86 background_task_runner_(background_task_runner), 101 background_task_runner_(background_task_runner),
87 tracker_(tracker) { 102 tracker_(tracker),
88 } 103 favicon_service_(favicon_service) {}
89 104
90 LargeIconWorker::~LargeIconWorker() { 105 void LargeIconWorkerBase::PrepareLargeIconResult(
91 } 106 const favicon_base::FaviconRawBitmapResult* bitmap_result,
92 107 bool create_bitmap) {
93 void LargeIconWorker::OnIconLookupComplete( 108 if (create_bitmap && bitmap_result && bitmap_result->is_valid()) {
109 result_ = base::MakeUnique<favicon_base::LargeIconResult>(*bitmap_result);
110 } else {
111 // Compute fallback icon style.
112 std::unique_ptr<favicon_base::FallbackIconStyle> fallback_icon_style =
113 base::MakeUnique<favicon_base::FallbackIconStyle>();
114 if (bitmap_result && bitmap_result->is_valid()) {
115 favicon_base::SetDominantColorAsBackground(bitmap_result->bitmap_data,
116 fallback_icon_style.get());
117 }
118 result_ = base::MakeUnique<favicon_base::LargeIconResult>(
119 std::move(fallback_icon_style));
120 }
121 }
122
123 void LargeIconWorkerBase::RunCallback() {
124 callback_.Run(*result_);
125 }
126
127 // Processes the bitmap data returned from a Google favicon server as part of a
128 // LargeIconService request.
129 class LargeIconCacheWorker
130 : public LargeIconWorkerBase,
131 public base::RefCountedThreadSafe<LargeIconCacheWorker> {
132 public:
133 LargeIconCacheWorker(const GURL& page_url,
134 int min_source_size_in_pixel,
135 int desired_size_in_pixel,
136 favicon_base::LargeIconCallback callback,
137 scoped_refptr<base::TaskRunner> background_task_runner,
138 base::CancelableTaskTracker* tracker,
139 FaviconService* favicon_service);
140
141 base::CancelableTaskTracker::TaskId Start() override;
142
143 private:
144 friend class base::RefCountedThreadSafe<LargeIconCacheWorker>;
145 virtual ~LargeIconCacheWorker();
146
147 // Must run on the owner (UI) thread in production.
148 // Intermediate callback for GetLargeIconOrFallbackStyle(). Invokes
149 // ProcessIconOnBackgroundThread() so we do not perform complex image
150 // operations on the UI thread.
151 void OnCachedIconLookupComplete(
152 const favicon_base::FaviconRawBitmapResult& bitmap_result);
153
154 // Must run on a background thread in production.
155 // Tries to resize |bitmap_result| and pass the output to |callback_|. If
156 // that does not work, computes the icon fallback style and uses it to
157 // invoke |callback_|. This must be run on a background thread because image
158 // resizing and dominant color extraction can be expensive.
159 void ProcessCachedIconOnBackgroundThread(
160 const favicon_base::FaviconRawBitmapResult& bitmap_result);
161
162 // Must run on a background thread in production.
163 // If |bitmap_result| is square and large enough (>= |min_source_in_pixel_|),
164 // resizes it to |desired_size_in_pixel_| (but if |desired_size_in_pixel_| is
165 // 0 then don't resize). If successful, stores the resulting bitmap data
166 // into |bitmap_result| and returns true.
167 bool ResizeCachedIconOnBackgroundThreadIfValid(
168 const favicon_base::FaviconRawBitmapResult& bitmap_result,
169 favicon_base::FaviconRawBitmapResult* resized_bitmap_result);
170
171 DISALLOW_COPY_AND_ASSIGN(LargeIconCacheWorker);
172 };
173
174 LargeIconCacheWorker::LargeIconCacheWorker(
175 const GURL& page_url,
176 int min_source_size_in_pixel,
177 int desired_size_in_pixel,
178 favicon_base::LargeIconCallback callback,
179 scoped_refptr<base::TaskRunner> background_task_runner,
180 base::CancelableTaskTracker* tracker,
181 FaviconService* favicon_service)
182 : LargeIconWorkerBase(page_url,
183 min_source_size_in_pixel,
184 desired_size_in_pixel,
185 callback,
186 background_task_runner,
187 tracker,
188 favicon_service) {}
189
190 LargeIconCacheWorker::~LargeIconCacheWorker() {}
191
192 base::CancelableTaskTracker::TaskId LargeIconCacheWorker::Start() {
193 return favicon_service_->GetRawFaviconForPageURL(
194 page_url_,
195 favicon_base::IconType::FAVICON | favicon_base::IconType::TOUCH_ICON |
196 favicon_base::IconType::TOUCH_PRECOMPOSED_ICON,
197 desired_size_in_pixel_,
198 base::Bind(&LargeIconCacheWorker::OnCachedIconLookupComplete, this),
199 tracker_);
200 }
201
202 void LargeIconCacheWorker::OnCachedIconLookupComplete(
94 const favicon_base::FaviconRawBitmapResult& bitmap_result) { 203 const favicon_base::FaviconRawBitmapResult& bitmap_result) {
95 bitmap_result_ = bitmap_result; 204 // Prepare the data for the callback and run it.
96 tracker_->PostTaskAndReply( 205 tracker_->PostTaskAndReply(
97 background_task_runner_.get(), FROM_HERE, 206 background_task_runner_.get(), FROM_HERE,
98 base::Bind(&LargeIconWorker::ProcessIconOnBackgroundThread, this), 207 base::Bind(&LargeIconCacheWorker::ProcessCachedIconOnBackgroundThread,
99 base::Bind(&LargeIconWorker::OnIconProcessingComplete, this)); 208 this, bitmap_result),
100 } 209 base::Bind(&LargeIconCacheWorker::RunCallback, this));
101 210 }
102 void LargeIconWorker::ProcessIconOnBackgroundThread() { 211
212 void LargeIconCacheWorker::ProcessCachedIconOnBackgroundThread(
213 const favicon_base::FaviconRawBitmapResult& bitmap_result) {
pkotwicz 2017/02/28 01:51:56 Can this function be in the anonymous namespace an
jkrcal 2017/03/01 09:32:06 I would like to keep this function in the class as
103 favicon_base::FaviconRawBitmapResult resized_bitmap_result; 214 favicon_base::FaviconRawBitmapResult resized_bitmap_result;
104 if (ResizeLargeIconOnBackgroundThreadIfValid(&resized_bitmap_result)) { 215 bool create_bitmap = ResizeCachedIconOnBackgroundThreadIfValid(
105 result_.reset( 216 bitmap_result, &resized_bitmap_result);
106 new favicon_base::LargeIconResult(resized_bitmap_result)); 217 PrepareLargeIconResult(&resized_bitmap_result, create_bitmap);
107 } else { 218 }
108 // Failed to resize |bitmap_result_|, so compute fallback icon style. 219
109 std::unique_ptr<favicon_base::FallbackIconStyle> fallback_icon_style( 220 bool LargeIconCacheWorker::ResizeCachedIconOnBackgroundThreadIfValid(
110 new favicon_base::FallbackIconStyle()); 221 const favicon_base::FaviconRawBitmapResult& bitmap_result,
111 if (bitmap_result_.is_valid()) {
112 favicon_base::SetDominantColorAsBackground(
113 bitmap_result_.bitmap_data, fallback_icon_style.get());
114 }
115 result_.reset(
116 new favicon_base::LargeIconResult(fallback_icon_style.release()));
117 }
118 }
119
120 bool LargeIconWorker::ResizeLargeIconOnBackgroundThreadIfValid(
121 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) { 222 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) {
122 // Require bitmap to be valid and square. 223 // Require bitmap to be valid and square.
123 if (!bitmap_result_.is_valid() || 224 if (!bitmap_result.is_valid() ||
124 bitmap_result_.pixel_size.width() != bitmap_result_.pixel_size.height()) 225 bitmap_result.pixel_size.width() != bitmap_result.pixel_size.height())
125 return false; 226 return false;
126 227
127 // Require bitmap to be large enough. It's square, so just check width. 228 // Require bitmap to be large enough. It's square, so just check width.
128 if (bitmap_result_.pixel_size.width() < min_source_size_in_pixel_) 229 if (bitmap_result.pixel_size.width() < min_source_size_in_pixel_)
129 return false; 230 return false;
130 231
131 *resized_bitmap_result = bitmap_result_; 232 *resized_bitmap_result = bitmap_result;
132 233
133 // Special case: Can use |bitmap_result_| as is. 234 // Special case: Can use |bitmap_result| as is.
134 if (desired_size_in_pixel_ == 0 || 235 if (desired_size_in_pixel_ == 0 ||
135 bitmap_result_.pixel_size.width() == desired_size_in_pixel_) 236 bitmap_result.pixel_size.width() == desired_size_in_pixel_)
136 return true; 237 return true;
137 238
138 // Resize bitmap: decode PNG, resize, and re-encode PNG. 239 // Resize bitmap: decode PNG, resize, and re-encode PNG.
139 SkBitmap decoded_bitmap; 240 SkBitmap decoded_bitmap;
140 if (!gfx::PNGCodec::Decode(bitmap_result_.bitmap_data->front(), 241 if (!gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(),
141 bitmap_result_.bitmap_data->size(), &decoded_bitmap)) 242 bitmap_result.bitmap_data->size(),
142 return false; 243 &decoded_bitmap))
143 244 return false;
144 SkBitmap resized_bitmap = skia::ImageOperations::Resize( 245
246 SkBitmap bitmap = skia::ImageOperations::Resize(
145 decoded_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, 247 decoded_bitmap, skia::ImageOperations::RESIZE_LANCZOS3,
146 desired_size_in_pixel_, desired_size_in_pixel_); 248 desired_size_in_pixel_, desired_size_in_pixel_);
147 249
148 std::vector<unsigned char> bitmap_data; 250 std::vector<unsigned char> bitmap_data;
149 if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_bitmap, false, &bitmap_data)) 251 if (!gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bitmap_data))
150 return false; 252 return false;
151 253
152 resized_bitmap_result->pixel_size = 254 resized_bitmap_result->pixel_size =
153 gfx::Size(desired_size_in_pixel_, desired_size_in_pixel_); 255 gfx::Size(desired_size_in_pixel_, desired_size_in_pixel_);
154 resized_bitmap_result->bitmap_data = 256 resized_bitmap_result->bitmap_data =
155 base::RefCountedBytes::TakeVector(&bitmap_data); 257 base::RefCountedBytes::TakeVector(&bitmap_data);
156 return true; 258 return true;
157 } 259 }
158 260
159 void LargeIconWorker::OnIconProcessingComplete() { 261 // Processes the bitmap data returned from the FaviconService as part of a
160 callback_.Run(*result_); 262 // LargeIconService request.
263 class LargeIconGoogleServerWorker
264 : public LargeIconWorkerBase,
265 public base::RefCountedThreadSafe<LargeIconGoogleServerWorker> {
266 public:
267 LargeIconGoogleServerWorker(
268 const GURL& page_url,
269 int min_source_size_in_pixel,
270 int desired_size_in_pixel,
271 favicon_base::LargeIconCallback callback,
272 scoped_refptr<base::TaskRunner> background_task_runner,
273 base::CancelableTaskTracker* tracker,
274 FaviconService* favicon_service,
275 ImageFetcher* image_fetcher);
276
277 base::CancelableTaskTracker::TaskId Start() override;
278
279 private:
280 friend class base::RefCountedThreadSafe<LargeIconGoogleServerWorker>;
281 virtual ~LargeIconGoogleServerWorker();
282
283 void ProcessIconFromGoogleServerOnBackgroundThread(const GURL& icon_url,
284 const gfx::Image& image);
285
286 // Must run on a background thread in production.
287 // If |bitmap_result| is square and large enough (>= |min_source_in_pixel_|),
288 // resizes it to |desired_size_in_pixel_| (but if |desired_size_in_pixel_| is
289 // 0 then don't resize). If successful, stores the resulting bitmap data
290 // into |bitmap_result| and returns true.
291 bool ResizeIconFromGoogleServerOnBackgroundThreadIfValid(
292 const GURL& icon_url,
293 const gfx::Image image,
294 favicon_base::FaviconRawBitmapResult* resized_bitmap_result);
295
296 // Create the GET URL that requests the desired favicon from a Google favicon
297 // server (version 1 / version 2).
298 GURL GetIconUrlForGoogleServer1() const;
299 GURL GetIconUrlForGoogleServer2() const;
300
301 // Fetches an icon for the given |icon_url| and stores it in the favicon DB.
302 void FetchIconFromGoogleServer(const GURL& icon_url);
303 void OnFetchIconFromGoogleServerComplete(const std::string& icon_url,
304 const gfx::Image& image);
305
306 ImageFetcher* image_fetcher_;
307
308 DISALLOW_COPY_AND_ASSIGN(LargeIconGoogleServerWorker);
309 };
310
311 LargeIconGoogleServerWorker::LargeIconGoogleServerWorker(
312 const GURL& page_url,
313 int min_source_size_in_pixel,
314 int desired_size_in_pixel,
315 favicon_base::LargeIconCallback callback,
316 scoped_refptr<base::TaskRunner> background_task_runner,
317 base::CancelableTaskTracker* tracker,
318 FaviconService* favicon_service,
319 ImageFetcher* image_fetcher)
320 : LargeIconWorkerBase(page_url,
321 min_source_size_in_pixel,
322 desired_size_in_pixel,
323 callback,
324 background_task_runner,
325 tracker,
326 favicon_service),
327 image_fetcher_(image_fetcher) {}
328
329 LargeIconGoogleServerWorker::~LargeIconGoogleServerWorker() {}
330
331 base::CancelableTaskTracker::TaskId LargeIconGoogleServerWorker::Start() {
332 GURL server_url;
333 if (base::FeatureList::IsEnabled(kFaviconFetchLargeIconFromGoogleServer2)) {
334 server_url = GetIconUrlForGoogleServer2();
335 } else if (min_source_size_in_pixel_ <= 16 &&
336 base::FeatureList::IsEnabled(
337 kFaviconFetchLargeIconFromGoogleServer1)) {
338 // Server 1 cannot guarantee that the served icon has original size >=16px
339 // as it upscales images to fill in empty spots for missing sizes (32px,
340 // 64px) when indexing.
341 server_url = GetIconUrlForGoogleServer1();
342 }
343
344 return tracker_->PostTask(
345 background_task_runner_.get(), FROM_HERE,
346 base::Bind(&LargeIconGoogleServerWorker::FetchIconFromGoogleServer, this,
347 server_url));
348 }
349
350 GURL LargeIconGoogleServerWorker::GetIconUrlForGoogleServer1() const {
351 return GURL(base::StringPrintf(kGoogleServer1RequestFormat,
352 page_url_.spec().c_str(),
353 kGoogleServer1DesiredSizeInPixel));
354 }
355
356 GURL LargeIconGoogleServerWorker::GetIconUrlForGoogleServer2() const {
357 // TODO(jkrcal): make the desired/min/max sizes depend on the device (its
358 // scale factor, etc).
359 return GURL(base::StringPrintf(
360 kGoogleServer2RequestFormat, page_url_.GetWithEmptyPath().spec().c_str(),
361 kGoogleServer2DesiredSizeInPixel, kGoogleServer2MinSizeInPixel,
362 kGoogleServer2MaxSizeInPixel));
363 }
364
365 void LargeIconGoogleServerWorker::FetchIconFromGoogleServer(
366 const GURL& icon_url) {
367 if (icon_url.is_empty() // Do not fetch if fetching is disabled.
368 || favicon_service_->WasUnableToDownloadFavicon(icon_url)
369 // Do not retry if there is a previous cache miss recorded for |icon_url|.
370 ) {
371 PrepareLargeIconResult(nullptr, /*create_bitmap=*/false);
372 RunCallback();
373 return;
374 }
375
376 image_fetcher_->SetDataUseServiceName(
377 data_use_measurement::DataUseUserData::LARGE_ICON_SERVICE);
378 image_fetcher_->StartOrQueueNetworkRequest(
379 icon_url.spec(), icon_url,
380 base::Bind(
381 &LargeIconGoogleServerWorker::OnFetchIconFromGoogleServerComplete,
382 this));
383 }
384
385 void LargeIconGoogleServerWorker::OnFetchIconFromGoogleServerComplete(
386 const std::string& icon_url,
387 const gfx::Image& image) {
388 if (image.IsEmpty()) {
389 favicon_service_->UnableToDownloadFavicon(GURL(icon_url));
390 PrepareLargeIconResult(nullptr, /*create_bitmap=*/false);
391 RunCallback();
392 return;
393 }
394
395 // TODO(jkrcal): Extract the original icon url from the response headers if
396 // available and use it instead of |icon_url|.
397
398 // TODO(jkrcal): never overwrite favicons. Fix in this CL!
399 favicon_service_->SetFavicons(page_url_, GURL(icon_url),
400 favicon_base::IconType::TOUCH_ICON, image);
401 // Mark the icons as out-of-date so that they are refetched when we visit the
402 // original page any time in the future.
403 favicon_service_->SetFaviconOutOfDateForPage(page_url_);
404
405 tracker_->PostTaskAndReply(
406 background_task_runner_.get(), FROM_HERE,
407 base::Bind(&LargeIconGoogleServerWorker::
408 ProcessIconFromGoogleServerOnBackgroundThread,
409 this, GURL(icon_url), image),
410 base::Bind(&LargeIconGoogleServerWorker::RunCallback, this));
411 }
412
413 void LargeIconGoogleServerWorker::ProcessIconFromGoogleServerOnBackgroundThread(
414 const GURL& icon_url,
415 const gfx::Image& image) {
416 favicon_base::FaviconRawBitmapResult resized_bitmap_result;
417 bool create_bitmap = ResizeIconFromGoogleServerOnBackgroundThreadIfValid(
418 icon_url, image, &resized_bitmap_result);
419 PrepareLargeIconResult(&resized_bitmap_result, create_bitmap);
420 }
421
422 bool LargeIconGoogleServerWorker::
423 ResizeIconFromGoogleServerOnBackgroundThreadIfValid(
424 const GURL& icon_url,
425 const gfx::Image image,
426 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) {
427 // Require bitmap to be valid and square.
428 if (!image.IsEmpty() || image.Width() != image.Height())
429 return false;
430
431 // Require bitmap to be large enough. It's square, so just check width.
432 if (image.Width() < min_source_size_in_pixel_)
433 return false;
434
435 SkBitmap bitmap = image.AsBitmap();
436
437 // Resize if necessary.
438 if (desired_size_in_pixel_ != 0 && image.Width() != desired_size_in_pixel_) {
439 bitmap = skia::ImageOperations::Resize(
440 bitmap, skia::ImageOperations::RESIZE_LANCZOS3, desired_size_in_pixel_,
441 desired_size_in_pixel_);
442 }
443
444 std::vector<unsigned char> bitmap_data;
445 if (!gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bitmap_data))
446 return false;
447
448 resized_bitmap_result->pixel_size =
449 gfx::Size(desired_size_in_pixel_, desired_size_in_pixel_);
450 resized_bitmap_result->bitmap_data =
451 base::RefCountedBytes::TakeVector(&bitmap_data);
452 resized_bitmap_result->expired = true;
453 resized_bitmap_result->icon_url = icon_url;
454 resized_bitmap_result->icon_type = favicon_base::IconType::TOUCH_ICON;
455
456 return true;
161 } 457 }
162 458
163 } // namespace 459 } // namespace
164 460
165 namespace favicon {
166
167 LargeIconService::LargeIconService( 461 LargeIconService::LargeIconService(
168 FaviconService* favicon_service, 462 FaviconService* favicon_service,
169 const scoped_refptr<base::TaskRunner>& background_task_runner) 463 const scoped_refptr<base::TaskRunner>& background_task_runner,
464 std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher)
170 : favicon_service_(favicon_service), 465 : favicon_service_(favicon_service),
171 background_task_runner_(background_task_runner) { 466 background_task_runner_(background_task_runner),
172 large_icon_types_.push_back(favicon_base::IconType::FAVICON); 467 image_fetcher_(std::move(image_fetcher)) {}
173 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON);
174 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON);
175 }
176 468
177 LargeIconService::~LargeIconService() { 469 LargeIconService::~LargeIconService() {
178 } 470 }
179 471
180 base::CancelableTaskTracker::TaskId 472 base::CancelableTaskTracker::TaskId
181 LargeIconService::GetLargeIconOrFallbackStyle( 473 LargeIconService::GetLargeIconOrFallbackStyle(
182 const GURL& page_url, 474 const GURL& page_url,
183 int min_source_size_in_pixel, 475 int min_source_size_in_pixel,
184 int desired_size_in_pixel, 476 int desired_size_in_pixel,
185 const favicon_base::LargeIconCallback& callback, 477 const favicon_base::LargeIconCallback& callback,
186 base::CancelableTaskTracker* tracker) { 478 base::CancelableTaskTracker* tracker) {
187 DCHECK_LE(1, min_source_size_in_pixel); 479 DCHECK_LE(0, min_source_size_in_pixel);
188 DCHECK_LE(0, desired_size_in_pixel); 480 DCHECK_LE(0, desired_size_in_pixel);
189 481
190 scoped_refptr<LargeIconWorker> worker = 482 scoped_refptr<LargeIconCacheWorker> worker = new LargeIconCacheWorker(
191 new LargeIconWorker(min_source_size_in_pixel, desired_size_in_pixel, 483 page_url, min_source_size_in_pixel, desired_size_in_pixel, callback,
192 callback, background_task_runner_, tracker); 484 background_task_runner_, tracker, favicon_service_);
193 485 return worker->Start();
194 // TODO(beaudoin): For now this is just a wrapper around 486 }
195 // GetLargestRawFaviconForPageURL. Add the logic required to select the best 487
196 // possible large icon. Also add logic to fetch-on-demand when the URL of 488 base::CancelableTaskTracker::TaskId
197 // a large icon is known but its bitmap is not available. 489 LargeIconService::GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
198 return favicon_service_->GetLargestRawFaviconForPageURL( 490 const GURL& page_url,
199 page_url, large_icon_types_, min_source_size_in_pixel, 491 int min_source_size_in_pixel,
200 base::Bind(&LargeIconWorker::OnIconLookupComplete, worker), 492 int desired_size_in_pixel,
201 tracker); 493 const favicon_base::LargeIconCallback& callback,
494 base::CancelableTaskTracker* tracker) {
495 DCHECK_LE(0, min_source_size_in_pixel);
496 DCHECK_LE(0, desired_size_in_pixel);
497
498 scoped_refptr<LargeIconGoogleServerWorker> worker =
499 new LargeIconGoogleServerWorker(page_url, min_source_size_in_pixel,
500 desired_size_in_pixel, callback,
501 background_task_runner_, tracker,
502 favicon_service_, image_fetcher_.get());
503 return worker->Start();
202 } 504 }
203 505
204 } // namespace favicon 506 } // namespace favicon
OLDNEW
« no previous file with comments | « components/favicon/core/large_icon_service.h ('k') | components/favicon_base/favicon_types.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698