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

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

Issue 2799273002: Add support to process favicons from Web Manifests (Closed)
Patch Set: Add hacks for demoing (DONOTSUBMIT) Created 3 years, 7 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
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_handler.h" 5 #include "components/favicon/core/favicon_handler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 case FaviconDriverObserver::NON_TOUCH_16_DIP: 213 case FaviconDriverObserver::NON_TOUCH_16_DIP:
214 case FaviconDriverObserver::NON_TOUCH_LARGEST: 214 case FaviconDriverObserver::NON_TOUCH_LARGEST:
215 return favicon_base::FAVICON; 215 return favicon_base::FAVICON;
216 case FaviconDriverObserver::TOUCH_LARGEST: 216 case FaviconDriverObserver::TOUCH_LARGEST:
217 return favicon_base::TOUCH_ICON | favicon_base::TOUCH_PRECOMPOSED_ICON; 217 return favicon_base::TOUCH_ICON | favicon_base::TOUCH_PRECOMPOSED_ICON;
218 } 218 }
219 return 0; 219 return 0;
220 } 220 }
221 221
222 void FaviconHandler::FetchFavicon(const GURL& url) { 222 void FaviconHandler::FetchFavicon(const GURL& url) {
223 cancelable_task_tracker_.TryCancelAll(); 223 cancelable_task_tracker_for_page_url_.TryCancelAll();
224 cancelable_task_tracker_for_candidates_.TryCancelAll();
224 225
225 url_ = url; 226 url_ = url;
226 227
227 initial_history_result_expired_or_incomplete_ = false; 228 initial_history_result_expired_or_incomplete_ = false;
228 redownload_icons_ = false; 229 redownload_icons_ = false;
229 got_favicon_from_history_ = false; 230 got_favicon_from_history_ = false;
230 download_request_.Cancel(); 231 manifest_download_request_.Cancel();
232 image_download_request_.Cancel();
233 manifest_url_.reset();
231 candidates_.clear(); 234 candidates_.clear();
232 notification_icon_url_ = GURL(); 235 notification_icon_url_ = GURL();
233 notification_icon_type_ = favicon_base::INVALID_ICON; 236 notification_icon_type_ = favicon_base::INVALID_ICON;
234 num_download_requests_ = 0; 237 num_download_requests_ = 0;
235 current_candidate_index_ = 0u; 238 current_candidate_index_ = 0u;
236 best_favicon_ = DownloadedFavicon(); 239 best_favicon_ = DownloadedFavicon();
237 240
238 // Request the favicon from the history service. In parallel to this the 241 // Request the favicon from the history service. In parallel to this the
239 // renderer is going to notify us (well WebContents) when the favicon url is 242 // renderer is going to notify us (well WebContents) when the favicon url is
240 // available. 243 // available.
241 service_->GetFaviconForPageURL( 244 service_->GetFaviconForPageURL(
242 url_, icon_types_, preferred_icon_size(), 245 url_, icon_types_, preferred_icon_size(),
243 base::Bind(&FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, 246 base::Bind(&FaviconHandler::OnFaviconDataForInitialURLFromFaviconService,
244 base::Unretained(this)), 247 base::Unretained(this)),
245 &cancelable_task_tracker_); 248 &cancelable_task_tracker_for_page_url_);
246 } 249 }
247 250
248 bool FaviconHandler::UpdateFaviconCandidate( 251 bool FaviconHandler::UpdateFaviconCandidate(
249 const DownloadedFavicon& downloaded_favicon) { 252 const DownloadedFavicon& downloaded_favicon) {
250 if (downloaded_favicon.candidate.score > best_favicon_.candidate.score) 253 if (downloaded_favicon.candidate.score > best_favicon_.candidate.score)
251 best_favicon_ = downloaded_favicon; 254 best_favicon_ = downloaded_favicon;
252 255
253 if (download_largest_icon_) { 256 if (download_largest_icon_) {
254 // The size of the downloaded icon may not match the declared size. It's 257 // The size of the downloaded icon may not match the declared size. It's
255 // important to stop downloading if: 258 // important to stop downloading if:
(...skipping 10 matching lines...) Expand all
266 candidates_[current_candidate_index_ + 1].score <= 269 candidates_[current_candidate_index_ + 1].score <=
267 best_favicon_.candidate.score; 270 best_favicon_.candidate.score;
268 } else { 271 } else {
269 return best_favicon_.candidate.score == 1; 272 return best_favicon_.candidate.score == 1;
270 } 273 }
271 } 274 }
272 275
273 void FaviconHandler::SetFavicon(const GURL& icon_url, 276 void FaviconHandler::SetFavicon(const GURL& icon_url,
274 const gfx::Image& image, 277 const gfx::Image& image,
275 favicon_base::IconType icon_type) { 278 favicon_base::IconType icon_type) {
279 LOG(INFO) << "MIKEL FaviconHandler::SetFavicon() type " << icon_type << " url "
280 << icon_url;
276 if (ShouldSaveFavicon()) 281 if (ShouldSaveFavicon())
277 service_->SetFavicons(url_, icon_url, icon_type, image); 282 service_->SetFavicons(url_, icon_url, icon_type, image);
278 283
279 NotifyFaviconUpdated(icon_url, icon_type, image); 284 NotifyFaviconUpdated(icon_url, icon_type, image);
280 } 285 }
281 286
282 void FaviconHandler::NotifyFaviconUpdated( 287 void FaviconHandler::NotifyFaviconUpdated(
283 const std::vector<favicon_base::FaviconRawBitmapResult>& 288 const std::vector<favicon_base::FaviconRawBitmapResult>&
284 favicon_bitmap_results) { 289 favicon_bitmap_results) {
285 if (favicon_bitmap_results.empty())
286 return;
287
288 gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs( 290 gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs(
289 favicon_bitmap_results, 291 favicon_bitmap_results,
290 favicon_base::GetFaviconScales(), 292 favicon_base::GetFaviconScales(),
291 preferred_icon_size()); 293 preferred_icon_size());
292 // The history service sends back results for a single icon URL and icon 294 // The history service sends back results for a single icon URL and icon
293 // type, so it does not matter which result we get |icon_url| and |icon_type| 295 // type, so it does not matter which result we get |icon_url| and |icon_type|
294 // from. 296 // from.
295 const GURL icon_url = favicon_bitmap_results[0].icon_url; 297 const GURL icon_url = favicon_bitmap_results[0].icon_url;
296 favicon_base::IconType icon_type = favicon_bitmap_results[0].icon_type; 298 favicon_base::IconType icon_type = favicon_bitmap_results[0].icon_type;
297 NotifyFaviconUpdated(icon_url, icon_type, resized_image); 299 NotifyFaviconUpdated(icon_url, icon_type, resized_image);
298 } 300 }
299 301
300 void FaviconHandler::NotifyFaviconUpdated(const GURL& icon_url, 302 void FaviconHandler::NotifyFaviconUpdated(const GURL& icon_url,
301 favicon_base::IconType icon_type, 303 favicon_base::IconType icon_type,
302 const gfx::Image& image) { 304 const gfx::Image& image) {
303 if (image.IsEmpty()) 305 if (image.IsEmpty())
304 return; 306 return;
305 307
308 // If a manifest is being processed, it's URL overrides the icon URL.
309 const GURL& notification_icon_url = manifest_url_.value_or(icon_url);
310
306 gfx::Image image_with_adjusted_colorspace = image; 311 gfx::Image image_with_adjusted_colorspace = image;
307 favicon_base::SetFaviconColorSpace(&image_with_adjusted_colorspace); 312 favicon_base::SetFaviconColorSpace(&image_with_adjusted_colorspace);
308 313
309 delegate_->OnFaviconUpdated(url_, handler_type_, icon_url, 314 delegate_->OnFaviconUpdated(url_, handler_type_, notification_icon_url,
310 icon_url != notification_icon_url_, 315 notification_icon_url != notification_icon_url_,
311 image_with_adjusted_colorspace); 316 image_with_adjusted_colorspace);
312 317
313 notification_icon_url_ = icon_url; 318 notification_icon_url_ = notification_icon_url;
314 notification_icon_type_ = icon_type; 319 notification_icon_type_ = icon_type;
315 } 320 }
316 321
317 void FaviconHandler::OnUpdateFaviconURL( 322 void FaviconHandler::OnUpdateCandidates(
318 const GURL& page_url, 323 const GURL& page_url,
319 const std::vector<FaviconURL>& candidates) { 324 const std::vector<FaviconURL>& candidates,
325 const base::Optional<GURL>& manifest_url) {
326 DCHECK_EQ(page_url, url_);
320 if (page_url != url_) 327 if (page_url != url_)
321 return; 328 return;
322 329
330 // |candidates| or |manifest_url| could have been modified via Javascript.
331 if (manifest_url_ && manifest_url_ == manifest_url)
332 return;
333
334 manifest_url_ = manifest_url;
335 non_manifest_original_candidates_ = candidates;
336
337 // Check if the manifest previously returned a 404 (or a 200 but contained no
338 // icons), and ignore the manifest URL if that's the case.
339 if (manifest_url_ && service_->WasUnableToDownloadFavicon(*manifest_url_)) {
340 DVLOG(1) << "Skip failed Manifest: " << *manifest_url_;
341 manifest_url_.reset();
342 }
343
344 if (manifest_url_) {
345 cancelable_task_tracker_for_candidates_.TryCancelAll();
pkotwicz 2017/05/01 04:56:53 - Can this be moved outside of the if() statement.
mastiz 2017/05/04 10:57:53 I don't think this is desirable because OnGotFinal
pkotwicz 2017/05/04 17:28:25 Isn't this because |cancelable_task_tracker_for_ca
mastiz 2017/05/10 10:03:52 I'm not really sure why splitting would be any sim
pkotwicz 2017/05/12 06:13:28 I think that splitting the trackers would fix "Bug
mastiz 2017/05/15 14:06:59 I might have achieved this, PTAL. I've traded sim
pkotwicz 2017/05/16 06:36:35 This change is reasonable. Its a neat solution to
346 // See if there is a cached favicon for the manifest.
347 GetFaviconAndUpdateMappingsUnlessIncognito(
348 /*icon_url=*/*manifest_url_, favicon_base::FAVICON,
349 base::Bind(&FaviconHandler::OnFaviconDataForManifestFromFaviconService,
350 base::Unretained(this)));
351 } else {
352 // If no manifest available, proceed with the regular candidates only.
353 OnGotFinalIconURLCandidates(candidates);
354 }
355 }
356
357 void FaviconHandler::OnFaviconDataForManifestFromFaviconService(
358 const std::vector<favicon_base::FaviconRawBitmapResult>&
359 favicon_bitmap_results) {
360 bool has_valid_result = HasValidResult(favicon_bitmap_results);
361 bool has_expired_or_incomplete_result =
362 !has_valid_result || HasExpiredOrIncompleteResult(preferred_icon_size(),
363 favicon_bitmap_results);
364
365 if (has_valid_result) {
366 // There is a valid favicon. Notify any observers. It is useful to notify
367 // the observers even if the favicon is expired or incomplete (incorrect
368 // size) because temporarily showing the user an expired favicon or
369 // streched favicon is preferable to showing the user the default favicon.
370 NotifyFaviconUpdated(favicon_bitmap_results);
371 }
372
373 if (has_expired_or_incomplete_result) {
374 manifest_download_request_.Reset(base::Bind(
375 &FaviconHandler::OnDidDownloadManifest, base::Unretained(this)));
376 delegate_->DownloadManifest(*manifest_url_,
377 manifest_download_request_.callback());
378 }
379 }
380
381 void FaviconHandler::OnDidDownloadManifest(
382 int status_code,
383 const std::vector<FaviconURL>& candidates) {
384 // Mark manifest download as finished.
385 manifest_download_request_.Cancel();
386
387 if (!candidates.empty()) {
388 OnGotFinalIconURLCandidates(candidates);
389 return;
390 }
391
392 // If either the downloading of the manifest failed, OR the manifest contains
393 // no icons, proceed with the list of icons listed in the HTML.
394 DVLOG(1) << "Could not fetch Manifest icons from " << *manifest_url_
395 << ", falling back to inlined ones, which are "
396 << non_manifest_original_candidates_.size();
397
398 if (status_code == 404 || status_code == 200)
399 service_->UnableToDownloadFavicon(*manifest_url_);
400
401 manifest_url_.reset();
402 OnGotFinalIconURLCandidates(non_manifest_original_candidates_);
403 }
404
405 void FaviconHandler::OnGotFinalIconURLCandidates(
406 const std::vector<FaviconURL>& candidates) {
323 std::vector<FaviconCandidate> sorted_candidates; 407 std::vector<FaviconCandidate> sorted_candidates;
324 const std::vector<int> desired_pixel_sizes = 408 const std::vector<int> desired_pixel_sizes =
325 GetDesiredPixelSizes(handler_type_); 409 GetDesiredPixelSizes(handler_type_);
326 for (const FaviconURL& candidate : candidates) { 410 for (const FaviconURL& candidate : candidates) {
327 if (!candidate.icon_url.is_empty() && (candidate.icon_type & icon_types_)) { 411 if (!candidate.icon_url.is_empty() && (candidate.icon_type & icon_types_)) {
328 sorted_candidates.push_back( 412 sorted_candidates.push_back(
329 FaviconCandidate::FromFaviconURL(candidate, desired_pixel_sizes)); 413 FaviconCandidate::FromFaviconURL(candidate, desired_pixel_sizes));
330 } 414 }
331 } 415 }
332 416
333 std::stable_sort(sorted_candidates.begin(), sorted_candidates.end(), 417 std::stable_sort(sorted_candidates.begin(), sorted_candidates.end(),
334 &FaviconCandidate::CompareScore); 418 &FaviconCandidate::CompareScore);
335 419
336 if (candidates_.size() == sorted_candidates.size() && 420 if (candidates_.size() == sorted_candidates.size() &&
337 std::equal(sorted_candidates.begin(), sorted_candidates.end(), 421 std::equal(sorted_candidates.begin(), sorted_candidates.end(),
338 candidates_.begin())) { 422 candidates_.begin())) {
339 return; 423 return;
340 } 424 }
341 425
342 download_request_.Cancel(); 426 cancelable_task_tracker_for_candidates_.TryCancelAll();
427 image_download_request_.Cancel();
343 candidates_ = std::move(sorted_candidates); 428 candidates_ = std::move(sorted_candidates);
344 num_download_requests_ = 0; 429 num_download_requests_ = 0;
345 current_candidate_index_ = 0u; 430 current_candidate_index_ = 0u;
346 best_favicon_ = DownloadedFavicon(); 431 best_favicon_ = DownloadedFavicon();
347 432
348 // TODO(davemoore) Should clear on empty url. Currently we ignore it. 433 // TODO(davemoore) Should clear on empty url. Currently we ignore it.
349 // This appears to be what FF does as well. 434 // This appears to be what FF does as well.
350 if (current_candidate() && got_favicon_from_history_) 435 if (current_candidate() && got_favicon_from_history_)
351 OnGotInitialHistoryDataAndIconURLCandidates(); 436 OnGotInitialHistoryDataAndIconURLCandidates();
352 } 437 }
(...skipping 26 matching lines...) Expand all
379 } 464 }
380 465
381 void FaviconHandler::OnDidDownloadFavicon( 466 void FaviconHandler::OnDidDownloadFavicon(
382 favicon_base::IconType icon_type, 467 favicon_base::IconType icon_type,
383 int id, 468 int id,
384 int http_status_code, 469 int http_status_code,
385 const GURL& image_url, 470 const GURL& image_url,
386 const std::vector<SkBitmap>& bitmaps, 471 const std::vector<SkBitmap>& bitmaps,
387 const std::vector<gfx::Size>& original_bitmap_sizes) { 472 const std::vector<gfx::Size>& original_bitmap_sizes) {
388 // Mark download as finished. 473 // Mark download as finished.
389 download_request_.Cancel(); 474 image_download_request_.Cancel();
390 475
391 if (bitmaps.empty() && http_status_code == 404) { 476 if (bitmaps.empty() && http_status_code == 404) {
392 DVLOG(1) << "Failed to Download Favicon:" << image_url; 477 DVLOG(1) << "Failed to Download Favicon:" << image_url;
393 RecordDownloadOutcome(DownloadOutcome::FAILED); 478 RecordDownloadOutcome(DownloadOutcome::FAILED);
394 service_->UnableToDownloadFavicon(image_url); 479 service_->UnableToDownloadFavicon(image_url);
395 } 480 }
396 481
397 bool request_next_icon = true; 482 bool request_next_icon = true;
398 if (!bitmaps.empty()) { 483 if (!bitmaps.empty()) {
399 RecordDownloadOutcome(DownloadOutcome::SUCCEEDED); 484 RecordDownloadOutcome(DownloadOutcome::SUCCEEDED);
(...skipping 29 matching lines...) Expand all
429 if (request_next_icon && current_candidate_index_ + 1 < candidates_.size()) { 514 if (request_next_icon && current_candidate_index_ + 1 < candidates_.size()) {
430 // Process the next candidate. 515 // Process the next candidate.
431 ++current_candidate_index_; 516 ++current_candidate_index_;
432 DownloadCurrentCandidateOrAskFaviconService(); 517 DownloadCurrentCandidateOrAskFaviconService();
433 } else { 518 } else {
434 // OnDidDownloadFavicon() can only be called after requesting a download, so 519 // OnDidDownloadFavicon() can only be called after requesting a download, so
435 // |num_download_requests_| can never be 0. 520 // |num_download_requests_| can never be 0.
436 RecordDownloadAttemptsForHandlerType(handler_type_, num_download_requests_); 521 RecordDownloadAttemptsForHandlerType(handler_type_, num_download_requests_);
437 // We have either found the ideal candidate or run out of candidates. 522 // We have either found the ideal candidate or run out of candidates.
438 if (best_favicon_.candidate.icon_type != favicon_base::INVALID_ICON) { 523 if (best_favicon_.candidate.icon_type != favicon_base::INVALID_ICON) {
439 // No more icons to request, set the favicon from the candidate. 524 // No more icons to request, set the favicon from the candidate. Note that
440 SetFavicon(best_favicon_.candidate.icon_url, best_favicon_.image, 525 // manifest URLs override icon URLs if available.
441 best_favicon_.candidate.icon_type); 526 SetFavicon(manifest_url_.value_or(best_favicon_.candidate.icon_url),
527 best_favicon_.image, best_favicon_.candidate.icon_type);
442 } 528 }
443 // Clear download related state. 529 // Clear download related state.
444 current_candidate_index_ = candidates_.size(); 530 current_candidate_index_ = candidates_.size();
445 num_download_requests_ = 0; 531 num_download_requests_ = 0;
446 best_favicon_ = DownloadedFavicon(); 532 best_favicon_ = DownloadedFavicon();
447 } 533 }
448 } 534 }
449 535
450 const std::vector<GURL> FaviconHandler::GetIconURLs() const { 536 const std::vector<GURL> FaviconHandler::GetIconURLs() const {
451 std::vector<GURL> icon_urls; 537 std::vector<GURL> icon_urls;
452 for (const FaviconCandidate& candidate : candidates_) 538 for (const FaviconCandidate& candidate : candidates_)
453 icon_urls.push_back(candidate.icon_url); 539 icon_urls.push_back(candidate.icon_url);
454 return icon_urls; 540 return icon_urls;
455 } 541 }
456 542
457 bool FaviconHandler::HasPendingTasksForTest() { 543 bool FaviconHandler::HasPendingTasksForTest() {
458 return !download_request_.IsCancelled() || 544 return !manifest_download_request_.IsCancelled() ||
459 cancelable_task_tracker_.HasTrackedTasks(); 545 !image_download_request_.IsCancelled() ||
546 cancelable_task_tracker_for_page_url_.HasTrackedTasks() ||
547 cancelable_task_tracker_for_candidates_.HasTrackedTasks();
460 } 548 }
461 549
462 bool FaviconHandler::ShouldSaveFavicon() { 550 bool FaviconHandler::ShouldSaveFavicon() {
463 if (!delegate_->IsOffTheRecord()) 551 if (!delegate_->IsOffTheRecord())
464 return true; 552 return true;
465 553
466 // Always save favicon if the page is bookmarked. 554 // Always save favicon if the page is bookmarked.
467 return delegate_->IsBookmarked(url_); 555 return delegate_->IsBookmarked(url_);
468 } 556 }
469 557
470 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( 558 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService(
471 const std::vector<favicon_base::FaviconRawBitmapResult>& 559 const std::vector<favicon_base::FaviconRawBitmapResult>&
472 favicon_bitmap_results) { 560 favicon_bitmap_results) {
473 got_favicon_from_history_ = true; 561 got_favicon_from_history_ = true;
474 bool has_valid_result = HasValidResult(favicon_bitmap_results); 562 bool has_valid_result = HasValidResult(favicon_bitmap_results);
475 initial_history_result_expired_or_incomplete_ = 563 initial_history_result_expired_or_incomplete_ =
476 !has_valid_result || 564 !has_valid_result ||
477 HasExpiredOrIncompleteResult(preferred_icon_size(), 565 HasExpiredOrIncompleteResult(preferred_icon_size(),
478 favicon_bitmap_results); 566 favicon_bitmap_results);
479 redownload_icons_ = initial_history_result_expired_or_incomplete_ && 567 redownload_icons_ = initial_history_result_expired_or_incomplete_ &&
480 !favicon_bitmap_results.empty(); 568 !favicon_bitmap_results.empty();
481 569
482 if (has_valid_result && (!current_candidate() || 570 if (has_valid_result) {
483 DoUrlsAndIconsMatch(current_candidate()->icon_url, 571 if (!current_candidate() ||
484 current_candidate()->icon_type, 572 DoUrlsAndIconsMatch(current_candidate()->icon_url,
485 favicon_bitmap_results))) { 573 current_candidate()->icon_type,
486 // The db knows the favicon (although it may be out of date) and the entry 574 favicon_bitmap_results) ||
487 // doesn't have an icon. Set the favicon now, and if the favicon turns out 575 (manifest_url_ &&
488 // to be expired (or the wrong url) we'll fetch later on. This way the 576 DoUrlsAndIconsMatch(*manifest_url_, favicon_base::FAVICON,
489 // user doesn't see a flash of the default favicon. 577 favicon_bitmap_results))) {
490 NotifyFaviconUpdated(favicon_bitmap_results); 578 // The db knows the favicon (although it may be out of date) and the entry
579 // doesn't have an icon. Set the favicon now, and if the favicon turns out
580 // to be expired (or the wrong url) we'll fetch later on. This way the
581 // user doesn't see a flash of the default favicon.
582 NotifyFaviconUpdated(favicon_bitmap_results);
583 }
491 } 584 }
492 585
493 if (current_candidate()) 586 if (current_candidate())
494 OnGotInitialHistoryDataAndIconURLCandidates(); 587 OnGotInitialHistoryDataAndIconURLCandidates();
495 } 588 }
496 589
497 void FaviconHandler::DownloadCurrentCandidateOrAskFaviconService() { 590 void FaviconHandler::DownloadCurrentCandidateOrAskFaviconService() {
498 GURL icon_url = current_candidate()->icon_url; 591 const GURL icon_url = current_candidate()->icon_url;
499 favicon_base::IconType icon_type = current_candidate()->icon_type; 592 const favicon_base::IconType icon_type = current_candidate()->icon_type;
500 593 // If the icons listed in a manifest are being processed, skip the cache
501 if (redownload_icons_) { 594 // lookup for |icon_url| since the manifest's URL is used for caching anyway,
595 // and this lookup has happened earlier.
596 if (redownload_icons_ || manifest_url_) {
502 // We have the mapping, but the favicon is out of date. Download it now. 597 // We have the mapping, but the favicon is out of date. Download it now.
503 ScheduleDownload(icon_url, icon_type); 598 ScheduleFaviconDownload(icon_url, icon_type);
504 } else { 599 } else {
505 // We don't know the favicon, but we may have previously downloaded the 600 GetFaviconAndUpdateMappingsUnlessIncognito(
506 // favicon for another page that shares the same favicon. Ask for the 601 icon_url, icon_type,
507 // favicon given the favicon URL. 602 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)));
508 if (delegate_->IsOffTheRecord()) {
509 service_->GetFavicon(
510 icon_url, icon_type, preferred_icon_size(),
511 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)),
512 &cancelable_task_tracker_);
513 } else {
514 // Ask the history service for the icon. This does two things:
515 // 1. Attempts to fetch the favicon data from the database.
516 // 2. If the favicon exists in the database, this updates the database to
517 // include the mapping between the page url and the favicon url.
518 // This is asynchronous. The history service will call back when done.
519 // TODO(pkotwicz): pass in all of |image_urls_| to
520 // UpdateFaviconMappingsAndFetch().
521 service_->UpdateFaviconMappingsAndFetch(
522 url_, {icon_url}, icon_type, preferred_icon_size(),
523 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)),
524 &cancelable_task_tracker_);
525 }
526 } 603 }
527 } 604 }
528 605
606 void FaviconHandler::GetFaviconAndUpdateMappingsUnlessIncognito(
607 const GURL& icon_url,
608 favicon_base::IconType icon_type,
609 const favicon_base::FaviconResultsCallback& callback) {
610 // We don't know the favicon, but we may have previously downloaded the
611 // favicon for another page that shares the same favicon. Ask for the
612 // favicon given the favicon URL.
613 if (delegate_->IsOffTheRecord()) {
614 service_->GetFavicon(icon_url, icon_type, preferred_icon_size(), callback,
615 &cancelable_task_tracker_for_candidates_);
616 } else {
617 // Ask the history service for the icon. This does two things:
618 // 1. Attempts to fetch the favicon data from the database.
619 // 2. If the favicon exists in the database, this updates the database to
620 // include the mapping between the page url and the favicon url.
621 // This is asynchronous. The history service will call back when done.
622 // TODO(pkotwicz): pass in all of |image_urls_| to
623 // UpdateFaviconMappingsAndFetch().
624 service_->UpdateFaviconMappingsAndFetch(
625 url_, {icon_url}, icon_type, preferred_icon_size(), callback,
626 &cancelable_task_tracker_for_candidates_);
627 }
628 }
629
529 void FaviconHandler::OnFaviconData(const std::vector< 630 void FaviconHandler::OnFaviconData(const std::vector<
530 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { 631 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) {
531 bool has_results = !favicon_bitmap_results.empty(); 632 bool has_results = !favicon_bitmap_results.empty();
532 bool has_valid_result = HasValidResult(favicon_bitmap_results); 633 bool has_valid_result = HasValidResult(favicon_bitmap_results);
533 bool has_expired_or_incomplete_result = 634 bool has_expired_or_incomplete_result =
534 !has_valid_result || HasExpiredOrIncompleteResult(preferred_icon_size(), 635 !has_valid_result || HasExpiredOrIncompleteResult(preferred_icon_size(),
535 favicon_bitmap_results); 636 favicon_bitmap_results);
536 637
537 if (has_valid_result) { 638 if (has_valid_result) {
538 // There is a valid favicon. Notify any observers. It is useful to notify 639 // There is a valid favicon. Notify any observers. It is useful to notify
539 // the observers even if the favicon is expired or incomplete (incorrect 640 // the observers even if the favicon is expired or incomplete (incorrect
540 // size) because temporarily showing the user an expired favicon or 641 // size) because temporarily showing the user an expired favicon or
541 // streched favicon is preferable to showing the user the default favicon. 642 // streched favicon is preferable to showing the user the default favicon.
542 NotifyFaviconUpdated(favicon_bitmap_results); 643 NotifyFaviconUpdated(favicon_bitmap_results);
543 } 644 }
544 645
545 if (!current_candidate() || 646 if (!current_candidate() ||
546 (has_results && !DoUrlsAndIconsMatch(current_candidate()->icon_url, 647 (has_results && !DoUrlsAndIconsMatch(current_candidate()->icon_url,
547 current_candidate()->icon_type, 648 current_candidate()->icon_type,
548 favicon_bitmap_results))) { 649 favicon_bitmap_results))) {
549 // The icon URLs have been updated since the favicon data was requested. 650 // The icon URLs have been updated since the favicon data was requested.
550 return; 651 // TODO(mastiz) / DONOTSUBMIT: Remove all this 'if' block.
652 NOTREACHED();
pkotwicz 2017/05/01 04:56:53 Can you move the removal of this if() statement an
mastiz 2017/05/04 10:57:53 Yes, will do, together with a few changes in tests
mastiz 2017/05/10 10:03:52 Done.
551 } 653 }
552 654
553 if (has_expired_or_incomplete_result) { 655 if (has_expired_or_incomplete_result) {
554 ScheduleDownload(current_candidate()->icon_url, 656 ScheduleFaviconDownload(current_candidate()->icon_url,
555 current_candidate()->icon_type); 657 current_candidate()->icon_type);
556 } else if (num_download_requests_ > 0) { 658 } else if (num_download_requests_ > 0) {
557 RecordDownloadAttemptsForHandlerType(handler_type_, num_download_requests_); 659 RecordDownloadAttemptsForHandlerType(handler_type_, num_download_requests_);
558 } 660 }
559 } 661 }
560 662
561 void FaviconHandler::ScheduleDownload(const GURL& image_url, 663 void FaviconHandler::ScheduleFaviconDownload(const GURL& image_url,
562 favicon_base::IconType icon_type) { 664 favicon_base::IconType icon_type) {
563 DCHECK(image_url.is_valid()); 665 DCHECK(image_url.is_valid());
564 // Note that CancelableCallback starts cancelled. 666 // Note that CancelableCallback starts cancelled.
565 DCHECK(download_request_.IsCancelled()) << "More than one ongoing download"; 667 DCHECK(image_download_request_.IsCancelled())
668 << "More than one ongoing download";
566 if (service_->WasUnableToDownloadFavicon(image_url)) { 669 if (service_->WasUnableToDownloadFavicon(image_url)) {
567 DVLOG(1) << "Skip Failed FavIcon: " << image_url; 670 DVLOG(1) << "Skip Failed FavIcon: " << image_url;
568 RecordDownloadOutcome(DownloadOutcome::SKIPPED); 671 RecordDownloadOutcome(DownloadOutcome::SKIPPED);
569 OnDidDownloadFavicon(icon_type, 0, 0, image_url, std::vector<SkBitmap>(), 672 OnDidDownloadFavicon(icon_type, 0, 0, image_url, std::vector<SkBitmap>(),
570 std::vector<gfx::Size>()); 673 std::vector<gfx::Size>());
571 return; 674 return;
572 } 675 }
573 ++num_download_requests_; 676 ++num_download_requests_;
574 download_request_.Reset(base::Bind(&FaviconHandler::OnDidDownloadFavicon, 677 image_download_request_.Reset(
575 base::Unretained(this), icon_type)); 678 base::Bind(&FaviconHandler::OnDidDownloadFavicon, base::Unretained(this),
679 icon_type));
576 // A max bitmap size is specified to avoid receiving huge bitmaps in 680 // A max bitmap size is specified to avoid receiving huge bitmaps in
577 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() 681 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload()
578 // for more details about the max bitmap size. 682 // for more details about the max bitmap size.
579 const int download_id = 683 const int download_id =
580 delegate_->DownloadImage(image_url, GetMaximalIconSize(handler_type_), 684 delegate_->DownloadImage(image_url, GetMaximalIconSize(handler_type_),
581 download_request_.callback()); 685 image_download_request_.callback());
582 DCHECK_NE(download_id, 0); 686 DCHECK_NE(download_id, 0);
583 } 687 }
584 688
585 } // namespace favicon 689 } // namespace favicon
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698