diff options
Diffstat (limited to 'chrome/browser')
41 files changed, 889 insertions, 509 deletions
diff --git a/chrome/browser/bookmarks/bookmark_html_writer.cc b/chrome/browser/bookmarks/bookmark_html_writer.cc index 9bbd49d..501bed3 100644 --- a/chrome/browser/bookmarks/bookmark_html_writer.cc +++ b/chrome/browser/bookmarks/bookmark_html_writer.cc @@ -31,6 +31,7 @@ #include "net/base/file_stream.h" #include "net/base/net_errors.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/favicon_size.h" using content::BrowserThread; @@ -460,7 +461,8 @@ bool BookmarkFaviconFetcher::FetchNextFavicon() { if (favicons_map_->end() == iter) { FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( profile_, Profile::EXPLICIT_ACCESS); - favicon_service->GetFaviconForURL(profile_, GURL(url), history::FAVICON, + favicon_service->GetRawFaviconForURL(profile_, GURL(url), + history::FAVICON, gfx::kFaviconSize, ui::SCALE_FACTOR_100P, &favicon_consumer_, base::Bind(&BookmarkFaviconFetcher::OnFaviconDataAvailable, base::Unretained(this))); @@ -474,14 +476,15 @@ bool BookmarkFaviconFetcher::FetchNextFavicon() { void BookmarkFaviconFetcher::OnFaviconDataAvailable( FaviconService::Handle handle, - history::FaviconData favicon) { + const history::FaviconBitmapResult& bitmap_result) { GURL url; if (!bookmark_urls_.empty()) { url = GURL(bookmark_urls_.front()); bookmark_urls_.pop_front(); } - if (favicon.is_valid() && !url.is_empty()) { - favicons_map_->insert(make_pair(url.spec(), favicon.image_data)); + if (bitmap_result.is_valid() && !url.is_empty()) { + favicons_map_->insert( + make_pair(url.spec(), bitmap_result.bitmap_data)); } if (FetchNextFavicon()) { diff --git a/chrome/browser/bookmarks/bookmark_html_writer.h b/chrome/browser/bookmarks/bookmark_html_writer.h index 0eaf637..0b94e9e 100644 --- a/chrome/browser/bookmarks/bookmark_html_writer.h +++ b/chrome/browser/bookmarks/bookmark_html_writer.h @@ -64,8 +64,9 @@ class BookmarkFaviconFetcher: public content::NotificationObserver { // Favicon fetch callback. After all favicons are fetched executes // html output on the file thread. - void OnFaviconDataAvailable(FaviconService::Handle handle, - history::FaviconData favicon); + void OnFaviconDataAvailable( + FaviconService::Handle handle, + const history::FaviconBitmapResult& bitmap_result); // The Profile object used for accessing FaviconService, bookmarks model. Profile* profile_; diff --git a/chrome/browser/bookmarks/bookmark_model.cc b/chrome/browser/bookmarks/bookmark_model.cc index fcdea2f..30d361b 100644 --- a/chrome/browser/bookmarks/bookmark_model.cc +++ b/chrome/browser/bookmarks/bookmark_model.cc @@ -29,6 +29,7 @@ #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_collator.h" +#include "ui/gfx/favicon_size.h" #include "ui/gfx/image/image_util.h" using base::Time; @@ -777,21 +778,16 @@ BookmarkPermanentNode* BookmarkModel::CreatePermanentNode( void BookmarkModel::OnFaviconDataAvailable( FaviconService::Handle handle, - history::FaviconData favicon) { + const history::FaviconImageResult& image_result) { BookmarkNode* node = load_consumer_.GetClientData( FaviconServiceFactory::GetForProfile( profile_, Profile::EXPLICIT_ACCESS), handle); DCHECK(node); node->set_favicon_load_handle(0); - if (favicon.is_valid()) { - scoped_ptr<gfx::Image> favicon_image( - gfx::ImageFromPNGEncodedData(favicon.image_data->front(), - favicon.image_data->size())); - if (favicon_image.get()) { - node->set_favicon(*favicon_image.get()); - FaviconLoaded(node); - } + if (!image_result.image.IsEmpty()) { + node->set_favicon(image_result.image); + FaviconLoaded(node); } } @@ -804,8 +800,9 @@ void BookmarkModel::LoadFavicon(BookmarkNode* node) { profile_, Profile::EXPLICIT_ACCESS); if (!favicon_service) return; - FaviconService::Handle handle = favicon_service->GetFaviconForURL( - profile_, node->url(), history::FAVICON, &load_consumer_, + FaviconService::Handle handle = favicon_service->GetFaviconImageForURL( + profile_, node->url(), history::FAVICON, gfx::kFaviconSize, + &load_consumer_, base::Bind(&BookmarkModel::OnFaviconDataAvailable, base::Unretained(this))); load_consumer_.SetClientData(favicon_service, handle, node); diff --git a/chrome/browser/bookmarks/bookmark_model.h b/chrome/browser/bookmarks/bookmark_model.h index 1da7c74..a3a41e2 100644 --- a/chrome/browser/bookmarks/bookmark_model.h +++ b/chrome/browser/bookmarks/bookmark_model.h @@ -414,8 +414,9 @@ class BookmarkModel : public content::NotificationObserver, // Notification that a favicon has finished loading. If we can decode the // favicon, FaviconLoaded is invoked. - void OnFaviconDataAvailable(FaviconService::Handle handle, - history::FaviconData favicon); + void OnFaviconDataAvailable( + FaviconService::Handle handle, + const history::FaviconImageResult& image_result); // Invoked from the node to load the favicon. Requests the favicon from the // favicon service. diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc index 71f8d41..1494de9 100644 --- a/chrome/browser/extensions/extension_web_ui.cc +++ b/chrome/browser/extensions/extension_web_ui.cc @@ -105,37 +105,44 @@ class ExtensionWebUIImageLoadingTracker : public ImageLoadingTracker::Observer { gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize), ImageLoadingTracker::DONT_CACHE); } else { - ForwardResult(NULL); + ForwardResult(gfx::Image()); } } virtual void OnImageLoaded(const gfx::Image& image, const std::string& extension_id, int index) OVERRIDE { - if (!image.IsEmpty()) { - std::vector<unsigned char> image_data; - if (!gfx::PNGCodec::EncodeBGRASkBitmap(*image.ToSkBitmap(), false, - &image_data)) { - NOTREACHED() << "Could not encode extension favicon"; - } - ForwardResult(base::RefCountedBytes::TakeVector(&image_data)); - } else { - ForwardResult(NULL); - } + ForwardResult(image); } private: ~ExtensionWebUIImageLoadingTracker() {} - // Forwards the result on the request. If no favicon was available then - // |icon_data| may be backed by NULL. Once the result has been forwarded the - // instance is deleted. - void ForwardResult(scoped_refptr<base::RefCountedMemory> icon_data) { - history::FaviconData favicon; - favicon.known_icon = icon_data.get() != NULL && icon_data->size() > 0; - favicon.image_data = icon_data; - favicon.icon_type = history::FAVICON; - request_->ForwardResultAsync(request_->handle(), favicon); + // Forwards the result of the request. If no favicon was available then + // |icon| will be empty. Once the result has been forwarded the instance is + // deleted. + void ForwardResult(const gfx::Image& icon) { + std::vector<history::FaviconBitmapResult> favicon_bitmap_results; + SkBitmap icon_bitmap = icon.AsBitmap(); + if (!icon_bitmap.empty()) { + scoped_refptr<base::RefCountedBytes> icon_data( + new base::RefCountedBytes()); + if (gfx::PNGCodec::EncodeBGRASkBitmap(icon_bitmap, false, + &icon_data->data())) { + history::FaviconBitmapResult bitmap_result; + bitmap_result.bitmap_data = icon_data; + bitmap_result.pixel_size = gfx::Size(icon_bitmap.width(), + icon_bitmap.height()); + bitmap_result.icon_type = history::FAVICON; + + favicon_bitmap_results.push_back(bitmap_result); + } else { + NOTREACHED() << "Could not encode extension favicon"; + } + } + + request_->ForwardResultAsync(request_->handle(), favicon_bitmap_results, + history::IconURLSizesMap()); delete this; } diff --git a/chrome/browser/favicon/favicon_handler.cc b/chrome/browser/favicon/favicon_handler.cc index 49adcd6..dc2b228 100644 --- a/chrome/browser/favicon/favicon_handler.cc +++ b/chrome/browser/favicon/favicon_handler.cc @@ -61,6 +61,17 @@ bool UrlMatches(const GURL& gurl_a, const GURL& gurl_b) { return UrlWithoutFragment(gurl_a) == UrlWithoutFragment(gurl_b); } +// Returns true if at least one of the bitmaps in |favicon_bitmap_results| is +// expired. +bool HasExpiredFaviconResult( + const std::vector<history::FaviconBitmapResult>& favicon_bitmap_results) { + for (size_t i = 0; i < favicon_bitmap_results.size(); ++i) { + if (favicon_bitmap_results[i].expired) + return true; + } + return false; +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -278,11 +289,13 @@ void FaviconHandler::ProcessCurrentUrl() { entry->GetFavicon().url = current_candidate()->icon_url; } else if (!favicon_expired_ && got_favicon_from_history_ && - history_icon_.is_valid() && - DoUrlAndIconMatch( - *current_candidate(), - history_icon_.icon_url, history_icon_.icon_type)) { - return; + !history_results_.empty()) { + const history::FaviconBitmapResult& bitmap_result = history_results_[0]; + if (bitmap_result.is_valid() && + DoUrlAndIconMatch(*current_candidate(), bitmap_result.icon_url, + bitmap_result.icon_type)) { + return; + } } if (got_favicon_from_history_) @@ -356,7 +369,7 @@ void FaviconHandler::UpdateFaviconMappingAndFetch( const GURL& icon_url, history::IconType icon_type, CancelableRequestConsumerBase* consumer, - const FaviconService::FaviconDataCallback& callback) { + const FaviconService::FaviconResultsCallback& callback) { GetFaviconService()->UpdateFaviconMappingAndFetch(page_url, icon_url, icon_type, consumer, callback); } @@ -365,17 +378,19 @@ void FaviconHandler::GetFavicon( const GURL& icon_url, history::IconType icon_type, CancelableRequestConsumerBase* consumer, - const FaviconService::FaviconDataCallback& callback) { - GetFaviconService()->GetFavicon(icon_url, icon_type, consumer, callback); + const FaviconService::FaviconResultsCallback& callback) { + GetFaviconService()->GetFavicon(icon_url, icon_type, preferred_icon_size(), + ui::GetSupportedScaleFactors(), consumer, callback); } void FaviconHandler::GetFaviconForURL( const GURL& page_url, int icon_types, CancelableRequestConsumerBase* consumer, - const FaviconService::FaviconDataCallback& callback) { + const FaviconService::FaviconResultsCallback& callback) { GetFaviconService()->GetFaviconForURL(profile_, page_url, icon_types, - consumer, callback); + preferred_icon_size(), ui::GetSupportedScaleFactors(), consumer, + callback); } void FaviconHandler::SetHistoryFavicon( @@ -398,35 +413,42 @@ bool FaviconHandler::ShouldSaveFavicon(const GURL& url) { void FaviconHandler::OnFaviconDataForInitialURL( FaviconService::Handle handle, - history::FaviconData favicon) { + std::vector<history::FaviconBitmapResult> favicon_bitmap_results, + history::IconURLSizesMap icon_url_sizes) { NavigationEntry* entry = GetEntry(); if (!entry) return; got_favicon_from_history_ = true; - history_icon_ = favicon; + history_results_ = favicon_bitmap_results; + + bool has_results = !favicon_bitmap_results.empty(); + favicon_expired_ = (has_results && + HasExpiredFaviconResult(favicon_bitmap_results)); - favicon_expired_ = (favicon.known_icon && favicon.expired); + history::FaviconBitmapResult bitmap_result; + if (has_results) + bitmap_result = favicon_bitmap_results[0]; - if (favicon.known_icon && favicon.icon_type == history::FAVICON && + if (has_results && bitmap_result.icon_type == history::FAVICON && !entry->GetFavicon().valid && (!current_candidate() || - DoUrlAndIconMatch( - *current_candidate(), favicon.icon_url, favicon.icon_type))) { + DoUrlAndIconMatch(*current_candidate(), + bitmap_result.icon_url, bitmap_result.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 // user doesn't see a flash of the default favicon. - entry->GetFavicon().url = favicon.icon_url; - if (favicon.is_valid()) - UpdateFavicon(entry, favicon.image_data); + entry->GetFavicon().url = bitmap_result.icon_url; + if (bitmap_result.is_valid()) + UpdateFavicon(entry, bitmap_result.bitmap_data); entry->GetFavicon().valid = true; } - if (favicon.known_icon && !favicon.expired) { + if (has_results && !bitmap_result.expired) { if (current_candidate() && - !DoUrlAndIconMatch( - *current_candidate(), favicon.icon_url, favicon.icon_type)) { + !DoUrlAndIconMatch(*current_candidate(), + bitmap_result.icon_url, bitmap_result.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. @@ -474,32 +496,39 @@ void FaviconHandler::DownloadFaviconOrAskHistory( } } -void FaviconHandler::OnFaviconData(FaviconService::Handle handle, - history::FaviconData favicon) { +void FaviconHandler::OnFaviconData( + FaviconService::Handle handle, + std::vector<history::FaviconBitmapResult> favicon_bitmap_results, + history::IconURLSizesMap icon_url_sizes) { NavigationEntry* entry = GetEntry(); if (!entry) return; + bool has_results = !favicon_bitmap_results.empty(); + history::FaviconBitmapResult bitmap_result; + if (has_results) + bitmap_result = favicon_bitmap_results[0]; + // No need to update the favicon url. By the time we get here // UpdateFaviconURL will have set the favicon url. - if (favicon.icon_type == history::FAVICON) { - if (favicon.is_valid()) { + if (has_results && bitmap_result.icon_type == history::FAVICON) { + if (bitmap_result.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); + UpdateFavicon(entry, bitmap_result.bitmap_data); } - if (!favicon.known_icon || favicon.expired) { - // We don't know the favicon, or it is out of date. Request the current - // one. + if (HasExpiredFaviconResult(favicon_bitmap_results)) { + // The favicon is out of date. Request the current one. ScheduleDownload(entry->GetURL(), entry->GetFavicon().url, preferred_icon_size(), history::FAVICON, FaviconTabHelper::ImageDownloadCallback()); } - } else if (current_candidate() && (!favicon.known_icon || favicon.expired || - !(DoUrlAndIconMatch( - *current_candidate(), favicon.icon_url, favicon.icon_type)))) { + } else if (current_candidate() && + (!has_results || HasExpiredFaviconResult(favicon_bitmap_results) || + !(DoUrlAndIconMatch(*current_candidate(), bitmap_result.icon_url, + bitmap_result.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->GetURL(), current_candidate()->icon_url, @@ -507,7 +536,7 @@ void FaviconHandler::OnFaviconData(FaviconService::Handle handle, ToHistoryIconType(current_candidate()->icon_type), FaviconTabHelper::ImageDownloadCallback()); } - history_icon_ = favicon; + history_results_ = favicon_bitmap_results; } int FaviconHandler::ScheduleDownload( diff --git a/chrome/browser/favicon/favicon_handler.h b/chrome/browser/favicon/favicon_handler.h index 02b2f81..ec215f4 100644 --- a/chrome/browser/favicon/favicon_handler.h +++ b/chrome/browser/favicon/favicon_handler.h @@ -138,19 +138,19 @@ class FaviconHandler { const GURL& icon_url, history::IconType icon_type, CancelableRequestConsumerBase* consumer, - const FaviconService::FaviconDataCallback& callback); + const FaviconService::FaviconResultsCallback& callback); virtual void GetFavicon( const GURL& icon_url, history::IconType icon_type, CancelableRequestConsumerBase* consumer, - const FaviconService::FaviconDataCallback& callback); + const FaviconService::FaviconResultsCallback& callback); virtual void GetFaviconForURL( const GURL& page_url, int icon_types, CancelableRequestConsumerBase* consumer, - const FaviconService::FaviconDataCallback& callback); + const FaviconService::FaviconResultsCallback& callback); virtual void SetHistoryFavicon(const GURL& page_url, const GURL& icon_url, @@ -198,8 +198,10 @@ class FaviconHandler { }; // See description above class for details. - void OnFaviconDataForInitialURL(FaviconService::Handle handle, - history::FaviconData favicon); + void OnFaviconDataForInitialURL( + FaviconService::Handle handle, + std::vector<history::FaviconBitmapResult> favicon_bitmap_results, + history::IconURLSizesMap icon_url_sizes); // If the favicon has expired, asks the renderer to download the favicon. // Otherwise asks history to update the mapping between page url and icon @@ -209,8 +211,10 @@ class FaviconHandler { history::IconType icon_type); // See description above class for details. - void OnFaviconData(FaviconService::Handle handle, - history::FaviconData favicon); + void OnFaviconData( + FaviconService::Handle handle, + std::vector<history::FaviconBitmapResult> favicon_bitmap_results, + history::IconURLSizesMap icon_url_sizes); // Schedules a download for the specified entry. This adds the request to // download_requests_. @@ -285,8 +289,8 @@ class FaviconHandler { // The prioritized favicon candidates from the page back from the renderer. std::deque<FaviconURL> image_urls_; - // The FaviconData from history. - history::FaviconData history_icon_; + // The FaviconBitmapResults from history. + std::vector<history::FaviconBitmapResult> history_results_; // The Profile associated with this handler. Profile* profile_; diff --git a/chrome/browser/favicon/favicon_handler_unittest.cc b/chrome/browser/favicon/favicon_handler_unittest.cc index 50ad60c..b8110b1 100644 --- a/chrome/browser/favicon/favicon_handler_unittest.cc +++ b/chrome/browser/favicon/favicon_handler_unittest.cc @@ -44,6 +44,30 @@ void FillBitmap(int w, int h, std::vector<unsigned char>* output) { gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, output); } +void SetFaviconBitmapResult( + const GURL& icon_url, + history::IconType icon_type, + bool expired, + std::vector<history::FaviconBitmapResult>* favicon_bitmap_results) { + scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); + FillBitmap(gfx::kFaviconSize, gfx::kFaviconSize, &data->data()); + history::FaviconBitmapResult bitmap_result; + bitmap_result.expired = expired; + bitmap_result.bitmap_data = data; + bitmap_result.pixel_size = gfx::Size(); + bitmap_result.icon_type = icon_type; + bitmap_result.icon_url = icon_url; + + favicon_bitmap_results->push_back(bitmap_result); +} + +void SetFaviconBitmapResult( + const GURL& icon_url, + std::vector<history::FaviconBitmapResult>* favicon_bitmap_results) { + SetFaviconBitmapResult(icon_url, history::FAVICON, false /* expired */, + favicon_bitmap_results); +} + // This class is used to save the download request for verifying with test case. // It also will be used to invoke the onDidDownload callback. class DownloadHandler { @@ -100,7 +124,7 @@ class HistoryRequestHandler { HistoryRequestHandler(const GURL& page_url, const GURL& icon_url, int icon_type, - const FaviconService::FaviconDataCallback& callback) + const FaviconService::FaviconResultsCallback& callback) : page_url_(page_url), icon_url_(icon_url), icon_type_(icon_type), @@ -110,12 +134,12 @@ class HistoryRequestHandler { HistoryRequestHandler(const GURL& page_url, const GURL& icon_url, int icon_type, - const std::vector<unsigned char>& image_data, - const FaviconService::FaviconDataCallback& callback) + const std::vector<unsigned char>& bitmap_data, + const FaviconService::FaviconResultsCallback& callback) : page_url_(page_url), icon_url_(icon_url), icon_type_(icon_type), - image_data_(image_data), + bitmap_data_(bitmap_data), callback_(callback) { } @@ -125,9 +149,9 @@ class HistoryRequestHandler { const GURL page_url_; const GURL icon_url_; const int icon_type_; - const std::vector<unsigned char> image_data_; - history::FaviconData favicon_data_; - FaviconService::FaviconDataCallback callback_; + const std::vector<unsigned char> bitmap_data_; + std::vector<history::FaviconBitmapResult> history_results_; + FaviconService::FaviconResultsCallback callback_; private: DISALLOW_COPY_AND_ASSIGN(HistoryRequestHandler); @@ -222,7 +246,7 @@ class TestFaviconHandler : public FaviconHandler { const GURL& icon_url, history::IconType icon_type, CancelableRequestConsumerBase* consumer, - const FaviconService::FaviconDataCallback& callback) OVERRIDE { + const FaviconService::FaviconResultsCallback& callback) OVERRIDE { history_handler_.reset(new HistoryRequestHandler(page_url, icon_url, icon_type, callback)); } @@ -231,7 +255,7 @@ class TestFaviconHandler : public FaviconHandler { const GURL& icon_url, history::IconType icon_type, CancelableRequestConsumerBase* consumer, - const FaviconService::FaviconDataCallback& callback) OVERRIDE { + const FaviconService::FaviconResultsCallback& callback) OVERRIDE { history_handler_.reset(new HistoryRequestHandler(GURL(), icon_url, icon_type, callback)); } @@ -240,7 +264,7 @@ class TestFaviconHandler : public FaviconHandler { const GURL& page_url, int icon_types, CancelableRequestConsumerBase* consumer, - const FaviconService::FaviconDataCallback& callback) OVERRIDE { + const FaviconService::FaviconResultsCallback& callback) OVERRIDE { history_handler_.reset(new HistoryRequestHandler(page_url, GURL(), icon_types, callback)); } @@ -253,11 +277,11 @@ class TestFaviconHandler : public FaviconHandler { virtual void SetHistoryFavicon(const GURL& page_url, const GURL& icon_url, - const std::vector<unsigned char>& image_data, + const std::vector<unsigned char>& bitmap_data, history::IconType icon_type) OVERRIDE { history_handler_.reset(new HistoryRequestHandler( - page_url, icon_url,icon_type, image_data, - FaviconService::FaviconDataCallback())); + page_url, icon_url,icon_type, bitmap_data, + FaviconService::FaviconResultsCallback())); } virtual FaviconService* GetFaviconService() OVERRIDE { @@ -291,7 +315,7 @@ namespace { void HistoryRequestHandler::InvokeCallback() { if (!callback_.is_null()) - callback_.Run(0, favicon_data_); + callback_.Run(0, history_results_, history::IconURLSizesMap()); } void DownloadHandler::InvokeCallback() { @@ -326,14 +350,7 @@ TEST_F(FaviconHandlerTest, GetFaviconFromHistory) { EXPECT_EQ(GURL(), history_handler->icon_url_); EXPECT_EQ(history::FAVICON, history_handler->icon_type_); - // Set valid icon data. - history_handler->favicon_data_.known_icon = true; - history_handler->favicon_data_.icon_type = history::FAVICON; - history_handler->favicon_data_.expired = false; - history_handler->favicon_data_.icon_url = icon_url; - scoped_refptr<base::RefCountedBytes> data = new base::RefCountedBytes(); - FillBitmap(gfx::kFaviconSize, gfx::kFaviconSize, &data->data()); - history_handler->favicon_data_.image_data = data; + SetFaviconBitmapResult(icon_url, &history_handler->history_results_); // Send history response. history_handler->InvokeCallback(); @@ -375,10 +392,8 @@ TEST_F(FaviconHandlerTest, DownloadFavicon) { EXPECT_EQ(history::FAVICON, history_handler->icon_type_); // Set icon data expired - history_handler->favicon_data_.known_icon = true; - history_handler->favicon_data_.icon_type = history::FAVICON; - history_handler->favicon_data_.expired = true; - history_handler->favicon_data_.icon_url = icon_url; + SetFaviconBitmapResult(icon_url, history::FAVICON, true /* expired */, + &history_handler->history_results_); // Send history response. history_handler->InvokeCallback(); // Verify FaviconHandler status @@ -415,7 +430,7 @@ TEST_F(FaviconHandlerTest, DownloadFavicon) { ASSERT_TRUE(history_handler); EXPECT_EQ(icon_url, history_handler->icon_url_); EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_); - EXPECT_LT(0U, history_handler->image_data_.size()); + EXPECT_LT(0U, history_handler->bitmap_data_.size()); EXPECT_EQ(page_url, history_handler->page_url_); // Verify NavigationEntry. @@ -444,13 +459,7 @@ TEST_F(FaviconHandlerTest, UpdateAndDownloadFavicon) { EXPECT_EQ(history::FAVICON, history_handler->icon_type_); // Set valid icon data. - history_handler->favicon_data_.known_icon = true; - history_handler->favicon_data_.icon_type = history::FAVICON; - history_handler->favicon_data_.expired = false; - history_handler->favicon_data_.icon_url = icon_url; - scoped_refptr<base::RefCountedBytes> data = new base::RefCountedBytes(); - FillBitmap(gfx::kFaviconSize, gfx::kFaviconSize, &data->data()); - history_handler->favicon_data_.image_data = data; + SetFaviconBitmapResult(icon_url, &history_handler->history_results_); // Send history response. history_handler->InvokeCallback(); @@ -483,7 +492,7 @@ TEST_F(FaviconHandlerTest, UpdateAndDownloadFavicon) { EXPECT_EQ(page_url, history_handler->page_url_); // Simulate not find icon. - history_handler->favicon_data_.known_icon = false; + history_handler->history_results_.clear(); history_handler->InvokeCallback(); // Favicon should request to download icon now. @@ -505,7 +514,7 @@ TEST_F(FaviconHandlerTest, UpdateAndDownloadFavicon) { ASSERT_TRUE(history_handler); EXPECT_EQ(new_icon_url, history_handler->icon_url_); EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_); - EXPECT_LT(0U, history_handler->image_data_.size()); + EXPECT_LT(0U, history_handler->bitmap_data_.size()); EXPECT_EQ(page_url, history_handler->page_url_); // Verify NavigationEntry. @@ -533,14 +542,7 @@ TEST_F(FaviconHandlerTest, UpdateFavicon) { EXPECT_EQ(GURL(), history_handler->icon_url_); EXPECT_EQ(history::FAVICON, history_handler->icon_type_); - // Set valid icon data. - history_handler->favicon_data_.known_icon = true; - history_handler->favicon_data_.icon_type = history::FAVICON; - history_handler->favicon_data_.expired = false; - history_handler->favicon_data_.icon_url = icon_url; - scoped_refptr<base::RefCountedBytes> data = new base::RefCountedBytes(); - FillBitmap(gfx::kFaviconSize, gfx::kFaviconSize, &data->data()); - history_handler->favicon_data_.image_data = data; + SetFaviconBitmapResult(icon_url, &history_handler->history_results_); // Send history response. history_handler->InvokeCallback(); @@ -573,11 +575,7 @@ TEST_F(FaviconHandlerTest, UpdateFavicon) { EXPECT_EQ(page_url, history_handler->page_url_); // Simulate find icon. - history_handler->favicon_data_.known_icon = true; - history_handler->favicon_data_.icon_type = history::FAVICON; - history_handler->favicon_data_.expired = false; - history_handler->favicon_data_.icon_url = new_icon_url; - history_handler->favicon_data_.image_data = data; + SetFaviconBitmapResult(new_icon_url, &history_handler->history_results_); history_handler->InvokeCallback(); // Shouldn't request download favicon @@ -610,7 +608,7 @@ TEST_F(FaviconHandlerTest, Download2ndFaviconURLCandidate) { history_handler->icon_type_); // Icon not found. - history_handler->favicon_data_.known_icon = false; + history_handler->history_results_.clear(); // Send history response. history_handler->InvokeCallback(); // Verify FaviconHandler status. @@ -643,7 +641,7 @@ TEST_F(FaviconHandlerTest, Download2ndFaviconURLCandidate) { EXPECT_EQ(page_url, history_handler->page_url_); // Simulate not find icon. - history_handler->favicon_data_.known_icon = false; + history_handler->history_results_.clear(); history_handler->InvokeCallback(); // Should request download favicon. @@ -677,14 +675,9 @@ TEST_F(FaviconHandlerTest, Download2ndFaviconURLCandidate) { // Reset download handler download_handler->Reset(); - // Smulates getting a expired icon from history. - history_handler->favicon_data_.known_icon = true; - history_handler->favicon_data_.icon_type = history::TOUCH_ICON; - history_handler->favicon_data_.expired = true; - history_handler->favicon_data_.icon_url = new_icon_url; - scoped_refptr<base::RefCountedBytes> data = new base::RefCountedBytes(); - FillBitmap(gfx::kFaviconSize, gfx::kFaviconSize, &data->data()); - history_handler->favicon_data_.image_data = data; + // Simulates getting a expired icon from history. + SetFaviconBitmapResult(new_icon_url, history::TOUCH_ICON, + true /* expired */, &history_handler->history_results_); history_handler->InvokeCallback(); // Verify the download request. @@ -702,7 +695,7 @@ TEST_F(FaviconHandlerTest, Download2ndFaviconURLCandidate) { ASSERT_TRUE(history_handler); EXPECT_EQ(new_icon_url, history_handler->icon_url_); EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_); - EXPECT_LT(0U, history_handler->image_data_.size()); + EXPECT_LT(0U, history_handler->bitmap_data_.size()); EXPECT_EQ(page_url, history_handler->page_url_); } @@ -727,7 +720,7 @@ TEST_F(FaviconHandlerTest, UpdateDuringDownloading) { history_handler->icon_type_); // Icon not found. - history_handler->favicon_data_.known_icon = false; + history_handler->history_results_.clear(); // Send history response. history_handler->InvokeCallback(); // Verify FaviconHandler status. @@ -760,7 +753,7 @@ TEST_F(FaviconHandlerTest, UpdateDuringDownloading) { EXPECT_EQ(page_url, history_handler->page_url_); // Simulate not find icon. - history_handler->favicon_data_.known_icon = false; + history_handler->history_results_.clear(); history_handler->InvokeCallback(); // Should request download favicon. @@ -793,7 +786,7 @@ TEST_F(FaviconHandlerTest, UpdateDuringDownloading) { // Reset the history_handler to verify whether favicon is request from // history. // Save the callback for late use. - FaviconService::FaviconDataCallback callback = history_handler->callback_; + FaviconService::FaviconResultsCallback callback = history_handler->callback_; helper.set_history_handler(NULL); // Simulates download succeed. @@ -807,14 +800,8 @@ TEST_F(FaviconHandlerTest, UpdateDuringDownloading) { scoped_ptr<HistoryRequestHandler> handler; handler.reset(new HistoryRequestHandler(page_url, latest_icon_url, history::TOUCH_ICON, callback)); - handler->favicon_data_.known_icon = true; - handler->favicon_data_.expired = false; - handler->favicon_data_.icon_type = history::TOUCH_ICON; - handler->favicon_data_.icon_url = latest_icon_url; - scoped_refptr<base::RefCountedBytes> data = new base::RefCountedBytes(); - FillBitmap(gfx::kFaviconSize, gfx::kFaviconSize, &data->data()); - handler->favicon_data_.image_data = data; - + SetFaviconBitmapResult(latest_icon_url, history::TOUCH_ICON, + false /* expired */, &handler->history_results_); handler->InvokeCallback(); // No download request. @@ -838,14 +825,7 @@ TEST_F(FaviconHandlerTest, MultipleFavicon) { handler.FetchFavicon(page_url); HistoryRequestHandler* history_handler = handler.history_handler(); - // Set valid icon data. - history_handler->favicon_data_.known_icon = true; - history_handler->favicon_data_.icon_type = history::FAVICON; - history_handler->favicon_data_.expired = false; - history_handler->favicon_data_.icon_url = icon_url; - scoped_refptr<base::RefCountedBytes> data = new base::RefCountedBytes(); - FillBitmap(gfx::kFaviconSize, gfx::kFaviconSize, &data->data()); - history_handler->favicon_data_.image_data = data; + SetFaviconBitmapResult(icon_url, &history_handler->history_results_); // Send history response. history_handler->InvokeCallback(); @@ -864,7 +844,7 @@ TEST_F(FaviconHandlerTest, MultipleFavicon) { DownloadHandler* download_handler = handler.download_handler(); // Download the first icon (set not in history). - handler.history_handler()->favicon_data_.known_icon = false; + handler.history_handler()->history_results_.clear(); handler.history_handler()->InvokeCallback(); ASSERT_TRUE(download_handler->HasDownload()); EXPECT_EQ(icon_url_small, download_handler->GetImageUrl()); @@ -873,7 +853,7 @@ TEST_F(FaviconHandlerTest, MultipleFavicon) { EXPECT_EQ(3U, handler.image_urls().size()); // Download the second icon (set not in history). - handler.history_handler()->favicon_data_.known_icon = false; + handler.history_handler()->history_results_.clear(); handler.history_handler()->InvokeCallback(); ASSERT_TRUE(download_handler->HasDownload()); EXPECT_EQ(icon_url_large, download_handler->GetImageUrl()); @@ -882,7 +862,7 @@ TEST_F(FaviconHandlerTest, MultipleFavicon) { EXPECT_EQ(2U, handler.image_urls().size()); // Download the third icon (set not in history). - handler.history_handler()->favicon_data_.known_icon = false; + handler.history_handler()->history_results_.clear(); handler.history_handler()->InvokeCallback(); ASSERT_TRUE(download_handler->HasDownload()); EXPECT_EQ(icon_url_preferred1, download_handler->GetImageUrl()); @@ -915,13 +895,7 @@ TEST_F(FaviconHandlerTest, FirstFavicon) { HistoryRequestHandler* history_handler = handler.history_handler(); // Set valid icon data. - history_handler->favicon_data_.known_icon = true; - history_handler->favicon_data_.icon_type = history::FAVICON; - history_handler->favicon_data_.expired = false; - history_handler->favicon_data_.icon_url = icon_url; - scoped_refptr<base::RefCountedBytes> data = new base::RefCountedBytes(); - FillBitmap(gfx::kFaviconSize, gfx::kFaviconSize, &data->data()); - history_handler->favicon_data_.image_data = data; + SetFaviconBitmapResult(icon_url, &history_handler->history_results_); // Send history response. history_handler->InvokeCallback(); @@ -938,7 +912,7 @@ TEST_F(FaviconHandlerTest, FirstFavicon) { DownloadHandler* download_handler = handler.download_handler(); // Download the first icon (set not in history). - handler.history_handler()->favicon_data_.known_icon = false; + handler.history_handler()->history_results_.clear(); handler.history_handler()->InvokeCallback(); ASSERT_TRUE(download_handler->HasDownload()); EXPECT_EQ(icon_url_preferred1, download_handler->GetImageUrl()); diff --git a/chrome/browser/favicon/favicon_service.cc b/chrome/browser/favicon/favicon_service.cc index ff3d6e5..ec34ed1 100644 --- a/chrome/browser/favicon/favicon_service.cc +++ b/chrome/browser/favicon/favicon_service.cc @@ -4,21 +4,69 @@ #include "chrome/browser/favicon/favicon_service.h" +#include "chrome/browser/favicon/select_favicon_frames.h" #include "chrome/browser/history/history.h" #include "chrome/browser/history/history_backend.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" #include "chrome/common/url_constants.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/codec/png_codec.h" +#include "ui/gfx/image/image_skia.h" FaviconService::FaviconService(HistoryService* history_service) : history_service_(history_service) { } +FaviconService::Handle FaviconService::GetFaviconImage( + const GURL& icon_url, + history::IconType icon_type, + int desired_size_in_dip, + CancelableRequestConsumerBase* consumer, + const FaviconImageCallback& callback) { + GetFaviconRequest* request = new GetFaviconRequest(base::Bind( + &FaviconService::GetFaviconImageCallback, + base::Unretained(this), + desired_size_in_dip, + callback)); + AddRequest(request, consumer); + // TODO(pkotwicz): Pass in desired size and scale factors. + if (history_service_) + history_service_->GetFavicon(request, icon_url, icon_type); + else + ForwardEmptyResultAsync(request); + return request->handle(); +} + +FaviconService::Handle FaviconService::GetRawFavicon( + const GURL& icon_url, + history::IconType icon_type, + int desired_size_in_dip, + ui::ScaleFactor desired_scale_factor, + CancelableRequestConsumerBase* consumer, + const FaviconRawCallback& callback) { + GetFaviconRequest* request = new GetFaviconRequest(base::Bind( + &FaviconService::GetRawFaviconCallback, + base::Unretained(this), + desired_size_in_dip, + desired_scale_factor, + callback)); + AddRequest(request, consumer); + // TODO(pkotwicz): Pass in desired size and scale factor. + if (history_service_) + history_service_->GetFavicon(request, icon_url, icon_type); + else + ForwardEmptyResultAsync(request); + return request->handle(); +} + FaviconService::Handle FaviconService::GetFavicon( const GURL& icon_url, history::IconType icon_type, + int desired_size_in_dip, + const std::vector<ui::ScaleFactor>& desired_scale_factors, CancelableRequestConsumerBase* consumer, - const FaviconDataCallback& callback) { + const FaviconResultsCallback& callback) { GetFaviconRequest* request = new GetFaviconRequest(callback); AddRequest(request, consumer); if (history_service_) @@ -33,7 +81,7 @@ FaviconService::Handle FaviconService::UpdateFaviconMappingAndFetch( const GURL& icon_url, history::IconType icon_type, CancelableRequestConsumerBase* consumer, - const FaviconDataCallback& callback) { + const FaviconResultsCallback& callback) { GetFaviconRequest* request = new GetFaviconRequest(callback); AddRequest(request, consumer); if (history_service_) @@ -44,37 +92,75 @@ FaviconService::Handle FaviconService::UpdateFaviconMappingAndFetch( return request->handle(); } +FaviconService::Handle FaviconService::GetFaviconImageForURL( + Profile* profile, + const GURL& page_url, + int icon_types, + int desired_size_in_dip, + CancelableRequestConsumerBase* consumer, + const FaviconImageCallback& callback) { + GetFaviconRequest* request = new GetFaviconRequest(base::Bind( + &FaviconService::GetFaviconImageCallback, + base::Unretained(this), + desired_size_in_dip, + callback)); + + std::vector<ui::ScaleFactor> desired_scale_factors = + ui::GetSupportedScaleFactors(); + return GetFaviconForURLImpl(profile, page_url, icon_types, + desired_size_in_dip, desired_scale_factors, consumer, request); +} + +FaviconService::Handle FaviconService::GetRawFaviconForURL( + Profile* profile, + const GURL& page_url, + int icon_types, + int desired_size_in_dip, + ui::ScaleFactor desired_scale_factor, + CancelableRequestConsumerBase* consumer, + const FaviconRawCallback& callback) { + GetFaviconRequest* request = new GetFaviconRequest(base::Bind( + &FaviconService::GetRawFaviconCallback, + base::Unretained(this), + desired_size_in_dip, + desired_scale_factor, + callback)); + + std::vector<ui::ScaleFactor> desired_scale_factors; + desired_scale_factors.push_back(desired_scale_factor); + return GetFaviconForURLImpl(profile, page_url, icon_types, + desired_size_in_dip, desired_scale_factors, consumer, request); +} + FaviconService::Handle FaviconService::GetFaviconForURL( Profile* profile, const GURL& page_url, int icon_types, + int desired_size_in_dip, + const std::vector<ui::ScaleFactor>& desired_scale_factors, CancelableRequestConsumerBase* consumer, - const FaviconDataCallback& callback) { + const FaviconResultsCallback& callback) { GetFaviconRequest* request = new GetFaviconRequest(callback); - AddRequest(request, consumer); - FaviconService::Handle handle = request->handle(); - if (page_url.SchemeIs(chrome::kChromeUIScheme) || - page_url.SchemeIs(chrome::kExtensionScheme)) { - ChromeWebUIControllerFactory::GetInstance()->GetFaviconForURL( - profile, request, page_url); - } else { - if (history_service_) - history_service_->GetFaviconForURL(request, page_url, icon_types); - else - ForwardEmptyResultAsync(request); - } - return handle; + return GetFaviconForURLImpl(profile, page_url, icon_types, + desired_size_in_dip, desired_scale_factors, consumer, request); } -// Requests the favicon for |favicon_id|. The |consumer| is notified when the -// bits have been fetched. -FaviconService::Handle FaviconService::GetFaviconForID( +FaviconService::Handle FaviconService::GetRawFaviconForID( history::FaviconID favicon_id, + int desired_size_in_dip, + ui::ScaleFactor desired_scale_factor, CancelableRequestConsumerBase* consumer, - const FaviconDataCallback& callback) { - GetFaviconRequest* request = new GetFaviconRequest(callback); + const FaviconRawCallback& callback) { + GetFaviconRequest* request = new GetFaviconRequest(base::Bind( + &FaviconService::GetRawFaviconCallback, + base::Unretained(this), + desired_size_in_dip, + desired_scale_factor, + callback)); + AddRequest(request, consumer); FaviconService::Handle handle = request->handle(); + // TODO(pkotwicz): Pass in desired size and scale factor. if (history_service_) history_service_->GetFaviconForID(request, favicon_id); else @@ -112,6 +198,115 @@ void FaviconService::SetFavicon(const GURL& page_url, FaviconService::~FaviconService() { } +FaviconService::Handle FaviconService::GetFaviconForURLImpl( + Profile* profile, + const GURL& page_url, + int icon_types, + int desired_size_in_dip, + const std::vector<ui::ScaleFactor>& desired_scale_factors, + CancelableRequestConsumerBase* consumer, + GetFaviconRequest* request) { + AddRequest(request, consumer); + FaviconService::Handle handle = request->handle(); + if (page_url.SchemeIs(chrome::kChromeUIScheme) || + page_url.SchemeIs(chrome::kExtensionScheme)) { + // TODO(pkotwicz): Pass in desired size and desired scale factors. + ChromeWebUIControllerFactory::GetInstance()->GetFaviconForURL( + profile, request, page_url); + } else { + // TODO(pkotwicz): Pass in desired size and desired scale factors. + if (history_service_) + history_service_->GetFaviconForURL(request, page_url, icon_types); + else + ForwardEmptyResultAsync(request); + } + return handle; +} + +void FaviconService::GetFaviconImageCallback( + int desired_size_in_dip, + FaviconImageCallback callback, + Handle handle, + std::vector<history::FaviconBitmapResult> favicon_bitmap_results, + history::IconURLSizesMap icon_url_sizes_map) { + std::vector<SkBitmap> sk_bitmaps; + for (size_t i = 0; i < favicon_bitmap_results.size(); ++i) { + if (favicon_bitmap_results[i].is_valid()) { + scoped_refptr<base::RefCountedMemory> bitmap_data = + favicon_bitmap_results[i].bitmap_data; + SkBitmap out_bitmap; + if (gfx::PNGCodec::Decode(bitmap_data->front(), bitmap_data->size(), + &out_bitmap)) { + sk_bitmaps.push_back(out_bitmap); + } + } + } + history::FaviconImageResult image_result; + image_result.image = gfx::Image(SelectFaviconFrames( + sk_bitmaps, ui::GetSupportedScaleFactors(), desired_size_in_dip, NULL)); + image_result.icon_url = favicon_bitmap_results.empty() ? + GURL() : favicon_bitmap_results[0].icon_url; + + callback.Run(handle, image_result); +} + +void FaviconService::GetRawFaviconCallback( + int desired_size_in_dip, + ui::ScaleFactor desired_scale_factor, + FaviconRawCallback callback, + Handle handle, + std::vector<history::FaviconBitmapResult> favicon_bitmap_results, + history::IconURLSizesMap icon_url_sizes_map) { + if (favicon_bitmap_results.empty() || !favicon_bitmap_results[0].is_valid()) { + callback.Run(handle, history::FaviconBitmapResult()); + return; + } + + DCHECK_EQ(1u, favicon_bitmap_results.size()); + history::FaviconBitmapResult bitmap_result = favicon_bitmap_results[0]; + + // If history bitmap is already desired pixel size, return early. + float desired_scale = ui::GetScaleFactorScale(desired_scale_factor); + int desired_edge_width_in_pixel = static_cast<int>( + desired_size_in_dip * desired_scale + 0.5f); + gfx::Size desired_size_in_pixel(desired_edge_width_in_pixel, + desired_edge_width_in_pixel); + if (bitmap_result.pixel_size == desired_size_in_pixel) { + callback.Run(handle, bitmap_result); + return; + } + + // Convert raw bytes to SkBitmap, resize via SelectFaviconFrames(), then + // convert back. + SkBitmap bitmap; + if (!gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), + bitmap_result.bitmap_data->size(), + &bitmap)) { + callback.Run(handle, history::FaviconBitmapResult()); + return; + } + + std::vector<SkBitmap> bitmaps; + bitmaps.push_back(bitmap); + std::vector<ui::ScaleFactor> desired_scale_factors; + desired_scale_factors.push_back(desired_scale_factor); + gfx::ImageSkia resized_image = SelectFaviconFrames(bitmaps, + desired_scale_factors, desired_size_in_dip, NULL); + + std::vector<unsigned char> resized_bitmap_data; + if (!gfx::PNGCodec::EncodeBGRASkBitmap(*resized_image.bitmap(), false, + &resized_bitmap_data)) { + callback.Run(handle, history::FaviconBitmapResult()); + return; + } + + bitmap_result.bitmap_data = base::RefCountedBytes::TakeVector( + &resized_bitmap_data); + callback.Run(handle, bitmap_result); +} + void FaviconService::ForwardEmptyResultAsync(GetFaviconRequest* request) { - request->ForwardResultAsync(request->handle(), history::FaviconData()); + request->ForwardResultAsync(request->handle(), + std::vector<history::FaviconBitmapResult>(), + history::IconURLSizesMap()); } diff --git a/chrome/browser/favicon/favicon_service.h b/chrome/browser/favicon/favicon_service.h index b751760..9cb4f58 100644 --- a/chrome/browser/favicon/favicon_service.h +++ b/chrome/browser/favicon/favicon_service.h @@ -13,6 +13,7 @@ #include "chrome/browser/history/history_types.h" #include "chrome/browser/profiles/profile_keyed_service.h" #include "chrome/common/ref_counted_util.h" +#include "ui/base/layout.h" class GURL; class HistoryService; @@ -30,30 +31,79 @@ class FaviconService : public CancelableRequestProvider, virtual ~FaviconService(); - // Callback for GetFavicon. If we have previously inquired about the favicon - // for this URL, |know_favicon| will be true, and the rest of the fields will - // be valid (otherwise they will be ignored). + // Callback for GetFaviconImage() and GetFaviconImageForURL(). + // |FaviconImageResult::image| is constructed from the bitmaps for the + // passed in URL and icon types which most which closely match the passed in + // |desired_size_in_dip| at the scale factors supported by the current + // platform (eg MacOS). + // |FaviconImageResult::icon_url| is the favicon that the favicon bitmaps in + // |image| originate from. + // TODO(pkotwicz): Enable constructing |image| from bitmaps from several + // icon URLs. + typedef base::Callback<void(Handle, const history::FaviconImageResult&)> + FaviconImageCallback; + + // Callback for GetRawFavicon() and GetRawFaviconForURL(). + // FaviconBitmapResult::bitmap_data is the bitmap in the thumbnail database + // for the passed in URL and icon types whose pixel size best matches the + // passed in |desired_size_in_dip| and |desired_scale_factor|. Returns an + // invalid history::FaviconBitmapResult if there are no matches. + typedef base::Callback<void(Handle, const history::FaviconBitmapResult&)> + FaviconRawCallback; + + // Callback for GetFavicon() and GetFaviconForURL(). // - // On |know_favicon| == true, |data| will either contain the PNG encoded - // favicon data, or it will be NULL to indicate that the site does not have - // a favicon (in other words, we know the site doesn't have a favicon, as - // opposed to not knowing anything). |expired| will be set to true if we - // refreshed the favicon "too long" ago and should be updated if the page - // is visited again. + // The second argument is the set of bitmaps for the passed in URL and + // icon types whose pixel sizes best match the passed in + // |desired_size_in_dip| and |desired_scale_factors|. The vector has at most + // one result for each of |desired_scale_factors|. There are less entries if + // a single result is the best bitmap to use for several scale factors. + // + // Third argument: + // a) If the callback is called as a result of GetFaviconForURL(): + // The third argument is a map of the icon URLs mapped to |page_url| to + // the sizes at which the favicon is available from the web. + // b) If the callback is called as a result of GetFavicon() or + // UpdateFaviconMappingAndFetch(): + // The third argument is a map with a single element with the passed in + // |icon_url| to the vector of sizes of the favicon bitmaps at that URL. If + // |icon_url| is not known to the history backend, an empty map is + // returned. + // See history_types.h for more information about IconURLSizesMap. typedef base::Callback< void(Handle, // handle - history::FaviconData)> // the type of favicon - FaviconDataCallback; + std::vector<history::FaviconBitmapResult>, + history::IconURLSizesMap)> + FaviconResultsCallback; - typedef CancelableRequest<FaviconDataCallback> GetFaviconRequest; + typedef CancelableRequest<FaviconResultsCallback> GetFaviconRequest; - // Requests the |icon_type| of favicon. |consumer| is notified when the bits - // have been fetched. |icon_url| is the URL of the icon itself, e.g. + // Requests the favicon at |icon_url| of |icon_type| whose size most closely + // matches |desired_size_in_dip|. |consumer| is notified when the bits have + // been fetched. |icon_url| is the URL of the icon itself, e.g. // <http://www.google.com/favicon.ico>. + // Each of the three methods below differs in the format of the callback and + // the requested scale factors. All of the scale factors supported by the + // current platform (eg MacOS) are requested for GetFaviconImage(). + Handle GetFaviconImage(const GURL& icon_url, + history::IconType icon_type, + int desired_size_in_dip, + CancelableRequestConsumerBase* consumer, + const FaviconImageCallback& callback); + + Handle GetRawFavicon(const GURL& icon_url, + history::IconType icon_type, + int desired_size_in_dip, + ui::ScaleFactor desired_scale_factor, + CancelableRequestConsumerBase* consumer, + const FaviconRawCallback& callback); + Handle GetFavicon(const GURL& icon_url, history::IconType icon_type, + int desired_size_in_dip, + const std::vector<ui::ScaleFactor>& desired_scale_factors, CancelableRequestConsumerBase* consumer, - const FaviconDataCallback& callback); + const FaviconResultsCallback& callback); // Fetches the |icon_type| of favicon at |icon_url|, sending the results to // the given |callback|. If the favicon has previously been set via @@ -64,27 +114,49 @@ class FaviconService : public CancelableRequestProvider, const GURL& icon_url, history::IconType icon_type, CancelableRequestConsumerBase* consumer, - const FaviconDataCallback& callback); - - // Requests any |icon_types| of favicon for a web page URL. |consumer| is - // notified when the bits have been fetched. |icon_types| can be any - // combination of IconType value, but only one icon will be returned in the - // priority of TOUCH_PRECOMPOSED_ICON, TOUCH_ICON and FAVICON. - // - // Note: this version is intended to be used to retrieve the favicon of a - // page that has been browsed in the past. |expired| in the callback is - // always false. - Handle GetFaviconForURL(Profile* profile, - const GURL& page_url, - int icon_types, - CancelableRequestConsumerBase* consumer, - const FaviconDataCallback& callback); - - // Requests the favicon for |favicon_id|. The |consumer| is notified when the - // bits have been fetched. - Handle GetFaviconForID(history::FaviconID favicon_id, - CancelableRequestConsumerBase* consumer, - const FaviconDataCallback& callback); + const FaviconResultsCallback& callback); + + // Requests the favicons of any of |icon_types| whose pixel sizes most + // closely match |desired_size_in_dip| and desired scale factors for a web + // page URL. |consumer| is notified when the bits have been fetched. + // |icon_types| can be any combination of IconType value, but only one icon + // will be returned in the priority of TOUCH_PRECOMPOSED_ICON, TOUCH_ICON + // and FAVICON. Each of the three methods below differs in the format of the + // callback and the requested scale factors. All of the scale factors + // supported by the current platform (eg MacOS) are requested for + // GetFaviconImageForURL(). + Handle GetFaviconImageForURL(Profile* profile, + const GURL& page_url, + int icon_types, + int desired_size_in_dip, + CancelableRequestConsumerBase* consumer, + const FaviconImageCallback& callback); + + Handle GetRawFaviconForURL(Profile* profile, + const GURL& page_url, + int icon_types, + int desired_size_in_dip, + ui::ScaleFactor desired_scale_factor, + CancelableRequestConsumerBase* consumer, + const FaviconRawCallback& callback); + + Handle GetFaviconForURL( + Profile* profile, + const GURL& page_url, + int icon_types, + int desired_size_in_dip, + const std::vector<ui::ScaleFactor>& desired_scale_factors, + CancelableRequestConsumerBase* consumer, + const FaviconResultsCallback& callback); + + // Requests the favicon for |favicon_id| which most closely matches + // |desired_size_in_dip| and |desired_scale_factor|. The |consumer| is + // notified when the bits have been fetched. + Handle GetRawFaviconForID(history::FaviconID favicon_id, + int desired_size_in_dip, + ui::ScaleFactor desired_scale_factor, + CancelableRequestConsumerBase* consumer, + const FaviconRawCallback& callback); // Marks all types of favicon for the page as being out of date. void SetFaviconOutOfDateForPage(const GURL& page_url); @@ -114,6 +186,39 @@ class FaviconService : public CancelableRequestProvider, // Helper to forward an empty result if we cannot get the history service. void ForwardEmptyResultAsync(GetFaviconRequest* request); + // Helper function for GetFaviconImageForURL(), GetRawFaviconForURL() and + // GetFaviconForURL(). + Handle GetFaviconForURLImpl( + Profile* profile, + const GURL& page_url, + int icon_types, + int desired_size_in_dip, + const std::vector<ui::ScaleFactor>& desired_scale_factors, + CancelableRequestConsumerBase* consumer, + GetFaviconRequest* request); + + // Intermediate callback for GetFaviconImage() and GetFaviconImageForURL() + // so that history service can deal solely with FaviconResultsCallback. + // Builds history::FaviconImageResult from |favicon_bitmap_results| and runs + // |callback|. + void GetFaviconImageCallback( + int desired_size_in_dip, + FaviconImageCallback callback, + Handle handle, + std::vector<history::FaviconBitmapResult> favicon_bitmap_results, + history::IconURLSizesMap icon_url_sizes_map); + + // Intermediate callback for GetRawFavicon() and GetRawFaviconForURL() + // so that history service can deal solely with FaviconResultsCallback. + // Resizes history::FaviconBitmapResult if necessary and runs |callback|. + void GetRawFaviconCallback( + int desired_size_in_dip, + ui::ScaleFactor desired_scale_factor, + FaviconRawCallback callback, + Handle handle, + std::vector<history::FaviconBitmapResult> favicon_bitmap_results, + history::IconURLSizesMap icon_url_sizes_map); + DISALLOW_COPY_AND_ASSIGN(FaviconService); }; diff --git a/chrome/browser/history/android/sqlite_cursor.cc b/chrome/browser/history/android/sqlite_cursor.cc index 0469661..a350daa 100644 --- a/chrome/browser/history/android/sqlite_cursor.cc +++ b/chrome/browser/history/android/sqlite_cursor.cc @@ -11,6 +11,7 @@ #include "chrome/browser/history/android/android_history_types.h" #include "content/public/browser/browser_thread.h" #include "jni/SQLiteCursor_jni.h" +#include "ui/gfx/favicon_size.h" #include "sql/statement.h" using base::android::ConvertUTF8ToJavaString; @@ -222,11 +223,13 @@ bool SQLiteCursor::GetFavicon(history::FaviconID id, test_observer_->OnPostGetFaviconTask(); event_.Wait(); - if (!favicon_.is_valid()) + if (!favicon_bitmap_result_.is_valid()) return false; - image_data->assign(favicon_.image_data->front(), - favicon_.image_data->front() + favicon_.image_data->size()); + scoped_refptr<base::RefCountedMemory> bitmap_data = + favicon_bitmap_result_.bitmap_data; + image_data->assign(bitmap_data->front(), + bitmap_data->front() + bitmap_data->size()); return true; } @@ -236,15 +239,17 @@ bool SQLiteCursor::GetFavicon(history::FaviconID id, void SQLiteCursor::GetFaviconForIDInUIThread( history::FaviconID id, CancelableRequestConsumerBase* consumer, - const FaviconService::FaviconDataCallback& callback) { + const FaviconService::FaviconRawCallback& callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - favicon_service_->GetFaviconForID(id, consumer, callback); + favicon_service_->GetRawFaviconForID(id, gfx::kFaviconSize, + ui::SCALE_FACTOR_100P, consumer, callback); } -void SQLiteCursor::OnFaviconData(FaviconService::Handle handle, - history::FaviconData favicon) { - favicon_ = favicon; +void SQLiteCursor::OnFaviconData( + FaviconService::Handle handle, + const history::FaviconBitmapResult& bitmap_result) { + favicon_bitmap_result_ = bitmap_result; event_.Signal(); if (test_observer_) test_observer_->OnGetFaviconResult(); diff --git a/chrome/browser/history/android/sqlite_cursor.h b/chrome/browser/history/android/sqlite_cursor.h index de96e1a..f144397 100644 --- a/chrome/browser/history/android/sqlite_cursor.h +++ b/chrome/browser/history/android/sqlite_cursor.h @@ -147,11 +147,11 @@ class SQLiteCursor { void GetFaviconForIDInUIThread( history::FaviconID id, CancelableRequestConsumerBase* consumer, - const FaviconService::FaviconDataCallback& callback); + const FaviconService::FaviconRawCallback& callback); // The Callback function of GetFavicon(). void OnFaviconData(FaviconService::Handle handle, - history::FaviconData favicon); + const history::FaviconBitmapResult& bitmap_result); // The callback function of MoveTo(). void OnMoved(AndroidHistoryProviderService::Handle handle, @@ -186,7 +186,7 @@ class SQLiteCursor { int count_; // The favicon image. - history::FaviconData favicon_; + history::FaviconBitmapResult favicon_bitmap_result_; TestObserver* test_observer_; diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc index 48c039e..0383502 100644 --- a/chrome/browser/history/history_backend.cc +++ b/chrome/browser/history/history_backend.cc @@ -1889,30 +1889,26 @@ void HistoryBackend::UpdateFaviconMappingAndFetchImpl( if (request->canceled()) return; - FaviconData favicon; + std::vector<history::FaviconBitmapResult> favicon_bitmap_results; if (thumbnail_db_.get()) { + IconType icon_type; const FaviconID favicon_id = thumbnail_db_->GetFaviconIDForFaviconURL( - icon_url, icon_types, &favicon.icon_type); + icon_url, icon_types, &icon_type); if (favicon_id) { - scoped_refptr<base::RefCountedMemory> data; - Time last_updated; - if (thumbnail_db_->GetFavicon(favicon_id, &last_updated, &data, - NULL, NULL)) { - favicon.known_icon = true; - favicon.expired = (Time::Now() - last_updated) > - TimeDelta::FromDays(kFaviconRefetchDays); - favicon.image_data = data; - } + GetFaviconFromDB(favicon_id, &favicon_bitmap_results); if (page_url) - SetFaviconMapping(*page_url, favicon_id, favicon.icon_type); + SetFaviconMapping(*page_url, favicon_id, icon_type); } // else case, haven't cached entry yet. Caller is responsible for // downloading the favicon and invoking SetFavicon. } - request->ForwardResult(request->handle(), favicon); + // TODO(pkotwicz): Pass map of |icon_url| to the sizes available from the web + // at |icon_url| instead of an empty map. + request->ForwardResult(request->handle(), favicon_bitmap_results, + IconURLSizesMap()); } void HistoryBackend::GetFaviconForURL( @@ -1922,12 +1918,16 @@ void HistoryBackend::GetFaviconForURL( if (request->canceled()) return; - FaviconData favicon; + std::vector<FaviconBitmapResult> favicon_bitmap_results; // Get the favicon from DB. - GetFaviconFromDB(page_url, icon_types, &favicon); + GetFaviconFromDB(page_url, icon_types, &favicon_bitmap_results); - request->ForwardResult(request->handle(), favicon); + // TODO(pkotwicz): Pass map of matched icon URLs for |icon_types| to the + // sizes that each icon URL is available at from the web instead of an + // empty map. + request->ForwardResult(request->handle(), favicon_bitmap_results, + IconURLSizesMap()); } void HistoryBackend::GetFaviconForID(scoped_refptr<GetFaviconRequest> request, @@ -1935,9 +1935,15 @@ void HistoryBackend::GetFaviconForID(scoped_refptr<GetFaviconRequest> request, if (request->canceled()) return; - FaviconData favicon; - GetFaviconFromDB(id, &favicon); - request->ForwardResult(request->handle(), favicon); + std::vector<FaviconBitmapResult> favicon_bitmap_results; + + // Get the favicon from DB. + GetFaviconFromDB(id, &favicon_bitmap_results); + + // TODO(pkotwicz): Pass map of the matched icon URL to the sizes that it is + // available from the web instead of an empty map. + request->ForwardResult(request->handle(), favicon_bitmap_results, + IconURLSizesMap()); } void HistoryBackend::SetFavicon( @@ -2439,8 +2445,8 @@ BookmarkService* HistoryBackend::GetBookmarkService() { bool HistoryBackend::GetFaviconFromDB( const GURL& page_url, int icon_types, - FaviconData* favicon) { - DCHECK(favicon); + std::vector<FaviconBitmapResult>* favicon_bitmap_results) { + DCHECK(favicon_bitmap_results); if (!db_.get() || !thumbnail_db_.get()) return false; @@ -2456,7 +2462,7 @@ bool HistoryBackend::GetFaviconFromDB( for (std::vector<IconMapping>::iterator i = icon_mappings.begin(); i != icon_mappings.end(); ++i) { if ((i->icon_type & icon_types) && - GetFaviconFromDB(i->icon_id, favicon)) { + GetFaviconFromDB(i->icon_id, favicon_bitmap_results)) { success = true; break; } @@ -2467,19 +2473,25 @@ bool HistoryBackend::GetFaviconFromDB( return success; } -bool HistoryBackend::GetFaviconFromDB(FaviconID favicon_id, - FaviconData* favicon) { +bool HistoryBackend::GetFaviconFromDB( + FaviconID favicon_id, + std::vector<history::FaviconBitmapResult>* favicon_bitmap_results) { + FaviconBitmapResult bitmap_result; Time last_updated; - scoped_refptr<base::RefCountedMemory> data; - - if (!thumbnail_db_->GetFavicon(favicon_id, &last_updated, &data, - &favicon->icon_url, &favicon->icon_type)) + if (!thumbnail_db_->GetFavicon(favicon_id, + &last_updated, + &bitmap_result.bitmap_data, + &bitmap_result.icon_url, + &bitmap_result.icon_type)) { return false; + } - favicon->expired = (Time::Now() - last_updated) > + bitmap_result.expired = (Time::Now() - last_updated) > TimeDelta::FromDays(kFaviconRefetchDays); - favicon->known_icon = true; - favicon->image_data = data; + + favicon_bitmap_results->clear(); + if (bitmap_result.is_valid()) + favicon_bitmap_results->push_back(bitmap_result); return true; } diff --git a/chrome/browser/history/history_backend.h b/chrome/browser/history/history_backend.h index 01adce5..1bea489 100644 --- a/chrome/browser/history/history_backend.h +++ b/chrome/browser/history/history_backend.h @@ -650,13 +650,16 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>, // If there is a favicon for |page_url| and one of the types in |icon_types|, // |favicon| is set appropriately and true is returned. - bool GetFaviconFromDB(const GURL& page_url, - int icon_types, - FaviconData* favicon); + bool GetFaviconFromDB( + const GURL& page_url, + int icon_types, + std::vector<FaviconBitmapResult>* favicon_bitmap_results); // Get favicon by the given |favicon_id|, the |favicon| is set appropriately // and true if returned on success, otherwise false is returned. - bool GetFaviconFromDB(FaviconID favicon_id, FaviconData* favicon); + bool GetFaviconFromDB( + FaviconID favicon_id, + std::vector<FaviconBitmapResult>* favicon_bitmap_results); // Notify any observers of an addition to the visit database. void NotifyVisitObservers(const VisitRow& visit); diff --git a/chrome/browser/history/history_backend_unittest.cc b/chrome/browser/history/history_backend_unittest.cc index ab6e0e7..192f736 100644 --- a/chrome/browser/history/history_backend_unittest.cc +++ b/chrome/browser/history/history_backend_unittest.cc @@ -124,8 +124,10 @@ class HistoryBackendTest : public testing::Test { } // Callback for UpdateFaviconMappingsAndFetch. - void OnFaviconData(FaviconService::Handle handle, - history::FaviconData favicon_data) { + void OnFaviconResults( + FaviconService::Handle handle, + std::vector<history::FaviconBitmapResult> favicon_bitmap_results, + history::IconURLSizesMap icon_url_sizes) { } const history::MostVisitedURLList& get_most_visited_list() const { @@ -1224,7 +1226,8 @@ TEST_F(HistoryBackendTest, SetSameFaviconURLForTwoPages) { backend_->SetFavicon(page_url1, favicon_url, bitmap_data, FAVICON); scoped_refptr<GetFaviconRequest> request(new GetFaviconRequest( - base::Bind(&HistoryBackendTest::OnFaviconData, base::Unretained(this)))); + base::Bind(&HistoryBackendTest::OnFaviconResults, + base::Unretained(this)))); HistoryBackendCancelableRequest cancellable_request; cancellable_request.MockScheduleOfRequest<GetFaviconRequest>(request); backend_->UpdateFaviconMappingAndFetch(request, page_url2, favicon_url, @@ -1291,24 +1294,30 @@ TEST_F(HistoryBackendTest, GetFaviconForURL) { url, TOUCH_ICON, NULL)); // Test the Fav icon for this URL. - FaviconData favicon; - ASSERT_TRUE(backend_->GetFaviconFromDB(url, FAVICON, &favicon)); + std::vector<FaviconBitmapResult> favicon_bitmap_results; + ASSERT_TRUE(backend_->GetFaviconFromDB(url, FAVICON, + &favicon_bitmap_results)); + EXPECT_EQ(1u, favicon_bitmap_results.size()); + FaviconBitmapResult bitmap_result = favicon_bitmap_results[0]; std::string favicon_data( - favicon.image_data->front(), - favicon.image_data->front() + favicon.image_data->size()); + bitmap_result.bitmap_data->front(), + bitmap_result.bitmap_data->front() + bitmap_result.bitmap_data->size()); - EXPECT_EQ(FAVICON, favicon.icon_type); - EXPECT_EQ(icon_url, favicon.icon_url); + EXPECT_EQ(FAVICON, bitmap_result.icon_type); + EXPECT_EQ(icon_url, bitmap_result.icon_url); EXPECT_EQ(blob_data, favicon_data); // Test the touch icon for this URL. - ASSERT_TRUE(backend_->GetFaviconFromDB(url, TOUCH_ICON, &favicon)); + ASSERT_TRUE(backend_->GetFaviconFromDB(url, TOUCH_ICON, + &favicon_bitmap_results)); + EXPECT_EQ(1u, favicon_bitmap_results.size()); + bitmap_result = favicon_bitmap_results[0]; std::string touchicon_data( - favicon.image_data->front(), - favicon.image_data->front() + favicon.image_data->size()); + bitmap_result.bitmap_data->front(), + bitmap_result.bitmap_data->front() + bitmap_result.bitmap_data->size()); - EXPECT_EQ(TOUCH_ICON, favicon.icon_type); - EXPECT_EQ(icon_url, favicon.icon_url); + EXPECT_EQ(TOUCH_ICON, bitmap_result.icon_type); + EXPECT_EQ(icon_url, bitmap_result.icon_url); EXPECT_EQ(blob_data, touchicon_data); } @@ -1327,20 +1336,23 @@ TEST_F(HistoryBackendTest, CloneFaviconIsRestrictedToSameDomain) { url, FAVICON, NULL)); // Validate starting state. - FaviconData favicon; - EXPECT_TRUE(backend_->GetFaviconFromDB(url, FAVICON, &favicon)); - EXPECT_FALSE(backend_->GetFaviconFromDB(same_domain_url, FAVICON, &favicon)); - EXPECT_FALSE(backend_->GetFaviconFromDB(foreign_domain_url, - FAVICON, &favicon)); + std::vector<FaviconBitmapResult> favicon_bitmap_results; + EXPECT_TRUE(backend_->GetFaviconFromDB(url, FAVICON, + &favicon_bitmap_results)); + EXPECT_FALSE(backend_->GetFaviconFromDB(same_domain_url, FAVICON, + &favicon_bitmap_results)); + EXPECT_FALSE(backend_->GetFaviconFromDB(foreign_domain_url, FAVICON, + &favicon_bitmap_results)); // Same-domain cloning should work. backend_->CloneFavicon(url, same_domain_url); - EXPECT_TRUE(backend_->GetFaviconFromDB(same_domain_url, FAVICON, &favicon)); + EXPECT_TRUE(backend_->GetFaviconFromDB(same_domain_url, FAVICON, + &favicon_bitmap_results)); // Foreign-domain cloning is forbidden. backend_->CloneFavicon(url, foreign_domain_url); - EXPECT_FALSE(backend_->GetFaviconFromDB(foreign_domain_url, - FAVICON, &favicon)); + EXPECT_FALSE(backend_->GetFaviconFromDB(foreign_domain_url, FAVICON, + &favicon_bitmap_results)); } TEST_F(HistoryBackendTest, QueryFilteredURLs) { diff --git a/chrome/browser/history/history_marshaling.h b/chrome/browser/history/history_marshaling.h index f52486f..3e6aee1 100644 --- a/chrome/browser/history/history_marshaling.h +++ b/chrome/browser/history/history_marshaling.h @@ -57,7 +57,7 @@ typedef CancelableRequest<HistoryService::ThumbnailDataCallback> // Favicons ------------------------------------------------------------------- -typedef CancelableRequest<FaviconService::FaviconDataCallback> +typedef CancelableRequest<FaviconService::FaviconResultsCallback> GetFaviconRequest; // Downloads ------------------------------------------------------------------ diff --git a/chrome/browser/history/history_types.cc b/chrome/browser/history/history_types.cc index d1c5728..61aecc3 100644 --- a/chrome/browser/history/history_types.cc +++ b/chrome/browser/history/history_types.cc @@ -90,14 +90,6 @@ VisitRow::VisitRow(URLID arg_url_id, VisitRow::~VisitRow() { } -// Favicons ------------------------------------------------------------------- - -ImportedFaviconUsage::ImportedFaviconUsage() { -} - -ImportedFaviconUsage::~ImportedFaviconUsage() { -} - // StarredEntry ---------------------------------------------------------------- StarredEntry::StarredEntry() @@ -429,18 +421,22 @@ IconMapping::IconMapping() IconMapping::~IconMapping() {} -// FaviconData ---------------------------------------------------------------- +// FaviconBitmapResult -------------------------------------------------------- + +FaviconBitmapResult::FaviconBitmapResult() + : expired(false), + icon_type(history::INVALID_ICON) { +} -FaviconData::FaviconData() - : known_icon(false), - expired(false), - icon_type(history::INVALID_ICON) { +FaviconBitmapResult::~FaviconBitmapResult() { } -FaviconData::~FaviconData() {} +// FaviconImageResult --------------------------------------------------------- -bool FaviconData::is_valid() { - return known_icon && image_data.get() && image_data->size(); +FaviconImageResult::FaviconImageResult() { +} + +FaviconImageResult::~FaviconImageResult() { } // FaviconBitmap -------------------------------------------------------------- @@ -453,4 +449,12 @@ FaviconBitmap::FaviconBitmap() FaviconBitmap::~FaviconBitmap() { } +// ImportedFaviconUsage -------------------------------------------------------- + +ImportedFaviconUsage::ImportedFaviconUsage() { +} + +ImportedFaviconUsage::~ImportedFaviconUsage() { +} + } // namespace history diff --git a/chrome/browser/history/history_types.h b/chrome/browser/history/history_types.h index 2408d4c..326137f 100644 --- a/chrome/browser/history/history_types.h +++ b/chrome/browser/history/history_types.h @@ -22,6 +22,7 @@ #include "chrome/common/thumbnail_score.h" #include "content/public/common/page_transition_types.h" #include "googleurl/src/gurl.h" +#include "ui/gfx/image/image.h" #include "ui/gfx/size.h" class PageUsageData; @@ -274,23 +275,6 @@ typedef std::vector<VisitRow> VisitVector; // used by HistoryBackend::AddVisits() to create new visits for a URL. typedef std::pair<base::Time, content::PageTransition> VisitInfo; -// Favicons ------------------------------------------------------------------- - -// Used by the importer to set favicons for imported bookmarks. -struct ImportedFaviconUsage { - ImportedFaviconUsage(); - ~ImportedFaviconUsage(); - - // The URL of the favicon. - GURL favicon_url; - - // The raw png-encoded data. - std::vector<unsigned char> png_data; - - // The list of URLs using this favicon. - std::set<GURL> urls; -}; - // PageVisit ------------------------------------------------------------------ // Represents a simplified version of a visit for external users. Normally, @@ -772,30 +756,58 @@ struct IconMapping { IconType icon_type; }; -// Defines the favicon stored in history backend. -struct FaviconData { - FaviconData(); - ~FaviconData(); +// Defines a favicon bitmap which best matches the desired DIP size and one of +// the desired scale factors. +struct FaviconBitmapResult { + FaviconBitmapResult(); + ~FaviconBitmapResult(); - // Returns true if the icon is known and image has data. - bool is_valid(); + // Returns true if |bitmap_data| contains a valid bitmap. + bool is_valid() const { return bitmap_data.get() && bitmap_data->size(); } - // Indicates whether the icon is known by the history backend. - bool known_icon; + // Indicates whether |bitmap_data| is expired. + bool expired; - // The bits of image. - scoped_refptr<base::RefCountedMemory> image_data; + // The bits of the bitmap. + scoped_refptr<base::RefCountedMemory> bitmap_data; - // Indicates whether image is expired. - bool expired; + // The pixel dimensions of |bitmap_data|. + gfx::Size pixel_size; - // The icon's URL. + // The URL of the containing favicon. GURL icon_url; - // The type of favicon. - history::IconType icon_type; + // The icon type of the containing favicon. + IconType icon_type; +}; + +// Defines a gfx::Image of size desired_size_in_dip composed of image +// representations for each of the desired scale factors. +struct FaviconImageResult { + FaviconImageResult(); + ~FaviconImageResult(); + + // The resulting image. + gfx::Image image; + + // The URL of the favicon which contains all of the image representations of + // |image|. + // TODO(pkotwicz): Return multiple |icon_urls| to allow |image| to have + // representations from several favicons once content::FaviconStatus supports + // multiple URLs. + GURL icon_url; }; +// A map from an icon URL to a vector of the sizes of the favicon bitmaps at +// that URL. There are several sizes for an icon URL only if the icon URL is +// for a .ico file. The sizes for an icon URL represent the sizes that a +// favicon is available from the web, not the sizes at which bitmaps are +// cached in the thumbnail database for the icon URL. For instance, if an icon +// URL represents a .ico file with 16x16 and 32x32 bitmaps, the sizes vector +// will have both sizes regardless of whether either of these bitmaps is cached +// in the thumbnail database. +typedef std::map<GURL, std::vector<gfx::Size> > IconURLSizesMap; + // Defines a favicon bitmap stored in the history backend. struct FaviconBitmap { FaviconBitmap(); @@ -817,6 +829,21 @@ struct FaviconBitmap { gfx::Size pixel_size; }; +// Used by the importer to set favicons for imported bookmarks. +struct ImportedFaviconUsage { + ImportedFaviconUsage(); + ~ImportedFaviconUsage(); + + // The URL of the favicon. + GURL favicon_url; + + // The raw png-encoded data. + std::vector<unsigned char> png_data; + + // The list of URLs using this favicon. + std::set<GURL> urls; +}; + // Abbreviated information about a visit. struct BriefVisitInfo { URLID url_id; diff --git a/chrome/browser/jumplist_win.cc b/chrome/browser/jumplist_win.cc index d66c0da..7c0a6a0 100644 --- a/chrome/browser/jumplist_win.cc +++ b/chrome/browser/jumplist_win.cc @@ -44,6 +44,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/codec/png_codec.h" +#include "ui/gfx/favicon_size.h" #include "ui/gfx/icon_util.h" using content::BrowserThread; @@ -701,15 +702,15 @@ bool JumpList::StartLoadingFavicon() { } FaviconService* favicon_service = FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); - handle_ = favicon_service->GetFaviconForURL( - profile_, url, history::FAVICON, &favicon_consumer_, + handle_ = favicon_service->GetFaviconImageForURL( + profile_, url, history::FAVICON, gfx::kFaviconSize, &favicon_consumer_, base::Bind(&JumpList::OnFaviconDataAvailable, base::Unretained(this))); return true; } void JumpList::OnFaviconDataAvailable( FaviconService::Handle handle, - history::FaviconData favicon) { + const history::FaviconImageResult& image_result) { // If there is currently a favicon request in progress, it is now outdated, // as we have received another, so nullify the handle from the old request. handle_ = NULL; @@ -718,9 +719,9 @@ void JumpList::OnFaviconDataAvailable( base::AutoLock auto_lock(list_lock_); // Attach the received data to the ShellLinkItem object. // This data will be decoded by the RunUpdate method. - if (favicon.is_valid()) { + if (!image_result.image.IsEmpty()) { if (!icon_urls_.empty() && icon_urls_.front().second) - icon_urls_.front().second->SetIconData(favicon.image_data); + icon_urls_.front().second->SetIconData(image_result.image.AsBitmap()); } if (!icon_urls_.empty()) @@ -764,11 +765,11 @@ void JumpList::RunUpdate() { file_util::CreateDirectory(icon_dir_); // Create temporary icon files for shortcuts in the "Most Visited" category. - DecodeIconData(local_most_visited_pages); + CreateIconFiles(local_most_visited_pages); // Create temporary icon files for shortcuts in the "Recently Closed" // category. - DecodeIconData(local_recently_closed_pages); + CreateIconFiles(local_recently_closed_pages); // We finished collecting all resources needed for updating an appliation // JumpList. So, create a new JumpList and replace the current JumpList @@ -777,17 +778,11 @@ void JumpList::RunUpdate() { local_recently_closed_pages); } -void JumpList::DecodeIconData(const ShellLinkItemList& item_list) { +void JumpList::CreateIconFiles(const ShellLinkItemList& item_list) { for (ShellLinkItemList::const_iterator item = item_list.begin(); item != item_list.end(); ++item) { - SkBitmap icon_bitmap; - if ((*item)->data().get() && - gfx::PNGCodec::Decode((*item)->data()->front(), - (*item)->data()->size(), - &icon_bitmap)) { - FilePath icon_path; - if (CreateIconFile(icon_bitmap, icon_dir_, &icon_path)) - (*item)->SetIcon(icon_path.value(), 0, true); - } + FilePath icon_path; + if (CreateIconFile((*item)->data(), icon_dir_, &icon_path)) + (*item)->SetIcon(icon_path.value(), 0, true); } } diff --git a/chrome/browser/jumplist_win.h b/chrome/browser/jumplist_win.h index 5cd8fdc..cf334d1 100644 --- a/chrome/browser/jumplist_win.h +++ b/chrome/browser/jumplist_win.h @@ -17,6 +17,7 @@ #include "chrome/browser/history/history_types.h" #include "chrome/browser/sessions/tab_restore_service.h" #include "chrome/browser/sessions/tab_restore_service_observer.h" +#include "third_party/skia/include/core/SkBitmap.h" namespace content { class NotificationRegistrar; @@ -51,7 +52,7 @@ class ShellLinkItem : public base::RefCountedThreadSafe<ShellLinkItem> { const std::wstring& title() const { return title_; } const std::wstring& icon() const { return icon_; } int index() const { return index_; } - scoped_refptr<base::RefCountedMemory> data() const { return data_; } + const SkBitmap& data() const { return data_; } void SetArguments(const std::wstring& arguments) { arguments_ = arguments; @@ -67,7 +68,7 @@ class ShellLinkItem : public base::RefCountedThreadSafe<ShellLinkItem> { favicon_ = favicon; } - void SetIconData(scoped_refptr<base::RefCountedMemory> data) { + void SetIconData(const SkBitmap& data) { data_ = data; } @@ -79,7 +80,7 @@ class ShellLinkItem : public base::RefCountedThreadSafe<ShellLinkItem> { std::wstring arguments_; std::wstring title_; std::wstring icon_; - scoped_refptr<base::RefCountedMemory> data_; + SkBitmap data_; int index_; bool favicon_; @@ -176,8 +177,9 @@ class JumpList : public TabRestoreServiceObserver, // a ShellLinkItem object. // When finishing loading all favicons, this function posts a task that // decompresses collected favicons and updates a JumpList. - void OnFaviconDataAvailable(HistoryService::Handle handle, - history::FaviconData favicon); + void OnFaviconDataAvailable( + HistoryService::Handle handle, + const history::FaviconImageResult& image_result); // Callback for TopSites that notifies when the "Most // Visited" list is available. This function updates the ShellLinkItemList @@ -190,9 +192,9 @@ class JumpList : public TabRestoreServiceObserver, // has been fetched. void RunUpdate(); - // Helper method for RunUpdate to decode the data about the asynchrounously + // Helper method for RunUpdate to create icon files for the asynchrounously // loaded icons. - void DecodeIconData(const ShellLinkItemList& item_list); + void CreateIconFiles(const ShellLinkItemList& item_list); private: friend class base::RefCountedThreadSafe<JumpList>; diff --git a/chrome/browser/sync/glue/session_model_associator.cc b/chrome/browser/sync/glue/session_model_associator.cc index 9c690d3..58dc3a6 100644 --- a/chrome/browser/sync/glue/session_model_associator.cc +++ b/chrome/browser/sync/glue/session_model_associator.cc @@ -42,6 +42,7 @@ #include "sync/syncable/write_transaction.h" #include "sync/util/get_session_name.h" #include "sync/util/time.h" +#include "ui/gfx/favicon_size.h" #if defined(OS_LINUX) #include "base/linux_util.h" #elif defined(OS_WIN) @@ -551,8 +552,9 @@ void SessionModelAssociator::LoadFaviconForTab(TabLink* tab_link) { load_consumer_.CancelAllRequestsForClientData(tab_id); } DVLOG(1) << "Triggering favicon load for url " << tab_link->url().spec(); - FaviconService::Handle handle = favicon_service->GetFaviconForURL( - profile_, tab_link->url(), history::FAVICON, &load_consumer_, + FaviconService::Handle handle = favicon_service->GetRawFaviconForURL( + profile_, tab_link->url(), history::FAVICON, gfx::kFaviconSize, + ui::SCALE_FACTOR_100P, &load_consumer_, base::Bind(&SessionModelAssociator::OnFaviconDataAvailable, AsWeakPtr())); load_consumer_.SetClientData(favicon_service, handle, tab_id); @@ -561,7 +563,7 @@ void SessionModelAssociator::LoadFaviconForTab(TabLink* tab_link) { void SessionModelAssociator::OnFaviconDataAvailable( FaviconService::Handle handle, - history::FaviconData favicon) { + const history::FaviconBitmapResult& bitmap_result) { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); if (!command_line.HasSwitch(switches::kSyncTabFavicons)) return; @@ -581,10 +583,10 @@ void SessionModelAssociator::OnFaviconDataAvailable( // been canceled if the url had changed, we know the url must still be // up to date. - if (favicon.is_valid()) { + if (bitmap_result.is_valid()) { DCHECK_EQ(handle, tab_link->favicon_load_handle()); tab_link->set_favicon_load_handle(0); - DCHECK_EQ(favicon.icon_type, history::FAVICON); + DCHECK_EQ(bitmap_result.icon_type, history::FAVICON); DCHECK_NE(tab_link->sync_id(), syncer::kInvalidId); // Load the sync tab node and update the favicon data. syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); @@ -599,14 +601,14 @@ void SessionModelAssociator::OnFaviconDataAvailable( tab_node.GetSessionSpecifics(); DCHECK(session_specifics.has_tab()); sync_pb::SessionTab* tab = session_specifics.mutable_tab(); - if (favicon.image_data->size() > 0) { + if (bitmap_result.bitmap_data->size() > 0) { DVLOG(1) << "Storing session favicon for " << tab_link->url() << " with size " - << favicon.image_data->size() << " bytes."; - tab->set_favicon(favicon.image_data->front(), - favicon.image_data->size()); + << bitmap_result.bitmap_data->size() << " bytes."; + tab->set_favicon(bitmap_result.bitmap_data->front(), + bitmap_result.bitmap_data->size()); tab->set_favicon_type(sync_pb::SessionTab::TYPE_WEB_FAVICON); - tab->set_favicon_source(favicon.icon_url.spec()); + tab->set_favicon_source(bitmap_result.icon_url.spec()); } else { LOG(WARNING) << "Null favicon stored for url " << tab_link->url().spec(); } diff --git a/chrome/browser/sync/glue/session_model_associator.h b/chrome/browser/sync/glue/session_model_associator.h index e87dd17..76a1fb8 100644 --- a/chrome/browser/sync/glue/session_model_associator.h +++ b/chrome/browser/sync/glue/session_model_associator.h @@ -433,8 +433,9 @@ class SessionModelAssociator // Callback method to store a tab's favicon into its sync node once it becomes // available. Does nothing if no favicon data was available. - void OnFaviconDataAvailable(FaviconService::Handle handle, - history::FaviconData favicon); + void OnFaviconDataAvailable( + FaviconService::Handle handle, + const history::FaviconBitmapResult& bitmap_result); // Used to populate a session header from the session specifics header // provided. diff --git a/chrome/browser/ui/cocoa/history_menu_bridge.h b/chrome/browser/ui/cocoa/history_menu_bridge.h index 3db8323..10a5cff 100644 --- a/chrome/browser/ui/cocoa/history_menu_bridge.h +++ b/chrome/browser/ui/cocoa/history_menu_bridge.h @@ -190,8 +190,9 @@ class HistoryMenuBridge : public content::NotificationObserver, // request it. This decodes the raw data, updates the HistoryItem, and then // sets the image on the menu. Called on the same same thread that // GetFaviconForHistoryItem() was called on (UI thread). - void GotFaviconData(FaviconService::Handle handle, - history::FaviconData favicon); + void GotFaviconData( + FaviconService::Handle handle, + const history::FaviconImageResult& image_result); // Cancels a favicon load request for a given HistoryItem, if one is in // progress. diff --git a/chrome/browser/ui/cocoa/history_menu_bridge.mm b/chrome/browser/ui/cocoa/history_menu_bridge.mm index 6c55a9e..2f73278 100644 --- a/chrome/browser/ui/cocoa/history_menu_bridge.mm +++ b/chrome/browser/ui/cocoa/history_menu_bridge.mm @@ -31,6 +31,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/codec/png_codec.h" +#include "ui/gfx/favicon_size.h" #include "ui/gfx/image/image.h" #include "ui/gfx/mac/nsimage_cache.h" @@ -454,16 +455,18 @@ HistoryMenuBridge::HistoryItem* HistoryMenuBridge::HistoryItemForTab( void HistoryMenuBridge::GetFaviconForHistoryItem(HistoryItem* item) { FaviconService* service = FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); - FaviconService::Handle handle = service->GetFaviconForURL( - profile_, item->url, history::FAVICON, &favicon_consumer_, + FaviconService::Handle handle = service->GetFaviconImageForURL( + profile_, item->url, history::FAVICON, gfx::kFaviconSize, + &favicon_consumer_, base::Bind(&HistoryMenuBridge::GotFaviconData, base::Unretained(this))); favicon_consumer_.SetClientData(service, handle, item); item->icon_handle = handle; item->icon_requested = true; } -void HistoryMenuBridge::GotFaviconData(FaviconService::Handle handle, - history::FaviconData favicon) { +void HistoryMenuBridge::GotFaviconData( + FaviconService::Handle handle, + const history::FaviconImageResult& image_result) { // Since we're going to do Cocoa-y things, make sure this is the main thread. DCHECK([NSThread isMainThread]); @@ -475,18 +478,10 @@ void HistoryMenuBridge::GotFaviconData(FaviconService::Handle handle, item->icon_requested = false; item->icon_handle = 0; - // Convert the raw data to Skia and then to a NSImage. - // TODO(rsesek): Is there an easier way to do this? - SkBitmap icon; - if (favicon.is_valid() && - gfx::PNGCodec::Decode(favicon.image_data->front(), - favicon.image_data->size(), &icon)) { - NSImage* image = gfx::SkBitmapToNSImage(icon); - if (image) { - // The conversion was successful. - item->icon.reset([image retain]); - [item->menu_item setImage:item->icon.get()]; - } + NSImage* image = image_result.image.AsNSImage(); + if (image) { + item->icon.reset([image retain]); + [item->menu_item setImage:item->icon.get()]; } } diff --git a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm index a143e43..ccffea9 100644 --- a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm +++ b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm @@ -103,9 +103,10 @@ class HistoryMenuBridgeTest : public CocoaProfileTest { bridge_->GetFaviconForHistoryItem(item); } - void GotFaviconData(FaviconService::Handle handle, - history::FaviconData favicon) { - bridge_->GotFaviconData(handle, favicon); + void GotFaviconData( + FaviconService::Handle handle, + const history::FaviconImageResult& image_result) { + bridge_->GotFaviconData(handle, image_result); } CancelableRequestConsumerTSimple<HistoryMenuBridge::HistoryItem*>& @@ -358,25 +359,15 @@ TEST_F(HistoryMenuBridgeTest, GotFaviconData) { bitmap.allocPixels(); bitmap.eraseRGB(255, 0, 0); - // Convert it to raw PNG bytes. We totally ignore color order here because - // we just want to test the roundtrip through the Bridge, not that we can - // make icons look pretty. - std::vector<unsigned char> raw; - gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &raw); - // Set up the HistoryItem. HistoryMenuBridge::HistoryItem item; item.menu_item.reset([[NSMenuItem alloc] init]); GetFaviconForHistoryItem(&item); // Pretend to be called back. - history::FaviconData favicon; - favicon.known_icon = true; - favicon.image_data = new base::RefCountedBytes(raw); - favicon.expired = false; - favicon.icon_url = GURL(); - favicon.icon_type = history::FAVICON; - GotFaviconData(item.icon_handle, favicon); + history::FaviconImageResult image_result; + image_result.image = gfx::Image(bitmap); + GotFaviconData(item.icon_handle, image_result); // Make sure the callback works. EXPECT_FALSE(item.icon_requested); diff --git a/chrome/browser/ui/intents/web_intent_picker_controller.cc b/chrome/browser/ui/intents/web_intent_picker_controller.cc index f94c146..6d0f4d7 100644 --- a/chrome/browser/ui/intents/web_intent_picker_controller.cc +++ b/chrome/browser/ui/intents/web_intent_picker_controller.cc @@ -497,10 +497,11 @@ void WebIntentPickerController::AddServiceToModel( service.disposition); pending_async_count_++; - FaviconService::Handle handle = favicon_service->GetFaviconForURL( + FaviconService::Handle handle = favicon_service->GetFaviconImageForURL( tab_contents_->profile(), service.service_url, history::FAVICON, + gfx::kFaviconSize, &favicon_consumer_, base::Bind( &WebIntentPickerController::OnFaviconDataAvailable, @@ -574,18 +575,12 @@ void WebIntentPickerController::RegistryCallsCompleted() { } void WebIntentPickerController::OnFaviconDataAvailable( - FaviconService::Handle handle, history::FaviconData favicon_data) { + FaviconService::Handle handle, + const history::FaviconImageResult& image_result) { size_t index = favicon_consumer_.GetClientDataForCurrentRequest(); - if (favicon_data.is_valid()) { - SkBitmap icon_bitmap; - - if (gfx::PNGCodec::Decode(favicon_data.image_data->front(), - favicon_data.image_data->size(), - &icon_bitmap)) { - gfx::Image icon_image(icon_bitmap); - picker_model_->UpdateFaviconAt(index, icon_image); - return; - } + if (!image_result.image.IsEmpty()) { + picker_model_->UpdateFaviconAt(index, image_result.image); + return; } AsyncOperationFinished(); diff --git a/chrome/browser/ui/intents/web_intent_picker_controller.h b/chrome/browser/ui/intents/web_intent_picker_controller.h index e13c2d5..006bea7 100644 --- a/chrome/browser/ui/intents/web_intent_picker_controller.h +++ b/chrome/browser/ui/intents/web_intent_picker_controller.h @@ -167,9 +167,10 @@ class WebIntentPickerController void WebIntentServicesForExplicitIntent( const std::vector<webkit_glue::WebIntentServiceData>& services); - // Called when FaviconData is returned from the FaviconService. - void OnFaviconDataAvailable(FaviconService::Handle handle, - history::FaviconData favicon_data); + // Called when a favicon is returned from the FaviconService. + void OnFaviconDataAvailable( + FaviconService::Handle handle, + const history::FaviconImageResult& image_result); // Called when IntentExtensionInfo is returned from the CWSIntentsRegistry. void OnCWSIntentServicesAvailable( diff --git a/chrome/browser/ui/search_engines/template_url_table_model.cc b/chrome/browser/ui/search_engines/template_url_table_model.cc index 8a1587b..0e4aa91 100644 --- a/chrome/browser/ui/search_engines/template_url_table_model.cc +++ b/chrome/browser/ui/search_engines/template_url_table_model.cc @@ -20,7 +20,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/table_model_observer.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/codec/png_codec.h" +#include "ui/gfx/favicon_size.h" #include "ui/gfx/image/image_skia.h" // Group IDs used by TemplateURLTableModel. @@ -63,7 +63,7 @@ class ModelEntry { // fetched again. This should be invoked if the url is modified. void ResetIcon() { load_state_ = NOT_LOADED; - favicon_ = SkBitmap(); + favicon_ = gfx::ImageSkia(); } private: @@ -92,25 +92,24 @@ class ModelEntry { return; } load_state_ = LOADING; - favicon_service->GetFavicon(favicon_url, history::FAVICON, - &request_consumer_, + favicon_service->GetFaviconImage(favicon_url, history::FAVICON, + gfx::kFaviconSize, &request_consumer_, base::Bind(&ModelEntry::OnFaviconDataAvailable, base::Unretained(this))); } void OnFaviconDataAvailable( FaviconService::Handle handle, - history::FaviconData favicon) { + const history::FaviconImageResult& image_result) { load_state_ = LOADED; - if (favicon.is_valid() && gfx::PNGCodec::Decode(favicon.image_data->front(), - favicon.image_data->size(), - &favicon_)) { + if (!image_result.image.IsEmpty()) { + favicon_ = image_result.image.AsImageSkia(); model_->FaviconAvailable(this); } } TemplateURL* template_url_; - SkBitmap favicon_; + gfx::ImageSkia favicon_; LoadState load_state_; TemplateURLTableModel* model_; CancelableRequestConsumer request_consumer_; diff --git a/chrome/browser/ui/toolbar/back_forward_menu_model.cc b/chrome/browser/ui/toolbar/back_forward_menu_model.cc index 3c343f5..83135f2 100644 --- a/chrome/browser/ui/toolbar/back_forward_menu_model.cc +++ b/chrome/browser/ui/toolbar/back_forward_menu_model.cc @@ -31,7 +31,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/text/text_elider.h" -#include "ui/gfx/codec/png_codec.h" +#include "ui/gfx/favicon_size.h" using content::NavigationController; using content::NavigationEntry; @@ -250,8 +250,9 @@ void BackForwardMenuModel::FetchFavicon(NavigationEntry* entry) { browser_->profile(), Profile::EXPLICIT_ACCESS); if (!favicon_service) return; - FaviconService::Handle handle = favicon_service->GetFaviconForURL( - browser_->profile(), entry->GetURL(), history::FAVICON, &load_consumer_, + FaviconService::Handle handle = favicon_service->GetFaviconImageForURL( + browser_->profile(), entry->GetURL(), history::FAVICON, + gfx::kFaviconSize, &load_consumer_, base::Bind(&BackForwardMenuModel::OnFavIconDataAvailable, base::Unretained(this))); load_consumer_.SetClientData(favicon_service, handle, entry->GetUniqueID()); @@ -259,8 +260,8 @@ void BackForwardMenuModel::FetchFavicon(NavigationEntry* entry) { void BackForwardMenuModel::OnFavIconDataAvailable( FaviconService::Handle handle, - history::FaviconData favicon) { - if (favicon.is_valid()) { + const history::FaviconImageResult& image_result) { + if (!image_result.image.IsEmpty()) { int unique_id = load_consumer_.GetClientDataForCurrentRequest(); // Find the current model_index for the unique_id. NavigationEntry* entry = NULL; @@ -283,16 +284,13 @@ void BackForwardMenuModel::OnFavIconDataAvailable( // Now that we have a valid NavigationEntry, decode the favicon and assign // it to the NavigationEntry. - gfx::Image icon(favicon.image_data->front(), favicon.image_data->size()); - if (!icon.IsEmpty()) { - entry->GetFavicon().valid = true; - entry->GetFavicon().url = favicon.icon_url; - // TODO: Once the history service returns more representations, - // use them all instead of having just the lodpi favicon. - entry->GetFavicon().image = icon; - if (menu_model_delegate()) { - menu_model_delegate()->OnIconChanged(model_index); - } + entry->GetFavicon().valid = true; + entry->GetFavicon().url = image_result.icon_url; + // TODO: Once the history service returns more representations, + // use them all instead of having just the lodpi favicon. + entry->GetFavicon().image = image_result.image; + if (menu_model_delegate()) { + menu_model_delegate()->OnIconChanged(model_index); } } } diff --git a/chrome/browser/ui/toolbar/back_forward_menu_model.h b/chrome/browser/ui/toolbar/back_forward_menu_model.h index 97f1155..23f7a3e 100644 --- a/chrome/browser/ui/toolbar/back_forward_menu_model.h +++ b/chrome/browser/ui/toolbar/back_forward_menu_model.h @@ -94,8 +94,9 @@ class BackForwardMenuModel : public ui::MenuModel { void FetchFavicon(content::NavigationEntry* entry); // Callback from the favicon service. - void OnFavIconDataAvailable(FaviconService::Handle handle, - history::FaviconData favicon); + void OnFavIconDataAvailable( + FaviconService::Handle handle, + const history::FaviconImageResult& image_result); // Allows the unit test to use its own dummy tab contents. void set_test_web_contents(content::WebContents* test_web_contents) { diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index 1aa4629..2380d3c 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc @@ -479,13 +479,16 @@ void ChromeWebUIControllerFactory::GetFaviconForURL( url.host() != extension_misc::kBookmarkManagerId) { ExtensionWebUI::GetFaviconForURL(profile, request, url); } else { - history::FaviconData favicon; - favicon.image_data = scoped_refptr<base::RefCountedMemory>( - GetFaviconResourceBytes(url)); - favicon.known_icon = favicon.image_data.get() != NULL && - favicon.image_data->size() > 0; - favicon.icon_type = history::FAVICON; - request->ForwardResultAsync(request->handle(), favicon); + scoped_refptr<base::RefCountedMemory> bitmap(GetFaviconResourceBytes(url)); + std::vector<history::FaviconBitmapResult> favicon_bitmap_results; + if (bitmap.get() && bitmap->size()) { + history::FaviconBitmapResult bitmap_result; + bitmap_result.bitmap_data = bitmap; + bitmap_result.icon_type = history::FAVICON; + favicon_bitmap_results.push_back(bitmap_result); + } + request->ForwardResultAsync(request->handle(), favicon_bitmap_results, + history::IconURLSizesMap()); } } diff --git a/chrome/browser/ui/webui/extensions/extension_icon_source.cc b/chrome/browser/ui/webui/extensions/extension_icon_source.cc index b0901fa..72f6a1e 100644 --- a/chrome/browser/ui/webui/extensions/extension_icon_source.cc +++ b/chrome/browser/ui/webui/extensions/extension_icon_source.cc @@ -29,6 +29,7 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/color_utils.h" +#include "ui/gfx/favicon_size.h" #include "ui/gfx/skbitmap_operations.h" #include "webkit/glue/image_decoder.h" @@ -213,10 +214,12 @@ void ExtensionIconSource::LoadFaviconImage(int request_id) { } GURL favicon_url = GetData(request_id)->extension->GetFullLaunchURL(); - FaviconService::Handle handle = favicon_service->GetFaviconForURL( + FaviconService::Handle handle = favicon_service->GetRawFaviconForURL( profile_, favicon_url, history::FAVICON, + gfx::kFaviconSize, + ui::SCALE_FACTOR_100P, &cancelable_consumer_, base::Bind(&ExtensionIconSource::OnFaviconDataAvailable, base::Unretained(this))); @@ -225,14 +228,14 @@ void ExtensionIconSource::LoadFaviconImage(int request_id) { void ExtensionIconSource::OnFaviconDataAvailable( FaviconService::Handle request_handle, - history::FaviconData favicon) { + const history::FaviconBitmapResult& bitmap_result) { int request_id = cancelable_consumer_.GetClientData( FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS), request_handle); ExtensionIconRequest* request = GetData(request_id); // Fallback to the default icon if there wasn't a favicon. - if (!favicon.is_valid()) { + if (!bitmap_result.is_valid()) { LoadDefaultImage(request_id); return; } @@ -241,10 +244,10 @@ void ExtensionIconSource::OnFaviconDataAvailable( // If we don't need a grayscale image, then we can bypass FinalizeImage // to avoid unnecessary conversions. ClearData(request_id); - SendResponse(request_id, favicon.image_data); + SendResponse(request_id, bitmap_result.bitmap_data); } else { - FinalizeImage(ToBitmap(favicon.image_data->front(), - favicon.image_data->size()), request_id); + FinalizeImage(ToBitmap(bitmap_result.bitmap_data->front(), + bitmap_result.bitmap_data->size()), request_id); } } diff --git a/chrome/browser/ui/webui/extensions/extension_icon_source.h b/chrome/browser/ui/webui/extensions/extension_icon_source.h index 86dde18..2c409ff 100644 --- a/chrome/browser/ui/webui/extensions/extension_icon_source.h +++ b/chrome/browser/ui/webui/extensions/extension_icon_source.h @@ -108,8 +108,9 @@ class ExtensionIconSource : public ChromeURLDataManager::DataSource, void LoadFaviconImage(int request_id); // FaviconService callback - void OnFaviconDataAvailable(FaviconService::Handle request_handle, - history::FaviconData favicon); + void OnFaviconDataAvailable( + FaviconService::Handle request_handle, + const history::FaviconBitmapResult& bitmap_result); // ImageLoadingTracker::Observer virtual void OnImageLoaded(const gfx::Image& image, diff --git a/chrome/browser/ui/webui/favicon_source.cc b/chrome/browser/ui/webui/favicon_source.cc index 3ba9bef..b2fe5f9 100644 --- a/chrome/browser/ui/webui/favicon_source.cc +++ b/chrome/browser/ui/webui/favicon_source.cc @@ -15,6 +15,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/layout.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/favicon_size.h" FaviconSource::FaviconSource(Profile* profile, IconType type) : DataSource(type == FAVICON ? chrome::kChromeUIFaviconHost : @@ -53,9 +54,11 @@ void FaviconSource::StartDataRequest(const std::string& path, FaviconService::Handle handle; if (path.size() > 8 && path.substr(0, 8) == "iconurl/") { // TODO : Change GetFavicon to support combination of IconType. - handle = favicon_service->GetFavicon( + handle = favicon_service->GetRawFavicon( GURL(path.substr(8)), history::FAVICON, + gfx::kFaviconSize, + ui::SCALE_FACTOR_100P, &cancelable_consumer_, base::Bind(&FaviconSource::OnFaviconDataAvailable, base::Unretained(this))); @@ -105,10 +108,12 @@ void FaviconSource::StartDataRequest(const std::string& path, } // TODO(estade): fetch the requested size. - handle = favicon_service->GetFaviconForURL( + handle = favicon_service->GetRawFaviconForURL( profile_, url, icon_types_, + gfx::kFaviconSize, + ui::SCALE_FACTOR_100P, &cancelable_consumer_, base::Bind(&FaviconSource::OnFaviconDataAvailable, base::Unretained(this))); @@ -132,15 +137,15 @@ bool FaviconSource::ShouldReplaceExistingSource() const { void FaviconSource::OnFaviconDataAvailable( FaviconService::Handle request_handle, - history::FaviconData favicon) { + const history::FaviconBitmapResult& bitmap_result) { FaviconService* favicon_service = FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); int request_id = cancelable_consumer_.GetClientData(favicon_service, request_handle); - if (favicon.is_valid()) { + if (bitmap_result.is_valid()) { // Forward the data along to the networking system. - SendResponse(request_id, favicon.image_data); + SendResponse(request_id, bitmap_result.bitmap_data); } else { SendDefaultResponse(request_id); } diff --git a/chrome/browser/ui/webui/favicon_source.h b/chrome/browser/ui/webui/favicon_source.h index 319c88d..b501c8b 100644 --- a/chrome/browser/ui/webui/favicon_source.h +++ b/chrome/browser/ui/webui/favicon_source.h @@ -54,8 +54,9 @@ class FaviconSource : public ChromeURLDataManager::DataSource { void Init(Profile* profile, IconType type); // Called when favicon data is available from the history backend. - void OnFaviconDataAvailable(FaviconService::Handle request_handle, - history::FaviconData favicon); + void OnFaviconDataAvailable( + FaviconService::Handle request_handle, + const history::FaviconBitmapResult& bitmap_result); // Sends the default favicon. void SendDefaultResponse(int request_id); diff --git a/chrome/browser/ui/webui/ntp/android/bookmarks_handler.cc b/chrome/browser/ui/webui/ntp/android/bookmarks_handler.cc index 21199c0..05d8d35 100644 --- a/chrome/browser/ui/webui/ntp/android/bookmarks_handler.cc +++ b/chrome/browser/ui/webui/ntp/android/bookmarks_handler.cc @@ -21,6 +21,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/color_analysis.h" +#include "ui/gfx/favicon_size.h" using base::Int64ToString; using content::BrowserThread; @@ -353,10 +354,12 @@ void BookmarksHandler::HandleCreateHomeScreenBookmarkShortcut( FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( profile, Profile::EXPLICIT_ACCESS); - FaviconService::Handle handle = favicon_service->GetFaviconForURL( + FaviconService::Handle handle = favicon_service->GetRawFaviconForURL( profile, node->url(), history::FAVICON | history::TOUCH_ICON, + gfx::kFaviconSize, + ui::SCALE_FACTOR_100P, &cancelable_consumer_, base::Bind(&BookmarksHandler::OnShortcutFaviconDataAvailable, base::Unretained(this))); @@ -366,13 +369,13 @@ void BookmarksHandler::HandleCreateHomeScreenBookmarkShortcut( void BookmarksHandler::OnShortcutFaviconDataAvailable( FaviconService::Handle handle, - history::FaviconData favicon) { + const history::FaviconBitmapResult& bitmap_result) { SkColor color = SK_ColorWHITE; SkBitmap favicon_bitmap; - if (favicon.is_valid()) { - color = GetDominantColorForFavicon(favicon.image_data); - gfx::PNGCodec::Decode(favicon.image_data->front(), - favicon.image_data->size(), + if (bitmap_result.is_valid()) { + color = GetDominantColorForFavicon(bitmap_result.bitmap_data); + gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), + bitmap_result.bitmap_data->size(), &favicon_bitmap); } diff --git a/chrome/browser/ui/webui/ntp/android/bookmarks_handler.h b/chrome/browser/ui/webui/ntp/android/bookmarks_handler.h index cddae74..6cce36d 100644 --- a/chrome/browser/ui/webui/ntp/android/bookmarks_handler.h +++ b/chrome/browser/ui/webui/ntp/android/bookmarks_handler.h @@ -130,8 +130,9 @@ class BookmarksHandler : public content::WebUIMessageHandler, // Called once the favicon is loaded during creation of the bookmark shortcuts // and is available for use. - void OnShortcutFaviconDataAvailable(FaviconService::Handle handle, - history::FaviconData favicon); + void OnShortcutFaviconDataAvailable( + FaviconService::Handle handle, + const history::FaviconBitmapResult& bitmap_result); DISALLOW_COPY_AND_ASSIGN(BookmarksHandler); }; diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc index 51dd848..1cbc800 100644 --- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc +++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc @@ -54,6 +54,7 @@ #include "ui/base/animation/animation.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/codec/png_codec.h" +#include "ui/gfx/favicon_size.h" using application_launch::LaunchParams; using application_launch::OpenApplication; @@ -704,8 +705,9 @@ void AppLauncherHandler::HandleGenerateAppForLink(const ListValue* args) { install_info->app_url = launch_url; install_info->page_ordinal = page_ordinal; - FaviconService::Handle h = favicon_service->GetFaviconForURL( - profile, launch_url, history::FAVICON, &favicon_consumer_, + FaviconService::Handle h = favicon_service->GetFaviconImageForURL( + profile, launch_url, history::FAVICON, gfx::kFaviconSize, + &favicon_consumer_, base::Bind(&AppLauncherHandler::OnFaviconForApp, base::Unretained(this))); favicon_consumer_.SetClientData(favicon_service, h, install_info.release()); } @@ -754,8 +756,9 @@ void AppLauncherHandler::HandleSetNotificationsDisabled( extension_service_->SetAppNotificationDisabled(extension_id, disabled); } -void AppLauncherHandler::OnFaviconForApp(FaviconService::Handle handle, - history::FaviconData data) { +void AppLauncherHandler::OnFaviconForApp( + FaviconService::Handle handle, + const history::FaviconImageResult& image_result) { scoped_ptr<AppInstallInfo> install_info( favicon_consumer_.GetClientDataForCurrentRequest()); scoped_ptr<WebApplicationInfo> web_app(new WebApplicationInfo()); @@ -764,16 +767,12 @@ void AppLauncherHandler::OnFaviconForApp(FaviconService::Handle handle, web_app->app_url = install_info->app_url; web_app->urls.push_back(install_info->app_url); - WebApplicationInfo::IconInfo icon; - web_app->icons.push_back(icon); - if (data.is_valid() && gfx::PNGCodec::Decode(data.image_data->front(), - data.image_data->size(), - &(web_app->icons[0].data))) { - web_app->icons[0].url = GURL(); - web_app->icons[0].width = web_app->icons[0].data.width(); - web_app->icons[0].height = web_app->icons[0].data.height(); - } else { - web_app->icons.clear(); + if (!image_result.image.IsEmpty()) { + WebApplicationInfo::IconInfo icon; + icon.data = image_result.image.AsBitmap(); + icon.width = icon.data.width(); + icon.height = icon.data.height(); + web_app->icons.push_back(icon); } scoped_refptr<CrxInstaller> installer( diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.h b/chrome/browser/ui/webui/ntp/app_launcher_handler.h index cdc767c..d06b48a 100644 --- a/chrome/browser/ui/webui/ntp/app_launcher_handler.h +++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.h @@ -155,7 +155,7 @@ class AppLauncherHandler : public content::WebUIMessageHandler, // Continuation for installing a bookmark app after favicon lookup. void OnFaviconForApp(FaviconService::Handle handle, - history::FaviconData data); + const history::FaviconImageResult& image_result); // Sends |highlight_app_id_| to the js. void SetAppToBeHighlighted(); diff --git a/chrome/browser/ui/webui/ntp/favicon_webui_handler.cc b/chrome/browser/ui/webui/ntp/favicon_webui_handler.cc index 1691142..e226c5f 100644 --- a/chrome/browser/ui/webui/ntp/favicon_webui_handler.cc +++ b/chrome/browser/ui/webui/ntp/favicon_webui_handler.cc @@ -23,6 +23,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/color_analysis.h" +#include "ui/gfx/favicon_size.h" namespace { @@ -109,10 +110,12 @@ void FaviconWebUIHandler::HandleGetFaviconDominantColor(const ListValue* args) { } dom_id_map_[id_] = dom_id; - FaviconService::Handle handle = favicon_service->GetFaviconForURL( + FaviconService::Handle handle = favicon_service->GetRawFaviconForURL( Profile::FromWebUI(web_ui()), url, history::FAVICON, + gfx::kFaviconSize, + ui::SCALE_FACTOR_100P, &consumer_, base::Bind(&FaviconWebUIHandler::OnFaviconDataAvailable, base::Unretained(this))); @@ -121,14 +124,14 @@ void FaviconWebUIHandler::HandleGetFaviconDominantColor(const ListValue* args) { void FaviconWebUIHandler::OnFaviconDataAvailable( FaviconService::Handle request_handle, - history::FaviconData favicon) { + const history::FaviconBitmapResult& bitmap_result) { FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( Profile::FromWebUI(web_ui()), Profile::EXPLICIT_ACCESS); int id = consumer_.GetClientData(favicon_service, request_handle); scoped_ptr<StringValue> color_value; - if (favicon.is_valid()) - color_value.reset(GetDominantColorCssString(favicon.image_data)); + if (bitmap_result.is_valid()) + color_value.reset(GetDominantColorCssString(bitmap_result.bitmap_data)); else color_value.reset(new StringValue("#919191")); diff --git a/chrome/browser/ui/webui/ntp/favicon_webui_handler.h b/chrome/browser/ui/webui/ntp/favicon_webui_handler.h index 67d9928..9aa7cb6 100644 --- a/chrome/browser/ui/webui/ntp/favicon_webui_handler.h +++ b/chrome/browser/ui/webui/ntp/favicon_webui_handler.h @@ -40,8 +40,9 @@ class FaviconWebUIHandler : public content::WebUIMessageHandler { private: // Called when favicon data is available from the history backend. - void OnFaviconDataAvailable(FaviconService::Handle request_handle, - history::FaviconData favicon); + void OnFaviconDataAvailable( + FaviconService::Handle request_handle, + const history::FaviconBitmapResult& bitmap_result); CancelableRequestConsumerTSimple<int> consumer_; |