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 "chrome/browser/favicon/favicon_handler.h" | 5 #include "chrome/browser/favicon/favicon_handler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 return exact_match; | 281 return exact_match; |
282 } | 282 } |
283 | 283 |
284 void FaviconHandler::SetFavicon(const GURL& url, | 284 void FaviconHandler::SetFavicon(const GURL& url, |
285 const GURL& icon_url, | 285 const GURL& icon_url, |
286 const gfx::Image& image, | 286 const gfx::Image& image, |
287 favicon_base::IconType icon_type) { | 287 favicon_base::IconType icon_type) { |
288 if (client_->GetFaviconService() && ShouldSaveFavicon(url)) | 288 if (client_->GetFaviconService() && ShouldSaveFavicon(url)) |
289 SetHistoryFavicons(url, icon_url, icon_type, image); | 289 SetHistoryFavicons(url, icon_url, icon_type, image); |
290 | 290 |
291 if (UrlMatches(url, url_) && icon_type == favicon_base::FAVICON) { | 291 if (!UrlMatches(url, url_) || PageChangedSinceFaviconWasRequested()) |
292 if (!PageChangedSinceFaviconWasRequested()) | 292 return; |
293 SetFaviconOnActivePage(icon_url, image); | 293 |
294 } | 294 NotifyFaviconAvailable( |
| 295 icon_url, |
| 296 image, |
| 297 icon_type == favicon_base::FAVICON && !download_largest_icon_); |
295 } | 298 } |
296 | 299 |
297 void FaviconHandler::SetFaviconOnActivePage(const std::vector< | 300 void FaviconHandler::NotifyFaviconAvailable( |
298 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { | 301 const std::vector<favicon_base::FaviconRawBitmapResult>& |
| 302 favicon_bitmap_results, |
| 303 bool update_active_favicon) { |
299 gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs( | 304 gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs( |
300 favicon_bitmap_results, | 305 favicon_bitmap_results, |
301 favicon_base::GetFaviconScales(), | 306 favicon_base::GetFaviconScales(), |
302 preferred_icon_size()); | 307 preferred_icon_size()); |
303 // The history service sends back results for a single icon URL, so it does | 308 // The history service sends back results for a single icon URL, so it does |
304 // not matter which result we get the |icon_url| from. | 309 // not matter which result we get the |icon_url| from. |
305 const GURL icon_url = favicon_bitmap_results.empty() ? | 310 const GURL icon_url = favicon_bitmap_results.empty() ? |
306 GURL() : favicon_bitmap_results[0].icon_url; | 311 GURL() : favicon_bitmap_results[0].icon_url; |
307 SetFaviconOnActivePage(icon_url, resized_image); | 312 NotifyFaviconAvailable(icon_url, resized_image, update_active_favicon); |
308 } | 313 } |
309 | 314 |
310 void FaviconHandler::SetFaviconOnActivePage(const GURL& icon_url, | 315 void FaviconHandler::NotifyFaviconAvailable(const GURL& icon_url, |
311 const gfx::Image& image) { | 316 const gfx::Image& image, |
312 // No matter what happens, we need to mark the favicon as being set. | 317 bool update_active_favicon) { |
313 driver_->SetActiveFaviconValidity(true); | |
314 | |
315 bool icon_url_changed = driver_->GetActiveFaviconURL() != icon_url; | |
316 driver_->SetActiveFaviconURL(icon_url); | |
317 | |
318 if (image.IsEmpty()) | |
319 return; | |
320 | |
321 gfx::Image image_with_adjusted_colorspace = image; | 318 gfx::Image image_with_adjusted_colorspace = image; |
322 favicon_base::SetFaviconColorSpace(&image_with_adjusted_colorspace); | 319 favicon_base::SetFaviconColorSpace(&image_with_adjusted_colorspace); |
323 | 320 |
324 driver_->SetActiveFaviconImage(image_with_adjusted_colorspace); | 321 driver_->OnFaviconAvailable( |
325 NotifyFaviconUpdated(icon_url_changed); | 322 image_with_adjusted_colorspace, icon_url, update_active_favicon); |
326 } | 323 } |
327 | 324 |
328 void FaviconHandler::OnUpdateFaviconURL( | 325 void FaviconHandler::OnUpdateFaviconURL( |
329 const std::vector<FaviconURL>& candidates) { | 326 const std::vector<FaviconURL>& candidates) { |
330 image_urls_.clear(); | 327 image_urls_.clear(); |
331 best_favicon_candidate_ = FaviconCandidate(); | 328 best_favicon_candidate_ = FaviconCandidate(); |
332 for (std::vector<FaviconURL>::const_iterator i = candidates.begin(); | 329 for (std::vector<FaviconURL>::const_iterator i = candidates.begin(); |
333 i != candidates.end(); ++i) { | 330 i != candidates.end(); ++i) { |
334 if (!i->icon_url.is_empty() && (i->icon_type & icon_types_)) | 331 if (!i->icon_url.is_empty() && (i->icon_type & icon_types_)) |
335 image_urls_.push_back(*i); | 332 image_urls_.push_back(*i); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 } | 500 } |
504 | 501 |
505 bool FaviconHandler::ShouldSaveFavicon(const GURL& url) { | 502 bool FaviconHandler::ShouldSaveFavicon(const GURL& url) { |
506 if (!driver_->IsOffTheRecord()) | 503 if (!driver_->IsOffTheRecord()) |
507 return true; | 504 return true; |
508 | 505 |
509 // Otherwise store the favicon if the page is bookmarked. | 506 // Otherwise store the favicon if the page is bookmarked. |
510 return client_->IsBookmarked(url); | 507 return client_->IsBookmarked(url); |
511 } | 508 } |
512 | 509 |
513 void FaviconHandler::NotifyFaviconUpdated(bool icon_url_changed) { | |
514 driver_->NotifyFaviconUpdated(icon_url_changed); | |
515 } | |
516 | |
517 int FaviconHandler::GetMaximalIconSize(favicon_base::IconType icon_type) { | 510 int FaviconHandler::GetMaximalIconSize(favicon_base::IconType icon_type) { |
518 switch (icon_type) { | 511 switch (icon_type) { |
519 case favicon_base::FAVICON: | 512 case favicon_base::FAVICON: |
520 #if defined(OS_ANDROID) | 513 #if defined(OS_ANDROID) |
521 return 192; | 514 return 192; |
522 #else | 515 #else |
523 return gfx::ImageSkia::GetMaxSupportedScale() * gfx::kFaviconSize; | 516 return gfx::ImageSkia::GetMaxSupportedScale() * gfx::kFaviconSize; |
524 #endif | 517 #endif |
525 case favicon_base::TOUCH_ICON: | 518 case favicon_base::TOUCH_ICON: |
526 case favicon_base::TOUCH_PRECOMPOSED_ICON: | 519 case favicon_base::TOUCH_PRECOMPOSED_ICON: |
527 return kTouchIconSize; | 520 return kTouchIconSize; |
528 case favicon_base::INVALID_ICON: | 521 case favicon_base::INVALID_ICON: |
529 return 0; | 522 return 0; |
530 } | 523 } |
531 NOTREACHED(); | 524 NOTREACHED(); |
532 return 0; | 525 return 0; |
533 } | 526 } |
534 | 527 |
535 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( | 528 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( |
536 const std::vector<favicon_base::FaviconRawBitmapResult>& | 529 const std::vector<favicon_base::FaviconRawBitmapResult>& |
537 favicon_bitmap_results) { | 530 favicon_bitmap_results) { |
538 if (PageChangedSinceFaviconWasRequested()) | 531 if (PageChangedSinceFaviconWasRequested()) |
539 return; | 532 return; |
540 got_favicon_from_history_ = true; | 533 got_favicon_from_history_ = true; |
541 history_results_ = favicon_bitmap_results; | 534 history_results_ = favicon_bitmap_results; |
542 bool has_results = !favicon_bitmap_results.empty(); | 535 bool has_results = !favicon_bitmap_results.empty(); |
543 favicon_expired_or_incomplete_ = has_results && HasExpiredOrIncompleteResult( | 536 favicon_expired_or_incomplete_ = has_results && HasExpiredOrIncompleteResult( |
544 preferred_icon_size(), favicon_bitmap_results); | 537 preferred_icon_size(), favicon_bitmap_results); |
| 538 bool has_valid_result = HasValidResult(favicon_bitmap_results); |
| 539 |
545 if (has_results && icon_types_ == favicon_base::FAVICON && | 540 if (has_results && icon_types_ == favicon_base::FAVICON && |
546 !driver_->GetActiveFaviconValidity() && | 541 !driver_->GetActiveFaviconValidity() && |
547 (!current_candidate() || | 542 (!current_candidate() || |
548 DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results))) { | 543 DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results))) { |
549 if (HasValidResult(favicon_bitmap_results)) { | 544 if (has_valid_result) { |
550 // The db knows the favicon (although it may be out of date) and the entry | 545 // The db knows the favicon (although it may be out of date) and the entry |
551 // doesn't have an icon. Set the favicon now, and if the favicon turns out | 546 // doesn't have an icon. Set the favicon now, and if the favicon turns out |
552 // to be expired (or the wrong url) we'll fetch later on. This way the | 547 // to be expired (or the wrong url) we'll fetch later on. This way the |
553 // user doesn't see a flash of the default favicon. | 548 // user doesn't see a flash of the default favicon. |
554 SetFaviconOnActivePage(favicon_bitmap_results); | 549 NotifyFaviconAvailable(favicon_bitmap_results, !download_largest_icon_); |
555 } else { | 550 } else { |
556 // If |favicon_bitmap_results| does not have any valid results, treat the | 551 // If |favicon_bitmap_results| does not have any valid results, treat the |
557 // favicon as if it's expired. | 552 // favicon as if it's expired. |
558 // TODO(pkotwicz): Do something better. | 553 // TODO(pkotwicz): Do something better. |
559 favicon_expired_or_incomplete_ = true; | 554 favicon_expired_or_incomplete_ = true; |
560 } | 555 } |
561 } | 556 } |
562 if (has_results && !favicon_expired_or_incomplete_) { | 557 if (has_results && !favicon_expired_or_incomplete_) { |
563 if (current_candidate() && | 558 if (current_candidate() && |
564 !DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results)) { | 559 !DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results)) { |
565 // Mapping in the database is wrong. DownloadFavIconOrAskHistory will | 560 // Mapping in the database is wrong. DownloadFavIconOrAskHistory will |
566 // update the mapping for this url and download the favicon if we don't | 561 // update the mapping for this url and download the favicon if we don't |
567 // already have it. | 562 // already have it. |
568 DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(), | 563 DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(), |
569 current_candidate()->icon_url, | 564 current_candidate()->icon_url, |
570 current_candidate()->icon_type); | 565 current_candidate()->icon_type); |
571 } | 566 } |
572 } else if (current_candidate()) { | 567 } else if (current_candidate()) { |
573 // We know the official url for the favicon, but either don't have the | 568 // We know the official url for the favicon, but either don't have the |
574 // favicon or it's expired. Continue on to DownloadFaviconOrAskHistory to | 569 // favicon or it's expired. Continue on to DownloadFaviconOrAskHistory to |
575 // either download or check history again. | 570 // either download or check history again. |
576 DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(), | 571 DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(), |
577 current_candidate()->icon_url, | 572 current_candidate()->icon_url, |
578 current_candidate()->icon_type); | 573 current_candidate()->icon_type); |
579 } | 574 } |
580 // else we haven't got the icon url. When we get it we'll ask the | 575 // else we haven't got the icon url. When we get it we'll ask the |
581 // renderer to download the icon. | 576 // renderer to download the icon. |
| 577 |
| 578 if (has_valid_result && icon_types_ != favicon_base::FAVICON) |
| 579 NotifyFaviconAvailable(favicon_bitmap_results, false); |
582 } | 580 } |
583 | 581 |
584 void FaviconHandler::DownloadFaviconOrAskFaviconService( | 582 void FaviconHandler::DownloadFaviconOrAskFaviconService( |
585 const GURL& page_url, | 583 const GURL& page_url, |
586 const GURL& icon_url, | 584 const GURL& icon_url, |
587 favicon_base::IconType icon_type) { | 585 favicon_base::IconType icon_type) { |
588 if (favicon_expired_or_incomplete_) { | 586 if (favicon_expired_or_incomplete_) { |
589 // We have the mapping, but the favicon is out of date. Download it now. | 587 // We have the mapping, but the favicon is out of date. Download it now. |
590 ScheduleDownload(page_url, icon_url, icon_type); | 588 ScheduleDownload(page_url, icon_url, icon_type); |
591 } else if (client_->GetFaviconService()) { | 589 } else if (client_->GetFaviconService()) { |
(...skipping 20 matching lines...) Expand all Loading... |
612 } | 610 } |
613 | 611 |
614 void FaviconHandler::OnFaviconData(const std::vector< | 612 void FaviconHandler::OnFaviconData(const std::vector< |
615 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { | 613 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { |
616 if (PageChangedSinceFaviconWasRequested()) | 614 if (PageChangedSinceFaviconWasRequested()) |
617 return; | 615 return; |
618 | 616 |
619 bool has_results = !favicon_bitmap_results.empty(); | 617 bool has_results = !favicon_bitmap_results.empty(); |
620 bool has_expired_or_incomplete_result = HasExpiredOrIncompleteResult( | 618 bool has_expired_or_incomplete_result = HasExpiredOrIncompleteResult( |
621 preferred_icon_size(), favicon_bitmap_results); | 619 preferred_icon_size(), favicon_bitmap_results); |
| 620 bool has_valid_result = HasValidResult(favicon_bitmap_results); |
622 | 621 |
623 if (has_results && icon_types_ == favicon_base::FAVICON) { | 622 if (has_results && icon_types_ == favicon_base::FAVICON) { |
624 if (HasValidResult(favicon_bitmap_results)) { | 623 if (has_valid_result) { |
625 // There is a favicon, set it now. If expired we'll download the current | 624 // There is a favicon, set it now. If expired we'll download the current |
626 // one again, but at least the user will get some icon instead of the | 625 // one again, but at least the user will get some icon instead of the |
627 // default and most likely the current one is fine anyway. | 626 // default and most likely the current one is fine anyway. |
628 SetFaviconOnActivePage(favicon_bitmap_results); | 627 NotifyFaviconAvailable(favicon_bitmap_results, !download_largest_icon_); |
629 } | 628 } |
630 if (has_expired_or_incomplete_result) { | 629 if (has_expired_or_incomplete_result) { |
631 // The favicon is out of date. Request the current one. | 630 // The favicon is out of date. Request the current one. |
632 ScheduleDownload(driver_->GetActiveURL(), | 631 ScheduleDownload(driver_->GetActiveURL(), |
633 driver_->GetActiveFaviconURL(), | 632 driver_->GetActiveFaviconURL(), |
634 favicon_base::FAVICON); | 633 favicon_base::FAVICON); |
635 } | 634 } |
636 } else if (current_candidate() && | 635 } else if (current_candidate() && |
637 (!has_results || has_expired_or_incomplete_result || | 636 (!has_results || has_expired_or_incomplete_result || |
638 !(DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results)))) { | 637 !(DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results)))) { |
639 // We don't know the favicon, it is out of date or its type is not same as | 638 // We don't know the favicon, it is out of date or its type is not same as |
640 // one got from page. Request the current one. | 639 // one got from page. Request the current one. |
641 ScheduleDownload(driver_->GetActiveURL(), | 640 ScheduleDownload(driver_->GetActiveURL(), |
642 current_candidate()->icon_url, | 641 current_candidate()->icon_url, |
643 current_candidate()->icon_type); | 642 current_candidate()->icon_type); |
644 } | 643 } |
645 history_results_ = favicon_bitmap_results; | 644 history_results_ = favicon_bitmap_results; |
| 645 |
| 646 if (has_valid_result && icon_types_ != favicon_base::FAVICON) |
| 647 NotifyFaviconAvailable(favicon_bitmap_results, false); |
646 } | 648 } |
647 | 649 |
648 int FaviconHandler::ScheduleDownload(const GURL& url, | 650 int FaviconHandler::ScheduleDownload(const GURL& url, |
649 const GURL& image_url, | 651 const GURL& image_url, |
650 favicon_base::IconType icon_type) { | 652 favicon_base::IconType icon_type) { |
651 // A max bitmap size is specified to avoid receiving huge bitmaps in | 653 // A max bitmap size is specified to avoid receiving huge bitmaps in |
652 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() | 654 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() |
653 // for more details about the max bitmap size. | 655 // for more details about the max bitmap size. |
654 const int download_id = DownloadFavicon(image_url, | 656 const int download_id = DownloadFavicon(image_url, |
655 GetMaximalIconSize(icon_type)); | 657 GetMaximalIconSize(icon_type)); |
(...skipping 13 matching lines...) Expand all Loading... |
669 if (i->icon_sizes.empty()) | 671 if (i->icon_sizes.empty()) |
670 continue; | 672 continue; |
671 | 673 |
672 gfx::Size largest = i->icon_sizes[GetLargestSizeIndex(i->icon_sizes)]; | 674 gfx::Size largest = i->icon_sizes[GetLargestSizeIndex(i->icon_sizes)]; |
673 i->icon_sizes.clear(); | 675 i->icon_sizes.clear(); |
674 i->icon_sizes.push_back(largest); | 676 i->icon_sizes.push_back(largest); |
675 } | 677 } |
676 std::stable_sort(image_urls_.begin(), image_urls_.end(), | 678 std::stable_sort(image_urls_.begin(), image_urls_.end(), |
677 CompareIconSize); | 679 CompareIconSize); |
678 } | 680 } |
OLD | NEW |