Index: chrome/browser/favicon/favicon_service.cc |
diff --git a/chrome/browser/favicon/favicon_service.cc b/chrome/browser/favicon/favicon_service.cc |
index ff3d6e572a5a96cab137fb30538c26916918201f..ec34ed10c7f7294048dfbf4d5237783c30a80f5b 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()); |
} |