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

Side by Side Diff: chrome/browser/favicon/favicon_handler.cc

Issue 10911149: Cleanup FaviconHandler (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 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 | Annotate | Revision Log
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 "chrome/browser/favicon/favicon_handler.h" 5 #include "chrome/browser/favicon/favicon_handler.h"
6 6
7 #include "build/build_config.h" 7 #include "build/build_config.h"
8 8
9 #include <algorithm>
9 #include <vector> 10 #include <vector>
10 11
11 #include "base/bind.h" 12 #include "base/bind.h"
12 #include "base/bind_helpers.h" 13 #include "base/bind_helpers.h"
13 #include "base/memory/ref_counted_memory.h" 14 #include "base/memory/ref_counted_memory.h"
14 #include "chrome/browser/bookmarks/bookmark_model.h" 15 #include "chrome/browser/bookmarks/bookmark_model.h"
15 #include "chrome/browser/bookmarks/bookmark_model_factory.h" 16 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
16 #include "chrome/browser/favicon/favicon_service_factory.h" 17 #include "chrome/browser/favicon/favicon_service_factory.h"
17 #include "chrome/browser/favicon/favicon_util.h" 18 #include "chrome/browser/favicon/favicon_util.h"
19 #include "chrome/browser/history/select_favicon_frames.h"
18 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/common/icon_messages.h" 21 #include "chrome/common/icon_messages.h"
20 #include "content/public/browser/favicon_status.h" 22 #include "content/public/browser/favicon_status.h"
21 #include "content/public/browser/navigation_entry.h" 23 #include "content/public/browser/navigation_entry.h"
22 #include "skia/ext/image_operations.h" 24 #include "skia/ext/image_operations.h"
23 #include "ui/gfx/codec/png_codec.h" 25 #include "ui/gfx/codec/png_codec.h"
24 #include "ui/gfx/image/image.h" 26 #include "ui/gfx/image/image.h"
25 #include "ui/gfx/image/image_skia.h" 27 #include "ui/gfx/image/image_skia.h"
26 #include "ui/gfx/image/image_util.h" 28 #include "ui/gfx/image/image_util.h"
27 29
(...skipping 18 matching lines...) Expand all
46 return history::INVALID_ICON; 48 return history::INVALID_ICON;
47 } 49 }
48 50
49 bool DoUrlAndIconMatch(const FaviconURL& favicon_url, 51 bool DoUrlAndIconMatch(const FaviconURL& favicon_url,
50 const GURL& url, 52 const GURL& url,
51 history::IconType icon_type) { 53 history::IconType icon_type) {
52 return favicon_url.icon_url == url && 54 return favicon_url.icon_url == url &&
53 favicon_url.icon_type == static_cast<FaviconURL::IconType>(icon_type); 55 favicon_url.icon_type == static_cast<FaviconURL::IconType>(icon_type);
54 } 56 }
55 57
58 // Returns true if all of the icon URLs and icon types in |bitmap_results| are
59 // identical and if they match the icon URL and icon type in |favicon_url|.
60 // Returns false if |bitmap_results| is empty.
61 bool DoUrlsAndIconsMatch(
62 const FaviconURL& favicon_url,
63 const std::vector<history::FaviconBitmapResult>& bitmap_results) {
64 if (bitmap_results.empty())
65 return false;
66
67 history::IconType icon_type = ToHistoryIconType(favicon_url.icon_type);
68
69 for (size_t i = 0; i < bitmap_results.size(); ++i) {
70 if (favicon_url.icon_url != bitmap_results[i].icon_url ||
71 icon_type != bitmap_results[i].icon_type) {
72 return false;
73 }
74 }
75 return true;
76 }
77
56 std::string UrlWithoutFragment(const GURL& gurl) { 78 std::string UrlWithoutFragment(const GURL& gurl) {
57 GURL::Replacements replacements; 79 GURL::Replacements replacements;
58 replacements.ClearRef(); 80 replacements.ClearRef();
59 return gurl.ReplaceComponents(replacements).spec(); 81 return gurl.ReplaceComponents(replacements).spec();
60 } 82 }
61 83
62 bool UrlMatches(const GURL& gurl_a, const GURL& gurl_b) { 84 bool UrlMatches(const GURL& gurl_a, const GURL& gurl_b) {
63 return UrlWithoutFragment(gurl_a) == UrlWithoutFragment(gurl_b); 85 return UrlWithoutFragment(gurl_a) == UrlWithoutFragment(gurl_b);
64 } 86 }
65 87
66 // Returns true if at least one of the bitmaps in |favicon_bitmap_results| is 88 // Return true if |bitmap_result| is expired.
67 // expired. 89 bool IsExpired(const history::FaviconBitmapResult& bitmap_result) {
68 bool HasExpiredFaviconResult( 90 return bitmap_result.expired;
69 const std::vector<history::FaviconBitmapResult>& favicon_bitmap_results) { 91 }
70 for (size_t i = 0; i < favicon_bitmap_results.size(); ++i) { 92
71 if (favicon_bitmap_results[i].expired) 93 // Return true if |bitmap_result| is valid.
72 return true; 94 bool IsValid(const history::FaviconBitmapResult& bitmap_result) {
73 } 95 return bitmap_result.is_valid();
74 return false; 96 }
97
98 // Returns true if at least one of the bitmaps in |bitmap_results| is expired.
99 bool HasExpiredResult(
100 const std::vector<history::FaviconBitmapResult>& bitmap_results) {
101 std::vector<history::FaviconBitmapResult>::const_iterator it =
102 std::find_if(bitmap_results.begin(), bitmap_results.end(), IsExpired);
103 return it != bitmap_results.end();
104 }
105
106 // Returns true if at least one of |bitmap_results| is valid.
107 bool HasValidResult(
108 const std::vector<history::FaviconBitmapResult>& bitmap_results) {
109 std::vector<history::FaviconBitmapResult>::const_iterator it =
110 std::find_if(bitmap_results.begin(), bitmap_results.end(), IsValid);
111 return it != bitmap_results.end();
75 } 112 }
76 113
77 } // namespace 114 } // namespace
78 115
79 //////////////////////////////////////////////////////////////////////////////// 116 ////////////////////////////////////////////////////////////////////////////////
80 117
81 FaviconHandler::DownloadRequest::DownloadRequest() 118 FaviconHandler::DownloadRequest::DownloadRequest()
82 : icon_type(history::INVALID_ICON) { 119 : icon_type(history::INVALID_ICON) {
83 } 120 }
84 121
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 } 239 }
203 if (update_candidate) { 240 if (update_candidate) {
204 favicon_candidate_ = FaviconCandidate( 241 favicon_candidate_ = FaviconCandidate(
205 url, image_url, image, score, icon_type); 242 url, image_url, image, score, icon_type);
206 } 243 }
207 return exact_match; 244 return exact_match;
208 } 245 }
209 246
210 void FaviconHandler::SetFavicon( 247 void FaviconHandler::SetFavicon(
211 const GURL& url, 248 const GURL& url,
212 const GURL& image_url, 249 const GURL& icon_url,
213 const gfx::Image& image, 250 const gfx::Image& image,
214 history::IconType icon_type) { 251 history::IconType icon_type) {
215 SkBitmap bitmap = *(image.ToSkBitmap());
216 const gfx::Image& sized_image = (preferred_icon_size() == 0 ||
217 (preferred_icon_size() == bitmap.width() &&
218 preferred_icon_size() == bitmap.height())) ?
219 image : ResizeFaviconIfNeeded(image);
220
221 if (GetFaviconService() && ShouldSaveFavicon(url)) { 252 if (GetFaviconService() && ShouldSaveFavicon(url)) {
222 std::vector<unsigned char> image_data; 253 std::vector<unsigned char> image_data;
223 if (gfx::PNGEncodedDataFromImage(sized_image, &image_data)) 254 if (gfx::PNGEncodedDataFromImage(image, &image_data))
224 SetHistoryFavicon(url, image_url, image_data, icon_type); 255 SetHistoryFavicon(url, icon_url, image_data, icon_type);
225 } 256 }
226 257
227 if (UrlMatches(url, url_) && icon_type == history::FAVICON) { 258 if (UrlMatches(url, url_) && icon_type == history::FAVICON) {
228 NavigationEntry* entry = GetEntry(); 259 NavigationEntry* entry = GetEntry();
229 if (entry) { 260 if (entry) {
230 entry->GetFavicon().url = image_url; 261 entry->GetFavicon().url = icon_url;
231 UpdateFavicon(entry, &sized_image); 262 UpdateFavicon(entry, &image);
232 } 263 }
233 } 264 }
234 } 265 }
235 266
236 void FaviconHandler::UpdateFavicon(NavigationEntry* entry, 267 void FaviconHandler::UpdateFavicon(NavigationEntry* entry,
237 const std::vector<history::FaviconBitmapResult>& favicon_bitmap_results) { 268 const std::vector<history::FaviconBitmapResult>& favicon_bitmap_results) {
238 gfx::Image resized_image = FaviconUtil::SelectFaviconFramesFromPNGs( 269 gfx::Image resized_image = FaviconUtil::SelectFaviconFramesFromPNGs(
239 favicon_bitmap_results, 270 favicon_bitmap_results,
240 ui::GetSupportedScaleFactors(), 271 ui::GetSupportedScaleFactors(),
241 preferred_icon_size()); 272 preferred_icon_size());
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 bitmap_result.icon_type)) { 332 bitmap_result.icon_type)) {
302 return; 333 return;
303 } 334 }
304 } 335 }
305 336
306 if (got_favicon_from_history_) 337 if (got_favicon_from_history_)
307 DownloadFaviconOrAskHistory(entry->GetURL(), current_candidate()->icon_url, 338 DownloadFaviconOrAskHistory(entry->GetURL(), current_candidate()->icon_url,
308 ToHistoryIconType(current_candidate()->icon_type)); 339 ToHistoryIconType(current_candidate()->icon_type));
309 } 340 }
310 341
311 void FaviconHandler::OnDidDownloadFavicon(int id, 342 void FaviconHandler::OnDidDownloadFavicon(
312 const GURL& image_url, 343 int id,
313 bool errored, 344 const GURL& image_url,
314 const gfx::Image& image, 345 bool errored,
315 float score) { 346 int requested_size,
347 const std::vector<SkBitmap>& bitmaps) {
316 DownloadRequests::iterator i = download_requests_.find(id); 348 DownloadRequests::iterator i = download_requests_.find(id);
317 if (i == download_requests_.end()) { 349 if (i == download_requests_.end()) {
318 // Currently WebContents notifies us of ANY downloads so that it is 350 // Currently WebContents notifies us of ANY downloads so that it is
319 // possible to get here. 351 // possible to get here.
320 return; 352 return;
321 } 353 }
322 354
323 if (!i->second.callback.is_null()) { 355 if (!i->second.callback.is_null()) {
324 i->second.callback.Run(id, errored, *image.ToSkBitmap()); 356 // Find bitmap which most closely matches |requested_size| and return it in
357 // callback.
358 std::vector<gfx::Size> sizes;
359 for (size_t j = 0; j < bitmaps.size(); ++j)
360 sizes.push_back(gfx::Size(bitmaps[j].width(), bitmaps[j].height()));
361 std::vector<ui::ScaleFactor> scale_factors;
362 scale_factors.push_back(ui::SCALE_FACTOR_100P);
363 std::vector<size_t> selected_bitmap_indices;
364 SelectFaviconFrameIndices(sizes, scale_factors, requested_size,
365 &selected_bitmap_indices, NULL);
366 DCHECK_EQ(1u, selected_bitmap_indices.size());
367 size_t closest_index = selected_bitmap_indices[0];
368 i->second.callback.Run(id, errored, bitmaps[closest_index]);
325 } else if (current_candidate() && 369 } else if (current_candidate() &&
326 DoUrlAndIconMatch(*current_candidate(), image_url, 370 DoUrlAndIconMatch(*current_candidate(), image_url,
327 i->second.icon_type)) { 371 i->second.icon_type)) {
372 float score = 0.0f;
373 std::vector<ui::ScaleFactor> scale_factors = ui::GetSupportedScaleFactors();
374 gfx::Image image(SelectFaviconFrames(bitmaps, scale_factors, requested_size,
375 &score));
376
328 // The downloaded icon is still valid when there is no FaviconURL update 377 // The downloaded icon is still valid when there is no FaviconURL update
329 // during the downloading. 378 // during the downloading.
330 bool request_next_icon = true; 379 bool request_next_icon = true;
331 if (!errored) { 380 if (!errored) {
332 request_next_icon = !UpdateFaviconCandidate( 381 request_next_icon = !UpdateFaviconCandidate(
333 i->second.url, image_url, image, score, i->second.icon_type); 382 i->second.url, image_url, image, score, i->second.icon_type);
334 } 383 }
335 if (request_next_icon && GetEntry() && image_urls_.size() > 1) { 384 if (request_next_icon && GetEntry() && image_urls_.size() > 1) {
336 // Remove the first member of image_urls_ and process the remaining. 385 // Remove the first member of image_urls_ and process the remaining.
337 image_urls_.pop_front(); 386 image_urls_.pop_front();
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 std::vector<history::FaviconBitmapResult> favicon_bitmap_results, 471 std::vector<history::FaviconBitmapResult> favicon_bitmap_results,
423 history::IconURLSizesMap icon_url_sizes) { 472 history::IconURLSizesMap icon_url_sizes) {
424 NavigationEntry* entry = GetEntry(); 473 NavigationEntry* entry = GetEntry();
425 if (!entry) 474 if (!entry)
426 return; 475 return;
427 476
428 got_favicon_from_history_ = true; 477 got_favicon_from_history_ = true;
429 history_results_ = favicon_bitmap_results; 478 history_results_ = favicon_bitmap_results;
430 479
431 bool has_results = !favicon_bitmap_results.empty(); 480 bool has_results = !favicon_bitmap_results.empty();
432 favicon_expired_ = (has_results && 481 favicon_expired_ = (has_results && HasExpiredResult(favicon_bitmap_results));
433 HasExpiredFaviconResult(favicon_bitmap_results));
434 482
435 history::FaviconBitmapResult bitmap_result; 483 if (has_results && icon_types_ == history::FAVICON &&
436 if (has_results)
437 bitmap_result = favicon_bitmap_results[0];
438
439 if (has_results && bitmap_result.icon_type == history::FAVICON &&
440 !entry->GetFavicon().valid && 484 !entry->GetFavicon().valid &&
441 (!current_candidate() || 485 (!current_candidate() ||
442 DoUrlAndIconMatch(*current_candidate(), 486 DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results))) {
443 bitmap_result.icon_url, bitmap_result.icon_type))) {
444 // The db knows the favicon (although it may be out of date) and the entry 487 // The db knows the favicon (although it may be out of date) and the entry
445 // doesn't have an icon. Set the favicon now, and if the favicon turns out 488 // doesn't have an icon. Set the favicon now, and if the favicon turns out
446 // to be expired (or the wrong url) we'll fetch later on. This way the 489 // to be expired (or the wrong url) we'll fetch later on. This way the
447 // user doesn't see a flash of the default favicon. 490 // user doesn't see a flash of the default favicon.
448 entry->GetFavicon().url = bitmap_result.icon_url; 491
449 if (bitmap_result.is_valid()) 492 // The history service sends back results for a single icon URL, so it does
493 // not matter which result we get the |icon_url| from.
494 entry->GetFavicon().url = favicon_bitmap_results[0].icon_url;
495 if (HasValidResult(favicon_bitmap_results))
450 UpdateFavicon(entry, favicon_bitmap_results); 496 UpdateFavicon(entry, favicon_bitmap_results);
451 entry->GetFavicon().valid = true; 497 entry->GetFavicon().valid = true;
452 } 498 }
453 499
454 if (has_results && !bitmap_result.expired) { 500 if (has_results && !HasExpiredResult(favicon_bitmap_results)) {
455 if (current_candidate() && 501 if (current_candidate() &&
456 !DoUrlAndIconMatch(*current_candidate(), 502 !DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results)) {
457 bitmap_result.icon_url, bitmap_result.icon_type)) {
458 // Mapping in the database is wrong. DownloadFavIconOrAskHistory will 503 // Mapping in the database is wrong. DownloadFavIconOrAskHistory will
459 // update the mapping for this url and download the favicon if we don't 504 // update the mapping for this url and download the favicon if we don't
460 // already have it. 505 // already have it.
461 DownloadFaviconOrAskHistory(entry->GetURL(), 506 DownloadFaviconOrAskHistory(entry->GetURL(),
462 current_candidate()->icon_url, 507 current_candidate()->icon_url,
463 static_cast<history::IconType>(current_candidate()->icon_type)); 508 static_cast<history::IconType>(current_candidate()->icon_type));
464 } 509 }
465 } else if (current_candidate()) { 510 } else if (current_candidate()) {
466 // We know the official url for the favicon, by either don't have the 511 // We know the official url for the favicon, by either don't have the
467 // favicon or its expired. Continue on to DownloadFaviconOrAskHistory to 512 // favicon or its expired. Continue on to DownloadFaviconOrAskHistory to
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 549
505 void FaviconHandler::OnFaviconData( 550 void FaviconHandler::OnFaviconData(
506 FaviconService::Handle handle, 551 FaviconService::Handle handle,
507 std::vector<history::FaviconBitmapResult> favicon_bitmap_results, 552 std::vector<history::FaviconBitmapResult> favicon_bitmap_results,
508 history::IconURLSizesMap icon_url_sizes) { 553 history::IconURLSizesMap icon_url_sizes) {
509 NavigationEntry* entry = GetEntry(); 554 NavigationEntry* entry = GetEntry();
510 if (!entry) 555 if (!entry)
511 return; 556 return;
512 557
513 bool has_results = !favicon_bitmap_results.empty(); 558 bool has_results = !favicon_bitmap_results.empty();
514 history::FaviconBitmapResult bitmap_result;
515 if (has_results)
516 bitmap_result = favicon_bitmap_results[0];
517 559
518 // No need to update the favicon url. By the time we get here 560 // No need to update the favicon url. By the time we get here
519 // UpdateFaviconURL will have set the favicon url. 561 // UpdateFaviconURL will have set the favicon url.
520 if (has_results && bitmap_result.icon_type == history::FAVICON) { 562 if (has_results && icon_types_ == history::FAVICON) {
521 if (bitmap_result.is_valid()) { 563 if (HasValidResult(favicon_bitmap_results)) {
522 // There is a favicon, set it now. If expired we'll download the current 564 // There is a favicon, set it now. If expired we'll download the current
523 // one again, but at least the user will get some icon instead of the 565 // one again, but at least the user will get some icon instead of the
524 // default and most likely the current one is fine anyway. 566 // default and most likely the current one is fine anyway.
525 UpdateFavicon(entry, favicon_bitmap_results); 567 UpdateFavicon(entry, favicon_bitmap_results);
526 } 568 }
527 if (HasExpiredFaviconResult(favicon_bitmap_results)) { 569 if (HasExpiredResult(favicon_bitmap_results)) {
528 // The favicon is out of date. Request the current one. 570 // The favicon is out of date. Request the current one.
529 ScheduleDownload(entry->GetURL(), entry->GetFavicon().url, 571 ScheduleDownload(entry->GetURL(), entry->GetFavicon().url,
530 preferred_icon_size(), 572 preferred_icon_size(),
531 history::FAVICON, 573 history::FAVICON,
532 FaviconTabHelper::ImageDownloadCallback()); 574 FaviconTabHelper::ImageDownloadCallback());
533 } 575 }
534 } else if (current_candidate() && 576 } else if (current_candidate() &&
535 (!has_results || HasExpiredFaviconResult(favicon_bitmap_results) || 577 (!has_results || HasExpiredResult(favicon_bitmap_results) ||
536 !(DoUrlAndIconMatch(*current_candidate(), bitmap_result.icon_url, 578 !(DoUrlsAndIconsMatch(*current_candidate(), favicon_bitmap_results)))) {
537 bitmap_result.icon_type)))) {
538 // We don't know the favicon, it is out of date or its type is not same as 579 // We don't know the favicon, it is out of date or its type is not same as
539 // one got from page. Request the current one. 580 // one got from page. Request the current one.
540 ScheduleDownload(entry->GetURL(), current_candidate()->icon_url, 581 ScheduleDownload(entry->GetURL(), current_candidate()->icon_url,
541 preferred_icon_size(), 582 preferred_icon_size(),
542 ToHistoryIconType(current_candidate()->icon_type), 583 ToHistoryIconType(current_candidate()->icon_type),
543 FaviconTabHelper::ImageDownloadCallback()); 584 FaviconTabHelper::ImageDownloadCallback());
544 } 585 }
545 history_results_ = favicon_bitmap_results; 586 history_results_ = favicon_bitmap_results;
546 } 587 }
547 588
548 int FaviconHandler::ScheduleDownload( 589 int FaviconHandler::ScheduleDownload(
549 const GURL& url, 590 const GURL& url,
550 const GURL& image_url, 591 const GURL& image_url,
551 int image_size, 592 int image_size,
552 history::IconType icon_type, 593 history::IconType icon_type,
553 const FaviconTabHelper::ImageDownloadCallback& callback) { 594 const FaviconTabHelper::ImageDownloadCallback& callback) {
554 const int download_id = DownloadFavicon(image_url, image_size); 595 const int download_id = DownloadFavicon(image_url, image_size);
555 if (download_id) { 596 if (download_id) {
556 // Download ids should be unique. 597 // Download ids should be unique.
557 DCHECK(download_requests_.find(download_id) == download_requests_.end()); 598 DCHECK(download_requests_.find(download_id) == download_requests_.end());
558 download_requests_[download_id] = 599 download_requests_[download_id] =
559 DownloadRequest(url, image_url, callback, icon_type); 600 DownloadRequest(url, image_url, callback, icon_type);
560 } 601 }
561 602
562 return download_id; 603 return download_id;
563 } 604 }
564
565 gfx::Image FaviconHandler::ResizeFaviconIfNeeded(const gfx::Image& image) {
566 // Get an SkBitmap from the gfx::Image.
567 SkBitmap bitmap = *image.ToSkBitmap();
568 int width = bitmap.width();
569 int height = bitmap.height();
570 if (width > 0 && height > 0) {
571 gfx::CalculateFaviconTargetSize(&width, &height);
572 return gfx::Image(skia::ImageOperations::Resize(
573 bitmap, skia::ImageOperations::RESIZE_LANCZOS3,
574 width, height));
575 }
576
577 return image;
578 }
OLDNEW
« no previous file with comments | « chrome/browser/favicon/favicon_handler.h ('k') | chrome/browser/favicon/favicon_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698