Commit 0081ca8b authored by Juanmi Huertas's avatar Juanmi Huertas Committed by Commit Bot

Ensuring the arrayBuffer is not deleted by copying it

Improving the DCHECKS to control that we are being on the correct thread
and copying the buffer if we are not coming from mainthread.

Bug: 986792
Change-Id: I45436b2a778c72586719f88aa579ad3e24cc48cf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1721790
Commit-Queue: Juanmi Huertas <juanmihd@chromium.org>
Reviewed-by: default avatarFernando Serboncini <fserb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#682931}
parent 39f98e85
...@@ -313,24 +313,27 @@ void ImageBitmapFactories::ImageBitmapLoader::DidFail(FileErrorCode) { ...@@ -313,24 +313,27 @@ void ImageBitmapFactories::ImageBitmapLoader::DidFail(FileErrorCode) {
void ImageBitmapFactories::ImageBitmapLoader::ScheduleAsyncImageBitmapDecoding( void ImageBitmapFactories::ImageBitmapLoader::ScheduleAsyncImageBitmapDecoding(
DOMArrayBuffer* array_buffer) { DOMArrayBuffer* array_buffer) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
scoped_refptr<base::SingleThreadTaskRunner> task_runner = scoped_refptr<base::SingleThreadTaskRunner> task_runner =
Thread::Current()->GetTaskRunner(); Thread::Current()->GetTaskRunner();
worker_pool::PostTask( worker_pool::PostTask(
FROM_HERE, FROM_HERE,
CrossThreadBindOnce( CrossThreadBindOnce(
&ImageBitmapFactories::ImageBitmapLoader::DecodeImageOnDecoderThread, &ImageBitmapFactories::ImageBitmapLoader::DecodeImageOnDecoderThread,
WrapCrossThreadPersistent(this), std::move(task_runner), WrapCrossThreadWeakPersistent(this), std::move(task_runner),
WrapCrossThreadPersistent(array_buffer), options_->premultiplyAlpha(), WrapCrossThreadPersistent(array_buffer), options_->premultiplyAlpha(),
options_->colorSpaceConversion())); options_->colorSpaceConversion(), IsMainThread()));
} }
void ImageBitmapFactories::ImageBitmapLoader::DecodeImageOnDecoderThread( void ImageBitmapFactories::ImageBitmapLoader::DecodeImageOnDecoderThread(
scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_refptr<base::SingleThreadTaskRunner> task_runner,
DOMArrayBuffer* array_buffer, DOMArrayBuffer* array_buffer,
const String& premultiply_alpha_option, const String& premultiply_alpha_option,
const String& color_space_conversion_option) { const String& color_space_conversion_option,
DCHECK(!IsMainThread()); bool scheduled_from_main_thread) {
#if DCHECK_IS_ON()
DCHECK(!sequence_checker_.CalledOnValidSequence());
#endif // DCHECK_IS_ON()
ImageDecoder::AlphaOption alpha_op = ImageDecoder::kAlphaPremultiplied; ImageDecoder::AlphaOption alpha_op = ImageDecoder::kAlphaPremultiplied;
if (premultiply_alpha_option == "none") if (premultiply_alpha_option == "none")
alpha_op = ImageDecoder::kAlphaNotPremultiplied; alpha_op = ImageDecoder::kAlphaNotPremultiplied;
...@@ -338,9 +341,21 @@ void ImageBitmapFactories::ImageBitmapLoader::DecodeImageOnDecoderThread( ...@@ -338,9 +341,21 @@ void ImageBitmapFactories::ImageBitmapLoader::DecodeImageOnDecoderThread(
if (color_space_conversion_option == "none") if (color_space_conversion_option == "none")
ignore_color_space = true; ignore_color_space = true;
const bool data_complete = true; const bool data_complete = true;
// As array buffer can be created from a worker thread, and that thread can be
// destroyed, there would be the possibility of a race condition here when
// creating the SkData without copy (just referencing it). To fix this issue
// we will be making it with copy if we don't come from the main thread, to
// ensure that the data will be safe in the current thread where the decoding
// is taking place.
// todo(crbug/989675) Evaluate if there is another way to fix this without
// copying the array.
std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create( std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
SegmentReader::CreateFromSkData(SkData::MakeWithoutCopy( SegmentReader::CreateFromSkData(
array_buffer->Data(), array_buffer->ByteLength())), scheduled_from_main_thread
? SkData::MakeWithoutCopy(array_buffer->Data(),
array_buffer->ByteLength())
: SkData::MakeWithCopy(array_buffer->Data(),
array_buffer->ByteLength())),
data_complete, alpha_op, ImageDecoder::kDefaultBitDepth, data_complete, alpha_op, ImageDecoder::kDefaultBitDepth,
ignore_color_space ? ColorBehavior::Ignore() : ColorBehavior::Tag()); ignore_color_space ? ColorBehavior::Ignore() : ColorBehavior::Tag());
sk_sp<SkImage> frame; sk_sp<SkImage> frame;
...@@ -351,11 +366,13 @@ void ImageBitmapFactories::ImageBitmapLoader::DecodeImageOnDecoderThread( ...@@ -351,11 +366,13 @@ void ImageBitmapFactories::ImageBitmapLoader::DecodeImageOnDecoderThread(
*task_runner, FROM_HERE, *task_runner, FROM_HERE,
CrossThreadBindOnce(&ImageBitmapFactories::ImageBitmapLoader:: CrossThreadBindOnce(&ImageBitmapFactories::ImageBitmapLoader::
ResolvePromiseOnOriginalThread, ResolvePromiseOnOriginalThread,
WrapCrossThreadPersistent(this), std::move(frame))); WrapCrossThreadWeakPersistent(this),
std::move(frame)));
} }
void ImageBitmapFactories::ImageBitmapLoader::ResolvePromiseOnOriginalThread( void ImageBitmapFactories::ImageBitmapLoader::ResolvePromiseOnOriginalThread(
sk_sp<SkImage> frame) { sk_sp<SkImage> frame) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!frame) { if (!frame) {
RejectPromise(kUndecodableImageBitmapRejectionReason); RejectPromise(kUndecodableImageBitmapRejectionReason);
return; return;
......
...@@ -129,6 +129,8 @@ class ImageBitmapFactories final ...@@ -129,6 +129,8 @@ class ImageBitmapFactories final
~ImageBitmapLoader() override; ~ImageBitmapLoader() override;
private: private:
SEQUENCE_CHECKER(sequence_checker_);
enum ImageBitmapRejectionReason { enum ImageBitmapRejectionReason {
kUndecodableImageBitmapRejectionReason, kUndecodableImageBitmapRejectionReason,
kAllocationFailureImageBitmapRejectionReason, kAllocationFailureImageBitmapRejectionReason,
...@@ -137,11 +139,11 @@ class ImageBitmapFactories final ...@@ -137,11 +139,11 @@ class ImageBitmapFactories final
void RejectPromise(ImageBitmapRejectionReason); void RejectPromise(ImageBitmapRejectionReason);
void ScheduleAsyncImageBitmapDecoding(DOMArrayBuffer*); void ScheduleAsyncImageBitmapDecoding(DOMArrayBuffer*);
void DecodeImageOnDecoderThread( void DecodeImageOnDecoderThread(scoped_refptr<base::SingleThreadTaskRunner>,
scoped_refptr<base::SingleThreadTaskRunner>, DOMArrayBuffer*,
DOMArrayBuffer*, const String& premultiply_alpha_option,
const String& premultiply_alpha_option, const String& color_space_conversion_option,
const String& color_space_conversion_option); bool scheduled_from_main_thread);
void ResolvePromiseOnOriginalThread(sk_sp<SkImage>); void ResolvePromiseOnOriginalThread(sk_sp<SkImage>);
// ContextLifecycleObserver // ContextLifecycleObserver
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment