Index: chrome/browser/favicon/favicon_handler.cc |
diff --git a/chrome/browser/favicon/favicon_handler.cc b/chrome/browser/favicon/favicon_handler.cc |
index cc19d92541f23d57081a84c2bf2027bfbd7343d1..042abc17a61c79f2d4ea48777780048f95cb6fa8 100644 |
--- a/chrome/browser/favicon/favicon_handler.cc |
+++ b/chrome/browser/favicon/favicon_handler.cc |
@@ -101,6 +101,7 @@ void FaviconHandler::FetchFavicon(const GURL& url) { |
favicon_expired_ = got_favicon_from_history_ = false; |
current_url_index_ = 0; |
urls_.clear(); |
+ favicon_candidates_.clear(); |
// Request the favicon from the history service. In parallel to this the |
// renderer is going to notify us (well TabContents) when the favicon url is |
@@ -124,12 +125,52 @@ FaviconService* FaviconHandler::GetFaviconService() { |
return profile_->GetFaviconService(Profile::EXPLICIT_ACCESS); |
} |
+void FaviconHandler::AddFaviconCandidate( |
+ const GURL& url, |
+ const GURL& image_url, |
+ const gfx::Image& image, |
+ history::IconType icon_type) { |
+ FaviconCandidate candidate; |
+ candidate.url = url; |
+ candidate.image_url = image_url; |
+ candidate.image = image; |
+ candidate.icon_type = icon_type; |
+ favicon_candidates_.push_back(candidate); |
+} |
+ |
+void FaviconHandler::SetFaviconFromCandidates() { |
+ if (favicon_candidates_.empty()) |
+ return; |
+ const int preferred_size = preferred_icon_size(); |
+ FaviconCandidates::iterator match; |
+ if (preferred_size == 0) { |
+ // No size preference, use the first icon. |
+ match = favicon_candidates_.begin(); |
+ } else { |
+ // Use the icon closest to preferred_, favoring sizes >= preferred_size. |
+ int match_size = -1; |
+ for (FaviconCandidates::iterator iter = favicon_candidates_.begin(); |
+ iter != favicon_candidates_.end(); ++iter) { |
+ FaviconCandidate& candidate = *iter; |
+ SkBitmap bitmap = *candidate.image.ToSkBitmap(); |
+ int bitmap_size = std::max(bitmap.width(), bitmap.height()); |
+ if (match_size < 0 || |
+ (bitmap_size >= preferred_size && bitmap_size < match_size) || |
+ (match_size < preferred_size && bitmap_size > match_size)) { |
+ match = iter; |
+ } |
+ } |
+ } |
+ SetFavicon(match->url, match->image_url, match->image, match->icon_type); |
+ favicon_candidates_.clear(); |
+} |
+ |
void FaviconHandler::SetFavicon( |
const GURL& url, |
const GURL& image_url, |
const gfx::Image& image, |
history::IconType icon_type) { |
- const SkBitmap& bitmap = image; |
+ SkBitmap bitmap = *image.ToSkBitmap(); |
const gfx::Image& sized_image = (preferred_icon_size() == 0 || |
(preferred_icon_size() == bitmap.width() && |
preferred_icon_size() == bitmap.height())) ? |
@@ -236,12 +277,17 @@ void FaviconHandler::OnDidDownloadFavicon(int id, |
// The downloaded icon is still valid when there is no FaviconURL update |
// during the downloading. |
if (!errored) { |
- SetFavicon(i->second.url, image_url, image, i->second.icon_type); |
- } else if (GetEntry() && ++current_url_index_ < urls_.size()) { |
- // Copies all candidate except first one and notifies the FaviconHandler, |
+ AddFaviconCandidate(i->second.url, image_url, image, i->second.icon_type); |
+ } |
+ if ((errored || preferred_icon_size() != 0) && |
+ (GetEntry() && ++current_url_index_ < urls_.size())) { |
+ // Copies all candidates except the first and notifies the FaviconHandler, |
// so the next candidate can be processed. |
std::vector<FaviconURL> new_candidates(urls_.begin() + 1, urls_.end()); |
OnUpdateFaviconURL(0, new_candidates); |
+ } else { |
+ // We have all candidates, choose one and set the favicon. |
+ SetFaviconFromCandidates(); |
} |
} |
download_requests_.erase(i); |