blob: 12306d8392893fee0bb4b68d2e09de2ea2094e51 [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"
11#include "base/lazy_instance.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"
[email protected]c38831a12011-10-28 12:44:4914#include "content/public/browser/browser_thread.h"
rockot2a0f4fb32016-11-11 18:44:1915#include "content/public/common/service_manager_connection.h"
16#include "ipc/ipc_channel.h"
17#include "services/image_decoder/public/cpp/decode.h"
18#include "services/service_manager/public/cpp/connector.h"
amistry6f72f042016-04-05 20:42:0719#include "third_party/skia/include/core/SkBitmap.h"
[email protected]631bb742011-11-02 11:29:3920
twellingtona71414d2015-03-26 15:09:4521namespace {
22
23// static, Leaky to allow access from any thread.
24base::LazyInstance<ImageDecoder>::Leaky g_decoder = LAZY_INSTANCE_INITIALIZER;
25
rockot2a0f4fb32016-11-11 18:44:1926const int64_t kMaxImageSizeInBytes =
27 static_cast<int64_t>(IPC::Channel::kMaximumMessageSize);
twellingtona71414d2015-03-26 15:09:4528
rockot2a0f4fb32016-11-11 18:44:1929// Note that this is always called on the thread which initiated the
30// corresponding image_decoder::Decode request.
amistry6f72f042016-04-05 20:42:0731void OnDecodeImageDone(
32 base::Callback<void(int)> fail_callback,
33 base::Callback<void(const SkBitmap&, int)> success_callback,
mswb0123d12016-06-01 21:59:5434 int request_id,
35 const SkBitmap& image) {
mswb0123d12016-06-01 21:59:5436 if (!image.isNull() && !image.empty())
37 success_callback.Run(image, request_id);
38 else
39 fail_callback.Run(request_id);
amistry6f72f042016-04-05 20:42:0740}
41
rockot2a0f4fb32016-11-11 18:44:1942void BindToBrowserConnector(service_manager::mojom::ConnectorRequest request) {
43 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
44 content::BrowserThread::PostTask(
45 content::BrowserThread::UI, FROM_HERE,
46 base::Bind(&BindToBrowserConnector, base::Passed(&request)));
47 return;
48 }
49
50 content::ServiceManagerConnection::GetForProcess()->GetConnector()
benbd3c2482017-01-07 05:48:2151 ->BindConnectorRequest(std::move(request));
rockot2a0f4fb32016-11-11 18:44:1952}
53
54void RunDecodeCallbackOnTaskRunner(
55 const image_decoder::mojom::ImageDecoder::DecodeImageCallback& callback,
56 scoped_refptr<base::SequencedTaskRunner> task_runner,
57 const SkBitmap& image) {
58 task_runner->PostTask(FROM_HERE, base::Bind(callback, image));
59}
60
61void DecodeImage(
62 std::vector<uint8_t> image_data,
63 image_decoder::mojom::ImageCodec codec,
64 bool shrink_to_fit,
65 const image_decoder::mojom::ImageDecoder::DecodeImageCallback& callback,
66 scoped_refptr<base::SequencedTaskRunner> callback_task_runner) {
67 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
68
69 service_manager::mojom::ConnectorRequest connector_request;
70 std::unique_ptr<service_manager::Connector> connector =
71 service_manager::Connector::Create(&connector_request);
72 BindToBrowserConnector(std::move(connector_request));
73
74 image_decoder::Decode(connector.get(), image_data, codec, shrink_to_fit,
75 kMaxImageSizeInBytes,
76 base::Bind(&RunDecodeCallbackOnTaskRunner,
77 callback, callback_task_runner));
78}
79
twellingtona71414d2015-03-26 15:09:4580} // namespace
81
thestigc5eeb9f362015-04-22 18:42:3282ImageDecoder::ImageRequest::ImageRequest()
83 : task_runner_(base::ThreadTaskRunnerHandle::Get()) {
fdoraye2b19a12016-07-29 02:30:1684 DCHECK(sequence_checker_.CalledOnValidSequence());
thestigc5eeb9f362015-04-22 18:42:3285}
86
twellingtona71414d2015-03-26 15:09:4587ImageDecoder::ImageRequest::ImageRequest(
88 const scoped_refptr<base::SequencedTaskRunner>& task_runner)
89 : task_runner_(task_runner) {
fdoraye2b19a12016-07-29 02:30:1690 DCHECK(sequence_checker_.CalledOnValidSequence());
twellingtona71414d2015-03-26 15:09:4591}
[email protected]863e6d962011-05-15 19:39:3592
twellingtona71414d2015-03-26 15:09:4593ImageDecoder::ImageRequest::~ImageRequest() {
fdoraye2b19a12016-07-29 02:30:1694 DCHECK(sequence_checker_.CalledOnValidSequence());
twellingtona71414d2015-03-26 15:09:4595 ImageDecoder::Cancel(this);
96}
97
rockot2a0f4fb32016-11-11 18:44:1998ImageDecoder::ImageDecoder() : image_request_id_counter_(0) {}
99
100ImageDecoder::~ImageDecoder() {}
101
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) {
105 StartWithOptions(image_request, std::move(image_data), DEFAULT_CODEC, false);
106}
107
108// static
109void ImageDecoder::Start(ImageRequest* image_request,
twellingtona71414d2015-03-26 15:09:45110 const std::string& image_data) {
nya601d9702016-07-26 18:39:21111 Start(image_request,
112 std::vector<uint8_t>(image_data.begin(), image_data.end()));
113}
114
115// static
116void ImageDecoder::StartWithOptions(ImageRequest* image_request,
117 std::vector<uint8_t> image_data,
118 ImageCodec image_codec,
119 bool shrink_to_fit) {
rockot2a0f4fb32016-11-11 18:44:19120 g_decoder.Get().StartWithOptionsImpl(image_request, std::move(image_data),
121 image_codec, shrink_to_fit);
twellingtona71414d2015-03-26 15:09:45122}
123
124// static
125void ImageDecoder::StartWithOptions(ImageRequest* image_request,
126 const std::string& image_data,
127 ImageCodec image_codec,
128 bool shrink_to_fit) {
nya601d9702016-07-26 18:39:21129 StartWithOptions(image_request,
130 std::vector<uint8_t>(image_data.begin(), image_data.end()),
131 image_codec, shrink_to_fit);
thestigc5eeb9f362015-04-22 18:42:32132}
133
134void ImageDecoder::StartWithOptionsImpl(ImageRequest* image_request,
nya601d9702016-07-26 18:39:21135 std::vector<uint8_t> image_data,
thestigc5eeb9f362015-04-22 18:42:32136 ImageCodec image_codec,
137 bool shrink_to_fit) {
twellingtona71414d2015-03-26 15:09:45138 DCHECK(image_request);
139 DCHECK(image_request->task_runner());
thestigc5eeb9f362015-04-22 18:42:32140
141 int request_id;
142 {
143 base::AutoLock lock(map_lock_);
144 request_id = image_request_id_counter_++;
145 image_request_id_map_.insert(std::make_pair(request_id, image_request));
146 }
147
rockot2a0f4fb32016-11-11 18:44:19148 image_decoder::mojom::ImageCodec codec =
149 image_decoder::mojom::ImageCodec::DEFAULT;
150#if defined(OS_CHROMEOS)
151 if (image_codec == ROBUST_JPEG_CODEC)
152 codec = image_decoder::mojom::ImageCodec::ROBUST_JPEG;
153 if (image_codec == ROBUST_PNG_CODEC)
154 codec = image_decoder::mojom::ImageCodec::ROBUST_PNG;
155#endif // defined(OS_CHROMEOS)
156
157 auto callback = base::Bind(
158 &OnDecodeImageDone,
159 base::Bind(&ImageDecoder::OnDecodeImageFailed, base::Unretained(this)),
160 base::Bind(&ImageDecoder::OnDecodeImageSucceeded, base::Unretained(this)),
161 request_id);
162
163 // NOTE: There exist ImageDecoder consumers which implicitly rely on this
164 // operation happening on a thread which always has a ThreadTaskRunnerHandle.
165 // We arbitrarily use the IO thread here to match details of the legacy
166 // implementation.
167 content::BrowserThread::PostTask(
168 content::BrowserThread::IO, FROM_HERE,
169 base::Bind(&DecodeImage, base::Passed(&image_data), codec, shrink_to_fit,
170 callback, make_scoped_refptr(image_request->task_runner())));
[email protected]551707a2010-06-16 16:59:47171}
172
twellingtona71414d2015-03-26 15:09:45173// static
174void ImageDecoder::Cancel(ImageRequest* image_request) {
175 DCHECK(image_request);
rockot2a0f4fb32016-11-11 18:44:19176 g_decoder.Get().CancelImpl(image_request);
twellingtona71414d2015-03-26 15:09:45177}
178
179void ImageDecoder::CancelImpl(ImageRequest* image_request) {
180 base::AutoLock lock(map_lock_);
181 for (auto it = image_request_id_map_.begin();
182 it != image_request_id_map_.end();) {
183 if (it->second == image_request) {
184 image_request_id_map_.erase(it++);
185 } else {
186 ++it;
187 }
188 }
189}
190
twellingtona71414d2015-03-26 15:09:45191void ImageDecoder::OnDecodeImageSucceeded(
192 const SkBitmap& decoded_image,
193 int request_id) {
thestigc5eeb9f362015-04-22 18:42:32194 ImageRequest* image_request;
195 {
196 base::AutoLock lock(map_lock_);
197 auto it = image_request_id_map_.find(request_id);
198 if (it == image_request_id_map_.end())
199 return;
200 image_request = it->second;
twellingtona71414d2015-03-26 15:09:45201 image_request_id_map_.erase(it);
[email protected]11f16d102012-08-29 23:12:15202 }
thestigc5eeb9f362015-04-22 18:42:32203
204 DCHECK(image_request->task_runner()->RunsTasksOnCurrentThread());
205 image_request->OnImageDecoded(decoded_image);
206}
207
rockot2a0f4fb32016-11-11 18:44:19208void ImageDecoder::OnDecodeImageFailed(int request_id) {
thestigc5eeb9f362015-04-22 18:42:32209 ImageRequest* image_request;
210 {
211 base::AutoLock lock(map_lock_);
212 auto it = image_request_id_map_.find(request_id);
213 if (it == image_request_id_map_.end())
214 return;
215 image_request = it->second;
216 image_request_id_map_.erase(it);
217 }
218
219 DCHECK(image_request->task_runner()->RunsTasksOnCurrentThread());
220 image_request->OnDecodeImageFailed();
[email protected]551707a2010-06-16 16:59:47221}