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

Side by Side Diff: third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp

Issue 2359363005: Support Blob on the V8-based structured clone path. (Closed)
Patch Set: Created 4 years, 2 months 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "bindings/core/v8/serialization/V8ScriptValueSerializer.h" 5 #include "bindings/core/v8/serialization/V8ScriptValueSerializer.h"
6 6
7 #include "bindings/core/v8/ExceptionStatePlaceholder.h" 7 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
8 #include "bindings/core/v8/ScriptController.h" 8 #include "bindings/core/v8/ScriptController.h"
9 #include "bindings/core/v8/ScriptSourceCode.h" 9 #include "bindings/core/v8/ScriptSourceCode.h"
10 #include "bindings/core/v8/V8BindingForTesting.h" 10 #include "bindings/core/v8/V8BindingForTesting.h"
11 #include "bindings/core/v8/V8Blob.h"
11 #include "bindings/core/v8/V8DOMException.h" 12 #include "bindings/core/v8/V8DOMException.h"
12 #include "bindings/core/v8/V8ImageBitmap.h" 13 #include "bindings/core/v8/V8ImageBitmap.h"
13 #include "bindings/core/v8/V8ImageData.h" 14 #include "bindings/core/v8/V8ImageData.h"
14 #include "bindings/core/v8/V8MessagePort.h" 15 #include "bindings/core/v8/V8MessagePort.h"
15 #include "bindings/core/v8/V8OffscreenCanvas.h" 16 #include "bindings/core/v8/V8OffscreenCanvas.h"
16 #include "bindings/core/v8/V8StringResource.h" 17 #include "bindings/core/v8/V8StringResource.h"
17 #include "bindings/core/v8/serialization/V8ScriptValueDeserializer.h" 18 #include "bindings/core/v8/serialization/V8ScriptValueDeserializer.h"
18 #include "core/dom/MessagePort.h" 19 #include "core/dom/MessagePort.h"
20 #include "core/fileapi/Blob.h"
19 #include "core/frame/LocalFrame.h" 21 #include "core/frame/LocalFrame.h"
20 #include "core/html/ImageData.h" 22 #include "core/html/ImageData.h"
21 #include "core/offscreencanvas/OffscreenCanvas.h" 23 #include "core/offscreencanvas/OffscreenCanvas.h"
22 #include "platform/RuntimeEnabledFeatures.h" 24 #include "platform/RuntimeEnabledFeatures.h"
23 #include "platform/graphics/StaticBitmapImage.h" 25 #include "platform/graphics/StaticBitmapImage.h"
26 #include "public/platform/WebBlobInfo.h"
24 #include "public/platform/WebMessagePortChannel.h" 27 #include "public/platform/WebMessagePortChannel.h"
25 #include "public/platform/WebMessagePortChannelClient.h" 28 #include "public/platform/WebMessagePortChannelClient.h"
26 #include "testing/gmock/include/gmock/gmock.h" 29 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h" 30 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/skia/include/core/SkCanvas.h" 31 #include "third_party/skia/include/core/SkCanvas.h"
29 #include "third_party/skia/include/core/SkImage.h" 32 #include "third_party/skia/include/core/SkImage.h"
30 #include "third_party/skia/include/core/SkSurface.h" 33 #include "third_party/skia/include/core/SkSurface.h"
31 34
32 namespace blink { 35 namespace blink {
33 namespace { 36 namespace {
(...skipping 14 matching lines...) Expand all
48 }; 51 };
49 52
50 RefPtr<SerializedScriptValue> serializedValue(const Vector<uint8_t>& bytes) 53 RefPtr<SerializedScriptValue> serializedValue(const Vector<uint8_t>& bytes)
51 { 54 {
52 // TODO(jbroman): Fix this once SerializedScriptValue can take bytes without 55 // TODO(jbroman): Fix this once SerializedScriptValue can take bytes without
53 // endianness swapping. 56 // endianness swapping.
54 DCHECK_EQ(bytes.size() % 2, 0u); 57 DCHECK_EQ(bytes.size() % 2, 0u);
55 return SerializedScriptValue::create(String(reinterpret_cast<const UChar*>(& bytes[0]), bytes.size() / 2)); 58 return SerializedScriptValue::create(String(reinterpret_cast<const UChar*>(& bytes[0]), bytes.size() / 2));
56 } 59 }
57 60
58 v8::Local<v8::Value> roundTrip(v8::Local<v8::Value> value, V8TestingScope& scope , ExceptionState* overrideExceptionState = nullptr, Transferables* transferables = nullptr) 61 v8::Local<v8::Value> roundTrip(
62 v8::Local<v8::Value> value, V8TestingScope& scope,
63 ExceptionState* overrideExceptionState = nullptr,
64 Transferables* transferables = nullptr,
65 WebBlobInfoArray* blobInfo = nullptr)
59 { 66 {
60 RefPtr<ScriptState> scriptState = scope.getScriptState(); 67 RefPtr<ScriptState> scriptState = scope.getScriptState();
61 ExceptionState& exceptionState = overrideExceptionState ? *overrideException State : scope.getExceptionState(); 68 ExceptionState& exceptionState = overrideExceptionState ? *overrideException State : scope.getExceptionState();
62 69
63 // Extract message ports and disentangle them. 70 // Extract message ports and disentangle them.
64 std::unique_ptr<MessagePortChannelArray> channels; 71 std::unique_ptr<MessagePortChannelArray> channels;
65 if (transferables) { 72 if (transferables) {
66 channels = MessagePort::disentanglePorts(scope.getExecutionContext(), tr ansferables->messagePorts, exceptionState); 73 channels = MessagePort::disentanglePorts(scope.getExecutionContext(), tr ansferables->messagePorts, exceptionState);
67 if (exceptionState.hadException()) 74 if (exceptionState.hadException())
68 return v8::Local<v8::Value>(); 75 return v8::Local<v8::Value>();
69 } 76 }
70 77
71 RefPtr<SerializedScriptValue> serializedScriptValue = 78 V8ScriptValueSerializer serializer(scriptState);
72 V8ScriptValueSerializer(scriptState).serialize(value, transferables, exc eptionState); 79 serializer.setBlobInfoArray(blobInfo);
80 RefPtr<SerializedScriptValue> serializedScriptValue = serializer.serialize(v alue, transferables, exceptionState);
73 DCHECK_EQ(!serializedScriptValue, exceptionState.hadException()); 81 DCHECK_EQ(!serializedScriptValue, exceptionState.hadException());
74 if (!serializedScriptValue) 82 if (!serializedScriptValue)
75 return v8::Local<v8::Value>(); 83 return v8::Local<v8::Value>();
76 84
77 // If there are message ports, make new ones and entangle them. 85 // If there are message ports, make new ones and entangle them.
78 MessagePortArray* transferredMessagePorts = MessagePort::entanglePorts(*scop e.getExecutionContext(), std::move(channels)); 86 MessagePortArray* transferredMessagePorts = MessagePort::entanglePorts(*scop e.getExecutionContext(), std::move(channels));
79 87
80 V8ScriptValueDeserializer deserializer(scriptState, serializedScriptValue); 88 V8ScriptValueDeserializer deserializer(scriptState, serializedScriptValue);
81 deserializer.setTransferredMessagePorts(transferredMessagePorts); 89 deserializer.setTransferredMessagePorts(transferredMessagePorts);
90 deserializer.setBlobInfoArray(blobInfo);
82 return deserializer.deserialize(); 91 return deserializer.deserialize();
83 } 92 }
84 93
85 v8::Local<v8::Value> eval(const String& source, V8TestingScope& scope) 94 v8::Local<v8::Value> eval(const String& source, V8TestingScope& scope)
86 { 95 {
87 return scope.frame().script().executeScriptInMainWorldAndReturnValue(source) ; 96 return scope.frame().script().executeScriptInMainWorldAndReturnValue(source) ;
88 } 97 }
89 98
90 String toJSON(v8::Local<v8::Object> object, const V8TestingScope& scope) 99 String toJSON(v8::Local<v8::Object> object, const V8TestingScope& scope)
91 { 100 {
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 transferables.offscreenCanvases.append(canvas); 486 transferables.offscreenCanvases.append(canvas);
478 v8::Local<v8::Value> result = roundTrip(wrapper, scope, nullptr, &transferab les); 487 v8::Local<v8::Value> result = roundTrip(wrapper, scope, nullptr, &transferab les);
479 ASSERT_TRUE(V8OffscreenCanvas::hasInstance(result, scope.isolate())); 488 ASSERT_TRUE(V8OffscreenCanvas::hasInstance(result, scope.isolate()));
480 OffscreenCanvas* newCanvas = V8OffscreenCanvas::toImpl(result.As<v8::Object> ()); 489 OffscreenCanvas* newCanvas = V8OffscreenCanvas::toImpl(result.As<v8::Object> ());
481 EXPECT_EQ(IntSize(10, 7), newCanvas->size()); 490 EXPECT_EQ(IntSize(10, 7), newCanvas->size());
482 EXPECT_EQ(519, newCanvas->getAssociatedCanvasId()); 491 EXPECT_EQ(519, newCanvas->getAssociatedCanvasId());
483 EXPECT_TRUE(canvas->isNeutered()); 492 EXPECT_TRUE(canvas->isNeutered());
484 EXPECT_FALSE(newCanvas->isNeutered()); 493 EXPECT_FALSE(newCanvas->isNeutered());
485 } 494 }
486 495
496 TEST(V8ScriptValueSerializerTest, RoundTripBlob)
497 {
498 ScopedEnableV8BasedStructuredClone enable;
499 V8TestingScope scope;
500 const char kHelloWorld[] = "Hello world!";
501 Blob* blob = Blob::create(
502 reinterpret_cast<const unsigned char*>(&kHelloWorld),
503 sizeof(kHelloWorld), "text/plain");
504 String uuid = blob->uuid();
505 EXPECT_FALSE(uuid.isEmpty());
506 v8::Local<v8::Value> wrapper = toV8(blob, scope.getScriptState());
507 v8::Local<v8::Value> result = roundTrip(wrapper, scope);
508 ASSERT_TRUE(V8Blob::hasInstance(result, scope.isolate()));
509 Blob* newBlob = V8Blob::toImpl(result.As<v8::Object>());
510 EXPECT_EQ("text/plain", newBlob->type());
511 EXPECT_EQ(sizeof(kHelloWorld), newBlob->size());
512 EXPECT_EQ(uuid, newBlob->uuid());
513 }
514
515 TEST(V8ScriptValueSerializerTest, DecodeBlob)
516 {
517 ScopedEnableV8BasedStructuredClone enable;
518 V8TestingScope scope;
519 RefPtr<SerializedScriptValue> input = serializedValue({
520 0xff, 0x09, 0x3f, 0x00, 0x62, 0x24, 0x64, 0x38, 0x37, 0x35, 0x64, 0x66,
521 0x63, 0x32, 0x2d, 0x34, 0x35, 0x30, 0x35, 0x2d, 0x34, 0x36, 0x31, 0x62,
522 0x2d, 0x39, 0x38, 0x66, 0x65, 0x2d, 0x30, 0x63, 0x66, 0x36, 0x63, 0x63,
523 0x35, 0x65, 0x61, 0x66, 0x34, 0x34, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f,
524 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x0c});
525 v8::Local<v8::Value> result = V8ScriptValueDeserializer(scope.getScriptState (), input).deserialize();
526 ASSERT_TRUE(V8Blob::hasInstance(result, scope.isolate()));
527 Blob* newBlob = V8Blob::toImpl(result.As<v8::Object>());
528 EXPECT_EQ("d875dfc2-4505-461b-98fe-0cf6cc5eaf44", newBlob->uuid());
529 EXPECT_EQ("text/plain", newBlob->type());
530 EXPECT_EQ(12u, newBlob->size());
531 }
532
533 TEST(V8ScriptValueSerializerTest, RoundTripBlobIndex)
534 {
535 ScopedEnableV8BasedStructuredClone enable;
536 V8TestingScope scope;
537 const char kHelloWorld[] = "Hello world!";
538 Blob* blob = Blob::create(
539 reinterpret_cast<const unsigned char*>(&kHelloWorld),
540 sizeof(kHelloWorld), "text/plain");
541 String uuid = blob->uuid();
542 EXPECT_FALSE(uuid.isEmpty());
543 v8::Local<v8::Value> wrapper = toV8(blob, scope.getScriptState());
544 WebBlobInfoArray blobInfoArray;
545 v8::Local<v8::Value> result = roundTrip(wrapper, scope, nullptr, nullptr, &b lobInfoArray);
546
547 // As before, the resulting blob should be correct.
548 ASSERT_TRUE(V8Blob::hasInstance(result, scope.isolate()));
549 Blob* newBlob = V8Blob::toImpl(result.As<v8::Object>());
550 EXPECT_EQ("text/plain", newBlob->type());
551 EXPECT_EQ(sizeof(kHelloWorld), newBlob->size());
552 EXPECT_EQ(uuid, newBlob->uuid());
553
554 // The blob info array should also contain the blob details since it was
555 // serialized by index into this array.
556 ASSERT_EQ(1u, blobInfoArray.size());
557 const WebBlobInfo& info = blobInfoArray[0];
558 EXPECT_FALSE(info.isFile());
559 EXPECT_EQ(uuid, String(info.uuid()));
560 EXPECT_EQ("text/plain", info.type());
561 EXPECT_EQ(sizeof(kHelloWorld), static_cast<size_t>(info.size()));
562 }
563
564 TEST(V8ScriptValueSerializerTest, DecodeBlobIndex)
565 {
566 ScopedEnableV8BasedStructuredClone enable;
567 V8TestingScope scope;
568 RefPtr<SerializedScriptValue> input = serializedValue({
569 0xff, 0x09, 0x3f, 0x00, 0x69, 0x00});
570 WebBlobInfoArray blobInfoArray;
571 blobInfoArray.emplaceAppend("d875dfc2-4505-461b-98fe-0cf6cc5eaf44", "text/pl ain", 12);
572 V8ScriptValueDeserializer deserializer(scope.getScriptState(), input);
573 deserializer.setBlobInfoArray(&blobInfoArray);
574 v8::Local<v8::Value> result = deserializer.deserialize();
575 ASSERT_TRUE(V8Blob::hasInstance(result, scope.isolate()));
576 Blob* newBlob = V8Blob::toImpl(result.As<v8::Object>());
577 EXPECT_EQ("d875dfc2-4505-461b-98fe-0cf6cc5eaf44", newBlob->uuid());
578 EXPECT_EQ("text/plain", newBlob->type());
579 EXPECT_EQ(12u, newBlob->size());
580 }
581
582 TEST(V8ScriptValueSerializerTest, DecodeBlobIndexOutOfRange)
583 {
584 ScopedEnableV8BasedStructuredClone enable;
585 V8TestingScope scope;
586 RefPtr<SerializedScriptValue> input = serializedValue({
587 0xff, 0x09, 0x3f, 0x00, 0x69, 0x01});
588 {
589 V8ScriptValueDeserializer deserializer(scope.getScriptState(), input);
590 ASSERT_TRUE(deserializer.deserialize()->IsNull());
591 }
592 {
593 WebBlobInfoArray blobInfoArray;
594 blobInfoArray.emplaceAppend("d875dfc2-4505-461b-98fe-0cf6cc5eaf44", "tex t/plain", 12);
595 V8ScriptValueDeserializer deserializer(scope.getScriptState(), input);
596 deserializer.setBlobInfoArray(&blobInfoArray);
597 ASSERT_TRUE(deserializer.deserialize()->IsNull());
598 }
599 }
600
487 } // namespace 601 } // namespace
488 } // namespace blink 602 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698