Commit abcbc58f authored by mcasas's avatar mcasas Committed by Commit bot

Shape Detection: resolve with empty results if any input element's dimension is zero

This CL homogenises the behaviour of the ShapeDetector's
detect() in case of an input element with any zero dimension.
Assuming such input element pass the cross origin test and
its underlying pixel data can be retrieved, then if either width
or height is zero, detect() Promise is resolved with an empty
array.

LayoutTests are adapted/extended/cleaned up.

BUG=674306

Review-Url: https://codereview.chromium.org/2626743002
Cr-Commit-Position: refs/heads/master@{#442737}
parent 8a062852
...@@ -3,11 +3,12 @@ ...@@ -3,11 +3,12 @@
<script src=../../resources/testharnessreport.js></script> <script src=../../resources/testharnessreport.js></script>
<script> <script>
// This test verifies FaceDetector.detect() with an empty HTMLImageElement. // This test verifies *Detector.detect() returns an empty list when fed with
var createTestForEmptyInput = function(detectorName) { // an empty HTMLImageElement.
var createTestForEmptyInput = function(createDetector) {
async_test(function(t) { async_test(function(t) {
var image = new Image(); var image = new Image();
var detector = eval("new " + detectorName + "();"); var detector = createDetector();
var tryDetection = function() { var tryDetection = function() {
detector.detect(image) detector.detect(image)
.then(detectionResult => { .then(detectionResult => {
...@@ -25,9 +26,9 @@ var createTestForEmptyInput = function(detectorName) { ...@@ -25,9 +26,9 @@ var createTestForEmptyInput = function(detectorName) {
}; };
generate_tests(createTestForEmptyInput, [ generate_tests(createTestForEmptyInput, [
[ "Face", "FaceDetector" ], [ "Face", () => { return new FaceDetector(); } ],
[ "Barcode", "BarcodeDetector" ], [ "Barcode", () => { return new BarcodeDetector(); } ],
[ "Text", "TextDetector" ] [ "Text", () => { return new TextDetector(); } ]
]); ]);
</script> </script>
...@@ -5,43 +5,59 @@ ...@@ -5,43 +5,59 @@
// Returns a Promise that is resolve()d if detect() is rejected. Needs an input // Returns a Promise that is resolve()d if detect() is rejected. Needs an input
// |element| (e.g. an HTMLImageElement or HTMLVideoElement) and a |url| to load. // |element| (e.g. an HTMLImageElement or HTMLVideoElement) and a |url| to load.
function detectFaceOnElementAndExpectError(element, url) { function detectOnElementAndExpectError(createDetector, element, url) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
var tryFaceDetection = function() { var tryDetection = function() {
var faceDetector = new FaceDetector(); var detector = createDetector();
faceDetector.detect(element) detector.detect(element)
.then(faceDetectionResult => { .then(detectionResult => {
reject("Promise should have been rejected."); reject("Promise should have been rejected.");
}) })
.catch(error => { .catch(error => {
resolve(error); resolve(error);
}); });
}; };
element.onload = tryFaceDetection; element.onload = tryDetection;
element.onerror = tryFaceDetection; element.onerror = tryDetection;
element.src = url; element.src = url;
}); });
} };
// This test verifies that FaceDetector will reject an undecodable image. // This test verifies that a Detector will reject an undecodable image.
promise_test(function(t) { var createTestForBadImage = function(createDetector) {
var image = new Image(); promise_test(function(t) {
return detectFaceOnElementAndExpectError(image, var image = new Image();
"../../imported/wpt/images/broken.png") return detectOnElementAndExpectError(createDetector, image,
.then(function(error) { "../../imported/wpt/images/broken.png")
assert_equals(error.name, "InvalidStateError"); .then(function(error) {
assert_regexp_match(error.message, /Unable to decompress*/); assert_equals(error.name, "InvalidStateError");
}); assert_regexp_match(error.message, /Unable to decompress*/);
}, "FaceDetector should reject undecodable images with an InvalidStateError."); });
}, "Detector should reject undecodable images with an InvalidStateError.");
};
// This test verifies that FaceDetector will reject a broken video. generate_tests(createTestForBadImage, [
promise_test(function(t) { [ "Face", () => { return new FaceDetector(); } ],
var video = document.createElement('video'); [ "Barcode", () => { return new BarcodeDetector(); } ],
return detectFaceOnElementAndExpectError(video, "content/garbage.webm") [ "Text", () => { return new TextDetector(); } ]
.then(function(error) { ]);
assert_equals(error.name, "InvalidStateError");
});
}, "FaceDetector should reject undecodable videos with an InvalidStateError.");
// This test verifies that a Detector will reject a broken video.
var createTestForBadVideo = function(createDetector) {
promise_test(function(t) {
var video = document.createElement('video');
return detectOnElementAndExpectError(createDetector, video,
"content/garbage.webm")
.then(function(error) {
assert_equals(error.name, "InvalidStateError");
});
}, "Detector should reject undecodable videos with an InvalidStateError.");
};
generate_tests(createTestForBadVideo, [
[ "Face", () => { return new FaceDetector(); } ],
[ "Barcode", () => { return new BarcodeDetector(); } ],
[ "Text", () => { return new TextDetector(); } ]
]);
</script> </script>
...@@ -107,6 +107,10 @@ ScriptPromise ShapeDetector::detect(ScriptState* scriptState, ...@@ -107,6 +107,10 @@ ScriptPromise ShapeDetector::detect(ScriptState* scriptState,
DOMException::create(InvalidStateError, "Invalid element or state.")); DOMException::create(InvalidStateError, "Invalid element or state."));
return promise; return promise;
} }
if (size.isEmpty()) {
resolver->resolve(HeapVector<Member<DOMRect>>());
return promise;
}
SkPixmap pixmap; SkPixmap pixmap;
RefPtr<Uint8Array> pixelData; RefPtr<Uint8Array> pixelData;
...@@ -150,6 +154,11 @@ ScriptPromise ShapeDetector::detectShapesOnImageData( ...@@ -150,6 +154,11 @@ ScriptPromise ShapeDetector::detectShapesOnImageData(
ImageData* imageData) { ImageData* imageData) {
ScriptPromise promise = resolver->promise(); ScriptPromise promise = resolver->promise();
if (imageData->size().isZero()) {
resolver->resolve(HeapVector<Member<DOMRect>>());
return promise;
}
uint8_t* const data = imageData->data()->data(); uint8_t* const data = imageData->data()->data();
WTF::CheckedNumeric<int> allocationSize = imageData->size().area() * 4; WTF::CheckedNumeric<int> allocationSize = imageData->size().area() * 4;
...@@ -167,7 +176,6 @@ ScriptPromise ShapeDetector::detectShapesOnImageElement( ...@@ -167,7 +176,6 @@ ScriptPromise ShapeDetector::detectShapesOnImageElement(
const HTMLImageElement* img) { const HTMLImageElement* img) {
ScriptPromise promise = resolver->promise(); ScriptPromise promise = resolver->promise();
// TODO(mcasas): reconsider this resolve(), https://crbug.com/674306.
if (img->bitmapSourceSize().isZero()) { if (img->bitmapSourceSize().isZero()) {
resolver->resolve(HeapVector<Member<DOMRect>>()); resolver->resolve(HeapVector<Member<DOMRect>>());
return promise; return promise;
......
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