OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "components/favicon/core/favicon_service_impl.h" |
| 6 |
| 7 #include <stddef.h> |
| 8 #include <cmath> |
| 9 #include <utility> |
| 10 |
| 11 #include "base/hash.h" |
| 12 #include "base/single_thread_task_runner.h" |
| 13 #include "base/threading/thread_task_runner_handle.h" |
| 14 #include "base/trace_event/trace_event.h" |
| 15 #include "components/favicon/core/favicon_client.h" |
| 16 #include "components/favicon_base/favicon_util.h" |
| 17 #include "components/favicon_base/select_favicon_frames.h" |
| 18 #include "components/history/core/browser/history_service.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" |
| 24 |
| 25 namespace favicon { |
| 26 namespace { |
| 27 |
| 28 // Returns a vector of pixel edge sizes from |size_in_dip| and |
| 29 // favicon_base::GetFaviconScales(). |
| 30 std::vector<int> GetPixelSizesForFaviconScales(int size_in_dip) { |
| 31 std::vector<float> scales = favicon_base::GetFaviconScales(); |
| 32 std::vector<int> sizes_in_pixel; |
| 33 for (size_t i = 0; i < scales.size(); ++i) { |
| 34 sizes_in_pixel.push_back(std::ceil(size_in_dip * scales[i])); |
| 35 } |
| 36 return sizes_in_pixel; |
| 37 } |
| 38 |
| 39 } // namespace |
| 40 |
| 41 FaviconServiceImpl::FaviconServiceImpl( |
| 42 std::unique_ptr<FaviconClient> favicon_client, |
| 43 history::HistoryService* history_service) |
| 44 : favicon_client_(std::move(favicon_client)), |
| 45 history_service_(history_service) { |
| 46 DCHECK(history_service_); |
| 47 } |
| 48 |
| 49 FaviconServiceImpl::~FaviconServiceImpl() {} |
| 50 |
| 51 base::CancelableTaskTracker::TaskId FaviconServiceImpl::GetFaviconImage( |
| 52 const GURL& icon_url, |
| 53 const favicon_base::FaviconImageCallback& callback, |
| 54 base::CancelableTaskTracker* tracker) { |
| 55 TRACE_EVENT0("browser", "FaviconServiceImpl::GetFaviconImage"); |
| 56 favicon_base::FaviconResultsCallback callback_runner = |
| 57 base::Bind(&FaviconServiceImpl::RunFaviconImageCallbackWithBitmapResults, |
| 58 base::Unretained(this), callback, gfx::kFaviconSize); |
| 59 std::vector<GURL> icon_urls; |
| 60 icon_urls.push_back(icon_url); |
| 61 return history_service_->GetFavicons( |
| 62 icon_urls, favicon_base::FAVICON, |
| 63 GetPixelSizesForFaviconScales(gfx::kFaviconSize), callback_runner, |
| 64 tracker); |
| 65 } |
| 66 |
| 67 base::CancelableTaskTracker::TaskId FaviconServiceImpl::GetRawFavicon( |
| 68 const GURL& icon_url, |
| 69 favicon_base::IconType icon_type, |
| 70 int desired_size_in_pixel, |
| 71 const favicon_base::FaviconRawBitmapCallback& callback, |
| 72 base::CancelableTaskTracker* tracker) { |
| 73 TRACE_EVENT0("browser", "FaviconServiceImpl::GetRawFavicon"); |
| 74 favicon_base::FaviconResultsCallback callback_runner = base::Bind( |
| 75 &FaviconServiceImpl::RunFaviconRawBitmapCallbackWithBitmapResults, |
| 76 base::Unretained(this), callback, desired_size_in_pixel); |
| 77 |
| 78 std::vector<GURL> icon_urls; |
| 79 icon_urls.push_back(icon_url); |
| 80 std::vector<int> desired_sizes_in_pixel; |
| 81 desired_sizes_in_pixel.push_back(desired_size_in_pixel); |
| 82 |
| 83 return history_service_->GetFavicons( |
| 84 icon_urls, icon_type, desired_sizes_in_pixel, callback_runner, tracker); |
| 85 } |
| 86 |
| 87 base::CancelableTaskTracker::TaskId FaviconServiceImpl::GetFavicon( |
| 88 const GURL& icon_url, |
| 89 favicon_base::IconType icon_type, |
| 90 int desired_size_in_dip, |
| 91 const favicon_base::FaviconResultsCallback& callback, |
| 92 base::CancelableTaskTracker* tracker) { |
| 93 TRACE_EVENT0("browser", "FaviconServiceImpl::GetFavicon"); |
| 94 std::vector<GURL> icon_urls; |
| 95 icon_urls.push_back(icon_url); |
| 96 return history_service_->GetFavicons( |
| 97 icon_urls, icon_type, GetPixelSizesForFaviconScales(desired_size_in_dip), |
| 98 callback, tracker); |
| 99 } |
| 100 |
| 101 base::CancelableTaskTracker::TaskId |
| 102 FaviconServiceImpl::GetFaviconImageForPageURL( |
| 103 const GURL& page_url, |
| 104 const favicon_base::FaviconImageCallback& callback, |
| 105 base::CancelableTaskTracker* tracker) { |
| 106 TRACE_EVENT0("browser", "FaviconServiceImpl::GetFaviconImageForPageURL"); |
| 107 return GetFaviconForPageURLImpl( |
| 108 page_url, favicon_base::FAVICON, |
| 109 GetPixelSizesForFaviconScales(gfx::kFaviconSize), |
| 110 base::Bind(&FaviconServiceImpl::RunFaviconImageCallbackWithBitmapResults, |
| 111 base::Unretained(this), callback, gfx::kFaviconSize), |
| 112 tracker); |
| 113 } |
| 114 |
| 115 base::CancelableTaskTracker::TaskId FaviconServiceImpl::GetRawFaviconForPageURL( |
| 116 const GURL& page_url, |
| 117 int icon_types, |
| 118 int desired_size_in_pixel, |
| 119 const favicon_base::FaviconRawBitmapCallback& callback, |
| 120 base::CancelableTaskTracker* tracker) { |
| 121 TRACE_EVENT0("browser", "FaviconServiceImpl::GetRawFaviconForPageURL"); |
| 122 std::vector<int> desired_sizes_in_pixel; |
| 123 desired_sizes_in_pixel.push_back(desired_size_in_pixel); |
| 124 return GetFaviconForPageURLImpl( |
| 125 page_url, icon_types, desired_sizes_in_pixel, |
| 126 base::Bind( |
| 127 &FaviconServiceImpl::RunFaviconRawBitmapCallbackWithBitmapResults, |
| 128 base::Unretained(this), callback, desired_size_in_pixel), |
| 129 tracker); |
| 130 } |
| 131 |
| 132 base::CancelableTaskTracker::TaskId |
| 133 FaviconServiceImpl::GetLargestRawFaviconForPageURL( |
| 134 const GURL& page_url, |
| 135 const std::vector<int>& icon_types, |
| 136 int minimum_size_in_pixels, |
| 137 const favicon_base::FaviconRawBitmapCallback& callback, |
| 138 base::CancelableTaskTracker* tracker) { |
| 139 TRACE_EVENT0("browser", "FaviconServiceImpl::GetLargestRawFaviconForPageURL"); |
| 140 favicon_base::FaviconResultsCallback favicon_results_callback = base::Bind( |
| 141 &FaviconServiceImpl::RunFaviconRawBitmapCallbackWithBitmapResults, |
| 142 base::Unretained(this), callback, 0); |
| 143 if (favicon_client_ && favicon_client_->IsNativeApplicationURL(page_url)) { |
| 144 std::vector<int> desired_sizes_in_pixel; |
| 145 desired_sizes_in_pixel.push_back(0); |
| 146 return favicon_client_->GetFaviconForNativeApplicationURL( |
| 147 page_url, desired_sizes_in_pixel, favicon_results_callback, tracker); |
| 148 } |
| 149 return history_service_->GetLargestFaviconForURL( |
| 150 page_url, icon_types, minimum_size_in_pixels, callback, tracker); |
| 151 } |
| 152 |
| 153 base::CancelableTaskTracker::TaskId FaviconServiceImpl::GetFaviconForPageURL( |
| 154 const GURL& page_url, |
| 155 int icon_types, |
| 156 int desired_size_in_dip, |
| 157 const favicon_base::FaviconResultsCallback& callback, |
| 158 base::CancelableTaskTracker* tracker) { |
| 159 TRACE_EVENT0("browser", "FaviconServiceImpl::GetFaviconForPageURL"); |
| 160 return GetFaviconForPageURLImpl( |
| 161 page_url, icon_types, GetPixelSizesForFaviconScales(desired_size_in_dip), |
| 162 callback, tracker); |
| 163 } |
| 164 |
| 165 base::CancelableTaskTracker::TaskId |
| 166 FaviconServiceImpl::UpdateFaviconMappingsAndFetch( |
| 167 const GURL& page_url, |
| 168 const std::vector<GURL>& icon_urls, |
| 169 int icon_types, |
| 170 int desired_size_in_dip, |
| 171 const favicon_base::FaviconResultsCallback& callback, |
| 172 base::CancelableTaskTracker* tracker) { |
| 173 return history_service_->UpdateFaviconMappingsAndFetch( |
| 174 page_url, icon_urls, icon_types, |
| 175 GetPixelSizesForFaviconScales(desired_size_in_dip), callback, tracker); |
| 176 } |
| 177 |
| 178 base::CancelableTaskTracker::TaskId |
| 179 FaviconServiceImpl::GetLargestRawFaviconForID( |
| 180 favicon_base::FaviconID favicon_id, |
| 181 const favicon_base::FaviconRawBitmapCallback& callback, |
| 182 base::CancelableTaskTracker* tracker) { |
| 183 TRACE_EVENT0("browser", "FaviconServiceImpl::GetLargestRawFaviconForID"); |
| 184 // Use 0 as |desired_size| to get the largest bitmap for |favicon_id| without |
| 185 // any resizing. |
| 186 int desired_size = 0; |
| 187 favicon_base::FaviconResultsCallback callback_runner = base::Bind( |
| 188 &FaviconServiceImpl::RunFaviconRawBitmapCallbackWithBitmapResults, |
| 189 base::Unretained(this), callback, desired_size); |
| 190 |
| 191 return history_service_->GetFaviconForID(favicon_id, desired_size, |
| 192 callback_runner, tracker); |
| 193 } |
| 194 |
| 195 void FaviconServiceImpl::SetFaviconOutOfDateForPage(const GURL& page_url) { |
| 196 history_service_->SetFaviconsOutOfDateForPage(page_url); |
| 197 } |
| 198 |
| 199 void FaviconServiceImpl::SetImportedFavicons( |
| 200 const favicon_base::FaviconUsageDataList& favicon_usage) { |
| 201 history_service_->SetImportedFavicons(favicon_usage); |
| 202 } |
| 203 |
| 204 void FaviconServiceImpl::MergeFavicon( |
| 205 const GURL& page_url, |
| 206 const GURL& icon_url, |
| 207 favicon_base::IconType icon_type, |
| 208 scoped_refptr<base::RefCountedMemory> bitmap_data, |
| 209 const gfx::Size& pixel_size) { |
| 210 history_service_->MergeFavicon(page_url, icon_url, icon_type, bitmap_data, |
| 211 pixel_size); |
| 212 } |
| 213 |
| 214 void FaviconServiceImpl::SetFavicons(const GURL& page_url, |
| 215 const GURL& icon_url, |
| 216 favicon_base::IconType icon_type, |
| 217 const gfx::Image& image) { |
| 218 gfx::ImageSkia image_skia = image.AsImageSkia(); |
| 219 image_skia.EnsureRepsForSupportedScales(); |
| 220 const std::vector<gfx::ImageSkiaRep>& image_reps = image_skia.image_reps(); |
| 221 std::vector<SkBitmap> bitmaps; |
| 222 const std::vector<float> favicon_scales = favicon_base::GetFaviconScales(); |
| 223 for (size_t i = 0; i < image_reps.size(); ++i) { |
| 224 // Don't save if the scale isn't one of supported favicon scales. |
| 225 if (std::find(favicon_scales.begin(), favicon_scales.end(), |
| 226 image_reps[i].scale()) == favicon_scales.end()) { |
| 227 continue; |
| 228 } |
| 229 bitmaps.push_back(image_reps[i].sk_bitmap()); |
| 230 } |
| 231 history_service_->SetFavicons(page_url, icon_type, icon_url, bitmaps); |
| 232 } |
| 233 |
| 234 void FaviconServiceImpl::UnableToDownloadFavicon(const GURL& icon_url) { |
| 235 MissingFaviconURLHash url_hash = base::Hash(icon_url.spec()); |
| 236 missing_favicon_urls_.insert(url_hash); |
| 237 } |
| 238 |
| 239 bool FaviconServiceImpl::WasUnableToDownloadFavicon( |
| 240 const GURL& icon_url) const { |
| 241 MissingFaviconURLHash url_hash = base::Hash(icon_url.spec()); |
| 242 return missing_favicon_urls_.find(url_hash) != missing_favicon_urls_.end(); |
| 243 } |
| 244 |
| 245 void FaviconServiceImpl::ClearUnableToDownloadFavicons() { |
| 246 missing_favicon_urls_.clear(); |
| 247 } |
| 248 |
| 249 base::CancelableTaskTracker::TaskId |
| 250 FaviconServiceImpl::GetFaviconForPageURLImpl( |
| 251 const GURL& page_url, |
| 252 int icon_types, |
| 253 const std::vector<int>& desired_sizes_in_pixel, |
| 254 const favicon_base::FaviconResultsCallback& callback, |
| 255 base::CancelableTaskTracker* tracker) { |
| 256 if (favicon_client_ && favicon_client_->IsNativeApplicationURL(page_url)) { |
| 257 return favicon_client_->GetFaviconForNativeApplicationURL( |
| 258 page_url, desired_sizes_in_pixel, callback, tracker); |
| 259 } |
| 260 return history_service_->GetFaviconsForURL( |
| 261 page_url, icon_types, desired_sizes_in_pixel, callback, tracker); |
| 262 } |
| 263 |
| 264 void FaviconServiceImpl::RunFaviconImageCallbackWithBitmapResults( |
| 265 const favicon_base::FaviconImageCallback& callback, |
| 266 int desired_size_in_dip, |
| 267 const std::vector<favicon_base::FaviconRawBitmapResult>& |
| 268 favicon_bitmap_results) { |
| 269 TRACE_EVENT0("browser", |
| 270 "FaviconServiceImpl::RunFaviconImageCallbackWithBitmapResults"); |
| 271 favicon_base::FaviconImageResult image_result; |
| 272 image_result.image = favicon_base::SelectFaviconFramesFromPNGs( |
| 273 favicon_bitmap_results, favicon_base::GetFaviconScales(), |
| 274 desired_size_in_dip); |
| 275 favicon_base::SetFaviconColorSpace(&image_result.image); |
| 276 |
| 277 image_result.icon_url = image_result.image.IsEmpty() |
| 278 ? GURL() |
| 279 : favicon_bitmap_results[0].icon_url; |
| 280 callback.Run(image_result); |
| 281 } |
| 282 |
| 283 void FaviconServiceImpl::RunFaviconRawBitmapCallbackWithBitmapResults( |
| 284 const favicon_base::FaviconRawBitmapCallback& callback, |
| 285 int desired_size_in_pixel, |
| 286 const std::vector<favicon_base::FaviconRawBitmapResult>& |
| 287 favicon_bitmap_results) { |
| 288 TRACE_EVENT0( |
| 289 "browser", |
| 290 "FaviconServiceImpl::RunFaviconRawBitmapCallbackWithBitmapResults"); |
| 291 callback.Run( |
| 292 ResizeFaviconBitmapResult(favicon_bitmap_results, desired_size_in_pixel)); |
| 293 } |
| 294 |
| 295 } // namespace favicon |
OLD | NEW |