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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 if (!b1.icon_sizes.empty()) | 144 if (!b1.icon_sizes.empty()) |
| 145 area1 = b1.icon_sizes.front().GetArea(); | 145 area1 = b1.icon_sizes.front().GetArea(); |
| 146 | 146 |
| 147 int area2 = 0; | 147 int area2 = 0; |
| 148 if (!b2.icon_sizes.empty()) | 148 if (!b2.icon_sizes.empty()) |
| 149 area2 = b2.icon_sizes.front().GetArea(); | 149 area2 = b2.icon_sizes.front().GetArea(); |
| 150 | 150 |
| 151 return area1 > area2; | 151 return area1 > area2; |
| 152 } | 152 } |
| 153 | 153 |
| 154 // Checks whether two FaviconURLs are equal ignoring the icon sizes. | |
| 155 bool FaviconURLsEqualIgnoringSizes(const FaviconURL& u1, const FaviconURL& u2) { | |
| 156 return u1.icon_type == u2.icon_type && u1.icon_url == u2.icon_url; | |
| 157 } | |
| 158 | |
| 154 } // namespace | 159 } // namespace |
| 155 | 160 |
| 156 //////////////////////////////////////////////////////////////////////////////// | 161 //////////////////////////////////////////////////////////////////////////////// |
| 157 | 162 |
| 158 FaviconHandler::DownloadRequest::DownloadRequest() | 163 FaviconHandler::DownloadRequest::DownloadRequest() |
| 159 : icon_type(favicon_base::INVALID_ICON) { | 164 : icon_type(favicon_base::INVALID_ICON) { |
| 160 } | 165 } |
| 161 | 166 |
| 162 FaviconHandler::DownloadRequest::~DownloadRequest() { | 167 FaviconHandler::DownloadRequest::~DownloadRequest() { |
| 163 } | 168 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 192 FaviconHandler::FaviconHandler(FaviconService* service, | 197 FaviconHandler::FaviconHandler(FaviconService* service, |
| 193 FaviconDriver* driver, | 198 FaviconDriver* driver, |
| 194 Type handler_type, | 199 Type handler_type, |
| 195 bool download_largest_icon) | 200 bool download_largest_icon) |
| 196 : got_favicon_from_history_(false), | 201 : got_favicon_from_history_(false), |
| 197 favicon_expired_or_incomplete_(false), | 202 favicon_expired_or_incomplete_(false), |
| 198 handler_type_(handler_type), | 203 handler_type_(handler_type), |
| 199 icon_types_(FaviconHandler::GetIconTypesFromHandlerType(handler_type)), | 204 icon_types_(FaviconHandler::GetIconTypesFromHandlerType(handler_type)), |
| 200 download_largest_icon_(download_largest_icon), | 205 download_largest_icon_(download_largest_icon), |
| 201 service_(service), | 206 service_(service), |
| 202 driver_(driver) { | 207 driver_(driver), |
| 208 current_candidate_index_(0u) { | |
| 203 DCHECK(driver_); | 209 DCHECK(driver_); |
| 204 } | 210 } |
| 205 | 211 |
| 206 FaviconHandler::~FaviconHandler() { | 212 FaviconHandler::~FaviconHandler() { |
| 207 } | 213 } |
| 208 | 214 |
| 209 // static | 215 // static |
| 210 int FaviconHandler::GetIconTypesFromHandlerType( | 216 int FaviconHandler::GetIconTypesFromHandlerType( |
| 211 FaviconHandler::Type handler_type) { | 217 FaviconHandler::Type handler_type) { |
| 212 switch (handler_type) { | 218 switch (handler_type) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 223 | 229 |
| 224 void FaviconHandler::FetchFavicon(const GURL& url) { | 230 void FaviconHandler::FetchFavicon(const GURL& url) { |
| 225 cancelable_task_tracker_.TryCancelAll(); | 231 cancelable_task_tracker_.TryCancelAll(); |
| 226 | 232 |
| 227 url_ = url; | 233 url_ = url; |
| 228 | 234 |
| 229 favicon_expired_or_incomplete_ = got_favicon_from_history_ = false; | 235 favicon_expired_or_incomplete_ = got_favicon_from_history_ = false; |
| 230 download_requests_.clear(); | 236 download_requests_.clear(); |
| 231 image_urls_.clear(); | 237 image_urls_.clear(); |
| 232 history_results_.clear(); | 238 history_results_.clear(); |
| 239 current_candidate_index_ = 0u; | |
| 233 best_favicon_candidate_ = FaviconCandidate(); | 240 best_favicon_candidate_ = FaviconCandidate(); |
| 234 | 241 |
| 235 // Request the favicon from the history service. In parallel to this the | 242 // Request the favicon from the history service. In parallel to this the |
| 236 // renderer is going to notify us (well WebContents) when the favicon url is | 243 // renderer is going to notify us (well WebContents) when the favicon url is |
| 237 // available. | 244 // available. |
| 238 GetFaviconForURLFromFaviconService( | 245 GetFaviconForURLFromFaviconService( |
| 239 url_, icon_types_, | 246 url_, icon_types_, |
| 240 base::Bind(&FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, | 247 base::Bind(&FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, |
| 241 base::Unretained(this)), | 248 base::Unretained(this)), |
| 242 &cancelable_task_tracker_); | 249 &cancelable_task_tracker_); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 259 | 266 |
| 260 // The size of the downloaded icon may not match the declared size. Stop | 267 // The size of the downloaded icon may not match the declared size. Stop |
| 261 // downloading if: | 268 // downloading if: |
| 262 // - current candidate is only candidate. | 269 // - current candidate is only candidate. |
| 263 // - next candidate doesn't have sizes attributes, in this case, the rest | 270 // - next candidate doesn't have sizes attributes, in this case, the rest |
| 264 // candidates don't have sizes attribute either, stop downloading now, | 271 // candidates don't have sizes attribute either, stop downloading now, |
| 265 // otherwise, all favicon without sizes attribute are downloaded. | 272 // otherwise, all favicon without sizes attribute are downloaded. |
| 266 // - next candidate has sizes attribute and it is not larger than largest, | 273 // - next candidate has sizes attribute and it is not larger than largest, |
| 267 // - current candidate is maximal one we want. | 274 // - current candidate is maximal one we want. |
| 268 const int maximal_size = GetMaximalIconSize(icon_type); | 275 const int maximal_size = GetMaximalIconSize(icon_type); |
| 269 exact_match = image_urls_.size() == 1 || | 276 if (current_candidate_index_ + 1 >= image_urls_.size()) { |
| 270 image_urls_[1].icon_sizes.empty() || | 277 exact_match = true; |
| 271 image_urls_[1].icon_sizes[0].GetArea() <= largest.GetArea() || | 278 } else { |
| 272 (image.Size().width() == maximal_size && | 279 FaviconURL next_image_url = image_urls_[current_candidate_index_ + 1]; |
| 273 image.Size().height() == maximal_size); | 280 exact_match = next_image_url.icon_sizes.empty() || |
| 281 next_image_url.icon_sizes[0].GetArea() <= largest.GetArea() || | |
| 282 (image.Size().width() == maximal_size && | |
| 283 image.Size().height() == maximal_size); | |
| 284 } | |
| 274 } else { | 285 } else { |
| 275 exact_match = score == 1 || preferred_icon_size() == 0; | 286 exact_match = score == 1 || preferred_icon_size() == 0; |
| 276 replace_best_favicon_candidate = | 287 replace_best_favicon_candidate = |
| 277 exact_match || | 288 exact_match || |
| 278 best_favicon_candidate_.icon_type == favicon_base::INVALID_ICON || | 289 best_favicon_candidate_.icon_type == favicon_base::INVALID_ICON || |
| 279 score > best_favicon_candidate_.score; | 290 score > best_favicon_candidate_.score; |
| 280 } | 291 } |
| 281 if (replace_best_favicon_candidate) { | 292 if (replace_best_favicon_candidate) { |
| 282 best_favicon_candidate_ = | 293 best_favicon_candidate_ = |
| 283 FaviconCandidate(image_url, image, score, icon_type); | 294 FaviconCandidate(image_url, image, score, icon_type); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 319 driver_->OnFaviconAvailable( | 330 driver_->OnFaviconAvailable( |
| 320 url_, icon_url, image_with_adjusted_colorspace, is_active_favicon); | 331 url_, icon_url, image_with_adjusted_colorspace, is_active_favicon); |
| 321 } | 332 } |
| 322 | 333 |
| 323 void FaviconHandler::OnUpdateFaviconURL( | 334 void FaviconHandler::OnUpdateFaviconURL( |
| 324 const GURL& page_url, | 335 const GURL& page_url, |
| 325 const std::vector<FaviconURL>& candidates) { | 336 const std::vector<FaviconURL>& candidates) { |
| 326 if (page_url != url_) | 337 if (page_url != url_) |
| 327 return; | 338 return; |
| 328 | 339 |
| 329 download_requests_.clear(); | 340 std::vector<FaviconURL> pruned_candidates; |
| 330 image_urls_.clear(); | |
| 331 best_favicon_candidate_ = FaviconCandidate(); | |
| 332 | |
| 333 for (const FaviconURL& candidate : candidates) { | 341 for (const FaviconURL& candidate : candidates) { |
| 334 if (!candidate.icon_url.is_empty() && (candidate.icon_type & icon_types_)) | 342 if (!candidate.icon_url.is_empty() && (candidate.icon_type & icon_types_)) |
| 335 image_urls_.push_back(candidate); | 343 pruned_candidates.push_back(candidate); |
| 336 } | 344 } |
| 337 | 345 |
| 338 if (download_largest_icon_) | 346 if (download_largest_icon_) |
| 339 SortAndPruneImageUrls(); | 347 SortAndPruneImageUrls(&pruned_candidates); |
| 348 | |
| 349 // Ignore FaviconURL::icon_sizes because FaviconURL::icon_sizes is not stored | |
| 350 // in the history database. | |
| 351 if (image_urls_.size() == pruned_candidates.size() && | |
| 352 std::equal(pruned_candidates.begin(), pruned_candidates.end(), | |
| 353 image_urls_.begin(), FaviconURLsEqualIgnoringSizes)) { | |
| 354 return; | |
| 355 } | |
| 356 | |
| 357 download_requests_.clear(); | |
| 358 image_urls_ = pruned_candidates; | |
| 359 current_candidate_index_ = 0u; | |
| 360 best_favicon_candidate_ = FaviconCandidate(); | |
| 340 | 361 |
| 341 // TODO(davemoore) Should clear on empty url. Currently we ignore it. | 362 // TODO(davemoore) Should clear on empty url. Currently we ignore it. |
| 342 // This appears to be what FF does as well. | 363 // This appears to be what FF does as well. |
| 343 if (!image_urls_.empty()) | 364 if (current_candidate()) |
| 344 ProcessCurrentUrl(); | 365 ProcessCurrentUrl(); |
| 345 } | 366 } |
| 346 | 367 |
| 347 void FaviconHandler::ProcessCurrentUrl() { | 368 void FaviconHandler::ProcessCurrentUrl() { |
| 348 DCHECK(!image_urls_.empty()); | 369 DCHECK(!image_urls_.empty()); |
| 349 | 370 |
| 350 // current_candidate() may return NULL if download_largest_icon_ is true and | |
| 351 // all the sizes are larger than the max. | |
| 352 if (!current_candidate()) | |
| 353 return; | |
| 354 | |
| 355 if (current_candidate()->icon_type == favicon_base::FAVICON && | 371 if (current_candidate()->icon_type == favicon_base::FAVICON && |
| 356 !download_largest_icon_) { | 372 !download_largest_icon_) { |
| 357 if (!favicon_expired_or_incomplete_ && | 373 if (!favicon_expired_or_incomplete_ && |
| 358 driver_->GetActiveFaviconValidity() && | 374 driver_->GetActiveFaviconValidity() && |
| 359 DoUrlAndIconMatch(*current_candidate(), | 375 DoUrlAndIconMatch(*current_candidate(), |
| 360 driver_->GetActiveFaviconURL(), | 376 driver_->GetActiveFaviconURL(), |
| 361 favicon_base::FAVICON)) | 377 favicon_base::FAVICON)) |
| 362 return; | 378 return; |
| 363 } else if (!favicon_expired_or_incomplete_ && got_favicon_from_history_ && | 379 } else if (!favicon_expired_or_incomplete_ && got_favicon_from_history_ && |
| 364 HasValidResult(history_results_) && | 380 HasValidResult(history_results_) && |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 419 | 435 |
| 420 if (!image_skia.isNull()) { | 436 if (!image_skia.isNull()) { |
| 421 gfx::Image image(image_skia); | 437 gfx::Image image(image_skia); |
| 422 // The downloaded icon is still valid when there is no FaviconURL update | 438 // The downloaded icon is still valid when there is no FaviconURL update |
| 423 // during the downloading. | 439 // during the downloading. |
| 424 request_next_icon = !UpdateFaviconCandidate(image_url, image, score, | 440 request_next_icon = !UpdateFaviconCandidate(image_url, image, score, |
| 425 download_request.icon_type); | 441 download_request.icon_type); |
| 426 } | 442 } |
| 427 } | 443 } |
| 428 | 444 |
| 429 if (request_next_icon && image_urls_.size() > 1) { | 445 if (request_next_icon && current_candidate_index_ + 1 < image_urls_.size()) { |
| 430 // Remove the first member of image_urls_ and process the remaining. | 446 // Process the next candidate. |
| 431 image_urls_.erase(image_urls_.begin()); | 447 ++current_candidate_index_; |
| 432 ProcessCurrentUrl(); | 448 ProcessCurrentUrl(); |
| 433 } else { | 449 } else { |
| 434 // We have either found the ideal candidate or run out of candidates. | 450 // We have either found the ideal candidate or run out of candidates. |
| 435 if (best_favicon_candidate_.icon_type != favicon_base::INVALID_ICON) { | 451 if (best_favicon_candidate_.icon_type != favicon_base::INVALID_ICON) { |
| 436 // No more icons to request, set the favicon from the candidate. | 452 // No more icons to request, set the favicon from the candidate. |
| 437 SetFavicon(best_favicon_candidate_.image_url, | 453 SetFavicon(best_favicon_candidate_.image_url, |
| 438 best_favicon_candidate_.image, | 454 best_favicon_candidate_.image, |
| 439 best_favicon_candidate_.icon_type); | 455 best_favicon_candidate_.icon_type); |
| 440 } | 456 } |
| 441 // Clear download related state. | 457 // Clear download related state. |
| 442 image_urls_.clear(); | |
| 443 download_requests_.clear(); | 458 download_requests_.clear(); |
| 459 current_candidate_index_ = image_urls_.size(); | |
| 444 best_favicon_candidate_ = FaviconCandidate(); | 460 best_favicon_candidate_ = FaviconCandidate(); |
| 445 } | 461 } |
| 446 } | 462 } |
| 447 | 463 |
| 448 bool FaviconHandler::HasPendingTasksForTest() { | 464 bool FaviconHandler::HasPendingTasksForTest() { |
| 449 return !download_requests_.empty() || | 465 return !download_requests_.empty() || |
| 450 cancelable_task_tracker_.HasTrackedTasks(); | 466 cancelable_task_tracker_.HasTrackedTasks(); |
| 451 } | 467 } |
| 452 | 468 |
| 453 int FaviconHandler::DownloadFavicon(const GURL& image_url, | 469 int FaviconHandler::DownloadFavicon(const GURL& image_url, |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 657 if (download_id == 0) { | 673 if (download_id == 0) { |
| 658 // If DownloadFavicon() did not start a download, it returns a download id | 674 // If DownloadFavicon() did not start a download, it returns a download id |
| 659 // of 0. We still need to call OnDidDownloadFavicon() because the method is | 675 // of 0. We still need to call OnDidDownloadFavicon() because the method is |
| 660 // responsible for initiating the data request for the next candidate. | 676 // responsible for initiating the data request for the next candidate. |
| 661 OnDidDownloadFavicon(download_id, image_url, std::vector<SkBitmap>(), | 677 OnDidDownloadFavicon(download_id, image_url, std::vector<SkBitmap>(), |
| 662 std::vector<gfx::Size>()); | 678 std::vector<gfx::Size>()); |
| 663 | 679 |
| 664 } | 680 } |
| 665 } | 681 } |
| 666 | 682 |
| 667 void FaviconHandler::SortAndPruneImageUrls() { | 683 void FaviconHandler::SortAndPruneImageUrls( |
| 684 std::vector<FaviconURL>* image_urls) { | |
|
sky
2015/10/05 17:22:43
Move this into anonymous namespace as it no longer
| |
| 668 // Not using const-reference since the loop mutates FaviconURL::icon_sizes. | 685 // Not using const-reference since the loop mutates FaviconURL::icon_sizes. |
| 669 for (FaviconURL& image_url : image_urls_) { | 686 for (FaviconURL& image_url : *image_urls) { |
| 670 if (image_url.icon_sizes.empty()) | 687 if (image_url.icon_sizes.empty()) |
| 671 continue; | 688 continue; |
| 672 | 689 |
| 673 gfx::Size largest = | 690 gfx::Size largest = |
| 674 image_url.icon_sizes[GetLargestSizeIndex(image_url.icon_sizes)]; | 691 image_url.icon_sizes[GetLargestSizeIndex(image_url.icon_sizes)]; |
| 675 image_url.icon_sizes.clear(); | 692 image_url.icon_sizes.clear(); |
| 676 image_url.icon_sizes.push_back(largest); | 693 image_url.icon_sizes.push_back(largest); |
| 677 } | 694 } |
| 678 std::stable_sort(image_urls_.begin(), image_urls_.end(), | 695 std::stable_sort(image_urls->begin(), image_urls->end(), CompareIconSize); |
| 679 CompareIconSize); | |
| 680 } | 696 } |
| 681 | 697 |
| 682 } // namespace favicon | 698 } // namespace favicon |
| OLD | NEW |