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 "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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 | 168 |
| 169 // Checks whether two FaviconURLs are equal ignoring the icon sizes. | 169 // Checks whether two FaviconURLs are equal ignoring the icon sizes. |
| 170 bool FaviconURLsEqualIgnoringSizes(const FaviconURL& u1, const FaviconURL& u2) { | 170 bool FaviconURLsEqualIgnoringSizes(const FaviconURL& u1, const FaviconURL& u2) { |
| 171 return u1.icon_type == u2.icon_type && u1.icon_url == u2.icon_url; | 171 return u1.icon_type == u2.icon_type && u1.icon_url == u2.icon_url; |
| 172 } | 172 } |
| 173 | 173 |
| 174 } // namespace | 174 } // namespace |
| 175 | 175 |
| 176 //////////////////////////////////////////////////////////////////////////////// | 176 //////////////////////////////////////////////////////////////////////////////// |
| 177 | 177 |
| 178 FaviconHandler::DownloadRequest::DownloadRequest() | |
| 179 : icon_type(favicon_base::INVALID_ICON) { | |
| 180 } | |
| 181 | |
| 182 FaviconHandler::DownloadRequest::~DownloadRequest() { | |
| 183 } | |
| 184 | |
| 185 FaviconHandler::DownloadRequest::DownloadRequest( | |
| 186 const GURL& image_url, | |
| 187 favicon_base::IconType icon_type) | |
| 188 : image_url(image_url), icon_type(icon_type) { | |
| 189 } | |
| 190 | |
| 191 //////////////////////////////////////////////////////////////////////////////// | |
| 192 | |
| 193 FaviconHandler::FaviconCandidate::FaviconCandidate() | 178 FaviconHandler::FaviconCandidate::FaviconCandidate() |
| 194 : score(0), icon_type(favicon_base::INVALID_ICON) { | 179 : score(0), icon_type(favicon_base::INVALID_ICON) { |
| 195 } | 180 } |
| 196 | 181 |
| 197 FaviconHandler::FaviconCandidate::~FaviconCandidate() { | 182 FaviconHandler::FaviconCandidate::~FaviconCandidate() { |
| 198 } | 183 } |
| 199 | 184 |
| 200 FaviconHandler::FaviconCandidate::FaviconCandidate( | 185 FaviconHandler::FaviconCandidate::FaviconCandidate( |
| 201 const GURL& image_url, | 186 const GURL& image_url, |
| 202 const gfx::Image& image, | 187 const gfx::Image& image, |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 217 got_favicon_from_history_(false), | 202 got_favicon_from_history_(false), |
| 218 initial_history_result_expired_or_incomplete_(false), | 203 initial_history_result_expired_or_incomplete_(false), |
| 219 redownload_icons_(false), | 204 redownload_icons_(false), |
| 220 icon_types_(FaviconHandler::GetIconTypesFromHandlerType(handler_type)), | 205 icon_types_(FaviconHandler::GetIconTypesFromHandlerType(handler_type)), |
| 221 download_largest_icon_( | 206 download_largest_icon_( |
| 222 handler_type == FaviconDriverObserver::NON_TOUCH_LARGEST || | 207 handler_type == FaviconDriverObserver::NON_TOUCH_LARGEST || |
| 223 handler_type == FaviconDriverObserver::TOUCH_LARGEST), | 208 handler_type == FaviconDriverObserver::TOUCH_LARGEST), |
| 224 notification_icon_type_(favicon_base::INVALID_ICON), | 209 notification_icon_type_(favicon_base::INVALID_ICON), |
| 225 service_(service), | 210 service_(service), |
| 226 delegate_(delegate), | 211 delegate_(delegate), |
| 227 current_candidate_index_(0u), | 212 current_candidate_index_(0u) { |
| 228 weak_ptr_factory_(this) { | |
| 229 DCHECK(delegate_); | 213 DCHECK(delegate_); |
| 230 } | 214 } |
| 231 | 215 |
| 232 FaviconHandler::~FaviconHandler() { | 216 FaviconHandler::~FaviconHandler() { |
| 233 } | 217 } |
| 234 | 218 |
| 235 // static | 219 // static |
| 236 int FaviconHandler::GetIconTypesFromHandlerType( | 220 int FaviconHandler::GetIconTypesFromHandlerType( |
| 237 FaviconDriverObserver::NotificationIconType handler_type) { | 221 FaviconDriverObserver::NotificationIconType handler_type) { |
| 238 switch (handler_type) { | 222 switch (handler_type) { |
| 239 case FaviconDriverObserver::NON_TOUCH_16_DIP: | 223 case FaviconDriverObserver::NON_TOUCH_16_DIP: |
| 240 case FaviconDriverObserver::NON_TOUCH_LARGEST: | 224 case FaviconDriverObserver::NON_TOUCH_LARGEST: |
| 241 return favicon_base::FAVICON; | 225 return favicon_base::FAVICON; |
| 242 case FaviconDriverObserver::TOUCH_LARGEST: | 226 case FaviconDriverObserver::TOUCH_LARGEST: |
| 243 return favicon_base::TOUCH_ICON | favicon_base::TOUCH_PRECOMPOSED_ICON; | 227 return favicon_base::TOUCH_ICON | favicon_base::TOUCH_PRECOMPOSED_ICON; |
| 244 } | 228 } |
| 245 return 0; | 229 return 0; |
| 246 } | 230 } |
| 247 | 231 |
| 248 void FaviconHandler::FetchFavicon(const GURL& url) { | 232 void FaviconHandler::FetchFavicon(const GURL& url) { |
| 249 cancelable_task_tracker_.TryCancelAll(); | 233 cancelable_task_tracker_.TryCancelAll(); |
| 250 | 234 |
| 251 url_ = url; | 235 url_ = url; |
| 252 | 236 |
| 253 initial_history_result_expired_or_incomplete_ = false; | 237 initial_history_result_expired_or_incomplete_ = false; |
| 254 redownload_icons_ = false; | 238 redownload_icons_ = false; |
| 255 got_favicon_from_history_ = false; | 239 got_favicon_from_history_ = false; |
| 256 download_requests_.clear(); | 240 download_request_.Cancel(); |
| 257 image_urls_.clear(); | 241 image_urls_.clear(); |
| 258 notification_icon_url_ = GURL(); | 242 notification_icon_url_ = GURL(); |
| 259 notification_icon_type_ = favicon_base::INVALID_ICON; | 243 notification_icon_type_ = favicon_base::INVALID_ICON; |
| 260 current_candidate_index_ = 0u; | 244 current_candidate_index_ = 0u; |
| 261 best_favicon_candidate_ = FaviconCandidate(); | 245 best_favicon_candidate_ = FaviconCandidate(); |
| 262 | 246 |
| 263 // Request the favicon from the history service. In parallel to this the | 247 // 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 | 248 // renderer is going to notify us (well WebContents) when the favicon url is |
| 265 // available. | 249 // available. |
| 266 if (service_) { | 250 if (service_) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 380 SortAndPruneImageUrls(&pruned_candidates); | 364 SortAndPruneImageUrls(&pruned_candidates); |
| 381 | 365 |
| 382 // Ignore FaviconURL::icon_sizes because FaviconURL::icon_sizes is not stored | 366 // Ignore FaviconURL::icon_sizes because FaviconURL::icon_sizes is not stored |
| 383 // in the history database. | 367 // in the history database. |
| 384 if (image_urls_.size() == pruned_candidates.size() && | 368 if (image_urls_.size() == pruned_candidates.size() && |
| 385 std::equal(pruned_candidates.begin(), pruned_candidates.end(), | 369 std::equal(pruned_candidates.begin(), pruned_candidates.end(), |
| 386 image_urls_.begin(), FaviconURLsEqualIgnoringSizes)) { | 370 image_urls_.begin(), FaviconURLsEqualIgnoringSizes)) { |
| 387 return; | 371 return; |
| 388 } | 372 } |
| 389 | 373 |
| 390 download_requests_.clear(); | 374 download_request_.Cancel(); |
| 391 image_urls_ = pruned_candidates; | 375 image_urls_ = pruned_candidates; |
| 392 current_candidate_index_ = 0u; | 376 current_candidate_index_ = 0u; |
| 393 best_favicon_candidate_ = FaviconCandidate(); | 377 best_favicon_candidate_ = FaviconCandidate(); |
| 394 | 378 |
| 395 // TODO(davemoore) Should clear on empty url. Currently we ignore it. | 379 // TODO(davemoore) Should clear on empty url. Currently we ignore it. |
| 396 // This appears to be what FF does as well. | 380 // This appears to be what FF does as well. |
| 397 if (current_candidate() && got_favicon_from_history_) | 381 if (current_candidate() && got_favicon_from_history_) |
| 398 OnGotInitialHistoryDataAndIconURLCandidates(); | 382 OnGotInitialHistoryDataAndIconURLCandidates(); |
| 399 } | 383 } |
| 400 | 384 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 428 // TODO: Store all of the icon URLs associated with a page in history so | 412 // TODO: Store all of the icon URLs associated with a page in history so |
| 429 // that we can check whether the page's icon URLs match the page's icon URLs | 413 // that we can check whether the page's icon URLs match the page's icon URLs |
| 430 // at the time that the favicon data was stored to the history database. | 414 // at the time that the favicon data was stored to the history database. |
| 431 return; | 415 return; |
| 432 } | 416 } |
| 433 | 417 |
| 434 DownloadCurrentCandidateOrAskFaviconService(); | 418 DownloadCurrentCandidateOrAskFaviconService(); |
| 435 } | 419 } |
| 436 | 420 |
| 437 void FaviconHandler::OnDidDownloadFavicon( | 421 void FaviconHandler::OnDidDownloadFavicon( |
| 422 favicon_base::IconType icon_type, | |
| 438 int id, | 423 int id, |
| 439 int http_status_code, | 424 int http_status_code, |
| 440 const GURL& image_url, | 425 const GURL& image_url, |
| 441 const std::vector<SkBitmap>& bitmaps, | 426 const std::vector<SkBitmap>& bitmaps, |
| 442 const std::vector<gfx::Size>& original_bitmap_sizes) { | 427 const std::vector<gfx::Size>& original_bitmap_sizes) { |
| 428 // Mark ongoing download as finalized. | |
|
pkotwicz
2017/03/10 03:42:29
Nit: How about: "Mark download as finished."
mastiz
2017/03/10 11:34:50
Done.
| |
| 429 download_request_.Cancel(); | |
| 430 | |
| 443 if (bitmaps.empty() && http_status_code == 404) { | 431 if (bitmaps.empty() && http_status_code == 404) { |
| 444 DVLOG(1) << "Failed to Download Favicon:" << image_url; | 432 DVLOG(1) << "Failed to Download Favicon:" << image_url; |
| 445 if (service_) | 433 if (service_) |
| 446 service_->UnableToDownloadFavicon(image_url); | 434 service_->UnableToDownloadFavicon(image_url); |
| 447 } | 435 } |
| 448 | 436 |
| 449 DownloadRequests::iterator i = download_requests_.find(id); | 437 DCHECK(current_candidate()); |
| 450 if (i == download_requests_.end()) { | 438 DCHECK(DoUrlAndIconMatch(*current_candidate(), image_url, icon_type)); |
|
pkotwicz
2017/03/10 03:42:29
Nit: Remove the DCHECKs(). I generally don't think
mastiz
2017/03/10 11:34:50
Done.
| |
| 451 // Currently WebContents notifies us of ANY downloads so that it is | |
| 452 // possible to get here. | |
| 453 return; | |
| 454 } | |
| 455 | |
| 456 DownloadRequest download_request = i->second; | |
| 457 download_requests_.erase(i); | |
| 458 | |
| 459 if (!current_candidate() || | |
| 460 !DoUrlAndIconMatch(*current_candidate(), | |
| 461 image_url, | |
| 462 download_request.icon_type)) { | |
| 463 return; | |
| 464 } | |
| 465 | 439 |
| 466 bool request_next_icon = true; | 440 bool request_next_icon = true; |
| 467 if (!bitmaps.empty()) { | 441 if (!bitmaps.empty()) { |
| 468 float score = 0.0f; | 442 float score = 0.0f; |
| 469 gfx::ImageSkia image_skia; | 443 gfx::ImageSkia image_skia; |
| 470 if (download_largest_icon_) { | 444 if (download_largest_icon_) { |
| 471 int index = -1; | 445 int index = -1; |
| 472 // Use the largest bitmap if FaviconURL doesn't have sizes attribute. | 446 // Use the largest bitmap if FaviconURL doesn't have sizes attribute. |
| 473 if (current_candidate()->icon_sizes.empty()) { | 447 if (current_candidate()->icon_sizes.empty()) { |
| 474 index = GetLargestSizeIndex(original_bitmap_sizes); | 448 index = GetLargestSizeIndex(original_bitmap_sizes); |
| 475 } else { | 449 } else { |
| 476 index = GetIndexBySize(original_bitmap_sizes, | 450 index = GetIndexBySize(original_bitmap_sizes, |
| 477 current_candidate()->icon_sizes[0]); | 451 current_candidate()->icon_sizes[0]); |
| 478 // Find largest bitmap if there is no one exactly matched. | 452 // Find largest bitmap if there is no one exactly matched. |
| 479 if (index == -1) | 453 if (index == -1) |
| 480 index = GetLargestSizeIndex(original_bitmap_sizes); | 454 index = GetLargestSizeIndex(original_bitmap_sizes); |
| 481 } | 455 } |
| 482 image_skia = gfx::ImageSkia(gfx::ImageSkiaRep(bitmaps[index], 1)); | 456 image_skia = gfx::ImageSkia(gfx::ImageSkiaRep(bitmaps[index], 1)); |
| 483 } else { | 457 } else { |
| 484 image_skia = CreateFaviconImageSkia(bitmaps, | 458 image_skia = CreateFaviconImageSkia(bitmaps, |
| 485 original_bitmap_sizes, | 459 original_bitmap_sizes, |
| 486 preferred_icon_size(), | 460 preferred_icon_size(), |
| 487 &score); | 461 &score); |
| 488 } | 462 } |
| 489 | 463 |
| 490 if (!image_skia.isNull()) { | 464 if (!image_skia.isNull()) { |
| 491 gfx::Image image(image_skia); | 465 gfx::Image image(image_skia); |
| 492 // The downloaded icon is still valid when there is no FaviconURL update | 466 // The downloaded icon is still valid when there is no FaviconURL update |
| 493 // during the downloading. | 467 // during the downloading. |
| 494 request_next_icon = !UpdateFaviconCandidate(image_url, image, score, | 468 request_next_icon = |
| 495 download_request.icon_type); | 469 !UpdateFaviconCandidate(image_url, image, score, icon_type); |
| 496 } | 470 } |
| 497 } | 471 } |
| 498 | 472 |
| 499 if (request_next_icon && current_candidate_index_ + 1 < image_urls_.size()) { | 473 if (request_next_icon && current_candidate_index_ + 1 < image_urls_.size()) { |
| 500 // Process the next candidate. | 474 // Process the next candidate. |
| 501 ++current_candidate_index_; | 475 ++current_candidate_index_; |
| 502 DownloadCurrentCandidateOrAskFaviconService(); | 476 DownloadCurrentCandidateOrAskFaviconService(); |
| 503 } else { | 477 } else { |
| 504 // We have either found the ideal candidate or run out of candidates. | 478 // We have either found the ideal candidate or run out of candidates. |
| 505 if (best_favicon_candidate_.icon_type != favicon_base::INVALID_ICON) { | 479 if (best_favicon_candidate_.icon_type != favicon_base::INVALID_ICON) { |
| 506 // No more icons to request, set the favicon from the candidate. | 480 // No more icons to request, set the favicon from the candidate. |
| 507 SetFavicon(best_favicon_candidate_.image_url, | 481 SetFavicon(best_favicon_candidate_.image_url, |
| 508 best_favicon_candidate_.image, | 482 best_favicon_candidate_.image, |
| 509 best_favicon_candidate_.icon_type); | 483 best_favicon_candidate_.icon_type); |
| 510 } | 484 } |
| 511 // Clear download related state. | 485 // Clear download related state. |
| 512 download_requests_.clear(); | |
| 513 current_candidate_index_ = image_urls_.size(); | 486 current_candidate_index_ = image_urls_.size(); |
| 514 best_favicon_candidate_ = FaviconCandidate(); | 487 best_favicon_candidate_ = FaviconCandidate(); |
| 515 } | 488 } |
| 516 } | 489 } |
| 517 | 490 |
| 518 bool FaviconHandler::HasPendingTasksForTest() { | 491 bool FaviconHandler::HasPendingTasksForTest() { |
| 519 return !download_requests_.empty() || | 492 return !download_request_.IsCancelled() || |
| 520 cancelable_task_tracker_.HasTrackedTasks(); | 493 cancelable_task_tracker_.HasTrackedTasks(); |
| 521 } | 494 } |
| 522 | 495 |
| 523 bool FaviconHandler::ShouldSaveFavicon() { | 496 bool FaviconHandler::ShouldSaveFavicon() { |
| 524 if (!delegate_->IsOffTheRecord()) | 497 if (!delegate_->IsOffTheRecord()) |
| 525 return true; | 498 return true; |
| 526 | 499 |
| 527 // Always save favicon if the page is bookmarked. | 500 // Always save favicon if the page is bookmarked. |
| 528 return delegate_->IsBookmarked(url_); | 501 return delegate_->IsBookmarked(url_); |
| 529 } | 502 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 611 | 584 |
| 612 if (has_expired_or_incomplete_result) { | 585 if (has_expired_or_incomplete_result) { |
| 613 ScheduleDownload(current_candidate()->icon_url, | 586 ScheduleDownload(current_candidate()->icon_url, |
| 614 current_candidate()->icon_type); | 587 current_candidate()->icon_type); |
| 615 } | 588 } |
| 616 } | 589 } |
| 617 | 590 |
| 618 void FaviconHandler::ScheduleDownload(const GURL& image_url, | 591 void FaviconHandler::ScheduleDownload(const GURL& image_url, |
| 619 favicon_base::IconType icon_type) { | 592 favicon_base::IconType icon_type) { |
| 620 DCHECK(image_url.is_valid()); | 593 DCHECK(image_url.is_valid()); |
| 594 // Note that CancelableCallback starts cancelled. | |
| 595 DCHECK(download_request_.IsCancelled()) << "More than one ongoing download"; | |
| 621 if (service_ && service_->WasUnableToDownloadFavicon(image_url)) { | 596 if (service_ && service_->WasUnableToDownloadFavicon(image_url)) { |
| 622 DVLOG(1) << "Skip Failed FavIcon: " << image_url; | 597 DVLOG(1) << "Skip Failed FavIcon: " << image_url; |
| 623 // Registration in download_requests_ is needed to prevent | 598 OnDidDownloadFavicon(icon_type, 0, 0, image_url, std::vector<SkBitmap>(), |
| 624 // OnDidDownloadFavicon() from returning early. | |
| 625 download_requests_[0] = DownloadRequest(image_url, icon_type); | |
| 626 OnDidDownloadFavicon(0, 0, image_url, std::vector<SkBitmap>(), | |
| 627 std::vector<gfx::Size>()); | 599 std::vector<gfx::Size>()); |
| 628 return; | 600 return; |
| 629 } | 601 } |
| 602 download_request_.Reset(base::Bind(&FaviconHandler::OnDidDownloadFavicon, | |
| 603 base::Unretained(this), icon_type)); | |
| 630 // A max bitmap size is specified to avoid receiving huge bitmaps in | 604 // A max bitmap size is specified to avoid receiving huge bitmaps in |
| 631 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() | 605 // OnDidDownloadFavicon(). See FaviconDriver::StartDownload() |
| 632 // for more details about the max bitmap size. | 606 // for more details about the max bitmap size. |
| 633 const int download_id = | 607 const int download_id = delegate_->DownloadImage( |
| 634 delegate_->DownloadImage(image_url, GetMaximalIconSize(icon_type), | 608 image_url, GetMaximalIconSize(icon_type), download_request_.callback()); |
| 635 base::Bind(&FaviconHandler::OnDidDownloadFavicon, | |
| 636 weak_ptr_factory_.GetWeakPtr())); | |
| 637 DCHECK_NE(download_id, 0); | 609 DCHECK_NE(download_id, 0); |
| 638 | |
| 639 // Download ids should be unique. | |
| 640 DCHECK(download_requests_.find(download_id) == download_requests_.end()); | |
| 641 download_requests_[download_id] = DownloadRequest(image_url, icon_type); | |
| 642 } | 610 } |
| 643 | 611 |
| 644 } // namespace favicon | 612 } // namespace favicon |
| OLD | NEW |