favicon_service.cc revision 116680a4aac90f2aa7413d9095a592090648e557
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
76d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include <cmath>
86d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/hash.h"
10b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_backend.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_service_factory.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/favicon_base/favicon_types.h"
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/favicon_base/favicon_util.h"
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/favicon_base/select_favicon_frames.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/constants.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/favicon_size.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::Bind;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CancelOrRunFaviconResultsCallback(
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const favicon_base::FaviconResultsCallback& callback,
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::vector<favicon_base::FaviconRawBitmapResult>& results) {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_canceled.Run())
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(results);
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Helper to run callback with empty results if we cannot get the history
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// service.
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::CancelableTaskTracker::TaskId RunWithEmptyResultAsync(
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const favicon_base::FaviconResultsCallback& callback,
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::CancelableTaskTracker* tracker) {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return tracker->PostTask(
447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::MessageLoopProxy::current().get(),
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Bind(callback, std::vector<favicon_base::FaviconRawBitmapResult>()));
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Return the TaskId to retreive the favicon from chrome specific URL.
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::CancelableTaskTracker::TaskId GetFaviconForChromeURL(
518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    Profile* profile,
528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const GURL& page_url,
536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::vector<int>& desired_sizes_in_pixel,
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const favicon_base::FaviconResultsCallback& callback,
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::CancelableTaskTracker* tracker) {
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::CancelableTaskTracker::IsCanceledCallback is_canceled_cb;
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::CancelableTaskTracker::TaskId id =
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      tracker->NewTrackedTaskId(&is_canceled_cb);
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  favicon_base::FaviconResultsCallback cancelable_cb =
608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      Bind(&CancelOrRunFaviconResultsCallback, is_canceled_cb, callback);
616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  ChromeWebUIControllerFactory::GetInstance()->GetFaviconForURL(
626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      profile, page_url, desired_sizes_in_pixel, cancelable_cb);
638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return id;
648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// Returns a vector of pixel edge sizes from |size_in_dip| and
676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// favicon_base::GetFaviconScales().
686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)std::vector<int> GetPixelSizesForFaviconScales(int size_in_dip) {
696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  std::vector<float> scales = favicon_base::GetFaviconScales();
706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  std::vector<int> sizes_in_pixel;
716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (size_t i = 0; i < scales.size(); ++i) {
726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    sizes_in_pixel.push_back(std::ceil(size_in_dip * scales[i]));
736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return sizes_in_pixel;
756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
79116680a4aac90f2aa7413d9095a592090648e557Ben MurdochFaviconService::FaviconService(Profile* profile, FaviconClient* favicon_client)
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : history_service_(
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          HistoryServiceFactory::GetForProfile(profile,
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                               Profile::EXPLICIT_ACCESS)),
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      profile_(profile),
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      favicon_client_(favicon_client) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconService::FaviconResultsCallbackRunner(
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const favicon_base::FaviconResultsCallback& callback,
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::vector<favicon_base::FaviconRawBitmapResult>* results) {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(*results);
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::CancelableTaskTracker::TaskId FaviconService::GetFaviconImage(
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& icon_url,
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const favicon_base::FaviconImageCallback& callback,
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::CancelableTaskTracker* tracker) {
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  favicon_base::FaviconResultsCallback callback_runner =
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Bind(&FaviconService::RunFaviconImageCallbackWithBitmapResults,
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           base::Unretained(this), callback, gfx::kFaviconSize);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (history_service_) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<GURL> icon_urls;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icon_urls.push_back(icon_url);
1046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return history_service_->GetFavicons(
1056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        icon_urls,
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        favicon_base::FAVICON,
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        GetPixelSizesForFaviconScales(gfx::kFaviconSize),
1086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        callback_runner,
1096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        tracker);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return RunWithEmptyResultAsync(callback_runner, tracker);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::CancelableTaskTracker::TaskId FaviconService::GetRawFavicon(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& icon_url,
1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    favicon_base::IconType icon_type,
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int desired_size_in_pixel,
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const favicon_base::FaviconRawBitmapCallback& callback,
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::CancelableTaskTracker* tracker) {
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  favicon_base::FaviconResultsCallback callback_runner =
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           base::Unretained(this),
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           callback,
1246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)           desired_size_in_pixel);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (history_service_) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<GURL> icon_urls;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icon_urls.push_back(icon_url);
1296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    std::vector<int> desired_sizes_in_pixel;
1306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    desired_sizes_in_pixel.push_back(desired_size_in_pixel);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return history_service_->GetFavicons(
1336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        icon_urls, icon_type, desired_sizes_in_pixel, callback_runner, tracker);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return RunWithEmptyResultAsync(callback_runner, tracker);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::CancelableTaskTracker::TaskId FaviconService::GetFavicon(
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& icon_url,
1400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    favicon_base::IconType icon_type,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int desired_size_in_dip,
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const favicon_base::FaviconResultsCallback& callback,
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::CancelableTaskTracker* tracker) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (history_service_) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<GURL> icon_urls;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    icon_urls.push_back(icon_url);
1476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return history_service_->GetFavicons(
1486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        icon_urls,
1496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        icon_type,
1506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        GetPixelSizesForFaviconScales(desired_size_in_dip),
1516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        callback,
1526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        tracker);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return RunWithEmptyResultAsync(callback, tracker);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)base::CancelableTaskTracker::TaskId FaviconService::GetFaviconImageForPageURL(
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const GURL& page_url,
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const favicon_base::FaviconImageCallback& callback,
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::CancelableTaskTracker* tracker) {
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return GetFaviconForPageURLImpl(
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      page_url,
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      favicon_base::FAVICON,
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      GetPixelSizesForFaviconScales(gfx::kFaviconSize),
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Bind(&FaviconService::RunFaviconImageCallbackWithBitmapResults,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           base::Unretained(this),
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           callback,
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           gfx::kFaviconSize),
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tracker);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)base::CancelableTaskTracker::TaskId FaviconService::GetRawFaviconForPageURL(
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const GURL& page_url,
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int icon_types,
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int desired_size_in_pixel,
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const favicon_base::FaviconRawBitmapCallback& callback,
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::CancelableTaskTracker* tracker) {
1786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  std::vector<int> desired_sizes_in_pixel;
1796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  desired_sizes_in_pixel.push_back(desired_size_in_pixel);
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return GetFaviconForPageURLImpl(
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      page_url,
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      icon_types,
1836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      desired_sizes_in_pixel,
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           base::Unretained(this),
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           callback,
1876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)           desired_size_in_pixel),
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tracker);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)base::CancelableTaskTracker::TaskId
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)FaviconService::GetLargestRawFaviconForPageURL(
1938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const GURL& page_url,
1948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::vector<int>& icon_types,
1958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    int minimum_size_in_pixels,
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const favicon_base::FaviconRawBitmapCallback& callback,
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::CancelableTaskTracker* tracker) {
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  favicon_base::FaviconResultsCallback favicon_results_callback =
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           base::Unretained(this),
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           callback,
2026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)           0);
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (page_url.SchemeIs(content::kChromeUIScheme) ||
2048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      page_url.SchemeIs(extensions::kExtensionScheme)) {
2056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    std::vector<int> desired_sizes_in_pixel;
2066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    desired_sizes_in_pixel.push_back(0);
207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return GetFaviconForChromeURL(profile_,
2086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                  page_url,
2096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                  desired_sizes_in_pixel,
2106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                  favicon_results_callback,
2116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                  tracker);
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (history_service_) {
2148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return history_service_->GetLargestFaviconForURL(page_url, icon_types,
2158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        minimum_size_in_pixels, callback, tracker);
2168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
2178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return RunWithEmptyResultAsync(favicon_results_callback, tracker);
2188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)base::CancelableTaskTracker::TaskId FaviconService::GetFaviconForPageURL(
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const GURL& page_url,
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int icon_types,
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int desired_size_in_dip,
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const favicon_base::FaviconResultsCallback& callback,
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::CancelableTaskTracker* tracker) {
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return GetFaviconForPageURLImpl(
227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      page_url,
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      icon_types,
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      GetPixelSizesForFaviconScales(desired_size_in_dip),
2306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      callback,
2316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      tracker);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
234116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbase::CancelableTaskTracker::TaskId
235116680a4aac90f2aa7413d9095a592090648e557Ben MurdochFaviconService::UpdateFaviconMappingsAndFetch(
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const GURL& page_url,
237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const std::vector<GURL>& icon_urls,
238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int icon_types,
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int desired_size_in_dip,
240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const favicon_base::FaviconResultsCallback& callback,
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::CancelableTaskTracker* tracker) {
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (history_service_) {
243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return history_service_->UpdateFaviconMappingsAndFetch(
244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        page_url,
245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        icon_urls,
246116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        icon_types,
247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        GetPixelSizesForFaviconScales(desired_size_in_dip),
248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        callback,
249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        tracker);
250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return RunWithEmptyResultAsync(callback, tracker);
252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::CancelableTaskTracker::TaskId FaviconService::GetLargestRawFaviconForID(
2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    favicon_base::FaviconID favicon_id,
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const favicon_base::FaviconRawBitmapCallback& callback,
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::CancelableTaskTracker* tracker) {
2586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Use 0 as |desired_size| to get the largest bitmap for |favicon_id| without
2596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // any resizing.
2606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  int desired_size = 0;
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  favicon_base::FaviconResultsCallback callback_runner =
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           base::Unretained(this),
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           callback,
2656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)           desired_size);
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (history_service_) {
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return history_service_->GetFaviconForID(
2696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        favicon_id, desired_size, callback_runner, tracker);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return RunWithEmptyResultAsync(callback_runner, tracker);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconService::SetFaviconOutOfDateForPage(const GURL& page_url) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (history_service_)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    history_service_->SetFaviconsOutOfDateForPage(page_url);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconService::CloneFavicon(const GURL& old_page_url,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const GURL& new_page_url) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (history_service_)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    history_service_->CloneFavicons(old_page_url, new_page_url);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconService::MergeFavicon(
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& page_url,
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& icon_url,
2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    favicon_base::IconType icon_type,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::RefCountedMemory> bitmap_data,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& pixel_size) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (history_service_) {
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    history_service_->MergeFavicon(page_url, icon_url, icon_type, bitmap_data,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   pixel_size);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FaviconService::SetFavicons(const GURL& page_url,
29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                 const GURL& icon_url,
2990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                 favicon_base::IconType icon_type,
30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                 const gfx::Image& image) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!history_service_)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia image_skia = image.AsImageSkia();
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  image_skia.EnsureRepsForSupportedScales();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<gfx::ImageSkiaRep>& image_reps = image_skia.image_reps();
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::vector<favicon_base::FaviconRawBitmapData> favicon_bitmap_data;
308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const std::vector<float> favicon_scales = favicon_base::GetFaviconScales();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < image_reps.size(); ++i) {
310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Don't save if the scale isn't one of supported favicon scale.
311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (std::find(favicon_scales.begin(),
312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                  favicon_scales.end(),
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                  image_reps[i].scale()) == favicon_scales.end()) {
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      continue;
315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::RefCountedBytes> bitmap_data(
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new base::RefCountedBytes());
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (gfx::PNGCodec::EncodeBGRASkBitmap(image_reps[i].sk_bitmap(),
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          false,
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          &bitmap_data->data())) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Size pixel_size(image_reps[i].pixel_width(),
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           image_reps[i].pixel_height());
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      favicon_base::FaviconRawBitmapData bitmap_data_element;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bitmap_data_element.bitmap_data = bitmap_data;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bitmap_data_element.pixel_size = pixel_size;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bitmap_data_element.icon_url = icon_url;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      favicon_bitmap_data.push_back(bitmap_data_element);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  history_service_->SetFavicons(page_url, icon_type, favicon_bitmap_data);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FaviconService::UnableToDownloadFavicon(const GURL& icon_url) {
33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MissingFaviconURLHash url_hash = base::Hash(icon_url.spec());
33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  missing_favicon_urls_.insert(url_hash);
33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool FaviconService::WasUnableToDownloadFavicon(const GURL& icon_url) const {
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MissingFaviconURLHash url_hash = base::Hash(icon_url.spec());
34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return missing_favicon_urls_.find(url_hash) != missing_favicon_urls_.end();
34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void FaviconService::ClearUnableToDownloadFavicons() {
34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  missing_favicon_urls_.clear();
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FaviconService::~FaviconService() {}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)base::CancelableTaskTracker::TaskId FaviconService::GetFaviconForPageURLImpl(
352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const GURL& page_url,
353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int icon_types,
3546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::vector<int>& desired_sizes_in_pixel,
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const favicon_base::FaviconResultsCallback& callback,
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::CancelableTaskTracker* tracker) {
357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (page_url.SchemeIs(content::kChromeUIScheme) ||
358116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      page_url.SchemeIs(extensions::kExtensionScheme)) {
3596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return GetFaviconForChromeURL(
360116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        profile_, page_url, desired_sizes_in_pixel, callback, tracker);
361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (history_service_) {
363116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return history_service_->GetFaviconsForURL(page_url,
364116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                               icon_types,
3656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                               desired_sizes_in_pixel,
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               callback,
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               tracker);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return RunWithEmptyResultAsync(callback, tracker);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconService::RunFaviconImageCallbackWithBitmapResults(
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const favicon_base::FaviconImageCallback& callback,
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int desired_size_in_dip,
375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::vector<favicon_base::FaviconRawBitmapResult>&
3760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        favicon_bitmap_results) {
3770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  favicon_base::FaviconImageResult image_result;
378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  image_result.image = favicon_base::SelectFaviconFramesFromPNGs(
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      favicon_bitmap_results,
3806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      favicon_base::GetFaviconScales(),
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      desired_size_in_dip);
382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  favicon_base::SetFaviconColorSpace(&image_result.image);
383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  image_result.icon_url = image_result.image.IsEmpty() ?
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL() : favicon_bitmap_results[0].icon_url;
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(image_result);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults(
390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const favicon_base::FaviconRawBitmapCallback& callback,
3916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    int desired_size_in_pixel,
392f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::vector<favicon_base::FaviconRawBitmapResult>&
3930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        favicon_bitmap_results) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (favicon_bitmap_results.empty() || !favicon_bitmap_results[0].is_valid()) {
395f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    callback.Run(favicon_base::FaviconRawBitmapResult());
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(1u, favicon_bitmap_results.size());
400f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  favicon_base::FaviconRawBitmapResult bitmap_result =
401f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      favicon_bitmap_results[0];
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the desired size is 0, SelectFaviconFrames() will return the largest
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bitmap without doing any resizing. As |favicon_bitmap_results| has bitmap
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // data for a single bitmap, return it and avoid an unnecessary decode.
4066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (desired_size_in_pixel == 0) {
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(bitmap_result);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If history bitmap is already desired pixel size, return early.
4126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (bitmap_result.pixel_size.width() == desired_size_in_pixel &&
4136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      bitmap_result.pixel_size.height() == desired_size_in_pixel) {
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(bitmap_result);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert raw bytes to SkBitmap, resize via SelectFaviconFrames(), then
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // convert back.
4206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  std::vector<float> desired_favicon_scales;
4216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  desired_favicon_scales.push_back(1.0f);
422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs(
4236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      favicon_bitmap_results, desired_favicon_scales, desired_size_in_pixel);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<unsigned char> resized_bitmap_data;
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_image.AsBitmap(), false,
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         &resized_bitmap_data)) {
428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    callback.Run(favicon_base::FaviconRawBitmapResult());
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitmap_result.bitmap_data = base::RefCountedBytes::TakeVector(
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &resized_bitmap_data);
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(bitmap_result);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
436