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 |