Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: components/favicon/core/large_icon_service.cc

Issue 2784233003: [LargeIconService] Allow decoding of images in the service (Closed)
Patch Set: Minor changes #2 Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « components/favicon/core/large_icon_service.h ('k') | components/favicon/core/large_icon_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698