Commit fc5d49e3 authored by junov's avatar junov Committed by Commit bot

Add OffscreenCanvas to ImageBitmapSource union typedef

This change makes it possible to call createImageBitmap with
an OffscreenCanvas object as an argument.  It also takes care
of propagating the origin-clean flag.

BUG=672571
TBR=haraken@chromium.org

Review-Url: https://codereview.chromium.org/2570613002
Cr-Commit-Position: refs/heads/master@{#438617}
parent b8ad7cfd
<!DOCTYPE html>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script>
async_test(t => {
var offscreen = new OffscreenCanvas(50, 50);
var ctx = offscreen.getContext('2d');
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 50, 50);
createImageBitmap(offscreen).then(image => {
var output = new OffscreenCanvas(50, 50);
var outCtx = offscreen.getContext('2d');
outCtx.drawImage(image, 0, 0);
var pixel = outCtx.getImageData(0, 0, 1, 1).data;
t.step(function() {
assert_array_equals(pixel, [0, 255, 0, 255]);
});
t.done();
});
}, "Call createImageBitmap on OffscreenCanvas with 2D context");
</script>
......@@ -5,10 +5,10 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
PASS Rejected as expected: undefined
PASS reason instanceof Error is true
TypeError: Failed to execute 'createImageBitmap' on 'Window': The provided value is not of type '(HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or Blob or ImageData or ImageBitmap)'
TypeError: Failed to execute 'createImageBitmap' on 'Window': The provided value is not of type '(HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or Blob or ImageData or ImageBitmap or OffscreenCanvas)'
PASS Rejected as expected: null
PASS reason instanceof Error is true
TypeError: Failed to execute 'createImageBitmap' on 'Window': The provided value is not of type '(HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or Blob or ImageData or ImageBitmap)'
TypeError: Failed to execute 'createImageBitmap' on 'Window': The provided value is not of type '(HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or Blob or ImageData or ImageBitmap or OffscreenCanvas)'
PASS Rejected as expected: empty image
PASS reason instanceof Error is true
InvalidStateError: Failed to execute 'createImageBitmap' on 'Window': No image can be retrieved from the provided element.
......
......@@ -6,7 +6,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
Starting worker: ./resources/canvas-createImageBitmap-invalid-args-in-workers.js
PASS [Worker] Rejected as expected: null
PASS [Worker] reason instanceof Error is true
[Worker] TypeError: Failed to execute 'createImageBitmap' on 'WorkerGlobalScope': The provided value is not of type '(HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or Blob or ImageData or ImageBitmap)'
[Worker] TypeError: Failed to execute 'createImageBitmap' on 'WorkerGlobalScope': The provided value is not of type '(HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or Blob or ImageData or ImageBitmap or OffscreenCanvas)'
PASS [Worker] Rejected as expected: invalid area
PASS [Worker] reason instanceof Error is true
[Worker] IndexSizeError: Failed to execute 'createImageBitmap' on 'WorkerGlobalScope': The source height provided is 0.
......
<!DOCTYPE html>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script>
function verifyOffscreenCanvasTaintedThenDone(offscreen, t) {
assert_throws("SecurityError", function() {
offscreen.getContext("2d").getImageData(0, 0, 1, 1);
}, "Check getImageData blocked.");
offscreen.convertToBlob().then(
function() {
assert_unreached("Promise returned by convertToBlob was resolved.");
t.done();
},
rejectionValue => {
assert_equals(rejectionValue.name, "SecurityError");
t.done();
}
);
}
async_test(t => {
var image = new Image();
// Notice that we don't set the image.crossOrigin property.
image.src = "http://localhost:8000/security/resources/abe-allow-star.php";
image.onload = function() {
var offscreen = new OffscreenCanvas(10, 10);
var ctx = offscreen.getContext('2d');
ctx.drawImage(image, 0, 0);
t.step(function() {
verifyOffscreenCanvasTaintedThenDone(offscreen, t);
});
}
}, "Verify that an OffscreenCanvas tainted with cross-origin content cannot be read.");
async_test(t => {
var image = new Image();
// Notice that we don't set the image.crossOrigin property.
image.src = "http://localhost:8000/security/resources/abe-allow-star.php";
image.onload = function() {
var offscreen = new OffscreenCanvas(10, 10);
var ctx = offscreen.getContext('2d');
ctx.drawImage(image, 0, 0);
createImageBitmap(offscreen).then(imageBitmap => {
var offscreen2 = new OffscreenCanvas(10, 10);
var ctx2 = offscreen2.getContext('2d');
ctx2.drawImage(imageBitmap, 0, 0);
t.step(function() {
verifyOffscreenCanvasTaintedThenDone(offscreen, t);
});
})
}
}, "Verify that createImageBitmap(OffscreenCanvas) propagates the origin-clean flag.");
</script>
......@@ -164,8 +164,8 @@ bindings_core_generated_union_type_files = [
"$bindings_core_v8_output_dir/FileOrUSVString.h",
"$bindings_core_v8_output_dir/HTMLElementOrLong.cpp",
"$bindings_core_v8_output_dir/HTMLElementOrLong.h",
"$bindings_core_v8_output_dir/HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmap.cpp",
"$bindings_core_v8_output_dir/HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmap.h",
"$bindings_core_v8_output_dir/HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas.cpp",
"$bindings_core_v8_output_dir/HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas.h",
"$bindings_core_v8_output_dir/HTMLOptionElementOrHTMLOptGroupElement.cpp",
"$bindings_core_v8_output_dir/HTMLOptionElementOrHTMLOptGroupElement.h",
"$bindings_core_v8_output_dir/HTMLScriptElementOrSVGScriptElement.cpp",
......
......@@ -7,6 +7,7 @@
#include "core/html/HTMLCanvasElement.h"
#include "core/html/HTMLVideoElement.h"
#include "core/html/ImageData.h"
#include "core/offscreencanvas/OffscreenCanvas.h"
#include "platform/graphics/skia/SkiaUtils.h"
#include "platform/image-decoders/ImageDecoder.h"
#include "third_party/skia/include/core/SkCanvas.h"
......@@ -687,6 +688,42 @@ ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas,
m_image->setPremultiplied(parsedOptions.premultiplyAlpha);
}
ImageBitmap::ImageBitmap(OffscreenCanvas* offscreenCanvas,
Optional<IntRect> cropRect,
const ImageBitmapOptions& options) {
SourceImageStatus status;
RefPtr<Image> input = offscreenCanvas->getSourceImageForCanvas(
&status, PreferNoAcceleration, SnapshotReasonCreateImageBitmap,
FloatSize(offscreenCanvas->size()));
if (status != NormalSourceImageStatus)
return;
ParsedOptions parsedOptions =
parseOptions(options, cropRect, IntSize(input->width(), input->height()));
if (dstBufferSizeHasOverflow(parsedOptions))
return;
bool isPremultiplyAlphaReverted = false;
if (!parsedOptions.premultiplyAlpha) {
parsedOptions.premultiplyAlpha = true;
isPremultiplyAlphaReverted = true;
}
m_image = cropImageAndApplyColorSpaceConversion(
input.get(), parsedOptions, PremultiplyAlpha,
ColorBehavior::transformToGlobalTarget());
if (!m_image)
return;
if (isPremultiplyAlphaReverted) {
parsedOptions.premultiplyAlpha = false;
m_image = StaticBitmapImage::create(premulSkImageToUnPremul(
m_image->imageForCurrentFrame(ColorBehavior::transformToGlobalTarget())
.get()));
}
if (!m_image)
return;
m_image->setOriginClean(offscreenCanvas->originClean());
m_image->setPremultiplied(parsedOptions.premultiplyAlpha);
}
ImageBitmap::ImageBitmap(const void* pixelData,
uint32_t width,
uint32_t height,
......@@ -946,6 +983,12 @@ ImageBitmap* ImageBitmap::create(HTMLCanvasElement* canvas,
return new ImageBitmap(canvas, cropRect, options);
}
ImageBitmap* ImageBitmap::create(OffscreenCanvas* offscreenCanvas,
Optional<IntRect> cropRect,
const ImageBitmapOptions& options) {
return new ImageBitmap(offscreenCanvas, cropRect, options);
}
ImageBitmap* ImageBitmap::create(ImageData* data,
Optional<IntRect> cropRect,
const ImageBitmapOptions& options) {
......
......@@ -25,6 +25,7 @@ class HTMLCanvasElement;
class HTMLVideoElement;
class ImageData;
class ImageDecoder;
class OffscreenCanvas;
enum AlphaDisposition {
PremultiplyAlpha,
......@@ -58,6 +59,9 @@ class CORE_EXPORT ImageBitmap final
static ImageBitmap* create(HTMLCanvasElement*,
Optional<IntRect>,
const ImageBitmapOptions& = ImageBitmapOptions());
static ImageBitmap* create(OffscreenCanvas*,
Optional<IntRect>,
const ImageBitmapOptions& = ImageBitmapOptions());
static ImageBitmap* create(ImageData*,
Optional<IntRect>,
const ImageBitmapOptions& = ImageBitmapOptions());
......@@ -144,6 +148,7 @@ class CORE_EXPORT ImageBitmap final
Document*,
const ImageBitmapOptions&);
ImageBitmap(HTMLCanvasElement*, Optional<IntRect>, const ImageBitmapOptions&);
ImageBitmap(OffscreenCanvas*, Optional<IntRect>, const ImageBitmapOptions&);
ImageBitmap(ImageData*, Optional<IntRect>, const ImageBitmapOptions&);
ImageBitmap(ImageBitmap*, Optional<IntRect>, const ImageBitmapOptions&);
ImageBitmap(PassRefPtr<StaticBitmapImage>);
......
......@@ -42,6 +42,7 @@
#include "core/html/HTMLVideoElement.h"
#include "core/html/ImageData.h"
#include "core/imagebitmap/ImageBitmapOptions.h"
#include "core/offscreencanvas/OffscreenCanvas.h"
#include "core/svg/graphics/SVGImage.h"
#include "core/workers/WorkerGlobalScope.h"
#include "platform/CrossThreadFunctional.h"
......@@ -93,6 +94,8 @@ static inline ImageBitmapSource* toImageBitmapSourceInternal(
return value.getAsImageData();
if (value.isImageBitmap())
return value.getAsImageBitmap();
if (value.isOffscreenCanvas())
return value.getAsOffscreenCanvas();
ASSERT_NOT_REACHED();
return nullptr;
}
......
......@@ -31,7 +31,7 @@
#ifndef ImageBitmapFactories_h
#define ImageBitmapFactories_h
#include "bindings/core/v8/HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmap.h"
#include "bindings/core/v8/HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas.h"
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "bindings/core/v8/ScriptState.h"
......@@ -55,7 +55,7 @@ class ImageBitmapSource;
class ImageBitmapOptions;
class WebTaskRunner;
typedef HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmap
typedef HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas
ImageBitmapSourceUnion;
class ImageBitmapFactories final
......
......@@ -35,7 +35,8 @@ typedef (HTMLImageElement or
HTMLCanvasElement or
Blob or
ImageData or
ImageBitmap) ImageBitmapSource;
ImageBitmap or
OffscreenCanvas) ImageBitmapSource;
[
LegacyTreatAsPartialInterface,
......
......@@ -6,6 +6,7 @@
#include "core/dom/ExceptionCode.h"
#include "core/fileapi/Blob.h"
#include "core/frame/ImageBitmap.h"
#include "core/html/ImageData.h"
#include "core/html/canvas/CanvasAsyncBlobCreator.h"
#include "core/html/canvas/CanvasContextCreationAttributes.h"
......@@ -111,6 +112,30 @@ PassRefPtr<Image> OffscreenCanvas::getSourceImageForCanvas(
return image.release();
}
IntSize OffscreenCanvas::bitmapSourceSize() const {
return m_size;
}
ScriptPromise OffscreenCanvas::createImageBitmap(
ScriptState* scriptState,
EventTarget&,
Optional<IntRect> cropRect,
const ImageBitmapOptions& options,
ExceptionState& exceptionState) {
if ((cropRect &&
!ImageBitmap::isSourceSizeValid(cropRect->width(), cropRect->height(),
exceptionState)) ||
!ImageBitmap::isSourceSizeValid(bitmapSourceSize().width(),
bitmapSourceSize().height(),
exceptionState))
return ScriptPromise();
if (!ImageBitmap::isResizeOptionValid(options, exceptionState))
return ScriptPromise();
return ImageBitmapSource::fulfillImageBitmap(
scriptState,
isPaintable() ? ImageBitmap::create(this, cropRect, options) : nullptr);
}
bool OffscreenCanvas::isOpaque() const {
if (!m_context)
return false;
......
......@@ -27,7 +27,8 @@ typedef OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2Renderin
OffscreenRenderingContext;
class CORE_EXPORT OffscreenCanvas final : public EventTargetWithInlineData,
public CanvasImageSource {
public CanvasImageSource,
public ImageBitmapSource {
DEFINE_WRAPPERTYPEINFO();
public:
......@@ -103,6 +104,14 @@ class CORE_EXPORT OffscreenCanvas final : public EventTargetWithInlineData,
return m_executionContext.get();
}
// ImageBitmapSource implementation
IntSize bitmapSourceSize() const final;
ScriptPromise createImageBitmap(ScriptState*,
EventTarget&,
Optional<IntRect>,
const ImageBitmapOptions&,
ExceptionState&) final;
// CanvasImageSource implementation
PassRefPtr<Image> getSourceImageForCanvas(SourceImageStatus*,
AccelerationHint,
......
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