Commit a2959bab authored by François Beaufort's avatar François Beaufort Committed by Commit Bot

[Shape Detection] Make Detected{Barcode,Face,Text} serializable.

This CL makes sure DetectedBarcode, DetectedFace, and DetectedText
results can be passed as a message in postMessage().

Change-Id: If8e50d359a321816222a3fabfa9bb02c4106154a
Reviewed-on: https://chromium-review.googlesource.com/c/1251549Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: François Beaufort <beaufort.francois@gmail.com>
Cr-Commit-Position: refs/heads/master@{#596128}
parent 5d546c9a
......@@ -38,7 +38,7 @@ namespace blink {
// Embedders may serialize this as out-of-band metadata along with
// collections of serialized data so that version skew can be detected
// before deserializing individual values.
const unsigned kSerializedScriptValueVersion = 18;
const unsigned kSerializedScriptValueVersion = 19;
} // namespace blink
......
......@@ -93,7 +93,15 @@ enum SerializationTag {
// namedCurve:uint32_t
kRTCCertificateTag = 'k', // length:uint32_t, pemPrivateKey:WebCoreString,
// pemCertificate:WebCoreString
kVersionTag = 0xFF // version:uint32_t -> Uses this as the file version.
kDetectedBarcodeTag =
'B', // raw_value:WebCoreString, bounding_box:DOMRectReadOnly,
// corner_points:Point2D[length] -> DetectedBarcode (ref)
kDetectedFaceTag =
'F', // raw_value:WebCoreString, bounding_box:DOMRectReadOnly,
// corner_points:Point2D[length] -> DetectedText (ref)
kDetectedTextTag = 't', // bounding_box:DOMRectReadOnly,
// landmarks:Landmark[length] -> DetectedFace (ref)
kVersionTag = 0xFF // version:uint32_t -> Uses this as the file version.
};
} // namespace blink
......
......@@ -88,6 +88,7 @@ class CORE_EXPORT SerializedScriptValue
// Version 17: Remove unnecessary byte swapping.
// Version 18: Add a list of key-value pairs for ImageBitmap and ImageData to
// support color space information, compression, etc.
// Version 19: Add DetectedBarcode, DetectedFace, and DetectedText support.
//
// The following versions cannot be used, in order to be able to
// deserialize version 0 SSVs. The class implementation has details.
......@@ -100,7 +101,7 @@ class CORE_EXPORT SerializedScriptValue
//
// Recent changes are routinely reverted in preparation for branch, and this
// has been the cause of at least one bug in the past.
static constexpr uint32_t kWireFormatVersion = 18;
static constexpr uint32_t kWireFormatVersion = 19;
// This enumeration specifies whether we're serializing a value for storage;
// e.g. when writing to IndexedDB. This corresponds to the forStorage flag of
......
......@@ -419,11 +419,7 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
return DOMRect::Create(x, y, width, height);
}
case kDOMRectReadOnlyTag: {
double x = 0, y = 0, width = 0, height = 0;
if (!ReadDouble(&x) || !ReadDouble(&y) || !ReadDouble(&width) ||
!ReadDouble(&height))
return nullptr;
return DOMRectReadOnly::Create(x, y, width, height);
return ReadDOMRectReadOnly();
}
case kDOMQuadTag: {
DOMPointInit pointInits[4];
......@@ -560,6 +556,14 @@ File* V8ScriptValueDeserializer::ReadFileIndex() {
blob_handle);
}
DOMRectReadOnly* V8ScriptValueDeserializer::ReadDOMRectReadOnly() {
double x = 0, y = 0, width = 0, height = 0;
if (!ReadDouble(&x) || !ReadDouble(&y) || !ReadDouble(&width) ||
!ReadDouble(&height))
return nullptr;
return DOMRectReadOnly::Create(x, y, width, height);
}
scoped_refptr<BlobDataHandle>
V8ScriptValueDeserializer::GetOrCreateBlobDataHandle(const String& uuid,
const String& type,
......
......@@ -17,6 +17,7 @@
namespace blink {
class DOMRectReadOnly;
class File;
class UnpackedSerializedScriptValue;
......@@ -65,6 +66,7 @@ class CORE_EXPORT V8ScriptValueDeserializer
return deserializer_.ReadRawBytes(size, data);
}
bool ReadUTF8String(String* string_out);
DOMRectReadOnly* ReadDOMRectReadOnly();
template <typename E>
bool ReadUint32Enum(E* value) {
......
......@@ -14,6 +14,9 @@
#include "third_party/blink/renderer/modules/crypto/crypto_key.h"
#include "third_party/blink/renderer/modules/filesystem/dom_file_system.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_certificate.h"
#include "third_party/blink/renderer/modules/shapedetection/detected_barcode.h"
#include "third_party/blink/renderer/modules/shapedetection/detected_face.h"
#include "third_party/blink/renderer/modules/shapedetection/detected_text.h"
namespace blink {
......@@ -57,6 +60,60 @@ ScriptWrappable* V8ScriptValueDeserializerForModules::ReadDOMObject(
return nullptr;
return new RTCCertificate(std::move(certificate));
}
case kDetectedBarcodeTag: {
String raw_value;
if (!ReadUTF8String(&raw_value))
return nullptr;
DOMRectReadOnly* bounding_box = ReadDOMRectReadOnly();
if (!bounding_box)
return nullptr;
uint32_t corner_points_length;
if (!ReadUint32(&corner_points_length))
return nullptr;
HeapVector<Point2D> corner_points;
for (uint32_t i = 0; i < corner_points_length; i++) {
Point2D point;
if (!ReadPoint2D(&point))
return nullptr;
corner_points.push_back(point);
}
return DetectedBarcode::Create(raw_value, bounding_box, corner_points);
}
case kDetectedFaceTag: {
DOMRectReadOnly* bounding_box = ReadDOMRectReadOnly();
if (!bounding_box)
return nullptr;
uint32_t landmarks_length;
if (!ReadUint32(&landmarks_length))
return nullptr;
HeapVector<Landmark> landmarks;
for (uint32_t i = 0; i < landmarks_length; i++) {
Landmark landmark;
if (!ReadLandmark(&landmark))
return nullptr;
landmarks.push_back(landmark);
}
return DetectedFace::Create(bounding_box, landmarks);
}
case kDetectedTextTag: {
String raw_value;
if (!ReadUTF8String(&raw_value))
return nullptr;
DOMRectReadOnly* bounding_box = ReadDOMRectReadOnly();
if (!bounding_box)
return nullptr;
uint32_t corner_points_length;
if (!ReadUint32(&corner_points_length))
return nullptr;
HeapVector<Point2D> corner_points;
for (uint32_t i = 0; i < corner_points_length; i++) {
Point2D point;
if (!ReadPoint2D(&point))
return nullptr;
corner_points.push_back(point);
}
return DetectedText::Create(raw_value, bounding_box, corner_points);
}
default:
break;
}
......@@ -291,4 +348,32 @@ CryptoKey* V8ScriptValueDeserializerForModules::ReadCryptoKey() {
return CryptoKey::Create(key);
}
bool V8ScriptValueDeserializerForModules::ReadLandmark(Landmark* landmark) {
String type;
if (!ReadUTF8String(&type))
return false;
uint32_t locations_length;
if (!ReadUint32(&locations_length))
return false;
HeapVector<Point2D> locations;
for (uint32_t i = 0; i < locations_length; i++) {
Point2D location;
if (!ReadPoint2D(&location))
return false;
locations.push_back(location);
}
landmark->setType(type);
landmark->setLocations(locations);
return true;
}
bool V8ScriptValueDeserializerForModules::ReadPoint2D(Point2D* point) {
double x = 0, y = 0;
if (!ReadDouble(&x) || !ReadDouble(&y))
return false;
point->setX(x);
point->setY(y);
return true;
}
} // namespace blink
......@@ -11,6 +11,8 @@
namespace blink {
class CryptoKey;
class Landmark;
class Point2D;
// Extends V8ScriptValueSerializer with support for modules/ types.
class MODULES_EXPORT V8ScriptValueDeserializerForModules final
......@@ -42,6 +44,8 @@ class MODULES_EXPORT V8ScriptValueDeserializerForModules final
return true;
}
CryptoKey* ReadCryptoKey();
bool ReadLandmark(Landmark* landmark);
bool ReadPoint2D(Point2D* point);
};
} // namespace blink
......
......@@ -8,8 +8,12 @@
#include "third_party/blink/public/platform/web_crypto.h"
#include "third_party/blink/public/platform/web_crypto_key.h"
#include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_rect_read_only.h"
#include "third_party/blink/renderer/bindings/modules/v8/serialization/web_crypto_sub_tags.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_crypto_key.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_detected_barcode.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_detected_face.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_detected_text.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_dom_file_system.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_certificate.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
......@@ -54,6 +58,61 @@ bool V8ScriptValueSerializerForModules::WriteDOMObject(
WriteUTF8String(pem.certificate().c_str());
return true;
}
if (wrapper_type_info == &V8DetectedBarcode::wrapperTypeInfo) {
DetectedBarcode* detected_barcode = wrappable->ToImpl<DetectedBarcode>();
WriteTag(kDetectedBarcodeTag);
WriteUTF8String(detected_barcode->rawValue());
DOMRectReadOnly* bounding_box = detected_barcode->boundingBox();
WriteDouble(bounding_box->x());
WriteDouble(bounding_box->y());
WriteDouble(bounding_box->width());
WriteDouble(bounding_box->height());
const HeapVector<Point2D>& corner_points = detected_barcode->cornerPoints();
WriteUint32(static_cast<uint32_t>(corner_points.size()));
for (const auto& corner_point : corner_points) {
WriteDouble(corner_point.x());
WriteDouble(corner_point.y());
}
return true;
}
if (wrapper_type_info == &V8DetectedFace::wrapperTypeInfo) {
DetectedFace* detected_face = wrappable->ToImpl<DetectedFace>();
WriteTag(kDetectedFaceTag);
DOMRectReadOnly* bounding_box = detected_face->boundingBox();
WriteDouble(bounding_box->x());
WriteDouble(bounding_box->y());
WriteDouble(bounding_box->width());
WriteDouble(bounding_box->height());
const HeapVector<Landmark>& landmarks = detected_face->landmarks();
WriteUint32(static_cast<uint32_t>(landmarks.size()));
for (const auto& landmark : landmarks) {
WriteUTF8String(landmark.type());
const HeapVector<Point2D>& locations = landmark.locations();
WriteUint32(static_cast<uint32_t>(locations.size()));
for (const auto& location : locations) {
WriteDouble(location.x());
WriteDouble(location.y());
}
}
return true;
}
if (wrapper_type_info == &V8DetectedText::wrapperTypeInfo) {
DetectedText* detected_text = wrappable->ToImpl<DetectedText>();
WriteTag(kDetectedTextTag);
WriteUTF8String(detected_text->rawValue());
DOMRectReadOnly* bounding_box = detected_text->boundingBox();
WriteDouble(bounding_box->x());
WriteDouble(bounding_box->y());
WriteDouble(bounding_box->width());
WriteDouble(bounding_box->height());
const HeapVector<Point2D>& corner_points = detected_text->cornerPoints();
WriteUint32(static_cast<uint32_t>(corner_points.size()));
for (const auto& corner_point : corner_points) {
WriteDouble(corner_point.x());
WriteDouble(corner_point.y());
}
return true;
}
return false;
}
......
......@@ -17,8 +17,12 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_rect_read_only.h"
#include "third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_crypto_key.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_detected_barcode.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_detected_face.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_detected_text.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_dom_file_system.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_certificate.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
......@@ -972,5 +976,83 @@ TEST(V8ScriptValueSerializerForModulesTest, DecodeInvalidDOMFileSystem) {
->IsNull());
}
TEST(V8ScriptValueSerializerForModulesTest, DecodeDetectedBarcode) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
scoped_refptr<SerializedScriptValue> input = SerializedValue(
{0xff, 0x13, 0xff, 0x0d, 0x5c, 'B', 0x04, 0x74, 0x65, 0x78, 0x74, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40});
v8::Local<v8::Value> result =
V8ScriptValueDeserializerForModules(script_state, input).Deserialize();
ASSERT_TRUE(V8DetectedBarcode::hasInstance(result, scope.GetIsolate()));
DetectedBarcode* detected_barcode =
V8DetectedBarcode::ToImpl(result.As<v8::Object>());
EXPECT_EQ("text", detected_barcode->rawValue());
DOMRectReadOnly* bounding_box = detected_barcode->boundingBox();
EXPECT_EQ(1, bounding_box->x());
EXPECT_EQ(2, bounding_box->y());
EXPECT_EQ(3, bounding_box->width());
EXPECT_EQ(4, bounding_box->height());
const HeapVector<Point2D>& corner_points = detected_barcode->cornerPoints();
EXPECT_EQ(1u, corner_points.size());
EXPECT_EQ(1, corner_points[0].x());
EXPECT_EQ(2, corner_points[0].y());
}
TEST(V8ScriptValueSerializerForModulesTest, DecodeDetectedFace) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
scoped_refptr<SerializedScriptValue> input = SerializedValue(
{0xff, 0x13, 0xff, 0x0d, 0x5c, 'F', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x40, 0x01, 0x03, 0x65, 0x79, 0x65, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40});
v8::Local<v8::Value> result =
V8ScriptValueDeserializerForModules(script_state, input).Deserialize();
ASSERT_TRUE(V8DetectedFace::hasInstance(result, scope.GetIsolate()));
DetectedFace* detected_face = V8DetectedFace::ToImpl(result.As<v8::Object>());
DOMRectReadOnly* bounding_box = detected_face->boundingBox();
EXPECT_EQ(1, bounding_box->x());
EXPECT_EQ(2, bounding_box->y());
EXPECT_EQ(3, bounding_box->width());
EXPECT_EQ(4, bounding_box->height());
const HeapVector<Landmark>& landmarks = detected_face->landmarks();
EXPECT_EQ(1u, landmarks.size());
EXPECT_EQ("eye", landmarks[0].type());
const HeapVector<Point2D>& locations = landmarks[0].locations();
EXPECT_EQ(1u, locations.size());
EXPECT_EQ(1, locations[0].x());
EXPECT_EQ(2, locations[0].y());
}
TEST(V8ScriptValueSerializerForModulesTest, DecodeDetectedText) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
scoped_refptr<SerializedScriptValue> input = SerializedValue(
{0xff, 0x13, 0xff, 0x0d, 0x5c, 't', 0x04, 0x74, 0x65, 0x78, 0x74, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40});
v8::Local<v8::Value> result =
V8ScriptValueDeserializerForModules(script_state, input).Deserialize();
ASSERT_TRUE(V8DetectedText::hasInstance(result, scope.GetIsolate()));
DetectedText* detected_text = V8DetectedText::ToImpl(result.As<v8::Object>());
EXPECT_EQ("text", detected_text->rawValue());
DOMRectReadOnly* bounding_box = detected_text->boundingBox();
EXPECT_EQ(1, bounding_box->x());
EXPECT_EQ(2, bounding_box->y());
EXPECT_EQ(3, bounding_box->width());
EXPECT_EQ(4, bounding_box->height());
const HeapVector<Point2D>& corner_points = detected_text->cornerPoints();
EXPECT_EQ(1u, corner_points.size());
EXPECT_EQ(1, corner_points[0].x());
EXPECT_EQ(2, corner_points[0].y());
}
} // namespace
} // 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