diff options
Diffstat (limited to 'chrome/browser/favicon/favicon_service.cc')
-rw-r--r-- | chrome/browser/favicon/favicon_service.cc | 239 |
1 files changed, 217 insertions, 22 deletions
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()); } |