blob: 96cb124f04e0b93a21876f5e3aaac7cda511b819 [file] [log] [blame]
[email protected]44013f682012-05-31 13:49:401// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]551707a2010-06-16 16:59:472// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]6d33da172011-11-22 03:56:095#include "chrome/browser/image_decoder.h"
[email protected]551707a2010-06-16 16:59:476
nya601d9702016-07-26 18:39:217#include <utility>
8
[email protected]31893772011-10-11 17:41:509#include "base/bind.h"
rockot2a0f4fb32016-11-11 18:44:1910#include "base/callback.h"
Eric Seckler8652dcd52018-09-20 10:42:2811#include "base/task/post_task.h"
gabb15e19072016-05-11 20:45:4112#include "base/threading/thread_task_runner_handle.h"
avi6846aef2015-12-26 01:09:3813#include "build/build_config.h"
Eric Seckler8652dcd52018-09-20 10:42:2814#include "content/public/browser/browser_task_traits.h"
[email protected]c38831a12011-10-28 12:44:4915#include "content/public/browser/browser_thread.h"
rockot2a0f4fb32016-11-11 18:44:1916#include "content/public/common/service_manager_connection.h"
17#include "ipc/ipc_channel.h"
rockote0437032017-03-25 02:49:0018#include "services/data_decoder/public/cpp/decode_image.h"
rockot2a0f4fb32016-11-11 18:44:1919#include "services/service_manager/public/cpp/connector.h"
amistry6f72f042016-04-05 20:42:0720#include "third_party/skia/include/core/SkBitmap.h"
tschumann30ee1082017-03-02 19:37:5321#include "ui/gfx/geometry/size.h"
[email protected]631bb742011-11-02 11:29:3922
twellingtona71414d2015-03-26 15:09:4523namespace {
24
rockot2a0f4fb32016-11-11 18:44:1925const int64_t kMaxImageSizeInBytes =
26 static_cast<int64_t>(IPC::Channel::kMaximumMessageSize);
twellingtona71414d2015-03-26 15:09:4527
rockot2a0f4fb32016-11-11 18:44:1928// Note that this is always called on the thread which initiated the
rockote0437032017-03-25 02:49:0029// corresponding data_decoder::DecodeImage request.
amistry6f72f042016-04-05 20:42:0730void OnDecodeImageDone(
31 base::Callback<void(int)> fail_callback,
32 base::Callback<void(const SkBitmap&, int)> success_callback,
mswb0123d12016-06-01 21:59:5433 int request_id,
34 const SkBitmap& image) {
mswb0123d12016-06-01 21:59:5435 if (!image.isNull() && !image.empty())
36 success_callback.Run(image, request_id);
37 else
38 fail_callback.Run(request_id);
amistry6f72f042016-04-05 20:42:0739}
40
rockot2a0f4fb32016-11-11 18:44:1941void BindToBrowserConnector(service_manager::mojom::ConnectorRequest request) {
Lei Zhangc06d9792018-01-27 07:14:5342 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
rockot2a0f4fb32016-11-11 18:44:1943
44 content::ServiceManagerConnection::GetForProcess()->GetConnector()
benbd3c2482017-01-07 05:48:2145 ->BindConnectorRequest(std::move(request));
rockot2a0f4fb32016-11-11 18:44:1946}
47
48void RunDecodeCallbackOnTaskRunner(
tzik4ec0ecf2017-07-07 03:51:5349 data_decoder::mojom::ImageDecoder::DecodeImageCallback callback,
rockot2a0f4fb32016-11-11 18:44:1950 scoped_refptr<base::SequencedTaskRunner> task_runner,
51 const SkBitmap& image) {
tzik4ec0ecf2017-07-07 03:51:5352 task_runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback), image));
rockot2a0f4fb32016-11-11 18:44:1953}
54
55void DecodeImage(
56 std::vector<uint8_t> image_data,
rockote0437032017-03-25 02:49:0057 data_decoder::mojom::ImageCodec codec,
rockot2a0f4fb32016-11-11 18:44:1958 bool shrink_to_fit,
tschumann30ee1082017-03-02 19:37:5359 const gfx::Size& desired_image_frame_size,
tzik4ec0ecf2017-07-07 03:51:5360 data_decoder::mojom::ImageDecoder::DecodeImageCallback callback,
rockot2a0f4fb32016-11-11 18:44:1961 scoped_refptr<base::SequencedTaskRunner> callback_task_runner) {
62 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
63
64 service_manager::mojom::ConnectorRequest connector_request;
65 std::unique_ptr<service_manager::Connector> connector =
66 service_manager::Connector::Create(&connector_request);
Eric Seckler8652dcd52018-09-20 10:42:2867 base::PostTaskWithTraits(
68 FROM_HERE, {content::BrowserThread::UI},
Lei Zhangc06d9792018-01-27 07:14:5369 base::BindOnce(&BindToBrowserConnector, std::move(connector_request)));
rockot2a0f4fb32016-11-11 18:44:1970
tzik4ec0ecf2017-07-07 03:51:5371 data_decoder::DecodeImage(
72 connector.get(), image_data, codec, shrink_to_fit, kMaxImageSizeInBytes,
73 desired_image_frame_size,
74 base::BindOnce(&RunDecodeCallbackOnTaskRunner, std::move(callback),
75 std::move(callback_task_runner)));
rockot2a0f4fb32016-11-11 18:44:1976}
77
twellingtona71414d2015-03-26 15:09:4578} // namespace
79
thestigc5eeb9f362015-04-22 18:42:3280ImageDecoder::ImageRequest::ImageRequest()
81 : task_runner_(base::ThreadTaskRunnerHandle::Get()) {
fdoraye2b19a12016-07-29 02:30:1682 DCHECK(sequence_checker_.CalledOnValidSequence());
thestigc5eeb9f362015-04-22 18:42:3283}
84
twellingtona71414d2015-03-26 15:09:4585ImageDecoder::ImageRequest::ImageRequest(
86 const scoped_refptr<base::SequencedTaskRunner>& task_runner)
87 : task_runner_(task_runner) {
fdoraye2b19a12016-07-29 02:30:1688 DCHECK(sequence_checker_.CalledOnValidSequence());
twellingtona71414d2015-03-26 15:09:4589}
[email protected]863e6d962011-05-15 19:39:3590
twellingtona71414d2015-03-26 15:09:4591ImageDecoder::ImageRequest::~ImageRequest() {
fdoraye2b19a12016-07-29 02:30:1692 DCHECK(sequence_checker_.CalledOnValidSequence());
twellingtona71414d2015-03-26 15:09:4593 ImageDecoder::Cancel(this);
94}
95
scottmgd69ee9d2017-02-06 20:55:3696// static
97ImageDecoder* ImageDecoder::GetInstance() {
98 static auto* image_decoder = new ImageDecoder();
99 return image_decoder;
100}
rockot2a0f4fb32016-11-11 18:44:19101
twellingtona71414d2015-03-26 15:09:45102// static
103void ImageDecoder::Start(ImageRequest* image_request,
nya601d9702016-07-26 18:39:21104 std::vector<uint8_t> image_data) {
tschumann30ee1082017-03-02 19:37:53105 StartWithOptions(image_request, std::move(image_data), DEFAULT_CODEC, false,
106 gfx::Size());
nya601d9702016-07-26 18:39:21107}
108
109// static
110void ImageDecoder::Start(ImageRequest* image_request,
twellingtona71414d2015-03-26 15:09:45111 const std::string& image_data) {
nya601d9702016-07-26 18:39:21112 Start(image_request,
113 std::vector<uint8_t>(image_data.begin(), image_data.end()));
114}
115
116// static
117void ImageDecoder::StartWithOptions(ImageRequest* image_request,
118 std::vector<uint8_t> image_data,
119 ImageCodec image_codec,
tschumann30ee1082017-03-02 19:37:53120 bool shrink_to_fit,
121 const gfx::Size& desired_image_frame_size) {
scottmgd69ee9d2017-02-06 20:55:36122 ImageDecoder::GetInstance()->StartWithOptionsImpl(
tschumann30ee1082017-03-02 19:37:53123 image_request, std::move(image_data), image_codec, shrink_to_fit,
124 desired_image_frame_size);
twellingtona71414d2015-03-26 15:09:45125}
126
127// static
128void ImageDecoder::StartWithOptions(ImageRequest* image_request,
129 const std::string& image_data,
130 ImageCodec image_codec,
131 bool shrink_to_fit) {
nya601d9702016-07-26 18:39:21132 StartWithOptions(image_request,
133 std::vector<uint8_t>(image_data.begin(), image_data.end()),
tschumann30ee1082017-03-02 19:37:53134 image_codec, shrink_to_fit, gfx::Size());
thestigc5eeb9f362015-04-22 18:42:32135}
136
scottmgd69ee9d2017-02-06 20:55:36137ImageDecoder::ImageDecoder() : image_request_id_counter_(0) {}
138
tschumann30ee1082017-03-02 19:37:53139void ImageDecoder::StartWithOptionsImpl(
140 ImageRequest* image_request,
141 std::vector<uint8_t> image_data,
142 ImageCodec image_codec,
143 bool shrink_to_fit,
144 const gfx::Size& desired_image_frame_size) {
twellingtona71414d2015-03-26 15:09:45145 DCHECK(image_request);
146 DCHECK(image_request->task_runner());
thestigc5eeb9f362015-04-22 18:42:32147
148 int request_id;
149 {
150 base::AutoLock lock(map_lock_);
151 request_id = image_request_id_counter_++;
152 image_request_id_map_.insert(std::make_pair(request_id, image_request));
153 }
154
rockote0437032017-03-25 02:49:00155 data_decoder::mojom::ImageCodec codec =
156 data_decoder::mojom::ImageCodec::DEFAULT;
rockot2a0f4fb32016-11-11 18:44:19157#if defined(OS_CHROMEOS)
158 if (image_codec == ROBUST_JPEG_CODEC)
rockote0437032017-03-25 02:49:00159 codec = data_decoder::mojom::ImageCodec::ROBUST_JPEG;
rockot2a0f4fb32016-11-11 18:44:19160 if (image_codec == ROBUST_PNG_CODEC)
rockote0437032017-03-25 02:49:00161 codec = data_decoder::mojom::ImageCodec::ROBUST_PNG;
rockot2a0f4fb32016-11-11 18:44:19162#endif // defined(OS_CHROMEOS)
163
164 auto callback = base::Bind(
165 &OnDecodeImageDone,
166 base::Bind(&ImageDecoder::OnDecodeImageFailed, base::Unretained(this)),
167 base::Bind(&ImageDecoder::OnDecodeImageSucceeded, base::Unretained(this)),
168 request_id);
169
170 // NOTE: There exist ImageDecoder consumers which implicitly rely on this
171 // operation happening on a thread which always has a ThreadTaskRunnerHandle.
172 // We arbitrarily use the IO thread here to match details of the legacy
173 // implementation.
Eric Seckler8652dcd52018-09-20 10:42:28174 base::PostTaskWithTraits(
175 FROM_HERE, {content::BrowserThread::IO},
tzik6d3cd7562018-02-21 12:07:22176 base::BindOnce(&DecodeImage, std::move(image_data), codec, shrink_to_fit,
177 desired_image_frame_size, callback,
kylecharda69d882017-10-04 05:49:52178 base::WrapRefCounted(image_request->task_runner())));
[email protected]551707a2010-06-16 16:59:47179}
180
twellingtona71414d2015-03-26 15:09:45181// static
182void ImageDecoder::Cancel(ImageRequest* image_request) {
183 DCHECK(image_request);
scottmgd69ee9d2017-02-06 20:55:36184 ImageDecoder::GetInstance()->CancelImpl(image_request);
twellingtona71414d2015-03-26 15:09:45185}
186
187void ImageDecoder::CancelImpl(ImageRequest* image_request) {
188 base::AutoLock lock(map_lock_);
189 for (auto it = image_request_id_map_.begin();
190 it != image_request_id_map_.end();) {
191 if (it->second == image_request) {
192 image_request_id_map_.erase(it++);
193 } else {
194 ++it;
195 }
196 }
197}
198
twellingtona71414d2015-03-26 15:09:45199void ImageDecoder::OnDecodeImageSucceeded(
200 const SkBitmap& decoded_image,
201 int request_id) {
thestigc5eeb9f362015-04-22 18:42:32202 ImageRequest* image_request;
203 {
204 base::AutoLock lock(map_lock_);
205 auto it = image_request_id_map_.find(request_id);
206 if (it == image_request_id_map_.end())
207 return;
208 image_request = it->second;
twellingtona71414d2015-03-26 15:09:45209 image_request_id_map_.erase(it);
[email protected]11f16d102012-08-29 23:12:15210 }
thestigc5eeb9f362015-04-22 18:42:32211
peary2be588082017-05-17 01:59:49212 DCHECK(image_request->task_runner()->RunsTasksInCurrentSequence());
thestigc5eeb9f362015-04-22 18:42:32213 image_request->OnImageDecoded(decoded_image);
214}
215
rockot2a0f4fb32016-11-11 18:44:19216void ImageDecoder::OnDecodeImageFailed(int request_id) {
thestigc5eeb9f362015-04-22 18:42:32217 ImageRequest* image_request;
218 {
219 base::AutoLock lock(map_lock_);
220 auto it = image_request_id_map_.find(request_id);
221 if (it == image_request_id_map_.end())
222 return;
223 image_request = it->second;
224 image_request_id_map_.erase(it);
225 }
226
peary2be588082017-05-17 01:59:49227 DCHECK(image_request->task_runner()->RunsTasksInCurrentSequence());
thestigc5eeb9f362015-04-22 18:42:32228 image_request->OnDecodeImageFailed();
[email protected]551707a2010-06-16 16:59:47229}