Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4474)

Unified Diff: chrome/browser/image_decoder.cc

Issue 2475543003: Introduce the image_decoder service (Closed)
Patch Set: . Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/image_decoder.h ('k') | chrome/browser/search/suggestions/image_decoder_impl.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/image_decoder.cc
diff --git a/chrome/browser/image_decoder.cc b/chrome/browser/image_decoder.cc
index 3815f26dc922621713773dbb4ee634ea70e37626..93360b7007c11ba8359abb1cd4186281aa08bcd8 100644
--- a/chrome/browser/image_decoder.cc
+++ b/chrome/browser/image_decoder.cc
@@ -7,53 +7,78 @@
#include <utility>
#include "base/bind.h"
+#include "base/callback.h"
+#include "base/lazy_instance.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/common/image_decoder.mojom.h"
-#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/utility_process_host.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "content/public/common/service_manager_connection.h"
+#include "ipc/ipc_channel.h"
+#include "services/image_decoder/public/cpp/decode.h"
+#include "services/service_manager/public/cpp/connector.h"
#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/l10n/l10n_util.h"
-
-using content::BrowserThread;
-using content::UtilityProcessHost;
namespace {
// static, Leaky to allow access from any thread.
base::LazyInstance<ImageDecoder>::Leaky g_decoder = LAZY_INSTANCE_INITIALIZER;
-// How long to wait after the last request has been received before ending
-// batch mode.
-const int kBatchModeTimeoutSeconds = 5;
+const int64_t kMaxImageSizeInBytes =
+ static_cast<int64_t>(IPC::Channel::kMaximumMessageSize);
+// Note that this is always called on the thread which initiated the
+// corresponding image_decoder::Decode request.
void OnDecodeImageDone(
base::Callback<void(int)> fail_callback,
base::Callback<void(const SkBitmap&, int)> success_callback,
int request_id,
const SkBitmap& image) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!image.isNull() && !image.empty())
success_callback.Run(image, request_id);
else
fail_callback.Run(request_id);
}
-} // namespace
+void BindToBrowserConnector(service_manager::mojom::ConnectorRequest request) {
+ if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&BindToBrowserConnector, base::Passed(&request)));
+ return;
+ }
+
+ content::ServiceManagerConnection::GetForProcess()->GetConnector()
+ ->BindRequest(std::move(request));
+}
-ImageDecoder::ImageDecoder()
- : image_request_id_counter_(0) {
- // A single ImageDecoder instance should live for the life of the program.
- // Explicitly add a reference so the object isn't deleted.
- AddRef();
+void RunDecodeCallbackOnTaskRunner(
+ const image_decoder::mojom::ImageDecoder::DecodeImageCallback& callback,
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ const SkBitmap& image) {
+ task_runner->PostTask(FROM_HERE, base::Bind(callback, image));
}
-ImageDecoder::~ImageDecoder() {
+void DecodeImage(
+ std::vector<uint8_t> image_data,
+ image_decoder::mojom::ImageCodec codec,
+ bool shrink_to_fit,
+ const image_decoder::mojom::ImageDecoder::DecodeImageCallback& callback,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ service_manager::mojom::ConnectorRequest connector_request;
+ std::unique_ptr<service_manager::Connector> connector =
+ service_manager::Connector::Create(&connector_request);
+ BindToBrowserConnector(std::move(connector_request));
+
+ image_decoder::Decode(connector.get(), image_data, codec, shrink_to_fit,
+ kMaxImageSizeInBytes,
+ base::Bind(&RunDecodeCallbackOnTaskRunner,
+ callback, callback_task_runner));
}
+} // namespace
+
ImageDecoder::ImageRequest::ImageRequest()
: task_runner_(base::ThreadTaskRunnerHandle::Get()) {
DCHECK(sequence_checker_.CalledOnValidSequence());
@@ -70,6 +95,10 @@ ImageDecoder::ImageRequest::~ImageRequest() {
ImageDecoder::Cancel(this);
}
+ImageDecoder::ImageDecoder() : image_request_id_counter_(0) {}
+
+ImageDecoder::~ImageDecoder() {}
+
// static
void ImageDecoder::Start(ImageRequest* image_request,
std::vector<uint8_t> image_data) {
@@ -88,9 +117,8 @@ void ImageDecoder::StartWithOptions(ImageRequest* image_request,
std::vector<uint8_t> image_data,
ImageCodec image_codec,
bool shrink_to_fit) {
- g_decoder.Pointer()->StartWithOptionsImpl(image_request,
- std::move(image_data),
- image_codec, shrink_to_fit);
+ g_decoder.Get().StartWithOptionsImpl(image_request, std::move(image_data),
+ image_codec, shrink_to_fit);
}
// static
@@ -117,68 +145,35 @@ void ImageDecoder::StartWithOptionsImpl(ImageRequest* image_request,
image_request_id_map_.insert(std::make_pair(request_id, image_request));
}
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(
- &ImageDecoder::DecodeImageInSandbox,
- g_decoder.Pointer(), request_id,
- base::Passed(std::move(image_data)),
- image_codec, shrink_to_fit));
+ image_decoder::mojom::ImageCodec codec =
+ image_decoder::mojom::ImageCodec::DEFAULT;
+#if defined(OS_CHROMEOS)
+ if (image_codec == ROBUST_JPEG_CODEC)
+ codec = image_decoder::mojom::ImageCodec::ROBUST_JPEG;
+ if (image_codec == ROBUST_PNG_CODEC)
+ codec = image_decoder::mojom::ImageCodec::ROBUST_PNG;
+#endif // defined(OS_CHROMEOS)
+
+ auto callback = base::Bind(
+ &OnDecodeImageDone,
+ base::Bind(&ImageDecoder::OnDecodeImageFailed, base::Unretained(this)),
+ base::Bind(&ImageDecoder::OnDecodeImageSucceeded, base::Unretained(this)),
+ request_id);
+
+ // NOTE: There exist ImageDecoder consumers which implicitly rely on this
+ // operation happening on a thread which always has a ThreadTaskRunnerHandle.
+ // We arbitrarily use the IO thread here to match details of the legacy
+ // implementation.
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&DecodeImage, base::Passed(&image_data), codec, shrink_to_fit,
+ callback, make_scoped_refptr(image_request->task_runner())));
}
// static
void ImageDecoder::Cancel(ImageRequest* image_request) {
DCHECK(image_request);
- g_decoder.Pointer()->CancelImpl(image_request);
-}
-
-void ImageDecoder::DecodeImageInSandbox(
- int request_id,
- std::vector<uint8_t> image_data,
- ImageCodec image_codec,
- bool shrink_to_fit) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- base::AutoLock lock(map_lock_);
- const auto it = image_request_id_map_.find(request_id);
- if (it == image_request_id_map_.end())
- return;
-
- ImageRequest* image_request = it->second;
- if (!utility_process_host_) {
- StartBatchMode();
- }
- if (!utility_process_host_) {
- // Utility process failed to start; notify delegate and return.
- // Without this check, we were seeing crashes on startup. Further
- // investigation is needed to determine why the utility process
- // is failing to start. See crbug.com/472272
- image_request->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&ImageDecoder::RunOnDecodeImageFailed, this, request_id));
- return;
- }
-
- if (!batch_mode_timer_) {
- // Created here so it will call StopBatchMode() on the right thread.
- batch_mode_timer_.reset(new base::DelayTimer(
- FROM_HERE, base::TimeDelta::FromSeconds(kBatchModeTimeoutSeconds), this,
- &ImageDecoder::StopBatchMode));
- }
- batch_mode_timer_->Reset();
-
- mojom::ImageCodec mojo_codec = mojom::ImageCodec::DEFAULT;
-#if defined(OS_CHROMEOS)
- if (image_codec == ROBUST_JPEG_CODEC)
- mojo_codec = mojom::ImageCodec::ROBUST_JPEG;
- if (image_codec == ROBUST_PNG_CODEC)
- mojo_codec = mojom::ImageCodec::ROBUST_PNG;
-#endif // defined(OS_CHROMEOS)
- decoder_->DecodeImage(
- image_data, mojo_codec, shrink_to_fit,
- base::Bind(&OnDecodeImageDone,
- base::Bind(&ImageDecoder::OnDecodeImageFailed, this),
- base::Bind(&ImageDecoder::OnDecodeImageSucceeded, this),
- request_id));
+ g_decoder.Get().CancelImpl(image_request);
}
void ImageDecoder::CancelImpl(ImageRequest* image_request) {
@@ -193,104 +188,9 @@ void ImageDecoder::CancelImpl(ImageRequest* image_request) {
}
}
-void ImageDecoder::StartBatchMode() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- utility_process_host_ =
- UtilityProcessHost::Create(
- this, base::ThreadTaskRunnerHandle::Get().get())->AsWeakPtr();
- utility_process_host_->SetName(l10n_util::GetStringUTF16(
- IDS_UTILITY_PROCESS_IMAGE_DECODER_NAME));
- if (!utility_process_host_->Start()) {
- delete utility_process_host_.get();
- return;
- }
- utility_process_host_->GetRemoteInterfaces()->GetInterface(&decoder_);
-}
-
-void ImageDecoder::StopBatchMode() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- {
- // Check for outstanding requests and wait for them to finish.
- base::AutoLock lock(map_lock_);
- if (!image_request_id_map_.empty()) {
- batch_mode_timer_->Reset();
- return;
- }
- }
-
- if (utility_process_host_) {
- // With Mojo, the utility process needs to be explicitly shut down by
- // deleting the host.
- delete utility_process_host_.get();
- decoder_.reset();
- utility_process_host_.reset();
- }
-}
-
-void ImageDecoder::FailAllRequests() {
- RequestMap requests;
- {
- base::AutoLock lock(map_lock_);
- requests = image_request_id_map_;
- }
-
- // Since |OnProcessCrashed| and |OnProcessLaunchFailed| are run asynchronously
- // from the actual event, it's possible for a new utility process to have been
- // created and sent requests by the time these functions are run. This results
- // in failing requests that are unaffected by the crash. Although not ideal,
- // this is valid and simpler than tracking which request is sent to which
- // utility process, and whether the request has been sent at all.
- for (const auto& request : requests)
- OnDecodeImageFailed(request.first);
-}
-
-void ImageDecoder::OnProcessCrashed(int exit_code) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FailAllRequests();
-}
-
-void ImageDecoder::OnProcessLaunchFailed(int error_code) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- FailAllRequests();
-}
-
-bool ImageDecoder::OnMessageReceived(const IPC::Message& message) {
- return false;
-}
-
void ImageDecoder::OnDecodeImageSucceeded(
const SkBitmap& decoded_image,
int request_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- base::AutoLock lock(map_lock_);
- auto it = image_request_id_map_.find(request_id);
- if (it == image_request_id_map_.end())
- return;
-
- ImageRequest* image_request = it->second;
- image_request->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&ImageDecoder::RunOnImageDecoded,
- this,
- decoded_image,
- request_id));
-}
-
-void ImageDecoder::OnDecodeImageFailed(int request_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- base::AutoLock lock(map_lock_);
- auto it = image_request_id_map_.find(request_id);
- if (it == image_request_id_map_.end())
- return;
-
- ImageRequest* image_request = it->second;
- image_request->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&ImageDecoder::RunOnDecodeImageFailed, this, request_id));
-}
-
-void ImageDecoder::RunOnImageDecoded(const SkBitmap& decoded_image,
- int request_id) {
ImageRequest* image_request;
{
base::AutoLock lock(map_lock_);
@@ -305,7 +205,7 @@ void ImageDecoder::RunOnImageDecoded(const SkBitmap& decoded_image,
image_request->OnImageDecoded(decoded_image);
}
-void ImageDecoder::RunOnDecodeImageFailed(int request_id) {
+void ImageDecoder::OnDecodeImageFailed(int request_id) {
ImageRequest* image_request;
{
base::AutoLock lock(map_lock_);
« no previous file with comments | « chrome/browser/image_decoder.h ('k') | chrome/browser/search/suggestions/image_decoder_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698