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/message_loop/message_loop.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 "content/public/browser/browser_thread.h" |
10 #include "skia/ext/image_operations.h" | 15 #include "skia/ext/image_operations.h" |
11 #include "ui/gfx/codec/png_codec.h" | 16 #include "ui/gfx/codec/png_codec.h" |
12 #include "ui/gfx/geometry/size.h" | 17 #include "ui/gfx/geometry/size.h" |
13 | 18 |
19 namespace { | |
20 | |
21 } // namespace | |
22 | |
14 namespace favicon { | 23 namespace favicon { |
15 | 24 |
16 LargeIconService::LargeIconService(FaviconService* favicon_service) | 25 LargeIconService::Session::Session( |
17 : favicon_service_(favicon_service) { | 26 int min_source_size_in_pixel, |
18 large_icon_types_.push_back(favicon_base::IconType::FAVICON); | 27 int desired_size_in_pixel, |
19 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON); | 28 favicon_base::LargeIconCallback callback, |
20 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON); | 29 scoped_refptr<base::TaskRunner> background_task_runner, |
30 base::CancelableTaskTracker* tracker) | |
31 : min_source_size_in_pixel_(min_source_size_in_pixel), | |
32 desired_size_in_pixel_(desired_size_in_pixel), | |
33 callback_(callback), | |
34 background_task_runner_(background_task_runner), | |
35 caller_task_runner_(base::MessageLoop::current()->task_runner()), | |
36 tracker_(tracker) { | |
21 } | 37 } |
22 | 38 |
23 LargeIconService::~LargeIconService() { | 39 LargeIconService::Session::~Session() { |
24 } | 40 } |
25 | 41 |
26 base::CancelableTaskTracker::TaskId | 42 void LargeIconService::Session::OnIconLookupComplete( |
27 LargeIconService::GetLargeIconOrFallbackStyle( | 43 const favicon_base::FaviconRawBitmapResult& bitmap_result) { |
28 const GURL& page_url, | 44 bitmap_result_ = bitmap_result; |
29 int min_source_size_in_pixel, | 45 tracker_->PostTask( |
30 int desired_size_in_pixel, | 46 background_task_runner_.get(), FROM_HERE, |
31 const favicon_base::LargeIconCallback& callback, | 47 base::Bind(&LargeIconService::Session::ProcessIconOnBackgroundThread, |
32 base::CancelableTaskTracker* tracker) { | 48 this)); |
pkotwicz
2015/05/11 14:35:08
Shouldn't you use CancelableTaskTracker::PostTaskA
huangs
2015/05/11 15:20:39
Nice! Done.
| |
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 } | 49 } |
49 | 50 |
50 bool LargeIconService::ResizeLargeIconIfValid( | 51 void LargeIconService::Session::ProcessIconOnBackgroundThread() { |
52 favicon_base::FaviconRawBitmapResult resized_bitmap_result; | |
53 if (ResizeLargeIconOnBackgroundThreadIfValid(min_source_size_in_pixel_, | |
54 desired_size_in_pixel_, bitmap_result_, &resized_bitmap_result)) { | |
55 result_.reset( | |
56 new favicon_base::LargeIconResult(resized_bitmap_result)); | |
57 } else { | |
58 // Failed to resize |bitmap_result|, so compute fallback icon style. | |
59 scoped_ptr<favicon_base::FallbackIconStyle> fallback_icon_style( | |
60 new favicon_base::FallbackIconStyle()); | |
61 if (bitmap_result_.is_valid()) { | |
62 favicon_base::SetDominantColorAsBackground( | |
63 bitmap_result_.bitmap_data, fallback_icon_style.get()); | |
64 } | |
65 result_.reset( | |
66 new favicon_base::LargeIconResult(fallback_icon_style.release())); | |
67 } | |
68 | |
69 // Should not use |tracker_|, which should only be used in the caller thread. | |
70 caller_task_runner_->PostTask( | |
71 FROM_HERE, | |
72 base::Bind(&LargeIconService::Session::OnIconProcessingComplete, this)); | |
73 } | |
74 | |
75 // static | |
76 bool LargeIconService::Session::ResizeLargeIconOnBackgroundThreadIfValid( | |
51 int min_source_size_in_pixel, | 77 int min_source_size_in_pixel, |
52 int desired_size_in_pixel, | 78 int desired_size_in_pixel, |
53 const favicon_base::FaviconRawBitmapResult& bitmap_result, | 79 const favicon_base::FaviconRawBitmapResult& bitmap_result, |
54 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) { | 80 favicon_base::FaviconRawBitmapResult* resized_bitmap_result) { |
55 // Require bitmap to be valid and square. | 81 // Require bitmap to be valid and square. |
56 if (!bitmap_result.is_valid() || | 82 if (!bitmap_result.is_valid() || |
57 bitmap_result.pixel_size.width() != bitmap_result.pixel_size.height()) | 83 bitmap_result.pixel_size.width() != bitmap_result.pixel_size.height()) |
58 return false; | 84 return false; |
59 | 85 |
60 // Require bitmap to be large enough. It's square, so just check width. | 86 // 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)) | 108 if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_bitmap, false, &bitmap_data)) |
83 return false; | 109 return false; |
84 | 110 |
85 resized_bitmap_result->pixel_size = | 111 resized_bitmap_result->pixel_size = |
86 gfx::Size(desired_size_in_pixel, desired_size_in_pixel); | 112 gfx::Size(desired_size_in_pixel, desired_size_in_pixel); |
87 resized_bitmap_result->bitmap_data = | 113 resized_bitmap_result->bitmap_data = |
88 base::RefCountedBytes::TakeVector(&bitmap_data); | 114 base::RefCountedBytes::TakeVector(&bitmap_data); |
89 return true; | 115 return true; |
90 } | 116 } |
91 | 117 |
92 void LargeIconService::RunLargeIconCallback( | 118 void LargeIconService::Session::OnIconProcessingComplete() { |
93 const favicon_base::LargeIconCallback& callback, | 119 callback_.Run(*result_); |
94 int min_source_size_in_pixel, | 120 } |
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 | 121 |
104 // Failed to resize |bitmap_result|, so compute fallback icon style. | 122 LargeIconService::LargeIconService(FaviconService* favicon_service) |
105 favicon_base::LargeIconResult result(new favicon_base::FallbackIconStyle()); | 123 : favicon_service_(favicon_service) { |
106 if (bitmap_result.is_valid()) { | 124 large_icon_types_.push_back(favicon_base::IconType::FAVICON); |
107 favicon_base::SetDominantColorAsBackground( | 125 large_icon_types_.push_back(favicon_base::IconType::TOUCH_ICON); |
108 bitmap_result.bitmap_data, result.fallback_icon_style.get()); | 126 large_icon_types_.push_back(favicon_base::IconType::TOUCH_PRECOMPOSED_ICON); |
109 } | 127 } |
110 callback.Run(result); | 128 |
129 LargeIconService::~LargeIconService() { | |
130 } | |
131 | |
132 base::CancelableTaskTracker::TaskId | |
133 LargeIconService::GetLargeIconOrFallbackStyle( | |
134 const GURL& page_url, | |
135 int min_source_size_in_pixel, | |
136 int desired_size_in_pixel, | |
137 const favicon_base::LargeIconCallback& callback, | |
138 base::CancelableTaskTracker* tracker) { | |
139 DCHECK_LE(1, min_source_size_in_pixel); | |
140 DCHECK_LE(0, desired_size_in_pixel); | |
141 | |
142 scoped_refptr<LargeIconService::Session> session = | |
143 new LargeIconService::Session(min_source_size_in_pixel, | |
144 desired_size_in_pixel, callback, GetBackgroundTaskRunner(), tracker); | |
145 | |
146 // TODO(beaudoin): For now this is just a wrapper around | |
147 // GetLargestRawFaviconForPageURL. Add the logic required to select the best | |
148 // possible large icon. Also add logic to fetch-on-demand when the URL of | |
149 // a large icon is known but its bitmap is not available. | |
150 return favicon_service_->GetLargestRawFaviconForPageURL( | |
151 page_url, large_icon_types_, desired_size_in_pixel, | |
152 base::Bind(&LargeIconService::Session::OnIconLookupComplete, session), | |
153 tracker); | |
154 } | |
155 | |
156 // Returns TaskRunner used to execute background task. | |
157 scoped_refptr<base::TaskRunner> LargeIconService::GetBackgroundTaskRunner() { | |
158 return content::BrowserThread::GetBlockingPool() | |
159 ->GetTaskRunnerWithShutdownBehavior( | |
160 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); | |
111 } | 161 } |
112 | 162 |
113 } // namespace favicon | 163 } // namespace favicon |
OLD | NEW |