Commit b96de7c4 authored by jbroman's avatar jbroman Committed by Commit bot

Support OffscreenCanvas transfer with V8-based structured clone.

BUG=148757

Review-Url: https://codereview.chromium.org/2361253002
Cr-Commit-Position: refs/heads/master@{#420582}
parent 4a69c4cc
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "core/dom/MessagePort.h" #include "core/dom/MessagePort.h"
#include "core/frame/ImageBitmap.h" #include "core/frame/ImageBitmap.h"
#include "core/html/ImageData.h" #include "core/html/ImageData.h"
#include "core/offscreencanvas/OffscreenCanvas.h"
#include "platform/RuntimeEnabledFeatures.h" #include "platform/RuntimeEnabledFeatures.h"
#include "wtf/CheckedNumeric.h" #include "wtf/CheckedNumeric.h"
...@@ -149,6 +150,21 @@ ScriptWrappable* V8ScriptValueDeserializer::readDOMObject(SerializationTag tag) ...@@ -149,6 +150,21 @@ ScriptWrappable* V8ScriptValueDeserializer::readDOMObject(SerializationTag tag)
return nullptr; return nullptr;
return (*m_transferredMessagePorts)[index].get(); return (*m_transferredMessagePorts)[index].get();
} }
case OffscreenCanvasTransferTag: {
uint32_t width = 0, height = 0, canvasId = 0, clientId = 0, localId = 0;
uint64_t nonce = 0;
if (!readUint32(&width)
|| !readUint32(&height)
|| !readUint32(&canvasId)
|| !readUint32(&clientId)
|| !readUint32(&localId)
|| !readUint64(&nonce))
return nullptr;
OffscreenCanvas* canvas = OffscreenCanvas::create(width, height);
canvas->setAssociatedCanvasId(canvasId);
canvas->setSurfaceId(clientId, localId, nonce);
return canvas;
}
default: default:
break; break;
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "bindings/core/v8/V8ImageBitmap.h" #include "bindings/core/v8/V8ImageBitmap.h"
#include "bindings/core/v8/V8ImageData.h" #include "bindings/core/v8/V8ImageData.h"
#include "bindings/core/v8/V8MessagePort.h" #include "bindings/core/v8/V8MessagePort.h"
#include "bindings/core/v8/V8OffscreenCanvas.h"
#include "core/dom/DOMArrayBufferBase.h" #include "core/dom/DOMArrayBufferBase.h"
#include "core/html/ImageData.h" #include "core/html/ImageData.h"
#include "platform/RuntimeEnabledFeatures.h" #include "platform/RuntimeEnabledFeatures.h"
...@@ -103,6 +104,10 @@ void V8ScriptValueSerializer::finalizeTransfer(ExceptionState& exceptionState) ...@@ -103,6 +104,10 @@ void V8ScriptValueSerializer::finalizeTransfer(ExceptionState& exceptionState)
m_serializedScriptValue->transferImageBitmaps(isolate, m_transferables->imageBitmaps, exceptionState); m_serializedScriptValue->transferImageBitmaps(isolate, m_transferables->imageBitmaps, exceptionState);
if (exceptionState.hadException()) if (exceptionState.hadException())
return; return;
m_serializedScriptValue->transferOffscreenCanvas(isolate, m_transferables->offscreenCanvases, exceptionState);
if (exceptionState.hadException())
return;
} }
void V8ScriptValueSerializer::writeUTF8String(const String& string) void V8ScriptValueSerializer::writeUTF8String(const String& string)
...@@ -176,6 +181,32 @@ bool V8ScriptValueSerializer::writeDOMObject(ScriptWrappable* wrappable, Excepti ...@@ -176,6 +181,32 @@ bool V8ScriptValueSerializer::writeDOMObject(ScriptWrappable* wrappable, Excepti
writeUint32(static_cast<uint32_t>(index)); writeUint32(static_cast<uint32_t>(index));
return true; return true;
} }
if (wrapperTypeInfo == &V8OffscreenCanvas::wrapperTypeInfo) {
OffscreenCanvas* canvas = wrappable->toImpl<OffscreenCanvas>();
size_t index = kNotFound;
if (m_transferables)
index = m_transferables->offscreenCanvases.find(canvas);
if (index == kNotFound) {
exceptionState.throwDOMException(DataCloneError, "An OffscreenCanvas could not be cloned because it was not transferred.");
return false;
}
if (canvas->isNeutered()) {
exceptionState.throwDOMException(DataCloneError, "An OffscreenCanvas could not be cloned because it was detached.");
return false;
}
if (canvas->renderingContext()) {
exceptionState.throwDOMException(DataCloneError, "An OffscreenCanvas could not be cloned because it had a rendering context.");
return false;
}
writeTag(OffscreenCanvasTransferTag);
writeUint32(canvas->width());
writeUint32(canvas->height());
writeUint32(canvas->getAssociatedCanvasId());
writeUint32(canvas->clientId());
writeUint32(canvas->localId());
writeUint64(canvas->nonce());
return true;
}
return false; return false;
} }
......
...@@ -12,11 +12,13 @@ ...@@ -12,11 +12,13 @@
#include "bindings/core/v8/V8ImageBitmap.h" #include "bindings/core/v8/V8ImageBitmap.h"
#include "bindings/core/v8/V8ImageData.h" #include "bindings/core/v8/V8ImageData.h"
#include "bindings/core/v8/V8MessagePort.h" #include "bindings/core/v8/V8MessagePort.h"
#include "bindings/core/v8/V8OffscreenCanvas.h"
#include "bindings/core/v8/V8StringResource.h" #include "bindings/core/v8/V8StringResource.h"
#include "bindings/core/v8/serialization/V8ScriptValueDeserializer.h" #include "bindings/core/v8/serialization/V8ScriptValueDeserializer.h"
#include "core/dom/MessagePort.h" #include "core/dom/MessagePort.h"
#include "core/frame/LocalFrame.h" #include "core/frame/LocalFrame.h"
#include "core/html/ImageData.h" #include "core/html/ImageData.h"
#include "core/offscreencanvas/OffscreenCanvas.h"
#include "platform/RuntimeEnabledFeatures.h" #include "platform/RuntimeEnabledFeatures.h"
#include "platform/graphics/StaticBitmapImage.h" #include "platform/graphics/StaticBitmapImage.h"
#include "public/platform/WebMessagePortChannel.h" #include "public/platform/WebMessagePortChannel.h"
...@@ -463,5 +465,24 @@ TEST(V8ScriptValueSerializerTest, TransferImageBitmap) ...@@ -463,5 +465,24 @@ TEST(V8ScriptValueSerializerTest, TransferImageBitmap)
EXPECT_TRUE(imageBitmap->isNeutered()); EXPECT_TRUE(imageBitmap->isNeutered());
} }
TEST(V8ScriptValueSerializerTest, TransferOffscreenCanvas)
{
// More exhaustive tests in LayoutTests/. This is a sanity check.
ScopedEnableV8BasedStructuredClone enable;
V8TestingScope scope;
OffscreenCanvas* canvas = OffscreenCanvas::create(10, 7);
canvas->setAssociatedCanvasId(519);
v8::Local<v8::Value> wrapper = toV8(canvas, scope.getScriptState());
Transferables transferables;
transferables.offscreenCanvases.append(canvas);
v8::Local<v8::Value> result = roundTrip(wrapper, scope, nullptr, &transferables);
ASSERT_TRUE(V8OffscreenCanvas::hasInstance(result, scope.isolate()));
OffscreenCanvas* newCanvas = V8OffscreenCanvas::toImpl(result.As<v8::Object>());
EXPECT_EQ(IntSize(10, 7), newCanvas->size());
EXPECT_EQ(519, newCanvas->getAssociatedCanvasId());
EXPECT_TRUE(canvas->isNeutered());
EXPECT_FALSE(newCanvas->isNeutered());
}
} // namespace } // namespace
} // namespace blink } // namespace blink
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