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 "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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 image(image), | 193 image(image), |
| 194 score(score), | 194 score(score), |
| 195 icon_type(icon_type) {} | 195 icon_type(icon_type) {} |
| 196 | 196 |
| 197 //////////////////////////////////////////////////////////////////////////////// | 197 //////////////////////////////////////////////////////////////////////////////// |
| 198 | 198 |
| 199 FaviconHandler::FaviconHandler(FaviconClient* client, | 199 FaviconHandler::FaviconHandler(FaviconClient* client, |
| 200 FaviconDriver* driver, | 200 FaviconDriver* driver, |
| 201 Type icon_type, | 201 Type icon_type, |
| 202 bool download_largest_icon) | 202 bool download_largest_icon) |
| 203 : got_favicon_from_history_(false), | 203 : waiting_for_favicon_service_data_(false), |
| 204 got_favicon_from_history_(false), | |
| 204 favicon_expired_or_incomplete_(false), | 205 favicon_expired_or_incomplete_(false), |
| 205 icon_types_(icon_type == FAVICON | 206 icon_types_(icon_type == FAVICON |
| 206 ? favicon_base::FAVICON | 207 ? favicon_base::FAVICON |
| 207 : favicon_base::TOUCH_ICON | | 208 : favicon_base::TOUCH_ICON | |
| 208 favicon_base::TOUCH_PRECOMPOSED_ICON), | 209 favicon_base::TOUCH_PRECOMPOSED_ICON), |
| 209 download_largest_icon_(download_largest_icon), | 210 download_largest_icon_(download_largest_icon), |
| 210 client_(client), | 211 client_(client), |
| 211 driver_(driver) { | 212 driver_(driver) { |
| 212 DCHECK(driver_); | 213 DCHECK(driver_); |
| 213 } | 214 } |
| 214 | 215 |
| 215 FaviconHandler::~FaviconHandler() { | 216 FaviconHandler::~FaviconHandler() { |
| 216 } | 217 } |
| 217 | 218 |
| 218 void FaviconHandler::FetchFavicon(const GURL& url) { | 219 void FaviconHandler::FetchFavicon(const GURL& url) { |
| 219 cancelable_task_tracker_.TryCancelAll(); | 220 cancelable_task_tracker_.TryCancelAll(); |
| 220 | 221 |
| 221 url_ = url; | 222 url_ = url; |
| 222 | 223 |
| 224 waiting_for_favicon_service_data_ = true; | |
| 223 favicon_expired_or_incomplete_ = got_favicon_from_history_ = false; | 225 favicon_expired_or_incomplete_ = got_favicon_from_history_ = false; |
| 224 image_urls_.clear(); | 226 image_urls_.clear(); |
| 225 | 227 |
| 226 // Request the favicon from the history service. In parallel to this the | 228 // Request the favicon from the history service. In parallel to this the |
| 227 // renderer is going to notify us (well WebContents) when the favicon url is | 229 // renderer is going to notify us (well WebContents) when the favicon url is |
| 228 // available. | 230 // available. |
| 229 if (client_->GetFaviconService()) { | 231 if (client_->GetFaviconService()) { |
| 230 GetFaviconForURLFromFaviconService( | 232 GetFaviconForURLFromFaviconService( |
| 231 url_, | 233 url_, |
| 232 icon_types_, | 234 icon_types_, |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 const GURL& image_url, | 379 const GURL& image_url, |
| 378 const std::vector<SkBitmap>& bitmaps, | 380 const std::vector<SkBitmap>& bitmaps, |
| 379 const std::vector<gfx::Size>& original_bitmap_sizes) { | 381 const std::vector<gfx::Size>& original_bitmap_sizes) { |
| 380 DownloadRequests::iterator i = download_requests_.find(id); | 382 DownloadRequests::iterator i = download_requests_.find(id); |
| 381 if (i == download_requests_.end()) { | 383 if (i == download_requests_.end()) { |
| 382 // Currently WebContents notifies us of ANY downloads so that it is | 384 // Currently WebContents notifies us of ANY downloads so that it is |
| 383 // possible to get here. | 385 // possible to get here. |
| 384 return; | 386 return; |
| 385 } | 387 } |
| 386 | 388 |
| 389 DownloadRequest download_request = i->second; | |
|
sky
2015/02/19 18:08:10
I'm assuming you didn't make this a const & becaus
| |
| 387 if (current_candidate() && | 390 if (current_candidate() && |
| 388 DoUrlAndIconMatch(*current_candidate(), image_url, i->second.icon_type)) { | 391 DoUrlAndIconMatch(*current_candidate(), |
| 392 image_url, | |
| 393 download_request.icon_type)) { | |
| 389 bool request_next_icon = true; | 394 bool request_next_icon = true; |
| 390 float score = 0.0f; | 395 float score = 0.0f; |
| 391 gfx::ImageSkia image_skia; | 396 gfx::ImageSkia image_skia; |
| 392 if (download_largest_icon_ && !bitmaps.empty()) { | 397 if (download_largest_icon_ && !bitmaps.empty()) { |
| 393 int index = -1; | 398 int index = -1; |
| 394 // Use the largest bitmap if FaviconURL doesn't have sizes attribute. | 399 // Use the largest bitmap if FaviconURL doesn't have sizes attribute. |
| 395 if (current_candidate()->icon_sizes.empty()) { | 400 if (current_candidate()->icon_sizes.empty()) { |
| 396 index = GetLargestSizeIndex(original_bitmap_sizes); | 401 index = GetLargestSizeIndex(original_bitmap_sizes); |
| 397 } else { | 402 } else { |
| 398 index = GetIndexBySize(original_bitmap_sizes, | 403 index = GetIndexBySize(original_bitmap_sizes, |
| 399 current_candidate()->icon_sizes[0]); | 404 current_candidate()->icon_sizes[0]); |
| 400 // Find largest bitmap if there is no one exactly matched. | 405 // Find largest bitmap if there is no one exactly matched. |
| 401 if (index == -1) | 406 if (index == -1) |
| 402 index = GetLargestSizeIndex(original_bitmap_sizes); | 407 index = GetLargestSizeIndex(original_bitmap_sizes); |
| 403 } | 408 } |
| 404 image_skia = gfx::ImageSkia(gfx::ImageSkiaRep(bitmaps[index], 1)); | 409 image_skia = gfx::ImageSkia(gfx::ImageSkiaRep(bitmaps[index], 1)); |
| 405 } else { | 410 } else { |
| 406 image_skia = CreateFaviconImageSkia(bitmaps, | 411 image_skia = CreateFaviconImageSkia(bitmaps, |
| 407 original_bitmap_sizes, | 412 original_bitmap_sizes, |
| 408 preferred_icon_size(), | 413 preferred_icon_size(), |
| 409 &score); | 414 &score); |
| 410 } | 415 } |
| 411 | 416 |
| 412 if (!image_skia.isNull()) { | 417 if (!image_skia.isNull()) { |
| 413 gfx::Image image(image_skia); | 418 gfx::Image image(image_skia); |
| 414 // The downloaded icon is still valid when there is no FaviconURL update | 419 // The downloaded icon is still valid when there is no FaviconURL update |
| 415 // during the downloading. | 420 // during the downloading. |
| 416 if (!bitmaps.empty()) { | 421 if (!bitmaps.empty()) { |
| 417 request_next_icon = !UpdateFaviconCandidate( | 422 request_next_icon = !UpdateFaviconCandidate( |
| 418 i->second.url, image_url, image, score, i->second.icon_type); | 423 download_request.url, image_url, image, score, |
| 424 download_request.icon_type); | |
| 419 } | 425 } |
| 420 } | 426 } |
| 421 if (request_next_icon && !PageChangedSinceFaviconWasRequested() && | 427 if (request_next_icon && !PageChangedSinceFaviconWasRequested() && |
| 422 image_urls_.size() > 1) { | 428 image_urls_.size() > 1) { |
| 423 // Remove the first member of image_urls_ and process the remaining. | 429 // Remove the first member of image_urls_ and process the remaining. |
| 424 image_urls_.erase(image_urls_.begin()); | 430 image_urls_.erase(image_urls_.begin()); |
| 425 ProcessCurrentUrl(); | 431 ProcessCurrentUrl(); |
| 426 } else if (best_favicon_candidate_.icon_type != | 432 } else if (best_favicon_candidate_.icon_type != |
| 427 favicon_base::INVALID_ICON) { | 433 favicon_base::INVALID_ICON) { |
| 434 // Clear |download_requests_| so that a receiver of the notification | |
| 435 // sent by FaviconDriver::OnFaviconAvailable() can correctly compute | |
| 436 // HasPendingDownloadsForTest(). | |
|
sky
2015/02/19 18:08:10
I'm confused. Why do we need to do this? If it's j
| |
| 437 download_requests_.clear(); | |
| 438 | |
| 428 // No more icons to request, set the favicon from the candidate. | 439 // No more icons to request, set the favicon from the candidate. |
| 429 SetFavicon(best_favicon_candidate_.url, | 440 SetFavicon(best_favicon_candidate_.url, |
| 430 best_favicon_candidate_.image_url, | 441 best_favicon_candidate_.image_url, |
| 431 best_favicon_candidate_.image, | 442 best_favicon_candidate_.image, |
| 432 best_favicon_candidate_.icon_type); | 443 best_favicon_candidate_.icon_type); |
| 433 // Reset candidate. | 444 // Reset candidate. |
| 434 image_urls_.clear(); | 445 image_urls_.clear(); |
| 435 best_favicon_candidate_ = FaviconCandidate(); | 446 best_favicon_candidate_ = FaviconCandidate(); |
| 436 } | 447 } |
| 437 } | 448 } |
| 438 download_requests_.erase(i); | 449 download_requests_.erase(id); |
|
sky
2015/02/19 18:08:10
This is subtle too. |i| may have been invalidated.
| |
| 450 } | |
| 451 | |
| 452 bool FaviconHandler::HasPendingFaviconServiceRequestsForTest() const { | |
| 453 return waiting_for_favicon_service_data_; | |
| 454 } | |
| 455 | |
| 456 bool FaviconHandler::HasPendingDownloadsForTest() const { | |
| 457 return !download_requests_.empty(); | |
| 439 } | 458 } |
| 440 | 459 |
| 441 bool FaviconHandler::PageChangedSinceFaviconWasRequested() { | 460 bool FaviconHandler::PageChangedSinceFaviconWasRequested() { |
| 442 if (UrlMatches(driver_->GetActiveURL(), url_) && url_.is_valid()) { | 461 if (UrlMatches(driver_->GetActiveURL(), url_) && url_.is_valid()) { |
| 443 return false; | 462 return false; |
| 444 } | 463 } |
| 445 // If the URL has changed out from under us (as will happen with redirects) | 464 // If the URL has changed out from under us (as will happen with redirects) |
| 446 // return true. | 465 // return true. |
| 447 return true; | 466 return true; |
| 448 } | 467 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 524 } | 543 } |
| 525 NOTREACHED(); | 544 NOTREACHED(); |
| 526 return 0; | 545 return 0; |
| 527 } | 546 } |
| 528 | 547 |
| 529 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( | 548 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService( |
| 530 const std::vector<favicon_base::FaviconRawBitmapResult>& | 549 const std::vector<favicon_base::FaviconRawBitmapResult>& |
| 531 favicon_bitmap_results) { | 550 favicon_bitmap_results) { |
| 532 if (PageChangedSinceFaviconWasRequested()) | 551 if (PageChangedSinceFaviconWasRequested()) |
| 533 return; | 552 return; |
| 553 waiting_for_favicon_service_data_ = false; | |
| 534 got_favicon_from_history_ = true; | 554 got_favicon_from_history_ = true; |
| 535 history_results_ = favicon_bitmap_results; | 555 history_results_ = favicon_bitmap_results; |
| 536 bool has_results = !favicon_bitmap_results.empty(); | 556 bool has_results = !favicon_bitmap_results.empty(); |
| 537 favicon_expired_or_incomplete_ = has_results && HasExpiredOrIncompleteResult( | 557 favicon_expired_or_incomplete_ = has_results && HasExpiredOrIncompleteResult( |
| 538 preferred_icon_size(), favicon_bitmap_results); | 558 preferred_icon_size(), favicon_bitmap_results); |
| 539 bool has_valid_result = HasValidResult(favicon_bitmap_results); | 559 bool has_valid_result = HasValidResult(favicon_bitmap_results); |
| 540 | 560 |
| 541 if (has_results && icon_types_ == favicon_base::FAVICON && | 561 if (has_results && icon_types_ == favicon_base::FAVICON && |
| 542 !download_largest_icon_ && !driver_->GetActiveFaviconValidity() && | 562 !download_largest_icon_ && !driver_->GetActiveFaviconValidity() && |
| 543 (!current_candidate() || | 563 (!current_candidate() || |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 586 const GURL& icon_url, | 606 const GURL& icon_url, |
| 587 favicon_base::IconType icon_type) { | 607 favicon_base::IconType icon_type) { |
| 588 if (favicon_expired_or_incomplete_) { | 608 if (favicon_expired_or_incomplete_) { |
| 589 // We have the mapping, but the favicon is out of date. Download it now. | 609 // We have the mapping, but the favicon is out of date. Download it now. |
| 590 ScheduleDownload(page_url, icon_url, icon_type); | 610 ScheduleDownload(page_url, icon_url, icon_type); |
| 591 } else if (client_->GetFaviconService()) { | 611 } else if (client_->GetFaviconService()) { |
| 592 // We don't know the favicon, but we may have previously downloaded the | 612 // We don't know the favicon, but we may have previously downloaded the |
| 593 // favicon for another page that shares the same favicon. Ask for the | 613 // favicon for another page that shares the same favicon. Ask for the |
| 594 // favicon given the favicon URL. | 614 // favicon given the favicon URL. |
| 595 if (driver_->IsOffTheRecord()) { | 615 if (driver_->IsOffTheRecord()) { |
| 616 waiting_for_favicon_service_data_ = true; | |
|
sky
2015/02/19 18:08:10
Is there a reason you don't want to move setting t
| |
| 596 GetFaviconFromFaviconService( | 617 GetFaviconFromFaviconService( |
| 597 icon_url, icon_type, | 618 icon_url, icon_type, |
| 598 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), | 619 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), |
| 599 &cancelable_task_tracker_); | 620 &cancelable_task_tracker_); |
| 600 } else { | 621 } else { |
| 601 // Ask the history service for the icon. This does two things: | 622 // Ask the history service for the icon. This does two things: |
| 602 // 1. Attempts to fetch the favicon data from the database. | 623 // 1. Attempts to fetch the favicon data from the database. |
| 603 // 2. If the favicon exists in the database, this updates the database to | 624 // 2. If the favicon exists in the database, this updates the database to |
| 604 // include the mapping between the page url and the favicon url. | 625 // include the mapping between the page url and the favicon url. |
| 605 // This is asynchronous. The history service will call back when done. | 626 // This is asynchronous. The history service will call back when done. |
| 606 UpdateFaviconMappingAndFetch( | 627 waiting_for_favicon_service_data_ = true; |
| 628 UpdateFaviconMappingAndFetch( | |
| 607 page_url, icon_url, icon_type, | 629 page_url, icon_url, icon_type, |
| 608 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), | 630 base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)), |
| 609 &cancelable_task_tracker_); | 631 &cancelable_task_tracker_); |
| 610 } | 632 } |
| 611 } | 633 } |
| 612 } | 634 } |
| 613 | 635 |
| 614 void FaviconHandler::OnFaviconData(const std::vector< | 636 void FaviconHandler::OnFaviconData(const std::vector< |
| 615 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { | 637 favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) { |
| 616 if (PageChangedSinceFaviconWasRequested()) | 638 if (PageChangedSinceFaviconWasRequested()) |
| 617 return; | 639 return; |
| 618 | 640 |
| 641 waiting_for_favicon_service_data_ = false; | |
| 642 | |
| 619 bool has_results = !favicon_bitmap_results.empty(); | 643 bool has_results = !favicon_bitmap_results.empty(); |
| 620 bool has_expired_or_incomplete_result = HasExpiredOrIncompleteResult( | 644 bool has_expired_or_incomplete_result = HasExpiredOrIncompleteResult( |
| 621 preferred_icon_size(), favicon_bitmap_results); | 645 preferred_icon_size(), favicon_bitmap_results); |
| 622 bool has_valid_result = HasValidResult(favicon_bitmap_results); | 646 bool has_valid_result = HasValidResult(favicon_bitmap_results); |
| 623 | 647 |
| 624 if (has_results && icon_types_ == favicon_base::FAVICON && | 648 if (has_results && icon_types_ == favicon_base::FAVICON && |
| 625 !download_largest_icon_) { | 649 !download_largest_icon_) { |
| 626 if (has_valid_result) { | 650 if (has_valid_result) { |
| 627 // There is a favicon, set it now. If expired we'll download the current | 651 // There is a favicon, set it now. If expired we'll download the current |
| 628 // one again, but at least the user will get some icon instead of the | 652 // one again, but at least the user will get some icon instead of the |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 676 if (i->icon_sizes.empty()) | 700 if (i->icon_sizes.empty()) |
| 677 continue; | 701 continue; |
| 678 | 702 |
| 679 gfx::Size largest = i->icon_sizes[GetLargestSizeIndex(i->icon_sizes)]; | 703 gfx::Size largest = i->icon_sizes[GetLargestSizeIndex(i->icon_sizes)]; |
| 680 i->icon_sizes.clear(); | 704 i->icon_sizes.clear(); |
| 681 i->icon_sizes.push_back(largest); | 705 i->icon_sizes.push_back(largest); |
| 682 } | 706 } |
| 683 std::stable_sort(image_urls_.begin(), image_urls_.end(), | 707 std::stable_sort(image_urls_.begin(), image_urls_.end(), |
| 684 CompareIconSize); | 708 CompareIconSize); |
| 685 } | 709 } |
| OLD | NEW |