Chromium Code Reviews| 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..f6f3e54d1aa432328462781724902248b6862889 100644 |
| --- a/chrome/browser/favicon/favicon_handler.cc |
| +++ b/chrome/browser/favicon/favicon_handler.cc |
| @@ -51,6 +51,8 @@ bool DoUrlAndIconMatch(const FaviconURL& favicon_url, |
| } // namespace |
| +//////////////////////////////////////////////////////////////////////////////// |
| + |
| FaviconHandler::DownloadRequest::DownloadRequest() |
| : icon_type(history::INVALID_ICON) { |
| } |
| @@ -69,6 +71,28 @@ FaviconHandler::DownloadRequest::DownloadRequest( |
| icon_type(icon_type) { |
| } |
| +//////////////////////////////////////////////////////////////////////////////// |
| + |
| +FaviconHandler::FaviconCandidate::FaviconCandidate() |
| + : icon_type(history::INVALID_ICON) { |
| +} |
| + |
| +FaviconHandler::FaviconCandidate::~FaviconCandidate() { |
| +} |
| + |
| +FaviconHandler::FaviconCandidate::FaviconCandidate( |
| + const GURL& url, |
| + const GURL& image_url, |
| + const gfx::Image& image, |
| + history::IconType icon_type) |
| + : url(url), |
| + image_url(image_url), |
| + image(image), |
| + icon_type(icon_type) { |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| + |
| FaviconHandler::FaviconHandler(Profile* profile, |
| FaviconHandlerDelegate* delegate, |
| Type icon_type) |
| @@ -101,6 +125,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 +149,42 @@ FaviconService* FaviconHandler::GetFaviconService() { |
| return profile_->GetFaviconService(Profile::EXPLICIT_ACCESS); |
| } |
| +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_size, 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; |
| + match_size = bitmap_size; |
| + if (bitmap_size == preferred_size) |
| + break; |
| + } |
| + } |
| + } |
| + 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())) ? |
| @@ -143,8 +198,10 @@ void FaviconHandler::SetFavicon( |
| if (url == url_ && icon_type == history::FAVICON) { |
| NavigationEntry* entry = GetEntry(); |
| - if (entry) |
| + if (entry) { |
| + entry->GetFavicon().url = image_url; |
| UpdateFavicon(entry, &sized_image); |
| + } |
| } |
| } |
| @@ -236,12 +293,18 @@ 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, |
| + favicon_candidates_.push_back(FaviconCandidate( |
| + i->second.url, image_url, image, i->second.icon_type)); |
|
michaelbai
2012/03/14 22:34:14
Would you like stop fetch the rest of icons if the
stevenjb
2012/03/15 00:45:53
Yes that would be better. I thought of this but di
michaelbai
2012/03/15 01:12:00
It seemed you don't need favicon_candidates_ vecto
stevenjb
2012/03/15 21:05:10
That's a fair point. I did another round of re-fac
|
| + } |
| + 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); |