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

Unified Diff: chrome/browser/favicon_helper.cc

Issue 6672065: Support touch icon in FaviconHelper (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix compile error for clank mac and unit test memory leak Created 9 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/favicon_helper.h ('k') | chrome/browser/favicon_helper_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/favicon_helper.cc
diff --git a/chrome/browser/favicon_helper.cc b/chrome/browser/favicon_helper.cc
index 1e5206b4c9eed6628f4ce99d2e153b832e5808f8..6479c697be28c809506f6f629b28d987056605cd 100644
--- a/chrome/browser/favicon_helper.cc
+++ b/chrome/browser/favicon_helper.cc
@@ -20,13 +20,29 @@
#include "content/browser/tab_contents/tab_contents.h"
#include "skia/ext/image_operations.h"
#include "ui/gfx/codec/png_codec.h"
-#include "ui/gfx/favicon_size.h"
-FaviconHelper::FaviconHelper(TabContents* tab_contents)
+FaviconHelper::DownloadRequest::DownloadRequest()
+ : callback(NULL),
+ icon_type(history::INVALID_ICON) {
+}
+
+FaviconHelper::DownloadRequest::DownloadRequest(const GURL& url,
+ const GURL& image_url,
+ ImageDownloadCallback* callback,
+ history::IconType icon_type)
+ : url(url),
+ image_url(image_url),
+ callback(callback),
+ icon_type(icon_type) {
+}
+
+FaviconHelper::FaviconHelper(TabContents* tab_contents, Type icon_type)
: TabContentsObserver(tab_contents),
- got_favicon_url_(false),
got_favicon_from_history_(false),
- favicon_expired_(false) {
+ favicon_expired_(false),
+ icon_types_(icon_type == FAVICON ? history::FAVICON :
+ history::TOUCH_ICON | history::TOUCH_PRECOMPOSED_ICON),
+ current_url_index_(0) {
}
FaviconHelper::~FaviconHelper() {
@@ -46,49 +62,48 @@ void FaviconHelper::FetchFavicon(const GURL& url) {
url_ = url;
- favicon_expired_ = got_favicon_from_history_ = got_favicon_url_ = false;
+ favicon_expired_ = got_favicon_from_history_ = false;
+ current_url_index_ = 0;
+ urls_.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
// available.
if (GetFaviconService()) {
- GetFaviconService()->GetFaviconForURL(url_, history::FAVICON,
- &cancelable_consumer_,
+ GetFaviconForURL(url_, icon_types_, &cancelable_consumer_,
NewCallback(this, &FaviconHelper::OnFaviconDataForInitialURL));
}
}
int FaviconHelper::DownloadImage(const GURL& image_url,
int image_size,
+ history::IconType icon_type,
ImageDownloadCallback* callback) {
DCHECK(callback); // Must provide a callback.
- return ScheduleDownload(GURL(), image_url, image_size, callback);
-}
-
-Profile* FaviconHelper::profile() {
- return tab_contents()->profile();
+ return ScheduleDownload(GURL(), image_url, image_size, icon_type, callback);
}
FaviconService* FaviconHelper::GetFaviconService() {
- return profile()->GetFaviconService(Profile::EXPLICIT_ACCESS);
+ return tab_contents()->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS);
}
void FaviconHelper::SetFavicon(
const GURL& url,
const GURL& image_url,
- const SkBitmap& image) {
- const SkBitmap& sized_image =
- (image.width() == kFaviconSize && image.height() == kFaviconSize)
- ? image : ConvertToFaviconSize(image);
+ const SkBitmap& image,
+ history::IconType icon_type) {
+ const SkBitmap& sized_image = (preferred_icon_size() == 0 ||
+ (preferred_icon_size() == image.width() &&
+ preferred_icon_size() == image.height())) ?
+ image : ConvertToFaviconSize(image);
if (GetFaviconService() && ShouldSaveFavicon(url)) {
std::vector<unsigned char> image_data;
gfx::PNGCodec::EncodeBGRASkBitmap(sized_image, false, &image_data);
- GetFaviconService()->SetFavicon(url, image_url, image_data,
- history::FAVICON);
+ SetHistoryFavicon(url, image_url, image_data, icon_type);
}
- if (url == url_) {
+ if (url == url_ && icon_type == history::FAVICON) {
NavigationEntry* entry = GetEntry();
if (entry)
UpdateFavicon(entry, sized_image);
@@ -114,41 +129,138 @@ void FaviconHelper::UpdateFavicon(NavigationEntry* entry,
tab_contents()->NotifyNavigationStateChanged(TabContents::INVALIDATE_TAB);
}
-void FaviconHelper::OnUpdateFaviconURL(int32 page_id, const GURL& icon_url) {
- // TODO(davemoore) Should clear on empty url. Currently we ignore it.
- // This appears to be what FF does as well.
- if (icon_url.is_empty())
- return;
-
+void FaviconHelper::OnUpdateFaviconURL(
+ int32 page_id,
+ const std::vector<FaviconURL>& candidates) {
NavigationEntry* entry = GetEntry();
if (!entry)
return;
- got_favicon_url_ = true;
+ bool got_favicon_url_update = false;
+ for (std::vector<FaviconURL>::const_iterator i = candidates.begin();
+ i != candidates.end(); ++i) {
+ if (!i->icon_url.is_empty() && (i->icon_type & icon_types_)) {
+ if (!got_favicon_url_update) {
+ got_favicon_url_update = true;
+ urls_.clear();
+ current_url_index_ = 0;
+ }
+ urls_.push_back(*i);
+ }
+ }
+
+ // TODO(davemoore) Should clear on empty url. Currently we ignore it.
+ // This appears to be what FF does as well.
+ // No URL was added.
+ if (!got_favicon_url_update)
+ return;
if (!GetFaviconService())
return;
- if (!favicon_expired_ && entry->favicon().is_valid() &&
- entry->favicon().url() == icon_url) {
- // We already have the icon, no need to proceed.
+ // For FAVICON.
+ if (current_candidate()->icon_type == ::FAVICON) {
+ if (!favicon_expired_ && entry->favicon().is_valid() &&
+ do_url_and_icon_match(*current_candidate(), entry->favicon().url(),
+ history::FAVICON))
+ return;
+
+ entry->favicon().set_url(current_candidate()->icon_url);
+ } else if (!favicon_expired_ && got_favicon_from_history_ &&
+ history_icon_.is_valid() &&
+ do_url_and_icon_match(*current_candidate(),
+ history_icon_.icon_url, history_icon_.icon_type)) {
return;
}
- entry->favicon().set_url(icon_url);
-
if (got_favicon_from_history_)
- DownloadFaviconOrAskHistory(entry);
+ DownloadFaviconOrAskHistory(entry->url(), current_candidate()->icon_url,
+ ToHistoryIconType(current_candidate()->icon_type));
+}
+
+NavigationEntry* FaviconHelper::GetEntry() {
+ NavigationEntry* entry = tab_contents()->controller().GetActiveEntry();
+ if (entry && entry->url() == url_ &&
+ tab_contents()->IsActiveEntry(entry->page_id())) {
+ return entry;
+ }
+ // If the URL has changed out from under us (as will happen with redirects)
+ // return NULL.
+ return NULL;
+}
+
+int FaviconHelper::DownloadFavicon(const GURL& image_url, int image_size) {
+ return tab_contents()->render_view_host()->DownloadFavicon(image_url,
+ image_size);
+}
+
+void FaviconHelper::UpdateFaviconMappingAndFetch(
+ const GURL& page_url,
+ const GURL& icon_url,
+ history::IconType icon_type,
+ CancelableRequestConsumerBase* consumer,
+ FaviconService::FaviconDataCallback* callback) {
+ GetFaviconService()->UpdateFaviconMappingAndFetch(page_url, icon_url,
+ icon_type, consumer, callback);
+}
+
+void FaviconHelper::GetFavicon(
+ const GURL& icon_url,
+ history::IconType icon_type,
+ CancelableRequestConsumerBase* consumer,
+ FaviconService::FaviconDataCallback* callback) {
+ GetFaviconService()->GetFavicon(icon_url, icon_type, consumer, callback);
+}
+
+void FaviconHelper::GetFaviconForURL(
+ const GURL& page_url,
+ int icon_types,
+ CancelableRequestConsumerBase* consumer,
+ FaviconService::FaviconDataCallback* callback) {
+ GetFaviconService()->GetFaviconForURL(page_url, icon_types, consumer,
+ callback);
+}
+
+void FaviconHelper::SetHistoryFavicon(
+ const GURL& page_url,
+ const GURL& icon_url,
+ const std::vector<unsigned char>& image_data,
+ history::IconType icon_type) {
+ GetFaviconService()->SetFavicon(page_url, icon_url, image_data, icon_type);
+}
+
+bool FaviconHelper::ShouldSaveFavicon(const GURL& url) {
+ if (!tab_contents()->profile()->IsOffTheRecord())
+ return true;
+
+ // Otherwise store the favicon if the page is bookmarked.
+ BookmarkModel* bookmark_model = tab_contents()->profile()->GetBookmarkModel();
+ return bookmark_model && bookmark_model->IsBookmarked(url);
+}
+
+history::IconType FaviconHelper::ToHistoryIconType(IconType icon_type) {
+ switch (icon_type) {
+ case ::FAVICON:
+ return history::FAVICON;
+ case ::TOUCH_ICON:
+ return history::TOUCH_ICON;
+ case ::TOUCH_PRECOMPOSED_ICON:
+ return history::TOUCH_PRECOMPOSED_ICON;
+ case ::INVALID_ICON:
+ return history::INVALID_ICON;
+ }
+ NOTREACHED();
+ // Shouldn't reach here, just make compiler happy.
+ return history::INVALID_ICON;
}
bool FaviconHelper::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
+ bool message_handled = true;
IPC_BEGIN_MESSAGE_MAP(FaviconHelper, message)
- IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFaviconURL, OnUpdateFaviconURL)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidDownloadFavicon, OnDidDownloadFavicon)
- IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_MESSAGE_UNHANDLED(message_handled = false)
IPC_END_MESSAGE_MAP()
- return handled;
+ return message_handled;
}
void FaviconHelper::OnDidDownloadFavicon(int id,
@@ -164,24 +276,23 @@ void FaviconHelper::OnDidDownloadFavicon(int id,
if (i->second.callback) {
i->second.callback->Run(id, errored, image);
- } else if (!errored) {
- SetFavicon(i->second.url, image_url, image);
+ } else if (current_candidate() &&
+ do_url_and_icon_match(*current_candidate(), image_url,
+ i->second.icon_type)) {
+ // 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 FaviconHelper,
+ // so the next candidate can be processed.
+ std::vector<FaviconURL> new_candidates(++urls_.begin(), urls_.end());
+ OnUpdateFaviconURL(0, new_candidates);
+ }
}
-
download_requests_.erase(i);
}
-NavigationEntry* FaviconHelper::GetEntry() {
- NavigationEntry* entry = tab_contents()->controller().GetActiveEntry();
- if (entry && entry->url() == url_ &&
- tab_contents()->IsActiveEntry(entry->page_id())) {
- return entry;
- }
- // If the URL has changed out from under us (as will happen with redirects)
- // return NULL.
- return NULL;
-}
-
void FaviconHelper::OnFaviconDataForInitialURL(
FaviconService::Handle handle,
history::FaviconData favicon) {
@@ -190,11 +301,14 @@ void FaviconHelper::OnFaviconDataForInitialURL(
return;
got_favicon_from_history_ = true;
+ history_icon_ = favicon;
favicon_expired_ = (favicon.known_icon && favicon.expired);
- if (favicon.known_icon && !entry->favicon().is_valid() &&
- (!got_favicon_url_ || entry->favicon().url() == favicon.icon_url)) {
+ if (favicon.known_icon && favicon.icon_type == history::FAVICON &&
+ !entry->favicon().is_valid() &&
+ (!current_candidate() || do_url_and_icon_match(*current_candidate(),
+ favicon.icon_url, favicon.icon_type))) {
// The db knows the favicon (although it may be out of date) and the entry
// doesn't have an icon. Set the favicon now, and if the favicon turns out
// to be expired (or the wrong url) we'll fetch later on. This way the
@@ -206,36 +320,39 @@ void FaviconHelper::OnFaviconDataForInitialURL(
}
if (favicon.known_icon && !favicon.expired) {
- if (got_favicon_url_ && entry->favicon().url() != favicon.icon_url) {
- // Mapping in the database is wrong. DownloadFaviconOrAskHistory will
+ if (current_candidate() && !do_url_and_icon_match(*current_candidate(),
+ favicon.icon_url, favicon.icon_type)) {
+ // Mapping in the database is wrong. DownloadFavIconOrAskHistory will
// update the mapping for this url and download the favicon if we don't
// already have it.
- DownloadFaviconOrAskHistory(entry);
+ DownloadFaviconOrAskHistory(entry->url(), current_candidate()->icon_url,
+ static_cast<history::IconType>(current_candidate()->icon_type));
}
- } else if (got_favicon_url_) {
+ } else if (current_candidate()) {
// We know the official url for the favicon, by either don't have the
// favicon or its expired. Continue on to DownloadFaviconOrAskHistory to
// either download or check history again.
- DownloadFaviconOrAskHistory(entry);
+ DownloadFaviconOrAskHistory(entry->url(), current_candidate()->icon_url,
+ ToHistoryIconType(current_candidate()->icon_type));
}
// else we haven't got the icon url. When we get it we'll ask the
// renderer to download the icon.
}
-void FaviconHelper::DownloadFaviconOrAskHistory(NavigationEntry* entry) {
- DCHECK(entry); // We should only get here if entry is valid.
+void FaviconHelper::DownloadFaviconOrAskHistory(
+ const GURL& page_url,
+ const GURL& icon_url,
+ history::IconType icon_type) {
if (favicon_expired_) {
// We have the mapping, but the favicon is out of date. Download it now.
- ScheduleDownload(entry->url(), entry->favicon().url(), kFaviconSize, NULL);
+ ScheduleDownload(page_url, icon_url, preferred_icon_size(), icon_type,
+ NULL);
} else if (GetFaviconService()) {
// We don't know the favicon, but we may have previously downloaded the
// favicon for another page that shares the same favicon. Ask for the
// favicon given the favicon URL.
- if (profile()->IsOffTheRecord()) {
- GetFaviconService()->GetFavicon(
- entry->favicon().url(),
- history::FAVICON,
- &cancelable_consumer_,
+ if (tab_contents()->profile()->IsOffTheRecord()) {
+ GetFavicon(icon_url, icon_type, &cancelable_consumer_,
NewCallback(this, &FaviconHelper::OnFaviconData));
} else {
// Ask the history service for the icon. This does two things:
@@ -244,50 +361,58 @@ void FaviconHelper::DownloadFaviconOrAskHistory(NavigationEntry* entry) {
// include the mapping between the page url and the favicon url.
// This is asynchronous. The history service will call back when done.
// Issue the request and associate the current page ID with it.
- GetFaviconService()->UpdateFaviconMappingAndFetch(
- entry->url(),
- entry->favicon().url(),
- history::FAVICON,
+ UpdateFaviconMappingAndFetch(page_url, icon_url, icon_type,
&cancelable_consumer_,
NewCallback(this, &FaviconHelper::OnFaviconData));
}
}
}
-void FaviconHelper::OnFaviconData(
- FaviconService::Handle handle,
- history::FaviconData favicon) {
+void FaviconHelper::OnFaviconData(FaviconService::Handle handle,
+ history::FaviconData favicon) {
NavigationEntry* entry = GetEntry();
if (!entry)
return;
// No need to update the favicon url. By the time we get here
// UpdateFaviconURL will have set the favicon url.
-
- if (favicon.is_valid()) {
- // There is a favicon, set it now. If expired we'll download the current
- // one again, but at least the user will get some icon instead of the
- // default and most likely the current one is fine anyway.
- UpdateFavicon(entry, favicon.image_data);
- }
-
- if (!favicon.known_icon || favicon.expired) {
- // We don't know the favicon, or it is out of date. Request the current one.
- ScheduleDownload(entry->url(), entry->favicon().url(), kFaviconSize, NULL);
+ if (favicon.icon_type == history::FAVICON) {
+ if (favicon.is_valid()) {
+ // There is a favicon, set it now. If expired we'll download the current
+ // one again, but at least the user will get some icon instead of the
+ // default and most likely the current one is fine anyway.
+ UpdateFavicon(entry, favicon.image_data);
+ }
+ if (!favicon.known_icon || favicon.expired) {
+ // We don't know the favicon, or it is out of date. Request the current
+ // one.
+ ScheduleDownload(entry->url(), entry->favicon().url(),
+ preferred_icon_size(),
+ history::FAVICON, NULL);
+ }
+ } else if (current_candidate() && (!favicon.known_icon || favicon.expired ||
+ !(do_url_and_icon_match(*current_candidate(), favicon.icon_url,
+ favicon.icon_type)))) {
+ // We don't know the favicon, it is out of date or its type is not same as
+ // one got from page. Request the current one.
+ ScheduleDownload(entry->url(), current_candidate()->icon_url,
+ preferred_icon_size(),
+ ToHistoryIconType(current_candidate()->icon_type), NULL);
}
+ history_icon_ = favicon;
}
int FaviconHelper::ScheduleDownload(const GURL& url,
const GURL& image_url,
int image_size,
+ history::IconType icon_type,
ImageDownloadCallback* callback) {
- const int download_id = tab_contents()->render_view_host()->DownloadFavicon(
- image_url, image_size);
-
+ const int download_id = DownloadFavicon(image_url, image_size);
if (download_id) {
// Download ids should be unique.
DCHECK(download_requests_.find(download_id) == download_requests_.end());
- download_requests_[download_id] = DownloadRequest(url, image_url, callback);
+ download_requests_[download_id] =
+ DownloadRequest(url, image_url, callback, icon_type);
}
return download_id;
@@ -304,12 +429,3 @@ SkBitmap FaviconHelper::ConvertToFaviconSize(const SkBitmap& image) {
}
return image;
}
-
-bool FaviconHelper::ShouldSaveFavicon(const GURL& url) {
- if (!profile()->IsOffTheRecord())
- return true;
-
- // Otherwise store the favicon if the page is bookmarked.
- BookmarkModel* bookmark_model = profile()->GetBookmarkModel();
- return bookmark_model && bookmark_model->IsBookmarked(url);
-}
« no previous file with comments | « chrome/browser/favicon_helper.h ('k') | chrome/browser/favicon_helper_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698