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 |