diff --git a/testing/web-platform/meta/MANIFEST.json b/testing/web-platform/meta/MANIFEST.json
index 6e2c6ea3431..da115865086 100644
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -13583,6 +13583,10 @@
"path": "cssom-view/elementsFromPoint.html",
"url": "/cssom-view/elementsFromPoint.html"
},
+ {
+ "path": "cssom-view/scrollingElement.html",
+ "url": "/cssom-view/scrollingElement.html"
+ },
{
"path": "custom-elements/concepts/custom-elements-type-naming.html",
"url": "/custom-elements/concepts/custom-elements-type-naming.html"
@@ -15119,6 +15123,366 @@
"path": "ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.html",
"url": "/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.html"
},
+ {
+ "path": "fetch/api/basic/accept-header-worker.html",
+ "url": "/fetch/api/basic/accept-header-worker.html"
+ },
+ {
+ "path": "fetch/api/basic/accept-header.html",
+ "url": "/fetch/api/basic/accept-header.html"
+ },
+ {
+ "path": "fetch/api/basic/integrity-worker.html",
+ "url": "/fetch/api/basic/integrity-worker.html"
+ },
+ {
+ "path": "fetch/api/basic/integrity.html",
+ "url": "/fetch/api/basic/integrity.html"
+ },
+ {
+ "path": "fetch/api/basic/mode-no-cors-worker.html",
+ "url": "/fetch/api/basic/mode-no-cors-worker.html"
+ },
+ {
+ "path": "fetch/api/basic/mode-no-cors.html",
+ "url": "/fetch/api/basic/mode-no-cors.html"
+ },
+ {
+ "path": "fetch/api/basic/mode-same-origin-worker.html",
+ "url": "/fetch/api/basic/mode-same-origin-worker.html"
+ },
+ {
+ "path": "fetch/api/basic/mode-same-origin.html",
+ "url": "/fetch/api/basic/mode-same-origin.html"
+ },
+ {
+ "path": "fetch/api/basic/request-forbidden-headers-worker.html",
+ "url": "/fetch/api/basic/request-forbidden-headers-worker.html"
+ },
+ {
+ "path": "fetch/api/basic/request-forbidden-headers.html",
+ "url": "/fetch/api/basic/request-forbidden-headers.html"
+ },
+ {
+ "path": "fetch/api/basic/request-headers-worker.html",
+ "url": "/fetch/api/basic/request-headers-worker.html"
+ },
+ {
+ "path": "fetch/api/basic/request-headers.html",
+ "url": "/fetch/api/basic/request-headers.html"
+ },
+ {
+ "path": "fetch/api/basic/scheme-about-worker.html",
+ "url": "/fetch/api/basic/scheme-about-worker.html"
+ },
+ {
+ "path": "fetch/api/basic/scheme-about.html",
+ "url": "/fetch/api/basic/scheme-about.html"
+ },
+ {
+ "path": "fetch/api/basic/scheme-blob-worker.html",
+ "url": "/fetch/api/basic/scheme-blob-worker.html"
+ },
+ {
+ "path": "fetch/api/basic/scheme-blob.html",
+ "url": "/fetch/api/basic/scheme-blob.html"
+ },
+ {
+ "path": "fetch/api/basic/scheme-data-worker.html",
+ "url": "/fetch/api/basic/scheme-data-worker.html"
+ },
+ {
+ "path": "fetch/api/basic/scheme-data.html",
+ "url": "/fetch/api/basic/scheme-data.html"
+ },
+ {
+ "path": "fetch/api/basic/scheme-others-worker.html",
+ "url": "/fetch/api/basic/scheme-others-worker.html"
+ },
+ {
+ "path": "fetch/api/basic/scheme-others.html",
+ "url": "/fetch/api/basic/scheme-others.html"
+ },
+ {
+ "path": "fetch/api/basic/stream-response-worker.html",
+ "url": "/fetch/api/basic/stream-response-worker.html"
+ },
+ {
+ "path": "fetch/api/basic/stream-response.html",
+ "url": "/fetch/api/basic/stream-response.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-basic-worker.html",
+ "url": "/fetch/api/cors/cors-basic-worker.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-basic.html",
+ "url": "/fetch/api/cors/cors-basic.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-cookies-worker.html",
+ "url": "/fetch/api/cors/cors-cookies-worker.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-cookies.html",
+ "url": "/fetch/api/cors/cors-cookies.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-filtering-worker.html",
+ "url": "/fetch/api/cors/cors-filtering-worker.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-filtering.html",
+ "url": "/fetch/api/cors/cors-filtering.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-multiple-origins-worker.html",
+ "url": "/fetch/api/cors/cors-multiple-origins-worker.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-multiple-origins.html",
+ "url": "/fetch/api/cors/cors-multiple-origins.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-no-preflight-worker.html",
+ "url": "/fetch/api/cors/cors-no-preflight-worker.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-no-preflight.html",
+ "url": "/fetch/api/cors/cors-no-preflight.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-origin-worker.html",
+ "url": "/fetch/api/cors/cors-origin-worker.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-origin.html",
+ "url": "/fetch/api/cors/cors-origin.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-preflight-redirect-worker.html",
+ "url": "/fetch/api/cors/cors-preflight-redirect-worker.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-preflight-redirect.html",
+ "url": "/fetch/api/cors/cors-preflight-redirect.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-preflight-referrer-worker.html",
+ "url": "/fetch/api/cors/cors-preflight-referrer-worker.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-preflight-referrer.html",
+ "url": "/fetch/api/cors/cors-preflight-referrer.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-preflight-status-worker.html",
+ "url": "/fetch/api/cors/cors-preflight-status-worker.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-preflight-status.html",
+ "url": "/fetch/api/cors/cors-preflight-status.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-preflight-worker.html",
+ "url": "/fetch/api/cors/cors-preflight-worker.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-preflight.html",
+ "url": "/fetch/api/cors/cors-preflight.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-redirect-credentials-worker.html",
+ "url": "/fetch/api/cors/cors-redirect-credentials-worker.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-redirect-credentials.html",
+ "url": "/fetch/api/cors/cors-redirect-credentials.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-redirect-worker.html",
+ "url": "/fetch/api/cors/cors-redirect-worker.html"
+ },
+ {
+ "path": "fetch/api/cors/cors-redirect.html",
+ "url": "/fetch/api/cors/cors-redirect.html"
+ },
+ {
+ "path": "fetch/api/credentials/authentication-basic-worker.html",
+ "url": "/fetch/api/credentials/authentication-basic-worker.html"
+ },
+ {
+ "path": "fetch/api/credentials/authentication-basic.html",
+ "url": "/fetch/api/credentials/authentication-basic.html"
+ },
+ {
+ "path": "fetch/api/credentials/cookies-worker.html",
+ "url": "/fetch/api/credentials/cookies-worker.html"
+ },
+ {
+ "path": "fetch/api/credentials/cookies.html",
+ "url": "/fetch/api/credentials/cookies.html"
+ },
+ {
+ "path": "fetch/api/headers/headers-basic.html",
+ "url": "/fetch/api/headers/headers-basic.html"
+ },
+ {
+ "path": "fetch/api/headers/headers-casing.html",
+ "url": "/fetch/api/headers/headers-casing.html"
+ },
+ {
+ "path": "fetch/api/headers/headers-combine.html",
+ "url": "/fetch/api/headers/headers-combine.html"
+ },
+ {
+ "path": "fetch/api/headers/headers-errors.html",
+ "url": "/fetch/api/headers/headers-errors.html"
+ },
+ {
+ "path": "fetch/api/headers/headers-idl.html",
+ "url": "/fetch/api/headers/headers-idl.html"
+ },
+ {
+ "path": "fetch/api/headers/headers-normalize.html",
+ "url": "/fetch/api/headers/headers-normalize.html"
+ },
+ {
+ "path": "fetch/api/headers/headers-structure.html",
+ "url": "/fetch/api/headers/headers-structure.html"
+ },
+ {
+ "path": "fetch/api/policies/csp-blocked-worker.html",
+ "url": "/fetch/api/policies/csp-blocked-worker.html"
+ },
+ {
+ "path": "fetch/api/policies/csp-blocked.html",
+ "url": "/fetch/api/policies/csp-blocked.html"
+ },
+ {
+ "path": "fetch/api/policies/referrer-no-referrer-worker.html",
+ "url": "/fetch/api/policies/referrer-no-referrer-worker.html"
+ },
+ {
+ "path": "fetch/api/policies/referrer-no-referrer.html",
+ "url": "/fetch/api/policies/referrer-no-referrer.html"
+ },
+ {
+ "path": "fetch/api/policies/referrer-origin-worker.html",
+ "url": "/fetch/api/policies/referrer-origin-worker.html"
+ },
+ {
+ "path": "fetch/api/policies/referrer-origin.html",
+ "url": "/fetch/api/policies/referrer-origin.html"
+ },
+ {
+ "path": "fetch/api/policies/referrer-unsafe-url-worker.html",
+ "url": "/fetch/api/policies/referrer-unsafe-url-worker.html"
+ },
+ {
+ "path": "fetch/api/policies/referrer-unsafe-url.html",
+ "url": "/fetch/api/policies/referrer-unsafe-url.html"
+ },
+ {
+ "path": "fetch/api/redirect/redirect-count-worker.html",
+ "url": "/fetch/api/redirect/redirect-count-worker.html"
+ },
+ {
+ "path": "fetch/api/redirect/redirect-count.html",
+ "url": "/fetch/api/redirect/redirect-count.html"
+ },
+ {
+ "path": "fetch/api/redirect/redirect-location-worker.html",
+ "url": "/fetch/api/redirect/redirect-location-worker.html"
+ },
+ {
+ "path": "fetch/api/redirect/redirect-location.html",
+ "url": "/fetch/api/redirect/redirect-location.html"
+ },
+ {
+ "path": "fetch/api/redirect/redirect-method-worker.html",
+ "url": "/fetch/api/redirect/redirect-method-worker.html"
+ },
+ {
+ "path": "fetch/api/redirect/redirect-method.html",
+ "url": "/fetch/api/redirect/redirect-method.html"
+ },
+ {
+ "path": "fetch/api/redirect/redirect-mode-worker.html",
+ "url": "/fetch/api/redirect/redirect-mode-worker.html"
+ },
+ {
+ "path": "fetch/api/redirect/redirect-mode.html",
+ "url": "/fetch/api/redirect/redirect-mode.html"
+ },
+ {
+ "path": "fetch/api/request/request-clone.sub.html",
+ "url": "/fetch/api/request/request-clone.sub.html"
+ },
+ {
+ "path": "fetch/api/request/request-consume.html",
+ "url": "/fetch/api/request/request-consume.html"
+ },
+ {
+ "path": "fetch/api/request/request-disturbed.html",
+ "url": "/fetch/api/request/request-disturbed.html"
+ },
+ {
+ "path": "fetch/api/request/request-error.html",
+ "url": "/fetch/api/request/request-error.html"
+ },
+ {
+ "path": "fetch/api/request/request-idl.html",
+ "url": "/fetch/api/request/request-idl.html"
+ },
+ {
+ "path": "fetch/api/request/request-init-001.sub.html",
+ "url": "/fetch/api/request/request-init-001.sub.html"
+ },
+ {
+ "path": "fetch/api/request/request-init-002.html",
+ "url": "/fetch/api/request/request-init-002.html"
+ },
+ {
+ "path": "fetch/api/request/request-init-003.sub.html",
+ "url": "/fetch/api/request/request-init-003.sub.html"
+ },
+ {
+ "path": "fetch/api/request/request-structure.html",
+ "url": "/fetch/api/request/request-structure.html"
+ },
+ {
+ "path": "fetch/api/response/response-clone.html",
+ "url": "/fetch/api/response/response-clone.html"
+ },
+ {
+ "path": "fetch/api/response/response-consume.html",
+ "url": "/fetch/api/response/response-consume.html"
+ },
+ {
+ "path": "fetch/api/response/response-error.html",
+ "url": "/fetch/api/response/response-error.html"
+ },
+ {
+ "path": "fetch/api/response/response-idl.html",
+ "url": "/fetch/api/response/response-idl.html"
+ },
+ {
+ "path": "fetch/api/response/response-init-001.html",
+ "url": "/fetch/api/response/response-init-001.html"
+ },
+ {
+ "path": "fetch/api/response/response-init-002.html",
+ "url": "/fetch/api/response/response-init-002.html"
+ },
+ {
+ "path": "fetch/api/response/response-static-error.html",
+ "url": "/fetch/api/response/response-static-error.html"
+ },
+ {
+ "path": "fetch/api/response/response-static-redirect.html",
+ "url": "/fetch/api/response/response-static-redirect.html"
+ },
{
"path": "fetch/nosniff/image.html",
"url": "/fetch/nosniff/image.html"
@@ -15691,6 +16055,10 @@
"path": "html/browsers/history/the-location-interface/location_href.html",
"url": "/html/browsers/history/the-location-interface/location_href.html"
},
+ {
+ "path": "html/browsers/history/the-location-interface/location_origin.html",
+ "url": "/html/browsers/history/the-location-interface/location_origin.html"
+ },
{
"path": "html/browsers/history/the-location-interface/location_pathname.html",
"url": "/html/browsers/history/the-location-interface/location_pathname.html"
@@ -18063,6 +18431,10 @@
"path": "html/semantics/embedded-content/the-embed-element/embed-dimension.html",
"url": "/html/semantics/embedded-content/the-embed-element/embed-dimension.html"
},
+ {
+ "path": "html/semantics/embedded-content/the-embed-element/embed-document.html",
+ "url": "/html/semantics/embedded-content/the-embed-element/embed-document.html"
+ },
{
"path": "html/semantics/embedded-content/the-iframe-element/iframe_javascript_url_01.htm",
"url": "/html/semantics/embedded-content/the-iframe-element/iframe_javascript_url_01.htm"
@@ -20867,10 +21239,6 @@
"path": "old-tests/submission/Microsoft/sandbox/sandbox_001.htm",
"url": "/old-tests/submission/Microsoft/sandbox/sandbox_001.htm"
},
- {
- "path": "old-tests/submission/Microsoft/sandbox/sandbox_002.htm",
- "url": "/old-tests/submission/Microsoft/sandbox/sandbox_002.htm"
- },
{
"path": "old-tests/submission/Microsoft/sandbox/sandbox_005.htm",
"url": "/old-tests/submission/Microsoft/sandbox/sandbox_005.htm"
@@ -30287,6 +30655,10 @@
"path": "websockets/Create-Secure-verify-url-set-non-default-port.htm",
"url": "/websockets/Create-Secure-verify-url-set-non-default-port.htm"
},
+ {
+ "path": "websockets/Create-asciiSep-protocol-string.htm",
+ "url": "/websockets/Create-asciiSep-protocol-string.htm"
+ },
{
"path": "websockets/Create-invalid-urls.htm",
"url": "/websockets/Create-invalid-urls.htm"
@@ -30303,6 +30675,10 @@
"path": "websockets/Create-protocol-with-space.htm",
"url": "/websockets/Create-protocol-with-space.htm"
},
+ {
+ "path": "websockets/Create-protocols-repeated-case-insensitive.htm",
+ "url": "/websockets/Create-protocols-repeated-case-insensitive.htm"
+ },
{
"path": "websockets/Create-protocols-repeated.htm",
"url": "/websockets/Create-protocols-repeated.htm"
@@ -33017,6 +33393,11 @@
"timeout": "long",
"url": "/media-source/mediasource-redundant-seek.html"
},
+ {
+ "path": "old-tests/submission/Microsoft/sandbox/sandbox_002.htm",
+ "timeout": "long",
+ "url": "/old-tests/submission/Microsoft/sandbox/sandbox_002.htm"
+ },
{
"path": "quirks-mode/hashless-hex-color.html",
"timeout": "long",
@@ -33332,22 +33713,7 @@
},
"local_changes": {
"deleted": [],
- "items": {
- "testharness": {
- "cssom-view/scrollingElement.html": [
- {
- "path": "cssom-view/scrollingElement.html",
- "url": "/cssom-view/scrollingElement.html"
- }
- ],
- "html/semantics/embedded-content/the-embed-element/embed-document.html": [
- {
- "path": "html/semantics/embedded-content/the-embed-element/embed-document.html",
- "url": "/html/semantics/embedded-content/the-embed-element/embed-document.html"
- }
- ]
- }
- },
+ "items": {},
"reftest_nodes": {}
},
"reftest_nodes": {
@@ -39460,7 +39826,7 @@
}
]
},
- "rev": "c41adf030ec80a62ef9e1988d3c4be460f2a0012",
+ "rev": "f3f87e1a2cc3845819038a8a6fe435bb6092e213",
"url_base": "/",
"version": 2
}
diff --git a/testing/web-platform/meta/mozilla-sync b/testing/web-platform/meta/mozilla-sync
index aa790901d5a..269ca479cd1 100644
--- a/testing/web-platform/meta/mozilla-sync
+++ b/testing/web-platform/meta/mozilla-sync
@@ -1 +1 @@
-82103213aaab9f39b722547a39be0de377dd9242
\ No newline at end of file
+a035c3724da7e8235c26a3b6ea567365efda3b15
\ No newline at end of file
diff --git a/testing/web-platform/tests/battery-status/OWNERS b/testing/web-platform/tests/battery-status/OWNERS
new file mode 100644
index 00000000000..eb86aa06933
--- /dev/null
+++ b/testing/web-platform/tests/battery-status/OWNERS
@@ -0,0 +1,3 @@
+@anssiko
+@dontcallmedom
+@zqzhang
diff --git a/testing/web-platform/tests/dom/nodes/attributes.html b/testing/web-platform/tests/dom/nodes/attributes.html
index e331389ff85..76a501c37ca 100644
--- a/testing/web-platform/tests/dom/nodes/attributes.html
+++ b/testing/web-platform/tests/dom/nodes/attributes.html
@@ -446,6 +446,26 @@ test(function() {
assert_equals(el2.getAttributeNS("x", "foo"), "bar");
}, "Basic functionality of setAttributeNodeNS")
+test(function() {
+ var el = document.createElement("div");
+ var other = document.createElement("div");
+ attr = document.createAttribute("foo");
+ assert_equals(el.setAttributeNode(attr), null);
+ assert_equals(attr.ownerElement, el);
+ assert_throws("INUSE_ATTRIBUTE_ERR",
+ function() { other.setAttributeNode(attr) },
+ "Attribute already associated with el")
+}, "If attr’s element is neither null nor element, throw an InUseAttributeError.");
+
+test(function() {
+ var el = document.createElement("div");
+ attr = document.createAttribute("foo");
+ assert_equals(el.setAttributeNode(attr), null);
+ el.setAttribute("bar", "qux");
+ assert_equals(el.setAttributeNode(attr), attr);
+ assert_equals(el.attributes[0], attr);
+}, "Replacing an attr by itself");
+
test(function() {
var el = document.createElement("div")
el.setAttribute("foo", "bar")
diff --git a/testing/web-platform/tests/fetch/api/basic/accept-header-worker.html b/testing/web-platform/tests/fetch/api/basic/accept-header-worker.html
new file mode 100644
index 00000000000..4d5b3220580
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/accept-header-worker.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch in worker: accept header
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/accept-header.html b/testing/web-platform/tests/fetch/api/basic/accept-header.html
new file mode 100644
index 00000000000..cd9550fb2cc
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/accept-header.html
@@ -0,0 +1,15 @@
+
+
+
+
+ Fetch: accept header
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/accept-header.js b/testing/web-platform/tests/fetch/api/basic/accept-header.js
new file mode 100644
index 00000000000..33226e8562a
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/accept-header.js
@@ -0,0 +1,14 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+promise_test(function() {
+ return fetch(RESOURCES_DIR + "inspect-headers.py?headers=Accept").then(function(response) {
+ assert_equals(response.status, 200, "HTTP status is 200");
+ assert_equals(response.type , "basic", "Response's type is basic");
+ assert_equals(response.headers.get("x-request-accept"), "*/*", "Request has accept header with value '*/*'");
+ });
+}, "Request through fetch should have 'accept' header with value '*/*'");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/basic/integrity-worker.html b/testing/web-platform/tests/fetch/api/basic/integrity-worker.html
new file mode 100644
index 00000000000..9240bc6325a
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/integrity-worker.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch in worker: integrity handling
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/integrity.html b/testing/web-platform/tests/fetch/api/basic/integrity.html
new file mode 100644
index 00000000000..150c9b71d54
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/integrity.html
@@ -0,0 +1,15 @@
+
+
+
+
+ Fetch: integrity handling
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/integrity.js b/testing/web-platform/tests/fetch/api/basic/integrity.js
new file mode 100644
index 00000000000..4e849f564e1
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/integrity.js
@@ -0,0 +1,45 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function integrity(desc, url, integrity, shouldPass) {
+ if (shouldPass) {
+ promise_test(function(test) {
+ return fetch(url, {'integrity': integrity}).then(function(resp) {
+ assert_equals(resp.status, 200, "Response's status is 200");
+ });
+ }, desc);
+ } else {
+ promise_test(function(test) {
+ return promise_rejects(test, new TypeError(), fetch(url, {'integrity': integrity}));
+ }, desc);
+ }
+}
+
+var topSha256 = "sha256-KHIDZcXnR2oBHk9DrAA+5fFiR6JjudYjqoXtMR1zvzk=";
+var topSha384 = "sha384-MgZYnnAzPM/MjhqfOIMfQK5qcFvGZsGLzx4Phd7/A8fHTqqLqXqKo8cNzY3xEPTL";
+var topSha512 = "sha512-D6yns0qxG0E7+TwkevZ4Jt5t7Iy3ugmAajG/dlf6Pado1JqTyneKXICDiqFIkLMRExgtvg8PlxbKTkYfRejSOg==";
+var invalidSha256 = "sha256-dKUcPOn/AlUjWIwcHeHNqYXPlvyGiq+2dWOdFcE+24I=";
+var invalidSha512 = "sha512-oUceBRNxPxnY60g/VtPCj2syT4wo4EZh2CgYdWy9veW8+OsReTXoh7dizMGZafvx9+QhMS39L/gIkxnPIn41Zg==";
+
+var url = "../resources/top.txt";
+var corsUrl = "http://www1.{{host}}:{{ports[http][0]}}" + dirname(location.pathname) + RESOURCES_DIR + "top.txt";
+/* Enable CORS*/
+corsUrl += "?pipe=header(Access-Control-Allow-Origin,*)";
+
+integrity("Empty string integrity", url, "", true);
+integrity("SHA-256 integrity", url, topSha256, true);
+integrity("SHA-384 integrity", url, topSha384, true);
+integrity("SHA-512 integrity", url, topSha512, true);
+integrity("Invalid integrity", url, invalidSha256, false);
+integrity("Multiple integrities: valid stronger than invalid", url, invalidSha256 + " " + topSha384, true);
+integrity("Multiple integrities: invalid stronger than valid", url, invalidSha512 + " " + topSha384, false);
+integrity("Multiple integrities: invalid as strong as valid", url, invalidSha512 + " " + topSha512, true);
+integrity("Multiple integrities: both are valid", url, topSha384 + " " + topSha512, true);
+integrity("Multiple integrities: both are invalid", url, invalidSha256 + " " + invalidSha512, false);
+integrity("CORS empty integrity", corsUrl, "", true);
+integrity("CORS SHA-512 integrity", corsUrl, topSha512, true);
+integrity("CORS invalid integrity", corsUrl, invalidSha512, false);
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/basic/mode-no-cors-worker.html b/testing/web-platform/tests/fetch/api/basic/mode-no-cors-worker.html
new file mode 100644
index 00000000000..87376a130f8
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/mode-no-cors-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: no-cors mode and opaque filtering
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/mode-no-cors.html b/testing/web-platform/tests/fetch/api/basic/mode-no-cors.html
new file mode 100644
index 00000000000..7aee3790933
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/mode-no-cors.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch: no-cors mode and opaque filtering
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/mode-no-cors.js b/testing/web-platform/tests/fetch/api/basic/mode-no-cors.js
new file mode 100644
index 00000000000..27483654f74
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/mode-no-cors.js
@@ -0,0 +1,31 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function fetchNoCors(url, isOpaqueFiltered) {
+ var urlQuery = "?pipe=header(x-is-filtered,value)"
+ promise_test(function(test) {
+ if (isOpaqueFiltered)
+ return fetch(url + urlQuery, {"mode": "no-cors"}).then(function(resp) {
+ assert_equals(resp.status, 0, "Opaque filter: status is 0");
+ assert_equals(resp.statusText, "", "Opaque filter: statusText is \"\"");
+ assert_equals(resp.type , "opaque", "Opaque filter: response's type is opaque");
+ assert_equals(resp.headers.get("x-is-filtered"), null, "Header x-is-filtered is filtered");
+ });
+ else
+ return fetch(url + urlQuery, {"mode": "no-cors"}).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_equals(resp.type , "basic", "Response's type is basic");
+ assert_equals(resp.headers.get("x-is-filtered"), "value", "Header x-is-filtered is not filtered");
+ });
+ }, "Fetch "+ url + " with no-cors mode");
+}
+
+fetchNoCors(RESOURCES_DIR + "top.txt", false);
+fetchNoCors("http://{{host}}:{{ports[http][0]}}/fetch/api/resources/top.txt", false);
+fetchNoCors("https://{{host}}:{{ports[https][0]}}/fetch/api/resources/top.txt", true);
+fetchNoCors("http://{{domains[www]}}:{{ports[http][0]}}/fetch/api/resources/top.txt", true);
+
+done();
+
diff --git a/testing/web-platform/tests/fetch/api/basic/mode-same-origin-worker.html b/testing/web-platform/tests/fetch/api/basic/mode-same-origin-worker.html
new file mode 100644
index 00000000000..0c62472aaf1
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/mode-same-origin-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: same-origin mode
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/mode-same-origin.html b/testing/web-platform/tests/fetch/api/basic/mode-same-origin.html
new file mode 100644
index 00000000000..d94832a2aa0
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/mode-same-origin.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch: same-origin mode
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/mode-same-origin.js b/testing/web-platform/tests/fetch/api/basic/mode-same-origin.js
new file mode 100644
index 00000000000..c00d96fad32
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/mode-same-origin.js
@@ -0,0 +1,24 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function fetchSameOrigin(url, shouldPass) {
+ promise_test(function(test) {
+ if (shouldPass)
+ return fetch(url , {"mode": "same-origin"}).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_equals(resp.type, "basic", "response type is basic");
+ });
+ else
+ return promise_rejects(test, new TypeError, fetch(url, {mode: "same-origin"}));
+ }, "Fetch "+ url + " with same-origin mode");
+}
+
+fetchSameOrigin(RESOURCES_DIR + "top.txt", true);
+fetchSameOrigin("http://{{host}}:{{ports[http][0]}}/fetch/api/resources/top.txt", true);
+fetchSameOrigin("https://{{host}}:{{ports[https][0]}}/fetch/api/resources/top.txt", false);
+fetchSameOrigin("http://{{domains[www]}}:{{ports[http][0]}}/fetch/api/resources/top.txt", false);
+
+done();
+
diff --git a/testing/web-platform/tests/fetch/api/basic/request-forbidden-headers-worker.html b/testing/web-platform/tests/fetch/api/basic/request-forbidden-headers-worker.html
new file mode 100644
index 00000000000..12e87f9e4c6
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/request-forbidden-headers-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: forbidden request header management
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/request-forbidden-headers.html b/testing/web-platform/tests/fetch/api/basic/request-forbidden-headers.html
new file mode 100644
index 00000000000..56ce2a65b11
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/request-forbidden-headers.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch: forbidden request header management
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/request-forbidden-headers.js b/testing/web-platform/tests/fetch/api/basic/request-forbidden-headers.js
new file mode 100644
index 00000000000..72a8392a54f
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/request-forbidden-headers.js
@@ -0,0 +1,48 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function requestForbiddenHeaders(desc, forbiddenHeaders) {
+ var url = RESOURCES_DIR + "inspect-headers.py";
+ var requestInit = {"headers": forbiddenHeaders}
+ var urlParameters = "?headers=" + Object.keys(forbiddenHeaders).join("|");
+
+ promise_test(function(test){
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_equals(resp.type , "basic", "Response's type is basic");
+ for (var header in forbiddenHeaders)
+ assert_not_equals(resp.headers.get("x-request-" + header), forbiddenHeaders[header], header + " does not have the value we defined");
+ });
+ }, desc);
+}
+
+requestForbiddenHeaders("Accept-Charset is a forbidden request header", {"Accept-Charset": "utf-8"});
+requestForbiddenHeaders("Accept-Encoding is a forbidden request header", {"Accept-Encoding": ""});
+
+requestForbiddenHeaders("Access-Control-Request-Headers is a forbidden request header", {"Access-Control-Request-Headers": ""});
+requestForbiddenHeaders("Access-Control-Request-Method is a forbidden request header", {"Access-Control-Request-Method": ""});
+requestForbiddenHeaders("Connection is a forbidden request header", {"Connection": "close"});
+requestForbiddenHeaders("Content-Length is a forbidden request header", {"Content-Length": "42"});
+requestForbiddenHeaders("Cookie is a forbidden request header", {"Cookie": "cookie=none"});
+requestForbiddenHeaders("Cookie2 is a forbidden request header", {"Cookie2": "cookie2=none"});
+requestForbiddenHeaders("Date is a forbidden request header", {"Date": "Wed, 04 May 1988 22:22:22 GMT"});
+requestForbiddenHeaders("DNT is a forbidden request header", {"DNT": "4"});
+requestForbiddenHeaders("Expect is a forbidden request header", {"Expect": "100-continue"});
+requestForbiddenHeaders("Host is a forbidden request header", {"Host": "http://wrong-host.com"});
+requestForbiddenHeaders("Keep-Alive is a forbidden request header", {"Keep-Alive": "timeout=15"});
+requestForbiddenHeaders("Origin is a forbidden request header", {"Origin": "http://wrong-origin.com"});
+requestForbiddenHeaders("Referer is a forbidden request header", {"Referer": "http://wrong-referer.com"});
+requestForbiddenHeaders("TE is a forbidden request header", {"TE": "trailers"});
+requestForbiddenHeaders("Trailer is a forbidden request header", {"Trailer": "Accept"});
+requestForbiddenHeaders("Transfer-Encoding is a forbidden request header", {"Transfer-Encoding": "chunked"});
+requestForbiddenHeaders("Upgrade is a forbidden request header", {"Upgrade": "HTTP/2.0"});
+requestForbiddenHeaders("Via is a forbidden request header", {"Via": "1.1 nowhere.com"});
+requestForbiddenHeaders("Proxy- is a forbidden request header", {"Proxy-": "value"});
+requestForbiddenHeaders("Proxy-Test is a forbidden request header", {"Proxy-Test": "value"});
+requestForbiddenHeaders("Sec- is a forbidden request header", {"Sec-": "value"});
+requestForbiddenHeaders("Sec-Test is a forbidden request header", {"Sec-Test": "value"});
+
+done();
+
diff --git a/testing/web-platform/tests/fetch/api/basic/request-headers-worker.html b/testing/web-platform/tests/fetch/api/basic/request-headers-worker.html
new file mode 100644
index 00000000000..85b4c4c7084
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/request-headers-worker.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch in worker: User agent add headers to request
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/request-headers.html b/testing/web-platform/tests/fetch/api/basic/request-headers.html
new file mode 100644
index 00000000000..5236d29b107
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/request-headers.html
@@ -0,0 +1,15 @@
+
+
+
+
+ Fetch: User agent add headers to request
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/request-headers.js b/testing/web-platform/tests/fetch/api/basic/request-headers.js
new file mode 100644
index 00000000000..ec14385b606
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/request-headers.js
@@ -0,0 +1,35 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function requestHeaders(desc, url, method, body, expectedOrigin, expectedContentLength) {
+ var urlParameters = "?headers=origin|user-agent|accept-charset|content-length";
+ var requestInit = {"method": method}
+ if (body)
+ requestInit["body"] = body;
+ promise_test(function(test){
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_equals(resp.type , "basic", "Response's type is basic");
+ assert_equals(resp.headers.get("x-request-origin") , expectedOrigin, "Request has header origin: " + expectedOrigin);
+ assert_equals(resp.headers.get("x-request-content-length") , expectedContentLength, "Request has header content-length: " + expectedContentLength);
+ assert_true(resp.headers.has("x-request-user-agent"), "Request has header user-agent");
+ assert_false(resp.headers.has("accept-charset"), "Request has header accept-charset");
+ });
+ }, desc);
+}
+
+var url = RESOURCES_DIR + "inspect-headers.py"
+
+requestHeaders("Fetch with GET", url, "GET", null, location.origin, null);
+requestHeaders("Fetch with HEAD", url, "HEAD", null, location.origin, "0");
+requestHeaders("Fetch with HEAD with body", url, "HEAD", "Request's body", location.origin, "14");
+requestHeaders("Fetch with PUT without body", url, "POST", null, location.origin, "0");
+requestHeaders("Fetch with PUT with body", url, "PUT", "Request's body", location.origin, "14");
+requestHeaders("Fetch with POST without body", url, "POST", null, location.origin, "0");
+requestHeaders("Fetch with POST with body", url, "POST", "Request's body", location.origin, "14");
+requestHeaders("Fetch with Chicken", url, "Chicken", null, location.origin, null);
+requestHeaders("Fetch with Chicken with body", url, "Chicken", "Request's body", location.origin, "14");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/basic/scheme-about-worker.html b/testing/web-platform/tests/fetch/api/basic/scheme-about-worker.html
new file mode 100644
index 00000000000..9c9d9a038a9
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/scheme-about-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: about scheme
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/scheme-about.html b/testing/web-platform/tests/fetch/api/basic/scheme-about.html
new file mode 100644
index 00000000000..8b6df24682f
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/scheme-about.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch: about scheme
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/scheme-about.js b/testing/web-platform/tests/fetch/api/basic/scheme-about.js
new file mode 100644
index 00000000000..5f3e7cfd5c5
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/scheme-about.js
@@ -0,0 +1,40 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+var unicorn = '';
+
+function checkFetchResponse(url, data, mime, desc) {
+ if (!desc) {
+ var cut = (url.length >= 45) ? "[...]" : "";
+ desc = "Fetching " + url.substring(0, 45) + cut + " is OK"
+ }
+ promise_test(function(test) {
+ return fetch(url).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_equals(resp.type, "basic", "response type is basic");
+ assert_equals(resp.headers.get("Content-Type"), mime, "Content-Type is " + resp.headers.get("Content-Type"));
+ return resp.text();
+ }).then(function(bodyAsText) {
+ assert_equals(bodyAsText, data, "Response's body is " + data);
+ })
+ }, desc);
+}
+
+checkFetchResponse("about:blank", "", "text/html;charset=utf-8");
+checkFetchResponse("about:unicorn", unicorn, "image/svg+xml");
+
+function checkKoUrl(url, desc) {
+ if (!desc)
+ desc = "Fetching " + url.substring(0, 45) + " is KO"
+ promise_test(function(test) {
+ var promise = fetch(url);
+ return promise_rejects(test, new TypeError(), promise);
+ }, desc);
+}
+
+checkKoUrl("about:invalid.com");
+checkKoUrl("about:config");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/basic/scheme-blob-worker.html b/testing/web-platform/tests/fetch/api/basic/scheme-blob-worker.html
new file mode 100644
index 00000000000..961ecbd525b
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/scheme-blob-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: blob scheme
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/scheme-blob.html b/testing/web-platform/tests/fetch/api/basic/scheme-blob.html
new file mode 100644
index 00000000000..7787c3710f6
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/scheme-blob.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch: blob scheme
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/scheme-blob.js b/testing/web-platform/tests/fetch/api/basic/scheme-blob.js
new file mode 100644
index 00000000000..d9b804d4e58
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/scheme-blob.js
@@ -0,0 +1,41 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function checkFetchResponse(url, data, mime, size, desc) {
+ if (!desc)
+ var cut = (url.length >= 45) ? "[...]" : "";
+ desc = "Fetching " + url.substring(0, 45) + cut + " is OK"
+ promise_test(function(test) {
+ size = size.toString();
+ return fetch(url).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_equals(resp.type, "basic", "response type is basic");
+ assert_equals(resp.headers.get("Content-Type"), mime, "Content-Type is " + resp.headers.get("Content-Type"));
+ assert_equals(resp.headers.get("Content-Length"), size, "Content-Length is " + resp.headers.get("Content-Length"));
+ return resp.text();
+ }).then(function(bodyAsText) {
+ assert_equals(bodyAsText, data, "Response's body is " + data);
+ })
+ }, desc);
+}
+
+var blob = new Blob(["Blob's data"], { "type" : "text/plain" });
+checkFetchResponse(URL.createObjectURL(blob), "Blob's data", "text/plain", blob.size);
+
+function checkKoUrl(url, method, desc) {
+ if (!desc)
+ var cut = (url.length >= 45) ? "[...]" : "";
+ desc = "Fetching [" + method + "] " + url.substring(0, 45) + cut + " is KO"
+ promise_test(function(test) {
+ var promise = fetch(url, {"method": method});
+ return promise_rejects(test, new TypeError(), promise);
+ }, desc);
+}
+
+var blob2 = new Blob(["Blob's data"], { "type" : "text/plain" });
+checkKoUrl("blob:http://{{domains[www]}}:{{ports[http][0]}}/", "GET");
+checkKoUrl(URL.createObjectURL(blob2), "POST");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/basic/scheme-data-worker.html b/testing/web-platform/tests/fetch/api/basic/scheme-data-worker.html
new file mode 100644
index 00000000000..42fc3f4a9c0
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/scheme-data-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: data scheme
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/scheme-data.html b/testing/web-platform/tests/fetch/api/basic/scheme-data.html
new file mode 100644
index 00000000000..0b41991c9fc
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/scheme-data.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch: data scheme
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/scheme-data.js b/testing/web-platform/tests/fetch/api/basic/scheme-data.js
new file mode 100644
index 00000000000..775466799cd
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/scheme-data.js
@@ -0,0 +1,39 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function checkFetchResponse(url, data, mime) {
+ var cut = (url.length >= 40) ? "[...]" : "";
+ desc = "Fetching " + url.substring(0, 40) + cut + " is OK"
+ promise_test(function(test) {
+ return fetch(url).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_equals(resp.type, "basic", "response type is basic");
+ assert_equals(resp.headers.get("Content-Type"), mime, "Content-Type is " + resp.headers.get("Content-Type"));
+ return resp.text();
+ }).then(function(body) {
+ assert_equals(body, data, "Response's body is correct");
+ });
+ }, desc);
+}
+
+checkFetchResponse("data:,response%27s%20body", "response's body", "text/plain;charset=US-ASCII");
+checkFetchResponse("data:text/plain;base64,cmVzcG9uc2UncyBib2R5", "response's body", "text/plain");
+checkFetchResponse("data:image/png;base64,cmVzcG9uc2UncyBib2R5",
+ "response's body",
+ "image/png");
+
+function checkKoUrl(url, method, desc) {
+ var cut = (url.length >= 40) ? "[...]" : "";
+ desc = "Fetching [" + method + "] " + url.substring(0, 45) + cut + " is KO"
+ promise_test(function(test) {
+ return promise_rejects(test, new TypeError(), fetch(url, {"method": method}));
+ }, desc);
+}
+
+checkKoUrl("data:notAdataUrl.com", "GET");
+checkKoUrl("data:,response%27s%20body", "POST");
+checkKoUrl("data:,response%27s%20body", "HEAD");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/basic/scheme-others-worker.html b/testing/web-platform/tests/fetch/api/basic/scheme-others-worker.html
new file mode 100644
index 00000000000..397d9257b1b
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/scheme-others-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: urls with unsupported schemes
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/scheme-others.html b/testing/web-platform/tests/fetch/api/basic/scheme-others.html
new file mode 100644
index 00000000000..dd37143b0f1
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/scheme-others.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch: urls with unsupported schemes
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/scheme-others.js b/testing/web-platform/tests/fetch/api/basic/scheme-others.js
new file mode 100644
index 00000000000..ce02ec1340a
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/scheme-others.js
@@ -0,0 +1,33 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function checkKoUrl(url, desc) {
+ if (!desc)
+ desc = "Fetching " + url.substring(0, 45) + " is KO"
+ promise_test(function(test) {
+ var promise = fetch(url);
+ return promise_rejects(test, new TypeError(), promise);
+ }, desc);
+}
+
+var urlWithoutScheme = "://{{host}}:{{ports[http][0]}}/";
+checkKoUrl("aaa" + urlWithoutScheme);
+checkKoUrl("cap" + urlWithoutScheme);
+checkKoUrl("cid" + urlWithoutScheme);
+checkKoUrl("dav" + urlWithoutScheme);
+checkKoUrl("dict" + urlWithoutScheme);
+checkKoUrl("dns" + urlWithoutScheme);
+checkKoUrl("geo" + urlWithoutScheme);
+checkKoUrl("im" + urlWithoutScheme);
+checkKoUrl("imap" + urlWithoutScheme);
+checkKoUrl("ipp" + urlWithoutScheme);
+checkKoUrl("ldap" + urlWithoutScheme);
+checkKoUrl("mailto" + urlWithoutScheme);
+checkKoUrl("nfs" + urlWithoutScheme);
+checkKoUrl("pop" + urlWithoutScheme);
+checkKoUrl("rtsp" + urlWithoutScheme);
+checkKoUrl("snmp" + urlWithoutScheme);
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/basic/stream-response-worker.html b/testing/web-platform/tests/fetch/api/basic/stream-response-worker.html
new file mode 100644
index 00000000000..0be1c0d13f1
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/stream-response-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: retrieve response's body progressively
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/stream-response.html b/testing/web-platform/tests/fetch/api/basic/stream-response.html
new file mode 100644
index 00000000000..eb6b1415a1f
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/stream-response.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch: retrieve response's body progressively
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/basic/stream-response.js b/testing/web-platform/tests/fetch/api/basic/stream-response.js
new file mode 100644
index 00000000000..ea370bc7cdf
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/basic/stream-response.js
@@ -0,0 +1,37 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function streamBody(reader, test, count) {
+ return reader.read().then(function(data) {
+ if (!data.done && count < 2) {
+ count += 1;
+ return streamBody(reader, test, count);
+ } else {
+ test.step(function() {
+ assert_true(count >= 2, "Retrieve body progressively");
+ test.done();
+ return;
+ });
+ }
+ });
+}
+
+//simulate streaming:
+//count is large enough to let the UA deliver the body before it is completely retrieved
+async_test(function(test) {
+ fetch(RESOURCES_DIR + "trickle.py?ms=30&count=100").then(function(resp) {
+ var count = 0;
+ if (resp.body)
+ return streamBody(resp.body.getReader(), test, count);
+ else
+ test.step(function() {
+ assert_unreached( "Body does not exist in response");
+ test.done();
+ return;
+ });
+ });
+}, "Stream response's body");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-basic-worker.html b/testing/web-platform/tests/fetch/api/cors/cors-basic-worker.html
new file mode 100644
index 00000000000..97e173c1522
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-basic-worker.html
@@ -0,0 +1,19 @@
+
+
+
+
+ Fetch in worker: basic CORS
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-basic.html b/testing/web-platform/tests/fetch/api/cors/cors-basic.html
new file mode 100644
index 00000000000..4aa38f75b85
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-basic.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Fetch: basic CORS
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-basic.js b/testing/web-platform/tests/fetch/api/cors/cors-basic.js
new file mode 100644
index 00000000000..3fe4644db14
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-basic.js
@@ -0,0 +1,45 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function cors(desc, scheme, subdomain, port) {
+ if (!port)
+ port = location.port;
+ if (subdomain)
+ subdomain = subdomain + ".";
+ else
+ subdomain = "";
+
+ var url = scheme + "://" + subdomain + "{{host}}" + ":" + port + dirname(location.pathname);
+ var urlParameters = "?pipe=header(Access-Control-Allow-Origin,*)";
+
+ promise_test(function(test) {
+ return fetch(url + RESOURCES_DIR + "top.txt" + urlParameters, {"mode": "no-cors"} ).then(function(resp) {
+ assert_equals(resp.status, 0, "Opaque filter: status is 0");
+ assert_equals(resp.statusText, "", "Opaque filter: statusText is \"\"");
+ assert_equals(resp.type , "opaque", "Opaque filter: response's type is opaque");
+ });
+ }, desc + " [no-cors mode]");
+
+ promise_test(function(test) {
+ var testedPromise = fetch(url + RESOURCES_DIR + "top.txt", {"mode": "cors"} ).then(function(resp) {
+ return promise_rejects(test, new TypeError(), testedPromise);
+ });
+ }, desc + " [server forbid CORS]");
+
+ promise_test(function(test) {
+ return fetch(url + RESOURCES_DIR + "top.txt" + urlParameters, {"mode": "cors"} ).then(function(resp) {
+ assert_equals(resp.status, 200, "Fetch's response's status is 200");
+ assert_equals(resp.type , "cors", "CORS response's type is cors");
+ });
+ }, desc + " [cors mode]");
+}
+
+cors("Cross domain basic usage", "http", "www1");
+cors("Same domain different port", "http", undefined, "{{ports[http][1]}}");
+cors("Cross domain different port", "http", "www1", "{{ports[http][1]}}");
+cors("Cross domain different protocol", "https", "www1", "{{ports[https][0]}}");
+cors("Same domain different protocol different port", "https", undefined, "{{ports[https][0]}}");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-cookies-worker.html b/testing/web-platform/tests/fetch/api/cors/cors-cookies-worker.html
new file mode 100644
index 00000000000..fd79aad8f05
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-cookies-worker.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Fetch in worker: cookies management for cors requests
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-cookies.html b/testing/web-platform/tests/fetch/api/cors/cors-cookies.html
new file mode 100644
index 00000000000..8fb6a7c0cd7
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-cookies.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch: cookies management for cors requests
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-cookies.js b/testing/web-platform/tests/fetch/api/cors/cors-cookies.js
new file mode 100644
index 00000000000..d79dc84860d
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-cookies.js
@@ -0,0 +1,58 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function corsCookies(desc, domain1, domain2, credentialsMode, cookies) {
+ var urlSetCookie = "http://" + domain1 + ":{{ports[http][0]}}" + dirname(location.pathname) + RESOURCES_DIR + "top.txt";
+ var urlCheckCookies = "http://" + domain2 + ":{{ports[http][0]}}" + dirname(location.pathname) + RESOURCES_DIR + "inspect-headers.py?cors&headers=cookie";
+ //enable cors with credentials
+ var urlParameters = "?pipe=header(Access-Control-Allow-Origin," + location.origin + ")";
+ urlParameters += "|header(Access-Control-Allow-Credentials,true)";
+
+ var urlCleanParameters = "?pipe=header(Access-Control-Allow-Origin," + location.origin + ")";
+ urlCleanParameters += "|header(Access-Control-Allow-Credentials,true)";
+ if (cookies) {
+ urlParameters += "|header(Set-Cookie,";
+ urlParameters += cookies.join(",True)|header(Set-Cookie,") + ",True)";
+ urlCleanParameters += "|header(Set-Cookie,";
+ urlCleanParameters += cookies.join("%3B%20max-age=0,True)|header(Set-Cookie,") + "%3B%20max-age=0,True)";
+ }
+
+ var requestInit = {"credentials": credentialsMode, "mode": "cors"};
+
+ promise_test(function(test){
+ return fetch(urlSetCookie + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ //check cookies sent
+ return fetch(urlCheckCookies, requestInit);
+ }).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_false(resp.headers.has("Cookie") , "Cookie header is not exposed in response");
+ if (credentialsMode === "include" && domain1 === domain2) {
+ assert_equals(resp.headers.get("x-request-cookie") , cookies.join("; "), "Request includes cookie(s)");
+ }
+ else {
+ assert_false(resp.headers.has("x-request-cookie") , "Request should have no cookie");
+ }
+ //clean cookies
+ return fetch(urlSetCookie + urlCleanParameters, {"credentials": "include"});
+ }).catch(function(e) {
+ fetch(urlSetCookie + urlCleanParameters, {"credentials": "include"});
+ throw e;
+ });
+ }, desc);
+}
+
+var local = "{{host}}";
+var remote = "www.{{host}}";
+var remote1 = "www1.{{host}}";
+
+corsCookies("Include mode: 1 cookie", remote, remote, "include", ["a=1"]);
+corsCookies("Include mode: local cookies are not sent with remote request", local, remote, "include", ["c=3"]);
+corsCookies("Include mode: remote cookies are not sent with local request", remote, local, "include", ["d=4"]);
+corsCookies("Include mode: remote cookies are not sent with other remote request", remote, remote1, "include", ["e=5"]);
+corsCookies("Same-origin mode: cookies are discarded in cors request", remote, remote, "same-origin", ["f=6"]);
+corsCookies("Omit mode: no cookie sent", local, local, "omit", ["g=7"]);
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-filtering-worker.html b/testing/web-platform/tests/fetch/api/cors/cors-filtering-worker.html
new file mode 100644
index 00000000000..f15566fc509
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-filtering-worker.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Fetch in worker: filtered headers in CORS response
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-filtering.html b/testing/web-platform/tests/fetch/api/cors/cors-filtering.html
new file mode 100644
index 00000000000..b7500ad16d4
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-filtering.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch: filtered headers in CORS response
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-filtering.js b/testing/web-platform/tests/fetch/api/cors/cors-filtering.js
new file mode 100644
index 00000000000..aa21070f394
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-filtering.js
@@ -0,0 +1,66 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function corsFilter(corsUrl, headerName, headerValue, isFiltered) {
+ var url = corsUrl + "?pipe=header(" + headerName + "," + encodeURIComponent(headerValue) +")|header(Access-Control-Allow-Origin,*)";
+ promise_test(function(test) {
+ return fetch(url).then(function(resp) {
+ assert_equals(resp.status, 200, "Fetch success with code 200");
+ assert_equals(resp.type , "cors", "CORS fetch's response has cors type");
+ if (!isFiltered) {
+ assert_equals(resp.headers.get(headerName), headerValue,
+ headerName + " header should be included in response with value: " + headerValue);
+ } else {
+ assert_false(resp.headers.has(headerName), "UA should exclude " + headerName + " header from response");
+ }
+ test.done();
+ });
+ }, "CORS filter on " + headerName + " header");
+}
+
+function corsExposeFilter(corsUrl, headerName, headerValue, isForbidden) {
+ var url = corsUrl + "?pipe=header(" + headerName + "," + encodeURIComponent(headerValue) +")|" +
+ "header(Access-Control-Allow-Origin,*)" +
+ "header(Access-Control-Expose-Headers," + headerName + ")";
+
+ promise_test(function(test) {
+ return fetch(url).then(function(resp) {
+ assert_equals(resp.status, 200, "Fetch success with code 200");
+ assert_equals(resp.type , "cors", "CORS fetch's response has cors type");
+ if (!isForbidden) {
+ assert_equals(resp.headers.get(headerName), headerValue,
+ headerName + " header should be included in response with value: " + headerValue);
+ } else {
+ assert_false(resp.headers.has(headerName), "UA should exclude " + headerName + " header from response");
+ }
+ test.done();
+ });
+ }, "CORS filter on " + headerName + " header, header is exposed");
+}
+
+var url = "http://www1.{{host}}:{{ports[http][1]}}" + dirname(location.pathname) + RESOURCES_DIR + "top.txt";
+
+corsFilter(url, "Cache-Control", "no-cache", false);
+corsFilter(url, "Content-Language", "fr", false);
+corsFilter(url, "Content-Type", "text/html", false);
+corsFilter(url, "Expires","04 May 1988 22:22:22 GMT" , false);
+corsFilter(url, "Last-Modified", "04 May 1988 22:22:22 GMT", false);
+corsFilter(url, "Pragma", "no-cache", false);
+
+corsFilter(url, "Age", "27", true);
+corsFilter(url, "Server", "wptServe" , true);
+corsFilter(url, "Warning", "Mind the gap" , true);
+corsFilter(url, "Content-Length", "0" , true);
+corsFilter(url, "Set-Cookie", "name=value" , true);
+corsFilter(url, "Set-Cookie2", "name=value" , true);
+
+corsExposeFilter(url, "Age", "27", false);
+corsExposeFilter(url, "Server", "wptServe" , false);
+corsExposeFilter(url, "Warning", "Mind the gap" , false);
+corsExposeFilter(url, "Content-Length", "0" , false);
+corsExposeFilter(url, "Set-Cookie", "name=value" , true);
+corsExposeFilter(url, "Set-Cookie2", "name=value" , true);
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-multiple-origins-worker.html b/testing/web-platform/tests/fetch/api/cors/cors-multiple-origins-worker.html
new file mode 100644
index 00000000000..a8e50573278
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-multiple-origins-worker.html
@@ -0,0 +1,19 @@
+
+
+
+
+ Fetch in worker: check multiple Access-Control-Allow-Origin header management
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-multiple-origins.html b/testing/web-platform/tests/fetch/api/cors/cors-multiple-origins.html
new file mode 100644
index 00000000000..9b12b05064b
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-multiple-origins.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Fetch: check multiple Access-Control-Allow-Origin header management
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-multiple-origins.js b/testing/web-platform/tests/fetch/api/cors/cors-multiple-origins.js
new file mode 100644
index 00000000000..35c404b7770
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-multiple-origins.js
@@ -0,0 +1,32 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function corsMultipleOrigins(desc, originList, shouldPass) {
+ var urlParameters = "?origin=" + encodeURIComponent(originList.join(", "));
+ var url = "http://www1.{{host}}:{{ports[http][0]}}" + dirname(location.pathname) + RESOURCES_DIR + "preflight.py";
+
+ if (shouldPass) {
+ promise_test(function(test) {
+ return fetch(url + urlParameters).then(function(resp) {
+ assert_equals(resp.status, 200, "Response's status is 200");
+ });
+ }, desc);
+ } else {
+ promise_test(function(test) {
+ return promise_rejects(test, new TypeError(), fetch(url + urlParameters));
+ }, desc);
+ }
+}
+/* Actual origin */
+var origin = "http://{{host}}:{{ports[http][0]}}";
+
+corsMultipleOrigins("3 origins allowed, match the 3rd (" + origin + ")", ["\"\"", "http://example.com", origin], true);
+corsMultipleOrigins("3 origins allowed, match the 3rd (\"*\")", ["\"\"", "http://example.com", "*"], true);
+corsMultipleOrigins("3 origins allowed, match twice (" + origin + ")", ["\"\"", origin, origin], true);
+corsMultipleOrigins("3 origins allowed, match twice (\"*\")", ["*", "http://example.com", "*"], true);
+corsMultipleOrigins("3 origins allowed, match twice (\"*\" and " + origin + ")", ["*", "http://example.com", origin], true);
+corsMultipleOrigins("3 origins allowed, no match", ["", "http://example.com", "https://example2.com"], false);
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-no-preflight-worker.html b/testing/web-platform/tests/fetch/api/cors/cors-no-preflight-worker.html
new file mode 100644
index 00000000000..c6402ada093
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-no-preflight-worker.html
@@ -0,0 +1,20 @@
+
+
+
+
+ Fetch in worker: CORS request with simple methods and headers
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-no-preflight.html b/testing/web-platform/tests/fetch/api/cors/cors-no-preflight.html
new file mode 100644
index 00000000000..3ff5c97eac6
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-no-preflight.html
@@ -0,0 +1,20 @@
+
+
+
+
+ Fetch: CORS request with simple methods and headers
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-no-preflight.js b/testing/web-platform/tests/fetch/api/cors/cors-no-preflight.js
new file mode 100644
index 00000000000..8d932cc38bc
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-no-preflight.js
@@ -0,0 +1,50 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("/common/utils.js");
+ importScripts("../resources/utils.js");
+}
+
+function corsNoPreflight(desc, scheme, subdomain, port, method, headerName, headerValue) {
+ if (!port)
+ port = location.port;
+ if (subdomain)
+ subdomain = subdomain + ".";
+ else
+ subdomain = "";
+
+ var uuid_token = token();
+ var url = scheme + "://" + subdomain + "{{host}}" + ":" + port + dirname(location.pathname) + RESOURCES_DIR + "preflight.py";
+ var urlParameters = "?token=" + uuid_token + "&max_age=0";
+ var requestInit = {"mode": "cors", "method": method, "headers":{}};
+ if (headerName)
+ requestInit["headers"][headerName] = headerValue;
+
+ promise_test(function(test) {
+ fetch(RESOURCES_DIR + "clean-stash.py?token=" + uuid_token).then(function(resp) {
+ assert_equals(resp.status, 200, "Clean stash response's status is 200");
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 200, "Response's status is 200");
+ assert_equals(resp.headers.get("x-did-preflight"), "0", "No preflight request has been made");
+ });
+ });
+ }, desc);
+}
+var port2 = "{{ports[http][1]}}";
+var httpsPort = "{{ports[https][0]}}";
+
+corsNoPreflight("Cross domain basic usage [GET]", "http", "www1", undefined, "GET");
+corsNoPreflight("Same domain different port [GET]", "http", undefined, port2, "GET");
+corsNoPreflight("Cross domain different port [GET]", "http", "www1", port2, "GET");
+corsNoPreflight("Cross domain different protocol [GET]", "https", "www1", httpsPort, "GET");
+corsNoPreflight("Same domain different protocol different port [GET]", "https", undefined, httpsPort, "GET");
+corsNoPreflight("Cross domain [POST]", "http", "www1", undefined, "POST");
+corsNoPreflight("Cross domain [HEAD]", "http", "www1", undefined, "HEAD");
+corsNoPreflight("Cross domain [GET] [Accept: */*]", "http", "www1", undefined, "GET" , "Accept", "*/*");
+corsNoPreflight("Cross domain [GET] [Accept-Language: fr]", "http", "www1", undefined, "GET" , "Accept-Language", "fr");
+corsNoPreflight("Cross domain [GET] [Content-Language: fr]", "http", "www1", undefined, "GET" , "Content-Language", "fr");
+corsNoPreflight("Cross domain [GET] [Content-Type: application/x-www-form-urlencoded]", "http", "www1", undefined, "GET" , "Content-Type", "application/x-www-form-urlencoded");
+corsNoPreflight("Cross domain [GET] [Content-Type: multipart/form-data]", "http", "www1", undefined, "GET" , "Content-Type", "multipart/form-data");
+corsNoPreflight("Cross domain [GET] [Content-Type: text/plain]", "http", "www1", undefined, "GET" , "Content-Type", "text/plain");
+corsNoPreflight("Cross domain [GET] [Content-Type: text/plain;charset=utf-8]", "http", "www1", undefined, "GET" , "Content-Type", "text/plain;charset=utf-8");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-origin-worker.html b/testing/web-platform/tests/fetch/api/cors/cors-origin-worker.html
new file mode 100644
index 00000000000..f6145e6e3e1
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-origin-worker.html
@@ -0,0 +1,19 @@
+
+
+
+
+ Fetch in worker: check Access-Control-Allow-Origin header management
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-origin.html b/testing/web-platform/tests/fetch/api/cors/cors-origin.html
new file mode 100644
index 00000000000..de7a0552acc
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-origin.html
@@ -0,0 +1,19 @@
+
+
+
+
+ Fetch: check Access-Control-Allow-Origin header management
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-origin.js b/testing/web-platform/tests/fetch/api/cors/cors-origin.js
new file mode 100644
index 00000000000..36052742a5f
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-origin.js
@@ -0,0 +1,61 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+ importScripts("/common/utils.js");
+}
+
+/* If origin is undefined, it is set to fetched url's origin*/
+function corsOrigin(desc, scheme, subdomain, port, method, origin, shouldPass) {
+ if (!port)
+ port = location.port;
+ if (subdomain)
+ subdomain = subdomain + ".";
+ else
+ subdomain = "";
+ if (!origin)
+ origin = scheme + "://" + subdomain + "{{host}}" + ":" + port;
+
+ var uuid_token = token();
+ var urlParameters = "?token=" + uuid_token + "&max_age=0&origin=" + encodeURIComponent(origin) + "&allow_methods=" + method;
+ var url = scheme + "://" + subdomain + "{{host}}" + ":" + port + dirname(location.pathname) + RESOURCES_DIR + "preflight.py";
+ var requestInit = {"mode": "cors", "method": method};
+
+ promise_test(function(test) {
+ fetch(RESOURCES_DIR + "clean-stash.py?token=" + uuid_token).then(function(resp) {
+ assert_equals(resp.status, 200, "Clean stash response's status is 200");
+ if (shouldPass) {
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 200, "Response's status is 200");
+ });
+ } else {
+ return promise_rejects(test, new TypeError(), fetch(url + urlParameters, requestInit));
+ }
+ });
+ }, desc);
+
+}
+var port = "{{ports[http][0]}}";
+var port2 = "{{ports[http][1]}}";
+var httpsPort = "{{ports[https][0]}}";
+/* Actual origin */
+var origin = "http://{{host}}:{{ports[http][0]}}";
+
+corsOrigin("Cross domain different subdomain [origin OK]", "http", "www1", undefined, "GET", origin, true);
+corsOrigin("Cross domain different subdomain [origin KO]", "http", "www1", undefined, "GET", undefined, false);
+corsOrigin("Same domain different port [origin OK]", "http", undefined, port2, "GET", origin, true);
+corsOrigin("Same domain different port [origin KO]", "http", undefined, port2, "GET", undefined, false);
+corsOrigin("Cross domain different port [origin OK]", "http", "www1", port2, "GET", origin, true);
+corsOrigin("Cross domain different port [origin KO]", "http", "www1", port2, "GET", undefined, false);
+corsOrigin("Cross domain different protocol [origin OK]", "https", "www1", httpsPort, "GET", origin, true);
+corsOrigin("Cross domain different protocol [origin KO]", "https", "www1", httpsPort, "GET", undefined, false);
+corsOrigin("Same domain different protocol different port [origin OK]", "https", undefined, httpsPort, "GET", origin, true);
+corsOrigin("Same domain different protocol different port [origin KO]", "https", undefined, httpsPort, "GET", undefined, false);
+corsOrigin("Cross domain [POST] [origin OK]", "http", "www1", undefined, "POST", origin, true);
+corsOrigin("Cross domain [POST] [origin KO]", "http", "www1", undefined, "POST", undefined, false);
+corsOrigin("Cross domain [HEAD] [origin OK]", "http", "www1", undefined, "HEAD", origin, true);
+corsOrigin("Cross domain [HEAD] [origin KO]", "http", "www1", undefined, "HEAD", undefined, false);
+corsOrigin("CORS preflight [PUT] [origin OK]", "http", "www1", undefined, "PUT", origin, true);
+corsOrigin("CORS preflight [PUT] [origin KO]", "http", "www1", undefined, "PUT", undefined, false);
+corsOrigin("Allowed origin: \"\" [origin KO]", "http", "www1", undefined, "GET", "" , false);
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-preflight-redirect-worker.html b/testing/web-platform/tests/fetch/api/cors/cors-preflight-redirect-worker.html
new file mode 100644
index 00000000000..663f5d655c1
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-preflight-redirect-worker.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Fetch in worker: redirection handling for cors with preflight
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-preflight-redirect.html b/testing/web-platform/tests/fetch/api/cors/cors-preflight-redirect.html
new file mode 100644
index 00000000000..6f136af76be
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-preflight-redirect.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Fetch: redirection handling for cors with preflight
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-preflight-redirect.js b/testing/web-platform/tests/fetch/api/cors/cors-preflight-redirect.js
new file mode 100644
index 00000000000..52a7bca3cd7
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-preflight-redirect.js
@@ -0,0 +1,40 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+ importScripts("/common/utils.js");
+}
+
+function corsPreflightRedirect(desc, redirectUrl, redirectLocation, redirectStatus, redirectPreflight) {
+ var uuid_token = token();
+ var url = redirectUrl;
+ var urlParameters = "?token=" + uuid_token + "&max_age=0";
+ urlParameters += "&redirect_status=" + redirectStatus;
+ urlParameters += "&location=" + encodeURIComponent(redirectLocation);
+
+ if (redirectPreflight)
+ urlParameters += "&redirect_preflight";
+ var requestInit = {"mode": "cors", "redirect": "follow"};
+
+ /* Force preflight */
+ requestInit["headers"] = {"x-force-preflight": ""};
+ urlParameters += "&allow_headers=x-force-preflight";
+
+ promise_test(function(test) {
+ fetch(RESOURCES_DIR + "clean-stash.py?token=" + uuid_token).then(function(resp) {
+ assert_equals(resp.status, 200, "Clean stash response's status is 200");
+ return promise_rejects(test, new TypeError(), fetch(url + urlParameters, requestInit));
+ });
+ }, desc);
+}
+
+var redirectUrl = "http://www1.{{host}}:{{ports[http][0]}}" + dirname(location.pathname) + RESOURCES_DIR + "redirect.py";
+var locationUrl = "http://www1.{{host}}:{{ports[http][0]}}" + dirname(location.pathname) + RESOURCES_DIR + "preflight.py";
+
+for (var code of [301, 302, 303, 307, 308]) {
+ /* preflight should not follow the redirection */
+ corsPreflightRedirect("Redirection " + code + " on preflight failed", redirectUrl, locationUrl, code, true);
+ /* preflight is done before redirection: preflight force redirect to error */
+ corsPreflightRedirect("Redirection " + code + " after preflight failed", redirectUrl, locationUrl, code, false);
+}
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-preflight-referrer-worker.html b/testing/web-platform/tests/fetch/api/cors/cors-preflight-referrer-worker.html
new file mode 100644
index 00000000000..4ed9072fb51
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-preflight-referrer-worker.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Fetch in worker: Referer header management in CORS request with preflight
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-preflight-referrer.html b/testing/web-platform/tests/fetch/api/cors/cors-preflight-referrer.html
new file mode 100644
index 00000000000..a399a051cb1
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-preflight-referrer.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Fetch: Referer header management in CORS request with preflight
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-preflight-referrer.js b/testing/web-platform/tests/fetch/api/cors/cors-preflight-referrer.js
new file mode 100644
index 00000000000..5cc3a084436
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-preflight-referrer.js
@@ -0,0 +1,39 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("/common/utils.js");
+ importScripts("../resources/utils.js");
+}
+
+function corsPreflightReferrer(desc, corsUrl, referrerPolicy, expectedReferrer) {
+ var uuid_token = token();
+ var url = corsUrl;
+ var urlParameters = "?token=" + uuid_token + "&max_age=0";
+ var requestInit = {"mode": "cors", "referrerPolicy": referrerPolicy};
+
+ /* Force preflight */
+ requestInit["headers"] = {"x-force-preflight": ""};
+ urlParameters += "&allow_headers=x-force-preflight";
+
+ promise_test(function(test) {
+ fetch(RESOURCES_DIR + "clean-stash.py?token=" + uuid_token).then(function(resp) {
+ assert_equals(resp.status, 200, "Clean stash response's status is 200");
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 200, "Response's status is 200");
+ assert_equals(resp.headers.get("x-did-preflight"), "1", "Preflight request has been made");
+ assert_equals(resp.headers.get("x-preflight-referrer"), expectedReferrer, "Preflight's referrer is correct");
+ assert_equals(resp.headers.get("x-referrer"), expectedReferrer, "Request's refferer is correct");
+ });
+ });
+ }, desc);
+}
+
+var corsUrl = "http://www1.{{host}}:{{ports[http][0]}}" + dirname(location.pathname) + RESOURCES_DIR + "preflight.py";
+var origin = "http://{{host}}:{{ports[http][0]}}";
+
+corsPreflightReferrer("Referrer policy: no-referrer", corsUrl, "no-referrer", "");
+corsPreflightReferrer("Referrer policy: \"\"", corsUrl, "", "");
+corsPreflightReferrer("Referrer policy: origin-only", corsUrl, "origin-only", origin);
+corsPreflightReferrer("Referrer policy: origin-when-cross-origin", corsUrl, "origin-when-cross-origin", origin);
+corsPreflightReferrer("Referrer policy: unsafe-url", corsUrl, "unsafe-url", location.toString());
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-preflight-status-worker.html b/testing/web-platform/tests/fetch/api/cors/cors-preflight-status-worker.html
new file mode 100644
index 00000000000..7650c37d1ea
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-preflight-status-worker.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Fetch in worker: preflight status code handling
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-preflight-status.html b/testing/web-platform/tests/fetch/api/cors/cors-preflight-status.html
new file mode 100644
index 00000000000..bc11fb755e6
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-preflight-status.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch: preflight status code handling
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-preflight-status.js b/testing/web-platform/tests/fetch/api/cors/cors-preflight-status.js
new file mode 100644
index 00000000000..07bd23c9003
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-preflight-status.js
@@ -0,0 +1,41 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+ importScripts("/common/utils.js");
+}
+
+/* Check preflight is ok if status is ok status (200 to 299)*/
+function corsPreflightStatus(desc, corsUrl, preflightStatus) {
+ var uuid_token = token();
+ var url = corsUrl;
+ var requestInit = {"mode": "cors"};
+ /* Force preflight */
+ requestInit["headers"] = {"x-force-preflight": ""};
+
+ var urlParameters = "?token=" + uuid_token + "&max_age=0";
+ urlParameters += "&allow_headers=x-force-preflight";
+ urlParameters += "&preflight_status=" + preflightStatus;
+
+ promise_test(function(test) {
+ fetch(RESOURCES_DIR + "clean-stash.py?token=" + uuid_token).then(function(resp) {
+ assert_equals(resp.status, 200, "Clean stash response's status is 200");
+ if (200 <= preflightStatus && 299 >= preflightStatus) {
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 200, "Response's status is 200");
+ assert_equals(resp.headers.get("x-did-preflight"), "1", "Preflight request has been made");
+ });
+ } else {
+ return promise_rejects(test, new TypeError(), fetch(url + urlParameters, requestInit));
+ }
+ });
+ }, desc);
+}
+
+var corsUrl = "http://www1.{{host}}:{{ports[http][0]}}" + dirname(location.pathname) + RESOURCES_DIR + "preflight.py";
+for (status of [200, 201, 202, 203, 204, 205, 206,
+ 300, 301, 302, 303, 304, 305, 306, 307, 308,
+ 400, 401, 402, 403, 404, 405,
+ 501, 502, 503, 504, 505])
+ corsPreflightStatus("Preflight answered with status " + status, corsUrl, status);
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-preflight-worker.html b/testing/web-platform/tests/fetch/api/cors/cors-preflight-worker.html
new file mode 100644
index 00000000000..bedef5d7751
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-preflight-worker.html
@@ -0,0 +1,20 @@
+
+
+
+
+ Fetch in worker: Check cors fetches requiring prefligh
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-preflight.html b/testing/web-platform/tests/fetch/api/cors/cors-preflight.html
new file mode 100644
index 00000000000..c4a581a55c5
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-preflight.html
@@ -0,0 +1,20 @@
+
+
+
+
+ Fetch: Check cors fetches requiring preflight
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-preflight.js b/testing/web-platform/tests/fetch/api/cors/cors-preflight.js
new file mode 100644
index 00000000000..60ecd186df1
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-preflight.js
@@ -0,0 +1,82 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+ importScripts("/common/utils.js");
+}
+
+/*
+ Check preflight is done
+ Control if server allows method and headers and check accordingly
+ Check control access headers added by UA (for method and headers)
+*/
+function corsPreflight(desc, corsUrl, method, allowed, headers) {
+ var uuid_token = token();
+ fetch(RESOURCES_DIR + "clean-stash.py?token=" + uuid_token).then(function(response) {
+
+ var url = corsUrl;
+ var urlParameters = "?token=" + uuid_token + "&max_age=0";
+ var requestInit = {"mode": "cors", "method": method};
+ if (headers)
+ requestInit["headers"] = headers;
+
+ if (allowed) {
+ urlParameters += "&allow_methods=" + method;
+ if (headers) {
+ //Let's check prefligh request.
+ //Server will send back headers from Access-Control-Request-Headers in x-control-request-headers
+ urlParameters += "&control_request_headers"
+ //Make the server allow the headers
+ urlParameters += "&allow_headers="
+ urlParameters += headers.join("%2C%20");
+ }
+ promise_test(function(test) {
+ test.add_cleanup(function() {
+ fetch(RESOURCES_DIR + "clean-stash.py?token=" + uuid_token);
+ });
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 200, "Response's status is 200");
+ assert_equals(resp.headers.get("x-did-preflight"), "1", "Preflight request has been made");
+ if (headers) {
+ var actualHeaders = resp.headers.get("x-control-request-headers").split(",");
+ for (var i in actualHeaders)
+ actualHeaders[i] = actualHeaders[i].trim();
+ for (var header in headers)
+ assert_in_array(header, actualHeaders, "Preflight asked permission for header: " + header);
+ }
+ });
+ }, desc);
+ } else {
+ promise_test(function(test) {
+ test.add_cleanup(function() {
+ fetch(RESOURCES_DIR + "clean-stash.py?token=" + uuid_token);
+ });
+ return promise_rejects(test, new TypeError(), fetch(url + urlParameters, requestInit));
+ }, desc);
+ }
+ });
+}
+
+var corsUrl = "http://www1.{{host}}:{{ports[http][0]}}" + dirname(location.pathname) + RESOURCES_DIR + "preflight.py";
+
+corsPreflight("CORS [DELETE], server allows", corsUrl, "DELETE", true);
+corsPreflight("CORS [DELETE], server refuses", corsUrl, "DELETE", false);
+corsPreflight("CORS [PUT], server allows", corsUrl, "PUT", true);
+corsPreflight("CORS [PUT], server refuses", corsUrl, "PUT", false);
+corsPreflight("CORS [PATCH], server allows", corsUrl, "PATCH", true);
+corsPreflight("CORS [PATCH], server refuses", corsUrl, "PATCH", false);
+corsPreflight("CORS [NEW], server allows", corsUrl, "NEW", true);
+corsPreflight("CORS [NEW], server refuses", corsUrl, "NEW", false);
+
+corsPreflight("CORS [GET] [x-test-header: allowed], server allows", corsUrl, "GET", true, {"x-test-header1": "allowed"});
+corsPreflight("CORS [GET] [x-test-header: refused], server refuses", corsUrl, "GET", false, {"x-test-header1": "refused"});
+
+var headers = {"x-test-header1": "allowedOrRefused",
+ "x-test-header2": "allowedOrRefused",
+ "x-test-header3": "allowedOrRefused",
+};
+corsPreflight("CORS [GET] [several headers], server allows", corsUrl, "GET", true, headers);
+corsPreflight("CORS [GET] [several headers], server refuses", corsUrl, "GET", false, headers);
+corsPreflight("CORS [PUT] [several headers], server allows", corsUrl, "PUT", true, headers);
+corsPreflight("CORS [PUT] [several headers], server refuses", corsUrl, "PUT", false, headers);
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-redirect-credentials-worker.html b/testing/web-platform/tests/fetch/api/cors/cors-redirect-credentials-worker.html
new file mode 100644
index 00000000000..38e3e78ac51
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-redirect-credentials-worker.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch in worker: redirection url has credentials
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-redirect-credentials.html b/testing/web-platform/tests/fetch/api/cors/cors-redirect-credentials.html
new file mode 100644
index 00000000000..2491f692d10
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-redirect-credentials.html
@@ -0,0 +1,15 @@
+
+
+
+
+ Fetch: redirection url has credentials
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-redirect-credentials.js b/testing/web-platform/tests/fetch/api/cors/cors-redirect-credentials.js
new file mode 100644
index 00000000000..ce0ef2d0b26
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-redirect-credentials.js
@@ -0,0 +1,47 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function corsRedirectCredentials(desc, redirectUrl, redirectLocation, redirectStatus, locationCredentials) {
+
+ var url = redirectUrl
+ var urlParameters = "?redirect_status=" + redirectStatus;
+ urlParameters += "&location=" + encodeURIComponent(redirectLocation.replace("://", "://" + locationCredentials + "@"));
+
+ var requestInit = {"mode": "cors", "redirect": "follow", "credentials":"include"};
+
+ promise_test(function(test) {
+ return promise_rejects(test, new TypeError(), fetch(url + urlParameters, requestInit));
+ }, desc);
+}
+
+var redirPath = dirname(location.pathname) + RESOURCES_DIR + "redirect.py";
+var preflightPath = dirname(location.pathname) + RESOURCES_DIR + "preflight.py";
+
+var localRedirect = "http://{{host}}:{{ports[http][0]}}" + redirPath;
+var remoteRedirect = "http://www1.{{host}}:{{ports[http][0]}}" + redirPath;
+
+var localLocation = "http://{{host}}:{{ports[http][0]}}" + preflightPath;
+var remoteLocation = "http://www1.{{host}}:{{ports[http][0]}}" + preflightPath;
+var remoteLocation2 = "http://www.{{host}}:{{ports[http][0]}}" + preflightPath;
+
+for (var code of [301, 302, 303, 307, 308]) {
+ corsRedirectCredentials("Redirect " + code + " from same origin to remote with user and password", localRedirect, remoteLocation, code, "user:password");
+ corsRedirectCredentials("Redirect " + code + " from same origin to remote with user", localRedirect, remoteLocation, code, "user:");
+ corsRedirectCredentials("Redirect " + code + " from same origin to remote with password", localRedirect, remoteLocation, code, ":password");
+
+ corsRedirectCredentials("Redirect " + code + " from remote to same origin with user and password", remoteRedirect, localLocation, code, "user:password");
+ corsRedirectCredentials("Redirect " + code + " from remote to same origin with user", remoteRedirect, localLocation, code, "user:");
+ corsRedirectCredentials("Redirect " + code + " from remote to same origin with password", remoteRedirect, localLocation, code, ":password");
+
+ corsRedirectCredentials("Redirect " + code + " from remote to another remote with user and password", remoteRedirect, remoteLocation2, code, "user:password");
+ corsRedirectCredentials("Redirect " + code + " from remote to another remote with user", remoteRedirect, remoteLocation2, code, "user:");
+ corsRedirectCredentials("Redirect " + code + " from remote to another remote with password", remoteRedirect, remoteLocation2, code, ":password");
+
+ corsRedirectCredentials("Redirect " + code + " from remote to same remote with user and password", remoteRedirect, remoteLocation, code, "user:password");
+ corsRedirectCredentials("Redirect " + code + " from remote to same remote with user", remoteRedirect, remoteLocation, code, "user:");
+ corsRedirectCredentials("Redirect " + code + " from remote to same remote with password", remoteRedirect, remoteLocation, code, ":password");
+}
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-redirect-worker.html b/testing/web-platform/tests/fetch/api/cors/cors-redirect-worker.html
new file mode 100644
index 00000000000..bf7bd965272
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-redirect-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: CORS Redirection with several origins
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-redirect.html b/testing/web-platform/tests/fetch/api/cors/cors-redirect.html
new file mode 100644
index 00000000000..f88eacf7bc5
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-redirect.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch: CORS Redirection with several origins
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/cors/cors-redirect.js b/testing/web-platform/tests/fetch/api/cors/cors-redirect.js
new file mode 100644
index 00000000000..a818054ab10
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/cors/cors-redirect.js
@@ -0,0 +1,44 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("/common/utils.js");
+ importScripts("../resources/utils.js");
+}
+
+function corsRedirect(desc, redirectUrl, redirectLocation, redirectStatus, expectedOrigin) {
+ var uuid_token = token();
+ var url = redirectUrl;
+ var urlParameters = "?token=" + uuid_token + "&max_age=0";
+ urlParameters += "&redirect_status=" + redirectStatus;
+ urlParameters += "&location=" + encodeURIComponent(redirectLocation);
+
+ var requestInit = {"mode": "cors", "redirect": "follow"};
+
+ promise_test(function(test) {
+ fetch(RESOURCES_DIR + "clean-stash.py?token=" + uuid_token).then(function(resp) {
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 200, "Response's status is 200");
+ assert_equals(resp.headers.get("x-did-preflight"), "0", "No preflight request has been made");
+ assert_equals(resp.headers.get("x-origin"), expectedOrigin, "Origin is correctly set after redirect");
+ });
+ });
+ }, desc);
+}
+
+var redirPath = dirname(location.pathname) + RESOURCES_DIR + "redirect.py";
+var preflightPath = dirname(location.pathname) + RESOURCES_DIR + "preflight.py";
+
+var localRedirect = "http://{{host}}:{{ports[http][0]}}" + redirPath;
+var remoteRedirect = "http://www1.{{host}}:{{ports[http][0]}}" + redirPath;
+
+var localLocation = "http://{{host}}:{{ports[http][0]}}" + preflightPath;
+var remoteLocation = "http://www1.{{host}}:{{ports[http][0]}}" + preflightPath;
+var remoteLocation2 = "http://www.{{host}}:{{ports[http][0]}}" + preflightPath;
+
+for (var code of [301, 302, 303, 307, 308]) {
+ corsRedirect("Redirect " + code + ": cors to same cors", remoteRedirect, remoteLocation, code, location.origin);
+ corsRedirect("Redirect " + code + ": cors to another cors", remoteRedirect, remoteLocation2, code, "null");
+ corsRedirect("Redirect " + code + ": same origin to cors", localRedirect, remoteLocation, code, location.origin);
+ corsRedirect("Redirect " + code + ": cors to same origin", remoteRedirect, localLocation, code, "null");
+}
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/credentials/authentication-basic-worker.html b/testing/web-platform/tests/fetch/api/credentials/authentication-basic-worker.html
new file mode 100644
index 00000000000..e9ced4f10af
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/credentials/authentication-basic-worker.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch in worker: Authorisation header management for basic authentication
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/credentials/authentication-basic.html b/testing/web-platform/tests/fetch/api/credentials/authentication-basic.html
new file mode 100644
index 00000000000..cba1ecd4acc
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/credentials/authentication-basic.html
@@ -0,0 +1,15 @@
+
+
+
+
+ Fetch: Authorisation header management for basic authentication
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/credentials/authentication-basic.js b/testing/web-platform/tests/fetch/api/credentials/authentication-basic.js
new file mode 100644
index 00000000000..ce93e9d7b93
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/credentials/authentication-basic.js
@@ -0,0 +1,21 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function basicAuth(desc, user, pass, mode, status) {
+ promise_test(function(test) {
+ var headers = { "Authorization": "Basic " + btoa(user + ":" + pass)};
+ var requestInit = {"credentials": mode, "headers": headers};
+ return fetch(RESOURCES_DIR + "authentication.py?realm=test", requestInit).then(function(resp) {
+ assert_equals(resp.status, status, "HTTP status is " + status);
+ assert_equals(resp.type , "basic", "Response's type is basic");
+ });
+ }, desc);
+}
+
+basicAuth("User-added Authorization header with include mode", "user", "password", "include", 200);
+basicAuth("User-added Authorization header with same-origin mode", "user", "password", "same-origin", 200);
+basicAuth("User-added Authorization header with omit mode", "user", "password", "omit", 200);
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/credentials/cookies-worker.html b/testing/web-platform/tests/fetch/api/credentials/cookies-worker.html
new file mode 100644
index 00000000000..86febf10bef
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/credentials/cookies-worker.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Fetch in worker: cookies management
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/credentials/cookies.html b/testing/web-platform/tests/fetch/api/credentials/cookies.html
new file mode 100644
index 00000000000..72913029a2f
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/credentials/cookies.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch: cookies management
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/credentials/cookies.js b/testing/web-platform/tests/fetch/api/credentials/cookies.js
new file mode 100644
index 00000000000..9c394d6fb38
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/credentials/cookies.js
@@ -0,0 +1,51 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function cookies(desc, credentials1, credentials2 ,cookies) {
+ var url = RESOURCES_DIR + "top.txt"
+ var urlParameters = "";
+ var urlCleanParameters = "";
+ if (cookies) {
+ urlParameters +="?pipe=header(Set-Cookie,";
+ urlParameters += cookies.join(",True)|header(Set-Cookie,") + ",True)";
+ urlCleanParameters +="?pipe=header(Set-Cookie,";
+ urlCleanParameters += cookies.join("%3B%20max-age=0,True)|header(Set-Cookie,") + "%3B%20max-age=0,True)";
+ }
+
+ var requestInit = {"credentials": credentials1}
+ promise_test(function(test){
+ var requestInit = {"credentials": credentials1}
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_equals(resp.type , "basic", "Response's type is basic");
+ //check cookies sent
+ return fetch(RESOURCES_DIR + "inspect-headers.py?headers=cookie" , {"credentials": credentials2});
+ }).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_equals(resp.type , "basic", "Response's type is basic");
+ assert_false(resp.headers.has("Cookie") , "Cookie header is not exposed in response");
+ if (credentials1 != "omit" && credentials2 != "omit") {
+ assert_equals(resp.headers.get("x-request-cookie") , cookies.join("; "), "Request include cookie(s)");
+ }
+ else {
+ assert_false(resp.headers.has("x-request-cookie") , "Request does not have cookie(s)");
+ }
+ //clean cookies
+ return fetch(url + urlCleanParameters, {"credentials": "include"});
+ }).catch(function() {
+ fetch(url + urlCleanParameters, {"credentials": "include"});
+ });
+ }, desc);
+}
+
+cookies("Include mode: 1 cookie", "include", "include", ["a=1"]);
+cookies("Include mode: 2 cookies", "include", "include", ["b=2", "c=3"]);
+cookies("Omit mode: discard cookies", "omit", "omit", ["d=4"]);
+cookies("Omit mode: no cookie is stored", "omit", "include", ["e=5"]);
+cookies("Omit mode: no cookie is sent", "include", "omit", ["f=6"]);
+cookies("Same-origin mode: 1 cookie", "same-origin", "same-origin", ["a=1"]);
+cookies("Same-origin mode: 2 cookies", "same-origin", "same-origin", ["b=2", "c=3"]);
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/headers/headers-basic.html b/testing/web-platform/tests/fetch/api/headers/headers-basic.html
new file mode 100644
index 00000000000..a5b8b6cfa9c
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/headers/headers-basic.html
@@ -0,0 +1,111 @@
+
+
+
+
+ Headers structure
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/headers/headers-casing.html b/testing/web-platform/tests/fetch/api/headers/headers-casing.html
new file mode 100644
index 00000000000..1e505d81cda
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/headers/headers-casing.html
@@ -0,0 +1,64 @@
+
+
+
+
+ Headers case management
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/headers/headers-combine.html b/testing/web-platform/tests/fetch/api/headers/headers-combine.html
new file mode 100644
index 00000000000..ddcfdbee6eb
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/headers/headers-combine.html
@@ -0,0 +1,60 @@
+
+
+
+
+ Headers nameshake
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/headers/headers-errors.html b/testing/web-platform/tests/fetch/api/headers/headers-errors.html
new file mode 100644
index 00000000000..be2d1a518dc
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/headers/headers-errors.html
@@ -0,0 +1,66 @@
+
+
+
+
+ Headers errors
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/headers/headers-idl.html b/testing/web-platform/tests/fetch/api/headers/headers-idl.html
new file mode 100644
index 00000000000..2aaa1ceeaee
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/headers/headers-idl.html
@@ -0,0 +1,36 @@
+
+
+
+
+ Headers idl interface
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/headers/headers-normalize.html b/testing/web-platform/tests/fetch/api/headers/headers-normalize.html
new file mode 100644
index 00000000000..384c4f4c26f
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/headers/headers-normalize.html
@@ -0,0 +1,47 @@
+
+
+
+
+ Headers normalize values
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/headers/headers-structure.html b/testing/web-platform/tests/fetch/api/headers/headers-structure.html
new file mode 100644
index 00000000000..9448e450c9b
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/headers/headers-structure.html
@@ -0,0 +1,31 @@
+
+
+
+
+ Headers basic
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/policies/csp-blocked-worker.html b/testing/web-platform/tests/fetch/api/policies/csp-blocked-worker.html
new file mode 100644
index 00000000000..e8660dffa94
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/csp-blocked-worker.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch in worker: blocked by CSP
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/csp-blocked.html b/testing/web-platform/tests/fetch/api/policies/csp-blocked.html
new file mode 100644
index 00000000000..99e90dfcd8f
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/csp-blocked.html
@@ -0,0 +1,15 @@
+
+
+
+
+ Fetch: blocked by CSP
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/csp-blocked.html.headers b/testing/web-platform/tests/fetch/api/policies/csp-blocked.html.headers
new file mode 100644
index 00000000000..c8c1e9ffbd9
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/csp-blocked.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy: connect-src 'none';
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/csp-blocked.js b/testing/web-platform/tests/fetch/api/policies/csp-blocked.js
new file mode 100644
index 00000000000..0395304b816
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/csp-blocked.js
@@ -0,0 +1,13 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+//Content-Security-Policy: connect-src 'none'; cf .headers file
+cspViolationUrl = RESOURCES_DIR + "top.txt";
+
+promise_test(function(test) {
+ return promise_rejects(test, new TypeError(), fetch(cspViolationUrl));
+}, "Fetch is blocked by CSP, got a TypeError");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/policies/csp-blocked.js.headers b/testing/web-platform/tests/fetch/api/policies/csp-blocked.js.headers
new file mode 100644
index 00000000000..c8c1e9ffbd9
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/csp-blocked.js.headers
@@ -0,0 +1 @@
+Content-Security-Policy: connect-src 'none';
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer-worker.html b/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer-worker.html
new file mode 100644
index 00000000000..dbef9bb658f
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: referrer with no-referrer policy
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer.html b/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer.html
new file mode 100644
index 00000000000..22a6f34c525
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer.html
@@ -0,0 +1,15 @@
+
+
+
+
+ Fetch: referrer with no-referrer policy
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer.html.headers b/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer.html.headers
new file mode 100644
index 00000000000..6954766b475
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy: referrer no-referrer;
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer.js b/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer.js
new file mode 100644
index 00000000000..60600bf081c
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer.js
@@ -0,0 +1,19 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+var fetchedUrl = RESOURCES_DIR + "inspect-headers.py?headers=origin";
+
+promise_test(function(test) {
+ return fetch(fetchedUrl).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_equals(resp.type , "basic", "Response's type is basic");
+ var referrer = resp.headers.get("x-request-referer");
+ //Either no referrer header is sent or it is empty
+ if (referrer)
+ assert_equals(referrer, "", "request's referrer is empty");
+ });
+}, "Request's referrer is empty");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer.js.headers b/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer.js.headers
new file mode 100644
index 00000000000..6954766b475
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-no-referrer.js.headers
@@ -0,0 +1 @@
+Content-Security-Policy: referrer no-referrer;
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-origin-worker.html b/testing/web-platform/tests/fetch/api/policies/referrer-origin-worker.html
new file mode 100644
index 00000000000..bb80dd54fbf
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-origin-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: referrer with origin policy
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-origin.html b/testing/web-platform/tests/fetch/api/policies/referrer-origin.html
new file mode 100644
index 00000000000..92baed79be7
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-origin.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch: referrer with origin policy
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-origin.html.headers b/testing/web-platform/tests/fetch/api/policies/referrer-origin.html.headers
new file mode 100644
index 00000000000..9bb592a867d
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-origin.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy: referrer origin;
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-origin.js b/testing/web-platform/tests/fetch/api/policies/referrer-origin.js
new file mode 100644
index 00000000000..3eb414b2fe4
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-origin.js
@@ -0,0 +1,22 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+var origin = "http://{{host}}:{{ports[http][0]}}";
+var fetchedUrl = RESOURCES_DIR + "inspect-headers.py?headers=referer";
+
+promise_test(function(test) {
+ return fetch(fetchedUrl).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_equals(resp.type , "basic", "Response's type is basic");
+ assert_equals(resp.headers.get("x-request-referer"), origin, "request's referrer is " + origin);
+ });
+}, "Request's referrer is origin");
+
+promise_test(function(test) {
+ var referrerUrl = "http://{{domains[www]}}:{{ports[http][0]}}/";
+ return promise_rejects(test, new TypeError(), fetch(fetchedUrl, { "referrer": referrerUrl}));
+}, "Throw a TypeError referrer is not same-origin with origin");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-origin.js.headers b/testing/web-platform/tests/fetch/api/policies/referrer-origin.js.headers
new file mode 100644
index 00000000000..9bb592a867d
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-origin.js.headers
@@ -0,0 +1 @@
+Content-Security-Policy: referrer origin;
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url-worker.html b/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url-worker.html
new file mode 100644
index 00000000000..42045776b12
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: referrer with unsafe-url policy
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url.html b/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url.html
new file mode 100644
index 00000000000..10dd79e3d35
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch: referrer with unsafe-url policy
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url.html.headers b/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url.html.headers
new file mode 100644
index 00000000000..8efcca15fe0
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy: referrer unsafe-url;
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url.js b/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url.js
new file mode 100644
index 00000000000..b593fad5aa2
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url.js
@@ -0,0 +1,17 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+var referrerUrl = location.href;
+var fetchedUrl = RESOURCES_DIR + "inspect-headers.py?headers=referer";
+
+promise_test(function(test) {
+ return fetch(fetchedUrl).then(function(resp) {
+ assert_equals(resp.status, 200, "HTTP status is 200");
+ assert_equals(resp.type , "basic", "Response's type is basic");
+ assert_equals(resp.headers.get("x-request-referer"), referrerUrl, "request's referrer is " + referrerUrl);
+ });
+}, "Request's referrer is the full url of current document/worker");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url.js.headers b/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url.js.headers
new file mode 100644
index 00000000000..8efcca15fe0
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/policies/referrer-unsafe-url.js.headers
@@ -0,0 +1 @@
+Content-Security-Policy: referrer unsafe-url;
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/redirect/redirect-count-worker.html b/testing/web-platform/tests/fetch/api/redirect/redirect-count-worker.html
new file mode 100644
index 00000000000..1ce33b7c403
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/redirect/redirect-count-worker.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch in worker: rediraction loop
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/redirect/redirect-count.html b/testing/web-platform/tests/fetch/api/redirect/redirect-count.html
new file mode 100644
index 00000000000..61deb9f528d
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/redirect/redirect-count.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch: redirection loop
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/redirect/redirect-count.js b/testing/web-platform/tests/fetch/api/redirect/redirect-count.js
new file mode 100644
index 00000000000..ffa521a5c0f
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/redirect/redirect-count.js
@@ -0,0 +1,42 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+ importScripts("/common/utils.js");
+}
+
+function redirectCount(desc, redirectUrl, redirectLocation, redirectStatus, maxCount, shouldPass) {
+ var uuid_token = token();
+
+ var urlParameters = "?token=" + uuid_token + "&max_age=0";
+ urlParameters += "&redirect_status=" + redirectStatus;
+ urlParameters += "&max_count=" + maxCount;
+ if (redirectLocation)
+ urlParameters += "&location=" + encodeURIComponent(redirectLocation);
+
+ var url = redirectUrl;
+ var requestInit = {"redirect": "follow"};
+
+ promise_test(function(test) {
+ fetch(RESOURCES_DIR + "clean-stash.py?token=" + uuid_token).then(function(resp) {
+ assert_equals(resp.status, 200, "Clean stash response's status is 200");
+
+ if (!shouldPass)
+ return promise_rejects(test, new TypeError(), fetch(url + urlParameters, requestInit));
+
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 200, "Response's status is 200");
+ });
+ }).then(function(body) {
+ assert_equals(body, maxCount.toString(), "Redirected " + maxCount + "times");
+ });
+ }, desc);
+}
+
+var redirUrl = RESOURCES_DIR + "redirect.py";
+
+for (var statusCode of [301, 302, 303, 307, 308]) {
+ redirectCount("Redirect " + statusCode + " 20 times", redirUrl, redirUrl, statusCode, 20, true);
+ redirectCount("Redirect " + statusCode + " 21 times", redirUrl, redirUrl, statusCode, 21, false);
+}
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/redirect/redirect-location-worker.html b/testing/web-platform/tests/fetch/api/redirect/redirect-location-worker.html
new file mode 100644
index 00000000000..e2970811c07
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/redirect/redirect-location-worker.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch in worker: handling Location header during redirection
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/redirect/redirect-location.html b/testing/web-platform/tests/fetch/api/redirect/redirect-location.html
new file mode 100644
index 00000000000..ac35dea54c4
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/redirect/redirect-location.html
@@ -0,0 +1,15 @@
+
+
+
+
+ Fetch: handling Location header during redirection
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/redirect/redirect-location.js b/testing/web-platform/tests/fetch/api/redirect/redirect-location.js
new file mode 100644
index 00000000000..5b081a75408
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/redirect/redirect-location.js
@@ -0,0 +1,50 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function redirectLocation(desc, redirectUrl, redirectLocation, redirectStatus, redirectMode, shouldPass) {
+ var url = redirectUrl;
+ var urlParameters = "?redirect_status=" + redirectStatus;
+ if (redirectLocation)
+ urlParameters += "&location=" + encodeURIComponent(redirectLocation);
+
+ var requestInit = {"redirect": redirectMode};
+
+ promise_test(function(test) {
+ if (redirectMode === "error" || !shouldPass)
+ return promise_rejects(test, new TypeError(), fetch(url + urlParameters, requestInit));
+ if (redirectLocation && redirectMode === "manual")
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 0, "Response's status is 0");
+ assert_equals(resp.type, "opaqueredirect", "Response's type is opaqueredirect");
+ assert_equals(resp.statusText, "", "Response's statusText is \"\"");
+ assert_true(resp.headers.entries().next().done, "Headers should be empty");
+ });
+
+ if (redirectMode === "manual" || redirectMode === "follow")
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, redirectStatus, "Response's status is " + redirectStatus);
+ });
+ assert_unreached(redirectMode + " is not a valid redirect mode");
+ }, desc);
+}
+
+var redirUrl = RESOURCES_DIR + "redirect.py";
+var locationUrl = "top.txt";
+var invalidLocationUrl = "#invalidurl:";
+var dataLocationUrl = "data:,data%20url";
+// FIXME: We may want to mix redirect-mode and cors-mode.
+// FIXME: Add tests for "error" redirect-mode.
+for (var statusCode of [301, 302, 303, 307, 308]) {
+ redirectLocation("Redirect " + statusCode + " in \"follow\" mode without location", redirUrl, undefined, statusCode, "follow", true);
+ redirectLocation("Redirect " + statusCode + " in \"manual\" mode without location", redirUrl, undefined, statusCode, "manual", true);
+
+ redirectLocation("Redirect " + statusCode + " in \"follow\" mode with invalid location", redirUrl, invalidLocationUrl, statusCode, "follow", false);
+ redirectLocation("Redirect " + statusCode + " in \"manual\" mode with invalid location", redirUrl, invalidLocationUrl, statusCode, "manual", false);
+
+ redirectLocation("Redirect " + statusCode + " in \"follow\" mode with data location", redirUrl, dataLocationUrl, statusCode, "follow", false);
+ redirectLocation("Redirect " + statusCode + " in \"manual\" mode with data location", redirUrl, dataLocationUrl, statusCode, "manual", true);
+}
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/redirect/redirect-method-worker.html b/testing/web-platform/tests/fetch/api/redirect/redirect-method-worker.html
new file mode 100644
index 00000000000..fc0bc5e529d
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/redirect/redirect-method-worker.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch in worker: request method handling when redirected
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/redirect/redirect-method.html b/testing/web-platform/tests/fetch/api/redirect/redirect-method.html
new file mode 100644
index 00000000000..028842dbe07
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/redirect/redirect-method.html
@@ -0,0 +1,15 @@
+
+
+
+
+ Fetch: request method handling when redirected
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/redirect/redirect-method.js b/testing/web-platform/tests/fetch/api/redirect/redirect-method.js
new file mode 100644
index 00000000000..a7e1b0b69c5
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/redirect/redirect-method.js
@@ -0,0 +1,46 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function redirectMethod(desc, redirectUrl, redirectLocation, redirectStatus, method, expectedMethod) {
+ var url = redirectUrl;
+ var urlParameters = "?redirect_status=" + redirectStatus;
+ urlParameters += "&location=" + encodeURIComponent(redirectLocation);
+
+ var requestInit = {"method": method, "redirect": "follow"};
+ if (method != "GET" && method != "HEAD")
+ requestInit.body = "this is my body";
+
+ promise_test(function(test) {
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 200, "Response's status is 200");
+ assert_equals(resp.type, "basic", "Response's type basic");
+ assert_equals(resp.headers.get("x-request-method"), expectedMethod, "Request method after redirection is " + expectedMethod);
+ return resp.text().then(function(text) {
+ assert_equals(text, expectedMethod == "POST" ? requestInit.body : "");
+ });
+ });
+ }, desc);
+}
+
+var redirUrl = RESOURCES_DIR + "redirect.py";
+var locationUrl = "method.py";
+
+redirectMethod("Redirect 301 with GET", redirUrl, locationUrl, 301, "GET", "GET");
+redirectMethod("Redirect 301 with POST", redirUrl, locationUrl, 301, "POST", "GET");
+redirectMethod("Redirect 301 with HEAD", redirUrl, locationUrl, 301, "HEAD", "HEAD");
+
+redirectMethod("Redirect 302 with GET", redirUrl, locationUrl, 302, "GET", "GET");
+redirectMethod("Redirect 302 with POST", redirUrl, locationUrl, 302, "POST", "GET");
+redirectMethod("Redirect 302 with HEAD", redirUrl, locationUrl, 302, "HEAD", "HEAD");
+
+redirectMethod("Redirect 303 with GET", redirUrl, locationUrl, 303, "GET", "GET");
+redirectMethod("Redirect 303 with POST", redirUrl, locationUrl, 303, "POST", "GET");
+redirectMethod("Redirect 303 with HEAD", redirUrl, locationUrl, 303, "HEAD", "HEAD");
+
+redirectMethod("Redirect 307 with GET", redirUrl, locationUrl, 307, "GET", "GET");
+redirectMethod("Redirect 307 with POST", redirUrl, locationUrl, 307, "POST", "POST");
+redirectMethod("Redirect 307 with HEAD", redirUrl, locationUrl, 307, "HEAD", "HEAD");
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/redirect/redirect-mode-worker.html b/testing/web-platform/tests/fetch/api/redirect/redirect-mode-worker.html
new file mode 100644
index 00000000000..32d219f7678
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/redirect/redirect-mode-worker.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Fetch in worker: redirect mode handling
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/redirect/redirect-mode.html b/testing/web-platform/tests/fetch/api/redirect/redirect-mode.html
new file mode 100644
index 00000000000..2f68d2b70a0
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/redirect/redirect-mode.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Fetch: redirect mode handling
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/redirect/redirect-mode.js b/testing/web-platform/tests/fetch/api/redirect/redirect-mode.js
new file mode 100644
index 00000000000..f6832c49276
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/redirect/redirect-mode.js
@@ -0,0 +1,40 @@
+if (this.document === undefined) {
+ importScripts("/resources/testharness.js");
+ importScripts("../resources/utils.js");
+}
+
+function redirectMode(desc, redirectUrl, redirectLocation, redirectStatus, redirectMode) {
+ var url = redirectUrl;
+ var urlParameters = "?redirect_status=" + redirectStatus;
+ urlParameters += "&location=" + encodeURIComponent(redirectLocation);
+
+ var requestInit = {"redirect": redirectMode};
+
+ promise_test(function(test) {
+ if (redirectMode === "error")
+ return promise_rejects(test, new TypeError(), fetch(url + urlParameters, requestInit));
+ if (redirectMode === "manual")
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_equals(resp.status, 0, "Response's status is 0");
+ assert_equals(resp.type, "opaqueredirect", "Response's type is opaqueredirect");
+ assert_equals(resp.statusText, "", "Response's statusText is \"\"");
+ });
+ if (redirectMode === "follow")
+ return fetch(url + urlParameters, requestInit).then(function(resp) {
+ assert_true(new URL(resp.url).pathname.endsWith(locationUrl), "Response's url should be the redirected one");
+ assert_equals(resp.status, 200, "Response's status is 200");
+ });
+ assert_unreached(redirectMode + " is no a valid redirect mode");
+ }, desc);
+}
+
+var redirUrl = RESOURCES_DIR + "redirect.py";
+var locationUrl = "top.txt";
+
+for (var statusCode of [301, 302, 303, 307, 308]) {
+ redirectMode("Redirect " + statusCode + " in \"error\" mode ", redirUrl, locationUrl, statusCode, "error");
+ redirectMode("Redirect " + statusCode + " in \"follow\" mode ", redirUrl, locationUrl, statusCode, "follow");
+ redirectMode("Redirect " + statusCode + " in \"manual\" mode ", redirUrl, locationUrl, statusCode, "manual");
+}
+
+done();
diff --git a/testing/web-platform/tests/fetch/api/request/request-clone.sub.html b/testing/web-platform/tests/fetch/api/request/request-clone.sub.html
new file mode 100644
index 00000000000..ae784564d70
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/request/request-clone.sub.html
@@ -0,0 +1,48 @@
+
+
+
+
+ Request clone
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/request/request-consume.html b/testing/web-platform/tests/fetch/api/request/request-consume.html
new file mode 100644
index 00000000000..d0f756dc402
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/request/request-consume.html
@@ -0,0 +1,89 @@
+
+
+
+
+ Request consume
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/request/request-disturbed.html b/testing/web-platform/tests/fetch/api/request/request-disturbed.html
new file mode 100644
index 00000000000..958def41768
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/request/request-disturbed.html
@@ -0,0 +1,55 @@
+
+
+
+
+ Request disturbed
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/request/request-error.html b/testing/web-platform/tests/fetch/api/request/request-error.html
new file mode 100644
index 00000000000..51db7378e92
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/request/request-error.html
@@ -0,0 +1,104 @@
+
+
+
+
+ Request error
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/request/request-idl.html b/testing/web-platform/tests/fetch/api/request/request-idl.html
new file mode 100644
index 00000000000..0faefee3aa4
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/request/request-idl.html
@@ -0,0 +1,85 @@
+
+
+
+
+ Request idl interface
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/request/request-init-001.sub.html b/testing/web-platform/tests/fetch/api/request/request-init-001.sub.html
new file mode 100644
index 00000000000..92206b45128
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/request/request-init-001.sub.html
@@ -0,0 +1,92 @@
+
+
+
+
+ Request init: simple cases
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/request/request-init-002.html b/testing/web-platform/tests/fetch/api/request/request-init-002.html
new file mode 100644
index 00000000000..46246c11eaf
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/request/request-init-002.html
@@ -0,0 +1,62 @@
+
+
+
+
+ Request init: headers and body
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/request/request-init-003.sub.html b/testing/web-platform/tests/fetch/api/request/request-init-003.sub.html
new file mode 100644
index 00000000000..41bafebb18d
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/request/request-init-003.sub.html
@@ -0,0 +1,84 @@
+
+
+
+
+ Request: init with request or url
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/request/request-structure.html b/testing/web-platform/tests/fetch/api/request/request-structure.html
new file mode 100644
index 00000000000..2d7d4dba7bf
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/request/request-structure.html
@@ -0,0 +1,132 @@
+
+
+
+
+ Request structure
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/resources/authentication.py b/testing/web-platform/tests/fetch/api/resources/authentication.py
new file mode 100644
index 00000000000..a06d179e58e
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/resources/authentication.py
@@ -0,0 +1,15 @@
+def main(request, response):
+ user = request.auth.username
+ password = request.auth.password
+
+ if user == "user" and password == "password":
+ return "Authentication done"
+
+ realm = "test"
+ if "realm" in request.GET:
+ realm = request.GET.first("realm")
+
+ return ((401, "Unauthorized"),
+ [("WWW-Authenticate", 'Basic realm="' + realm + '"')],
+ "Please login with credentials 'user' and 'password'")
+
diff --git a/testing/web-platform/tests/fetch/api/resources/clean-stash.py b/testing/web-platform/tests/fetch/api/resources/clean-stash.py
new file mode 100644
index 00000000000..3ae73105269
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/resources/clean-stash.py
@@ -0,0 +1,6 @@
+def main(request, response):
+ token = request.GET.first("token")
+ if request.server.stash.take(token) is not None:
+ return "1"
+ else:
+ return "0"
diff --git a/testing/web-platform/tests/fetch/api/resources/inspect-headers.py b/testing/web-platform/tests/fetch/api/resources/inspect-headers.py
new file mode 100644
index 00000000000..c4ace18ab64
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/resources/inspect-headers.py
@@ -0,0 +1,22 @@
+def main(request, response):
+ headers = []
+ request_headers = []
+ if "headers" in request.GET:
+ checked_headers = request.GET.first("headers").split("|")
+ for header in checked_headers:
+ if header in request.headers:
+ headers.append(("x-request-" + header, request.headers.get(header, "") ))
+
+ if "cors" in request.GET:
+ if "Origin" in request.headers:
+ headers.append(("Access-Control-Allow-Origin", request.headers.get("Origin", "")))
+ else:
+ headers.append(("Access-Control-Allow-Origin", "*"))
+ headers.append(("Access-Control-Allow-Credentials", "true"))
+ headers.append(("Access-Control-Allow-Methods", "GET, POST, HEAD"))
+ exposed_headers = ["x-request-" + header for header in checked_headers]
+ headers.append(("Access-Control-Expose-Headers", ", ".join(exposed_headers)))
+ headers.append(("Access-Control-Allow-Headers", ", ".join(request.headers)))
+
+ headers.append(("content-type", "text/plain"))
+ return headers, ""
diff --git a/testing/web-platform/tests/fetch/api/resources/method.py b/testing/web-platform/tests/fetch/api/resources/method.py
new file mode 100644
index 00000000000..db234f9d123
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/resources/method.py
@@ -0,0 +1,11 @@
+def main(request, response):
+ headers = []
+ if "cors" in request.GET:
+ headers.append(("Access-Control-Allow-Origin", "*"))
+ headers.append(("Access-Control-Allow-Credentials", "true"))
+ headers.append(("Access-Control-Allow-Methods", "GET, POST, PUT, FOO"))
+ headers.append(("Access-Control-Allow-Headers", "x-test, x-foo"))
+ headers.append(("Access-Control-Expose-Headers", "x-request-method"))
+
+ headers.append(("x-request-method", request.method))
+ return headers, request.body
diff --git a/testing/web-platform/tests/fetch/api/resources/preflight.py b/testing/web-platform/tests/fetch/api/resources/preflight.py
new file mode 100644
index 00000000000..72dceba683d
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/resources/preflight.py
@@ -0,0 +1,56 @@
+def main(request, response):
+ headers = [("Content-Type", "text/plain")]
+ stashed_data = {'control_request_headers': "", 'preflight': "0", 'preflight_referrer': ""}
+
+ if "origin" in request.GET:
+ for origin in request.GET['origin'].split(", "):
+ headers.append(("Access-Control-Allow-Origin", origin))
+ else:
+ headers.append(("Access-Control-Allow-Origin", "*"))
+
+ if request.method == "OPTIONS":
+ if not "Access-Control-Request-Method" in request.headers:
+ response.set_error(400, "No Access-Control-Request-Method header")
+ return "ERROR: No access-control-request-method in preflight!"
+
+ if "control_request_headers" in request.GET:
+ stashed_data['control_request_headers'] = request.headers.get("Access-Control-Request-Headers", "")
+
+ if "max_age" in request.GET:
+ headers.append(("Access-Control-Max-Age", request.GET['max_age']))
+
+ if "allow_headers" in request.GET:
+ headers.append(("Access-Control-Allow-Headers", request.GET['allow_headers']))
+
+ if "allow_methods" in request.GET:
+ headers.append(("Access-Control-Allow-Methods", request.GET['allow_methods']))
+
+ preflight_status = 200
+ if "preflight_status" in request.GET:
+ preflight_status = int(request.GET.first("preflight_status"))
+
+ stashed_data['preflight'] = "1"
+ stashed_data['preflight_referrer'] = request.headers.get("Referer", "")
+ request.server.stash.put(request.GET.first("token"), stashed_data)
+
+ return preflight_status, headers, ""
+
+ token = None
+ if "token" in request.GET:
+ token = request.GET.first("token")
+ data = request.server.stash.take(token)
+ if data:
+ stashed_data = data
+
+ #use x-* headers for returning value to bodyless responses
+ headers.append(("Access-Control-Expose-Headers", "x-did-preflight, x-control-request-headers, x-referrer, x-preflight-referrer, x-origin"))
+ headers.append(("x-did-preflight", stashed_data['preflight']))
+ headers.append(("x-control-request-headers", stashed_data['control_request_headers']))
+ headers.append(("x-preflight-referrer", stashed_data['preflight_referrer']))
+ headers.append(("x-referrer", request.headers.get("Referer", "") ))
+ headers.append(("x-origin", request.headers.get("Origin", "") ))
+
+ if token:
+ request.server.stash.put(token, stashed_data)
+
+ return headers, ""
diff --git a/testing/web-platform/tests/fetch/api/resources/redirect.py b/testing/web-platform/tests/fetch/api/resources/redirect.py
new file mode 100644
index 00000000000..3767b223aac
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/resources/redirect.py
@@ -0,0 +1,48 @@
+def main(request, response):
+ stashed_data = {'count': 0, 'preflight': "0"}
+ status = 302
+ headers = [("Content-Type", "text/plain"),
+ ("Cache-Control", "no-cache"),
+ ("Pragma", "no-cache"),
+ ("Access-Control-Allow-Origin", "*")]
+ token = None
+
+ if "token" in request.GET:
+ token = request.GET.first("token")
+ data = request.server.stash.take(token)
+ if data:
+ stashed_data = data
+
+ if request.method == "OPTIONS":
+ if "allow_headers" in request.GET:
+ headers.append(("Access-Control-Allow-Headers", request.GET['allow_headers']))
+ stashed_data['preflight'] = "1"
+ #Preflight is not redirected: return 200
+ if not "redirect_preflight" in request.GET:
+ if token:
+ request.server.stash.put(request.GET.first("token"), stashed_data)
+ return 200, headers, ""
+
+ if "redirect_status" in request.GET:
+ status = int(request.GET['redirect_status'])
+
+ stashed_data['count'] += 1
+
+ #keep url parameters in location
+ url_parameters = "?" + "&".join(map(lambda x: x[0][0] + "=" + x[1][0], request.GET.items()))
+ #make sure location changes during redirection loop
+ url_parameters += "&count=" + str(stashed_data['count'])
+
+ if "location" in request.GET:
+ headers.append(("Location", request.GET['location'] + url_parameters))
+
+ if token:
+ request.server.stash.put(request.GET.first("token"), stashed_data)
+ if "max_count" in request.GET:
+ max_count = int(request.GET['max_count'])
+ #stop redirecting and return count
+ if stashed_data['count'] > max_count:
+ # -1 because the last is not a redirection
+ return str(stashed_data['count'] - 1)
+
+ return status, headers, ""
diff --git a/testing/web-platform/tests/fetch/api/resources/top.txt b/testing/web-platform/tests/fetch/api/resources/top.txt
new file mode 100644
index 00000000000..83a3157d14d
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/resources/top.txt
@@ -0,0 +1 @@
+top
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/resources/trickle.py b/testing/web-platform/tests/fetch/api/resources/trickle.py
new file mode 100644
index 00000000000..0e709445c59
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/resources/trickle.py
@@ -0,0 +1,12 @@
+import time
+
+def main(request, response):
+ delay = float(request.GET.first("ms", 500)) / 1E3
+ count = int(request.GET.first("count", 50))
+ time.sleep(delay)
+ response.headers.set("Content-type", "text/plain")
+ response.write_status_headers()
+ time.sleep(delay);
+ for i in xrange(count):
+ response.writer.write_content("TEST_TRICKLE\n")
+ time.sleep(delay)
diff --git a/testing/web-platform/tests/fetch/api/resources/utils.js b/testing/web-platform/tests/fetch/api/resources/utils.js
new file mode 100644
index 00000000000..a090e1eebd5
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/resources/utils.js
@@ -0,0 +1,68 @@
+var inWorker = false;
+var RESOURCES_DIR = "../resources/";
+
+try {
+ inWorker = !(self instanceof Window);
+} catch (e) {
+ inWorker = true;
+}
+
+function dirname(path) {
+ return path.replace(/\/[^\/]*$/, '/')
+}
+
+function checkRequest(request, ExpectedValuesDict) {
+ for (var attribute in ExpectedValuesDict) {
+ switch(attribute) {
+ case "headers":
+ for (var key of ExpectedValuesDict["headers"].keys()) {
+ assert_equals(request["headers"].get(key), ExpectedValuesDict["headers"].get(key),
+ "Check headers attribute has " + key + ":" + ExpectedValuesDict["headers"].get(key));
+ }
+ break;
+
+ case "body":
+ //for checking body's content, a dedicated asyncronous/promise test should be used
+ assert_true(request["headers"].has("Content-Type") , "Check request has body using Content-Type header")
+ break;
+
+ case "method":
+ case "referrer":
+ case "referrerPolicy":
+ case "credentials":
+ case "cache":
+ case "redirect":
+ case "integrity":
+ case "url":
+ case "destination":
+ assert_equals(request[attribute], ExpectedValuesDict[attribute], "Check " + attribute + " attribute")
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+//check reader's text content in an asyncronous test
+function readTextStream(reader, asyncTest, expectedValue, retrievedText) {
+ if (!retrievedText)
+ retrievedText = "";
+ reader.read().then(function(data) {
+ if (!data.done) {
+ var decoder = new TextDecoder();
+ retrievedText += decoder.decode(data.value);
+ readTextStream(reader, asyncTest, expectedValue, retrievedText);
+ return;
+ }
+ asyncTest.step(function() {
+ assert_equals(retrievedText, expectedValue, "Retrieve and verify stream");
+ asyncTest.done();
+ });
+ }).catch(function(e) {
+ asyncTest.step(function() {
+ assert_unreached("Cannot read stream " + e);
+ asyncTest.done();
+ });
+ });
+}
diff --git a/testing/web-platform/tests/fetch/api/response/response-clone.html b/testing/web-platform/tests/fetch/api/response/response-clone.html
new file mode 100644
index 00000000000..8afcf36d831
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/response/response-clone.html
@@ -0,0 +1,66 @@
+
+
+
+
+ Response clone
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/response/response-consume.html b/testing/web-platform/tests/fetch/api/response/response-consume.html
new file mode 100644
index 00000000000..14dcad795c2
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/response/response-consume.html
@@ -0,0 +1,81 @@
+
+
+
+
+ Response consume
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/response/response-error.html b/testing/web-platform/tests/fetch/api/response/response-error.html
new file mode 100644
index 00000000000..1e68f6d01c6
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/response/response-error.html
@@ -0,0 +1,39 @@
+
+
+
+
+ Response error
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/response/response-idl.html b/testing/web-platform/tests/fetch/api/response/response-idl.html
new file mode 100644
index 00000000000..e849856cee3
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/response/response-idl.html
@@ -0,0 +1,69 @@
+
+
+
+
+ Response idl interface
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/response/response-init-001.html b/testing/web-platform/tests/fetch/api/response/response-init-001.html
new file mode 100644
index 00000000000..e36f90e4c82
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/response/response-init-001.html
@@ -0,0 +1,63 @@
+
+
+
+
+ Response init: simple cases
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/api/response/response-init-002.html b/testing/web-platform/tests/fetch/api/response/response-init-002.html
new file mode 100644
index 00000000000..29008584a85
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/response/response-init-002.html
@@ -0,0 +1,62 @@
+
+
+
+
+ Response init: body and headers
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/response/response-static-error.html b/testing/web-platform/tests/fetch/api/response/response-static-error.html
new file mode 100644
index 00000000000..6e927a8bf62
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/response/response-static-error.html
@@ -0,0 +1,25 @@
+
+
+
+
+ Response: error static method
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/fetch/api/response/response-static-redirect.html b/testing/web-platform/tests/fetch/api/response/response-static-redirect.html
new file mode 100644
index 00000000000..6a50440de36
--- /dev/null
+++ b/testing/web-platform/tests/fetch/api/response/response-static-redirect.html
@@ -0,0 +1,45 @@
+
+
+
+
+ Response: redirect static method
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/html/OWNERS b/testing/web-platform/tests/html/OWNERS
new file mode 100644
index 00000000000..210a621c919
--- /dev/null
+++ b/testing/web-platform/tests/html/OWNERS
@@ -0,0 +1,7 @@
+@Ms2ger
+@gsnedders
+@jgraham
+@plehegar
+@sideshowbarker
+@zcorpan
+@zqzhang
diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_origin.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_origin.html
new file mode 100644
index 00000000000..2325f4018aa
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_origin.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/html/dom/interfaces.html b/testing/web-platform/tests/html/dom/interfaces.html
index f76d0ce38a7..8eb7df805fb 100644
--- a/testing/web-platform/tests/html/dom/interfaces.html
+++ b/testing/web-platform/tests/html/dom/interfaces.html
@@ -1591,7 +1591,7 @@ interface HTMLFormElement : HTMLElement {
attribute DOMString target;
readonly attribute HTMLFormControlsCollection elements;
- readonly attribute long length;
+ readonly attribute unsigned long length;
getter Element (unsigned long index);
getter (RadioNodeList or Element) (DOMString name);
diff --git a/testing/web-platform/tests/url/urltestdata.json b/testing/web-platform/tests/url/urltestdata.json
index 1f787d795ef..1e8c68fc46b 100644
--- a/testing/web-platform/tests/url/urltestdata.json
+++ b/testing/web-platform/tests/url/urltestdata.json
@@ -1760,7 +1760,7 @@
{
"input": "http://example.com/foo/%2e%2",
"base": "about:blank",
- "href": "http://example.com/foo/%2e%2",
+ "href": "http://example.com/foo/.%2",
"origin": "http://example.com",
"protocol": "http:",
"username": "",
@@ -1768,14 +1768,14 @@
"host": "example.com",
"hostname": "example.com",
"port": "",
- "pathname": "/foo/%2e%2",
+ "pathname": "/foo/.%2",
"search": "",
"hash": ""
},
{
"input": "http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar",
"base": "about:blank",
- "href": "http://example.com/%2e.bar",
+ "href": "http://example.com/..bar",
"origin": "http://example.com",
"protocol": "http:",
"username": "",
@@ -1783,7 +1783,7 @@
"host": "example.com",
"hostname": "example.com",
"port": "",
- "pathname": "/%2e.bar",
+ "pathname": "/..bar",
"search": "",
"hash": ""
},
diff --git a/testing/web-platform/tests/webgl/OWNERS b/testing/web-platform/tests/webgl/OWNERS
new file mode 100644
index 00000000000..fd31fb27543
--- /dev/null
+++ b/testing/web-platform/tests/webgl/OWNERS
@@ -0,0 +1 @@
+@Ms2ger
diff --git a/testing/web-platform/tests/websockets/Create-asciiSep-protocol-string.htm b/testing/web-platform/tests/websockets/Create-asciiSep-protocol-string.htm
new file mode 100644
index 00000000000..7309009d052
--- /dev/null
+++ b/testing/web-platform/tests/websockets/Create-asciiSep-protocol-string.htm
@@ -0,0 +1,21 @@
+
+
+
+ W3C WebSocket API - Create WebSocket - ascii protocol string with separator
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/websockets/Create-protocols-repeated-case-insensitive.htm b/testing/web-platform/tests/websockets/Create-protocols-repeated-case-insensitive.htm
new file mode 100644
index 00000000000..f32ce5bfd58
--- /dev/null
+++ b/testing/web-platform/tests/websockets/Create-protocols-repeated-case-insensitive.htm
@@ -0,0 +1,18 @@
+
+
+
+ W3C WebSocket API - Create WebSocket - repeated protocols with different case
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/websockets/websocket.js b/testing/web-platform/tests/websockets/websocket.js
index 2d2697a1170..79b7bd59c58 100644
--- a/testing/web-platform/tests/websockets/websocket.js
+++ b/testing/web-platform/tests/websockets/websocket.js
@@ -8,6 +8,7 @@ var __CONTROLPATH = "control";
var __PROTOCOL = "echo";
var __PROTOCOLS = ["echo", "chat"];
var __REPEATED__PROTOCOLS = ["echo", "echo"];
+var __REPEATED__PROTOCOLS_CASE_INSENSITIVE = ["echo", "eCho"];
var __URL;
var __IS__WEBSOCKET;
var __PASS = "Pass";
@@ -47,6 +48,12 @@ function CreateWebSocketNonAsciiProtocol(nonAsciiProtocol) {
wsocket = new WebSocket(__URL, nonAsciiProtocol);
}
+function CreateWebSocketWithAsciiSep(asciiWithSep) {
+ IsWebSocket();
+ __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH;
+ wsocket = new WebSocket(__URL, asciiWithSep);
+}
+
function CreateWebSocketWithBlockedPort(blockedPort) {
IsWebSocket();
__URL = "wss://" + __SERVER__NAME + ":" + blockedPort + "/" + __PATH;
@@ -71,6 +78,12 @@ function CreateWebSocketWithRepeatedProtocols() {
wsocket = new WebSocket(__URL, __REPEATED__PROTOCOLS);
}
+function CreateWebSocketWithRepeatedProtocolsCaseInsensitive() {
+ IsWebSocket();
+ __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH;
+ wsocket = new WebSocket(__URL, __REPEATED__PROTOCOLS_CASE_INSENSITIVE);
+}
+
function CreateWebSocket(isSecure, isProtocol, isProtocols) {
IsWebSocket();
if (isSecure) {
diff --git a/testing/web-platform/tests/webvtt/OWNERS b/testing/web-platform/tests/webvtt/OWNERS
new file mode 100644
index 00000000000..dd2b7600f63
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/OWNERS
@@ -0,0 +1,4 @@
+@foolip
+@r12a
+@silviapfeiffer
+@zcorpan