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 |