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 "base/bind.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "base/memory/scoped_ptr.h" | |
| 10 #include "base/task_runner.h" | |
| 11 #include "base/threading/sequenced_worker_pool.h" | |
| 7 #include "components/favicon/core/favicon_service.h" | 12 #include "components/favicon/core/favicon_service.h" |
| 8 #include "components/favicon_base/fallback_icon_style.h" | 13 #include "components/favicon_base/fallback_icon_style.h" |
| 9 #include "components/favicon_base/favicon_types.h" | 14 #include "components/favicon_base/favicon_types.h" |
| 15 #include "content/public/browser/browser_thread.h" | |
| 10 #include "skia/ext/image_operations.h" | 16 #include "skia/ext/image_operations.h" |
| 11 #include "ui/gfx/codec/png_codec.h" | 17 #include "ui/gfx/codec/png_codec.h" |
| 12 #include "ui/gfx/geometry/size.h" | 18 #include "ui/gfx/geometry/size.h" |
| 13 | 19 |
| 14 namespace favicon { | 20 namespace { |
| 15 | 21 |
| 16 LargeIconService::LargeIconService(FaviconService* favicon_service) | 22 // Tracks the states of a request session for LargeIconService, and manages |
| 17 : favicon_service_(favicon_service) { | 23 // the callback chain on different threads. |
|
pkotwicz
2015/05/11 18:57:39
How about: "Processes the bitmap data returned fro
huangs
2015/05/11 20:24:37
Done.
| |
| 18 large_icon_types_.push_back(favicon_base::IconType::FAVICON); | 24 class LargeIconWorker : public base::RefCountedThreadSafe<LargeIconWorker> { |
| 19 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON); | 25 public: |
| 20 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON); | 26 LargeIconWorker(int min_source_size_in_pixel, |
| 27 int desired_size_in_pixel, | |
| 28 favicon_base::LargeIconCallback callback, | |
| 29 scoped_refptr<base::TaskRunner> background_task_runner, | |
| 30 base::CancelableTaskTracker* tracker); | |
| 31 | |
| 32 // Must run on the owner (UI) thread in production. | |
| 33 // Intermediate callback for GetLargeIconOrFallbackStyle(). Invokes | |
| 34 // ProcessIconOnBackgroundThread() so we do not perform complex image | |
| 35 // operations on the UI thread. | |
| 36 void OnIconLookupComplete( | |
| 37 const favicon_base::FaviconRawBitmapResult& bitmap_result); | |
| 38 | |
| 39 private: | |
| 40 friend class base::RefCountedThreadSafe<LargeIconWorker>; | |
| 41 | |
| 42 ~LargeIconWorker(); | |
| 43 | |
| 44 // Must run on a background thread in production. | |
| 45 // Tries to resize |bitmap_result| and pass the output to |callback|. If | |
|
pkotwicz
2015/05/11 18:57:39
|bitmap_result| -> |bitmap_result_|
|callback| ->
huangs
2015/05/11 20:24:37
Done. Also below since we're making static functio
| |
| 46 // that does not work, computes the icon fallback style and uses it to | |
| 47 // invoke |callback|. This must be run on a background thread because image | |
|
pkotwicz
2015/05/11 18:57:39
|callback| -> |callback_|
huangs
2015/05/11 20:24:37
Done.
| |
| 48 // resizing and dominant color extraction can be expensive. | |
| 49 void ProcessIconOnBackgroundThread(); | |
| 50 | |
| 51 // Must run on a background thread in production. | |
| 52 // If |bitmap_result| is square and large enough (>= |min_source_in_pixel|), | |
| 53 // resizes it to |desired_size_in_pixel| (but if |desired_size_in_pixel| is | |
| 54 // 0 then don't resize). If successful, stores the resulting bitmap data | |
| 55 // into |resized_bitmap_result| and returns true. | |
| 56 static bool ResizeLargeIconOnBackgroundThreadIfValid( | |
| 57 int min_source_size_in_pixel, | |
| 58 int desired_size_in_pixel, | |
| 59 const favicon_base::FaviconRawBitmapResult& bitmap_result, | |
| 60 favicon_base::FaviconRawBitmapResult* resized_bitmap_result); | |
| 61 | |
| 62 // Must run on the owner (UI) thread in production. | |
| 63 // Invoked when ProcessIconOnBackgroundThread() is done. | |
| 64 void OnIconProcessingComplete(); | |
| 65 | |
| 66 int min_source_size_in_pixel_; | |
| 67 int desired_size_in_pixel_; | |
| 68 favicon_base::LargeIconCallback callback_; | |
| 69 scoped_refptr<base::TaskRunner> background_task_runner_; | |
| 70 base::CancelableTaskTracker* tracker_; | |
| 71 favicon_base::FaviconRawBitmapResult bitmap_result_; | |
| 72 scoped_ptr<favicon_base::LargeIconResult> result_; | |
| 73 | |
| 74 DISALLOW_COPY_AND_ASSIGN(LargeIconWorker); | |
| 75 }; | |
| 76 | |
| 77 LargeIconWorker::LargeIconWorker( | |
| 78 int min_source_size_in_pixel, | |
| 79 int desired_size_in_pixel, | |
| 80 favicon_base::LargeIconCallback callback, | |
| 81 scoped_refptr<base::TaskRunner> background_task_runner, | |
| 82 base::CancelableTaskTracker* tracker) | |
| 83 : min_source_size_in_pixel_(min_source_size_in_pixel), | |
| 84 desired_size_in_pixel_(desired_size_in_pixel), | |
| 85 callback_(callback), | |
| 86 background_task_runner_(background_task_runner), | |
| 87 tracker_(tracker) { | |
| 21 } | 88 } |
| 22 | 89 |
| 23 LargeIconService::~LargeIconService() { | 90 LargeIconWorker::~LargeIconWorker() { |
| 24 } | 91 } |
| 25 | 92 |
| 26 base::CancelableTaskTracker::TaskId | 93 void LargeIconWorker::OnIconLookupComplete( |
| 27 LargeIconService::GetLargeIconOrFallbackStyle( | 94 const favicon_base::FaviconRawBitmapResult& bitmap_result) { |
| 28 const GURL& page_url, | 95 bitmap_result_ = bitmap_result; |
| 29 int min_source_size_in_pixel, | 96 tracker_->PostTaskAndReply( |
| 30 int desired_size_in_pixel, | 97 background_task_runner_.get(), FROM_HERE, |
| 31 const favicon_base::LargeIconCallback& callback, | 98 base::Bind(&LargeIconWorker::ProcessIconOnBackgroundThread, this), |
| 32 base::CancelableTaskTracker* tracker) { | 99 base::Bind(&LargeIconWorker::OnIconProcessingComplete, this)); |
| 33 DCHECK_LE(1, min_source_size_in_pixel); | |
| 34 DCHECK_LE(0, desired_size_in_pixel); | |
| 35 | |
| 36 // TODO(beaudoin): For now this is just a wrapper around | |
| 37 // GetLargestRawFaviconForPageURL. Add the logic required to select the best | |
| 38 // possible large icon. Also add logic to fetch-on-demand when the URL of | |
| 39 // a large icon is known but its bitmap is not available. | |
| 40 return favicon_service_->GetLargestRawFaviconForPageURL( | |
| 41 page_url, | |
| 42 large_icon_types_, | |
| 43 std::max(min_source_size_in_pixel, desired_size_in_pixel), | |
| 44 base::Bind(&LargeIconService::RunLargeIconCallback, | |
| 45 base::Unretained(this), callback, min_source_size_in_pixel, | |
| 46 desired_size_in_pixel), | |
| 47 tracker); | |
| 48 } | 100 } |
| 49 | 101 |
| 50 bool LargeIconService::ResizeLargeIconIfValid( | 102 void LargeIconWorker::ProcessIconOnBackgroundThread() { |
| 103 favicon_base::FaviconRawBitmapResult resized_bitmap_result; | |
| 104 if (ResizeLargeIconOnBackgroundThreadIfValid(min_source_size_in_pixel_, | |
| 105 desired_size_in_pixel_, bitmap_result_, &resized_bitmap_result)) { | |
| 106 result_.reset( | |
| 107 new favicon_base::LargeIconResult(resized_bitmap_result)); | |
| 108 } else { | |
| 109 // Failed to resize |bitmap_result|, so compute fallback icon style. | |
|
pkotwicz
2015/05/11 18:57:39
Nit: |bitmap_result| -> |bitmap_result_|
huangs
2015/05/11 20:24:37
Done.
| |
| 110 scoped_ptr<favicon_base::FallbackIconStyle> fallback_icon_style( | |
| 111 new favicon_base::FallbackIconStyle()); | |
| 112 if (bitmap_result_.is_valid()) { | |
| 113 favicon_base::SetDominantColorAsBackground( | |
| 114 bitmap_result_.bitmap_data, fallback_icon_style.get()); | |
| 115 } | |
| 116 result_.reset( | |
| 117 new favicon_base::LargeIconResult(fallback_icon_style.release())); | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 // static | |
| 122 bool LargeIconWorker::ResizeLargeIconOnBackgroundThreadIfValid( | |
|
pkotwicz
2015/05/11 18:57:39
Nit: Can't you grab |min_source_size_in_pixel|, |d
huangs
2015/05/11 20:24:37
Makes since now that the routine is not exposed. D
| |
| 51 int min_source_size_in_pixel, | 123 int min_source_size_in_pixel, |
| 52 int desired_size_in_pixel, | 124 int desired_size_in_pixel, |
| 53 const favicon_base::FaviconRawBitmapResult& bitmap_result, | 125 const favicon_base::FaviconRawBitmapResult& bitmap_result, |
| 54 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) { | 126 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) { |
| 55 // Require bitmap to be valid and square. | 127 // Require bitmap to be valid and square. |
| 56 if (!bitmap_result.is_valid() || | 128 if (!bitmap_result.is_valid() || |
| 57 bitmap_result.pixel_size.width() != bitmap_result.pixel_size.height()) | 129 bitmap_result.pixel_size.width() != bitmap_result.pixel_size.height()) |
| 58 return false; | 130 return false; |
| 59 | 131 |
| 60 // Require bitmap to be large enough. It's square, so just check width. | 132 // Require bitmap to be large enough. It's square, so just check width. |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 82 if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_bitmap, false, &bitmap_data)) | 154 if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_bitmap, false, &bitmap_data)) |
| 83 return false; | 155 return false; |
| 84 | 156 |
| 85 resized_bitmap_result->pixel_size = | 157 resized_bitmap_result->pixel_size = |
| 86 gfx::Size(desired_size_in_pixel, desired_size_in_pixel); | 158 gfx::Size(desired_size_in_pixel, desired_size_in_pixel); |
| 87 resized_bitmap_result->bitmap_data = | 159 resized_bitmap_result->bitmap_data = |
| 88 base::RefCountedBytes::TakeVector(&bitmap_data); | 160 base::RefCountedBytes::TakeVector(&bitmap_data); |
| 89 return true; | 161 return true; |
| 90 } | 162 } |
| 91 | 163 |
| 92 void LargeIconService::RunLargeIconCallback( | 164 void LargeIconWorker::OnIconProcessingComplete() { |
| 93 const favicon_base::LargeIconCallback& callback, | 165 callback_.Run(*result_); |
| 94 int min_source_size_in_pixel, | 166 } |
| 95 int desired_size_in_pixel, | |
| 96 const favicon_base::FaviconRawBitmapResult& bitmap_result) { | |
| 97 favicon_base::FaviconRawBitmapResult resized_bitmap_result; | |
| 98 if (ResizeLargeIconIfValid(min_source_size_in_pixel, desired_size_in_pixel, | |
| 99 bitmap_result, &resized_bitmap_result)) { | |
| 100 callback.Run(favicon_base::LargeIconResult(resized_bitmap_result)); | |
| 101 return; | |
| 102 } | |
| 103 | 167 |
| 104 // Failed to resize |bitmap_result|, so compute fallback icon style. | 168 } // namespace |
| 105 favicon_base::LargeIconResult result(new favicon_base::FallbackIconStyle()); | 169 |
| 106 if (bitmap_result.is_valid()) { | 170 namespace favicon { |
| 107 favicon_base::SetDominantColorAsBackground( | 171 |
| 108 bitmap_result.bitmap_data, result.fallback_icon_style.get()); | 172 LargeIconService::LargeIconService(FaviconService* favicon_service) |
| 109 } | 173 : favicon_service_(favicon_service) { |
| 110 callback.Run(result); | 174 large_icon_types_.push_back(favicon_base::IconType::FAVICON); |
| 175 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON); | |
| 176 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON); | |
| 177 } | |
| 178 | |
| 179 LargeIconService::~LargeIconService() { | |
| 180 } | |
| 181 | |
| 182 base::CancelableTaskTracker::TaskId | |
| 183 LargeIconService::GetLargeIconOrFallbackStyle( | |
| 184 const GURL& page_url, | |
| 185 int min_source_size_in_pixel, | |
| 186 int desired_size_in_pixel, | |
| 187 const favicon_base::LargeIconCallback& callback, | |
| 188 base::CancelableTaskTracker* tracker) { | |
| 189 DCHECK_LE(1, min_source_size_in_pixel); | |
| 190 DCHECK_LE(0, desired_size_in_pixel); | |
| 191 | |
| 192 scoped_refptr<LargeIconWorker> session = | |
|
pkotwicz
2015/05/11 18:57:39
Nit: session -> worker
huangs
2015/05/11 20:24:37
Done.
| |
| 193 new LargeIconWorker(min_source_size_in_pixel, | |
| 194 desired_size_in_pixel, callback, GetBackgroundTaskRunner(), tracker); | |
| 195 | |
| 196 // TODO(beaudoin): For now this is just a wrapper around | |
| 197 // GetLargestRawFaviconForPageURL. Add the logic required to select the best | |
| 198 // possible large icon. Also add logic to fetch-on-demand when the URL of | |
| 199 // a large icon is known but its bitmap is not available. | |
| 200 return favicon_service_->GetLargestRawFaviconForPageURL( | |
| 201 page_url, large_icon_types_, desired_size_in_pixel, | |
| 202 base::Bind(&LargeIconWorker::OnIconLookupComplete, session), | |
| 203 tracker); | |
| 204 } | |
| 205 | |
| 206 // Returns TaskRunner used to execute background task. | |
| 207 scoped_refptr<base::TaskRunner> LargeIconService::GetBackgroundTaskRunner() { | |
| 208 return content::BrowserThread::GetBlockingPool() | |
| 209 ->GetTaskRunnerWithShutdownBehavior( | |
| 210 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); | |
| 111 } | 211 } |
| 112 | 212 |
| 113 } // namespace favicon | 213 } // namespace favicon |
| OLD | NEW |