Chromium Code Reviews| OLD | NEW |
|---|---|
| 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> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 14 #include "base/feature_list.h" | |
| 14 #include "base/memory/ref_counted_memory.h" | 15 #include "base/memory/ref_counted_memory.h" |
| 15 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
| 16 #include "build/build_config.h" | 17 #include "build/build_config.h" |
| 17 #include "components/favicon/core/favicon_service.h" | 18 #include "components/favicon/core/favicon_service.h" |
| 18 #include "components/favicon_base/favicon_util.h" | 19 #include "components/favicon_base/favicon_util.h" |
| 19 #include "components/favicon_base/select_favicon_frames.h" | 20 #include "components/favicon_base/select_favicon_frames.h" |
| 20 #include "skia/ext/image_operations.h" | 21 #include "skia/ext/image_operations.h" |
| 21 #include "ui/gfx/codec/png_codec.h" | 22 #include "ui/gfx/codec/png_codec.h" |
| 22 #include "ui/gfx/image/image_skia.h" | 23 #include "ui/gfx/image/image_skia.h" |
| 23 #include "ui/gfx/image/image_util.h" | 24 #include "ui/gfx/image/image_util.h" |
| 24 | 25 |
| 25 namespace favicon { | 26 namespace favicon { |
| 27 | |
| 28 const base::Feature kFaviconsFromWebManifest{"FaviconsFromWebManifest", | |
| 29 base::FEATURE_DISABLED_BY_DEFAULT}; | |
| 30 | |
| 26 namespace { | 31 namespace { |
| 27 | 32 |
| 28 const int kNonTouchLargestIconSize = 192; | 33 const int kNonTouchLargestIconSize = 192; |
| 29 | 34 |
| 30 // Size (along each axis) of a touch icon. This currently corresponds to | 35 // Size (along each axis) of a touch icon. This currently corresponds to |
| 31 // the apple touch icon for iPad. | 36 // the apple touch icon for iPad. |
| 32 const int kTouchIconSize = 144; | 37 const int kTouchIconSize = 144; |
| 33 | 38 |
| 34 // Returns true if all of the icon URLs and icon types in |bitmap_results| are | 39 // Returns true if all of the icon URLs and icon types in |bitmap_results| are |
| 35 // identical and if they match |icon_url| and |icon_type|. Returns false if | 40 // identical and if they match |icon_url| and |icon_type|. Returns false if |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 | 226 |
| 222 void FaviconHandler::FetchFavicon(const GURL& url) { | 227 void FaviconHandler::FetchFavicon(const GURL& url) { |
| 223 cancelable_task_tracker_for_page_url_.TryCancelAll(); | 228 cancelable_task_tracker_for_page_url_.TryCancelAll(); |
| 224 cancelable_task_tracker_for_candidates_.TryCancelAll(); | 229 cancelable_task_tracker_for_candidates_.TryCancelAll(); |
| 225 | 230 |
| 226 url_ = url; | 231 url_ = url; |
| 227 | 232 |
| 228 initial_history_result_expired_or_incomplete_ = false; | 233 initial_history_result_expired_or_incomplete_ = false; |
| 229 redownload_icons_ = false; | 234 redownload_icons_ = false; |
| 230 got_favicon_from_history_ = false; | 235 got_favicon_from_history_ = false; |
| 236 manifest_download_request_.Cancel(); | |
| 231 image_download_request_.Cancel(); | 237 image_download_request_.Cancel(); |
| 238 manifest_url_.reset(); | |
| 232 candidates_.clear(); | 239 candidates_.clear(); |
| 233 notification_icon_url_ = GURL(); | 240 notification_icon_url_ = GURL(); |
| 234 notification_icon_type_ = favicon_base::INVALID_ICON; | 241 notification_icon_type_ = favicon_base::INVALID_ICON; |
| 235 num_image_download_requests_ = 0; | 242 num_image_download_requests_ = 0; |
| 236 current_candidate_index_ = 0u; | 243 current_candidate_index_ = 0u; |
| 237 best_favicon_ = DownloadedFavicon(); | 244 best_favicon_ = DownloadedFavicon(); |
| 238 | 245 |
| 239 // Request the favicon from the history service. In parallel to this the | 246 // Request the favicon from the history service. In parallel to this the |
| 240 // renderer is going to notify us (well WebContents) when the favicon url is | 247 // renderer is going to notify us (well WebContents) when the favicon url is |
| 241 // available. | 248 // available. |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 309 delegate_->OnFaviconUpdated(url_, handler_type_, icon_url, | 316 delegate_->OnFaviconUpdated(url_, handler_type_, icon_url, |
| 310 icon_url != notification_icon_url_, | 317 icon_url != notification_icon_url_, |
| 311 image_with_adjusted_colorspace); | 318 image_with_adjusted_colorspace); |
| 312 | 319 |
| 313 notification_icon_url_ = icon_url; | 320 notification_icon_url_ = icon_url; |
| 314 notification_icon_type_ = icon_type; | 321 notification_icon_type_ = icon_type; |
| 315 } | 322 } |
| 316 | 323 |
| 317 void FaviconHandler::OnUpdateCandidates( | 324 void FaviconHandler::OnUpdateCandidates( |
| 318 const GURL& page_url, | 325 const GURL& page_url, |
| 319 const std::vector<FaviconURL>& candidates) { | 326 const std::vector<FaviconURL>& candidates, |
| 327 const base::Optional<GURL>& manifest_url) { | |
|
pkotwicz
2017/05/12 06:13:29
I found two bugs :(
Scenario for Bug #1
1) OnUpda
mastiz
2017/05/12 13:31:33
I will work on this, I think you're right bugs exi
mastiz
2017/05/15 14:07:00
I added the two corresponding tests which now pass
| |
| 328 DCHECK_EQ(page_url, url_); | |
| 320 if (page_url != url_) | 329 if (page_url != url_) |
| 321 return; | 330 return; |
| 322 | 331 |
| 332 if (base::FeatureList::IsEnabled(kFaviconsFromWebManifest)) { | |
| 333 // |candidates| or |manifest_url| could have been modified via Javascript. | |
|
pkotwicz
2017/05/12 06:13:29
Nit: You can move the if() statement on line 334 o
mastiz
2017/05/12 13:31:33
Done.
| |
| 334 if (manifest_url_ && manifest_url_ == manifest_url) | |
| 335 return; | |
| 336 | |
| 337 manifest_url_ = manifest_url; | |
| 338 } | |
| 339 | |
| 340 non_manifest_original_candidates_ = candidates; | |
| 341 | |
| 342 // Check if the manifest was previously blacklisted (e.g. returned a 404) and | |
| 343 // ignore the manifest URL if that's the case. | |
| 344 if (manifest_url_ && service_->WasUnableToDownloadFavicon(*manifest_url_)) { | |
| 345 DVLOG(1) << "Skip failed Manifest: " << *manifest_url_; | |
| 346 manifest_url_.reset(); | |
| 347 } | |
| 348 | |
| 349 if (manifest_url_) { | |
| 350 cancelable_task_tracker_for_candidates_.TryCancelAll(); | |
|
pkotwicz
2017/05/12 06:13:29
For the sake of sanity, should we cancel |manifest
mastiz
2017/05/12 13:31:33
Done.
| |
| 351 // See if there is a cached favicon for the manifest. | |
| 352 GetFaviconAndUpdateMappingsUnlessIncognito( | |
| 353 /*icon_url=*/*manifest_url_, favicon_base::FAVICON, | |
| 354 base::Bind(&FaviconHandler::OnFaviconDataForManifestFromFaviconService, | |
|
pkotwicz
2017/05/12 07:20:26
The following scenario is buggy:
1) User is using
pkotwicz
2017/05/12 15:37:42
I think that this bug affects https://www.twitter.
mastiz
2017/05/15 14:07:00
Added UnknownManifestWithoutIconsAndRegularIconInH
pkotwicz
2017/05/16 06:36:35
Yes I would prefer that. That works well with my p
mastiz
2017/05/16 11:05:22
I have some trouble following this discussion, mig
mastiz
2017/05/16 17:53:45
As discussed offline: the original bug is not an a
| |
| 355 base::Unretained(this))); | |
| 356 } else { | |
| 357 // If no manifest available, proceed with the regular candidates only. | |
| 358 OnGotFinalIconURLCandidates(candidates); | |
| 359 } | |
| 360 } | |
| 361 | |
| 362 void FaviconHandler::OnFaviconDataForManifestFromFaviconService( | |
| 363 const std::vector<favicon_base::FaviconRawBitmapResult>& | |
| 364 favicon_bitmap_results) { | |
| 365 bool has_valid_result = HasValidResult(favicon_bitmap_results); | |
| 366 bool has_expired_or_incomplete_result = | |
| 367 !has_valid_result || HasExpiredOrIncompleteResult(preferred_icon_size(), | |
| 368 favicon_bitmap_results); | |
| 369 | |
| 370 if (has_valid_result) { | |
| 371 // There is a valid favicon. Notify any observers. It is useful to notify | |
| 372 // the observers even if the favicon is expired or incomplete (incorrect | |
| 373 // size) because temporarily showing the user an expired favicon or | |
| 374 // streched favicon is preferable to showing the user the default favicon. | |
| 375 NotifyFaviconUpdated(favicon_bitmap_results); | |
| 376 } | |
| 377 | |
| 378 if (has_expired_or_incomplete_result) { | |
| 379 manifest_download_request_.Reset(base::Bind( | |
| 380 &FaviconHandler::OnDidDownloadManifest, base::Unretained(this))); | |
| 381 delegate_->DownloadManifest(*manifest_url_, | |
| 382 manifest_download_request_.callback()); | |
| 383 } | |
| 384 } | |
| 385 | |
| 386 void FaviconHandler::OnDidDownloadManifest( | |
| 387 const std::vector<FaviconURL>& candidates) { | |
| 388 // Mark manifest download as finished. | |
| 389 manifest_download_request_.Cancel(); | |
| 390 | |
| 391 if (!candidates.empty()) { | |
| 392 OnGotFinalIconURLCandidates(candidates); | |
| 393 return; | |
| 394 } | |
| 395 | |
| 396 // If either the downloading of the manifest failed, OR the manifest contains | |
| 397 // no icons, proceed with the list of icons listed in the HTML. | |
| 398 DVLOG(1) << "Could not fetch Manifest icons from " << *manifest_url_ | |
| 399 << ", falling back to inlined ones, which are " | |
| 400 << non_manifest_original_candidates_.size(); | |
| 401 | |
| 402 manifest_url_.reset(); | |
| 403 OnGotFinalIconURLCandidates(non_manifest_original_candidates_); | |
| 404 } | |
| 405 | |
| 406 void FaviconHandler::OnGotFinalIconURLCandidates( | |
| 407 const std::vector<FaviconURL>& candidates) { | |
| 323 std::vector<FaviconCandidate> sorted_candidates; | 408 std::vector<FaviconCandidate> sorted_candidates; |
| 324 const std::vector<int> desired_pixel_sizes = | 409 const std::vector<int> desired_pixel_sizes = |
| 325 GetDesiredPixelSizes(handler_type_); | 410 GetDesiredPixelSizes(handler_type_); |
| 326 for (const FaviconURL& candidate : candidates) { | 411 for (const FaviconURL& candidate : candidates) { |
| 327 if (!candidate.icon_url.is_empty() && (candidate.icon_type & icon_types_)) { | 412 if (!candidate.icon_url.is_empty() && (candidate.icon_type & icon_types_)) { |
| 328 sorted_candidates.push_back( | 413 sorted_candidates.push_back( |
| 329 FaviconCandidate::FromFaviconURL(candidate, desired_pixel_sizes)); | 414 FaviconCandidate::FromFaviconURL(candidate, desired_pixel_sizes)); |
| 330 } | 415 } |
| 331 } | 416 } |
| 332 | 417 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 431 // Process the next candidate. | 516 // Process the next candidate. |
| 432 ++current_candidate_index_; | 517 ++current_candidate_index_; |
| 433 DownloadCurrentCandidateOrAskFaviconService(); | 518 DownloadCurrentCandidateOrAskFaviconService(); |
| 434 } else { | 519 } else { |
| 435 // OnDidDownloadFavicon() can only be called after requesting a download, so | 520 // OnDidDownloadFavicon() can only be called after requesting a download, so |
| 436 // |num_image_download_requests_| can never be 0. | 521 // |num_image_download_requests_| can never be 0. |
| 437 RecordDownloadAttemptsForHandlerType(handler_type_, | 522 RecordDownloadAttemptsForHandlerType(handler_type_, |
| 438 num_image_download_requests_); | 523 num_image_download_requests_); |
| 439 // We have either found the ideal candidate or run out of candidates. | 524 // We have either found the ideal candidate or run out of candidates. |
| 440 if (best_favicon_.candidate.icon_type != favicon_base::INVALID_ICON) { | 525 if (best_favicon_.candidate.icon_type != favicon_base::INVALID_ICON) { |
| 441 // No more icons to request, set the favicon from the candidate. | 526 // No more icons to request, set the favicon from the candidate. Note that |
| 442 SetFavicon(best_favicon_.candidate.icon_url, best_favicon_.image, | 527 // manifest URLs override icon URLs if available. |
|
pkotwicz
2017/05/12 06:13:29
Nit: "Note that manifest URLs override icon URLs i
mastiz
2017/05/12 13:31:33
Done.
| |
| 443 best_favicon_.candidate.icon_type); | 528 SetFavicon(manifest_url_.value_or(best_favicon_.candidate.icon_url), |
| 529 best_favicon_.image, best_favicon_.candidate.icon_type); | |
| 444 } | 530 } |
| 445 // Clear download related state. | 531 // Clear download related state. |
| 446 current_candidate_index_ = candidates_.size(); | 532 current_candidate_index_ = candidates_.size(); |
| 447 num_image_download_requests_ = 0; | 533 num_image_download_requests_ = 0; |
| 448 best_favicon_ = DownloadedFavicon(); | 534 best_favicon_ = DownloadedFavicon(); |
| 449 } | 535 } |
| 450 } | 536 } |
| 451 | 537 |
| 452 const std::vector<GURL> FaviconHandler::GetIconURLs() const { | 538 const std::vector<GURL> FaviconHandler::GetIconURLs() const { |
| 453 std::vector<GURL> icon_urls; | 539 std::vector<GURL> icon_urls; |
| 454 for (const FaviconCandidate& candidate : candidates_) | 540 for (const FaviconCandidate& candidate : candidates_) |
| 455 icon_urls.push_back(candidate.icon_url); | 541 icon_urls.push_back(candidate.icon_url); |
| 456 return icon_urls; | 542 return icon_urls; |
| 457 } | 543 } |
| 458 | 544 |
| 459 bool FaviconHandler::HasPendingTasksForTest() { | 545 bool FaviconHandler::HasPendingTasksForTest() { |
| 460 return !image_download_request_.IsCancelled() || | 546 return !image_download_request_.IsCancelled() || |
| 547 !manifest_download_request_.IsCancelled() || | |
| 461 cancelable_task_tracker_for_page_url_.HasTrackedTasks() || | 548 cancelable_task_tracker_for_page_url_.HasTrackedTasks() || |
| 462 cancelable_task_tracker_for_candidates_.HasTrackedTasks(); | 549 cancelable_task_tracker_for_candidates_.HasTrackedTasks(); |
| 463 } | 550 } |
| 464 | 551 |
| 465 bool FaviconHandler::ShouldSaveFavicon() { | 552 bool FaviconHandler::ShouldSaveFavicon() { |
| 466 if (!delegate_->IsOffTheRecord()) | 553 if (!delegate_->IsOffTheRecord()) |
| 467 return true; | 554 return true; |
| 468 | 555 |
| 469 // Always save favicon if the page is bookmarked. | 556 // Always save favicon if the page is bookmarked. |
| 470 return delegate_->IsBookmarked(url_); | 557 return delegate_->IsBookmarked(url_); |
| 471 } | 558 } |
| 472 | 559 |
| 473 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( | 560 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( |
| 474 const std::vector<favicon_base::FaviconRawBitmapResult>& | 561 const std::vector<favicon_base::FaviconRawBitmapResult>& |
| 475 favicon_bitmap_results) { | 562 favicon_bitmap_results) { |
| 476 got_favicon_from_history_ = true; | 563 got_favicon_from_history_ = true; |
| 477 bool has_valid_result = HasValidResult(favicon_bitmap_results); | 564 bool has_valid_result = HasValidResult(favicon_bitmap_results); |
| 478 initial_history_result_expired_or_incomplete_ = | 565 initial_history_result_expired_or_incomplete_ = |
| 479 !has_valid_result || | 566 !has_valid_result || |
| 480 HasExpiredOrIncompleteResult(preferred_icon_size(), | 567 HasExpiredOrIncompleteResult(preferred_icon_size(), |
| 481 favicon_bitmap_results); | 568 favicon_bitmap_results); |
| 482 redownload_icons_ = initial_history_result_expired_or_incomplete_ && | 569 redownload_icons_ = initial_history_result_expired_or_incomplete_ && |
| 483 !favicon_bitmap_results.empty(); | 570 !favicon_bitmap_results.empty(); |
| 484 | 571 |
| 485 if (has_valid_result && (!current_candidate() || | 572 if (has_valid_result) { |
|
pkotwicz
2017/05/12 06:13:29
Optional: In a separate CL you can remove the if()
| |
| 486 DoUrlsAndIconsMatch(current_candidate()->icon_url, | 573 if (!current_candidate() || |
| 487 current_candidate()->icon_type, | 574 DoUrlsAndIconsMatch(current_candidate()->icon_url, |
| 488 favicon_bitmap_results))) { | 575 current_candidate()->icon_type, |
| 489 // The db knows the favicon (although it may be out of date) and the entry | 576 favicon_bitmap_results) || |
| 490 // doesn't have an icon. Set the favicon now, and if the favicon turns out | 577 (manifest_url_ && |
| 491 // to be expired (or the wrong url) we'll fetch later on. This way the | 578 DoUrlsAndIconsMatch(*manifest_url_, favicon_base::FAVICON, |
| 492 // user doesn't see a flash of the default favicon. | 579 favicon_bitmap_results))) { |
| 493 NotifyFaviconUpdated(favicon_bitmap_results); | 580 // The db knows the favicon (although it may be out of date) and the entry |
| 581 // doesn't have an icon. Set the favicon now, and if the favicon turns out | |
| 582 // to be expired (or the wrong url) we'll fetch later on. This way the | |
| 583 // user doesn't see a flash of the default favicon. | |
| 584 NotifyFaviconUpdated(favicon_bitmap_results); | |
| 585 } | |
| 494 } | 586 } |
| 495 | 587 |
| 496 if (current_candidate()) | 588 if (current_candidate()) |
| 497 OnGotInitialHistoryDataAndIconURLCandidates(); | 589 OnGotInitialHistoryDataAndIconURLCandidates(); |
| 498 } | 590 } |
| 499 | 591 |
| 500 void FaviconHandler::DownloadCurrentCandidateOrAskFaviconService() { | 592 void FaviconHandler::DownloadCurrentCandidateOrAskFaviconService() { |
| 501 GURL icon_url = current_candidate()->icon_url; | 593 const GURL icon_url = current_candidate()->icon_url; |
| 502 favicon_base::IconType icon_type = current_candidate()->icon_type; | 594 const favicon_base::IconType icon_type = current_candidate()->icon_type; |
| 503 | 595 // If the icons listed in a manifest are being processed, skip the cache |
| 504 if (redownload_icons_) { | 596 // lookup for |icon_url| since the manifest's URL is used for caching anyway, |
| 597 // and this lookup has happened earlier. | |
|
pkotwicz
2017/05/12 06:13:29
How about: "since the manifest's URL is using for
mastiz
2017/05/12 13:31:33
Done.
| |
| 598 if (redownload_icons_ || manifest_url_) { | |
| 505 // We have the mapping, but the favicon is out of date. Download it now. | 599 // We have the mapping, but the favicon is out of date. Download it now. |
| 506 ScheduleImageDownload(icon_url, icon_type); | 600 ScheduleImageDownload(icon_url, icon_type); |
| 507 } else { | 601 } else { |
| 508 // We don't know the favicon, but we may have previously downloaded the | 602 GetFaviconAndUpdateMappingsUnlessIncognito( |
| 509 // favicon for another page that shares the same favicon. Ask for the | 603 icon_url, icon_type, |
| 510 // favicon given the favicon URL. | 604 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this))); |
| 511 if (delegate_->IsOffTheRecord()) { | |
| 512 service_->GetFavicon( | |
| 513 icon_url, icon_type, preferred_icon_size(), | |
| 514 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), | |
| 515 &cancelable_task_tracker_for_candidates_); | |
| 516 } else { | |
| 517 // Ask the history service for the icon. This does two things: | |
| 518 // 1. Attempts to fetch the favicon data from the database. | |
| 519 // 2. If the favicon exists in the database, this updates the database to | |
| 520 // include the mapping between the page url and the favicon url. | |
| 521 // This is asynchronous. The history service will call back when done. | |
| 522 service_->UpdateFaviconMappingsAndFetch( | |
| 523 url_, icon_url, icon_type, preferred_icon_size(), | |
| 524 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), | |
| 525 &cancelable_task_tracker_for_candidates_); | |
| 526 } | |
| 527 } | 605 } |
| 528 } | 606 } |
| 529 | 607 |
| 608 void FaviconHandler::GetFaviconAndUpdateMappingsUnlessIncognito( | |
| 609 const GURL& icon_url, | |
| 610 favicon_base::IconType icon_type, | |
| 611 const favicon_base::FaviconResultsCallback& callback) { | |
| 612 // We don't know the favicon, but we may have previously downloaded the | |
| 613 // favicon for another page that shares the same favicon. Ask for the | |
| 614 // favicon given the favicon URL. | |
| 615 if (delegate_->IsOffTheRecord()) { | |
| 616 service_->GetFavicon(icon_url, icon_type, preferred_icon_size(), callback, | |
| 617 &cancelable_task_tracker_for_candidates_); | |
| 618 } else { | |
| 619 // Ask the history service for the icon. This does two things: | |
| 620 // 1. Attempts to fetch the favicon data from the database. | |
| 621 // 2. If the favicon exists in the database, this updates the database to | |
| 622 // include the mapping between the page url and the favicon url. | |
| 623 // This is asynchronous. The history service will call back when done. | |
| 624 service_->UpdateFaviconMappingsAndFetch( | |
| 625 url_, icon_url, icon_type, preferred_icon_size(), callback, | |
| 626 &cancelable_task_tracker_for_candidates_); | |
| 627 } | |
| 628 } | |
| 629 | |
| 530 void FaviconHandler::OnFaviconData(const std::vector< | 630 void FaviconHandler::OnFaviconData(const std::vector< |
| 531 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { | 631 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { |
| 532 bool has_valid_result = HasValidResult(favicon_bitmap_results); | 632 bool has_valid_result = HasValidResult(favicon_bitmap_results); |
| 533 bool has_expired_or_incomplete_result = | 633 bool has_expired_or_incomplete_result = |
| 534 !has_valid_result || HasExpiredOrIncompleteResult(preferred_icon_size(), | 634 !has_valid_result || HasExpiredOrIncompleteResult(preferred_icon_size(), |
| 535 favicon_bitmap_results); | 635 favicon_bitmap_results); |
| 536 | 636 |
| 537 if (has_valid_result) { | 637 if (has_valid_result) { |
| 538 // There is a valid favicon. Notify any observers. It is useful to notify | 638 // 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 | 639 // the observers even if the favicon is expired or incomplete (incorrect |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 571 // A max bitmap size is specified to avoid receiving huge bitmaps in | 671 // A max bitmap size is specified to avoid receiving huge bitmaps in |
| 572 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() | 672 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() |
| 573 // for more details about the max bitmap size. | 673 // for more details about the max bitmap size. |
| 574 const int download_id = | 674 const int download_id = |
| 575 delegate_->DownloadImage(image_url, GetMaximalIconSize(handler_type_), | 675 delegate_->DownloadImage(image_url, GetMaximalIconSize(handler_type_), |
| 576 image_download_request_.callback()); | 676 image_download_request_.callback()); |
| 577 DCHECK_NE(download_id, 0); | 677 DCHECK_NE(download_id, 0); |
| 578 } | 678 } |
| 579 | 679 |
| 580 } // namespace favicon | 680 } // namespace favicon |
| OLD | NEW |