ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / favicon / favicon_service.cc
blob2bbdadb7b24f594affb165d9d1dd4d622ed04285
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 "chrome/browser/favicon/favicon_service.h"
7 #include <cmath>
9 #include "base/hash.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "chrome/browser/history/history_backend.h"
12 #include "chrome/browser/history/history_service.h"
13 #include "chrome/browser/history/history_service_factory.h"
14 #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
15 #include "chrome/common/url_constants.h"
16 #include "components/favicon_base/favicon_util.h"
17 #include "components/favicon_base/select_favicon_frames.h"
18 #include "extensions/common/constants.h"
19 #include "third_party/skia/include/core/SkBitmap.h"
20 #include "ui/gfx/codec/png_codec.h"
21 #include "ui/gfx/favicon_size.h"
22 #include "ui/gfx/image/image_skia.h"
23 #include "url/gurl.h"
25 using base::Bind;
27 namespace {
29 void CancelOrRunFaviconResultsCallback(
30 const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
31 const favicon_base::FaviconResultsCallback& callback,
32 const std::vector<favicon_base::FaviconRawBitmapResult>& results) {
33 if (is_canceled.Run())
34 return;
35 callback.Run(results);
38 // Helper to run callback with empty results if we cannot get the history
39 // service.
40 base::CancelableTaskTracker::TaskId RunWithEmptyResultAsync(
41 const favicon_base::FaviconResultsCallback& callback,
42 base::CancelableTaskTracker* tracker) {
43 return tracker->PostTask(
44 base::MessageLoopProxy::current().get(),
45 FROM_HERE,
46 Bind(callback, std::vector<favicon_base::FaviconRawBitmapResult>()));
49 // Return the TaskId to retreive the favicon from chrome specific URL.
50 base::CancelableTaskTracker::TaskId GetFaviconForChromeURL(
51 Profile* profile,
52 const GURL& page_url,
53 const std::vector<int>& desired_sizes_in_pixel,
54 const favicon_base::FaviconResultsCallback& callback,
55 base::CancelableTaskTracker* tracker) {
56 base::CancelableTaskTracker::IsCanceledCallback is_canceled_cb;
57 base::CancelableTaskTracker::TaskId id =
58 tracker->NewTrackedTaskId(&is_canceled_cb);
59 favicon_base::FaviconResultsCallback cancelable_cb =
60 Bind(&CancelOrRunFaviconResultsCallback, is_canceled_cb, callback);
61 ChromeWebUIControllerFactory::GetInstance()->GetFaviconForURL(
62 profile, page_url, desired_sizes_in_pixel, cancelable_cb);
63 return id;
66 // Returns a vector of pixel edge sizes from |size_in_dip| and
67 // favicon_base::GetFaviconScales().
68 std::vector<int> GetPixelSizesForFaviconScales(int size_in_dip) {
69 std::vector<float> scales = favicon_base::GetFaviconScales();
70 std::vector<int> sizes_in_pixel;
71 for (size_t i = 0; i < scales.size(); ++i) {
72 sizes_in_pixel.push_back(std::ceil(size_in_dip * scales[i]));
74 return sizes_in_pixel;
77 } // namespace
79 FaviconService::FaviconService(Profile* profile, FaviconClient* favicon_client)
80 : history_service_(HistoryServiceFactory::GetForProfile(
81 profile,
82 ServiceAccessType::EXPLICIT_ACCESS)),
83 profile_(profile),
84 favicon_client_(favicon_client) {
87 // static
88 void FaviconService::FaviconResultsCallbackRunner(
89 const favicon_base::FaviconResultsCallback& callback,
90 const std::vector<favicon_base::FaviconRawBitmapResult>* results) {
91 callback.Run(*results);
94 base::CancelableTaskTracker::TaskId FaviconService::GetFaviconImage(
95 const GURL& icon_url,
96 const favicon_base::FaviconImageCallback& callback,
97 base::CancelableTaskTracker* tracker) {
98 favicon_base::FaviconResultsCallback callback_runner =
99 Bind(&FaviconService::RunFaviconImageCallbackWithBitmapResults,
100 base::Unretained(this), callback, gfx::kFaviconSize);
101 if (history_service_) {
102 std::vector<GURL> icon_urls;
103 icon_urls.push_back(icon_url);
104 return history_service_->GetFavicons(
105 icon_urls,
106 favicon_base::FAVICON,
107 GetPixelSizesForFaviconScales(gfx::kFaviconSize),
108 callback_runner,
109 tracker);
111 return RunWithEmptyResultAsync(callback_runner, tracker);
114 base::CancelableTaskTracker::TaskId FaviconService::GetRawFavicon(
115 const GURL& icon_url,
116 favicon_base::IconType icon_type,
117 int desired_size_in_pixel,
118 const favicon_base::FaviconRawBitmapCallback& callback,
119 base::CancelableTaskTracker* tracker) {
120 favicon_base::FaviconResultsCallback callback_runner =
121 Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
122 base::Unretained(this),
123 callback,
124 desired_size_in_pixel);
126 if (history_service_) {
127 std::vector<GURL> icon_urls;
128 icon_urls.push_back(icon_url);
129 std::vector<int> desired_sizes_in_pixel;
130 desired_sizes_in_pixel.push_back(desired_size_in_pixel);
132 return history_service_->GetFavicons(
133 icon_urls, icon_type, desired_sizes_in_pixel, callback_runner, tracker);
135 return RunWithEmptyResultAsync(callback_runner, tracker);
138 base::CancelableTaskTracker::TaskId FaviconService::GetFavicon(
139 const GURL& icon_url,
140 favicon_base::IconType icon_type,
141 int desired_size_in_dip,
142 const favicon_base::FaviconResultsCallback& callback,
143 base::CancelableTaskTracker* tracker) {
144 if (history_service_) {
145 std::vector<GURL> icon_urls;
146 icon_urls.push_back(icon_url);
147 return history_service_->GetFavicons(
148 icon_urls,
149 icon_type,
150 GetPixelSizesForFaviconScales(desired_size_in_dip),
151 callback,
152 tracker);
154 return RunWithEmptyResultAsync(callback, tracker);
157 base::CancelableTaskTracker::TaskId FaviconService::GetFaviconImageForPageURL(
158 const GURL& page_url,
159 const favicon_base::FaviconImageCallback& callback,
160 base::CancelableTaskTracker* tracker) {
161 return GetFaviconForPageURLImpl(
162 page_url,
163 favicon_base::FAVICON,
164 GetPixelSizesForFaviconScales(gfx::kFaviconSize),
165 Bind(&FaviconService::RunFaviconImageCallbackWithBitmapResults,
166 base::Unretained(this),
167 callback,
168 gfx::kFaviconSize),
169 tracker);
172 base::CancelableTaskTracker::TaskId FaviconService::GetRawFaviconForPageURL(
173 const GURL& page_url,
174 int icon_types,
175 int desired_size_in_pixel,
176 const favicon_base::FaviconRawBitmapCallback& callback,
177 base::CancelableTaskTracker* tracker) {
178 std::vector<int> desired_sizes_in_pixel;
179 desired_sizes_in_pixel.push_back(desired_size_in_pixel);
180 return GetFaviconForPageURLImpl(
181 page_url,
182 icon_types,
183 desired_sizes_in_pixel,
184 Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
185 base::Unretained(this),
186 callback,
187 desired_size_in_pixel),
188 tracker);
191 base::CancelableTaskTracker::TaskId
192 FaviconService::GetLargestRawFaviconForPageURL(
193 const GURL& page_url,
194 const std::vector<int>& icon_types,
195 int minimum_size_in_pixels,
196 const favicon_base::FaviconRawBitmapCallback& callback,
197 base::CancelableTaskTracker* tracker) {
198 favicon_base::FaviconResultsCallback favicon_results_callback =
199 Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
200 base::Unretained(this),
201 callback,
203 if (page_url.SchemeIs(content::kChromeUIScheme) ||
204 page_url.SchemeIs(extensions::kExtensionScheme)) {
205 std::vector<int> desired_sizes_in_pixel;
206 desired_sizes_in_pixel.push_back(0);
207 return GetFaviconForChromeURL(profile_,
208 page_url,
209 desired_sizes_in_pixel,
210 favicon_results_callback,
211 tracker);
213 if (history_service_) {
214 return history_service_->GetLargestFaviconForURL(page_url, icon_types,
215 minimum_size_in_pixels, callback, tracker);
217 return RunWithEmptyResultAsync(favicon_results_callback, tracker);
220 base::CancelableTaskTracker::TaskId FaviconService::GetFaviconForPageURL(
221 const GURL& page_url,
222 int icon_types,
223 int desired_size_in_dip,
224 const favicon_base::FaviconResultsCallback& callback,
225 base::CancelableTaskTracker* tracker) {
226 return GetFaviconForPageURLImpl(
227 page_url,
228 icon_types,
229 GetPixelSizesForFaviconScales(desired_size_in_dip),
230 callback,
231 tracker);
234 base::CancelableTaskTracker::TaskId
235 FaviconService::UpdateFaviconMappingsAndFetch(
236 const GURL& page_url,
237 const std::vector<GURL>& icon_urls,
238 int icon_types,
239 int desired_size_in_dip,
240 const favicon_base::FaviconResultsCallback& callback,
241 base::CancelableTaskTracker* tracker) {
242 if (history_service_) {
243 return history_service_->UpdateFaviconMappingsAndFetch(
244 page_url,
245 icon_urls,
246 icon_types,
247 GetPixelSizesForFaviconScales(desired_size_in_dip),
248 callback,
249 tracker);
251 return RunWithEmptyResultAsync(callback, tracker);
254 base::CancelableTaskTracker::TaskId FaviconService::GetLargestRawFaviconForID(
255 favicon_base::FaviconID favicon_id,
256 const favicon_base::FaviconRawBitmapCallback& callback,
257 base::CancelableTaskTracker* tracker) {
258 // Use 0 as |desired_size| to get the largest bitmap for |favicon_id| without
259 // any resizing.
260 int desired_size = 0;
261 favicon_base::FaviconResultsCallback callback_runner =
262 Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
263 base::Unretained(this),
264 callback,
265 desired_size);
267 if (history_service_) {
268 return history_service_->GetFaviconForID(
269 favicon_id, desired_size, callback_runner, tracker);
271 return RunWithEmptyResultAsync(callback_runner, tracker);
274 void FaviconService::SetFaviconOutOfDateForPage(const GURL& page_url) {
275 if (history_service_)
276 history_service_->SetFaviconsOutOfDateForPage(page_url);
279 void FaviconService::CloneFavicon(const GURL& old_page_url,
280 const GURL& new_page_url) {
281 if (history_service_)
282 history_service_->CloneFavicons(old_page_url, new_page_url);
285 void FaviconService::SetImportedFavicons(
286 const favicon_base::FaviconUsageDataList& favicon_usage) {
287 if (history_service_)
288 history_service_->SetImportedFavicons(favicon_usage);
291 void FaviconService::MergeFavicon(
292 const GURL& page_url,
293 const GURL& icon_url,
294 favicon_base::IconType icon_type,
295 scoped_refptr<base::RefCountedMemory> bitmap_data,
296 const gfx::Size& pixel_size) {
297 if (history_service_) {
298 history_service_->MergeFavicon(page_url, icon_url, icon_type, bitmap_data,
299 pixel_size);
303 void FaviconService::SetFavicons(const GURL& page_url,
304 const GURL& icon_url,
305 favicon_base::IconType icon_type,
306 const gfx::Image& image) {
307 if (!history_service_)
308 return;
310 gfx::ImageSkia image_skia = image.AsImageSkia();
311 image_skia.EnsureRepsForSupportedScales();
312 const std::vector<gfx::ImageSkiaRep>& image_reps = image_skia.image_reps();
313 std::vector<SkBitmap> bitmaps;
314 const std::vector<float> favicon_scales = favicon_base::GetFaviconScales();
315 for (size_t i = 0; i < image_reps.size(); ++i) {
316 // Don't save if the scale isn't one of supported favicon scales.
317 if (std::find(favicon_scales.begin(),
318 favicon_scales.end(),
319 image_reps[i].scale()) == favicon_scales.end()) {
320 continue;
322 bitmaps.push_back(image_reps[i].sk_bitmap());
324 history_service_->SetFavicons(page_url, icon_type, icon_url, bitmaps);
327 void FaviconService::UnableToDownloadFavicon(const GURL& icon_url) {
328 MissingFaviconURLHash url_hash = base::Hash(icon_url.spec());
329 missing_favicon_urls_.insert(url_hash);
332 bool FaviconService::WasUnableToDownloadFavicon(const GURL& icon_url) const {
333 MissingFaviconURLHash url_hash = base::Hash(icon_url.spec());
334 return missing_favicon_urls_.find(url_hash) != missing_favicon_urls_.end();
337 void FaviconService::ClearUnableToDownloadFavicons() {
338 missing_favicon_urls_.clear();
341 FaviconService::~FaviconService() {}
343 base::CancelableTaskTracker::TaskId FaviconService::GetFaviconForPageURLImpl(
344 const GURL& page_url,
345 int icon_types,
346 const std::vector<int>& desired_sizes_in_pixel,
347 const favicon_base::FaviconResultsCallback& callback,
348 base::CancelableTaskTracker* tracker) {
349 if (page_url.SchemeIs(content::kChromeUIScheme) ||
350 page_url.SchemeIs(extensions::kExtensionScheme)) {
351 return GetFaviconForChromeURL(
352 profile_, page_url, desired_sizes_in_pixel, callback, tracker);
354 if (history_service_) {
355 return history_service_->GetFaviconsForURL(page_url,
356 icon_types,
357 desired_sizes_in_pixel,
358 callback,
359 tracker);
361 return RunWithEmptyResultAsync(callback, tracker);
364 void FaviconService::RunFaviconImageCallbackWithBitmapResults(
365 const favicon_base::FaviconImageCallback& callback,
366 int desired_size_in_dip,
367 const std::vector<favicon_base::FaviconRawBitmapResult>&
368 favicon_bitmap_results) {
369 favicon_base::FaviconImageResult image_result;
370 image_result.image = favicon_base::SelectFaviconFramesFromPNGs(
371 favicon_bitmap_results,
372 favicon_base::GetFaviconScales(),
373 desired_size_in_dip);
374 favicon_base::SetFaviconColorSpace(&image_result.image);
376 image_result.icon_url = image_result.image.IsEmpty() ?
377 GURL() : favicon_bitmap_results[0].icon_url;
378 callback.Run(image_result);
381 void FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults(
382 const favicon_base::FaviconRawBitmapCallback& callback,
383 int desired_size_in_pixel,
384 const std::vector<favicon_base::FaviconRawBitmapResult>&
385 favicon_bitmap_results) {
386 if (favicon_bitmap_results.empty() || !favicon_bitmap_results[0].is_valid()) {
387 callback.Run(favicon_base::FaviconRawBitmapResult());
388 return;
391 favicon_base::FaviconRawBitmapResult bitmap_result =
392 favicon_bitmap_results[0];
394 // If the desired size is 0, SelectFaviconFrames() will return the largest
395 // bitmap without doing any resizing. As |favicon_bitmap_results| has bitmap
396 // data for a single bitmap, return it and avoid an unnecessary decode.
397 if (desired_size_in_pixel == 0) {
398 callback.Run(bitmap_result);
399 return;
402 // If history bitmap is already desired pixel size, return early.
403 if (bitmap_result.pixel_size.width() == desired_size_in_pixel &&
404 bitmap_result.pixel_size.height() == desired_size_in_pixel) {
405 callback.Run(bitmap_result);
406 return;
409 // Convert raw bytes to SkBitmap, resize via SelectFaviconFrames(), then
410 // convert back.
411 std::vector<float> desired_favicon_scales;
412 desired_favicon_scales.push_back(1.0f);
413 gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs(
414 favicon_bitmap_results, desired_favicon_scales, desired_size_in_pixel);
416 std::vector<unsigned char> resized_bitmap_data;
417 if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_image.AsBitmap(), false,
418 &resized_bitmap_data)) {
419 callback.Run(favicon_base::FaviconRawBitmapResult());
420 return;
423 bitmap_result.bitmap_data = base::RefCountedBytes::TakeVector(
424 &resized_bitmap_data);
425 callback.Run(bitmap_result);