| 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 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 download_requests_.clear(); | 256 download_requests_.clear(); |
| 257 image_urls_.clear(); | 257 image_urls_.clear(); |
| 258 notification_icon_url_ = GURL(); | 258 notification_icon_url_ = GURL(); |
| 259 notification_icon_type_ = favicon_base::INVALID_ICON; | 259 notification_icon_type_ = favicon_base::INVALID_ICON; |
| 260 current_candidate_index_ = 0u; | 260 current_candidate_index_ = 0u; |
| 261 best_favicon_candidate_ = FaviconCandidate(); | 261 best_favicon_candidate_ = FaviconCandidate(); |
| 262 | 262 |
| 263 // Request the favicon from the history service. In parallel to this the | 263 // Request the favicon from the history service. In parallel to this the |
| 264 // renderer is going to notify us (well WebContents) when the favicon url is | 264 // renderer is going to notify us (well WebContents) when the favicon url is |
| 265 // available. | 265 // available. |
| 266 GetFaviconForURLFromFaviconService( | 266 if (service_) { |
| 267 url_, icon_types_, | 267 service_->GetFaviconForPageURL( |
| 268 base::Bind(&FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, | 268 url_, icon_types_, preferred_icon_size(), |
| 269 base::Unretained(this)), | 269 base::Bind( |
| 270 &cancelable_task_tracker_); | 270 &FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, |
| 271 base::Unretained(this)), |
| 272 &cancelable_task_tracker_); |
| 273 } |
| 271 } | 274 } |
| 272 | 275 |
| 273 bool FaviconHandler::UpdateFaviconCandidate(const GURL& image_url, | 276 bool FaviconHandler::UpdateFaviconCandidate(const GURL& image_url, |
| 274 const gfx::Image& image, | 277 const gfx::Image& image, |
| 275 float score, | 278 float score, |
| 276 favicon_base::IconType icon_type) { | 279 favicon_base::IconType icon_type) { |
| 277 bool replace_best_favicon_candidate = false; | 280 bool replace_best_favicon_candidate = false; |
| 278 bool exact_match = false; | 281 bool exact_match = false; |
| 279 if (download_largest_icon_) { | 282 if (download_largest_icon_) { |
| 280 replace_best_favicon_candidate = | 283 replace_best_favicon_candidate = |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 if (replace_best_favicon_candidate) { | 316 if (replace_best_favicon_candidate) { |
| 314 best_favicon_candidate_ = | 317 best_favicon_candidate_ = |
| 315 FaviconCandidate(image_url, image, score, icon_type); | 318 FaviconCandidate(image_url, image, score, icon_type); |
| 316 } | 319 } |
| 317 return exact_match; | 320 return exact_match; |
| 318 } | 321 } |
| 319 | 322 |
| 320 void FaviconHandler::SetFavicon(const GURL& icon_url, | 323 void FaviconHandler::SetFavicon(const GURL& icon_url, |
| 321 const gfx::Image& image, | 324 const gfx::Image& image, |
| 322 favicon_base::IconType icon_type) { | 325 favicon_base::IconType icon_type) { |
| 323 if (ShouldSaveFavicon()) | 326 if (service_ && ShouldSaveFavicon()) |
| 324 SetHistoryFavicons(url_, icon_url, icon_type, image); | 327 service_->SetFavicons(url_, icon_url, icon_type, image); |
| 325 | 328 |
| 326 NotifyFaviconUpdated(icon_url, icon_type, image); | 329 NotifyFaviconUpdated(icon_url, icon_type, image); |
| 327 } | 330 } |
| 328 | 331 |
| 329 void FaviconHandler::NotifyFaviconUpdated( | 332 void FaviconHandler::NotifyFaviconUpdated( |
| 330 const std::vector<favicon_base::FaviconRawBitmapResult>& | 333 const std::vector<favicon_base::FaviconRawBitmapResult>& |
| 331 favicon_bitmap_results) { | 334 favicon_bitmap_results) { |
| 332 if (favicon_bitmap_results.empty()) | 335 if (favicon_bitmap_results.empty()) |
| 333 return; | 336 return; |
| 334 | 337 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 image_urls_ = pruned_candidates; | 391 image_urls_ = pruned_candidates; |
| 389 current_candidate_index_ = 0u; | 392 current_candidate_index_ = 0u; |
| 390 best_favicon_candidate_ = FaviconCandidate(); | 393 best_favicon_candidate_ = FaviconCandidate(); |
| 391 | 394 |
| 392 // TODO(davemoore) Should clear on empty url. Currently we ignore it. | 395 // TODO(davemoore) Should clear on empty url. Currently we ignore it. |
| 393 // This appears to be what FF does as well. | 396 // This appears to be what FF does as well. |
| 394 if (current_candidate() && got_favicon_from_history_) | 397 if (current_candidate() && got_favicon_from_history_) |
| 395 OnGotInitialHistoryDataAndIconURLCandidates(); | 398 OnGotInitialHistoryDataAndIconURLCandidates(); |
| 396 } | 399 } |
| 397 | 400 |
| 401 int FaviconHandler::GetMaximalIconSize(favicon_base::IconType icon_type) { |
| 402 switch (icon_type) { |
| 403 case favicon_base::FAVICON: |
| 404 #if defined(OS_ANDROID) |
| 405 return 192; |
| 406 #else |
| 407 return gfx::ImageSkia::GetMaxSupportedScale() * gfx::kFaviconSize; |
| 408 #endif |
| 409 case favicon_base::TOUCH_ICON: |
| 410 case favicon_base::TOUCH_PRECOMPOSED_ICON: |
| 411 return kTouchIconSize; |
| 412 case favicon_base::INVALID_ICON: |
| 413 return 0; |
| 414 } |
| 415 NOTREACHED(); |
| 416 return 0; |
| 417 } |
| 418 |
| 398 void FaviconHandler::OnGotInitialHistoryDataAndIconURLCandidates() { | 419 void FaviconHandler::OnGotInitialHistoryDataAndIconURLCandidates() { |
| 399 if (!initial_history_result_expired_or_incomplete_ && | 420 if (!initial_history_result_expired_or_incomplete_ && |
| 400 DoUrlAndIconMatch(*current_candidate(), notification_icon_url_, | 421 DoUrlAndIconMatch(*current_candidate(), notification_icon_url_, |
| 401 notification_icon_type_)) { | 422 notification_icon_type_)) { |
| 402 // - The data from history is valid and not expired. | 423 // - The data from history is valid and not expired. |
| 403 // - The icon URL of the history data matches one of the page's icon URLs. | 424 // - The icon URL of the history data matches one of the page's icon URLs. |
| 404 // - The icon URL of the history data matches the icon URL of the last | 425 // - The icon URL of the history data matches the icon URL of the last |
| 405 // OnFaviconAvailable() notification. | 426 // OnFaviconAvailable() notification. |
| 406 // We are done. No additional downloads or history requests are needed. | 427 // We are done. No additional downloads or history requests are needed. |
| 407 // TODO: Store all of the icon URLs associated with a page in history so | 428 // TODO: Store all of the icon URLs associated with a page in history so |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 current_candidate_index_ = image_urls_.size(); | 513 current_candidate_index_ = image_urls_.size(); |
| 493 best_favicon_candidate_ = FaviconCandidate(); | 514 best_favicon_candidate_ = FaviconCandidate(); |
| 494 } | 515 } |
| 495 } | 516 } |
| 496 | 517 |
| 497 bool FaviconHandler::HasPendingTasksForTest() { | 518 bool FaviconHandler::HasPendingTasksForTest() { |
| 498 return !download_requests_.empty() || | 519 return !download_requests_.empty() || |
| 499 cancelable_task_tracker_.HasTrackedTasks(); | 520 cancelable_task_tracker_.HasTrackedTasks(); |
| 500 } | 521 } |
| 501 | 522 |
| 502 void FaviconHandler::UpdateFaviconMappingAndFetch( | |
| 503 const GURL& page_url, | |
| 504 const GURL& icon_url, | |
| 505 favicon_base::IconType icon_type, | |
| 506 const favicon_base::FaviconResultsCallback& callback, | |
| 507 base::CancelableTaskTracker* tracker) { | |
| 508 // TODO(pkotwicz): pass in all of |image_urls_| to | |
| 509 // UpdateFaviconMappingsAndFetch(). | |
| 510 if (service_) { | |
| 511 std::vector<GURL> icon_urls; | |
| 512 icon_urls.push_back(icon_url); | |
| 513 service_->UpdateFaviconMappingsAndFetch(page_url, icon_urls, icon_type, | |
| 514 preferred_icon_size(), callback, | |
| 515 tracker); | |
| 516 } | |
| 517 } | |
| 518 | |
| 519 void FaviconHandler::GetFaviconFromFaviconService( | |
| 520 const GURL& icon_url, | |
| 521 favicon_base::IconType icon_type, | |
| 522 const favicon_base::FaviconResultsCallback& callback, | |
| 523 base::CancelableTaskTracker* tracker) { | |
| 524 if (service_) { | |
| 525 service_->GetFavicon(icon_url, icon_type, preferred_icon_size(), callback, | |
| 526 tracker); | |
| 527 } | |
| 528 } | |
| 529 | |
| 530 void FaviconHandler::GetFaviconForURLFromFaviconService( | |
| 531 const GURL& page_url, | |
| 532 int icon_types, | |
| 533 const favicon_base::FaviconResultsCallback& callback, | |
| 534 base::CancelableTaskTracker* tracker) { | |
| 535 if (service_) { | |
| 536 service_->GetFaviconForPageURL(page_url, icon_types, preferred_icon_size(), | |
| 537 callback, tracker); | |
| 538 } | |
| 539 } | |
| 540 | |
| 541 void FaviconHandler::SetHistoryFavicons(const GURL& page_url, | |
| 542 const GURL& icon_url, | |
| 543 favicon_base::IconType icon_type, | |
| 544 const gfx::Image& image) { | |
| 545 if (service_) { | |
| 546 service_->SetFavicons(page_url, icon_url, icon_type, image); | |
| 547 } | |
| 548 } | |
| 549 | |
| 550 bool FaviconHandler::ShouldSaveFavicon() { | 523 bool FaviconHandler::ShouldSaveFavicon() { |
| 551 if (!delegate_->IsOffTheRecord()) | 524 if (!delegate_->IsOffTheRecord()) |
| 552 return true; | 525 return true; |
| 553 | 526 |
| 554 // Always save favicon if the page is bookmarked. | 527 // Always save favicon if the page is bookmarked. |
| 555 return delegate_->IsBookmarked(url_); | 528 return delegate_->IsBookmarked(url_); |
| 556 } | 529 } |
| 557 | 530 |
| 558 int FaviconHandler::GetMaximalIconSize(favicon_base::IconType icon_type) { | |
| 559 switch (icon_type) { | |
| 560 case favicon_base::FAVICON: | |
| 561 #if defined(OS_ANDROID) | |
| 562 return 192; | |
| 563 #else | |
| 564 return gfx::ImageSkia::GetMaxSupportedScale() * gfx::kFaviconSize; | |
| 565 #endif | |
| 566 case favicon_base::TOUCH_ICON: | |
| 567 case favicon_base::TOUCH_PRECOMPOSED_ICON: | |
| 568 return kTouchIconSize; | |
| 569 case favicon_base::INVALID_ICON: | |
| 570 return 0; | |
| 571 } | |
| 572 NOTREACHED(); | |
| 573 return 0; | |
| 574 } | |
| 575 | |
| 576 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( | 531 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( |
| 577 const std::vector<favicon_base::FaviconRawBitmapResult>& | 532 const std::vector<favicon_base::FaviconRawBitmapResult>& |
| 578 favicon_bitmap_results) { | 533 favicon_bitmap_results) { |
| 579 got_favicon_from_history_ = true; | 534 got_favicon_from_history_ = true; |
| 580 bool has_valid_result = HasValidResult(favicon_bitmap_results); | 535 bool has_valid_result = HasValidResult(favicon_bitmap_results); |
| 581 initial_history_result_expired_or_incomplete_ = | 536 initial_history_result_expired_or_incomplete_ = |
| 582 !has_valid_result || | 537 !has_valid_result || |
| 583 HasExpiredOrIncompleteResult(preferred_icon_size(), | 538 HasExpiredOrIncompleteResult(preferred_icon_size(), |
| 584 favicon_bitmap_results); | 539 favicon_bitmap_results); |
| 585 redownload_icons_ = initial_history_result_expired_or_incomplete_ && | 540 redownload_icons_ = initial_history_result_expired_or_incomplete_ && |
| (...skipping 13 matching lines...) Expand all Loading... |
| 599 OnGotInitialHistoryDataAndIconURLCandidates(); | 554 OnGotInitialHistoryDataAndIconURLCandidates(); |
| 600 } | 555 } |
| 601 | 556 |
| 602 void FaviconHandler::DownloadCurrentCandidateOrAskFaviconService() { | 557 void FaviconHandler::DownloadCurrentCandidateOrAskFaviconService() { |
| 603 GURL icon_url = current_candidate()->icon_url; | 558 GURL icon_url = current_candidate()->icon_url; |
| 604 favicon_base::IconType icon_type = current_candidate()->icon_type; | 559 favicon_base::IconType icon_type = current_candidate()->icon_type; |
| 605 | 560 |
| 606 if (redownload_icons_) { | 561 if (redownload_icons_) { |
| 607 // We have the mapping, but the favicon is out of date. Download it now. | 562 // We have the mapping, but the favicon is out of date. Download it now. |
| 608 ScheduleDownload(icon_url, icon_type); | 563 ScheduleDownload(icon_url, icon_type); |
| 609 } else { | 564 } else if (service_) { |
| 610 // We don't know the favicon, but we may have previously downloaded the | 565 // 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 | 566 // favicon for another page that shares the same favicon. Ask for the |
| 612 // favicon given the favicon URL. | 567 // favicon given the favicon URL. |
| 613 if (delegate_->IsOffTheRecord()) { | 568 if (delegate_->IsOffTheRecord()) { |
| 614 GetFaviconFromFaviconService( | 569 service_->GetFavicon( |
| 615 icon_url, icon_type, | 570 icon_url, icon_type, preferred_icon_size(), |
| 616 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), | 571 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), |
| 617 &cancelable_task_tracker_); | 572 &cancelable_task_tracker_); |
| 618 } else { | 573 } else { |
| 619 // Ask the history service for the icon. This does two things: | 574 // Ask the history service for the icon. This does two things: |
| 620 // 1. Attempts to fetch the favicon data from the database. | 575 // 1. Attempts to fetch the favicon data from the database. |
| 621 // 2. If the favicon exists in the database, this updates the database to | 576 // 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. | 577 // include the mapping between the page url and the favicon url. |
| 623 // This is asynchronous. The history service will call back when done. | 578 // This is asynchronous. The history service will call back when done. |
| 624 UpdateFaviconMappingAndFetch( | 579 // TODO(pkotwicz): pass in all of |image_urls_| to |
| 625 url_, icon_url, icon_type, | 580 // UpdateFaviconMappingsAndFetch(). |
| 581 service_->UpdateFaviconMappingsAndFetch( |
| 582 url_, {icon_url}, icon_type, preferred_icon_size(), |
| 626 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), | 583 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), |
| 627 &cancelable_task_tracker_); | 584 &cancelable_task_tracker_); |
| 628 } | 585 } |
| 629 } | 586 } |
| 630 } | 587 } |
| 631 | 588 |
| 632 void FaviconHandler::OnFaviconData(const std::vector< | 589 void FaviconHandler::OnFaviconData(const std::vector< |
| 633 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { | 590 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { |
| 634 bool has_results = !favicon_bitmap_results.empty(); | 591 bool has_results = !favicon_bitmap_results.empty(); |
| 635 bool has_valid_result = HasValidResult(favicon_bitmap_results); | 592 bool has_valid_result = HasValidResult(favicon_bitmap_results); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 670 std::vector<gfx::Size>()); | 627 std::vector<gfx::Size>()); |
| 671 return; | 628 return; |
| 672 } | 629 } |
| 673 // A max bitmap size is specified to avoid receiving huge bitmaps in | 630 // A max bitmap size is specified to avoid receiving huge bitmaps in |
| 674 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() | 631 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() |
| 675 // for more details about the max bitmap size. | 632 // for more details about the max bitmap size. |
| 676 const int download_id = | 633 const int download_id = |
| 677 delegate_->DownloadImage(image_url, GetMaximalIconSize(icon_type), | 634 delegate_->DownloadImage(image_url, GetMaximalIconSize(icon_type), |
| 678 base::Bind(&FaviconHandler::OnDidDownloadFavicon, | 635 base::Bind(&FaviconHandler::OnDidDownloadFavicon, |
| 679 weak_ptr_factory_.GetWeakPtr())); | 636 weak_ptr_factory_.GetWeakPtr())); |
| 637 DCHECK_NE(download_id, 0); |
| 680 | 638 |
| 681 // Download ids should be unique. | 639 // Download ids should be unique. |
| 682 DCHECK(download_requests_.find(download_id) == download_requests_.end()); | 640 DCHECK(download_requests_.find(download_id) == download_requests_.end()); |
| 683 download_requests_[download_id] = DownloadRequest(image_url, icon_type); | 641 download_requests_[download_id] = DownloadRequest(image_url, icon_type); |
| 684 | |
| 685 // TODO(mastiz): Remove the download_id == 0 handling because it's not used | |
| 686 // in production code, only tests. | |
| 687 if (download_id == 0) { | |
| 688 // If DownloadFavicon() did not start a download, it returns a download id | |
| 689 // of 0. We still need to call OnDidDownloadFavicon() because the method is | |
| 690 // responsible for initiating the data request for the next candidate. | |
| 691 OnDidDownloadFavicon(download_id, 0, image_url, std::vector<SkBitmap>(), | |
| 692 std::vector<gfx::Size>()); | |
| 693 } | |
| 694 } | 642 } |
| 695 | 643 |
| 696 } // namespace favicon | 644 } // namespace favicon |
| OLD | NEW |