Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: components/favicon/core/favicon_handler.cc

Issue 1295733002: Ignore duplicate FaviconHandler::OnUpdateFaviconURL() calls (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@page_changed_under_us
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 // Sorts the entries in |image_urls| by icon size in descending order.
155 // Discards all but the largest size for each FaviconURL.
156 void SortAndPruneImageUrls(std::vector<FaviconURL>* image_urls) {
157 // Not using const-reference since the loop mutates FaviconURL::icon_sizes.
158 for (FaviconURL& image_url : *image_urls) {
159 if (image_url.icon_sizes.empty())
160 continue;
161
162 gfx::Size largest =
163 image_url.icon_sizes[GetLargestSizeIndex(image_url.icon_sizes)];
164 image_url.icon_sizes.clear();
165 image_url.icon_sizes.push_back(largest);
166 }
167 std::stable_sort(image_urls->begin(), image_urls->end(), CompareIconSize);
168 }
169
170 // Checks whether two FaviconURLs are equal ignoring the icon sizes.
171 bool FaviconURLsEqualIgnoringSizes(const FaviconURL& u1, const FaviconURL& u2) {
172 return u1.icon_type == u2.icon_type && u1.icon_url == u2.icon_url;
173 }
174
154 } // namespace 175 } // namespace
155 176
156 //////////////////////////////////////////////////////////////////////////////// 177 ////////////////////////////////////////////////////////////////////////////////
157 178
158 FaviconHandler::DownloadRequest::DownloadRequest() 179 FaviconHandler::DownloadRequest::DownloadRequest()
159 : icon_type(favicon_base::INVALID_ICON) { 180 : icon_type(favicon_base::INVALID_ICON) {
160 } 181 }
161 182
162 FaviconHandler::DownloadRequest::~DownloadRequest() { 183 FaviconHandler::DownloadRequest::~DownloadRequest() {
163 } 184 }
(...skipping 28 matching lines...) Expand all
192 FaviconHandler::FaviconHandler(FaviconService* service, 213 FaviconHandler::FaviconHandler(FaviconService* service,
193 FaviconDriver* driver, 214 FaviconDriver* driver,
194 Type handler_type, 215 Type handler_type,
195 bool download_largest_icon) 216 bool download_largest_icon)
196 : got_favicon_from_history_(false), 217 : got_favicon_from_history_(false),
197 favicon_expired_or_incomplete_(false), 218 favicon_expired_or_incomplete_(false),
198 handler_type_(handler_type), 219 handler_type_(handler_type),
199 icon_types_(FaviconHandler::GetIconTypesFromHandlerType(handler_type)), 220 icon_types_(FaviconHandler::GetIconTypesFromHandlerType(handler_type)),
200 download_largest_icon_(download_largest_icon), 221 download_largest_icon_(download_largest_icon),
201 service_(service), 222 service_(service),
202 driver_(driver) { 223 driver_(driver),
224 current_candidate_index_(0u) {
203 DCHECK(driver_); 225 DCHECK(driver_);
204 } 226 }
205 227
206 FaviconHandler::~FaviconHandler() { 228 FaviconHandler::~FaviconHandler() {
207 } 229 }
208 230
209 // static 231 // static
210 int FaviconHandler::GetIconTypesFromHandlerType( 232 int FaviconHandler::GetIconTypesFromHandlerType(
211 FaviconHandler::Type handler_type) { 233 FaviconHandler::Type handler_type) {
212 switch (handler_type) { 234 switch (handler_type) {
(...skipping 10 matching lines...) Expand all
223 245
224 void FaviconHandler::FetchFavicon(const GURL& url) { 246 void FaviconHandler::FetchFavicon(const GURL& url) {
225 cancelable_task_tracker_.TryCancelAll(); 247 cancelable_task_tracker_.TryCancelAll();
226 248
227 url_ = url; 249 url_ = url;
228 250
229 favicon_expired_or_incomplete_ = got_favicon_from_history_ = false; 251 favicon_expired_or_incomplete_ = got_favicon_from_history_ = false;
230 download_requests_.clear(); 252 download_requests_.clear();
231 image_urls_.clear(); 253 image_urls_.clear();
232 history_results_.clear(); 254 history_results_.clear();
255 current_candidate_index_ = 0u;
233 best_favicon_candidate_ = FaviconCandidate(); 256 best_favicon_candidate_ = FaviconCandidate();
234 257
235 // Request the favicon from the history service. In parallel to this the 258 // 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 259 // renderer is going to notify us (well WebContents) when the favicon url is
237 // available. 260 // available.
238 GetFaviconForURLFromFaviconService( 261 GetFaviconForURLFromFaviconService(
239 url_, icon_types_, 262 url_, icon_types_,
240 base::Bind(&FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, 263 base::Bind(&FaviconHandler::OnFaviconDataForInitialURLFromFaviconService,
241 base::Unretained(this)), 264 base::Unretained(this)),
242 &cancelable_task_tracker_); 265 &cancelable_task_tracker_);
(...skipping 16 matching lines...) Expand all
259 282
260 // The size of the downloaded icon may not match the declared size. Stop 283 // The size of the downloaded icon may not match the declared size. Stop
261 // downloading if: 284 // downloading if:
262 // - current candidate is only candidate. 285 // - current candidate is only candidate.
263 // - next candidate doesn't have sizes attributes, in this case, the rest 286 // - next candidate doesn't have sizes attributes, in this case, the rest
264 // candidates don't have sizes attribute either, stop downloading now, 287 // candidates don't have sizes attribute either, stop downloading now,
265 // otherwise, all favicon without sizes attribute are downloaded. 288 // otherwise, all favicon without sizes attribute are downloaded.
266 // - next candidate has sizes attribute and it is not larger than largest, 289 // - next candidate has sizes attribute and it is not larger than largest,
267 // - current candidate is maximal one we want. 290 // - current candidate is maximal one we want.
268 const int maximal_size = GetMaximalIconSize(icon_type); 291 const int maximal_size = GetMaximalIconSize(icon_type);
269 exact_match = image_urls_.size() == 1 || 292 if (current_candidate_index_ + 1 >= image_urls_.size()) {
270 image_urls_[1].icon_sizes.empty() || 293 exact_match = true;
271 image_urls_[1].icon_sizes[0].GetArea() <= largest.GetArea() || 294 } else {
272 (image.Size().width() == maximal_size && 295 FaviconURL next_image_url = image_urls_[current_candidate_index_ + 1];
273 image.Size().height() == maximal_size); 296 exact_match = next_image_url.icon_sizes.empty() ||
297 next_image_url.icon_sizes[0].GetArea() <= largest.GetArea() ||
298 (image.Size().width() == maximal_size &&
299 image.Size().height() == maximal_size);
300 }
274 } else { 301 } else {
275 exact_match = score == 1 || preferred_icon_size() == 0; 302 exact_match = score == 1 || preferred_icon_size() == 0;
276 replace_best_favicon_candidate = 303 replace_best_favicon_candidate =
277 exact_match || 304 exact_match ||
278 best_favicon_candidate_.icon_type == favicon_base::INVALID_ICON || 305 best_favicon_candidate_.icon_type == favicon_base::INVALID_ICON ||
279 score > best_favicon_candidate_.score; 306 score > best_favicon_candidate_.score;
280 } 307 }
281 if (replace_best_favicon_candidate) { 308 if (replace_best_favicon_candidate) {
282 best_favicon_candidate_ = 309 best_favicon_candidate_ =
283 FaviconCandidate(image_url, image, score, icon_type); 310 FaviconCandidate(image_url, image, score, icon_type);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 driver_->OnFaviconAvailable( 346 driver_->OnFaviconAvailable(
320 url_, icon_url, image_with_adjusted_colorspace, is_active_favicon); 347 url_, icon_url, image_with_adjusted_colorspace, is_active_favicon);
321 } 348 }
322 349
323 void FaviconHandler::OnUpdateFaviconURL( 350 void FaviconHandler::OnUpdateFaviconURL(
324 const GURL& page_url, 351 const GURL& page_url,
325 const std::vector<FaviconURL>& candidates) { 352 const std::vector<FaviconURL>& candidates) {
326 if (page_url != url_) 353 if (page_url != url_)
327 return; 354 return;
328 355
329 download_requests_.clear(); 356 std::vector<FaviconURL> pruned_candidates;
330 image_urls_.clear();
331 best_favicon_candidate_ = FaviconCandidate();
332
333 for (const FaviconURL& candidate : candidates) { 357 for (const FaviconURL& candidate : candidates) {
334 if (!candidate.icon_url.is_empty() && (candidate.icon_type & icon_types_)) 358 if (!candidate.icon_url.is_empty() && (candidate.icon_type & icon_types_))
335 image_urls_.push_back(candidate); 359 pruned_candidates.push_back(candidate);
336 } 360 }
337 361
338 if (download_largest_icon_) 362 if (download_largest_icon_)
339 SortAndPruneImageUrls(); 363 SortAndPruneImageUrls(&pruned_candidates);
364
365 // Ignore FaviconURL::icon_sizes because FaviconURL::icon_sizes is not stored
366 // in the history database.
367 if (image_urls_.size() == pruned_candidates.size() &&
368 std::equal(pruned_candidates.begin(), pruned_candidates.end(),
369 image_urls_.begin(), FaviconURLsEqualIgnoringSizes)) {
370 return;
371 }
372
373 download_requests_.clear();
374 image_urls_ = pruned_candidates;
375 current_candidate_index_ = 0u;
376 best_favicon_candidate_ = FaviconCandidate();
340 377
341 // TODO(davemoore) Should clear on empty url. Currently we ignore it. 378 // TODO(davemoore) Should clear on empty url. Currently we ignore it.
342 // This appears to be what FF does as well. 379 // This appears to be what FF does as well.
343 if (!image_urls_.empty()) 380 if (current_candidate())
344 ProcessCurrentUrl(); 381 ProcessCurrentUrl();
345 } 382 }
346 383
347 void FaviconHandler::ProcessCurrentUrl() { 384 void FaviconHandler::ProcessCurrentUrl() {
348 DCHECK(!image_urls_.empty()); 385 DCHECK(!image_urls_.empty());
349 386
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 && 387 if (current_candidate()->icon_type == favicon_base::FAVICON &&
356 !download_largest_icon_) { 388 !download_largest_icon_) {
357 if (!favicon_expired_or_incomplete_ && 389 if (!favicon_expired_or_incomplete_ &&
358 driver_->GetActiveFaviconValidity() && 390 driver_->GetActiveFaviconValidity() &&
359 DoUrlAndIconMatch(*current_candidate(), 391 DoUrlAndIconMatch(*current_candidate(),
360 driver_->GetActiveFaviconURL(), 392 driver_->GetActiveFaviconURL(),
361 favicon_base::FAVICON)) 393 favicon_base::FAVICON))
362 return; 394 return;
363 } else if (!favicon_expired_or_incomplete_ && got_favicon_from_history_ && 395 } else if (!favicon_expired_or_incomplete_ && got_favicon_from_history_ &&
364 HasValidResult(history_results_) && 396 HasValidResult(history_results_) &&
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 451
420 if (!image_skia.isNull()) { 452 if (!image_skia.isNull()) {
421 gfx::Image image(image_skia); 453 gfx::Image image(image_skia);
422 // The downloaded icon is still valid when there is no FaviconURL update 454 // The downloaded icon is still valid when there is no FaviconURL update
423 // during the downloading. 455 // during the downloading.
424 request_next_icon = !UpdateFaviconCandidate(image_url, image, score, 456 request_next_icon = !UpdateFaviconCandidate(image_url, image, score,
425 download_request.icon_type); 457 download_request.icon_type);
426 } 458 }
427 } 459 }
428 460
429 if (request_next_icon && image_urls_.size() > 1) { 461 if (request_next_icon && current_candidate_index_ + 1 < image_urls_.size()) {
430 // Remove the first member of image_urls_ and process the remaining. 462 // Process the next candidate.
431 image_urls_.erase(image_urls_.begin()); 463 ++current_candidate_index_;
432 ProcessCurrentUrl(); 464 ProcessCurrentUrl();
433 } else { 465 } else {
434 // We have either found the ideal candidate or run out of candidates. 466 // We have either found the ideal candidate or run out of candidates.
435 if (best_favicon_candidate_.icon_type != favicon_base::INVALID_ICON) { 467 if (best_favicon_candidate_.icon_type != favicon_base::INVALID_ICON) {
436 // No more icons to request, set the favicon from the candidate. 468 // No more icons to request, set the favicon from the candidate.
437 SetFavicon(best_favicon_candidate_.image_url, 469 SetFavicon(best_favicon_candidate_.image_url,
438 best_favicon_candidate_.image, 470 best_favicon_candidate_.image,
439 best_favicon_candidate_.icon_type); 471 best_favicon_candidate_.icon_type);
440 } 472 }
441 // Clear download related state. 473 // Clear download related state.
442 image_urls_.clear();
443 download_requests_.clear(); 474 download_requests_.clear();
475 current_candidate_index_ = image_urls_.size();
444 best_favicon_candidate_ = FaviconCandidate(); 476 best_favicon_candidate_ = FaviconCandidate();
445 } 477 }
446 } 478 }
447 479
448 bool FaviconHandler::HasPendingTasksForTest() { 480 bool FaviconHandler::HasPendingTasksForTest() {
449 return !download_requests_.empty() || 481 return !download_requests_.empty() ||
450 cancelable_task_tracker_.HasTrackedTasks(); 482 cancelable_task_tracker_.HasTrackedTasks();
451 } 483 }
452 484
453 int FaviconHandler::DownloadFavicon(const GURL& image_url, 485 int FaviconHandler::DownloadFavicon(const GURL& image_url,
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 if (download_id == 0) { 689 if (download_id == 0) {
658 // If DownloadFavicon() did not start a download, it returns a download id 690 // 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 691 // of 0. We still need to call OnDidDownloadFavicon() because the method is
660 // responsible for initiating the data request for the next candidate. 692 // responsible for initiating the data request for the next candidate.
661 OnDidDownloadFavicon(download_id, image_url, std::vector<SkBitmap>(), 693 OnDidDownloadFavicon(download_id, image_url, std::vector<SkBitmap>(),
662 std::vector<gfx::Size>()); 694 std::vector<gfx::Size>());
663 695
664 } 696 }
665 } 697 }
666 698
667 void FaviconHandler::SortAndPruneImageUrls() {
668 // Not using const-reference since the loop mutates FaviconURL::icon_sizes.
669 for (FaviconURL& image_url : image_urls_) {
670 if (image_url.icon_sizes.empty())
671 continue;
672
673 gfx::Size largest =
674 image_url.icon_sizes[GetLargestSizeIndex(image_url.icon_sizes)];
675 image_url.icon_sizes.clear();
676 image_url.icon_sizes.push_back(largest);
677 }
678 std::stable_sort(image_urls_.begin(), image_urls_.end(),
679 CompareIconSize);
680 }
681
682 } // namespace favicon 699 } // namespace favicon
OLDNEW
« no previous file with comments | « components/favicon/core/favicon_handler.h ('k') | components/favicon/core/favicon_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698