Android Chromoting: Remove exit-fullscreen button.
[chromium-blink-merge.git] / components / favicon / core / favicon_service.cc
blobdd1ada4c0fe0500635e7174e9e5252d15df3c5e4
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/favicon/core/favicon_service.h"
7 #include <cmath>
9 #include "base/hash.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "components/favicon/core/favicon_client.h"
13 #include "components/favicon_base/favicon_util.h"
14 #include "components/favicon_base/select_favicon_frames.h"
15 #include "components/history/core/browser/history_service.h"
16 #include "third_party/skia/include/core/SkBitmap.h"
17 #include "ui/gfx/codec/png_codec.h"
18 #include "ui/gfx/favicon_size.h"
19 #include "ui/gfx/image/image_skia.h"
20 #include "url/gurl.h"
22 namespace favicon {
23 namespace {
25 // Helper to run callback with empty results if we cannot get the history
26 // service.
27 base::CancelableTaskTracker::TaskId RunWithEmptyResultAsync(
28 const favicon_base::FaviconResultsCallback& callback,
29 base::CancelableTaskTracker* tracker) {
30 scoped_refptr<base::SingleThreadTaskRunner> thread_runner(
31 base::ThreadTaskRunnerHandle::Get());
32 return tracker->PostTask(
33 thread_runner.get(), FROM_HERE,
34 base::Bind(callback,
35 std::vector<favicon_base::FaviconRawBitmapResult>()));
38 // Returns a vector of pixel edge sizes from |size_in_dip| and
39 // favicon_base::GetFaviconScales().
40 std::vector<int> GetPixelSizesForFaviconScales(int size_in_dip) {
41 std::vector<float> scales = favicon_base::GetFaviconScales();
42 std::vector<int> sizes_in_pixel;
43 for (size_t i = 0; i < scales.size(); ++i) {
44 sizes_in_pixel.push_back(std::ceil(size_in_dip * scales[i]));
46 return sizes_in_pixel;
49 } // namespace
51 FaviconService::FaviconService(FaviconClient* favicon_client,
52 history::HistoryService* history_service)
53 : history_service_(history_service), favicon_client_(favicon_client) {
56 FaviconService::~FaviconService() {
59 // static
60 void FaviconService::FaviconResultsCallbackRunner(
61 const favicon_base::FaviconResultsCallback& callback,
62 const std::vector<favicon_base::FaviconRawBitmapResult>* results) {
63 callback.Run(*results);
66 base::CancelableTaskTracker::TaskId FaviconService::GetFaviconImage(
67 const GURL& icon_url,
68 const favicon_base::FaviconImageCallback& callback,
69 base::CancelableTaskTracker* tracker) {
70 favicon_base::FaviconResultsCallback callback_runner =
71 base::Bind(&FaviconService::RunFaviconImageCallbackWithBitmapResults,
72 base::Unretained(this), callback, gfx::kFaviconSize);
73 if (history_service_) {
74 std::vector<GURL> icon_urls;
75 icon_urls.push_back(icon_url);
76 return history_service_->GetFavicons(
77 icon_urls,
78 favicon_base::FAVICON,
79 GetPixelSizesForFaviconScales(gfx::kFaviconSize),
80 callback_runner,
81 tracker);
83 return RunWithEmptyResultAsync(callback_runner, tracker);
86 base::CancelableTaskTracker::TaskId FaviconService::GetRawFavicon(
87 const GURL& icon_url,
88 favicon_base::IconType icon_type,
89 int desired_size_in_pixel,
90 const favicon_base::FaviconRawBitmapCallback& callback,
91 base::CancelableTaskTracker* tracker) {
92 favicon_base::FaviconResultsCallback callback_runner =
93 base::Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
94 base::Unretained(this), callback, desired_size_in_pixel);
96 if (history_service_) {
97 std::vector<GURL> icon_urls;
98 icon_urls.push_back(icon_url);
99 std::vector<int> desired_sizes_in_pixel;
100 desired_sizes_in_pixel.push_back(desired_size_in_pixel);
102 return history_service_->GetFavicons(
103 icon_urls, icon_type, desired_sizes_in_pixel, callback_runner, tracker);
105 return RunWithEmptyResultAsync(callback_runner, tracker);
108 base::CancelableTaskTracker::TaskId FaviconService::GetFavicon(
109 const GURL& icon_url,
110 favicon_base::IconType icon_type,
111 int desired_size_in_dip,
112 const favicon_base::FaviconResultsCallback& callback,
113 base::CancelableTaskTracker* tracker) {
114 if (history_service_) {
115 std::vector<GURL> icon_urls;
116 icon_urls.push_back(icon_url);
117 return history_service_->GetFavicons(
118 icon_urls,
119 icon_type,
120 GetPixelSizesForFaviconScales(desired_size_in_dip),
121 callback,
122 tracker);
124 return RunWithEmptyResultAsync(callback, tracker);
127 base::CancelableTaskTracker::TaskId FaviconService::GetFaviconImageForPageURL(
128 const GURL& page_url,
129 const favicon_base::FaviconImageCallback& callback,
130 base::CancelableTaskTracker* tracker) {
131 return GetFaviconForPageURLImpl(
132 page_url, favicon_base::FAVICON,
133 GetPixelSizesForFaviconScales(gfx::kFaviconSize),
134 base::Bind(&FaviconService::RunFaviconImageCallbackWithBitmapResults,
135 base::Unretained(this), callback, gfx::kFaviconSize),
136 tracker);
139 base::CancelableTaskTracker::TaskId FaviconService::GetRawFaviconForPageURL(
140 const GURL& page_url,
141 int icon_types,
142 int desired_size_in_pixel,
143 const favicon_base::FaviconRawBitmapCallback& callback,
144 base::CancelableTaskTracker* tracker) {
145 std::vector<int> desired_sizes_in_pixel;
146 desired_sizes_in_pixel.push_back(desired_size_in_pixel);
147 return GetFaviconForPageURLImpl(
148 page_url, icon_types, desired_sizes_in_pixel,
149 base::Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
150 base::Unretained(this), callback, desired_size_in_pixel),
151 tracker);
154 base::CancelableTaskTracker::TaskId
155 FaviconService::GetLargestRawFaviconForPageURL(
156 const GURL& page_url,
157 const std::vector<int>& icon_types,
158 int minimum_size_in_pixels,
159 const favicon_base::FaviconRawBitmapCallback& callback,
160 base::CancelableTaskTracker* tracker) {
161 favicon_base::FaviconResultsCallback favicon_results_callback =
162 base::Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
163 base::Unretained(this), callback, 0);
164 if (favicon_client_ && favicon_client_->IsNativeApplicationURL(page_url)) {
165 std::vector<int> desired_sizes_in_pixel;
166 desired_sizes_in_pixel.push_back(0);
167 return favicon_client_->GetFaviconForNativeApplicationURL(
168 page_url, desired_sizes_in_pixel, favicon_results_callback, tracker);
170 if (history_service_) {
171 return history_service_->GetLargestFaviconForURL(page_url, icon_types,
172 minimum_size_in_pixels, callback, tracker);
174 return RunWithEmptyResultAsync(favicon_results_callback, tracker);
177 base::CancelableTaskTracker::TaskId FaviconService::GetFaviconForPageURL(
178 const GURL& page_url,
179 int icon_types,
180 int desired_size_in_dip,
181 const favicon_base::FaviconResultsCallback& callback,
182 base::CancelableTaskTracker* tracker) {
183 return GetFaviconForPageURLImpl(
184 page_url,
185 icon_types,
186 GetPixelSizesForFaviconScales(desired_size_in_dip),
187 callback,
188 tracker);
191 base::CancelableTaskTracker::TaskId
192 FaviconService::UpdateFaviconMappingsAndFetch(
193 const GURL& page_url,
194 const std::vector<GURL>& icon_urls,
195 int icon_types,
196 int desired_size_in_dip,
197 const favicon_base::FaviconResultsCallback& callback,
198 base::CancelableTaskTracker* tracker) {
199 if (history_service_) {
200 return history_service_->UpdateFaviconMappingsAndFetch(
201 page_url,
202 icon_urls,
203 icon_types,
204 GetPixelSizesForFaviconScales(desired_size_in_dip),
205 callback,
206 tracker);
208 return RunWithEmptyResultAsync(callback, tracker);
211 base::CancelableTaskTracker::TaskId FaviconService::GetLargestRawFaviconForID(
212 favicon_base::FaviconID favicon_id,
213 const favicon_base::FaviconRawBitmapCallback& callback,
214 base::CancelableTaskTracker* tracker) {
215 // Use 0 as |desired_size| to get the largest bitmap for |favicon_id| without
216 // any resizing.
217 int desired_size = 0;
218 favicon_base::FaviconResultsCallback callback_runner =
219 base::Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
220 base::Unretained(this), callback, desired_size);
222 if (history_service_) {
223 return history_service_->GetFaviconForID(
224 favicon_id, desired_size, callback_runner, tracker);
226 return RunWithEmptyResultAsync(callback_runner, tracker);
229 void FaviconService::SetFaviconOutOfDateForPage(const GURL& page_url) {
230 if (history_service_)
231 history_service_->SetFaviconsOutOfDateForPage(page_url);
234 void FaviconService::CloneFavicon(const GURL& old_page_url,
235 const GURL& new_page_url) {
236 if (history_service_)
237 history_service_->CloneFavicons(old_page_url, new_page_url);
240 void FaviconService::SetImportedFavicons(
241 const favicon_base::FaviconUsageDataList& favicon_usage) {
242 if (history_service_)
243 history_service_->SetImportedFavicons(favicon_usage);
246 void FaviconService::MergeFavicon(
247 const GURL& page_url,
248 const GURL& icon_url,
249 favicon_base::IconType icon_type,
250 scoped_refptr<base::RefCountedMemory> bitmap_data,
251 const gfx::Size& pixel_size) {
252 if (history_service_) {
253 history_service_->MergeFavicon(page_url, icon_url, icon_type, bitmap_data,
254 pixel_size);
258 void FaviconService::SetFavicons(const GURL& page_url,
259 const GURL& icon_url,
260 favicon_base::IconType icon_type,
261 const gfx::Image& image) {
262 if (!history_service_)
263 return;
265 gfx::ImageSkia image_skia = image.AsImageSkia();
266 image_skia.EnsureRepsForSupportedScales();
267 const std::vector<gfx::ImageSkiaRep>& image_reps = image_skia.image_reps();
268 std::vector<SkBitmap> bitmaps;
269 const std::vector<float> favicon_scales = favicon_base::GetFaviconScales();
270 for (size_t i = 0; i < image_reps.size(); ++i) {
271 // Don't save if the scale isn't one of supported favicon scales.
272 if (std::find(favicon_scales.begin(),
273 favicon_scales.end(),
274 image_reps[i].scale()) == favicon_scales.end()) {
275 continue;
277 bitmaps.push_back(image_reps[i].sk_bitmap());
279 history_service_->SetFavicons(page_url, icon_type, icon_url, bitmaps);
282 void FaviconService::UnableToDownloadFavicon(const GURL& icon_url) {
283 MissingFaviconURLHash url_hash = base::Hash(icon_url.spec());
284 missing_favicon_urls_.insert(url_hash);
287 bool FaviconService::WasUnableToDownloadFavicon(const GURL& icon_url) const {
288 MissingFaviconURLHash url_hash = base::Hash(icon_url.spec());
289 return missing_favicon_urls_.find(url_hash) != missing_favicon_urls_.end();
292 void FaviconService::ClearUnableToDownloadFavicons() {
293 missing_favicon_urls_.clear();
296 base::CancelableTaskTracker::TaskId FaviconService::GetFaviconForPageURLImpl(
297 const GURL& page_url,
298 int icon_types,
299 const std::vector<int>& desired_sizes_in_pixel,
300 const favicon_base::FaviconResultsCallback& callback,
301 base::CancelableTaskTracker* tracker) {
302 if (favicon_client_ && favicon_client_->IsNativeApplicationURL(page_url)) {
303 return favicon_client_->GetFaviconForNativeApplicationURL(
304 page_url, desired_sizes_in_pixel, callback, tracker);
306 if (history_service_) {
307 return history_service_->GetFaviconsForURL(page_url,
308 icon_types,
309 desired_sizes_in_pixel,
310 callback,
311 tracker);
313 return RunWithEmptyResultAsync(callback, tracker);
316 void FaviconService::RunFaviconImageCallbackWithBitmapResults(
317 const favicon_base::FaviconImageCallback& callback,
318 int desired_size_in_dip,
319 const std::vector<favicon_base::FaviconRawBitmapResult>&
320 favicon_bitmap_results) {
321 favicon_base::FaviconImageResult image_result;
322 image_result.image = favicon_base::SelectFaviconFramesFromPNGs(
323 favicon_bitmap_results,
324 favicon_base::GetFaviconScales(),
325 desired_size_in_dip);
326 favicon_base::SetFaviconColorSpace(&image_result.image);
328 image_result.icon_url = image_result.image.IsEmpty() ?
329 GURL() : favicon_bitmap_results[0].icon_url;
330 callback.Run(image_result);
333 void FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults(
334 const favicon_base::FaviconRawBitmapCallback& callback,
335 int desired_size_in_pixel,
336 const std::vector<favicon_base::FaviconRawBitmapResult>&
337 favicon_bitmap_results) {
338 if (favicon_bitmap_results.empty() || !favicon_bitmap_results[0].is_valid()) {
339 callback.Run(favicon_base::FaviconRawBitmapResult());
340 return;
343 favicon_base::FaviconRawBitmapResult bitmap_result =
344 favicon_bitmap_results[0];
346 // If the desired size is 0, SelectFaviconFrames() will return the largest
347 // bitmap without doing any resizing. As |favicon_bitmap_results| has bitmap
348 // data for a single bitmap, return it and avoid an unnecessary decode.
349 if (desired_size_in_pixel == 0) {
350 callback.Run(bitmap_result);
351 return;
354 // If history bitmap is already desired pixel size, return early.
355 if (bitmap_result.pixel_size.width() == desired_size_in_pixel &&
356 bitmap_result.pixel_size.height() == desired_size_in_pixel) {
357 callback.Run(bitmap_result);
358 return;
361 // Convert raw bytes to SkBitmap, resize via SelectFaviconFrames(), then
362 // convert back.
363 std::vector<float> desired_favicon_scales;
364 desired_favicon_scales.push_back(1.0f);
365 gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs(
366 favicon_bitmap_results, desired_favicon_scales, desired_size_in_pixel);
368 std::vector<unsigned char> resized_bitmap_data;
369 if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_image.AsBitmap(), false,
370 &resized_bitmap_data)) {
371 callback.Run(favicon_base::FaviconRawBitmapResult());
372 return;
375 bitmap_result.bitmap_data = base::RefCountedBytes::TakeVector(
376 &resized_bitmap_data);
377 callback.Run(bitmap_result);
380 } // namespace favicon