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 <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 score(score), | 208 score(score), |
209 icon_type(icon_type) {} | 209 icon_type(icon_type) {} |
210 | 210 |
211 //////////////////////////////////////////////////////////////////////////////// | 211 //////////////////////////////////////////////////////////////////////////////// |
212 | 212 |
213 FaviconHandler::FaviconHandler(FaviconService* service, | 213 FaviconHandler::FaviconHandler(FaviconService* service, |
214 FaviconDriver* driver, | 214 FaviconDriver* driver, |
215 Type handler_type) | 215 Type handler_type) |
216 : got_favicon_from_history_(false), | 216 : got_favicon_from_history_(false), |
217 initial_history_result_expired_or_incomplete_(false), | 217 initial_history_result_expired_or_incomplete_(false), |
| 218 redownload_icons_(false), |
218 icon_types_(FaviconHandler::GetIconTypesFromHandlerType(handler_type)), | 219 icon_types_(FaviconHandler::GetIconTypesFromHandlerType(handler_type)), |
219 download_largest_icon_(handler_type == LARGEST_FAVICON || | 220 download_largest_icon_(handler_type == LARGEST_FAVICON || |
220 handler_type == LARGEST_TOUCH), | 221 handler_type == LARGEST_TOUCH), |
221 notification_icon_type_(favicon_base::INVALID_ICON), | 222 notification_icon_type_(favicon_base::INVALID_ICON), |
222 service_(service), | 223 service_(service), |
223 driver_(driver), | 224 driver_(driver), |
224 current_candidate_index_(0u) { | 225 current_candidate_index_(0u) { |
225 DCHECK(driver_); | 226 DCHECK(driver_); |
226 } | 227 } |
227 | 228 |
(...skipping 12 matching lines...) Expand all Loading... |
240 } | 241 } |
241 return 0; | 242 return 0; |
242 } | 243 } |
243 | 244 |
244 void FaviconHandler::FetchFavicon(const GURL& url) { | 245 void FaviconHandler::FetchFavicon(const GURL& url) { |
245 cancelable_task_tracker_.TryCancelAll(); | 246 cancelable_task_tracker_.TryCancelAll(); |
246 | 247 |
247 url_ = url; | 248 url_ = url; |
248 | 249 |
249 initial_history_result_expired_or_incomplete_ = false; | 250 initial_history_result_expired_or_incomplete_ = false; |
| 251 redownload_icons_ = false; |
250 got_favicon_from_history_ = false; | 252 got_favicon_from_history_ = false; |
251 download_requests_.clear(); | 253 download_requests_.clear(); |
252 image_urls_.clear(); | 254 image_urls_.clear(); |
253 notification_icon_url_ = GURL(); | 255 notification_icon_url_ = GURL(); |
254 notification_icon_type_ = favicon_base::INVALID_ICON; | 256 notification_icon_type_ = favicon_base::INVALID_ICON; |
255 current_candidate_index_ = 0u; | 257 current_candidate_index_ = 0u; |
256 best_favicon_candidate_ = FaviconCandidate(); | 258 best_favicon_candidate_ = FaviconCandidate(); |
257 | 259 |
258 // Request the favicon from the history service. In parallel to this the | 260 // Request the favicon from the history service. In parallel to this the |
259 // renderer is going to notify us (well WebContents) when the favicon url is | 261 // renderer is going to notify us (well WebContents) when the favicon url is |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 return 0; | 567 return 0; |
566 } | 568 } |
567 NOTREACHED(); | 569 NOTREACHED(); |
568 return 0; | 570 return 0; |
569 } | 571 } |
570 | 572 |
571 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( | 573 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( |
572 const std::vector<favicon_base::FaviconRawBitmapResult>& | 574 const std::vector<favicon_base::FaviconRawBitmapResult>& |
573 favicon_bitmap_results) { | 575 favicon_bitmap_results) { |
574 got_favicon_from_history_ = true; | 576 got_favicon_from_history_ = true; |
575 bool has_results = !favicon_bitmap_results.empty(); | |
576 initial_history_result_expired_or_incomplete_ = HasExpiredOrIncompleteResult( | |
577 preferred_icon_size(), favicon_bitmap_results); | |
578 bool has_valid_result = HasValidResult(favicon_bitmap_results); | 577 bool has_valid_result = HasValidResult(favicon_bitmap_results); |
| 578 initial_history_result_expired_or_incomplete_ = |
| 579 !has_valid_result || |
| 580 HasExpiredOrIncompleteResult(preferred_icon_size(), |
| 581 favicon_bitmap_results); |
| 582 redownload_icons_ = initial_history_result_expired_or_incomplete_ && |
| 583 !favicon_bitmap_results.empty(); |
579 | 584 |
580 if (has_results && !download_largest_icon_ && | 585 if (has_valid_result && |
581 (!current_candidate() || | 586 (!current_candidate() || |
582 DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results))) { | 587 DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results))) { |
583 if (has_valid_result) { | 588 // The db knows the favicon (although it may be out of date) and the entry |
584 // The db knows the favicon (although it may be out of date) and the entry | 589 // doesn't have an icon. Set the favicon now, and if the favicon turns out |
585 // doesn't have an icon. Set the favicon now, and if the favicon turns out | 590 // to be expired (or the wrong url) we'll fetch later on. This way the |
586 // to be expired (or the wrong url) we'll fetch later on. This way the | 591 // user doesn't see a flash of the default favicon. |
587 // user doesn't see a flash of the default favicon. | 592 |
588 NotifyFaviconAvailable(favicon_bitmap_results); | 593 NotifyFaviconAvailable(favicon_bitmap_results); |
589 } else { | |
590 // If |favicon_bitmap_results| does not have any valid results, treat the | |
591 // favicon as if it's expired. | |
592 // TODO(pkotwicz): Do something better. | |
593 initial_history_result_expired_or_incomplete_ = true; | |
594 } | |
595 } | 594 } |
596 | 595 |
597 if (has_valid_result && download_largest_icon_) | |
598 NotifyFaviconAvailable(favicon_bitmap_results); | |
599 | |
600 if (current_candidate()) | 596 if (current_candidate()) |
601 OnGotInitialHistoryDataAndIconURLCandidates(); | 597 OnGotInitialHistoryDataAndIconURLCandidates(); |
602 } | 598 } |
603 | 599 |
604 void FaviconHandler::DownloadCurrentCandidateOrAskFaviconService() { | 600 void FaviconHandler::DownloadCurrentCandidateOrAskFaviconService() { |
605 GURL icon_url = current_candidate()->icon_url; | 601 GURL icon_url = current_candidate()->icon_url; |
606 favicon_base::IconType icon_type = current_candidate()->icon_type; | 602 favicon_base::IconType icon_type = current_candidate()->icon_type; |
607 | 603 |
608 if (initial_history_result_expired_or_incomplete_) { | 604 if (redownload_icons_) { |
609 // We have the mapping, but the favicon is out of date. Download it now. | 605 // We have the mapping, but the favicon is out of date. Download it now. |
610 ScheduleDownload(icon_url, icon_type); | 606 ScheduleDownload(icon_url, icon_type); |
611 } else { | 607 } else { |
612 // We don't know the favicon, but we may have previously downloaded the | 608 // 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 | 609 // favicon for another page that shares the same favicon. Ask for the |
614 // favicon given the favicon URL. | 610 // favicon given the favicon URL. |
615 if (driver_->IsOffTheRecord()) { | 611 if (driver_->IsOffTheRecord()) { |
616 GetFaviconFromFaviconService( | 612 GetFaviconFromFaviconService( |
617 icon_url, icon_type, | 613 icon_url, icon_type, |
618 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), | 614 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), |
619 &cancelable_task_tracker_); | 615 &cancelable_task_tracker_); |
620 } else { | 616 } else { |
621 // Ask the history service for the icon. This does two things: | 617 // Ask the history service for the icon. This does two things: |
622 // 1. Attempts to fetch the favicon data from the database. | 618 // 1. Attempts to fetch the favicon data from the database. |
623 // 2. If the favicon exists in the database, this updates the database to | 619 // 2. If the favicon exists in the database, this updates the database to |
624 // include the mapping between the page url and the favicon url. | 620 // include the mapping between the page url and the favicon url. |
625 // This is asynchronous. The history service will call back when done. | 621 // This is asynchronous. The history service will call back when done. |
626 UpdateFaviconMappingAndFetch( | 622 UpdateFaviconMappingAndFetch( |
627 url_, icon_url, icon_type, | 623 url_, icon_url, icon_type, |
628 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), | 624 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), |
629 &cancelable_task_tracker_); | 625 &cancelable_task_tracker_); |
630 } | 626 } |
631 } | 627 } |
632 } | 628 } |
633 | 629 |
634 void FaviconHandler::OnFaviconData(const std::vector< | 630 void FaviconHandler::OnFaviconData(const std::vector< |
635 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { | 631 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { |
636 bool has_results = !favicon_bitmap_results.empty(); | 632 bool has_results = !favicon_bitmap_results.empty(); |
637 bool has_expired_or_incomplete_result = HasExpiredOrIncompleteResult( | |
638 preferred_icon_size(), favicon_bitmap_results); | |
639 bool has_valid_result = HasValidResult(favicon_bitmap_results); | 633 bool has_valid_result = HasValidResult(favicon_bitmap_results); |
| 634 bool has_expired_or_incomplete_result = |
| 635 !has_valid_result || HasExpiredOrIncompleteResult(preferred_icon_size(), |
| 636 favicon_bitmap_results); |
640 | 637 |
641 if (has_valid_result) { | 638 if (has_valid_result) { |
642 // 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 |
643 // the observers even if the favicon is expired or incomplete (incorrect | 640 // the observers even if the favicon is expired or incomplete (incorrect |
644 // size) because temporarily showing the user an expired favicon or | 641 // size) because temporarily showing the user an expired favicon or |
645 // streched favicon is preferable to showing the user the default favicon. | 642 // streched favicon is preferable to showing the user the default favicon. |
646 NotifyFaviconAvailable(favicon_bitmap_results); | 643 NotifyFaviconAvailable(favicon_bitmap_results); |
647 } | 644 } |
648 | 645 |
649 if (!current_candidate() || | 646 if (!current_candidate() || |
650 (has_results && | 647 (has_results && |
651 !DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results))) { | 648 !DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results))) { |
652 // The icon URLs have been updated since the favicon data was requested. | 649 // The icon URLs have been updated since the favicon data was requested. |
653 return; | 650 return; |
654 } | 651 } |
655 | 652 |
656 if (!has_results || has_expired_or_incomplete_result) { | 653 if (has_expired_or_incomplete_result) { |
657 ScheduleDownload(current_candidate()->icon_url, | 654 ScheduleDownload(current_candidate()->icon_url, |
658 current_candidate()->icon_type); | 655 current_candidate()->icon_type); |
659 } | 656 } |
660 } | 657 } |
661 | 658 |
662 void FaviconHandler::ScheduleDownload(const GURL& image_url, | 659 void FaviconHandler::ScheduleDownload(const GURL& image_url, |
663 favicon_base::IconType icon_type) { | 660 favicon_base::IconType icon_type) { |
664 // A max bitmap size is specified to avoid receiving huge bitmaps in | 661 // A max bitmap size is specified to avoid receiving huge bitmaps in |
665 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() | 662 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() |
666 // for more details about the max bitmap size. | 663 // for more details about the max bitmap size. |
667 const int download_id = DownloadFavicon(image_url, | 664 const int download_id = DownloadFavicon(image_url, |
668 GetMaximalIconSize(icon_type)); | 665 GetMaximalIconSize(icon_type)); |
669 | 666 |
670 // Download ids should be unique. | 667 // Download ids should be unique. |
671 DCHECK(download_requests_.find(download_id) == download_requests_.end()); | 668 DCHECK(download_requests_.find(download_id) == download_requests_.end()); |
672 download_requests_[download_id] = DownloadRequest(image_url, icon_type); | 669 download_requests_[download_id] = DownloadRequest(image_url, icon_type); |
673 | 670 |
674 if (download_id == 0) { | 671 if (download_id == 0) { |
675 // If DownloadFavicon() did not start a download, it returns a download id | 672 // If DownloadFavicon() did not start a download, it returns a download id |
676 // of 0. We still need to call OnDidDownloadFavicon() because the method is | 673 // of 0. We still need to call OnDidDownloadFavicon() because the method is |
677 // responsible for initiating the data request for the next candidate. | 674 // responsible for initiating the data request for the next candidate. |
678 OnDidDownloadFavicon(download_id, image_url, std::vector<SkBitmap>(), | 675 OnDidDownloadFavicon(download_id, image_url, std::vector<SkBitmap>(), |
679 std::vector<gfx::Size>()); | 676 std::vector<gfx::Size>()); |
680 | 677 |
681 } | 678 } |
682 } | 679 } |
683 | 680 |
684 } // namespace favicon | 681 } // namespace favicon |
OLD | NEW |