summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcostan@gmail.com <costan@gmail.com@bbb929c8-8fbe-4397-9dbb-9b2b20218538>2013-11-15 13:24:42 +0000
committercostan@gmail.com <costan@gmail.com@bbb929c8-8fbe-4397-9dbb-9b2b20218538>2013-11-15 13:24:42 +0000
commit83dc38cd16e7cc8dec3d0f9224a8d4a2e453459f (patch)
treea4b52e7b1a6c1709431a6745dfb2371711311b4a
parent4a2309898062a594325174ab56c5018cf1be2c95 (diff)
downloadchromium_src-83dc38cd16e7cc8dec3d0f9224a8d4a2e453459f.zip
chromium_src-83dc38cd16e7cc8dec3d0f9224a8d4a2e453459f.tar.gz
chromium_src-83dc38cd16e7cc8dec3d0f9224a8d4a2e453459f.tar.bz2
Implement File constructor.
The feature is behind the FileConstructor RuntimeEnabledFeature with status=experimental. BUG=164933 Review URL: https://codereview.chromium.org/57483002 git-svn-id: svn://svn.chromium.org/blink/trunk@162116 bbb929c8-8fbe-4397-9dbb-9b2b20218538
-rw-r--r--third_party/WebKit/LayoutTests/fast/files/blob-constructor-expected.txt10
-rw-r--r--third_party/WebKit/LayoutTests/fast/files/blob-constructor.html126
-rw-r--r--third_party/WebKit/LayoutTests/fast/files/blob-parts-slice-test-expected.txt117
-rw-r--r--third_party/WebKit/LayoutTests/fast/files/blob-parts-slice-test.html55
-rw-r--r--third_party/WebKit/LayoutTests/fast/files/blob-slice-test-expected.txt143
-rw-r--r--third_party/WebKit/LayoutTests/fast/files/blob-slice-test.html114
-rw-r--r--third_party/WebKit/LayoutTests/fast/files/file-constructor-expected.txt100
-rw-r--r--third_party/WebKit/LayoutTests/fast/files/file-constructor.html146
-rw-r--r--third_party/WebKit/LayoutTests/fast/files/resources/blob-slice-common.js49
-rw-r--r--third_party/WebKit/LayoutTests/fast/files/script-tests/blob-constructor.js114
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt27
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async.html131
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt27
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync.html116
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-tests.js23
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-content-type.html6
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-formdata-expected.txt16
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-formdata.html89
-rw-r--r--third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-constructors-listing-dedicated-worker-expected.txt1
-rw-r--r--third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-constructors-listing-shared-worker-expected.txt1
-rw-r--r--third_party/WebKit/LayoutTests/webexposed/global-constructors-listing-dedicated-worker-expected.txt1
-rw-r--r--third_party/WebKit/LayoutTests/webexposed/global-constructors-listing-shared-worker-expected.txt1
-rw-r--r--third_party/WebKit/Source/bindings/bindings.gypi3
-rw-r--r--third_party/WebKit/Source/bindings/v8/V8BindingMacros.h11
-rw-r--r--third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp62
-rw-r--r--third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.cpp102
-rw-r--r--third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.h57
-rw-r--r--third_party/WebKit/Source/bindings/v8/custom/V8FileCustom.cpp86
-rw-r--r--third_party/WebKit/Source/core/fileapi/Blob.cpp4
-rw-r--r--third_party/WebKit/Source/core/fileapi/Blob.h3
-rw-r--r--third_party/WebKit/Source/core/fileapi/BlobBuilder.cpp21
-rw-r--r--third_party/WebKit/Source/core/fileapi/BlobBuilder.h10
-rw-r--r--third_party/WebKit/Source/core/fileapi/File.cpp15
-rw-r--r--third_party/WebKit/Source/core/fileapi/File.h16
-rw-r--r--third_party/WebKit/Source/core/fileapi/File.idl5
-rw-r--r--third_party/WebKit/Source/core/fileapi/FileReader.cpp2
-rw-r--r--third_party/WebKit/Source/core/html/FormDataList.cpp2
-rw-r--r--third_party/WebKit/Source/core/xml/XMLHttpRequest.cpp2
-rw-r--r--third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in1
39 files changed, 1362 insertions, 453 deletions
diff --git a/third_party/WebKit/LayoutTests/fast/files/blob-constructor-expected.txt b/third_party/WebKit/LayoutTests/fast/files/blob-constructor-expected.txt
index 35e7b05..8d65661 100644
--- a/third_party/WebKit/LayoutTests/fast/files/blob-constructor-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/files/blob-constructor-expected.txt
@@ -24,13 +24,13 @@ PASS (new Blob([document])).size is 21
PASS (new Blob([toStringingObj])).size is 8
PASS new Blob([throwingObj]) threw exception Error.
PASS (new Blob([], {unknownKey:'value'})) instanceof window.Blob is true
-PASS new Blob([], {endings:'illegalValue'}) threw exception TypeError: Failed to construct 'Blob': The 2nd argument's "endings" property must be either "transparent" or "native"..
+PASS new Blob([], {endings:'illegalValue'}) threw exception TypeError: Failed to construct 'Blob': The "endings" property must be either "transparent" or "native"..
PASS new Blob([], {endings:throwingObj}) threw exception Error.
PASS new Blob([], {type:throwingObj}) threw exception Error.
-PASS new Blob([], {type:'helloĆ®'}) threw exception SyntaxError: Failed to construct 'Blob': The 2nd argument's "type" property must consist of ASCII characters..
+PASS new Blob([], {type:'helloĆ®'}) threw exception SyntaxError: Failed to construct 'Blob': The "type" property must consist of ASCII characters..
PASS new Blob([], {endings:throwingObj1, type:throwingObj2}) threw exception Error 1.
PASS new Blob([], {type:throwingObj2, endings:throwingObj1}) threw exception Error 1.
-PASS new Blob([], {type:throwingObj2, endings:'illegal'}) threw exception TypeError: Failed to construct 'Blob': The 2nd argument's "endings" property must be either "transparent" or "native"..
+PASS new Blob([], {type:throwingObj2, endings:'illegal'}) threw exception TypeError: Failed to construct 'Blob': The "endings" property must be either "transparent" or "native"..
PASS (new Blob([], null)) instanceof window.Blob threw exception TypeError: Failed to construct 'Blob': The 2nd argument is not of type Object..
PASS (new Blob([], undefined)) instanceof window.Blob threw exception TypeError: Failed to construct 'Blob': The 2nd argument is not of type Object..
PASS (new Blob([], 123)) instanceof window.Blob threw exception TypeError: Failed to construct 'Blob': The 2nd argument is not of type Object..
@@ -43,7 +43,7 @@ PASS (new Blob([], function () {})) instanceof window.Blob is true
PASS (new Blob([], {type:'text/html'})).type is 'text/html'
PASS (new Blob([], {type:'text/html'})).size is 0
PASS (new Blob([], {type:'text/plain;charset=UTF-8'})).type is 'text/plain;charset=utf-8'
-FAIL window.Blob.length should be 2. Was 0.
+PASS window.Blob.length is 0
PASS new Blob([new DataView(new ArrayBuffer(100))]).size is 100
PASS new Blob([new Uint8Array(100)]).size is 100
PASS new Blob([new Uint8ClampedArray(100)]).size is 100
@@ -73,7 +73,7 @@ PASS new Blob({length: 0}).size is 0
PASS new Blob({length: 1, 0: 'string'}).size is 6
PASS new Blob({length: 2, 0: new Uint8Array(100), 1: new Int16Array(100)}).size is 300
PASS new Blob({length: 1, 0: 'string'}, {type: 'text/html'}).type is 'text/html'
-PASS new Blob({length: 0}, {endings:'illegal'}) threw exception TypeError: Failed to construct 'Blob': The 2nd argument's "endings" property must be either "transparent" or "native"..
+PASS new Blob({length: 0}, {endings:'illegal'}) threw exception TypeError: Failed to construct 'Blob': The "endings" property must be either "transparent" or "native"..
PASS new Blob(throwingSequence) threw exception Error: Misbehaving property.
PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/fast/files/blob-constructor.html b/third_party/WebKit/LayoutTests/fast/files/blob-constructor.html
index 08e22a9..f5c125f 100644
--- a/third_party/WebKit/LayoutTests/fast/files/blob-constructor.html
+++ b/third_party/WebKit/LayoutTests/fast/files/blob-constructor.html
@@ -1,9 +1,119 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
+<!DOCTYPE html>
+
<script src="../../resources/js-test.js"></script>
-</head>
-<body>
-<script src="script-tests/blob-constructor.js"></script>
-</body>
-</html>
+<script>
+description("Test the Blob constructor.");
+
+// Test the different ways you can construct a Blob.
+shouldBeTrue("(new Blob()) instanceof window.Blob");
+shouldBeTrue("(new Blob([])) instanceof window.Blob");
+shouldBeTrue("(new Blob(['hello'])) instanceof window.Blob");
+shouldBeTrue("(new Blob(['hello'], {})) instanceof window.Blob");
+shouldBeTrue("(new Blob(['hello'], {type:'text/html'})) instanceof window.Blob");
+shouldBeTrue("(new Blob(['hello'], {type:'text/html', endings:'native'})) instanceof window.Blob");
+shouldBeTrue("(new Blob(['hello'], {type:'text/html', endings:'transparent'})) instanceof window.Blob");
+
+// Test invalid blob parts.
+shouldThrow("new Blob('hello')", '"TypeError: Failed to construct \'Blob\': The 1st argument is neither an array, nor does it have indexed properties."');
+shouldThrow("new Blob(0)", '"TypeError: Failed to construct \'Blob\': The 1st argument is neither an array, nor does it have indexed properties."');
+
+// Test valid blob parts.
+shouldBeTrue("(new Blob([])) instanceof window.Blob");
+shouldBeTrue("(new Blob(['stringPrimitive'])) instanceof window.Blob");
+shouldBeTrue("(new Blob([String('stringObject')])) instanceof window.Blob");
+shouldBeTrue("(new Blob([new Blob])) instanceof window.Blob");
+shouldBeTrue("(new Blob([new Blob([new Blob])])) instanceof window.Blob");
+
+// Test some conversions to string in the parts array.
+shouldBe("(new Blob([12])).size", "2");
+shouldBe("(new Blob([[]])).size", "0"); // [].toString() is the empty string
+shouldBe("(new Blob([{}])).size", "15");; // {}.toString() is the string "[object Object]"
+shouldBe("(new Blob([document])).size", "21"); // document.toString() is the string "[object HTMLDocument]"
+
+var toStringingObj = { toString: function() { return "A string"; } };
+shouldBe("(new Blob([toStringingObj])).size", "8");
+
+var throwingObj = { toString: function() { throw "Error"; } };
+shouldThrow("new Blob([throwingObj])", "'Error'");
+
+// Test some invalid property bags.
+shouldBeTrue("(new Blob([], {unknownKey:'value'})) instanceof window.Blob"); // Ignore invalid keys
+shouldThrow("new Blob([], {endings:'illegalValue'})", "'TypeError: Failed to construct \\'Blob\\': The \"endings\" property must be either \"transparent\" or \"native\".'");
+shouldThrow("new Blob([], {endings:throwingObj})", "'Error'");
+shouldThrow("new Blob([], {type:throwingObj})", "'Error'");
+shouldThrow("new Blob([], {type:'hello\u00EE'})", "'SyntaxError: Failed to construct \\'Blob\\': The \"type\" property must consist of ASCII characters.'");
+
+// Test that order of property bag evaluation is lexigraphical
+var throwingObj1 = { toString: function() { throw "Error 1"; } };
+var throwingObj2 = { toString: function() { throw "Error 2"; } };
+shouldThrow("new Blob([], {endings:throwingObj1, type:throwingObj2})", "'Error 1'");
+shouldThrow("new Blob([], {type:throwingObj2, endings:throwingObj1})", "'Error 1'");
+shouldThrow("new Blob([], {type:throwingObj2, endings:'illegal'})", "'TypeError: Failed to construct \\'Blob\\': The \"endings\" property must be either \"transparent\" or \"native\".'");
+
+// Test various non-object literals being used as property bags.
+shouldThrow("(new Blob([], null)) instanceof window.Blob", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument is not of type Object.'");
+shouldThrow("(new Blob([], undefined)) instanceof window.Blob", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument is not of type Object.'");
+shouldThrow("(new Blob([], 123)) instanceof window.Blob", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument is not of type Object.'");
+shouldThrow("(new Blob([], 123.4)) instanceof window.Blob", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument is not of type Object.'");
+shouldThrow("(new Blob([], true)) instanceof window.Blob", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument is not of type Object.'");
+shouldThrow("(new Blob([], 'abc')) instanceof window.Blob", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument is not of type Object.'");
+shouldBeTrue("(new Blob([], [])) instanceof window.Blob");
+shouldBeTrue("(new Blob([], /abc/)) instanceof window.Blob");
+shouldBeTrue("(new Blob([], function () {})) instanceof window.Blob");
+
+// Test that the type/size is correctly added to the Blob
+shouldBe("(new Blob([], {type:'text/html'})).type", "'text/html'");
+shouldBe("(new Blob([], {type:'text/html'})).size", "0");
+shouldBe("(new Blob([], {type:'text/plain;charset=UTF-8'})).type", "'text/plain;charset=utf-8'");
+
+// Test the number of expected arguments in the Blob constructor.
+shouldBe("window.Blob.length", "0");
+
+// Test ArrayBufferView parameters.
+shouldBe("new Blob([new DataView(new ArrayBuffer(100))]).size", "100");
+shouldBe("new Blob([new Uint8Array(100)]).size", "100");
+shouldBe("new Blob([new Uint8ClampedArray(100)]).size", "100");
+shouldBe("new Blob([new Uint16Array(100)]).size", "200");
+shouldBe("new Blob([new Uint32Array(100)]).size", "400");
+shouldBe("new Blob([new Int8Array(100)]).size", "100");
+shouldBe("new Blob([new Int16Array(100)]).size", "200");
+shouldBe("new Blob([new Int32Array(100)]).size", "400");
+shouldBe("new Blob([new Float32Array(100)]).size", "400");
+shouldBe("new Blob([new Float64Array(100)]).size", "800");
+shouldBe("new Blob([new Float64Array(100), new Int32Array(100), new Uint8Array(100), new DataView(new ArrayBuffer(100))]).size", "1400");
+shouldBe("new Blob([new Blob([new Int32Array(100)]), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))]).size", "1000");
+
+// Test ArrayBuffer parameters.
+shouldBe("new Blob([(new DataView(new ArrayBuffer(100))).buffer]).size", "100");
+shouldBe("new Blob([(new Uint8Array(100)).buffer]).size", "100");
+shouldBe("new Blob([(new Uint8ClampedArray(100)).buffer]).size", "100");
+shouldBe("new Blob([(new Uint16Array(100)).buffer]).size", "200");
+shouldBe("new Blob([(new Uint32Array(100)).buffer]).size", "400");
+shouldBe("new Blob([(new Int8Array(100)).buffer]).size", "100");
+shouldBe("new Blob([(new Int16Array(100)).buffer]).size", "200");
+shouldBe("new Blob([(new Int32Array(100)).buffer]).size", "400");
+shouldBe("new Blob([(new Float32Array(100)).buffer]).size", "400");
+shouldBe("new Blob([(new Float64Array(100)).buffer]).size", "800");
+shouldBe("new Blob([(new Float64Array(100)).buffer, (new Int32Array(100)).buffer, (new Uint8Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer]).size", "1400");
+shouldBe("new Blob([new Blob([(new Int32Array(100)).buffer]), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer]).size", "1000");
+
+// Test passing blob parts in sequences.
+shouldBeTrue("new Blob({length: 0}) instanceof window.Blob");
+shouldBe("new Blob({length: 0}).size", "0");
+shouldBe("new Blob({length: 1, 0: 'string'}).size", "6");
+shouldBe("new Blob({length: 2, 0: new Uint8Array(100), 1: new Int16Array(100)}).size", "300");
+shouldBe("new Blob({length: 1, 0: 'string'}, {type: 'text/html'}).type", "'text/html'");
+shouldThrow("new Blob({length: 0}, {endings:'illegal'})", "'TypeError: Failed to construct \\'Blob\\': The \"endings\" property must be either \"transparent\" or \"native\".'");
+
+// Test passing blog parts in a sequence-like object that throws on property access.
+var throwingSequence = {length: 4, 0: 'hello', 3: 'world'};
+Object.defineProperty(throwingSequence, "1", {
+ get: function() { throw new Error("Misbehaving property"); },
+ enumerable: true, configurable: true
+});
+Object.defineProperty(throwingSequence, "2", {
+ get: function() { throw new Error("This should not be thrown"); },
+ enumerable: true, configurable: true
+});
+shouldThrow("new Blob(throwingSequence)", "'Error: Misbehaving property'");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/files/blob-parts-slice-test-expected.txt b/third_party/WebKit/LayoutTests/fast/files/blob-parts-slice-test-expected.txt
new file mode 100644
index 0000000..87727d8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/files/blob-parts-slice-test-expected.txt
@@ -0,0 +1,117 @@
+Test the Blob.slice() behavior for Blobs made of multiple parts.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Blob .slice(2, 3)
+PASS blobContents is "2"
+File .slice(2, 3)
+PASS fileContents is "2"
+Blob .slice(2, 12)
+PASS blobContents is "23456789"
+File .slice(2, 12)
+PASS fileContents is "23456789"
+Blob .slice(2, 2)
+PASS blobContents is ""
+File .slice(2, 2)
+PASS fileContents is ""
+Blob .slice(2, 1)
+PASS blobContents is ""
+File .slice(2, 1)
+PASS fileContents is ""
+Blob .slice(2, -12)
+PASS blobContents is ""
+File .slice(2, -12)
+PASS fileContents is ""
+Blob .slice(2, 2147483647)
+PASS blobContents is "23456789"
+File .slice(2, 2147483647)
+PASS fileContents is "23456789"
+Blob .slice(2, -2147483648)
+PASS blobContents is ""
+File .slice(2, -2147483648)
+PASS fileContents is ""
+Blob .slice(2, 9223372036854775000)
+PASS blobContents is "23456789"
+File .slice(2, 9223372036854775000)
+PASS fileContents is "23456789"
+Blob .slice(2, -9223372036854775000)
+PASS blobContents is ""
+File .slice(2, -9223372036854775000)
+PASS fileContents is ""
+Blob .slice(-2, -1)
+PASS blobContents is "8"
+File .slice(-2, -1)
+PASS fileContents is "8"
+Blob .slice(-2, -2)
+PASS blobContents is ""
+File .slice(-2, -2)
+PASS fileContents is ""
+Blob .slice(-2, -3)
+PASS blobContents is ""
+File .slice(-2, -3)
+PASS fileContents is ""
+Blob .slice(-2, -12)
+PASS blobContents is ""
+File .slice(-2, -12)
+PASS fileContents is ""
+Blob .slice(-2, 2147483647)
+PASS blobContents is "89"
+File .slice(-2, 2147483647)
+PASS fileContents is "89"
+Blob .slice(-2, -2147483648)
+PASS blobContents is ""
+File .slice(-2, -2147483648)
+PASS fileContents is ""
+Blob .slice(-2, 9223372036854775000)
+PASS blobContents is "89"
+File .slice(-2, 9223372036854775000)
+PASS fileContents is "89"
+Blob .slice(-2, -9223372036854775000)
+PASS blobContents is ""
+File .slice(-2, -9223372036854775000)
+PASS fileContents is ""
+Blob .slice(0)
+PASS blobContents is "0123456789"
+File .slice(0)
+PASS fileContents is "0123456789"
+Blob .slice(2)
+PASS blobContents is "23456789"
+File .slice(2)
+PASS fileContents is "23456789"
+Blob .slice(-2)
+PASS blobContents is "89"
+File .slice(-2)
+PASS fileContents is "89"
+Blob .slice(12)
+PASS blobContents is ""
+File .slice(12)
+PASS fileContents is ""
+Blob .slice(-12)
+PASS blobContents is "0123456789"
+File .slice(-12)
+PASS fileContents is "0123456789"
+Blob .slice(2147483647)
+PASS blobContents is ""
+File .slice(2147483647)
+PASS fileContents is ""
+Blob .slice(-2147483648)
+PASS blobContents is "0123456789"
+File .slice(-2147483648)
+PASS fileContents is "0123456789"
+Blob .slice(9223372036854775000)
+PASS blobContents is ""
+File .slice(9223372036854775000)
+PASS fileContents is ""
+Blob .slice(-9223372036854775000)
+PASS blobContents is "0123456789"
+File .slice(-9223372036854775000)
+PASS fileContents is "0123456789"
+Blob .slice()
+PASS blobContents is "0123456789"
+File .slice()
+PASS fileContents is "0123456789"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/files/blob-parts-slice-test.html b/third_party/WebKit/LayoutTests/fast/files/blob-parts-slice-test.html
new file mode 100644
index 0000000..9f2f47b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/files/blob-parts-slice-test.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/js-test.js"></script>
+<script src="resources/blob-slice-common.js"></script>
+<script>
+description("Test the Blob.slice() behavior for Blobs made of multiple parts.");
+
+var sliceTestCases = [
+ [2, 3, "2"],
+ [2, 12, "23456789"],
+ [2, 2, ""],
+ [2, 1, ""],
+ [2, -12, ""],
+ [2, 2147483647, "23456789"],
+ [2, -2147483648, ""],
+ [2, 9223372036854775000, "23456789"],
+ [2, -9223372036854775000, ""],
+ [-2, -1, "8"],
+ [-2, -2, ""],
+ [-2, -3, ""],
+ [-2, -12, ""],
+ [-2, 2147483647, "89"],
+ [-2, -2147483648, ""],
+ [-2, 9223372036854775000, "89"],
+ [-2, -9223372036854775000, ""],
+ [0, null, "0123456789"],
+ [2, null, "23456789"],
+ [-2, null, "89"],
+ [12, null, ""],
+ [-12, null, "0123456789"],
+ [2147483647, null, ""],
+ [-2147483648, null, "0123456789"],
+ [9223372036854775000, null, ""],
+ [-9223372036854775000, null, "0123456789"],
+ [null, null, "0123456789"],
+];
+
+function runTests()
+{
+ blob = new Blob(["0", new File(["12"], "slice-piece.txt"),
+ new Blob(["345"]), "6789"]);
+ file = new File(["0", new File(["12"], "slice-piece.txt"),
+ new Blob(["345"]), "6789"], "slice-text.txt");
+
+ runNextTest();
+}
+
+window.jsTestIsAsync = true;
+</script>
+</head>
+<body onload="runTests()">
+<pre id='console'></pre>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/files/blob-slice-test-expected.txt b/third_party/WebKit/LayoutTests/fast/files/blob-slice-test-expected.txt
index 0f274d3..2f12c4f 100644
--- a/third_party/WebKit/LayoutTests/fast/files/blob-slice-test-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/files/blob-slice-test-expected.txt
@@ -1,28 +1,117 @@
-Slicing from 2 to 3: 2
-Slicing from 2 to 12: 23456789
-Slicing from 2 to 2:
-Slicing from 2 to 1:
-Slicing from 2 to -12:
-Slicing from 2 to 2147483647: 23456789
-Slicing from 2 to -2147483648:
-Slicing from 2 to 9223372036854775000: 23456789
-Slicing from 2 to -9223372036854775000:
-Slicing from -2 to -1: 8
-Slicing from -2 to -2:
-Slicing from -2 to -3:
-Slicing from -2 to -12:
-Slicing from -2 to 2147483647: 89
-Slicing from -2 to -2147483648:
-Slicing from -2 to 9223372036854775000: 89
-Slicing from -2 to -9223372036854775000:
-Slicing from 0: 0123456789
-Slicing from 2: 23456789
-Slicing from -2: 89
-Slicing from 12:
-Slicing from -12: 0123456789
-Slicing from 2147483647:
-Slicing from -2147483648: 0123456789
-Slicing from 9223372036854775000:
-Slicing from -9223372036854775000: 0123456789
-Slicing without parameters: 0123456789
+Test Blob.slice().
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Blob .slice(2, 3)
+PASS blobContents is "2"
+File .slice(2, 3)
+PASS fileContents is "2"
+Blob .slice(2, 12)
+PASS blobContents is "23456789"
+File .slice(2, 12)
+PASS fileContents is "23456789"
+Blob .slice(2, 2)
+PASS blobContents is ""
+File .slice(2, 2)
+PASS fileContents is ""
+Blob .slice(2, 1)
+PASS blobContents is ""
+File .slice(2, 1)
+PASS fileContents is ""
+Blob .slice(2, -12)
+PASS blobContents is ""
+File .slice(2, -12)
+PASS fileContents is ""
+Blob .slice(2, 2147483647)
+PASS blobContents is "23456789"
+File .slice(2, 2147483647)
+PASS fileContents is "23456789"
+Blob .slice(2, -2147483648)
+PASS blobContents is ""
+File .slice(2, -2147483648)
+PASS fileContents is ""
+Blob .slice(2, 9223372036854775000)
+PASS blobContents is "23456789"
+File .slice(2, 9223372036854775000)
+PASS fileContents is "23456789"
+Blob .slice(2, -9223372036854775000)
+PASS blobContents is ""
+File .slice(2, -9223372036854775000)
+PASS fileContents is ""
+Blob .slice(-2, -1)
+PASS blobContents is "8"
+File .slice(-2, -1)
+PASS fileContents is "8"
+Blob .slice(-2, -2)
+PASS blobContents is ""
+File .slice(-2, -2)
+PASS fileContents is ""
+Blob .slice(-2, -3)
+PASS blobContents is ""
+File .slice(-2, -3)
+PASS fileContents is ""
+Blob .slice(-2, -12)
+PASS blobContents is ""
+File .slice(-2, -12)
+PASS fileContents is ""
+Blob .slice(-2, 2147483647)
+PASS blobContents is "89"
+File .slice(-2, 2147483647)
+PASS fileContents is "89"
+Blob .slice(-2, -2147483648)
+PASS blobContents is ""
+File .slice(-2, -2147483648)
+PASS fileContents is ""
+Blob .slice(-2, 9223372036854775000)
+PASS blobContents is "89"
+File .slice(-2, 9223372036854775000)
+PASS fileContents is "89"
+Blob .slice(-2, -9223372036854775000)
+PASS blobContents is ""
+File .slice(-2, -9223372036854775000)
+PASS fileContents is ""
+Blob .slice(0)
+PASS blobContents is "0123456789"
+File .slice(0)
+PASS fileContents is "0123456789"
+Blob .slice(2)
+PASS blobContents is "23456789"
+File .slice(2)
+PASS fileContents is "23456789"
+Blob .slice(-2)
+PASS blobContents is "89"
+File .slice(-2)
+PASS fileContents is "89"
+Blob .slice(12)
+PASS blobContents is ""
+File .slice(12)
+PASS fileContents is ""
+Blob .slice(-12)
+PASS blobContents is "0123456789"
+File .slice(-12)
+PASS fileContents is "0123456789"
+Blob .slice(2147483647)
+PASS blobContents is ""
+File .slice(2147483647)
+PASS fileContents is ""
+Blob .slice(-2147483648)
+PASS blobContents is "0123456789"
+File .slice(-2147483648)
+PASS fileContents is "0123456789"
+Blob .slice(9223372036854775000)
+PASS blobContents is ""
+File .slice(9223372036854775000)
+PASS fileContents is ""
+Blob .slice(-9223372036854775000)
+PASS blobContents is "0123456789"
+File .slice(-9223372036854775000)
+PASS fileContents is "0123456789"
+Blob .slice()
+PASS blobContents is "0123456789"
+File .slice()
+PASS fileContents is "0123456789"
+PASS successfullyParsed is true
+
+TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/files/blob-slice-test.html b/third_party/WebKit/LayoutTests/fast/files/blob-slice-test.html
index 06fec6e..e6a2989 100644
--- a/third_party/WebKit/LayoutTests/fast/files/blob-slice-test.html
+++ b/third_party/WebKit/LayoutTests/fast/files/blob-slice-test.html
@@ -1,96 +1,50 @@
<!DOCTYPE html>
<html>
<head>
+<script src="../../resources/js-test.js"></script>
+<script src="resources/blob-slice-common.js"></script>
<script>
-var blob;
-var testIndex = 0;
-var sliceParams = [
- [2, 3],
- [2, 12],
- [2, 2],
- [2, 1],
- [2, -12],
- [2, 2147483647],
- [2, -2147483648],
- [2, 9223372036854775000],
- [2, -9223372036854775000],
- [-2, -1],
- [-2, -2],
- [-2, -3],
- [-2, -12],
- [-2, 2147483647],
- [-2, -2147483648],
- [-2, 9223372036854775000],
- [-2, -9223372036854775000],
- [0],
- [2],
- [-2],
- [12],
- [-12],
- [2147483647],
- [-2147483648],
- [9223372036854775000],
- [-9223372036854775000],
- [],
-];
-
-function log(message)
-{
- document.getElementById('console').appendChild(document.createTextNode(message + "\n"));
-}
-
-function testSlicing(start, end)
-{
- var subBlob;
- var reader = new FileReader();
- var message = "Slicing ";
- if (start == undefined && end == undefined) {
- message += "without parameters";
- subBlob = blob.slice();
- } else if (end == undefined) {
- message += "from " + start;
- subBlob = blob.slice(start);
- } else {
- message += "from " + start + " to " + end;
- subBlob = blob.slice(start, end);
- }
- message += ": ";
- reader.onload = function(event) {
- log(message + event.target.result);
- runNextTest();
- };
- reader.onerror = function(event) {
- log(message + "error " + event.target.error.code);
- runNextTest();
- };
- reader.readAsText(subBlob);
-}
-
-function runNextTest()
-{
- if (testIndex >= sliceParams.length) {
- if (window.testRunner)
- testRunner.notifyDone();
- return;
- }
+description("Test Blob.slice().");
- var start = sliceParams[testIndex][0];
- var end = sliceParams[testIndex][1];
- testIndex++;
- testSlicing(start, end);
-}
+var sliceTestCases = [
+ [2, 3, "2"],
+ [2, 12, "23456789"],
+ [2, 2, ""],
+ [2, 1, ""],
+ [2, -12, ""],
+ [2, 2147483647, "23456789"],
+ [2, -2147483648, ""],
+ [2, 9223372036854775000, "23456789"],
+ [2, -9223372036854775000, ""],
+ [-2, -1, "8"],
+ [-2, -2, ""],
+ [-2, -3, ""],
+ [-2, -12, ""],
+ [-2, 2147483647, "89"],
+ [-2, -2147483648, ""],
+ [-2, 9223372036854775000, "89"],
+ [-2, -9223372036854775000, ""],
+ [0, null, "0123456789"],
+ [2, null, "23456789"],
+ [-2, null, "89"],
+ [12, null, ""],
+ [-12, null, "0123456789"],
+ [2147483647, null, ""],
+ [-2147483648, null, "0123456789"],
+ [9223372036854775000, null, ""],
+ [-9223372036854775000, null, "0123456789"],
+ [null, null, "0123456789"],
+];
function runTests()
{
blob = new Blob(["0123456789"]);
+ file = new File(["0123456789"], "slice-test.txt");
runNextTest();
}
-if (window.testRunner) {
- testRunner.dumpAsText();
- testRunner.waitUntilDone();
-}
+window.jsTestIsAsync = true;
</script>
</head>
<body onload="runTests()">
diff --git a/third_party/WebKit/LayoutTests/fast/files/file-constructor-expected.txt b/third_party/WebKit/LayoutTests/fast/files/file-constructor-expected.txt
new file mode 100644
index 0000000..2c4bf48
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/files/file-constructor-expected.txt
@@ -0,0 +1,100 @@
+Test the File constructor.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS (new File([], 'world.html')) instanceof window.File is true
+PASS (new File(['hello'], 'world.html')) instanceof window.File is true
+PASS (new File(['hello'], 'world.html', {})) instanceof window.File is true
+PASS (new File(['hello'], 'world.html', {type:'text/html'})) instanceof window.File is true
+PASS (new File(['hello'], 'world.html', {type:'text/html', endings:'native'})) instanceof window.File is true
+PASS (new File(['hello'], 'world.html', {type:'text/html', endings:'transparent'})) instanceof window.File is true
+PASS (new File([], 'world.html')) instanceof window.File is true
+PASS (new File()) threw exception TypeError: File constructor requires at least two arguments.
+PASS (new File([])) threw exception TypeError: File constructor requires at least two arguments.
+PASS (new File([], null)) instanceof window.File is true
+PASS (new File([], 1)) instanceof window.File is true
+PASS (new File([], '')) instanceof window.File is true
+PASS (new File([], document)) instanceof window.File is true
+PASS new File('hello', 'world.html') threw exception TypeError: Failed to construct 'File': The 1st argument is neither an array, nor does it have indexed properties..
+PASS new File(0, 'world.html') threw exception TypeError: Failed to construct 'File': The 1st argument is neither an array, nor does it have indexed properties..
+PASS (new File([], 'world.html')) instanceof window.File is true
+PASS (new File(['stringPrimitive'], 'world.html')) instanceof window.File is true
+PASS (new File([String('stringObject')], 'world.html')) instanceof window.File is true
+PASS (new File([new Blob], 'world.html')) instanceof window.File is true
+PASS (new File([new Blob([new Blob])], 'world.html')) instanceof window.File is true
+PASS (new Blob([new File([], 'world.txt')])) instanceof window.Blob is true
+PASS (new Blob([new Blob([new File([new Blob], 'world.txt')])])) instanceof window.Blob is true
+PASS (new File([new File([], 'world.txt')], 'world.html')) instanceof window.File is true
+PASS (new File([new Blob([new File([new Blob], 'world.txt')])], 'world.html')) instanceof window.File is true
+PASS (new File([12], 'world.html')).size is 2
+PASS (new File([[]], 'world.html')).size is 0
+PASS (new File([{}], 'world.html')).size is 15
+PASS (new File([document], 'world.html')).size is 21
+PASS (new File([toStringingObj], 'world.html')).size is 8
+PASS new File([throwingObj], 'world.html') threw exception Error.
+PASS (new File([], null)).name is 'null'
+PASS (new File([], 12)).name is '12'
+PASS (new File([], '')).name is ''
+PASS (new File([], {})).name is '[object Object]'
+PASS (new File([], document)).name is '[object HTMLDocument]'
+PASS (new File([], toStringingObj)).name is 'A string'
+PASS (new File([], throwingObj)).name threw exception Error.
+PASS (new File([], 'world.html', {unknownKey:'value'})) instanceof window.File is true
+PASS new File([], 'world.html', {endings:'illegalValue'}) threw exception TypeError: Failed to construct 'File': The "endings" property must be either "transparent" or "native"..
+PASS new File([], 'world.html', {endings:throwingObj}) threw exception Error.
+PASS new File([], 'world.html', {type:throwingObj}) threw exception Error.
+PASS new File([], 'world.html', {type:'helloĆ®'}) threw exception SyntaxError: Failed to construct 'File': The "type" property must consist of ASCII characters..
+PASS (new File([], 'world.html', null)) instanceof window.File threw exception TypeError: Failed to construct 'File': The 3rd argument is not of type Object..
+PASS (new File([], 'world.html', undefined)) instanceof window.File threw exception TypeError: Failed to construct 'File': The 3rd argument is not of type Object..
+PASS (new File([], 'world.html', 123)) instanceof window.File threw exception TypeError: Failed to construct 'File': The 3rd argument is not of type Object..
+PASS (new File([], 'world.html', 123.4)) instanceof window.File threw exception TypeError: Failed to construct 'File': The 3rd argument is not of type Object..
+PASS (new File([], 'world.html', true)) instanceof window.File threw exception TypeError: Failed to construct 'File': The 3rd argument is not of type Object..
+PASS (new File([], 'world.html', 'abc')) instanceof window.File threw exception TypeError: Failed to construct 'File': The 3rd argument is not of type Object..
+PASS (new File([], 'world.html', [])) instanceof window.File is true
+PASS (new File([], 'world.html', /abc/)) instanceof window.File is true
+PASS (new File([], 'world.html', function () {})) instanceof window.File is true
+PASS (new File([], 'world.html', {type:'text/html'})).name is 'world.html'
+PASS (new File([], 'world.html', {type:'text/html'})).type is 'text/html'
+PASS (new File([], 'world.html', {type:'text/html'})).size is 0
+PASS (new File([], 'world.html', {type:'text/plain;charset=UTF-8'})).type is 'text/plain;charset=utf-8'
+PASS window.File.length is 2
+PASS new File([new DataView(new ArrayBuffer(100))], 'world.html').size is 100
+PASS new File([new Uint8Array(100)], 'world.html').size is 100
+PASS new File([new Uint8ClampedArray(100)], 'world.html').size is 100
+PASS new File([new Uint16Array(100)], 'world.html').size is 200
+PASS new File([new Uint32Array(100)], 'world.html').size is 400
+PASS new File([new Int8Array(100)], 'world.html').size is 100
+PASS new File([new Int16Array(100)], 'world.html').size is 200
+PASS new File([new Int32Array(100)], 'world.html').size is 400
+PASS new File([new Float32Array(100)], 'world.html').size is 400
+PASS new File([new Float64Array(100)], 'world.html').size is 800
+PASS new File([new Float64Array(100), new Int32Array(100), new Uint8Array(100), new DataView(new ArrayBuffer(100))], 'world.html').size is 1400
+PASS new File([new Blob([new Int32Array(100)]), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))], 'world.html').size is 1000
+PASS new File([new Blob([new Int32Array(100)]), new File([new Uint16Array(100)], 'world.txt'), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))], 'world.html').size is 1200
+PASS new File([(new DataView(new ArrayBuffer(100))).buffer], 'world.html').size is 100
+PASS new File([(new Uint8Array(100)).buffer], 'world.html').size is 100
+PASS new File([(new Uint8ClampedArray(100)).buffer], 'world.html').size is 100
+PASS new File([(new Uint16Array(100)).buffer], 'world.html').size is 200
+PASS new File([(new Uint32Array(100)).buffer], 'world.html').size is 400
+PASS new File([(new Int8Array(100)).buffer], 'world.html').size is 100
+PASS new File([(new Int16Array(100)).buffer], 'world.html').size is 200
+PASS new File([(new Int32Array(100)).buffer], 'world.html').size is 400
+PASS new File([(new Float32Array(100)).buffer], 'world.html').size is 400
+PASS new File([(new Float64Array(100)).buffer], 'world.html').size is 800
+PASS new File([(new Float64Array(100)).buffer, (new Int32Array(100)).buffer, (new Uint8Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer], 'world.html').size is 1400
+PASS new File([new Blob([(new Int32Array(100)).buffer]), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer], 'world.html').size is 1000
+PASS new File([new Blob([(new Int32Array(100)).buffer]), new File([new Uint16Array(100).buffer], 'world.txt'), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer], 'world.html').size is 1200
+PASS new Blob([new Blob([new Int32Array(100)]), new File([new Uint16Array(100)], 'world.txt'), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))]).size is 1200
+PASS new Blob([new Blob([(new Int32Array(100)).buffer]), new File([new Uint16Array(100).buffer], 'world.txt'), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer]).size is 1200
+PASS new File({length: 0}, 'world.txt') instanceof window.File is true
+PASS new File({length: 0}, 'world.txt').size is 0
+PASS new File({length: 1, 0: 'string'}, 'world.txt').size is 6
+PASS new File({length: 2, 0: new Uint8Array(100), 1: new Int16Array(100)}, 'world.txt').size is 300
+PASS new File({length: 1, 0: 'string'}, 'world.txt', {type: 'text/html'}).type is 'text/html'
+PASS new File({length: 0}, 'world.txt', {endings:'illegal'}) threw exception TypeError: Failed to construct 'File': The "endings" property must be either "transparent" or "native"..
+PASS new File(throwingSequence, 'world.txt') threw exception Error: Misbehaving property.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/files/file-constructor.html b/third_party/WebKit/LayoutTests/fast/files/file-constructor.html
new file mode 100644
index 0000000..f615864
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/files/file-constructor.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+
+<script src="../../resources/js-test.js"></script>
+<script>
+description("Test the File constructor.");
+
+// Test the different ways you can construct a File.
+shouldBeTrue("(new File([], 'world.html')) instanceof window.File");
+shouldBeTrue("(new File(['hello'], 'world.html')) instanceof window.File");
+shouldBeTrue("(new File(['hello'], 'world.html', {})) instanceof window.File");
+shouldBeTrue("(new File(['hello'], 'world.html', {type:'text/html'})) instanceof window.File");
+shouldBeTrue("(new File(['hello'], 'world.html', {type:'text/html', endings:'native'})) instanceof window.File");
+shouldBeTrue("(new File(['hello'], 'world.html', {type:'text/html', endings:'transparent'})) instanceof window.File");
+
+// Test that File inherits from File.
+shouldBeTrue("(new File([], 'world.html')) instanceof window.File")
+
+// Verify that the file name argument is required.
+shouldThrow("(new File())", "'TypeError: File constructor requires at least two arguments'");
+shouldThrow("(new File([]))", "'TypeError: File constructor requires at least two arguments'");
+
+// Test valid file names.
+shouldBeTrue("(new File([], null)) instanceof window.File");
+shouldBeTrue("(new File([], 1)) instanceof window.File");
+shouldBeTrue("(new File([], '')) instanceof window.File");
+shouldBeTrue("(new File([], document)) instanceof window.File");
+
+// Test invalid blob parts.
+shouldThrow("new File('hello', 'world.html')", '"TypeError: Failed to construct \'File\': The 1st argument is neither an array, nor does it have indexed properties."');
+shouldThrow("new File(0, 'world.html')", '"TypeError: Failed to construct \'File\': The 1st argument is neither an array, nor does it have indexed properties."');
+
+// Test valid blob parts.
+shouldBeTrue("(new File([], 'world.html')) instanceof window.File");
+shouldBeTrue("(new File(['stringPrimitive'], 'world.html')) instanceof window.File");
+shouldBeTrue("(new File([String('stringObject')], 'world.html')) instanceof window.File");
+shouldBeTrue("(new File([new Blob], 'world.html')) instanceof window.File");
+shouldBeTrue("(new File([new Blob([new Blob])], 'world.html')) instanceof window.File");
+
+// Test File instances used as blob parts.
+shouldBeTrue("(new Blob([new File([], 'world.txt')])) instanceof window.Blob");
+shouldBeTrue("(new Blob([new Blob([new File([new Blob], 'world.txt')])])) instanceof window.Blob");
+shouldBeTrue("(new File([new File([], 'world.txt')], 'world.html')) instanceof window.File");
+shouldBeTrue("(new File([new Blob([new File([new Blob], 'world.txt')])], 'world.html')) instanceof window.File");
+
+// Test some conversions to string in the parts array.
+shouldBe("(new File([12], 'world.html')).size", "2");
+shouldBe("(new File([[]], 'world.html')).size", "0"); // [].toString() is the empty string
+shouldBe("(new File([{}], 'world.html')).size", "15");; // {}.toString() is the string "[object Object]"
+shouldBe("(new File([document], 'world.html')).size", "21"); // document.toString() is the string "[object HTMLDocument]"
+
+var toStringingObj = { toString: function() { return "A string"; } };
+shouldBe("(new File([toStringingObj], 'world.html')).size", "8");
+
+var throwingObj = { toString: function() { throw "Error"; } };
+shouldThrow("new File([throwingObj], 'world.html')", "'Error'");
+
+// Test some conversions to string in the file name.
+shouldBe("(new File([], null)).name", "'null'");
+shouldBe("(new File([], 12)).name", "'12'");
+shouldBe("(new File([], '')).name", "''");
+shouldBe("(new File([], {})).name", "'[object Object]'");
+shouldBe("(new File([], document)).name", "'[object HTMLDocument]'");
+shouldBe("(new File([], toStringingObj)).name", "'A string'");
+shouldThrow("(new File([], throwingObj)).name", "'Error'");
+
+// Test some invalid property bags.
+shouldBeTrue("(new File([], 'world.html', {unknownKey:'value'})) instanceof window.File"); // Ignore invalid keys
+shouldThrow("new File([], 'world.html', {endings:'illegalValue'})", "'TypeError: Failed to construct \\'File\\': The \"endings\" property must be either \"transparent\" or \"native\".'");
+shouldThrow("new File([], 'world.html', {endings:throwingObj})", "'Error'");
+shouldThrow("new File([], 'world.html', {type:throwingObj})", "'Error'");
+shouldThrow("new File([], 'world.html', {type:'hello\u00EE'})", "'SyntaxError: Failed to construct \\'File\\': The \"type\" property must consist of ASCII characters.'");
+
+// Test various non-object literals being used as property bags.
+shouldThrow("(new File([], 'world.html', null)) instanceof window.File", "'TypeError: Failed to construct \\'File\\': The 3rd argument is not of type Object.'");
+shouldThrow("(new File([], 'world.html', undefined)) instanceof window.File", "'TypeError: Failed to construct \\'File\\': The 3rd argument is not of type Object.'");
+shouldThrow("(new File([], 'world.html', 123)) instanceof window.File", "'TypeError: Failed to construct \\'File\\': The 3rd argument is not of type Object.'");
+shouldThrow("(new File([], 'world.html', 123.4)) instanceof window.File", "'TypeError: Failed to construct \\'File\\': The 3rd argument is not of type Object.'");
+shouldThrow("(new File([], 'world.html', true)) instanceof window.File", "'TypeError: Failed to construct \\'File\\': The 3rd argument is not of type Object.'");
+shouldThrow("(new File([], 'world.html', 'abc')) instanceof window.File", "'TypeError: Failed to construct \\'File\\': The 3rd argument is not of type Object.'");
+shouldBeTrue("(new File([], 'world.html', [])) instanceof window.File");
+shouldBeTrue("(new File([], 'world.html', /abc/)) instanceof window.File");
+shouldBeTrue("(new File([], 'world.html', function () {})) instanceof window.File");
+
+// Test that the name/type/size are correctly added to the File.
+shouldBe("(new File([], 'world.html', {type:'text/html'})).name", "'world.html'");
+shouldBe("(new File([], 'world.html', {type:'text/html'})).type", "'text/html'");
+shouldBe("(new File([], 'world.html', {type:'text/html'})).size", "0");
+shouldBe("(new File([], 'world.html', {type:'text/plain;charset=UTF-8'})).type", "'text/plain;charset=utf-8'");
+
+// Test the number of expected arguments in the File constructor.
+shouldBe("window.File.length", "2");
+
+// Test ArrayBufferView parameters.
+shouldBe("new File([new DataView(new ArrayBuffer(100))], 'world.html').size", "100");
+shouldBe("new File([new Uint8Array(100)], 'world.html').size", "100");
+shouldBe("new File([new Uint8ClampedArray(100)], 'world.html').size", "100");
+shouldBe("new File([new Uint16Array(100)], 'world.html').size", "200");
+shouldBe("new File([new Uint32Array(100)], 'world.html').size", "400");
+shouldBe("new File([new Int8Array(100)], 'world.html').size", "100");
+shouldBe("new File([new Int16Array(100)], 'world.html').size", "200");
+shouldBe("new File([new Int32Array(100)], 'world.html').size", "400");
+shouldBe("new File([new Float32Array(100)], 'world.html').size", "400");
+shouldBe("new File([new Float64Array(100)], 'world.html').size", "800");
+shouldBe("new File([new Float64Array(100), new Int32Array(100), new Uint8Array(100), new DataView(new ArrayBuffer(100))], 'world.html').size", "1400");
+shouldBe("new File([new Blob([new Int32Array(100)]), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))], 'world.html').size", "1000");
+shouldBe("new File([new Blob([new Int32Array(100)]), new File([new Uint16Array(100)], 'world.txt'), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))], 'world.html').size", "1200");
+
+// Test ArrayBuffer parameters.
+shouldBe("new File([(new DataView(new ArrayBuffer(100))).buffer], 'world.html').size", "100");
+shouldBe("new File([(new Uint8Array(100)).buffer], 'world.html').size", "100");
+shouldBe("new File([(new Uint8ClampedArray(100)).buffer], 'world.html').size", "100");
+shouldBe("new File([(new Uint16Array(100)).buffer], 'world.html').size", "200");
+shouldBe("new File([(new Uint32Array(100)).buffer], 'world.html').size", "400");
+shouldBe("new File([(new Int8Array(100)).buffer], 'world.html').size", "100");
+shouldBe("new File([(new Int16Array(100)).buffer], 'world.html').size", "200");
+shouldBe("new File([(new Int32Array(100)).buffer], 'world.html').size", "400");
+shouldBe("new File([(new Float32Array(100)).buffer], 'world.html').size", "400");
+shouldBe("new File([(new Float64Array(100)).buffer], 'world.html').size", "800");
+shouldBe("new File([(new Float64Array(100)).buffer, (new Int32Array(100)).buffer, (new Uint8Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer], 'world.html').size", "1400");
+shouldBe("new File([new Blob([(new Int32Array(100)).buffer]), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer], 'world.html').size", "1000");
+shouldBe("new File([new Blob([(new Int32Array(100)).buffer]), new File([new Uint16Array(100).buffer], 'world.txt'), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer], 'world.html').size", "1200");
+
+// Test building Blobs with ArrayBuffer / ArrayBufferView parts enclosed in files.
+shouldBe("new Blob([new Blob([new Int32Array(100)]), new File([new Uint16Array(100)], 'world.txt'), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))]).size", "1200");
+shouldBe("new Blob([new Blob([(new Int32Array(100)).buffer]), new File([new Uint16Array(100).buffer], 'world.txt'), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer]).size", "1200");
+
+// Test passing blob parts in sequences.
+shouldBeTrue("new File({length: 0}, 'world.txt') instanceof window.File");
+shouldBe("new File({length: 0}, 'world.txt').size", "0");
+shouldBe("new File({length: 1, 0: 'string'}, 'world.txt').size", "6");
+shouldBe("new File({length: 2, 0: new Uint8Array(100), 1: new Int16Array(100)}, 'world.txt').size", "300");
+shouldBe("new File({length: 1, 0: 'string'}, 'world.txt', {type: 'text/html'}).type", "'text/html'");
+shouldThrow("new File({length: 0}, 'world.txt', {endings:'illegal'})", "'TypeError: Failed to construct \\'File\\': The \"endings\" property must be either \"transparent\" or \"native\".'");
+
+// Test passing blog parts in a sequence-like object that throws on property access.
+var throwingSequence = {length: 4, 0: 'hello', 3: 'world'};
+Object.defineProperty(throwingSequence, "1", {
+ get: function() { throw new Error("Misbehaving property"); },
+ enumerable: true, configurable: true
+});
+Object.defineProperty(throwingSequence, "2", {
+ get: function() { throw new Error("This should not be thrown"); },
+ enumerable: true, configurable: true
+});
+shouldThrow("new File(throwingSequence, 'world.txt')", "'Error: Misbehaving property'");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/files/resources/blob-slice-common.js b/third_party/WebKit/LayoutTests/fast/files/resources/blob-slice-common.js
new file mode 100644
index 0000000..ba7a251
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/files/resources/blob-slice-common.js
@@ -0,0 +1,49 @@
+var blob, file; // Populated by runTests() in individual tests.
+var sliceParams = []; // Populated by individual tests.
+var testIndex = 0;
+
+function testSlicing(start, end, expectedResult, blob, doneCallback)
+{
+ var blobClass = blob.constructor.name;
+ var sliced;
+ var reader = new FileReader();
+ var message = ".slice";
+ if (start === null && end === null) {
+ message += "()";
+ sliced = blob.slice();
+ } else if (end == undefined) {
+ message += "(" + start + ")";
+ sliced = blob.slice(start);
+ } else {
+ message += "(" + start + ", " + end + ")";
+ sliced = blob.slice(start, end);
+ }
+ reader.onloadend = function(event) {
+ var error = event.target.error;
+ if (error) {
+ testFailed("File read error " + message + error);
+ doneCallback();
+ return;
+ }
+ var blobContentsVar = blobClass.toLowerCase() + "Contents";
+ window[blobContentsVar] = event.target.result;
+ shouldBeEqualToString(blobContentsVar, expectedResult);
+ doneCallback();
+ };
+ debug(blobClass + " " + message);
+ reader.readAsText(sliced);
+}
+
+function runNextTest()
+{
+ if (testIndex >= sliceTestCases.length) {
+ finishJSTest();
+ return;
+ }
+
+ var testCase = sliceTestCases[testIndex];
+ testIndex++;
+ testSlicing(testCase[0], testCase[1], testCase[2], blob, function() {
+ testSlicing(testCase[0], testCase[1], testCase[2], file, runNextTest);
+ });
+}
diff --git a/third_party/WebKit/LayoutTests/fast/files/script-tests/blob-constructor.js b/third_party/WebKit/LayoutTests/fast/files/script-tests/blob-constructor.js
deleted file mode 100644
index 77ad34a..0000000
--- a/third_party/WebKit/LayoutTests/fast/files/script-tests/blob-constructor.js
+++ /dev/null
@@ -1,114 +0,0 @@
-description("Test the Blob constructor.");
-
-// Test the diffrent ways you can construct a Blob.
-shouldBeTrue("(new Blob()) instanceof window.Blob");
-shouldBeTrue("(new Blob([])) instanceof window.Blob");
-shouldBeTrue("(new Blob(['hello'])) instanceof window.Blob");
-shouldBeTrue("(new Blob(['hello'], {})) instanceof window.Blob");
-shouldBeTrue("(new Blob(['hello'], {type:'text/html'})) instanceof window.Blob");
-shouldBeTrue("(new Blob(['hello'], {type:'text/html', endings:'native'})) instanceof window.Blob");
-shouldBeTrue("(new Blob(['hello'], {type:'text/html', endings:'transparent'})) instanceof window.Blob");
-
-// Test invalid blob parts
-shouldThrow("new Blob('hello')", '"TypeError: Failed to construct \'Blob\': The 1st argument is neither an array, nor does it have indexed properties."');
-shouldThrow("new Blob(0)", '"TypeError: Failed to construct \'Blob\': The 1st argument is neither an array, nor does it have indexed properties."');
-
-// Test valid blob parts.
-shouldBeTrue("(new Blob([])) instanceof window.Blob");
-shouldBeTrue("(new Blob(['stringPrimitive'])) instanceof window.Blob");
-shouldBeTrue("(new Blob([String('stringObject')])) instanceof window.Blob");
-shouldBeTrue("(new Blob([new Blob])) instanceof window.Blob");
-shouldBeTrue("(new Blob([new Blob([new Blob])])) instanceof window.Blob");
-
-// Test some conversions to string in the parts array.
-shouldBe("(new Blob([12])).size", "2");
-shouldBe("(new Blob([[]])).size", "0"); // [].toString() is the empty string
-shouldBe("(new Blob([{}])).size", "15");; // {}.toString() is the string "[object Object]"
-shouldBe("(new Blob([document])).size", "21"); // document.toString() is the string "[object HTMLDocument]"
-
-var toStringingObj = { toString: function() { return "A string"; } };
-shouldBe("(new Blob([toStringingObj])).size", "8");
-
-var throwingObj = { toString: function() { throw "Error"; } };
-shouldThrow("new Blob([throwingObj])", "'Error'");
-
-// Test some invalid property bags
-shouldBeTrue("(new Blob([], {unknownKey:'value'})) instanceof window.Blob"); // Ignore invalid keys
-shouldThrow("new Blob([], {endings:'illegalValue'})", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument\\'s \"endings\" property must be either \"transparent\" or \"native\".'");
-shouldThrow("new Blob([], {endings:throwingObj})", "'Error'");
-shouldThrow("new Blob([], {type:throwingObj})", "'Error'");
-shouldThrow("new Blob([], {type:'hello\u00EE'})", "'SyntaxError: Failed to construct \\'Blob\\': The 2nd argument\\'s \"type\" property must consist of ASCII characters.'");
-
-// Test that order of property bag evaluation is lexigraphical
-var throwingObj1 = { toString: function() { throw "Error 1"; } };
-var throwingObj2 = { toString: function() { throw "Error 2"; } };
-shouldThrow("new Blob([], {endings:throwingObj1, type:throwingObj2})", "'Error 1'");
-shouldThrow("new Blob([], {type:throwingObj2, endings:throwingObj1})", "'Error 1'");
-shouldThrow("new Blob([], {type:throwingObj2, endings:'illegal'})", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument\\'s \"endings\" property must be either \"transparent\" or \"native\".'");
-
-// Test various non-object literals being used as property bags
-shouldThrow("(new Blob([], null)) instanceof window.Blob", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument is not of type Object.'");
-shouldThrow("(new Blob([], undefined)) instanceof window.Blob", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument is not of type Object.'");
-shouldThrow("(new Blob([], 123)) instanceof window.Blob", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument is not of type Object.'");
-shouldThrow("(new Blob([], 123.4)) instanceof window.Blob", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument is not of type Object.'");
-shouldThrow("(new Blob([], true)) instanceof window.Blob", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument is not of type Object.'");
-shouldThrow("(new Blob([], 'abc')) instanceof window.Blob", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument is not of type Object.'");
-shouldBeTrue("(new Blob([], [])) instanceof window.Blob");
-shouldBeTrue("(new Blob([], /abc/)) instanceof window.Blob");
-shouldBeTrue("(new Blob([], function () {})) instanceof window.Blob");
-
-// Test that the type/size is correctly added to the Blob
-shouldBe("(new Blob([], {type:'text/html'})).type", "'text/html'");
-shouldBe("(new Blob([], {type:'text/html'})).size", "0");
-shouldBe("(new Blob([], {type:'text/plain;charset=UTF-8'})).type", "'text/plain;charset=utf-8'");
-
-// Odds and ends
-shouldBe("window.Blob.length", "2");
-
-// Test ArrayBufferView Parameters
-shouldBe("new Blob([new DataView(new ArrayBuffer(100))]).size", "100");
-shouldBe("new Blob([new Uint8Array(100)]).size", "100");
-shouldBe("new Blob([new Uint8ClampedArray(100)]).size", "100");
-shouldBe("new Blob([new Uint16Array(100)]).size", "200");
-shouldBe("new Blob([new Uint32Array(100)]).size", "400");
-shouldBe("new Blob([new Int8Array(100)]).size", "100");
-shouldBe("new Blob([new Int16Array(100)]).size", "200");
-shouldBe("new Blob([new Int32Array(100)]).size", "400");
-shouldBe("new Blob([new Float32Array(100)]).size", "400");
-shouldBe("new Blob([new Float64Array(100)]).size", "800");
-shouldBe("new Blob([new Float64Array(100), new Int32Array(100), new Uint8Array(100), new DataView(new ArrayBuffer(100))]).size", "1400");
-shouldBe("new Blob([new Blob([new Int32Array(100)]), new Uint8Array(100), new Float32Array(100), new DataView(new ArrayBuffer(100))]).size", "1000");
-
-// Test ArrayBuffer Parameters
-shouldBe("new Blob([(new DataView(new ArrayBuffer(100))).buffer]).size", "100");
-shouldBe("new Blob([(new Uint8Array(100)).buffer]).size", "100");
-shouldBe("new Blob([(new Uint8ClampedArray(100)).buffer]).size", "100");
-shouldBe("new Blob([(new Uint16Array(100)).buffer]).size", "200");
-shouldBe("new Blob([(new Uint32Array(100)).buffer]).size", "400");
-shouldBe("new Blob([(new Int8Array(100)).buffer]).size", "100");
-shouldBe("new Blob([(new Int16Array(100)).buffer]).size", "200");
-shouldBe("new Blob([(new Int32Array(100)).buffer]).size", "400");
-shouldBe("new Blob([(new Float32Array(100)).buffer]).size", "400");
-shouldBe("new Blob([(new Float64Array(100)).buffer]).size", "800");
-shouldBe("new Blob([(new Float64Array(100)).buffer, (new Int32Array(100)).buffer, (new Uint8Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer]).size", "1400");
-shouldBe("new Blob([new Blob([(new Int32Array(100)).buffer]), (new Uint8Array(100)).buffer, (new Float32Array(100)).buffer, (new DataView(new ArrayBuffer(100))).buffer]).size", "1000");
-
-// Test passing blob parts in sequences.
-shouldBeTrue("new Blob({length: 0}) instanceof window.Blob");
-shouldBe("new Blob({length: 0}).size", "0");
-shouldBe("new Blob({length: 1, 0: 'string'}).size", "6");
-shouldBe("new Blob({length: 2, 0: new Uint8Array(100), 1: new Int16Array(100)}).size", "300");
-shouldBe("new Blob({length: 1, 0: 'string'}, {type: 'text/html'}).type", "'text/html'");
-shouldThrow("new Blob({length: 0}, {endings:'illegal'})", "'TypeError: Failed to construct \\'Blob\\': The 2nd argument\\'s \"endings\" property must be either \"transparent\" or \"native\".'");
-
-// Test passing blog parts in a sequence-like object that throws on property access.
-var throwingSequence = {length: 4, 0: 'hello', 3: 'world'};
-Object.defineProperty(throwingSequence, "1", {
- get: function() { throw new Error("Misbehaving property"); },
- enumerable: true, configurable: true
-});
-Object.defineProperty(throwingSequence, "2", {
- get: function() { throw new Error("This should not be thrown"); },
- enumerable: true, configurable: true
-});
-shouldThrow("new Blob(throwingSequence)", "'Error: Misbehaving property'");
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt
index 062c72f..420e464 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt
@@ -4,19 +4,24 @@ Test verifies that content MIME type is set correctly when Blob is sent using XM
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-PASS expectedMimeType is "text/plain;charset=utf-8"
-PASS expectedMimeType is ""
-PASS expectedMimeType is ""
-PASS expectedMimeType is ""
-PASS expectedMimeType is ""
-PASS expectedMimeType is ""
-PASS expectedMimeType is ""
-PASS expectedMimeType is ""
-PASS expectedMimeType is "multipart/mixed;boundary=\"--blob-boundary\""
-PASS expectedMimeType is ""
+PASS postedMimeType is "text/plain;charset=utf-8"
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is "multipart/mixed;boundary=\"--blob-boundary\""
+PASS postedMimeType is ""
PASS Exception should be thrown.
PASS Cross-origin request without CORS headers should fail.
-PASS expectedMimeType is "text/plain;charset=utf-8"
+PASS postedMimeType is "text/plain;charset=utf-8"
+PASS postedMimeType is "text/plain;charset=utf-8"
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is "multipart/mixed;boundary=\"--blob-boundary\""
+PASS Exception should be thrown.
PASS successfullyParsed is true
TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async.html b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async.html
index 1315f3e5..1dc1fb05 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async.html
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-async.html
@@ -1,73 +1,78 @@
<!DOCTYPE html>
-<html>
-<head>
- <script src="/js-test-resources/js-test.js"></script>
-</head>
-<body>
- <script src="post-blob-content-type-tests.js"></script>
- <script type="text/javascript">
- description("Test verifies that content MIME type is set correctly " +
- "when Blob is sent using " +
- "<a href='http://www.w3.org/TR/XMLHttpRequest/#the-send-method'>XMLHttpRequest asynchronously.</a>");
- var xhr;
- var expectedMimeType;
- window.jsTestIsAsync = true;
- var asyncTestCase = 0;
+<script src="/js-test-resources/js-test.js"></script>
+<script src="post-blob-content-type-tests.js"></script>
+<script type="text/javascript">
+ description("Test verifies that content MIME type is set correctly " +
+ "when Blob is sent using " +
+ "<a href='http://www.w3.org/TR/XMLHttpRequest/#the-send-method'>XMLHttpRequest asynchronously.</a>");
- function runNextAsyncTest() {
- asyncTestCase++;
- runAsyncTests();
- }
+ var xhr;
+ var expectedMimeType;
+ window.jsTestIsAsync = true;
+ var asyncTestCase = 0;
- function reportResult(e) {
- if (xhr.status === 200) {
- expectedMimeType = JSON.parse(xhr.response)['content-type'] || "";
- shouldBeEqualToString("expectedMimeType", xhrBlobTestCases[asyncTestCase].expectedMime);
- } else if (xhr.status === 0 && xhrBlobTestCases[asyncTestCase].shouldThrow){
- testPassed("Cross-origin request without CORS headers should fail.");
- } else {
- testFailed("Unknown error");
- }
+ function runNextAsyncTest() {
+ asyncTestCase++;
+ runAsyncTests();
+ }
- runNextAsyncTest();
- }
+ function reportResult(e) {
+ var testCase = xhrBlobTestCases[asyncTestCase];
+ if (xhr.status === 200) {
+ postedMimeType = JSON.parse(xhr.response)['content-type'] || "";
+ shouldBeEqualToString("postedMimeType", testCase.expectedMime);
+ } else if (xhr.status === 0 && testCase.shouldThrow){
+ testPassed("Cross-origin request without CORS headers should fail.");
+ } else {
+ testFailed("Unknown error");
+ }
- function runAsyncTests() {
- if (asyncTestCase >= xhrBlobTestCases.length) {
- finishJSTest();
- return;
- } else {
- var mime = xhrBlobTestCases[asyncTestCase].mime;
- var url = xhrBlobTestCases[asyncTestCase].url !== undefined ? xhrBlobTestCases[asyncTestCase].url + xhrBlobTestUrl : xhrBlobTestUrl;
- url += xhrBlobTestCases[asyncTestCase].allowOrigin || "";
- if (xhrBlobTestCases[asyncTestCase].shouldThrow !== undefined) {
- try {
- testBlobContentTypeAsync(url, mime);
- } catch (e) {
- testPassed("Exception should be thrown.")
- runNextAsyncTest();
- }
- } else
- testBlobContentTypeAsync(url, mime);
- }
- }
+ runNextAsyncTest();
+ }
- function testBlobContentTypeAsync(url, mimeType) {
- var blob;
- if (mimeType !== "")
- blob = new Blob(["Test content"], {type: mimeType});
- else
- blob = new Blob(["Test content"]);
+ function runAsyncTests() {
+ if (asyncTestCase >= xhrBlobTestCases.length) {
+ finishJSTest();
+ return;
+ } else {
+ var testCase = xhrBlobTestCases[asyncTestCase];
+ var mime = testCase.mime;
+ var file = testCase.file;
+ var url = testCase.url !== undefined ? testCase.url + xhrBlobTestUrl : xhrBlobTestUrl;
+ url += testCase.allowOrigin || "";
+ if (testCase.shouldThrow !== undefined) {
+ try {
+ testBlobContentTypeAsync(url, mime, file);
+ } catch (e) {
+ testPassed("Exception should be thrown.")
+ runNextAsyncTest();
+ }
+ } else
+ testBlobContentTypeAsync(url, mime);
+ }
+ }
- xhr = new XMLHttpRequest();
- xhr.onloadend = reportResult;
- xhr.open("POST", url, true);
- xhr.send(blob);
- }
+ function testBlobContentTypeAsync(url, mimeType, fileName) {
+ var blob;
+ if (fileName) {
+ if (mimeType !== "")
+ blob = new File(["Test content"], fileName, {type: mimeType});
+ else
+ blob = new File(["Test content"], fileName);
+ } else {
+ if (mimeType !== "")
+ blob = new Blob(["Test content"], {type: mimeType});
+ else
+ blob = new Blob(["Test content"]);
+ }
- runAsyncTests();
+ xhr = new XMLHttpRequest();
+ xhr.onloadend = reportResult;
+ xhr.open("POST", url, true);
+ xhr.send(blob);
+ }
- </script>
-</body>
-</html>
+ runAsyncTests();
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt
index 853476f..90920def 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt
@@ -4,19 +4,24 @@ Test verifies that content MIME type is set correctly when Blob is sent using XM
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-PASS expectedMimeType is "text/plain;charset=utf-8"
-PASS expectedMimeType is ""
-PASS expectedMimeType is ""
-PASS expectedMimeType is ""
-PASS expectedMimeType is ""
-PASS expectedMimeType is ""
-PASS expectedMimeType is ""
-PASS expectedMimeType is ""
-PASS expectedMimeType is "multipart/mixed;boundary=\"--blob-boundary\""
-PASS expectedMimeType is ""
+PASS postedMimeType is "text/plain;charset=utf-8"
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is "multipart/mixed;boundary=\"--blob-boundary\""
+PASS postedMimeType is ""
PASS Exception should be thrown.
PASS Exception should be thrown.
-PASS expectedMimeType is "text/plain;charset=utf-8"
+PASS postedMimeType is "text/plain;charset=utf-8"
+PASS postedMimeType is "text/plain;charset=utf-8"
+PASS postedMimeType is ""
+PASS postedMimeType is ""
+PASS postedMimeType is "multipart/mixed;boundary=\"--blob-boundary\""
+PASS Exception should be thrown.
PASS successfullyParsed is true
TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync.html b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync.html
index 4a78bd6..e111c94 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync.html
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-sync.html
@@ -1,57 +1,61 @@
<!DOCTYPE html>
-<html>
-<head>
- <script src="/js-test-resources/js-test.js"></script>
-</head>
-<body>
- <script src="post-blob-content-type-tests.js"></script>
- <script type="text/javascript">
- description("Test verifies that content MIME type is set correctly " +
- "when Blob is sent using " +
- "<a href='http://www.w3.org/TR/XMLHttpRequest/#the-send-method'>XMLHttpRequest synchronously.</a>");
-
- var xhr;
- var expectedMimeType;
-
- function runSyncTests() {
- var testCount = xhrBlobTestCases.length;
- for (var i = 0; i < testCount; i++) {
- var mime = xhrBlobTestCases[i].mime;
- var expectedMime = xhrBlobTestCases[i].expectedMime;
- var url = xhrBlobTestCases[i].url !== undefined ? xhrBlobTestCases[i].url + xhrBlobTestUrl : xhrBlobTestUrl;
- url += xhrBlobTestCases[i].allowOrigin || "";
- if (xhrBlobTestCases[i].shouldThrow !== undefined) {
- try {
- testBlobContentTypeSync(url, mime, expectedMime);
- } catch (e) {
- testPassed("Exception should be thrown.")
- }
- } else {
- testBlobContentTypeSync(url, mime, expectedMime);
- }
- }
- }
-
- function testBlobContentTypeSync(url, mimeType, expectedMime) {
- var blob;
- if (mimeType !== "")
- blob = new Blob(["Test content"], {type: mimeType});
- else
- blob = new Blob(["Test content"]);
-
- xhr = new XMLHttpRequest();
- xhr.open("POST", url, false);
- xhr.send(blob);
- if (xhr.status === 200) {
- expectedMimeType = JSON.parse(xhr.response)['content-type'] || "";
- shouldBeEqualToString("expectedMimeType", expectedMime);
- } else
- testFailed("Unknown error");
-
- }
-
- runSyncTests();
-
- </script>
-</body>
-</html>
+
+<script src="/js-test-resources/js-test.js"></script>
+<script src="post-blob-content-type-tests.js"></script>
+<script type="text/javascript">
+ description("Test verifies that content MIME type is set correctly " +
+ "when Blob is sent using " +
+ "<a href='http://www.w3.org/TR/XMLHttpRequest/#the-send-method'>XMLHttpRequest synchronously.</a>");
+
+ var xhr;
+ var expectedMimeType;
+
+ function runSyncTests() {
+ var testCount = xhrBlobTestCases.length;
+ for (var i = 0; i < testCount; i++) {
+ var testCase = xhrBlobTestCases[i];
+ var mime = testCase.mime;
+ var file = testCase.file;
+ var expectedMime = testCase.expectedMime;
+ var url = testCase.url !== undefined ? testCase.url + xhrBlobTestUrl : xhrBlobTestUrl;
+ url += testCase.allowOrigin || "";
+ if (testCase.shouldThrow !== undefined) {
+ try {
+ testBlobContentTypeSync(url, file, mime, expectedMime);
+ } catch (e) {
+ testPassed("Exception should be thrown.")
+ }
+ } else {
+ testBlobContentTypeSync(url, file, mime, expectedMime);
+ }
+ }
+ }
+
+ function testBlobContentTypeSync(url, fileName, mimeType, expectedMime) {
+ var blob;
+ if (fileName) {
+ if (mimeType !== "")
+ blob = new File(["Test content"], fileName, {type: mimeType});
+ else
+ blob = new File(["Test content"], fileName);
+ } else {
+ if (mimeType !== "")
+ blob = new Blob(["Test content"], {type: mimeType});
+ else
+ blob = new Blob(["Test content"]);
+ }
+
+ xhr = new XMLHttpRequest();
+ xhr.open("POST", url, false);
+ xhr.send(blob);
+ if (xhr.status === 200) {
+ postedMimeType = JSON.parse(xhr.response)['content-type'] || "";
+ shouldBeEqualToString("postedMimeType", expectedMime);
+ } else
+ testFailed("Unknown error");
+
+ }
+
+ runSyncTests();
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-tests.js b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-tests.js
index b2f29bc..6b5c611 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-tests.js
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-blob-content-type-tests.js
@@ -45,4 +45,25 @@ var xhrBlobTestCases = [{
expectedMime: 'text/plain;charset=utf-8',
url: 'http://localhost:8000',
allowOrigin: '?origin=http://127.0.0.1:8000'
-}]; \ No newline at end of file
+}, {
+ mime: 'text/plain;charset=utf-8',
+ expectedMime: 'text/plain;charset=utf-8',
+ file: 'hello.txt'
+}, {
+ mime: 'ASCII/CR\r;charset=invalid',
+ expectedMime: '',
+ file: 'hello.txt'
+}, {
+ mime: '',
+ expectedMime: '',
+ file: 'hello.txt'
+}, {
+ mime: 'multipart/mixed;boundary="--blob-boundary"',
+ expectedMime: 'multipart/mixed;boundary="--blob-boundary"',
+ file: 'hello.txt'
+}, {
+ mime: '\u0422\u0435\u0441\u0442',
+ expectedMime: '',
+ shouldThrow: true,
+ file: 'hello.txt'
+}];
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-content-type.html b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-content-type.html
index bc7aff4..973b95e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-content-type.html
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-content-type.html
@@ -1,5 +1,5 @@
-<html>
-<body>
+<!DOCTYPE html>
+
<p>Test for <a href="http://crbug.com/172802">bug 172802</a>
- Wrong default Content-Type set in XMLHttpRequest.send(DOMString)</p>
<p>Should be text/plain;charset=UTF-8:</p>
@@ -12,5 +12,3 @@
objXmlHttp.send("");
document.write("<pre>" + objXmlHttp.responseText + "</pre>");
</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-formdata-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-formdata-expected.txt
new file mode 100644
index 0000000..296dc7b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-formdata-expected.txt
@@ -0,0 +1,16 @@
+Test verifies that FormData is sent correctly when using XMLHttpRequest asynchronously.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS echoResult is "string=string value"
+PASS echoResult is "bareBlob=blob:application/octet-stream:blob-value"
+PASS echoResult is "mimeBlob=blob:text/html:blob-value"
+PASS echoResult is "namedBlob=blob-file.txt:application/octet-stream:blob-value"
+PASS echoResult is "bareFile=file-name.txt:application/octet-stream:file-value"
+PASS echoResult is "mimeFile=file-name.html:text/html:file-value"
+PASS echoResult is "renamedFile=file-name-override.html:text/html:file-value"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-formdata.html b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-formdata.html
new file mode 100644
index 0000000..8777ddc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/post-formdata.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+
+<script src="/js-test-resources/js-test.js"></script>
+<script>
+description("Test verifies that FormData is sent correctly when using " +
+ "<a href='http://www.w3.org/TR/XMLHttpRequest/#the-send-method'>XMLHttpRequest asynchronously.</a>");
+
+var xhrFormDataTestUrl = '/xmlhttprequest/resources/multipart-post-echo.php';
+var xhrFormDataTestCases = [{
+ data: { string: 'string value' },
+ result: "string=string value"
+}, {
+ data: { bareBlob: new Blob(['blob-value']) },
+ result: 'bareBlob=blob:application/octet-stream:blob-value'
+}, {
+ data: { mimeBlob: new Blob(['blob-value'], { type: 'text/html' }) },
+ result: 'mimeBlob=blob:text/html:blob-value'
+}, {
+ data: {
+ namedBlob: {
+ value: new Blob(['blob-value']),
+ fileName: 'blob-file.txt'
+ }
+ },
+ result: 'namedBlob=blob-file.txt:application/octet-stream:blob-value'
+}, {
+ data: { bareFile: new File(['file-value'], 'file-name.txt') },
+ result: 'bareFile=file-name.txt:application/octet-stream:file-value'
+}, {
+ data: {
+ mimeFile: new File(['file-value'], 'file-name.html', { type: 'text/html' })
+ },
+ result: 'mimeFile=file-name.html:text/html:file-value'
+}, {
+ data: {
+ renamedFile: {
+ value: new File(['file-value'], 'file-name.html', { type: 'text/html' }),
+ fileName: 'file-name-override.html'
+ }
+ },
+ result: 'renamedFile=file-name-override.html:text/html:file-value'
+}];
+
+var xhr;
+var expectedMimeType;
+window.jsTestIsAsync = true;
+var asyncTestCase = 0;
+
+function runNextAsyncTest() {
+ asyncTestCase++;
+ runAsyncTests();
+}
+
+function reportResult(e) {
+ var testCase = xhrFormDataTestCases[asyncTestCase];
+ if (xhr.status === 200) {
+ echoResult = xhr.response;
+ shouldBeEqualToString("echoResult", testCase.result);
+ } else {
+ testFailed("Unknown error");
+ }
+
+ runNextAsyncTest();
+}
+
+function runAsyncTests() {
+ if (asyncTestCase >= xhrFormDataTestCases.length) {
+ finishJSTest();
+ return;
+ }
+
+ var testCase = xhrFormDataTestCases[asyncTestCase];
+ var formData = new FormData();
+ for (var fieldName in testCase.data) {
+ fieldValue = testCase.data[fieldName];
+ if (fieldValue.constructor === Object)
+ formData.append(fieldName, fieldValue.value, fieldValue.fileName);
+ else
+ formData.append(fieldName, fieldValue);
+ }
+
+ xhr = new XMLHttpRequest();
+ xhr.onloadend = reportResult;
+ xhr.open("POST", xhrFormDataTestUrl, true);
+ xhr.send(formData);
+}
+
+runAsyncTests();
+</script>
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-constructors-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-constructors-listing-dedicated-worker-expected.txt
index 9a63e99..165afe3 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-constructors-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-constructors-listing-dedicated-worker-expected.txt
@@ -14,6 +14,7 @@ Starting worker: resources/global-context-constructors-listing.js
[Worker] Error
[Worker] EvalError
[Worker] EventSource
+[Worker] File
[Worker] FileError
[Worker] FileReader
[Worker] FileReaderSync
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-constructors-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-constructors-listing-shared-worker-expected.txt
index ac0ee39..8cb2046 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-constructors-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-constructors-listing-shared-worker-expected.txt
@@ -13,6 +13,7 @@ Starting worker: resources/global-context-constructors-listing.js
[Worker] Error
[Worker] EvalError
[Worker] EventSource
+[Worker] File
[Worker] FileError
[Worker] FileReader
[Worker] FileReaderSync
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-constructors-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-constructors-listing-dedicated-worker-expected.txt
index 45da6b0..e3912c7 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-constructors-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-constructors-listing-dedicated-worker-expected.txt
@@ -14,6 +14,7 @@ Starting worker: resources/global-context-constructors-listing.js
[Worker] Error
[Worker] EvalError
[Worker] EventSource
+[Worker] File
[Worker] FileError
[Worker] FileReader
[Worker] FileReaderSync
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-constructors-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-constructors-listing-shared-worker-expected.txt
index 35d341b..a06d5e2 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-constructors-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-constructors-listing-shared-worker-expected.txt
@@ -13,6 +13,7 @@ Starting worker: resources/global-context-constructors-listing.js
[Worker] Error
[Worker] EvalError
[Worker] EventSource
+[Worker] File
[Worker] FileError
[Worker] FileReader
[Worker] FileReaderSync
diff --git a/third_party/WebKit/Source/bindings/bindings.gypi b/third_party/WebKit/Source/bindings/bindings.gypi
index c7d340a..9f02268 100644
--- a/third_party/WebKit/Source/bindings/bindings.gypi
+++ b/third_party/WebKit/Source/bindings/bindings.gypi
@@ -152,6 +152,8 @@
'v8/custom/V8AudioNodeCustom.cpp',
'v8/custom/V8BiquadFilterNodeCustom.cpp',
'v8/custom/V8BlobCustom.cpp',
+ 'v8/custom/V8BlobCustomHelpers.cpp',
+ 'v8/custom/V8BlobCustomHelpers.h',
'v8/custom/V8CSSRuleCustom.cpp',
'v8/custom/V8CSSStyleDeclarationCustom.cpp',
'v8/custom/V8CSSValueCustom.cpp',
@@ -173,6 +175,7 @@
'v8/custom/V8EventCustom.cpp',
'v8/custom/V8EventTargetCustom.cpp',
'v8/custom/V8ErrorEventCustom.cpp',
+ 'v8/custom/V8FileCustom.cpp',
'v8/custom/V8FileReaderCustom.cpp',
'v8/custom/V8Float32ArrayCustom.h',
'v8/custom/V8Float64ArrayCustom.h',
diff --git a/third_party/WebKit/Source/bindings/v8/V8BindingMacros.h b/third_party/WebKit/Source/bindings/v8/V8BindingMacros.h
index 0123dbf..8098652 100644
--- a/third_party/WebKit/Source/bindings/v8/V8BindingMacros.h
+++ b/third_party/WebKit/Source/bindings/v8/V8BindingMacros.h
@@ -42,6 +42,17 @@ namespace WebCore {
return block.ReThrow(); \
}
+#define V8TRYCATCH_RETURN(type, var, value, retVal) \
+ type var; \
+ { \
+ v8::TryCatch block; \
+ var = (value); \
+ if (block.HasCaught()) { \
+ block.ReThrow(); \
+ return retVal; \
+ } \
+ }
+
#define V8TRYCATCH_VOID(type, var, value) \
type var; \
{ \
diff --git a/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp b/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp
index 96ba613..be506f8 100644
--- a/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp
+++ b/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp
@@ -31,14 +31,8 @@
#include "config.h"
#include "V8Blob.h"
-#include "bindings/v8/Dictionary.h"
-#include "bindings/v8/ExceptionMessages.h"
-#include "bindings/v8/V8Binding.h"
-#include "bindings/v8/V8Utilities.h"
-#include "bindings/v8/custom/V8ArrayBufferCustom.h"
-#include "bindings/v8/custom/V8ArrayBufferViewCustom.h"
+#include "bindings/v8/custom/V8BlobCustomHelpers.h"
#include "core/fileapi/BlobBuilder.h"
-#include "wtf/RefPtr.h"
namespace WebCore {
@@ -46,7 +40,7 @@ void V8Blob::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
{
if (!info.Length()) {
RefPtr<Blob> blob = Blob::create();
- info.GetReturnValue().Set(toV8(blob.get(), info.Holder(), info.GetIsolate()));
+ v8SetReturnValue(info, blob.release());
return;
}
@@ -61,63 +55,25 @@ void V8Blob::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
}
}
- String type;
- String endings = "transparent";
-
+ String contentType;
+ String endings = "transparent"; // default if no BlobPropertyBag is passed
if (info.Length() > 1) {
if (!info[1]->IsObject()) {
throwTypeError(ExceptionMessages::failedToConstruct("Blob", "The 2nd argument is not of type Object."), info.GetIsolate());
return;
}
- V8TRYCATCH_VOID(Dictionary, dictionary, Dictionary(info[1], info.GetIsolate()));
-
- V8TRYCATCH_VOID(bool, containsEndings, dictionary.get("endings", endings));
- if (containsEndings) {
- if (endings != "transparent" && endings != "native") {
- throwTypeError(ExceptionMessages::failedToConstruct("Blob", "The 2nd argument's \"endings\" property must be either \"transparent\" or \"native\"."), info.GetIsolate());
- return;
- }
- }
-
- V8TRYCATCH_VOID(bool, containsType, dictionary.get("type", type));
- UNUSED_PARAM(containsType);
- if (!type.containsOnlyASCII()) {
- throwError(v8SyntaxError, ExceptionMessages::failedToConstruct("Blob", "The 2nd argument's \"type\" property must consist of ASCII characters."), info.GetIsolate());
+ if (!V8BlobCustomHelpers::processBlobPropertyBag(info[1], "Blob", contentType, endings, info.GetIsolate()))
return;
- }
- type = type.lower();
}
- ASSERT(endings == "transparent" || endings == "native");
-
BlobBuilder blobBuilder;
v8::Local<v8::Object> blobParts = v8::Local<v8::Object>::Cast(info[0]);
- for (uint32_t i = 0; i < length; ++i) {
- v8::Local<v8::Value> item = blobParts->Get(v8::Uint32::New(i, info.GetIsolate()));
- if (item.IsEmpty())
- return;
-
- if (V8ArrayBuffer::hasInstance(item, info.GetIsolate(), worldType(info.GetIsolate()))) {
- ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(item));
- ASSERT(arrayBuffer);
- blobBuilder.append(arrayBuffer);
- } else if (V8ArrayBufferView::hasInstance(item, info.GetIsolate(), worldType(info.GetIsolate()))) {
- ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(item));
- ASSERT(arrayBufferView);
- blobBuilder.append(arrayBufferView);
- } else if (V8Blob::hasInstance(item, info.GetIsolate(), worldType(info.GetIsolate()))) {
- Blob* blob = V8Blob::toNative(v8::Handle<v8::Object>::Cast(item));
- ASSERT(blob);
- blobBuilder.append(blob);
- } else {
- V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, stringValue, item);
- blobBuilder.append(stringValue, endings);
- }
- }
+ if (!V8BlobCustomHelpers::processBlobParts(blobParts, length, endings, blobBuilder, info.GetIsolate()))
+ return;
- RefPtr<Blob> blob = blobBuilder.getBlob(type);
- info.GetReturnValue().Set(toV8(blob.get(), info.Holder(), info.GetIsolate()));
+ RefPtr<Blob> blob = blobBuilder.createBlob(contentType);
+ v8SetReturnValue(info, blob.release());
}
} // namespace WebCore
diff --git a/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.cpp b/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.cpp
new file mode 100644
index 0000000..ee35937
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "V8BlobCustomHelpers.h"
+
+#include "V8Blob.h"
+#include "bindings/v8/Dictionary.h"
+#include "bindings/v8/V8Binding.h"
+#include "bindings/v8/V8Utilities.h"
+#include "bindings/v8/custom/V8ArrayBufferCustom.h"
+#include "bindings/v8/custom/V8ArrayBufferViewCustom.h"
+#include "core/fileapi/BlobBuilder.h"
+
+namespace WebCore {
+
+namespace V8BlobCustomHelpers {
+
+bool processBlobPropertyBag(v8::Local<v8::Value> propertyBag, const char* blobClassName, String& contentType, String& endings, v8::Isolate* isolate)
+{
+ ASSERT(endings == "transparent");
+
+ V8TRYCATCH_RETURN(Dictionary, dictionary, Dictionary(propertyBag, isolate), false);
+
+ V8TRYCATCH_RETURN(bool, containsEndings, dictionary.get("endings", endings), false);
+ if (containsEndings) {
+ if (endings != "transparent" && endings != "native") {
+ throwTypeError(ExceptionMessages::failedToConstruct(blobClassName, "The \"endings\" property must be either \"transparent\" or \"native\"."), isolate);
+ return false;
+ }
+ }
+
+ V8TRYCATCH_RETURN(bool, containsType, dictionary.get("type", contentType), false);
+ if (containsType) {
+ if (!contentType.containsOnlyASCII()) {
+ throwError(v8SyntaxError, ExceptionMessages::failedToConstruct(blobClassName, "The \"type\" property must consist of ASCII characters."), isolate);
+ return false;
+ }
+ contentType = contentType.lower();
+ }
+ return true;
+}
+
+bool processBlobParts(v8::Local<v8::Object> blobParts, uint32_t blobPartsLength, const String& endings, BlobBuilder& blobBuilder, v8::Isolate* isolate)
+{
+ ASSERT(endings == "transparent" || endings == "native");
+
+ for (uint32_t i = 0; i < blobPartsLength; ++i) {
+ v8::Local<v8::Value> item = blobParts->Get(v8::Uint32::New(i, isolate));
+ if (item.IsEmpty())
+ return false;
+
+ if (V8ArrayBuffer::hasInstance(item, isolate, worldType(isolate))) {
+ ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(item));
+ ASSERT(arrayBuffer);
+ blobBuilder.append(arrayBuffer);
+ } else if (V8ArrayBufferView::hasInstance(item, isolate, worldType(isolate))) {
+ ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(item));
+ ASSERT(arrayBufferView);
+ blobBuilder.append(arrayBufferView);
+ } else if (V8Blob::hasInstance(item, isolate, worldType(isolate))) {
+ Blob* blob = V8Blob::toNative(v8::Handle<v8::Object>::Cast(item));
+ ASSERT(blob);
+ blobBuilder.append(blob);
+ } else {
+ V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, item, false);
+ blobBuilder.append(stringValue, endings);
+ }
+ }
+ return true;
+}
+
+} // namespace V8BlobCustomHelpers
+
+} // namespace WebCore
diff --git a/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.h b/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.h
new file mode 100644
index 0000000..8bb22f0
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef V8BlobCustomHelpers_h
+#define V8BlobCustomHelpers_h
+
+#include "bindings/v8/V8Binding.h"
+
+namespace WebCore {
+
+class BlobBuilder;
+
+// Shared code between the custom constructor bindings for Blob and File.
+namespace V8BlobCustomHelpers {
+
+// Extracts the "type" and "endings" properties out of the BlobPropertyBag passed to a Blob constructor.
+// http://www.w3.org/TR/FileAPI/#constructorParams
+// Returns true if everything went well, false if a JS exception was thrown.
+bool processBlobPropertyBag(v8::Local<v8::Value> propertyBag, const char* blobClassName, String& contentType, String& endings, v8::Isolate*);
+
+// Appends the blobParts passed to a Blob constructor into a BlobBuilder.
+// http://www.w3.org/TR/FileAPI/#constructorParams
+// Returns true if everything went well, false if a JS exception was thrown.
+bool processBlobParts(v8::Local<v8::Object> blobParts, uint32_t blobPartsLength, const String& endings, BlobBuilder&, v8::Isolate*);
+
+} // namespace V8BlobCustomHelpers
+
+} // namespace WebCore
+
+#endif // V8BlobCustomHelpers_h
diff --git a/third_party/WebKit/Source/bindings/v8/custom/V8FileCustom.cpp b/third_party/WebKit/Source/bindings/v8/custom/V8FileCustom.cpp
new file mode 100644
index 0000000..6983ef2
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/v8/custom/V8FileCustom.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "V8File.h"
+
+#include "RuntimeEnabledFeatures.h"
+#include "bindings/v8/custom/V8BlobCustomHelpers.h"
+#include "core/fileapi/BlobBuilder.h"
+
+namespace WebCore {
+
+void V8File::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+ if (!RuntimeEnabledFeatures::fileConstructorEnabled()) {
+ throwTypeError("Illegal constructor", info.GetIsolate());
+ return;
+ }
+
+ if (info.Length() < 2) {
+ throwTypeError("File constructor requires at least two arguments", info.GetIsolate());
+ return;
+ }
+
+ uint32_t length = 0;
+ if (info[0]->IsArray()) {
+ length = v8::Local<v8::Array>::Cast(info[0])->Length();
+ } else {
+ const int sequenceArgumentIndex = 0;
+ if (toV8Sequence(info[sequenceArgumentIndex], length, info.GetIsolate()).IsEmpty()) {
+ throwTypeError(ExceptionMessages::failedToConstruct("File", ExceptionMessages::notAnArrayTypeArgumentOrValue(sequenceArgumentIndex + 1)), info.GetIsolate());
+ return;
+ }
+ }
+
+ V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, fileName, info[1]);
+
+ String contentType;
+ String endings = "transparent"; // default if no BlobPropertyBag is passed
+ if (info.Length() > 2) {
+ if (!info[2]->IsObject()) {
+ throwTypeError(ExceptionMessages::failedToConstruct("File", "The 3rd argument is not of type Object."), info.GetIsolate());
+ return;
+ }
+
+ if (!V8BlobCustomHelpers::processBlobPropertyBag(info[2], "File", contentType, endings, info.GetIsolate()))
+ return;
+ }
+
+ BlobBuilder blobBuilder;
+ v8::Local<v8::Object> blobParts = v8::Local<v8::Object>::Cast(info[0]);
+ if (!V8BlobCustomHelpers::processBlobParts(blobParts, length, endings, blobBuilder, info.GetIsolate()))
+ return;
+
+ RefPtr<File> file = blobBuilder.createFile(contentType, fileName, currentTime());
+ v8SetReturnValue(info, file.release());
+}
+
+} // namespace WebCore
diff --git a/third_party/WebKit/Source/core/fileapi/Blob.cpp b/third_party/WebKit/Source/core/fileapi/Blob.cpp
index 5fda7d84..def1ae0 100644
--- a/third_party/WebKit/Source/core/fileapi/Blob.cpp
+++ b/third_party/WebKit/Source/core/fileapi/Blob.cpp
@@ -82,7 +82,7 @@ PassRefPtr<Blob> Blob::slice(long long start, long long end, const String& conte
// The modification time will be used to verify if the file has been changed or not, when the underlying data are accessed.
long long size;
double modificationTime;
- if (isFile()) {
+ if (hasBackingFile()) {
// FIXME: This involves synchronous file operation. We need to figure out how to make it asynchronous.
toFile(this)->captureSnapshot(size, modificationTime);
} else {
@@ -112,7 +112,7 @@ PassRefPtr<Blob> Blob::slice(long long start, long long end, const String& conte
long long length = end - start;
OwnPtr<BlobData> blobData = BlobData::create();
blobData->setContentType(contentType);
- if (isFile()) {
+ if (hasBackingFile()) {
if (!toFile(this)->fileSystemURL().isEmpty())
blobData->appendFileSystemURL(toFile(this)->fileSystemURL(), start, length, modificationTime);
else
diff --git a/third_party/WebKit/Source/core/fileapi/Blob.h b/third_party/WebKit/Source/core/fileapi/Blob.h
index 58006c8..6a72155 100644
--- a/third_party/WebKit/Source/core/fileapi/Blob.h
+++ b/third_party/WebKit/Source/core/fileapi/Blob.h
@@ -60,7 +60,10 @@ public:
String uuid() const { return m_blobDataHandle->uuid(); }
String type() const { return m_blobDataHandle->type(); }
virtual unsigned long long size() const { return m_blobDataHandle->size(); }
+ // True for all File instances, including the user-built ones.
virtual bool isFile() const { return false; }
+ // Only true for File instances that are backed by platform files.
+ virtual bool hasBackingFile() const { return false; }
PassRefPtr<BlobDataHandle> blobDataHandle() const { return m_blobDataHandle; }
PassRefPtr<Blob> slice(long long start = 0, long long end = std::numeric_limits<long long>::max(), const String& contentType = String()) const;
diff --git a/third_party/WebKit/Source/core/fileapi/BlobBuilder.cpp b/third_party/WebKit/Source/core/fileapi/BlobBuilder.cpp
index 8be60c1..70583af 100644
--- a/third_party/WebKit/Source/core/fileapi/BlobBuilder.cpp
+++ b/third_party/WebKit/Source/core/fileapi/BlobBuilder.cpp
@@ -94,7 +94,7 @@ void BlobBuilder::append(Blob* blob)
{
if (!blob)
return;
- if (blob->isFile()) {
+ if (blob->hasBackingFile()) {
File* file = toFile(blob);
// If the blob is file that is not snapshoted, capture the snapshot now.
// FIXME: This involves synchronous file operation. We need to figure out how to make it asynchronous.
@@ -122,7 +122,7 @@ void BlobBuilder::appendBytesData(const void* data, size_t length)
m_size += buffer.size() - oldSize;
}
-PassRefPtr<Blob> BlobBuilder::getBlob(const String& contentType)
+PassRefPtr<Blob> BlobBuilder::createBlob(const String& contentType)
{
OwnPtr<BlobData> blobData = BlobData::create();
blobData->setContentType(contentType);
@@ -134,7 +134,22 @@ PassRefPtr<Blob> BlobBuilder::getBlob(const String& contentType)
// Instead, we only need to keep a reference to the blob data just created.
m_items.append(BlobDataItem(blob->blobDataHandle(), 0, m_size));
- return blob;
+ return blob.release();
+}
+
+PassRefPtr<File> BlobBuilder::createFile(const String& contentType, const String& fileName, double modificationTime)
+{
+ OwnPtr<BlobData> blobData = BlobData::create();
+ blobData->setContentType(contentType);
+ blobData->swapItems(m_items);
+
+ RefPtr<File> file = File::create(fileName, modificationTime, BlobDataHandle::create(blobData.release(), m_size));
+
+ // After creating a file from the current blob data, we do not need to keep the data around any more.
+ // Instead, we only need to keep a reference to the blob data just created.
+ m_items.append(BlobDataItem(file->blobDataHandle(), 0, m_size));
+
+ return file.release();
}
} // namespace WebCore
diff --git a/third_party/WebKit/Source/core/fileapi/BlobBuilder.h b/third_party/WebKit/Source/core/fileapi/BlobBuilder.h
index 560a79c..cdf3cc5 100644
--- a/third_party/WebKit/Source/core/fileapi/BlobBuilder.h
+++ b/third_party/WebKit/Source/core/fileapi/BlobBuilder.h
@@ -34,15 +34,10 @@
#include "platform/blob/BlobData.h"
#include "wtf/Forward.h"
-namespace WTF{
-class TextEncoding;
-}
-
namespace WebCore {
class Blob;
-
-typedef int ExceptionCode;
+class File;
class BlobBuilder {
public:
@@ -53,7 +48,8 @@ public:
void append(ArrayBuffer*);
void append(ArrayBufferView*);
- PassRefPtr<Blob> getBlob(const String& contentType);
+ PassRefPtr<Blob> createBlob(const String& contentType);
+ PassRefPtr<File> createFile(const String& contentType, const String& fileName, double modificationTime);
private:
void appendBytesData(const void*, size_t);
diff --git a/third_party/WebKit/Source/core/fileapi/File.cpp b/third_party/WebKit/Source/core/fileapi/File.cpp
index 02d9700..6842161 100644
--- a/third_party/WebKit/Source/core/fileapi/File.cpp
+++ b/third_party/WebKit/Source/core/fileapi/File.cpp
@@ -94,6 +94,7 @@ PassRefPtr<File> File::createWithRelativePath(const String& path, const String&
File::File(const String& path, ContentTypeLookupPolicy policy)
: Blob(BlobDataHandle::create(createBlobDataForFile(path, policy), -1))
+ , m_hasBackingFile(true)
, m_path(path)
, m_name(blink::Platform::current()->fileUtilities()->baseName(path))
, m_snapshotSize(-1)
@@ -104,6 +105,7 @@ File::File(const String& path, ContentTypeLookupPolicy policy)
File::File(const String& path, const String& name, ContentTypeLookupPolicy policy)
: Blob(BlobDataHandle::create(createBlobDataForFileWithName(path, name, policy), -1))
+ , m_hasBackingFile(true)
, m_path(path)
, m_name(name)
, m_snapshotSize(-1)
@@ -114,6 +116,7 @@ File::File(const String& path, const String& name, ContentTypeLookupPolicy polic
File::File(const String& path, PassRefPtr<BlobDataHandle> blobDataHandle)
: Blob(blobDataHandle)
+ , m_hasBackingFile(true)
, m_path(path)
, m_name(blink::Platform::current()->fileUtilities()->baseName(path))
, m_snapshotSize(-1)
@@ -125,8 +128,19 @@ File::File(const String& path, PassRefPtr<BlobDataHandle> blobDataHandle)
// See SerializedScriptValue.cpp.
}
+File::File(const String& name, double modificationTime, PassRefPtr<BlobDataHandle> blobDataHandle)
+ : Blob(blobDataHandle)
+ , m_hasBackingFile(false)
+ , m_name(name)
+ , m_snapshotSize(Blob::size())
+ , m_snapshotModificationTime(modificationTime)
+{
+ ScriptWrappable::init(this);
+}
+
File::File(const String& name, const FileMetadata& metadata)
: Blob(BlobDataHandle::create(createBlobDataForFileWithMetadata(name, metadata), metadata.length))
+ , m_hasBackingFile(true)
, m_path(metadata.platformPath)
, m_name(name)
, m_snapshotSize(metadata.length)
@@ -137,6 +151,7 @@ File::File(const String& name, const FileMetadata& metadata)
File::File(const KURL& fileSystemURL, const FileMetadata& metadata)
: Blob(BlobDataHandle::create(createBlobDataForFileSystemURL(fileSystemURL, metadata), metadata.length))
+ , m_hasBackingFile(true)
, m_fileSystemURL(fileSystemURL)
, m_snapshotSize(metadata.length)
, m_snapshotModificationTime(metadata.modificationTime)
diff --git a/third_party/WebKit/Source/core/fileapi/File.h b/third_party/WebKit/Source/core/fileapi/File.h
index c6d8db4..f9c87b4 100644
--- a/third_party/WebKit/Source/core/fileapi/File.h
+++ b/third_party/WebKit/Source/core/fileapi/File.h
@@ -49,6 +49,11 @@ public:
return adoptRef(new File(path, policy));
}
+ static PassRefPtr<File> create(const String& name, double modificationTime, PassRefPtr<BlobDataHandle> blobDataHandle)
+ {
+ return adoptRef(new File(name, modificationTime, blobDataHandle));
+ }
+
// For deserialization.
static PassRefPtr<File> create(const String& path, PassRefPtr<BlobDataHandle> blobDataHandle)
{
@@ -70,7 +75,7 @@ public:
return adoptRef(new File(url, metadata));
}
- KURL fileSystemURL() const { return m_fileSystemURL; }
+ KURL fileSystemURL() const { ASSERT(m_hasBackingFile); return m_fileSystemURL; }
// Create a file with a name exposed to the author (via File.name and associated DOM properties) that differs from the one provided in the path.
static PassRefPtr<File> createWithName(const String& path, const String& name, ContentTypeLookupPolicy policy = WellKnownContentTypes)
@@ -80,10 +85,11 @@ public:
return adoptRef(new File(path, name, policy));
}
- virtual unsigned long long size() const;
- virtual bool isFile() const { return true; }
+ virtual unsigned long long size() const OVERRIDE;
+ virtual bool isFile() const OVERRIDE { return true; }
+ virtual bool hasBackingFile() const OVERRIDE { return m_hasBackingFile; }
- const String& path() const { return m_path; }
+ const String& path() const { ASSERT(m_hasBackingFile); return m_path; }
const String& name() const { return m_name; }
// This returns the current date and time if the file's last modifiecation date is not known (per spec: http://www.w3.org/TR/FileAPI/#dfn-lastModifiedDate).
@@ -99,12 +105,14 @@ private:
File(const String& path, ContentTypeLookupPolicy);
File(const String& path, const String& name, ContentTypeLookupPolicy);
File(const String& path, PassRefPtr<BlobDataHandle>);
+ File(const String& name, double modificationTime, PassRefPtr<BlobDataHandle>);
File(const String& name, const FileMetadata&);
File(const KURL& fileSystemURL, const FileMetadata&);
// Returns true if this has a valid snapshot metadata (i.e. m_snapshotSize >= 0).
bool hasValidSnapshotMetadata() const { return m_snapshotSize >= 0; }
+ bool m_hasBackingFile;
String m_path;
String m_name;
diff --git a/third_party/WebKit/Source/core/fileapi/File.idl b/third_party/WebKit/Source/core/fileapi/File.idl
index 56be7fc..fdbe18d 100644
--- a/third_party/WebKit/Source/core/fileapi/File.idl
+++ b/third_party/WebKit/Source/core/fileapi/File.idl
@@ -23,7 +23,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-interface File : Blob {
+[
+ GlobalContext=Window&WorkerGlobalScope,
+ CustomConstructor(sequence<any> blobParts, DOMString fileName, optional BlobPropertyBag options)
+] interface File : Blob {
readonly attribute DOMString name;
readonly attribute Date lastModifiedDate;
[RuntimeEnabled=DirectoryUpload] readonly attribute DOMString webkitRelativePath;
diff --git a/third_party/WebKit/Source/core/fileapi/FileReader.cpp b/third_party/WebKit/Source/core/fileapi/FileReader.cpp
index 2dffe0d..a2a5673 100644
--- a/third_party/WebKit/Source/core/fileapi/FileReader.cpp
+++ b/third_party/WebKit/Source/core/fileapi/FileReader.cpp
@@ -54,7 +54,7 @@ const CString utf8BlobUUID(Blob* blob)
const CString utf8FilePath(Blob* blob)
{
- return blob->isFile() ? toFile(blob)->path().utf8() : "";
+ return blob->hasBackingFile() ? toFile(blob)->path().utf8() : "";
}
#endif
diff --git a/third_party/WebKit/Source/core/html/FormDataList.cpp b/third_party/WebKit/Source/core/html/FormDataList.cpp
index f490596..b564d2c 100644
--- a/third_party/WebKit/Source/core/html/FormDataList.cpp
+++ b/third_party/WebKit/Source/core/html/FormDataList.cpp
@@ -115,7 +115,7 @@ void FormDataList::appendKeyValuePairItemsTo(FormData* formData, const WTF::Text
// Append body
formData->appendData(header.data(), header.size());
if (value.blob()) {
- if (value.blob()->isFile()) {
+ if (value.blob()->hasBackingFile()) {
File* file = toFile(value.blob());
// Do not add the file if the path is empty.
if (!file->path().isEmpty())
diff --git a/third_party/WebKit/Source/core/xml/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xml/XMLHttpRequest.cpp
index f8e652a..a5311cb 100644
--- a/third_party/WebKit/Source/core/xml/XMLHttpRequest.cpp
+++ b/third_party/WebKit/Source/core/xml/XMLHttpRequest.cpp
@@ -684,7 +684,7 @@ void XMLHttpRequest::send(Blob* body, ExceptionState& es)
// FIXME: add support for uploading bundles.
m_requestEntityBody = FormData::create();
- if (body->isFile())
+ if (body->hasBackingFile())
m_requestEntityBody->appendFile(toFile(body)->path());
else
m_requestEntityBody->appendBlob(body->uuid(), body->blobDataHandle());
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
index 2a730f3..1710595 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -50,6 +50,7 @@ EncryptedMedia status=experimental
EncryptedMediaAnyVersion status=stable
ExperimentalCanvasFeatures status=test
ExperimentalContentSecurityPolicyFeatures status=experimental
+FileConstructor status=experimental
FileSystem status=stable
FontLoadEvents status=experimental
Fullscreen status=stable