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

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

Issue 2784233003: [LargeIconService] Allow decoding of images in the service (Closed)
Patch Set: Peter's comments #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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 } 49 }
50 50
51 GURL GetIconUrlForGoogleServerV2(const GURL& page_url, 51 GURL GetIconUrlForGoogleServerV2(const GURL& page_url,
52 int min_source_size_in_pixel) { 52 int min_source_size_in_pixel) {
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 bool IsDbResultAdequate(const favicon_base::FaviconRawBitmapResult& db_result,
60 int min_source_size) {
61 return db_result.is_valid() &&
62 db_result.pixel_size.width() == db_result.pixel_size.height() &&
63 db_result.pixel_size.width() >= min_source_size;
64 }
65
66 // Must run on a background thread in production.
67 // Assumes |db_result| contains valid PNG data and it returns it as a
68 // gfx::Image. If |desired_size| is 0 then the image is not resized
69 // and the gfx::Image is just a wrapper around the raw PNG data. Otherwise, the
70 // image gets decoded and resized to |desired_size| (in px) and returned
71 // as a decoded bitmap.
pkotwicz 2017/04/04 12:43:42 How about: "Wraps the PNG data in |db_result| in a
jkrcal 2017/04/04 14:44:40 Ok, done.
72 gfx::Image ResizeLargeIconOnBackgroundThread(
73 const favicon_base::FaviconRawBitmapResult& db_result,
74 int desired_size) {
75 gfx::Image image = gfx::Image::CreateFrom1xPNGBytes(
76 db_result.bitmap_data->front(), db_result.bitmap_data->size());
77
78 if (desired_size == 0 || db_result.pixel_size.width() == desired_size) {
79 return image;
80 }
81
82 SkBitmap resized = skia::ImageOperations::Resize(
83 image.AsBitmap(), skia::ImageOperations::RESIZE_LANCZOS3, desired_size,
84 desired_size);
85 return gfx::Image::CreateFrom1xBitmap(resized);
86 }
87
88 // Processes the |db_result| and writes the result into |raw_result| if
89 // |raw_result| is not nullptr or to |bitmap|, otherwise. If |db_result| is not
90 // valid or is smaller than |min_source_size|, the resulting fallback style is
91 // written into |fallback_icon_style|.
92 void ProcessIconOnBackgroundThread(
93 const favicon_base::FaviconRawBitmapResult& db_result,
94 int min_source_size,
95 int desired_size,
96 favicon_base::FaviconRawBitmapResult* raw_result,
97 SkBitmap* bitmap,
98 favicon_base::FallbackIconStyle* fallback_icon_style) {
99 if (IsDbResultAdequate(db_result, min_source_size)) {
100 gfx::Image image;
101 image = ResizeLargeIconOnBackgroundThread(db_result, desired_size);
102
103 if (!image.IsEmpty()) {
104 if (raw_result) {
105 *raw_result = db_result;
106 if (desired_size != 0)
107 raw_result->pixel_size = gfx::Size(desired_size, desired_size);
108 raw_result->bitmap_data = image.As1xPNGBytes();
109 }
110 if (bitmap) {
111 *bitmap = image.AsBitmap();
112 }
113 return;
114 }
115 }
116
117 if (!fallback_icon_style)
118 return;
119
120 *fallback_icon_style = favicon_base::FallbackIconStyle();
121 if (db_result.is_valid()) {
122 favicon_base::SetDominantColorAsBackground(db_result.bitmap_data,
123 fallback_icon_style);
124 }
125 }
126
59 // Processes the bitmap data returned from the FaviconService as part of a 127 // Processes the bitmap data returned from the FaviconService as part of a
60 // LargeIconService request. 128 // LargeIconService request.
61 class LargeIconWorker : public base::RefCountedThreadSafe<LargeIconWorker> { 129 class LargeIconWorker : public base::RefCountedThreadSafe<LargeIconWorker> {
62 public: 130 public:
131 // Exactly one of the callbacks is expected to be non-null.
63 LargeIconWorker(int min_source_size_in_pixel, 132 LargeIconWorker(int min_source_size_in_pixel,
64 int desired_size_in_pixel, 133 int desired_size_in_pixel,
65 favicon_base::LargeIconCallback callback, 134 favicon_base::LargeIconCallback raw_bitmap_callback,
135 favicon_base::LargeIconImageCallback image_callback,
66 scoped_refptr<base::TaskRunner> background_task_runner, 136 scoped_refptr<base::TaskRunner> background_task_runner,
67 base::CancelableTaskTracker* tracker); 137 base::CancelableTaskTracker* tracker);
68 138
69 // Must run on the owner (UI) thread in production. 139 // Must run on the owner (UI) thread in production.
70 // Intermediate callback for GetLargeIconOrFallbackStyle(). Invokes 140 // Intermediate callback for GetLargeIconOrFallbackStyle(). Invokes
71 // ProcessIconOnBackgroundThread() so we do not perform complex image 141 // ProcessIconOnBackgroundThread() so we do not perform complex image
72 // operations on the UI thread. 142 // operations on the UI thread.
73 void OnIconLookupComplete( 143 void OnIconLookupComplete(
74 const favicon_base::FaviconRawBitmapResult& bitmap_result); 144 const favicon_base::FaviconRawBitmapResult& db_result);
75 145
76 private: 146 private:
77 friend class base::RefCountedThreadSafe<LargeIconWorker>; 147 friend class base::RefCountedThreadSafe<LargeIconWorker>;
78 148
79 ~LargeIconWorker(); 149 ~LargeIconWorker();
80 150
81 // Must run on a background thread in production.
82 // 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
84 // invoke |callback_|. This must be run on a background thread because image
85 // resizing and dominant color extraction can be expensive.
86 void ProcessIconOnBackgroundThread();
87
88 // Must run on a background thread in production.
89 // 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
91 // 0 then don't resize). If successful, stores the resulting bitmap data
92 // into |resized_bitmap_result| and returns true.
93 bool ResizeLargeIconOnBackgroundThreadIfValid(
94 favicon_base::FaviconRawBitmapResult* resized_bitmap_result);
95
96 // Must run on the owner (UI) thread in production. 151 // Must run on the owner (UI) thread in production.
97 // Invoked when ProcessIconOnBackgroundThread() is done. 152 // Invoked when ProcessIconOnBackgroundThread() is done.
98 void OnIconProcessingComplete(); 153 void OnIconProcessingComplete();
99 154
100 int min_source_size_in_pixel_; 155 int min_source_size_in_pixel_;
101 int desired_size_in_pixel_; 156 int desired_size_in_pixel_;
102 favicon_base::LargeIconCallback callback_; 157 favicon_base::LargeIconCallback raw_bitmap_callback_;
158 favicon_base::LargeIconImageCallback image_callback_;
103 scoped_refptr<base::TaskRunner> background_task_runner_; 159 scoped_refptr<base::TaskRunner> background_task_runner_;
104 base::CancelableTaskTracker* tracker_; 160 base::CancelableTaskTracker* tracker_;
105 favicon_base::FaviconRawBitmapResult bitmap_result_; 161
106 std::unique_ptr<favicon_base::LargeIconResult> result_; 162 favicon_base::FaviconRawBitmapResult raw_bitmap_result_;
163 SkBitmap image_result_;
164 std::unique_ptr<favicon_base::FallbackIconStyle> fallback_icon_style_;
107 165
108 DISALLOW_COPY_AND_ASSIGN(LargeIconWorker); 166 DISALLOW_COPY_AND_ASSIGN(LargeIconWorker);
109 }; 167 };
110 168
111 LargeIconWorker::LargeIconWorker( 169 LargeIconWorker::LargeIconWorker(
112 int min_source_size_in_pixel, 170 int min_source_size_in_pixel,
113 int desired_size_in_pixel, 171 int desired_size_in_pixel,
114 favicon_base::LargeIconCallback callback, 172 favicon_base::LargeIconCallback raw_bitmap_callback,
173 favicon_base::LargeIconImageCallback image_callback,
115 scoped_refptr<base::TaskRunner> background_task_runner, 174 scoped_refptr<base::TaskRunner> background_task_runner,
116 base::CancelableTaskTracker* tracker) 175 base::CancelableTaskTracker* tracker)
117 : min_source_size_in_pixel_(min_source_size_in_pixel), 176 : min_source_size_in_pixel_(min_source_size_in_pixel),
118 desired_size_in_pixel_(desired_size_in_pixel), 177 desired_size_in_pixel_(desired_size_in_pixel),
119 callback_(callback), 178 raw_bitmap_callback_(raw_bitmap_callback),
179 image_callback_(image_callback),
120 background_task_runner_(background_task_runner), 180 background_task_runner_(background_task_runner),
121 tracker_(tracker) { 181 tracker_(tracker),
122 } 182 fallback_icon_style_(
183 base::MakeUnique<favicon_base::FallbackIconStyle>()) {}
123 184
124 LargeIconWorker::~LargeIconWorker() { 185 LargeIconWorker::~LargeIconWorker() {
125 } 186 }
126 187
127 void LargeIconWorker::OnIconLookupComplete( 188 void LargeIconWorker::OnIconLookupComplete(
128 const favicon_base::FaviconRawBitmapResult& bitmap_result) { 189 const favicon_base::FaviconRawBitmapResult& db_result) {
129 bitmap_result_ = bitmap_result;
130 tracker_->PostTaskAndReply( 190 tracker_->PostTaskAndReply(
131 background_task_runner_.get(), FROM_HERE, 191 background_task_runner_.get(), FROM_HERE,
132 base::Bind(&LargeIconWorker::ProcessIconOnBackgroundThread, this), 192 base::Bind(&ProcessIconOnBackgroundThread, db_result,
193 min_source_size_in_pixel_, desired_size_in_pixel_,
194 raw_bitmap_callback_ ? &raw_bitmap_result_ : nullptr,
195 image_callback_ ? &image_result_ : nullptr,
196 fallback_icon_style_.get()),
133 base::Bind(&LargeIconWorker::OnIconProcessingComplete, this)); 197 base::Bind(&LargeIconWorker::OnIconProcessingComplete, this));
134 } 198 }
135 199
136 void LargeIconWorker::ProcessIconOnBackgroundThread() { 200 void LargeIconWorker::OnIconProcessingComplete() {
137 favicon_base::FaviconRawBitmapResult resized_bitmap_result; 201 // If |raw_bitmap_callback_| is provided, return the raw result.
138 if (ResizeLargeIconOnBackgroundThreadIfValid(&resized_bitmap_result)) { 202 if (raw_bitmap_callback_) {
139 result_.reset( 203 // Return the large icon, if we have the image.
pkotwicz 2017/04/04 12:43:43 This comment is redundant. It does not say anythin
jkrcal 2017/04/04 14:44:40 Done.
140 new favicon_base::LargeIconResult(resized_bitmap_result)); 204 if (raw_bitmap_result_.is_valid()) {
141 } else { 205 raw_bitmap_callback_.Run(
142 // Failed to resize |bitmap_result_|, so compute fallback icon style. 206 favicon_base::LargeIconResult(raw_bitmap_result_));
143 std::unique_ptr<favicon_base::FallbackIconStyle> fallback_icon_style( 207 return;
144 new favicon_base::FallbackIconStyle());
145 if (bitmap_result_.is_valid()) {
146 favicon_base::SetDominantColorAsBackground(
147 bitmap_result_.bitmap_data, fallback_icon_style.get());
148 } 208 }
149 result_.reset( 209 // Return fallback style, otherwise
pkotwicz 2017/04/04 12:43:43 This comment is redundant. It does not say anythin
jkrcal 2017/04/04 14:44:40 Done.
150 new favicon_base::LargeIconResult(fallback_icon_style.release())); 210 raw_bitmap_callback_.Run(
211 favicon_base::LargeIconResult(fallback_icon_style_.release()));
212 return;
151 } 213 }
152 }
153 214
154 bool LargeIconWorker::ResizeLargeIconOnBackgroundThreadIfValid( 215 // Otherwise we assume |image_callback_| is provided. Return decoded results.
pkotwicz 2017/04/04 12:43:42 This comment is redundant. It does not say anythin
jkrcal 2017/04/04 14:44:40 Done.
155 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) { 216 if (!image_result_.isNull()) {
156 // Require bitmap to be valid and square. 217 image_callback_.Run(favicon_base::LargeIconImageResult(
157 if (!bitmap_result_.is_valid() || 218 gfx::Image::CreateFrom1xBitmap(image_result_)));
158 bitmap_result_.pixel_size.width() != bitmap_result_.pixel_size.height()) 219 return;
159 return false; 220 }
160 221 image_callback_.Run(
161 // Require bitmap to be large enough. It's square, so just check width. 222 favicon_base::LargeIconImageResult(fallback_icon_style_.release()));
162 if (bitmap_result_.pixel_size.width() < min_source_size_in_pixel_)
163 return false;
164
165 *resized_bitmap_result = bitmap_result_;
166
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;
171
172 // Resize bitmap: decode PNG, resize, and re-encode PNG.
173 SkBitmap decoded_bitmap;
174 if (!gfx::PNGCodec::Decode(bitmap_result_.bitmap_data->front(),
175 bitmap_result_.bitmap_data->size(), &decoded_bitmap))
176 return false;
177
178 SkBitmap resized_bitmap = skia::ImageOperations::Resize(
179 decoded_bitmap, skia::ImageOperations::RESIZE_LANCZOS3,
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_);
188 resized_bitmap_result->bitmap_data =
189 base::RefCountedBytes::TakeVector(&bitmap_data);
190 return true;
191 }
192
193 void LargeIconWorker::OnIconProcessingComplete() {
194 callback_.Run(*result_);
195 } 223 }
196 224
197 void OnFetchIconFromGoogleServerComplete( 225 void OnFetchIconFromGoogleServerComplete(
198 FaviconService* favicon_service, 226 FaviconService* favicon_service,
199 const GURL& page_url, 227 const GURL& page_url,
200 const base::Callback<void(bool success)>& callback, 228 const base::Callback<void(bool success)>& callback,
201 const std::string& icon_url, 229 const std::string& icon_url,
202 const gfx::Image& image, 230 const gfx::Image& image,
203 const image_fetcher::RequestMetadata& metadata) { 231 const image_fetcher::RequestMetadata& metadata) {
204 if (image.IsEmpty()) { 232 if (image.IsEmpty()) {
(...skipping 30 matching lines...) Expand all
235 image_fetcher_(std::move(image_fetcher)) { 263 image_fetcher_(std::move(image_fetcher)) {
236 large_icon_types_.push_back(favicon_base::IconType::FAVICON); 264 large_icon_types_.push_back(favicon_base::IconType::FAVICON);
237 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON); 265 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON);
238 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON); 266 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON);
239 } 267 }
240 268
241 LargeIconService::~LargeIconService() { 269 LargeIconService::~LargeIconService() {
242 } 270 }
243 271
244 base::CancelableTaskTracker::TaskId 272 base::CancelableTaskTracker::TaskId
245 LargeIconService::GetLargeIconOrFallbackStyle( 273 LargeIconService::GetLargeIconOrFallbackStyle(
246 const GURL& page_url, 274 const GURL& page_url,
247 int min_source_size_in_pixel, 275 int min_source_size_in_pixel,
248 int desired_size_in_pixel, 276 int desired_size_in_pixel,
249 const favicon_base::LargeIconCallback& callback, 277 const favicon_base::LargeIconCallback& raw_bitmap_callback,
250 base::CancelableTaskTracker* tracker) { 278 base::CancelableTaskTracker* tracker) {
279 return GetLargeIconOrFallbackStyleImpl(
280 page_url, min_source_size_in_pixel, desired_size_in_pixel,
281 raw_bitmap_callback, favicon_base::LargeIconImageCallback(), tracker);
282 }
283
284 base::CancelableTaskTracker::TaskId
285 LargeIconService::GetLargeIconImageOrFallbackStyle(
286 const GURL& page_url,
287 int min_source_size_in_pixel,
288 int desired_size_in_pixel,
289 const favicon_base::LargeIconImageCallback& image_callback,
290 base::CancelableTaskTracker* tracker) {
291 return GetLargeIconOrFallbackStyleImpl(
292 page_url, min_source_size_in_pixel, desired_size_in_pixel,
293 favicon_base::LargeIconCallback(), image_callback, tracker);
294 }
295
296 base::CancelableTaskTracker::TaskId
297 LargeIconService::GetLargeIconOrFallbackStyleImpl(
pkotwicz 2017/04/04 12:43:42 Please reorder this function to match order in .h
jkrcal 2017/04/04 14:44:40 Done.
298 const GURL& page_url,
299 int min_source_size_in_pixel,
300 int desired_size_in_pixel,
301 const favicon_base::LargeIconCallback& raw_bitmap_callback,
302 const favicon_base::LargeIconImageCallback& image_callback,
303 base::CancelableTaskTracker* tracker) {
251 DCHECK_LE(1, min_source_size_in_pixel); 304 DCHECK_LE(1, min_source_size_in_pixel);
252 DCHECK_LE(0, desired_size_in_pixel); 305 DCHECK_LE(0, desired_size_in_pixel);
253 306
254 scoped_refptr<LargeIconWorker> worker = 307 scoped_refptr<LargeIconWorker> worker = new LargeIconWorker(
255 new LargeIconWorker(min_source_size_in_pixel, desired_size_in_pixel, 308 min_source_size_in_pixel, desired_size_in_pixel, raw_bitmap_callback,
256 callback, background_task_runner_, tracker); 309 image_callback, background_task_runner_, tracker);
257 310
258 // TODO(beaudoin): For now this is just a wrapper around 311 // TODO(beaudoin): For now this is just a wrapper around
259 // GetLargestRawFaviconForPageURL. Add the logic required to select the best 312 // GetLargestRawFaviconForPageURL. Add the logic required to select the best
260 // possible large icon. Also add logic to fetch-on-demand when the URL of 313 // 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. 314 // a large icon is known but its bitmap is not available.
262 return favicon_service_->GetLargestRawFaviconForPageURL( 315 return favicon_service_->GetLargestRawFaviconForPageURL(
263 page_url, large_icon_types_, min_source_size_in_pixel, 316 page_url, large_icon_types_, min_source_size_in_pixel,
264 base::Bind(&LargeIconWorker::OnIconLookupComplete, worker), 317 base::Bind(&LargeIconWorker::OnIconLookupComplete, worker), tracker);
265 tracker);
266 } 318 }
267 319
268 void LargeIconService:: 320 void LargeIconService::
269 GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( 321 GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
270 const GURL& page_url, 322 const GURL& page_url,
271 int min_source_size_in_pixel, 323 int min_source_size_in_pixel,
272 const base::Callback<void(bool success)>& callback) { 324 const base::Callback<void(bool success)>& callback) {
273 DCHECK_LE(0, min_source_size_in_pixel); 325 DCHECK_LE(0, min_source_size_in_pixel);
274 326
275 const GURL trimmed_page_url = TrimPageUrlForGoogleServer(page_url); 327 const GURL trimmed_page_url = TrimPageUrlForGoogleServer(page_url);
(...skipping 11 matching lines...) Expand all
287 339
288 image_fetcher_->SetDataUseServiceName( 340 image_fetcher_->SetDataUseServiceName(
289 data_use_measurement::DataUseUserData::LARGE_ICON_SERVICE); 341 data_use_measurement::DataUseUserData::LARGE_ICON_SERVICE);
290 image_fetcher_->StartOrQueueNetworkRequest( 342 image_fetcher_->StartOrQueueNetworkRequest(
291 icon_url.spec(), icon_url, 343 icon_url.spec(), icon_url,
292 base::Bind(&OnFetchIconFromGoogleServerComplete, favicon_service_, 344 base::Bind(&OnFetchIconFromGoogleServerComplete, favicon_service_,
293 page_url, callback)); 345 page_url, callback));
294 } 346 }
295 347
296 } // namespace favicon 348 } // namespace favicon
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698