| Index: chrome/browser/image_decoder.cc
|
| diff --git a/chrome/browser/image_decoder.cc b/chrome/browser/image_decoder.cc
|
| index 2f9e83b7ab8953f41eb2d5a4bfc091e8f7e81ce7..f3cb25470cf50ede69b0fd9ab26f087e3a1c4bbb 100644
|
| --- a/chrome/browser/image_decoder.cc
|
| +++ b/chrome/browser/image_decoder.cc
|
| @@ -13,38 +13,115 @@
|
| using content::BrowserThread;
|
| using content::UtilityProcessHost;
|
|
|
| -ImageDecoder::ImageDecoder(Delegate* delegate,
|
| - const std::string& image_data,
|
| - ImageCodec image_codec)
|
| - : delegate_(delegate),
|
| - image_data_(image_data.begin(), image_data.end()),
|
| - image_codec_(image_codec),
|
| - task_runner_(NULL),
|
| - shrink_to_fit_(false) {
|
| +// static, Leaky to allow access from any thread.
|
| +base::LazyInstance<ImageDecoder>::Leaky image_decoder_instance_ =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +// static
|
| +ImageDecoder* ImageDecoder::GetInstance() {
|
| + return image_decoder_instance_.Pointer();
|
| }
|
|
|
| -ImageDecoder::ImageDecoder(Delegate* delegate,
|
| - const std::vector<char>& image_data,
|
| - ImageCodec image_codec)
|
| - : delegate_(delegate),
|
| - image_data_(image_data.begin(), image_data.end()),
|
| - image_codec_(image_codec),
|
| - task_runner_(NULL),
|
| - shrink_to_fit_(false) {
|
| +ImageDecoder::ImageDecoder() : image_decoder_impl_(new ImageDecoderImpl()) {
|
| }
|
|
|
| -ImageDecoder::~ImageDecoder() {}
|
| +ImageDecoder::~ImageDecoder() {
|
| +}
|
|
|
| -void ImageDecoder::Start(scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
| - task_runner_ = task_runner;
|
| +void ImageDecoder::Start(Delegate* delegate,
|
| + const std::string& image_data,
|
| + ImageCodec image_codec,
|
| + scoped_refptr<base::SequencedTaskRunner> task_runner,
|
| + bool shrink_to_fit) {
|
| + DCHECK(task_runner);
|
| + DCHECK(delegate);
|
| BrowserThread::PostTask(
|
| - BrowserThread::IO, FROM_HERE,
|
| - base::Bind(&ImageDecoder::DecodeImageInSandbox, this, image_data_));
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(
|
| + &ImageDecoder::ImageDecoderImpl::DecodeImageInSandbox,
|
| + image_decoder_impl_, delegate,
|
| + std::vector<unsigned char>(image_data.begin(), image_data.end()),
|
| + image_codec, task_runner, shrink_to_fit));
|
| +}
|
| +
|
| +// ImageDecoder::ImageDecoderImpl Methods
|
| +
|
| +ImageDecoder::ImageDecoderImpl::ImageDecoderImpl()
|
| + : delegate_id_counter_(0),
|
| + last_request_(base::TimeTicks::Now()),
|
| + batch_mode_started_(false) {
|
| +}
|
| +
|
| +ImageDecoder::ImageDecoderImpl::~ImageDecoderImpl() {
|
| +}
|
| +
|
| +ImageDecoder::ImageDecoderImpl::RequestInfo::RequestInfo(
|
| + Delegate* delegate,
|
| + scoped_refptr<base::SequencedTaskRunner> task_runner)
|
| + : delegate(delegate), task_runner(task_runner) {
|
| +}
|
| +
|
| +ImageDecoder::ImageDecoderImpl::RequestInfo::~RequestInfo() {
|
| +}
|
| +
|
| +void ImageDecoder::ImageDecoderImpl::DecodeImageInSandbox(
|
| + Delegate* delegate,
|
| + const std::vector<unsigned char>& image_data,
|
| + ImageCodec image_codec,
|
| + scoped_refptr<base::SequencedTaskRunner> task_runner,
|
| + bool shrink_to_fit) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + if (!batch_mode_started_) {
|
| + StartBatchMode();
|
| + }
|
| +
|
| + last_request_ = base::TimeTicks::Now();
|
| + RequestInfo* request_info = new RequestInfo(delegate, task_runner);
|
| + request_info_id_map_.AddWithID(request_info, delegate_id_counter_);
|
| +
|
| + if (image_codec == ROBUST_JPEG_CODEC) {
|
| + utility_process_host_->Send(
|
| + new ChromeUtilityMsg_RobustJPEGDecodeImage(image_data,
|
| + delegate_id_counter_));
|
| + } else {
|
| + utility_process_host_->Send(new ChromeUtilityMsg_DecodeImage(
|
| + image_data, shrink_to_fit, delegate_id_counter_));
|
| + }
|
| +
|
| + ++delegate_id_counter_;
|
| }
|
|
|
| -bool ImageDecoder::OnMessageReceived(const IPC::Message& message) {
|
| +void ImageDecoder::ImageDecoderImpl::StartBatchMode() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + utility_process_host_ =
|
| + UtilityProcessHost::Create(this, base::MessageLoopProxy::current().get())
|
| + ->AsWeakPtr();
|
| + utility_process_host_->StartBatchMode();
|
| + batch_mode_started_ = true;
|
| + batch_mode_timer_.Start(FROM_HERE,
|
| + kBatchModeTimeout,
|
| + this,
|
| + &ImageDecoder::ImageDecoderImpl::StopBatchMode);
|
| +}
|
| +
|
| +void ImageDecoder::ImageDecoderImpl::StopBatchMode() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + if ((base::TimeTicks::Now() - last_request_) < kBatchModeTimeout) {
|
| + return;
|
| + }
|
| +
|
| + if (utility_process_host_) {
|
| + utility_process_host_->EndBatchMode();
|
| + utility_process_host_.reset();
|
| + }
|
| + batch_mode_started_ = false;
|
| + batch_mode_timer_.Stop();
|
| +}
|
| +
|
| +bool ImageDecoder::ImageDecoderImpl::OnMessageReceived(
|
| + const IPC::Message& message) {
|
| bool handled = true;
|
| - IPC_BEGIN_MESSAGE_MAP(ImageDecoder, message)
|
| + IPC_BEGIN_MESSAGE_MAP(ImageDecoder::ImageDecoderImpl, message)
|
| IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_DecodeImage_Succeeded,
|
| OnDecodeImageSucceeded)
|
| IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_DecodeImage_Failed,
|
| @@ -54,28 +131,35 @@ bool ImageDecoder::OnMessageReceived(const IPC::Message& message) {
|
| return handled;
|
| }
|
|
|
| -void ImageDecoder::OnDecodeImageSucceeded(const SkBitmap& decoded_image) {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| - if (delegate_)
|
| - delegate_->OnImageDecoded(this, decoded_image);
|
| -}
|
| +void ImageDecoder::ImageDecoderImpl::OnDecodeImageSucceeded(
|
| + const SkBitmap& decoded_image,
|
| + int id) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + if (request_info_id_map_.Lookup(id)) {
|
| + RequestInfo* request_info = request_info_id_map_.Lookup(id);
|
| + request_info->task_runner->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&Delegate::OnImageDecoded,
|
| + base::Unretained(request_info->delegate),
|
| + decoded_image));
|
|
|
| -void ImageDecoder::OnDecodeImageFailed() {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| - if (delegate_)
|
| - delegate_->OnDecodeImageFailed(this);
|
| + request_info_id_map_.Remove(id);
|
| + delete request_info;
|
| + request_info = nullptr;
|
| + }
|
| }
|
|
|
| -void ImageDecoder::DecodeImageInSandbox(
|
| - const std::vector<unsigned char>& image_data) {
|
| +void ImageDecoder::ImageDecoderImpl::OnDecodeImageFailed(int id) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - UtilityProcessHost* utility_process_host;
|
| - utility_process_host = UtilityProcessHost::Create(this, task_runner_.get());
|
| - if (image_codec_ == ROBUST_JPEG_CODEC) {
|
| - utility_process_host->Send(
|
| - new ChromeUtilityMsg_RobustJPEGDecodeImage(image_data));
|
| - } else {
|
| - utility_process_host->Send(
|
| - new ChromeUtilityMsg_DecodeImage(image_data, shrink_to_fit_));
|
| + if (request_info_id_map_.Lookup(id)) {
|
| + RequestInfo* request_info = request_info_id_map_.Lookup(id);
|
| + request_info->task_runner->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&Delegate::OnDecodeImageFailed,
|
| + base::Unretained(request_info->delegate)));
|
| +
|
| + request_info_id_map_.Remove(id);
|
| + delete request_info;
|
| + request_info = nullptr;
|
| }
|
| }
|
|
|