Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/favicon/core/large_icon_service.h" | 5 #include "components/favicon/core/large_icon_service.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 return GURL(base::StringPrintf( | 53 return GURL(base::StringPrintf( |
| 54 kGoogleServerV2RequestFormat, kGoogleServerV2DesiredSizeInPixel, | 54 kGoogleServerV2RequestFormat, kGoogleServerV2DesiredSizeInPixel, |
| 55 min_source_size_in_pixel, kGoogleServerV2MaxSizeInPixel, | 55 min_source_size_in_pixel, kGoogleServerV2MaxSizeInPixel, |
| 56 page_url.spec().c_str())); | 56 page_url.spec().c_str())); |
| 57 } | 57 } |
| 58 | 58 |
| 59 // Processes the bitmap data returned from the FaviconService as part of a | 59 // Processes the bitmap data returned from the FaviconService as part of a |
| 60 // LargeIconService request. | 60 // LargeIconService request. |
| 61 class LargeIconWorker : public base::RefCountedThreadSafe<LargeIconWorker> { | 61 class LargeIconWorker : public base::RefCountedThreadSafe<LargeIconWorker> { |
| 62 public: | 62 public: |
| 63 // Exactly one of the callbacks is expected to be non-null. | |
| 63 LargeIconWorker(int min_source_size_in_pixel, | 64 LargeIconWorker(int min_source_size_in_pixel, |
| 64 int desired_size_in_pixel, | 65 int desired_size_in_pixel, |
| 65 favicon_base::LargeIconCallback callback, | 66 favicon_base::LargeIconCallback raw_bitmap_callback, |
| 67 favicon_base::LargeIconImageCallback image_callback, | |
| 66 scoped_refptr<base::TaskRunner> background_task_runner, | 68 scoped_refptr<base::TaskRunner> background_task_runner, |
| 67 base::CancelableTaskTracker* tracker); | 69 base::CancelableTaskTracker* tracker); |
| 68 | 70 |
| 69 // Must run on the owner (UI) thread in production. | 71 // Must run on the owner (UI) thread in production. |
| 70 // Intermediate callback for GetLargeIconOrFallbackStyle(). Invokes | 72 // Intermediate callback for GetLargeIconOrFallbackStyle(). Invokes |
| 71 // ProcessIconOnBackgroundThread() so we do not perform complex image | 73 // ProcessIconOnBackgroundThread() so we do not perform complex image |
| 72 // operations on the UI thread. | 74 // operations on the UI thread. |
| 73 void OnIconLookupComplete( | 75 void OnIconLookupComplete( |
| 74 const favicon_base::FaviconRawBitmapResult& bitmap_result); | 76 const favicon_base::FaviconRawBitmapResult& raw_bitmap_result); |
| 75 | 77 |
| 76 private: | 78 private: |
| 77 friend class base::RefCountedThreadSafe<LargeIconWorker>; | 79 friend class base::RefCountedThreadSafe<LargeIconWorker>; |
| 78 | 80 |
| 79 ~LargeIconWorker(); | 81 ~LargeIconWorker(); |
| 80 | 82 |
| 81 // Must run on a background thread in production. | 83 // Must run on a background thread in production. |
| 82 // Tries to resize |bitmap_result_| and pass the output to |callback_|. If | 84 // Tries to resize |bitmap_result_| and pass the output to |callback_|. If |
| 83 // that does not work, computes the icon fallback style and uses it to | 85 // that does not work, computes the icon fallback style and uses it to |
| 84 // invoke |callback_|. This must be run on a background thread because image | 86 // invoke |callback_|. This must be run on a background thread because image |
| 85 // resizing and dominant color extraction can be expensive. | 87 // resizing and dominant color extraction can be expensive. |
| 86 void ProcessIconOnBackgroundThread(); | 88 void ProcessIconOnBackgroundThread(bool return_raw, |
| 89 bool return_original_size); | |
| 87 | 90 |
| 88 // Must run on a background thread in production. | 91 // Must run on a background thread in production. |
| 89 // If |bitmap_result_| is square and large enough (>= |min_source_in_pixel_|), | 92 // If |bitmap_result_| is square and large enough (>= |min_source_in_pixel_|), |
| 90 // resizes it to |desired_size_in_pixel_| (but if |desired_size_in_pixel_| is | 93 // resizes it to |desired_size_in_pixel_| (but if |desired_size_in_pixel_| is |
| 91 // 0 then don't resize). If successful, stores the resulting bitmap data | 94 // 0 then don't resize). If successful, stores the resulting raw bitmap data |
| 92 // into |resized_bitmap_result| and returns true. | 95 // into |raw_bitmap_result_| and image data in |image_result_| and returns |
| 93 bool ResizeLargeIconOnBackgroundThreadIfValid( | 96 // true. The params |return_raw| and |return_original_size| allow early exit |
| 94 favicon_base::FaviconRawBitmapResult* resized_bitmap_result); | 97 // to skip steps that are not needed. |
| 98 bool DecodeResizeAndEncodeLargeIconOnBackgroundThreadIfValid( | |
| 99 bool return_raw, | |
| 100 bool return_original_size); | |
| 95 | 101 |
| 96 // Must run on the owner (UI) thread in production. | 102 // Must run on the owner (UI) thread in production. |
| 97 // Invoked when ProcessIconOnBackgroundThread() is done. | 103 // Invoked when ProcessIconOnBackgroundThread() is done. |
| 98 void OnIconProcessingComplete(); | 104 void OnIconProcessingComplete(); |
| 99 | 105 |
| 100 int min_source_size_in_pixel_; | 106 int min_source_size_in_pixel_; |
| 101 int desired_size_in_pixel_; | 107 int desired_size_in_pixel_; |
| 102 favicon_base::LargeIconCallback callback_; | 108 favicon_base::LargeIconCallback raw_bitmap_callback_; |
| 109 favicon_base::LargeIconImageCallback image_callback_; | |
| 103 scoped_refptr<base::TaskRunner> background_task_runner_; | 110 scoped_refptr<base::TaskRunner> background_task_runner_; |
| 104 base::CancelableTaskTracker* tracker_; | 111 base::CancelableTaskTracker* tracker_; |
| 105 favicon_base::FaviconRawBitmapResult bitmap_result_; | 112 |
| 106 std::unique_ptr<favicon_base::LargeIconResult> result_; | 113 favicon_base::FaviconRawBitmapResult raw_bitmap_result_; |
| 114 SkBitmap image_result_; | |
| 115 std::unique_ptr<favicon_base::FallbackIconStyle> fallback_icon_style_; | |
| 107 | 116 |
| 108 DISALLOW_COPY_AND_ASSIGN(LargeIconWorker); | 117 DISALLOW_COPY_AND_ASSIGN(LargeIconWorker); |
| 109 }; | 118 }; |
| 110 | 119 |
| 111 LargeIconWorker::LargeIconWorker( | 120 LargeIconWorker::LargeIconWorker( |
| 112 int min_source_size_in_pixel, | 121 int min_source_size_in_pixel, |
| 113 int desired_size_in_pixel, | 122 int desired_size_in_pixel, |
| 114 favicon_base::LargeIconCallback callback, | 123 favicon_base::LargeIconCallback raw_bitmap_callback, |
| 124 favicon_base::LargeIconImageCallback image_callback, | |
| 115 scoped_refptr<base::TaskRunner> background_task_runner, | 125 scoped_refptr<base::TaskRunner> background_task_runner, |
| 116 base::CancelableTaskTracker* tracker) | 126 base::CancelableTaskTracker* tracker) |
| 117 : min_source_size_in_pixel_(min_source_size_in_pixel), | 127 : min_source_size_in_pixel_(min_source_size_in_pixel), |
| 118 desired_size_in_pixel_(desired_size_in_pixel), | 128 desired_size_in_pixel_(desired_size_in_pixel), |
| 119 callback_(callback), | 129 raw_bitmap_callback_(raw_bitmap_callback), |
| 130 image_callback_(image_callback), | |
| 120 background_task_runner_(background_task_runner), | 131 background_task_runner_(background_task_runner), |
| 121 tracker_(tracker) { | 132 tracker_(tracker) {} |
| 122 } | |
| 123 | 133 |
| 124 LargeIconWorker::~LargeIconWorker() { | 134 LargeIconWorker::~LargeIconWorker() { |
| 125 } | 135 } |
| 126 | 136 |
| 127 void LargeIconWorker::OnIconLookupComplete( | 137 void LargeIconWorker::OnIconLookupComplete( |
| 128 const favicon_base::FaviconRawBitmapResult& bitmap_result) { | 138 const favicon_base::FaviconRawBitmapResult& raw_bitmap_result) { |
| 129 bitmap_result_ = bitmap_result; | 139 raw_bitmap_result_ = raw_bitmap_result; |
| 140 | |
| 141 bool return_raw = !raw_bitmap_callback_.is_null(); | |
| 142 bool return_original_size = | |
| 143 (desired_size_in_pixel_ == 0 || | |
| 144 raw_bitmap_result_.pixel_size.width() == desired_size_in_pixel_); | |
| 145 | |
| 130 tracker_->PostTaskAndReply( | 146 tracker_->PostTaskAndReply( |
| 131 background_task_runner_.get(), FROM_HERE, | 147 background_task_runner_.get(), FROM_HERE, |
| 132 base::Bind(&LargeIconWorker::ProcessIconOnBackgroundThread, this), | 148 base::Bind(&LargeIconWorker::ProcessIconOnBackgroundThread, this, |
| 149 return_raw, return_original_size), | |
| 133 base::Bind(&LargeIconWorker::OnIconProcessingComplete, this)); | 150 base::Bind(&LargeIconWorker::OnIconProcessingComplete, this)); |
| 134 } | 151 } |
| 135 | 152 |
| 136 void LargeIconWorker::ProcessIconOnBackgroundThread() { | 153 void LargeIconWorker::ProcessIconOnBackgroundThread(bool return_raw, |
| 137 favicon_base::FaviconRawBitmapResult resized_bitmap_result; | 154 bool return_original_size) { |
| 138 if (ResizeLargeIconOnBackgroundThreadIfValid(&resized_bitmap_result)) { | 155 if (!DecodeResizeAndEncodeLargeIconOnBackgroundThreadIfValid( |
| 139 result_.reset( | 156 return_raw, return_original_size)) { |
| 140 new favicon_base::LargeIconResult(resized_bitmap_result)); | |
| 141 } else { | |
| 142 // Failed to resize |bitmap_result_|, so compute fallback icon style. | 157 // Failed to resize |bitmap_result_|, so compute fallback icon style. |
| 143 std::unique_ptr<favicon_base::FallbackIconStyle> fallback_icon_style( | 158 fallback_icon_style_ = |
| 144 new favicon_base::FallbackIconStyle()); | 159 base::WrapUnique(new favicon_base::FallbackIconStyle()); |
| 145 if (bitmap_result_.is_valid()) { | 160 if (raw_bitmap_result_.is_valid()) { |
| 146 favicon_base::SetDominantColorAsBackground( | 161 favicon_base::SetDominantColorAsBackground(raw_bitmap_result_.bitmap_data, |
| 147 bitmap_result_.bitmap_data, fallback_icon_style.get()); | 162 fallback_icon_style_.get()); |
| 148 } | 163 } |
| 149 result_.reset( | |
| 150 new favicon_base::LargeIconResult(fallback_icon_style.release())); | |
| 151 } | 164 } |
| 152 } | 165 } |
| 153 | 166 |
| 154 bool LargeIconWorker::ResizeLargeIconOnBackgroundThreadIfValid( | 167 bool LargeIconWorker::DecodeResizeAndEncodeLargeIconOnBackgroundThreadIfValid( |
| 155 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) { | 168 bool return_raw, |
| 169 bool return_original_size) { | |
|
pkotwicz
2017/04/02 20:46:52
How about something like this:
Some things about m
jkrcal
2017/04/03 17:44:55
Done.
| |
| 156 // Require bitmap to be valid and square. | 170 // Require bitmap to be valid and square. |
| 157 if (!bitmap_result_.is_valid() || | 171 if (!raw_bitmap_result_.is_valid() || |
| 158 bitmap_result_.pixel_size.width() != bitmap_result_.pixel_size.height()) | 172 raw_bitmap_result_.pixel_size.width() != |
| 173 raw_bitmap_result_.pixel_size.height()) { | |
| 174 return false; | |
| 175 } | |
| 176 | |
| 177 // Require bitmap to be large enough. It's square, so just check width. | |
| 178 if (raw_bitmap_result_.pixel_size.width() < min_source_size_in_pixel_) | |
| 159 return false; | 179 return false; |
| 160 | 180 |
| 161 // Require bitmap to be large enough. It's square, so just check width. | 181 // Decoding is not needed, we are done. |
| 162 if (bitmap_result_.pixel_size.width() < min_source_size_in_pixel_) | 182 if (return_original_size && return_raw) |
| 183 return true; | |
| 184 | |
| 185 // Decode the image. | |
| 186 if (!gfx::PNGCodec::Decode(raw_bitmap_result_.bitmap_data->front(), | |
| 187 raw_bitmap_result_.bitmap_data->size(), | |
| 188 &image_result_)) | |
| 163 return false; | 189 return false; |
| 164 | 190 |
| 165 *resized_bitmap_result = bitmap_result_; | 191 // Resizing is not needed, we are done. |
| 166 | 192 if (return_original_size) |
| 167 // Special case: Can use |bitmap_result_| as is. | |
| 168 if (desired_size_in_pixel_ == 0 || | |
| 169 bitmap_result_.pixel_size.width() == desired_size_in_pixel_) | |
| 170 return true; | 193 return true; |
| 171 | 194 |
| 172 // Resize bitmap: decode PNG, resize, and re-encode PNG. | 195 image_result_ = skia::ImageOperations::Resize( |
| 173 SkBitmap decoded_bitmap; | 196 image_result_, skia::ImageOperations::RESIZE_LANCZOS3, |
| 174 if (!gfx::PNGCodec::Decode(bitmap_result_.bitmap_data->front(), | 197 desired_size_in_pixel_, desired_size_in_pixel_); |
| 175 bitmap_result_.bitmap_data->size(), &decoded_bitmap)) | 198 |
| 199 // Encoding back is not needed, we are done. | |
| 200 if (!return_raw) | |
| 201 return true; | |
| 202 | |
| 203 std::vector<unsigned char> bitmap_data; | |
| 204 if (!gfx::PNGCodec::EncodeBGRASkBitmap(image_result_, false, &bitmap_data)) | |
| 176 return false; | 205 return false; |
| 177 | 206 |
| 178 SkBitmap resized_bitmap = skia::ImageOperations::Resize( | 207 // Write the results back into the original |raw_bitmap_result_|. |
| 179 decoded_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, | 208 raw_bitmap_result_.pixel_size = |
| 180 desired_size_in_pixel_, desired_size_in_pixel_); | |
| 181 | |
| 182 std::vector<unsigned char> bitmap_data; | |
| 183 if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_bitmap, false, &bitmap_data)) | |
| 184 return false; | |
| 185 | |
| 186 resized_bitmap_result->pixel_size = | |
| 187 gfx::Size(desired_size_in_pixel_, desired_size_in_pixel_); | 209 gfx::Size(desired_size_in_pixel_, desired_size_in_pixel_); |
| 188 resized_bitmap_result->bitmap_data = | 210 raw_bitmap_result_.bitmap_data = |
| 189 base::RefCountedBytes::TakeVector(&bitmap_data); | 211 base::RefCountedBytes::TakeVector(&bitmap_data); |
| 190 return true; | 212 return true; |
| 191 } | 213 } |
| 192 | 214 |
| 193 void LargeIconWorker::OnIconProcessingComplete() { | 215 void LargeIconWorker::OnIconProcessingComplete() { |
| 194 callback_.Run(*result_); | 216 // If fallback style is set, return that. |
| 217 if (fallback_icon_style_) { | |
| 218 if (raw_bitmap_callback_) { | |
| 219 raw_bitmap_callback_.Run( | |
| 220 favicon_base::LargeIconResult(fallback_icon_style_.release())); | |
| 221 } else { | |
| 222 image_callback_.Run( | |
| 223 favicon_base::LargeIconImageResult(fallback_icon_style_.release())); | |
| 224 } | |
| 225 return; | |
| 226 } | |
| 227 | |
| 228 // Return the large icon, otherwise. | |
| 229 if (raw_bitmap_callback_) { | |
| 230 raw_bitmap_callback_.Run(favicon_base::LargeIconResult(raw_bitmap_result_)); | |
| 231 } else { | |
| 232 image_callback_.Run(favicon_base::LargeIconImageResult( | |
| 233 gfx::Image::CreateFrom1xBitmap(image_result_))); | |
| 234 } | |
| 195 } | 235 } |
| 196 | 236 |
| 197 void OnFetchIconFromGoogleServerComplete( | 237 void OnFetchIconFromGoogleServerComplete( |
| 198 FaviconService* favicon_service, | 238 FaviconService* favicon_service, |
| 199 const GURL& page_url, | 239 const GURL& page_url, |
| 200 const base::Callback<void(bool success)>& callback, | 240 const base::Callback<void(bool success)>& callback, |
| 201 const std::string& icon_url, | 241 const std::string& icon_url, |
| 202 const gfx::Image& image, | 242 const gfx::Image& image, |
| 203 const image_fetcher::RequestMetadata& metadata) { | 243 const image_fetcher::RequestMetadata& metadata) { |
| 204 if (image.IsEmpty()) { | 244 if (image.IsEmpty()) { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 235 image_fetcher_(std::move(image_fetcher)) { | 275 image_fetcher_(std::move(image_fetcher)) { |
| 236 large_icon_types_.push_back(favicon_base::IconType::FAVICON); | 276 large_icon_types_.push_back(favicon_base::IconType::FAVICON); |
| 237 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON); | 277 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON); |
| 238 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON); | 278 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON); |
| 239 } | 279 } |
| 240 | 280 |
| 241 LargeIconService::~LargeIconService() { | 281 LargeIconService::~LargeIconService() { |
| 242 } | 282 } |
| 243 | 283 |
| 244 base::CancelableTaskTracker::TaskId | 284 base::CancelableTaskTracker::TaskId |
| 245 LargeIconService::GetLargeIconOrFallbackStyle( | 285 LargeIconService::GetLargeIconOrFallbackStyle( |
| 246 const GURL& page_url, | 286 const GURL& page_url, |
| 247 int min_source_size_in_pixel, | 287 int min_source_size_in_pixel, |
| 248 int desired_size_in_pixel, | 288 int desired_size_in_pixel, |
| 249 const favicon_base::LargeIconCallback& callback, | 289 const favicon_base::LargeIconCallback& raw_bitmap_callback, |
| 250 base::CancelableTaskTracker* tracker) { | 290 base::CancelableTaskTracker* tracker) { |
| 291 DCHECK_LE(1, min_source_size_in_pixel); | |
| 292 DCHECK_LE(0, desired_size_in_pixel); | |
| 293 | |
| 294 scoped_refptr<LargeIconWorker> worker = new LargeIconWorker( | |
| 295 min_source_size_in_pixel, desired_size_in_pixel, raw_bitmap_callback, | |
| 296 favicon_base::LargeIconImageCallback(), background_task_runner_, tracker); | |
| 297 | |
| 298 // TODO(beaudoin): For now this is just a wrapper around | |
| 299 // GetLargestRawFaviconForPageURL. Add the logic required to select the best | |
| 300 // possible large icon. Also add logic to fetch-on-demand when the URL of | |
| 301 // a large icon is known but its bitmap is not available. | |
| 302 return favicon_service_->GetLargestRawFaviconForPageURL( | |
| 303 page_url, large_icon_types_, min_source_size_in_pixel, | |
| 304 base::Bind(&LargeIconWorker::OnIconLookupComplete, worker), tracker); | |
| 305 } | |
| 306 | |
| 307 base::CancelableTaskTracker::TaskId | |
| 308 LargeIconService::GetLargeIconImageOrFallbackStyle( | |
| 309 const GURL& page_url, | |
| 310 int min_source_size_in_pixel, | |
| 311 int desired_size_in_pixel, | |
| 312 const favicon_base::LargeIconImageCallback& image_callback, | |
| 313 base::CancelableTaskTracker* tracker) { | |
| 251 DCHECK_LE(1, min_source_size_in_pixel); | 314 DCHECK_LE(1, min_source_size_in_pixel); |
| 252 DCHECK_LE(0, desired_size_in_pixel); | 315 DCHECK_LE(0, desired_size_in_pixel); |
| 253 | 316 |
| 254 scoped_refptr<LargeIconWorker> worker = | 317 scoped_refptr<LargeIconWorker> worker = |
| 255 new LargeIconWorker(min_source_size_in_pixel, desired_size_in_pixel, | 318 new LargeIconWorker(min_source_size_in_pixel, desired_size_in_pixel, |
| 256 callback, background_task_runner_, tracker); | 319 favicon_base::LargeIconCallback(), image_callback, |
| 320 background_task_runner_, tracker); | |
| 257 | 321 |
| 258 // TODO(beaudoin): For now this is just a wrapper around | 322 // TODO(beaudoin): For now this is just a wrapper around |
| 259 // GetLargestRawFaviconForPageURL. Add the logic required to select the best | 323 // GetLargestRawFaviconForPageURL. Add the logic required to select the best |
| 260 // possible large icon. Also add logic to fetch-on-demand when the URL of | 324 // possible large icon. Also add logic to fetch-on-demand when the URL of |
| 261 // a large icon is known but its bitmap is not available. | 325 // a large icon is known but its bitmap is not available. |
| 262 return favicon_service_->GetLargestRawFaviconForPageURL( | 326 return favicon_service_->GetLargestRawFaviconForPageURL( |
| 263 page_url, large_icon_types_, min_source_size_in_pixel, | 327 page_url, large_icon_types_, min_source_size_in_pixel, |
| 264 base::Bind(&LargeIconWorker::OnIconLookupComplete, worker), | 328 base::Bind(&LargeIconWorker::OnIconLookupComplete, worker), |
| 265 tracker); | 329 tracker); |
| 266 } | 330 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 287 | 351 |
| 288 image_fetcher_->SetDataUseServiceName( | 352 image_fetcher_->SetDataUseServiceName( |
| 289 data_use_measurement::DataUseUserData::LARGE_ICON_SERVICE); | 353 data_use_measurement::DataUseUserData::LARGE_ICON_SERVICE); |
| 290 image_fetcher_->StartOrQueueNetworkRequest( | 354 image_fetcher_->StartOrQueueNetworkRequest( |
| 291 icon_url.spec(), icon_url, | 355 icon_url.spec(), icon_url, |
| 292 base::Bind(&OnFetchIconFromGoogleServerComplete, favicon_service_, | 356 base::Bind(&OnFetchIconFromGoogleServerComplete, favicon_service_, |
| 293 page_url, callback)); | 357 page_url, callback)); |
| 294 } | 358 } |
| 295 | 359 |
| 296 } // namespace favicon | 360 } // namespace favicon |
| OLD | NEW |