Update web-platform-tests to revision d011702f368b88b3bae86e7a8fd2ddd22e18b33c

This commit is contained in:
Ms2ger 2016-04-12 09:07:41 +02:00
parent f9608022ca
commit 299ad0f9d0
573 changed files with 38776 additions and 14942 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,5 +0,0 @@
[setrequestheader-bogus-value.htm]
type: testharness
[XMLHttpRequest: setRequestHeader() value argument checks 4]
expected: FAIL

View file

@ -0,0 +1,5 @@
[HTMLCollection-as-proto-length-get-throws.html]
type: testharness
[HTMLcollection as a prototype should not allow getting .length on the base object]
expected: FAIL

View file

@ -207,3 +207,9 @@
[Node interface: document.createComment("abc") must inherit property "rootNode" with the proper type (16)] [Node interface: document.createComment("abc") must inherit property "rootNode" with the proper type (16)]
expected: FAIL expected: FAIL
[Element interface: element must inherit property "query" with the proper type (36)]
expected: FAIL
[Element interface: element must inherit property "queryAll" with the proper type (37)]
expected: FAIL

View file

@ -3,3 +3,9 @@
[Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)] [Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)]
expected: FAIL expected: FAIL
[Element in non-HTML namespace, prefix, lowercase name]
expected: FAIL
[Element in non-HTML namespace, prefix, uppercase name]
expected: FAIL

View file

@ -0,0 +1,8 @@
[Element-classlist.html]
type: testharness
[.contains(empty_string) must return false]
expected: FAIL
[.contains(string_with_spaces) must return false]
expected: FAIL

View file

@ -3,3 +3,9 @@
[Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)] [Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)]
expected: FAIL expected: FAIL
[Element in non-HTML namespace, prefix, lowercase name]
expected: FAIL
[Element in non-HTML namespace, prefix, uppercase name]
expected: FAIL

View file

@ -0,0 +1,17 @@
[case.html]
type: testharness
[getElementsByTagName a:abc]
expected: FAIL
[getElementsByTagName a:Abc]
expected: FAIL
[getElementsByTagName a:ABC]
expected: FAIL
[getElementsByTagName a:ä]
expected: FAIL
[getElementsByTagName a:Ä]
expected: FAIL

View file

@ -0,0 +1,5 @@
[remove-unscopable.html]
type: testharness
[remove() should be unscopable]
expected: FAIL

View file

@ -12,3 +12,12 @@
[Encode/decode round trip: utf-16] [Encode/decode round trip: utf-16]
expected: FAIL expected: FAIL
[Decode sample: utf-16le]
expected: FAIL
[Decode sample: utf-16be]
expected: FAIL
[Decode sample: utf-16]
expected: FAIL

View file

@ -18,3 +18,30 @@
[Streaming decode: utf-16be, 5 byte window] [Streaming decode: utf-16be, 5 byte window]
expected: FAIL expected: FAIL
[Streaming decode: utf-8, 1 byte window]
expected: FAIL
[Streaming decode: utf-8, 2 byte window]
expected: FAIL
[Streaming decode: utf-8, 3 byte window]
expected: FAIL
[Streaming decode: utf-8, 4 byte window]
expected: FAIL
[Streaming decode: utf-8, 5 byte window]
expected: FAIL
[Streaming decode: utf-16le, 2 byte window]
expected: FAIL
[Streaming decode: utf-16le, 4 byte window]
expected: FAIL
[Streaming decode: utf-16be, 2 byte window]
expected: FAIL
[Streaming decode: utf-16be, 4 byte window]
expected: FAIL

View file

@ -0,0 +1,119 @@
[textencoder-constructor-non-utf.html]
type: testharness
[Encoding argument not considered for encode: ibm866]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-2]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-3]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-4]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-5]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-6]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-7]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-8]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-8-i]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-10]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-13]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-14]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-15]
expected: FAIL
[Encoding argument not considered for encode: iso-8859-16]
expected: FAIL
[Encoding argument not considered for encode: koi8-r]
expected: FAIL
[Encoding argument not considered for encode: koi8-u]
expected: FAIL
[Encoding argument not considered for encode: macintosh]
expected: FAIL
[Encoding argument not considered for encode: windows-874]
expected: FAIL
[Encoding argument not considered for encode: windows-1250]
expected: FAIL
[Encoding argument not considered for encode: windows-1251]
expected: FAIL
[Encoding argument not considered for encode: windows-1252]
expected: FAIL
[Encoding argument not considered for encode: windows-1253]
expected: FAIL
[Encoding argument not considered for encode: windows-1254]
expected: FAIL
[Encoding argument not considered for encode: windows-1255]
expected: FAIL
[Encoding argument not considered for encode: windows-1256]
expected: FAIL
[Encoding argument not considered for encode: windows-1257]
expected: FAIL
[Encoding argument not considered for encode: windows-1258]
expected: FAIL
[Encoding argument not considered for encode: x-mac-cyrillic]
expected: FAIL
[Encoding argument not considered for encode: gbk]
expected: FAIL
[Encoding argument not considered for encode: gb18030]
expected: FAIL
[Encoding argument not considered for encode: big5]
expected: FAIL
[Encoding argument not considered for encode: euc-jp]
expected: FAIL
[Encoding argument not considered for encode: iso-2022-jp]
expected: FAIL
[Encoding argument not considered for encode: shift_jis]
expected: FAIL
[Encoding argument not considered for encode: euc-kr]
expected: FAIL
[Encoding argument not considered for encode: replacement]
expected: FAIL
[Encoding argument not considered for encode: utf-16be]
expected: FAIL
[Encoding argument not considered for encode: utf-16le]
expected: FAIL
[Encoding argument not considered for encode: x-user-defined]
expected: FAIL

View file

@ -1 +1 @@
0397e2a24d3e5c988b089ef100002397f4cabdfa f9608022caf7f223dfdfe960c31fb5fe7eb0d1f1

View file

@ -792,3 +792,9 @@
[Parsing: <h\tt\nt\rp://h\to\ns\rt:9\t0\n0\r0/p\ta\nt\rh?q\tu\ne\rry#f\tr\na\rg> against <about:blank>] [Parsing: <h\tt\nt\rp://h\to\ns\rt:9\t0\n0\r0/p\ta\nt\rh?q\tu\ne\rry#f\tr\na\rg> against <about:blank>]
expected: FAIL expected: FAIL
[Parsing: <?a=b&c=d> against <http://example.org/foo/bar>]
expected: FAIL
[Parsing: <??a=b&c=d> against <http://example.org/foo/bar>]
expected: FAIL

View file

@ -792,3 +792,9 @@
[Parsing: <h\tt\nt\rp://h\to\ns\rt:9\t0\n0\r0/p\ta\nt\rh?q\tu\ne\rry#f\tr\na\rg> against <about:blank>] [Parsing: <h\tt\nt\rp://h\to\ns\rt:9\t0\n0\r0/p\ta\nt\rh?q\tu\ne\rry#f\tr\na\rg> against <about:blank>]
expected: FAIL expected: FAIL
[Parsing: <?a=b&c=d> against <http://example.org/foo/bar>]
expected: FAIL
[Parsing: <??a=b&c=d> against <http://example.org/foo/bar>]
expected: FAIL

View file

@ -198,3 +198,15 @@
[Parsing: <h\tt\nt\rp://h\to\ns\rt:9\t0\n0\r0/p\ta\nt\rh?q\tu\ne\rry#f\tr\na\rg> against <about:blank>] [Parsing: <h\tt\nt\rp://h\to\ns\rt:9\t0\n0\r0/p\ta\nt\rh?q\tu\ne\rry#f\tr\na\rg> against <about:blank>]
expected: FAIL expected: FAIL
[URL.searchParams updating, clearing]
expected: FAIL
[URL.searchParams and URL.search setters, update propagation]
expected: FAIL
[Parsing: <?a=b&c=d> against <http://example.org/foo/bar>]
expected: FAIL
[Parsing: <??a=b&c=d> against <http://example.org/foo/bar>]
expected: FAIL

View file

@ -12,16 +12,20 @@
<script> <script>
function try_value(value) { function try_value(value) {
test(function() { test(function() {
var client = new XMLHttpRequest() var client = new XMLHttpRequest();
client.open("GET", "...") client.open("GET", "...");
assert_throws("SyntaxError", function() { client.setRequestHeader("x-test", value) }, ' given value ' + value+', ') assert_throws("SyntaxError", function() { client.setRequestHeader("x-test", value) }, ' given value ' + value+', ');
}) });
} }
try_value("t\rt") try_value("t\rt");
try_value("t\nt") try_value("t\nt");
try_value("t\bt"); try_value("t\bt");
try_value("\x7f"); try_value("\x7f");
try_value("テスト") test(function() {
var client = new XMLHttpRequest();
client.open("GET", "...");
assert_throws(new TypeError(), function() { client.setRequestHeader("x-test", "テスト") }, ' given value テスト,');
});
test(function() { test(function() {
var client = new XMLHttpRequest() var client = new XMLHttpRequest()

View file

@ -0,0 +1,6 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>webkit-text-fill-color: untouched</title>
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
<div style="color: green">These texts should be green</div>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>webkit-text-fill-color: green</title>
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
<link rel="help" href="https://compat.spec.whatwg.org/#the-webkit-text-fill-color">
<meta name="assert" content="The color of texts should be green">
<link rel="match" href="webkit-text-fill-color-property-001-ref.html">
<div style="-webkit-text-fill-color: green;">These texts should be green</div>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>webkit-text-fill-color: green</title>
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
<link rel="help" href="https://compat.spec.whatwg.org/#the-webkit-text-fill-color">
<meta name="assert" content="The color of texts should be green">
<link rel="match" href="webkit-text-fill-color-property-001-ref.html">
<div style="color: red; -webkit-text-fill-color: green;">These texts should be green</div>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>webkit-text-fill-color: green</title>
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
<link rel="help" href="https://compat.spec.whatwg.org/#the-webkit-text-fill-color">
<meta name="assert" content="The color of texts should be green">
<link rel="match" href="webkit-text-fill-color-property-001-ref.html">
<div style="color: red; -webkit-text-fill-color: green;">These texts <span style="color: red">should be green</span></div>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>webkit-text-fill-color: green</title>
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
<link rel="help" href="https://compat.spec.whatwg.org/#the-webkit-text-fill-color">
<meta name="assert" content="The color of texts should be green">
<link rel="match" href="webkit-text-fill-color-property-001-ref.html">
<div style="color: transparent; -webkit-text-fill-color: green;">These texts should be green</div>

View file

@ -0,0 +1,13 @@
<!doctype html>
<meta charset=utf-8>
<title>Make sure browsers throw when getting .length on some random object whose proto is an HTMLCollection</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
test(function() {
var obj = Object.create(document.getElementsByTagName("script"));
assert_throws(new TypeError(), function() {
obj.length;
});
}, "HTMLcollection as a prototype should not allow getting .length on the base object")
</script>

View file

@ -310,6 +310,9 @@ interface Element : Node {
HTMLCollection getElementsByTagName(DOMString localName); HTMLCollection getElementsByTagName(DOMString localName);
HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
HTMLCollection getElementsByClassName(DOMString classNames); HTMLCollection getElementsByClassName(DOMString classNames);
Element? insertAdjacentElement(DOMString where, Element element); // historical
void insertAdjacentText(DOMString where, DOMString data); // historical
}; };
interface NamedNodeMap { interface NamedNodeMap {

View file

@ -127,17 +127,19 @@ function test_getElementsByTagName(context, element) {
test(function() { test(function() {
var t = element.appendChild(document.createElementNS("test", "te:st")) var t = element.appendChild(document.createElementNS("test", "te:st"))
this.add_cleanup(function() {element.removeChild(t)}) this.add_cleanup(function() {element.removeChild(t)})
assert_array_equals(context.getElementsByTagName("st"), [t]) assert_array_equals(context.getElementsByTagName("st"), [])
assert_array_equals(context.getElementsByTagName("ST"), []) assert_array_equals(context.getElementsByTagName("ST"), [])
assert_array_equals(context.getElementsByTagName("te:st"), [t])
assert_array_equals(context.getElementsByTagName("te:ST"), [])
}, "Element in non-HTML namespace, prefix, lowercase name") }, "Element in non-HTML namespace, prefix, lowercase name")
test(function() { test(function() {
var t = element.appendChild(document.createElementNS("test", "te:ST")) var t = element.appendChild(document.createElementNS("test", "te:ST"))
this.add_cleanup(function() {element.removeChild(t)}) this.add_cleanup(function() {element.removeChild(t)})
assert_array_equals(context.getElementsByTagName("ST"), [t])
assert_array_equals(context.getElementsByTagName("st"), []) assert_array_equals(context.getElementsByTagName("st"), [])
assert_array_equals(context.getElementsByTagName("ST"), [])
assert_array_equals(context.getElementsByTagName("te:st"), []) assert_array_equals(context.getElementsByTagName("te:st"), [])
assert_array_equals(context.getElementsByTagName("te:ST"), []) assert_array_equals(context.getElementsByTagName("te:ST"), [t])
}, "Element in non-HTML namespace, prefix, uppercase name") }, "Element in non-HTML namespace, prefix, uppercase name")
test(function() { test(function() {

View file

@ -37,17 +37,19 @@ test(function() {
test(function() { test(function() {
var t = document.body.appendChild(document.createElementNS("test", "te:st")) var t = document.body.appendChild(document.createElementNS("test", "te:st"))
this.add_cleanup(function() {document.body.removeChild(t)}) this.add_cleanup(function() {document.body.removeChild(t)})
assert_array_equals(document.getElementsByTagName("st"), [t]) assert_array_equals(document.getElementsByTagName("st"), [])
assert_array_equals(document.getElementsByTagName("ST"), []) assert_array_equals(document.getElementsByTagName("ST"), [])
assert_array_equals(document.getElementsByTagName("te:st"), [t])
assert_array_equals(document.getElementsByTagName("te:ST"), [])
}, "Element in non-HTML namespace, prefix, lowercase name") }, "Element in non-HTML namespace, prefix, lowercase name")
test(function() { test(function() {
var t = document.body.appendChild(document.createElementNS("test", "te:ST")) var t = document.body.appendChild(document.createElementNS("test", "te:ST"))
this.add_cleanup(function() {document.body.removeChild(t)}) this.add_cleanup(function() {document.body.removeChild(t)})
assert_array_equals(document.getElementsByTagName("ST"), [t]) assert_array_equals(document.getElementsByTagName("ST"), [])
assert_array_equals(document.getElementsByTagName("st"), []) assert_array_equals(document.getElementsByTagName("st"), [])
assert_array_equals(document.getElementsByTagName("te:st"), []) assert_array_equals(document.getElementsByTagName("te:st"), [])
assert_array_equals(document.getElementsByTagName("te:ST"), []) assert_array_equals(document.getElementsByTagName("te:ST"), [t])
}, "Element in non-HTML namespace, prefix, uppercase name") }, "Element in non-HTML namespace, prefix, uppercase name")
test(function() { test(function() {

View file

@ -66,8 +66,8 @@ test(function () {
assert_equals( elem.classList.toString(), ' ', 'explicit' ); assert_equals( elem.classList.toString(), ' ', 'explicit' );
}, 'classList should contain initial markup whitespace'); }, 'classList should contain initial markup whitespace');
test(function () { test(function () {
assert_throws( 'SYNTAX_ERR', function () { elem.classList.contains(''); } ); assert_false( elem.classList.contains('') );
}, '.contains(empty_string) must throw a SYNTAX_ERR'); }, '.contains(empty_string) must return false');
test(function () { test(function () {
assert_throws( 'SYNTAX_ERR', function () { elem.classList.add(''); } ); assert_throws( 'SYNTAX_ERR', function () { elem.classList.add(''); } );
}, '.add(empty_string) must throw a SYNTAX_ERR'); }, '.add(empty_string) must throw a SYNTAX_ERR');
@ -85,8 +85,8 @@ test(function () {
assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('', ''); } ); assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('', ''); } );
}, '.replace with empty_string must throw a SYNTAX_ERR'); }, '.replace with empty_string must throw a SYNTAX_ERR');
test(function () { test(function () {
assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.contains('a b'); } ); assert_false( elem.classList.contains('a b') );
}, '.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR'); }, '.contains(string_with_spaces) must return false');
test(function () { test(function () {
assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.add('a b'); } ); assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.add('a b'); } );
}, '.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR'); }, '.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR');

View file

@ -0,0 +1,91 @@
<!doctype html>
<meta charset=utf-8>
<title></title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<div id="target"></div>
<div id="parent"><span id=target2></span></div>
<div id="log" style="visibility:visible"></div>
<span id="test1"></span>
<span id="test2"></span>
<span id="test3"></span>
<span id="test4"></span>
<script>
var target = document.getElementById("target");
var target2 = document.getElementById("target2");
test(function() {
assert_throws("SyntaxError", function() {
target.insertAdjacentElement("test", document.getElementById("test1"))
});
assert_throws("SyntaxError", function() {
target2.insertAdjacentElement("test", document.getElementById("test1"))
});
}, "Inserting to an invalid location should cause a Syntax Error exception")
test(function() {
var el = target.insertAdjacentElement("beforebegin", document.getElementById("test1"));
assert_equals(target.previousSibling.id, "test1");
assert_equals(el.id, "test1");
el = target2.insertAdjacentElement("beforebegin", document.getElementById("test1"));
assert_equals(target2.previousSibling.id, "test1");
assert_equals(el.id, "test1");
}, "Inserted element should be target element's previous sibling for 'beforebegin' case")
test(function() {
var el = target.insertAdjacentElement("afterbegin", document.getElementById("test2"));
assert_equals(target.firstChild.id, "test2");
assert_equals(el.id, "test2");
el = target2.insertAdjacentElement("afterbegin", document.getElementById("test2"));
assert_equals(target2.firstChild.id, "test2");
assert_equals(el.id, "test2");
}, "Inserted element should be target element's first child for 'afterbegin' case")
test(function() {
var el = target.insertAdjacentElement("beforeend", document.getElementById("test3"));
assert_equals(target.lastChild.id, "test3");
assert_equals(el.id, "test3");
el = target2.insertAdjacentElement("beforeend", document.getElementById("test3"));
assert_equals(target2.lastChild.id, "test3");
assert_equals(el.id, "test3");
}, "Inserted element should be target element's last child for 'beforeend' case")
test(function() {
var el = target.insertAdjacentElement("afterend", document.getElementById("test4"));
assert_equals(target.nextSibling.id, "test4");
assert_equals(el.id, "test4");
el = target2.insertAdjacentElement("afterend", document.getElementById("test4"));
assert_equals(target2.nextSibling.id, "test4");
assert_equals(el.id, "test4");
}, "Inserted element should be target element's next sibling for 'afterend' case")
test(function() {
var docElement = document.documentElement;
docElement.style.visibility="hidden";
assert_throws("HierarchyRequestError", function() {
var el = docElement.insertAdjacentElement("beforebegin", document.getElementById("test1"));
assert_equals(el, null);
});
var el = docElement.insertAdjacentElement("afterbegin", document.getElementById("test2"));
assert_equals(docElement.firstChild.id, "test2");
assert_equals(el.id, "test2");
el = docElement.insertAdjacentElement("beforeend", document.getElementById("test3"));
assert_equals(docElement.lastChild.id, "test3");
assert_equals(el.id, "test3");
assert_throws("HierarchyRequestError", function() {
var el = docElement.insertAdjacentElement("afterend", document.getElementById("test4"));
assert_equals(el, null);
});
}, "Adding more than one child to document should cause a HierarchyRequestError exception")
</script>

View file

@ -0,0 +1,76 @@
<!doctype html>
<meta charset=utf-8>
<title></title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<body style="visibility:hidden">
<div id="target"></div>
<div id="parent"><span id=target2></span></div>
<div id="log" style="visibility:visible"></div>
</body>
<script>
var target = document.getElementById("target");
var target2 = document.getElementById("target2");
test(function() {
assert_throws("SyntaxError", function() {
target.insertAdjacentText("test", "text")
});
assert_throws("SyntaxError", function() {
target2.insertAdjacentText("test", "test")
});
}, "Inserting to an invalid location should cause a Syntax Error exception")
test(function() {
target.insertAdjacentText("beforebegin", "test1");
assert_equals(target.previousSibling.nodeValue, "test1");
target2.insertAdjacentText("beforebegin", "test1");
assert_equals(target2.previousSibling.nodeValue, "test1");
}, "Inserted text node should be target element's previous sibling for 'beforebegin' case")
test(function() {
target.insertAdjacentText("afterbegin", "test2");
assert_equals(target.firstChild.nodeValue, "test2");
target2.insertAdjacentText("afterbegin", "test2");
assert_equals(target2.firstChild.nodeValue, "test2");
}, "Inserted text node should be target element's first child for 'afterbegin' case")
test(function() {
target.insertAdjacentText("beforeend", "test3");
assert_equals(target.lastChild.nodeValue, "test3");
target2.insertAdjacentText("beforeend", "test3");
assert_equals(target2.lastChild.nodeValue, "test3");
}, "Inserted text node should be target element's last child for 'beforeend' case")
test(function() {
target.insertAdjacentText("afterend", "test4");
assert_equals(target.nextSibling.nodeValue, "test4");
target2.insertAdjacentText("afterend", "test4");
assert_equals(target.nextSibling.nodeValue, "test4");
}, "Inserted text node should be target element's next sibling for 'afterend' case")
test(function() {
var docElement = document.documentElement;
docElement.style.visibility="hidden";
assert_throws("HierarchyRequestError", function() {
docElement.insertAdjacentText("beforebegin", "text1")
});
docElement.insertAdjacentText("afterbegin", "test2");
assert_equals(docElement.firstChild.nodeValue, "test2");
docElement.insertAdjacentText("beforeend", "test3");
assert_equals(docElement.lastChild.nodeValue, "test3");
assert_throws("HierarchyRequestError", function() {
docElement.insertAdjacentText("afterend", "test4")
});
}, "Adding more than one child to document should cause a HierarchyRequestError exception")
</script>

View file

@ -73,6 +73,13 @@ function ascii_lowercase(input) {
}); });
} }
function get_qualified_name(el) {
if (el.prefix) {
return el.prefix + ":" + el.localName;
}
return el.localName;
}
function test_create_element(name) { function test_create_element(name) {
var node = document.createElement(name); var node = document.createElement(name);
assert_equals(node.localName, expected_case(name)); assert_equals(node.localName, expected_case(name));
@ -133,9 +140,9 @@ function test_get_elements_tag_name(elements_to_create, search_string) {
var expected = Array.prototype.filter.call(container.childNodes, var expected = Array.prototype.filter.call(container.childNodes,
function(node) { function(node) {
if (is_html && node.namespaceURI === "http://www.w3.org/1999/xhtml") { if (is_html && node.namespaceURI === "http://www.w3.org/1999/xhtml") {
return node.localName === expected_case(search_string); return get_qualified_name(node) === expected_case(search_string);
} else { } else {
return node.localName === search_string; return get_qualified_name(node) === search_string;
} }
}); });
document.documentElement.appendChild(container); document.documentElement.appendChild(container);

View file

@ -0,0 +1,18 @@
<!doctype html>
<meta charset=utf-8>
<title></title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<div id="testDiv" onclick="result1 = remove; result2 = this.remove;"></div>
<script>
var remove = "Hello there";
var result1;
var result2;
test(function() {
assert_true(Element.prototype[Symbol.unscopables].remove);
var div = document.querySelector("#testDiv");
div.dispatchEvent(new Event("click"));
assert_equals(typeof result1, "string");
assert_equals(typeof result2, "function");
}, "remove() should be unscopable")
</script>

View file

@ -15,13 +15,11 @@ test(function() {
}, 'Default inputs'); }, 'Default inputs');
function testEncodeDecodeSample(encoding, string, bytes) { function testDecodeSample(encoding, string, bytes) {
test(function() { test(function() {
var encoded = new TextEncoder(encoding).encode(string);
assert_array_equals([].slice.call(encoded), bytes);
assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes)), string); assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes)), string);
assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes).buffer), string); assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes).buffer), string);
}, 'Encode/decode round trip: ' + encoding); }, 'Decode sample: ' + encoding);
} }
// z (ASCII U+007A), cent (Latin-1 U+00A2), CJK water (BMP U+6C34), // z (ASCII U+007A), cent (Latin-1 U+00A2), CJK water (BMP U+6C34),
@ -29,25 +27,29 @@ function testEncodeDecodeSample(encoding, string, bytes) {
// byte-swapped BOM (non-character U+FFFE) // byte-swapped BOM (non-character U+FFFE)
var sample = 'z\xA2\u6C34\uD834\uDD1E\uF8FF\uDBFF\uDFFD\uFFFE'; var sample = 'z\xA2\u6C34\uD834\uDD1E\uF8FF\uDBFF\uDFFD\uFFFE';
testEncodeDecodeSample( test(function() {
'utf-8', var encoding = 'utf-8';
sample, var string = sample;
[0x7A, 0xC2, 0xA2, 0xE6, 0xB0, 0xB4, 0xF0, 0x9D, 0x84, 0x9E, 0xEF, 0xA3, 0xBF, 0xF4, 0x8F, 0xBF, 0xBD, 0xEF, 0xBF, 0xBE] var bytes = [0x7A, 0xC2, 0xA2, 0xE6, 0xB0, 0xB4, 0xF0, 0x9D, 0x84, 0x9E, 0xEF, 0xA3, 0xBF, 0xF4, 0x8F, 0xBF, 0xBD, 0xEF, 0xBF, 0xBE];
); var encoded = new TextEncoder().encode(string);
assert_array_equals([].slice.call(encoded), bytes);
assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes)), string);
assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes).buffer), string);
}, 'Encode/decode round trip: utf-8');
testEncodeDecodeSample( testDecodeSample(
'utf-16le', 'utf-16le',
sample, sample,
[0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xF8, 0xFF, 0xDB, 0xFD, 0xDF, 0xFE, 0xFF] [0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xF8, 0xFF, 0xDB, 0xFD, 0xDF, 0xFE, 0xFF]
); );
testEncodeDecodeSample( testDecodeSample(
'utf-16be', 'utf-16be',
sample, sample,
[0x00, 0x7A, 0x00, 0xA2, 0x6C, 0x34, 0xD8, 0x34, 0xDD, 0x1E, 0xF8, 0xFF, 0xDB, 0xFF, 0xDF, 0xFD, 0xFF, 0xFE] [0x00, 0x7A, 0x00, 0xA2, 0x6C, 0x34, 0xD8, 0x34, 0xDD, 0x1E, 0xF8, 0xFF, 0xDB, 0xFF, 0xDF, 0xFD, 0xFF, 0xFE]
); );
testEncodeDecodeSample( testDecodeSample(
'utf-16', 'utf-16',
sample, sample,
[0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xF8, 0xFF, 0xDB, 0xFD, 0xDF, 0xFE, 0xFF] [0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xF8, 0xFF, 0xDB, 0xFD, 0xDF, 0xFE, 0xFF]

View file

@ -23,10 +23,6 @@ setup(function() {
}); });
tests.forEach(function(input) { tests.forEach(function(input) {
test(function() {
assert_throws(new RangeError(), function() { new TextEncoder(input); });
}, 'Invalid label ' + format_value(input) + ' should be rejected by TextEncoder.');
test(function() { test(function() {
assert_throws(new RangeError(), function() { new TextDecoder(input); }); assert_throws(new RangeError(), function() { new TextDecoder(input); });
}, 'Invalid label ' + format_value(input) + ' should be rejected by TextDecoder.'); }, 'Invalid label ' + format_value(input) + ' should be rejected by TextDecoder.');

View file

@ -6,7 +6,6 @@
<script> <script>
test(function() { test(function() {
assert_throws(new RangeError(), function() { new TextEncoder('replacement'); });
assert_throws(new RangeError(), function() { new TextDecoder('replacement'); }); assert_throws(new RangeError(), function() { new TextDecoder('replacement'); });
}, 'The "replacement" label should not be a known encoding.'); }, 'The "replacement" label should not be a known encoding.');
@ -16,7 +15,6 @@ encodings_table.forEach(function(section) {
}).forEach(function(encoding) { }).forEach(function(encoding) {
encoding.labels.forEach(function(label) { encoding.labels.forEach(function(label) {
test(function() { test(function() {
assert_throws(new RangeError(), function() { new TextEncoder(label); });
assert_throws(new RangeError(), function() { new TextDecoder(label); }); assert_throws(new RangeError(), function() { new TextDecoder(label); });
}, 'Label for "replacement" should be rejected by API: ' + label); }, 'Label for "replacement" should be rejected by API: ' + label);
}); });

View file

@ -38,7 +38,7 @@ interface TextDecoder {
// 8.2 Interface TextDecoder // 8.2 Interface TextDecoder
[Constructor(optional DOMString utfLabel = "utf-8"), [Constructor,
Exposed=Window,Worker] Exposed=Window,Worker]
interface TextEncoder { interface TextEncoder {
readonly attribute DOMString encoding; readonly attribute DOMString encoding;

View file

@ -5,12 +5,23 @@
<script src="resources/encodings.js"></script> <script src="resources/encodings.js"></script>
<script> <script>
var string = '\\x00123ABCabc\\x80\\xFF\\u0100\\u1000\\uFFFD\\uD800\\uDC00\\uDBFF\\uDFFF'; var string = '\x00123ABCabc\x80\xFF\u0100\u1000\uFFFD\uD800\uDC00\uDBFF\uDFFF';
var octets = {
'utf-16le': [0x00,0x00,0x31,0x00,0x32,0x00,0x33,0x00,0x41,0x00,0x42,0x00,
0x43,0x00,0x61,0x00,0x62,0x00,0x63,0x00,0x80,0x00,0xFF,0x00,
0x00,0x01,0x00,0x10,0xFD,0xFF,0x00,0xD8,0x00,0xDC,0xFF,0xDB,
0xFF,0xDF],
'utf-16be': [0x00,0x00,0x00,0x31,0x00,0x32,0x00,0x33,0x00,0x41,0x00,0x42,
0x00,0x43,0x00,0x61,0x00,0x62,0x00,0x63,0x00,0x80,0x00,0xFF,
0x01,0x00,0x10,0x00,0xFF,0xFD,0xD8,0x00,0xDC,0x00,0xDB,0xFF,
0xDF,0xFF]
};
utf_encodings.forEach(function (encoding) { utf_encodings.forEach(function (encoding) {
for (var len = 1; len <= 5; ++len) { for (var len = 1; len <= 5; ++len) {
test(function() { test(function() {
var encoded = new TextEncoder(encoding).encode(string); var encoded = octets[encoding] ||
new TextEncoder(encoding).encode(string);
var out = ''; var out = '';
var decoder = new TextDecoder(encoding); var decoder = new TextDecoder(encoding);

View file

@ -6,20 +6,16 @@
<script> <script>
encodings_table.forEach(function(section) { encodings_table.forEach(function(section) {
section.encodings.filter(function(encoding) { section.encodings.forEach(function(encoding) {
return encoding.name !== 'replacement'; if (encoding.name !== 'replacement') {
}).forEach(function(encoding) {
if (utf_encodings.indexOf(encoding.name) !== -1) {
test(function() { test(function() {
assert_equals(new TextDecoder(encoding.name).encoding, encoding.name); assert_equals(new TextDecoder(encoding.name).encoding, encoding.name);
assert_equals(new TextEncoder(encoding.name).encoding, encoding.name); }, 'Encoding argument supported for decode: ' + encoding.name);
}, 'UTF encodings are supported for encode and decode: ' + encoding.name);
} else {
test(function() {
assert_equals(new TextDecoder(encoding.name).encoding, encoding.name);
assert_throws(new RangeError(), function() { new TextEncoder(encoding.name); });
}, 'Non-UTF encodings supported only for decode, not encode: ' + encoding.name);
} }
test(function() {
assert_equals(new TextEncoder(encoding.name).encoding, 'utf-8');
}, 'Encoding argument not considered for encode: ' + encoding.name);
}); });
}); });

View file

@ -3,14 +3,14 @@ if (this.document === undefined) {
importScripts("../resources/utils.js"); importScripts("../resources/utils.js");
} }
var origin = "http://{{host}}:{{ports[http][0]}}"; var referrerOrigin = "http://{{host}}:{{ports[http][0]}}/";
var fetchedUrl = RESOURCES_DIR + "inspect-headers.py?headers=referer"; var fetchedUrl = RESOURCES_DIR + "inspect-headers.py?headers=referer";
promise_test(function(test) { promise_test(function(test) {
return fetch(fetchedUrl).then(function(resp) { return fetch(fetchedUrl).then(function(resp) {
assert_equals(resp.status, 200, "HTTP status is 200"); assert_equals(resp.status, 200, "HTTP status is 200");
assert_equals(resp.type , "basic", "Response's type is basic"); assert_equals(resp.type , "basic", "Response's type is basic");
assert_equals(resp.headers.get("x-request-referer"), origin, "request's referrer is " + origin); assert_equals(resp.headers.get("x-request-referer"), referrerOrigin, "request's referrer is " + referrerOrigin);
}); });
}, "Request's referrer is origin"); }, "Request's referrer is origin");

View file

@ -29,8 +29,8 @@ if (window.location.search) {
} }
var testContainer = document.querySelector('#testContainer'); var testContainer = document.querySelector('#testContainer');
var outerWidth = testContainer.getBoundingClientRect().width; var testContainerWidth = testContainer.getBoundingClientRect().width;
var outerHeight = testContainer.getBoundingClientRect().height; var testContainerHeight = testContainer.getBoundingClientRect().height;
SVGSizing.doCombinationTest( SVGSizing.doCombinationTest(
[["placeholder", [ null ]], [["placeholder", [ null ]],
@ -45,7 +45,8 @@ SVGSizing.doCombinationTest(
var testData = new SVGSizing.TestData(config); var testData = new SVGSizing.TestData(config);
var expectedRect = var expectedRect =
testData.computeInlineReplacedSize(outerWidth, outerHeight); testData.computeInlineReplacedSize(testContainerWidth,
testContainerHeight);
var svgElement = testData.buildSVGOrPlaceholder(); var svgElement = testData.buildSVGOrPlaceholder();
var container = var container =
testData.buildContainer(svgElement); testData.buildContainer(svgElement);

View file

@ -157,10 +157,6 @@ function assert_nodelist_contents_equal_noorder(actual, expected, message) {
} }
} }
function isVisible(el) {
return el.offsetTop != 0;
}
function isVoidElement(elementName) { function isVoidElement(elementName) {
return HTML5_VOID_ELEMENTS.indexOf(elementName) >= 0; return HTML5_VOID_ELEMENTS.indexOf(elementName) >= 0;
} }

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<iframe src="{{location[scheme]}}://{{domains[www2]}}:{{ports[http][0]}}{{location[path]}}/../Promise-incumbent-global-subsubframe.sub.html"></iframe>
<script>
document.domain = "{{host}}";
onmessage = function(e) {
if (e.data == "start") {
frames[0].Promise.resolve().then(frames[0].postMessage.bind(frames[0], "start", "*"));
} else {
parent.postMessage(e.data, "*");
}
}
</script>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<script>
document.domain = "{{host}}";
onmessage = function (e) {
parent.postMessage(
{
actual: e.origin,
expected: "{{location[scheme]}}://{{domains[www1]}}:{{ports[http][0]}}",
reason: "Incumbent should have been the caller of then()"
},
"*");
}
</script>

View file

@ -0,0 +1,20 @@
<!doctype html>
<meta charset=utf-8>
<title></title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<iframe src="{{location[scheme]}}://{{domains[www1]}}:{{ports[http][0]}}{{location[path]}}/../Promise-incumbent-global-subframe.sub.html"></iframe>
<script>
var t = async_test("Check the incumbent global Promise callbacks are called with");
onload = t.step_func(function() {
onmessage = t.step_func_done(function(e) {
var d = e.data;
assert_equals(d.actual, d.expected, d.reason);
});
frames[0].postMessage("start", "*");
});
</script>

View file

@ -105,6 +105,9 @@ W3C-TEST.ORG:subresource-integrity/refresh-header.js.headers
# semi-legitimate use of console.* # semi-legitimate use of console.*
CONSOLE:streams/resources/test-utils.js CONSOLE:streams/resources/test-utils.js
CONSOLE:service-workers/service-worker/resources/navigation-redirect-other-origin.html
CONSOLE:service-workers/service-worker/navigation-redirect.https.html
CONSOLE:service-workers/service-worker/resources/clients-get-other-origin.html
# Lint doesn't know about sub.svg I guess # Lint doesn't know about sub.svg I guess
PARSE-FAILED:content-security-policy/svg/including.sub.svg PARSE-FAILED:content-security-policy/svg/including.sub.svg

View file

@ -1,5 +1,6 @@
<!doctype html> <!doctype html>
<title>Selection.collapse() tests</title> <title>Selection.collapse() tests</title>
<meta name=timeout content=long>
<div id=log></div> <div id=log></div>
<script src=/resources/testharness.js></script> <script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script> <script src=/resources/testharnessreport.js></script>

View file

@ -1,6 +1,7 @@
<!doctype html> <!doctype html>
<title>Selection extend() tests</title> <title>Selection extend() tests</title>
<meta charset=utf-8> <meta charset=utf-8>
<meta name=timeout content=long>
<body> <body>
<script src=/resources/testharness.js></script> <script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script> <script src=/resources/testharnessreport.js></script>

View file

@ -0,0 +1,11 @@
<!DOCTYPE html>
<title>ServiceWorkerGlobalScope: close operation</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.sub.js"></script>
<script>
service_worker_test(
'resources/close-worker.js', 'ServiceWorkerGlobalScope: close operation');
</script>

View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<title>ServiceWorkerGlobalScope: registration</title>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='../resources/test-helpers.sub.js'></script>
<script>
promise_test(function(t) {
var script = 'resources/registration-attribute-worker.js';
var scope = 'resources/scope/registration-attribute';
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(frame) {
var expected_events_seen = [
'updatefound',
'install',
'statechange(installed)',
'statechange(activating)',
'activate',
'statechange(activated)',
'fetch',
];
assert_equals(
frame.contentDocument.body.textContent,
expected_events_seen.toString(),
'Service Worker should respond to fetch');
frame.remove();
return service_worker_unregister_and_done(t, scope);
});
}, 'Verify registration attribute on ServiceWorkerGlobalScope');
</script>

View file

@ -0,0 +1,8 @@
importScripts('../../resources/interfaces.js');
importScripts('../../resources/worker-testharness.js');
test(function() {
assert_throws({name: 'InvalidAccessError'}, function() {
self.close();
});
}, 'ServiceWorkerGlobalScope close operation');

View file

@ -0,0 +1,132 @@
importScripts('../../resources/test-helpers.sub.js');
importScripts('../../resources/worker-testharness.js');
var events_seen = [];
assert_equals(
self.registration.scope,
normalizeURL('scope/registration-attribute'),
'On worker script evaluation, registration attribute should be set');
assert_equals(
self.registration.installing,
null,
'On worker script evaluation, installing worker should be null');
assert_equals(
self.registration.waiting,
null,
'On worker script evaluation, waiting worker should be null');
assert_equals(
self.registration.active,
null,
'On worker script evaluation, active worker should be null');
self.registration.addEventListener('updatefound', function() {
events_seen.push('updatefound');
assert_equals(
self.registration.scope,
normalizeURL('scope/registration-attribute'),
'On updatefound event, registration attribute should be set');
assert_equals(
self.registration.installing.scriptURL,
normalizeURL('registration-attribute-worker.js'),
'On updatefound event, installing worker should be set');
assert_equals(
self.registration.waiting,
null,
'On updatefound event, waiting worker should be null');
assert_equals(
self.registration.active,
null,
'On updatefound event, active worker should be null');
assert_equals(
self.registration.installing.state,
'installing',
'On updatefound event, worker should be in the installing state');
var worker = self.registration.installing;
self.registration.installing.addEventListener('statechange', function() {
events_seen.push('statechange(' + worker.state + ')');
});
});
self.addEventListener('install', function(e) {
events_seen.push('install');
assert_equals(
self.registration.scope,
normalizeURL('scope/registration-attribute'),
'On install event, registration attribute should be set');
assert_equals(
self.registration.installing.scriptURL,
normalizeURL('registration-attribute-worker.js'),
'On install event, installing worker should be set');
assert_equals(
self.registration.waiting,
null,
'On install event, waiting worker should be null');
assert_equals(
self.registration.active,
null,
'On install event, active worker should be null');
assert_equals(
self.registration.installing.state,
'installing',
'On install event, worker should be in the installing state');
});
self.addEventListener('activate', function(e) {
events_seen.push('activate');
assert_equals(
self.registration.scope,
normalizeURL('scope/registration-attribute'),
'On activate event, registration attribute should be set');
assert_equals(
self.registration.installing,
null,
'On activate event, installing worker should be null');
assert_equals(
self.registration.waiting,
null,
'On activate event, waiting worker should be null');
assert_equals(
self.registration.active.scriptURL,
normalizeURL('registration-attribute-worker.js'),
'On activate event, active worker should be set');
assert_equals(
self.registration.active.state,
'activating',
'On activate event, worker should be in the activating state');
});
self.addEventListener('fetch', function(e) {
events_seen.push('fetch');
assert_equals(
self.registration.scope,
normalizeURL('scope/registration-attribute'),
'On fetch event, registration attribute should be set');
assert_equals(
self.registration.installing,
null,
'On fetch event, installing worker should be null');
assert_equals(
self.registration.waiting,
null,
'On fetch event, waiting worker should be null');
assert_equals(
self.registration.active.scriptURL,
normalizeURL('registration-attribute-worker.js'),
'On fetch event, active worker should be set');
assert_equals(
self.registration.active.state,
'activated',
'On fetch event, worker should be in the activated state');
e.respondWith(new Response(events_seen));
});

View file

@ -0,0 +1,23 @@
function matchQuery(query) {
return self.location.href.indexOf(query) != -1;
}
if (matchQuery('?evaluation'))
self.registration.unregister();
self.addEventListener('install', function(e) {
if (matchQuery('?install'))
self.registration.unregister();
});
self.addEventListener('activate', function(e) {
if (matchQuery('?activate'))
self.registration.unregister();
});
self.addEventListener('message', function(e) {
self.registration.unregister()
.then(function(result) {
e.data.port.postMessage({result: result});
});
});

View file

@ -0,0 +1,25 @@
importScripts('../../resources/test-helpers.sub.js');
importScripts('../../resources/worker-testharness.js');
var events_seen = [];
self.registration.addEventListener('updatefound', function() {
events_seen.push('updatefound');
});
self.addEventListener('activate', function(e) {
events_seen.push('activate');
});
self.addEventListener('fetch', function(e) {
events_seen.push('fetch');
e.respondWith(new Response(events_seen));
});
self.addEventListener('message', function(e) {
events_seen.push('message');
self.registration.update();
});
// update() during the script evaluation should be ignored.
self.registration.update();

View file

@ -0,0 +1,14 @@
import os
import time
def main(request, response):
# update() does not bypass cache so set the max-age to 0 such that update()
# can find a new version in the network.
headers = [('Cache-Control', 'max-age: 0'),
('Content-Type', 'application/javascript')]
with open(os.path.join(os.path.dirname(__file__),
'update-worker.js'), 'r') as file:
script = file.read()
# Return a different script for each access.
return headers, '// %s\n%s' % (time.time(), script)

View file

@ -0,0 +1,127 @@
<!DOCTYPE html>
<title>ServiceWorkerGlobalScope: unregister</title>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='../resources/test-helpers.sub.js'></script>
<script>
promise_test(function(t) {
var script = 'resources/unregister-worker.js?evaluation';
var scope = 'resources/scope/unregister-on-script-evaluation';
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'redundant');
})
.then(function() {
return navigator.serviceWorker.getRegistration(scope);
})
.then(function(result) {
assert_equals(
result,
undefined,
'After unregister(), the registration should not found');
return service_worker_unregister_and_done(t, scope);
});
}, 'Unregister on script evaluation');
promise_test(function(t) {
var script = 'resources/unregister-worker.js?install';
var scope = 'resources/scope/unregister-on-install-event';
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'redundant');
})
.then(function() {
return navigator.serviceWorker.getRegistration(scope);
})
.then(function(result) {
assert_equals(
result,
undefined,
'After unregister(), the registration should not found');
return service_worker_unregister_and_done(t, scope);
});
}, 'Unregister on installing event');
promise_test(function(t) {
var script = 'resources/unregister-worker.js?activate';
var scope = 'resources/scope/unregister-on-activate-event';
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'redundant');
})
.then(function() {
return navigator.serviceWorker.getRegistration(scope);
})
.then(function(result) {
assert_equals(
result,
undefined,
'After unregister(), the registration should not found');
return service_worker_unregister_and_done(t, scope);
});
}, 'Unregister on activate event');
promise_test(function(t) {
var script = 'resources/unregister-worker.js';
var scope = 'resources/unregister-controlling-worker.html';
var controller;
var frame;
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(f) {
frame = f;
controller = frame.contentWindow.navigator.serviceWorker.controller;
assert_equals(
controller.scriptURL,
normalizeURL(script),
'Service worker should control a new document')
// Wait for the completion of unregister() on the worker.
var channel = new MessageChannel();
var promise = new Promise(function(resolve) {
channel.port1.onmessage = t.step_func(function(e) {
assert_true(e.data.result,
'unregister() should successfully finish');
resolve();
});
});
controller.postMessage({port: channel.port2}, [channel.port2]);
return promise;
})
.then(function() {
return navigator.serviceWorker.getRegistration(scope);
})
.then(function(result) {
assert_equals(
result,
undefined,
'After unregister(), the registration should not found');
assert_equals(
frame.contentWindow.navigator.serviceWorker.controller,
controller,
'After unregister(), the worker should still control the document');
return with_iframe(scope);
})
.then(function(new_frame) {
assert_equals(
new_frame.contentWindow.navigator.serviceWorker.controller,
null,
'After unregister(), the worker should not control a new document');
frame.remove();
new_frame.remove();
return service_worker_unregister_and_done(t, scope);
})
}, 'Unregister controlling service worker');
</script>

View file

@ -0,0 +1,45 @@
<!DOCTYPE html>
<title>ServiceWorkerGlobalScope: update</title>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='../resources/test-helpers.sub.js'></script>
<script>
promise_test(function(t) {
var script = 'resources/update-worker.py';
var scope = 'resources/scope/update';
var registration;
var frame1;
return service_worker_unregister_and_register(t, script, scope)
.then(function(r) {
registration = r;
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(f) {
frame1 = f;
registration.active.postMessage('update');
return wait_for_update(t, registration);
})
.then(function() { return with_iframe(scope); })
.then(function(frame2) {
var expected_events_seen = [
'updatefound', // by register().
'activate',
'fetch',
'message',
'updatefound', // by update() in the message handler.
'fetch',
];
assert_equals(
frame2.contentDocument.body.textContent,
expected_events_seen.toString(),
'events seen by the worker');
frame1.remove();
frame2.remove();
return service_worker_unregister_and_done(t, scope);
});
}, 'Update a registration on ServiceWorkerGlobalScope');
</script>

View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<title>Service Worker: registration events</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
promise_test(function(t) {
var script = 'resources/empty-worker.js';
var scope = 'resources/blank.html';
var registration;
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
var sw = registration.installing;
return new Promise(t.step_func(function(resolve) {
sw.onstatechange = t.step_func(function() {
if (sw.state === 'installed') {
assert_equals(registration.active, null,
'installed event should be fired before activating service worker');
resolve();
}
});
}));
})
.then(function() {
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'installed event should be fired before activating service worker');
</script>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<title>Service Worker: Activation occurs after registration</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
var t = async_test('activation occurs after registration');
t.step(function() {
var scope = 'resources/blank.html';
var registration;
service_worker_unregister_and_register(
t, 'resources/empty-worker.js', scope)
.then(function(r) {
registration = r;
assert_equals(
r.installing.state,
'installing',
'worker should be in the "installing" state upon registration');
return wait_for_state(t, r.installing, 'activated');
})
.then(function() {
service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
});
</script>
</body>

View file

@ -0,0 +1,55 @@
<!DOCTYPE html>
<title>ServiceWorker: navigator.serviceWorker.active</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
// "active" is set
async_test(function(t) {
var step = t.step_func.bind(t);
var url = 'resources/empty-worker.js';
var scope = 'resources/blank.html';
var frame;
var registration;
service_worker_unregister(t, scope)
.then(step(function() { return with_iframe(scope); }))
.then(step(function(f) {
frame = f;
return navigator.serviceWorker.register(url, {scope: scope});
}))
.then(step(function(r) {
registration = r;
return wait_for_state(t, r.installing, 'activating');
}))
.then(step(function() {
var container = frame.contentWindow.navigator.serviceWorker;
assert_equals(
container.controller,
null,
'On activating state a document should not have a controller');
assert_equals(
registration.active.scriptURL,
normalizeURL(url),
'On activating state a document should have an active worker ');
assert_equals(
registration.waiting,
null,
'On activating state a document should not have a waiting worker');
assert_equals(
registration.installing,
null,
'On activating state a document should not have an installing ' +
'worker');
// FIXME: Add a test for a frame created after installation.
// Should the existing frame ("frame") block activation?
}))
.then(step(function() {
frame.remove();
return service_worker_unregister_and_done(t, scope);
}))
.catch(unreached_rejection(t));
}, 'active is set');
</script>

View file

@ -0,0 +1,91 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
var INSTALL_APPCACHE_URL = "resources/appcache-ordering.install.html";
var IS_APPCACHED_URL = "resources/appcache-ordering.is-appcached.html";
var SERVICE_WORKER_SCOPE = "resources/appcache-ordering";
var SERVICE_WORKER_SCRIPT = "resources/empty-worker.js";
var resolve_install_appcache = undefined;
var reject_install_appcache = undefined;
var frames = [];
// Called by the INSTALL_APPCACHE_URL child frame.
function notify_appcache_installed(success) {
if (success)
resolve_install_appcache();
else
reject_install_appcache();
}
function install_appcache() {
return new Promise(function(resolve, reject) {
var frame = document.createElement('iframe');
frames.push(frame);
frame.src = INSTALL_APPCACHE_URL;
document.body.appendChild(frame);
resolve_install_appcache = function() {
document.body.removeChild(frame);
resolve();
};
reject_install_appcache = function() {
document.body.removeChild(frame);
reject();
};
});
}
var resolve_is_appcached = undefined;
// Called by the IS_APPCACHED_URL child frame.
function notify_is_appcached(is) {
resolve_is_appcached(is);
}
function is_appcached() {
return new Promise(function(resolve) {
var frame = document.createElement('iframe');
frames.push(frame);
frame.src = IS_APPCACHED_URL;
document.body.appendChild(frame);
resolve_is_appcached = function(is) {
document.body.removeChild(frame);
resolve(is);
};
});
}
async_test(function(t) {
service_worker_unregister(t, SERVICE_WORKER_SCOPE)
.then(function() {
return install_appcache();
})
.then(function() {
return is_appcached();
})
.then(function(result) {
assert_true(result, 'appcache should initially be utilized');
return service_worker_unregister_and_register(
t, SERVICE_WORKER_SCRIPT, SERVICE_WORKER_SCOPE);
})
.then(function(r) {
return wait_for_state(t, r.installing, 'activated');
})
.then(function() {
return is_appcached();
})
.then(function(result) {
assert_false(result, 'but serviceworkers should take priority');
frames.forEach(function(f) { f.remove(); });
service_worker_unregister_and_done(t, SERVICE_WORKER_SCOPE);
})
.catch(unreached_rejection(t));
}, 'serviceworkers take priority over appcaches');
</script>
</body>

View file

@ -0,0 +1,123 @@
<!DOCTYPE html>
<title>Service Worker: claim client not using registration</title>
<script src="/resources/testharness.js"></script>
<script src="resources/testharness-helpers.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
promise_test(function(t) {
var init_scope = 'resources/blank.html?not-using-init';
var claim_scope = 'resources/blank.html?not-using';
var init_worker_url = 'resources/empty.js';
var claim_worker_url = 'resources/claim-worker.js';
var claim_worker, claim_registration, frame1, frame2;
return service_worker_unregister_and_register(
t, init_worker_url, init_scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
return Promise.all(
[with_iframe(init_scope), with_iframe(claim_scope)]);
})
.then(function(frames) {
frame1 = frames[0];
frame2 = frames[1];
assert_equals(
frame1.contentWindow.navigator.serviceWorker.controller.scriptURL,
normalizeURL(init_worker_url),
'Frame1 controller should not be null');
assert_equals(
frame2.contentWindow.navigator.serviceWorker.controller, null,
'Frame2 controller should be null');
return navigator.serviceWorker.register(claim_worker_url,
{scope: claim_scope});
})
.then(function(registration) {
claim_worker = registration.installing;
claim_registration = registration;
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
var saw_controllerchanged = new Promise(function(resolve) {
frame2.contentWindow.navigator.serviceWorker.oncontrollerchange =
function() { resolve(); }
});
var channel = new MessageChannel();
var saw_message = new Promise(function(resolve) {
channel.port1.onmessage = t.step_func(function(e) {
assert_equals(e.data, 'PASS',
'Worker call to claim() should fulfill.');
resolve();
});
});
claim_worker.postMessage({port: channel.port2}, [channel.port2]);
return Promise.all([saw_controllerchanged, saw_message]);
})
.then(function() {
assert_equals(
frame1.contentWindow.navigator.serviceWorker.controller.scriptURL,
normalizeURL(init_worker_url),
'Frame1 should not be influenced');
assert_equals(
frame2.contentWindow.navigator.serviceWorker.controller.scriptURL,
normalizeURL(claim_worker_url),
'Frame2 should be controlled by the new registration');
frame1.remove();
frame2.remove();
return claim_registration.unregister();
})
.then(function() {
return service_worker_unregister_and_done(t, init_scope);
});
}, 'Test claim client which is not using registration');
promise_test(function(t) {
var scope = 'resources/blank.html?longer-matched';
var claim_scope = 'resources/blank.html?longer';
var claim_worker_url = 'resources/claim-worker.js';
var installing_worker_url = 'resources/empty-worker.js';
var frame, claim_worker;
return with_iframe(scope)
.then(function(f) {
frame = f;
return navigator.serviceWorker.register(
claim_worker_url, {scope: claim_scope});
})
.then(function(registration) {
claim_worker = registration.installing;
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
return navigator.serviceWorker.register(
installing_worker_url, {scope: scope});
})
.then(function() {
var channel = new MessageChannel();
var saw_message = new Promise(function(resolve) {
channel.port1.onmessage = t.step_func(function(e) {
assert_equals(e.data, 'PASS',
'Worker call to claim() should fulfill.');
resolve();
});
});
claim_worker.postMessage({port: channel.port2}, [channel.port2]);
return saw_message;
})
.then(function() {
assert_equals(
frame.contentWindow.navigator.serviceWorker.controller, null,
'Frame should not be claimed when a longer-matched ' +
'registration exists');
frame.remove();
return service_worker_unregister(t, claim_scope);
})
.then(function() {
return service_worker_unregister_and_done(t, scope);
});
}, 'Test claim client when there\'s a longer-matched registration not ' +
'already used by the page');
</script>

View file

@ -0,0 +1,100 @@
<!DOCTYPE html>
<title>Service Worker: claim client using registration</title>
<script src="/resources/testharness.js"></script>
<script src="resources/testharness-helpers.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
promise_test(function(t) {
var scope = 'resources/';
var frame_url = 'resources/blank.html?using-different-registration';
var url1 = 'resources/empty.js';
var url2 = 'resources/claim-worker.js';
var worker, sw_registration, frame;
return service_worker_unregister_and_register(t, url1, scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
return with_iframe(frame_url);
})
.then(function(f) {
frame = f;
return navigator.serviceWorker.register(url2, {scope: frame_url});
})
.then(function(registration) {
worker = registration.installing;
sw_registration = registration;
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
var saw_controllerchanged = new Promise(function(resolve) {
frame.contentWindow.navigator.serviceWorker.oncontrollerchange =
function() { resolve(); }
});
var channel = new MessageChannel();
var saw_message = new Promise(function(resolve) {
channel.port1.onmessage = t.step_func(function(e) {
assert_equals(e.data, 'PASS',
'Worker call to claim() should fulfill.');
resolve();
});
});
worker.postMessage({port: channel.port2}, [channel.port2]);
return Promise.all([saw_controllerchanged, saw_message]);
})
.then(function() {
assert_equals(
frame.contentWindow.navigator.serviceWorker.controller.scriptURL,
normalizeURL(url2),
'Frame1 controller scriptURL should be changed to url2');
frame.remove();
return sw_registration.unregister();
})
.then(function() {
return service_worker_unregister_and_done(t, scope);
});
}, 'Test worker claims client which is using another registration');
promise_test(function(t) {
var scope = 'resources/blank.html?using-same-registration';
var url1 = 'resources/empty.js';
var url2 = 'resources/claim-worker.js';
var frame, worker;
return service_worker_unregister_and_register(t, url1, scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
return with_iframe(scope);
})
.then(function(f) {
frame = f;
return navigator.serviceWorker.register(url2, {scope: scope});
})
.then(function(registration) {
worker = registration.installing;
return wait_for_state(t, registration.installing, 'installed');
})
.then(function() {
var channel = new MessageChannel();
var saw_message = new Promise(function(resolve) {
channel.port1.onmessage = t.step_func(function(e) {
assert_equals(e.data, 'FAIL: exception: InvalidStateError',
'Worker call to claim() should reject with ' +
'InvalidStateError');
resolve();
});
});
worker.postMessage({port: channel.port2}, [channel.port2]);
return saw_message;
})
.then(function() {
frame.remove();
return service_worker_unregister_and_done(t, scope);
});
}, 'Test for the waiting worker claims a client which is using the the ' +
'same registration');
</script>

View file

@ -0,0 +1,42 @@
<!DOCTYPE html>
<title>Service Worker: Clients.get across origins</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
var host_info = get_host_info();
var scope = 'resources/blank.html?clients-get';
var t = async_test('Test Clients.get() cross origin');
var other_origin_iframe = host_info['HTTPS_REMOTE_ORIGIN'] + base_path() +
'resources/clients-get-other-origin.html';
var myOriginClientId;
t.step(function() {
service_worker_unregister_and_register(
t, 'resources/clients-get-worker.js', scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
return with_iframe(scope);
})
.then(function(frame1) {
myOriginClientId = frame1.contentDocument.body.textContent;
return with_iframe(other_origin_iframe);
})
.then(function(frame2) {
window.addEventListener('message', on_message_other_origin, false);
frame2.contentWindow.postMessage(
{clientId: myOriginClientId,
message: 'get_client_id'},
host_info['HTTPS_REMOTE_ORIGIN']);
})
.catch(unreached_rejection(t));
});
function on_message_other_origin(e) {
assert_equals(e.data.result, undefined);
t.done();
}
</script>

View file

@ -0,0 +1,70 @@
<!DOCTYPE html>
<title>Service Worker: Clients.get</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
var host_info = get_host_info();
var scope = 'resources/clients-get-frame.html';
var t = async_test('Test Clients.get()');
var clientIds = [];
var frame;
t.step(function() {
service_worker_unregister_and_register(
t, 'resources/clients-get-worker.js', scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
return with_iframe(scope + '#1');
})
.then(function(frame1) {
frame1.focus();
return wait_for_clientId();
})
.then(function(clientId) {
clientIds.push(clientId);
return with_iframe(scope + '#2');
})
.then(function(frame2) {
frame = frame2;
return wait_for_clientId();
})
.then(function(clientId) {
clientIds.push(clientId);
var channel = new MessageChannel();
channel.port1.onmessage = t.step_func(on_message);
frame.contentWindow.navigator.serviceWorker.controller.postMessage(
{port:channel.port2, clientIds:clientIds,
message: 'get_client_ids'}, [channel.port2]);
})
.catch(unreached_rejection(t));
});
function wait_for_clientId() {
return new Promise(function(resolve, reject) {
function get_client_id(e) {
window.removeEventListener("message", get_client_id);
resolve(e.data.clientId);
}
window.addEventListener("message", get_client_id, false);
});
}
var expected = [
/* visibilityState, focused, url, frameType */
['visible', true, new URL(scope + '#1', location).toString(), 'nested'],
['visible', false, new URL(scope + '#2', location).toString(), 'nested'],
undefined
];
function on_message(e) {
assert_equals(e.data.length, 3);
assert_array_equals(e.data[0], expected[0]);
assert_array_equals(e.data[1], expected[1]);
assert_equals(e.data[2], expected[2]);
service_worker_unregister_and_done(t, scope);
}
</script>

View file

@ -0,0 +1,78 @@
<!DOCTYPE html>
<title>Service Worker: Clients.matchAll with various clientTypes</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
var scope = 'resources/clients-matchall-client-types';
var iframe_url = scope + '-iframe.html';
var shared_worker_url = scope + '-shared-worker.js';
/* visibilityState, focused, url, frameType */
var expected_without_type = [
['visible', true, new URL(iframe_url, location).href, 'nested']
];
var expected_with_window = [
['visible', true, new URL(iframe_url, location).href, 'nested']
];
var expected_with_shared_worker = [
[,,new URL(shared_worker_url, location).href, 'none']
];
var expected_with_all = [
['visible', true, new URL(iframe_url, location).href, 'nested'],
[,,new URL(shared_worker_url, location).href, 'none']
];
function test_matchall(frame, expected, query_options) {
// Make sure the frame gets focus.
frame.focus();
expected.sort(function(a, b) { return a[2] > b[2] ? 1 : -1; });
return new Promise(function(resolve, reject) {
var channel = new MessageChannel();
channel.port1.onmessage = function(e) {
assert_equals(e.data.length, expected.length);
for (var i = 0; i < e.data.length; i++)
assert_array_equals(e.data[i], expected[i]);
resolve();
};
frame.contentWindow.navigator.serviceWorker.controller.postMessage(
{port:channel.port2, options:query_options},
[channel.port2]);
});
}
promise_test(function(t) {
var frame;
return service_worker_unregister_and_register(
t, 'resources/clients-matchall-worker.js', scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return with_iframe(iframe_url); })
.then(function(f) {
frame = f;
return new Promise(function(resolve, reject) {
var w = new SharedWorker(shared_worker_url);
w.port.onmessage = resolve;
});
})
.then(function() {
return test_matchall(frame, expected_without_type, {});
})
.then(function() {
return test_matchall(frame, expected_with_window, {type:'window'});
})
//.then(function() {
// return test_matchall(frame, expected_with_shared_worker,
// {type:'sharedworker'});
// })
//.then(function() {
// return test_matchall(frame, expected_with_all, {type:'all'});
// })
.then(function() {
frame.remove();
return service_worker_unregister_and_done(t, scope);
});
}, 'Verify matchAll() with various client types');
</script>

View file

@ -0,0 +1,93 @@
<!DOCTYPE html>
<title>Service Worker: Clients.matchAll with includeUncontrolled</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
var base_url = 'resources/blank.html'; // This is out-of-scope.
var scope = base_url + '?clients-matchAll-includeUncontrolled';
var frames = [];
// Creates 3 iframes, 2 for in-scope and 1 for out-of-scope.
// The frame opened for scope + '#2' is returned via a promise.
function create_iframes(scope) {
return with_iframe(base_url)
.then(function(frame0) {
frames.push(frame0);
return with_iframe(scope + '#1');
})
.then(function(frame1) {
frames.push(frame1);
return with_iframe(scope + '#2');
})
.then(function(frame2) {
frames.push(frame2);
return frame2;
})
}
var expected_without_include_uncontrolled = [
/* visibilityState, focused, url, frameType */
['visible', false, new URL(scope + '#1', location).toString(), 'nested'],
['visible', true, new URL(scope + '#2', location).toString(), 'nested']
];
var expected_with_include_uncontrolled = [
/* visibilityState, focused, url, frameType */
['visible', true, location.href, 'top-level'],
['visible', false, new URL(scope + '#1', location).toString(), 'nested'],
['visible', true, new URL(scope + '#2', location).toString(), 'nested'],
['visible', false, new URL(base_url, location).toString(), 'nested']
];
function test_matchall(frame, expected, query_options) {
// Make sure we have focus for '#2' frame and its parent window.
frame.focus();
frame.contentWindow.focus();
expected.sort(function(a, b) { return a[2] > b[2] ? 1 : -1; });
return new Promise(function(resolve, reject) {
var channel = new MessageChannel();
channel.port1.onmessage = function(e) {
// Ignore hidden clients which may be coming from background tabs, or
// clients unrelated to this test.
var data = e.data.filter(function(info) {
return info[0] == 'visible' &&
info[2].indexOf('service-worker') > -1;
});
data.sort(function(a, b) { return a[2] > b[2] ? 1 : -1; });
assert_equals(data.length, expected.length);
for (var i = 0; i < data.length; i++)
assert_array_equals(data[i], expected[i]);
resolve(frame);
};
frame.contentWindow.navigator.serviceWorker.controller.postMessage(
{port:channel.port2, options:query_options},
[channel.port2]);
});
}
// Run clients.matchAll without and with includeUncontrolled=true.
// (We want to run the two tests sequentially in the same async_test
// so that we can use the same set of iframes without intefering each other.
async_test(function(t) {
service_worker_unregister_and_register(
t, 'resources/clients-matchall-worker.js', scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return create_iframes(scope); })
.then(function(frame) {
return test_matchall(frame, expected_without_include_uncontrolled);
})
.then(function(frame) {
return test_matchall(frame, expected_with_include_uncontrolled,
{includeUncontrolled:true});
})
.then(function() {
frames.forEach(function(f) { f.remove() });
service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Verify matchAll() respect includeUncontrolled');
</script>

View file

@ -0,0 +1,45 @@
<!DOCTYPE html>
<title>Service Worker: Clients.matchAll</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
var scope = 'resources/blank.html?clients-matchAll';
var t = async_test('Test Clients.matchAll()');
var frames = [];
t.step(function() {
service_worker_unregister_and_register(
t, 'resources/clients-matchall-worker.js', scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return with_iframe(scope + '#1'); })
.then(function(frame1) {
frames.push(frame1);
frame1.focus();
return with_iframe(scope + '#2');
})
.then(function(frame2) {
frames.push(frame2);
var channel = new MessageChannel();
channel.port1.onmessage = t.step_func(onMessage);
frame2.contentWindow.navigator.serviceWorker.controller.postMessage(
{port:channel.port2}, [channel.port2]);
})
.catch(unreached_rejection(t));
});
var expected = [
/* visibilityState, focused, url, frameType */
['visible', true, new URL(scope + '#1', location).toString(), 'nested'],
['visible', false, new URL(scope + '#2', location).toString(), 'nested']
];
function onMessage(e) {
assert_equals(e.data.length, 2);
assert_array_equals(e.data[0], expected[0]);
assert_array_equals(e.data[1], expected[1]);
frames.forEach(function(f) { f.remove(); });
service_worker_unregister_and_done(t, scope);
}
</script>

View file

@ -0,0 +1,45 @@
<!DOCTYPE html>
<title>Service Worker: Controller on load</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
var t = async_test('controller is set for a controlled document');
t.step(function() {
var url = 'resources/empty-worker.js';
var scope = 'resources/blank.html';
var registration;
var controller;
var frame;
service_worker_unregister_and_register(t, url, scope)
.then(t.step_func(function(swr) {
registration = swr;
return wait_for_state(t, registration.installing, 'activated');
}))
.then(t.step_func(function() {
return with_iframe(scope)
}))
.then(t.step_func(function(f) {
frame = f;
var w = frame.contentWindow;
controller = w.navigator.serviceWorker.controller;
assert_true(controller instanceof w.ServiceWorker,
'controller should be a ServiceWorker object');
assert_equals(controller.scriptURL, normalizeURL(url));
// objects from different windows should not be equal
assert_not_equals(controller, registration.active);
return w.navigator.serviceWorker.getRegistration();
}))
.then(t.step_func(function(frameRegistration) {
// SW objects from same window should be equal
assert_equals(frameRegistration.active, controller);
frame.remove();
service_worker_unregister_and_done(t, scope);
}))
.catch(unreached_rejection(t));
});
</script>
</body>

View file

@ -0,0 +1,54 @@
<!DOCTYPE html>
<title>Service Worker: Controller on reload</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
promise_test(function(t) {
var scope = 'resources/blank.html';
var frame;
var registration;
var controller;
return service_worker_unregister(t, scope)
.then(function() {
return with_iframe(scope);
})
.then(function(f) {
frame = f;
return frame.contentWindow.navigator.serviceWorker.register(
'resources/empty-worker.js', {scope: scope});
})
.then(function(swr) {
registration = swr;
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
var w = frame.contentWindow;
assert_equals(w.navigator.serviceWorker.controller, null,
'controller should be null until the document is ' +
'reloaded');
return new Promise(function(resolve) {
frame.onload = function() { resolve(); }
w.location.reload();
});
})
.then(function() {
var w = frame.contentWindow;
controller = w.navigator.serviceWorker.controller;
assert_true(controller instanceof w.ServiceWorker,
'controller should be a ServiceWorker object upon reload');
// objects from separate windows should not be equal
assert_not_equals(controller, registration.active);
return w.navigator.serviceWorker.getRegistration();
})
.then(function(frameRegistration) {
assert_equals(frameRegistration.active, controller);
frame.remove();
service_worker_unregister_and_done(t, scope);
});
}, 'controller is set upon reload after registration');
</script>
</body>

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="resources/testharness-helpers.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
promise_test(function(t) {
var script = 'resources/extendable-event-async-waituntil.js';
var scope = 'resources/async-waituntil';
var worker;
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
worker = registration.installing;
return wait_for_state(t, worker, 'activated');
})
.then(function() {
var channel = new MessageChannel();
var saw_message = new Promise(function(resolve) {
channel.port1.onmessage = function(e) { resolve(e.data); }
});
worker.postMessage({port: channel.port2}, [channel.port2]);
return saw_message;
})
.then(function(message) {
assert_equals(message, 'PASS');
return service_worker_unregister_and_done(t, scope);
})
}, 'Calling waitUntil asynchronously throws an exception');
</script>

View file

@ -0,0 +1,125 @@
<!DOCTYPE html>
<title>ExtendableEvent: waitUntil</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
function runTest(test, scope, onRegister) {
var script = 'resources/extendable-event-waituntil.js?' + scope;
service_worker_unregister_and_register(test, script, scope)
.then(function(registration) {
onRegister(registration.installing);
});
}
// Sends a SYN to the worker and asynchronously listens for an ACK; sets
// |obj.synced| to true once ack'd.
function syncWorker(test, worker, obj) {
var channel = new MessageChannel();
channel.port1.onmessage = test.step_func(function(e) {
var message = e.data;
assert_equals(message, 'SYNC',
'Should receive sync message from worker.');
obj.synced = true;
channel.port1.postMessage('ACK');
});
worker.postMessage({port: channel.port2}, [channel.port2]);
}
async_test(function(t) {
// Passing scope as the test switch for worker script.
var scope = 'resources/install-fulfilled';
var onRegister = function(worker) {
var obj = {};
wait_for_state(t, worker, 'installed')
.then(function() {
assert_true(
obj.synced,
'state should be "installed" after the waitUntil promise ' +
'for "oninstall" is fulfilled.');
service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
syncWorker(t, worker, obj);
};
runTest(t, scope, onRegister);
}, 'Test install event waitUntil fulfilled');
async_test(function(t) {
var scope = 'resources/install-multiple-fulfilled';
var onRegister = function(worker) {
var obj1 = {};
var obj2 = {};
wait_for_state(t, worker, 'installed')
.then(function() {
assert_true(
obj1.synced && obj2.synced,
'state should be "installed" after all waitUntil promises ' +
'for "oninstall" are fulfilled.');
service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
syncWorker(t, worker, obj1);
syncWorker(t, worker, obj2);
};
runTest(t, scope, onRegister);
}, 'Test ExtendableEvent multiple waitUntil fulfilled.');
async_test(function(t) {
var scope = 'resources/install-reject-precedence';
var onRegister = function(worker) {
wait_for_state(t, worker, 'redundant')
.then(function() {
service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
};
runTest(t, scope, onRegister);
}, 'Test ExtendableEvent waitUntil reject precedence.');
async_test(function(t) {
var scope = 'resources/activate-fulfilled';
var onRegister = function(worker) {
var obj = {};
wait_for_state(t, worker, 'activating')
.then(function() {
syncWorker(t, worker, obj);
return wait_for_state(t, worker, 'activated');
})
.then(function() {
assert_true(
obj.synced,
'state should be "activated" after the waitUntil promise ' +
'for "onactivate" is fulfilled.');
service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
};
runTest(t, scope, onRegister);
}, 'Test activate event waitUntil fulfilled');
async_test(function(t) {
var scope = 'resources/install-rejected';
var onRegister = function(worker) {
wait_for_state(t, worker, 'redundant')
.then(function() {
service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
};
runTest(t, scope, onRegister);
}, 'Test install event waitUntil rejected');
async_test(function(t) {
var scope = 'resources/activate-rejected';
var onRegister = function(worker) {
wait_for_state(t, worker, 'activated')
.then(function() {
service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
};
runTest(t, scope, onRegister);
}, 'Test activate event waitUntil rejected.');
</script>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<title>Service Worker: canvas tainting of the fetched image using cached responses</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<body>
<script>
async_test(function(t) {
var SCOPE = 'resources/fetch-canvas-tainting-iframe.html?cache';
var SCRIPT = 'resources/fetch-rewrite-worker.js';
var host_info = get_host_info();
login_https(t)
.then(function() {
return service_worker_unregister_and_register(t, SCRIPT, SCOPE);
})
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return with_iframe(SCOPE); })
.then(function(frame) {
return new Promise(function(resolve, reject) {
var channel = new MessageChannel();
channel.port1.onmessage = t.step_func(function(e) {
assert_equals(e.data.results, 'finish');
frame.remove();
service_worker_unregister_and_done(t, SCOPE);
});
frame.contentWindow.postMessage({},
host_info['HTTPS_ORIGIN'],
[channel.port2]);
});
})
.catch(unreached_rejection(t));
}, 'Verify canvas tainting of fetched image in a Service Worker');
</script>
</body>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<title>Service Worker: canvas tainting of the fetched image</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<body>
<script>
async_test(function(t) {
var SCOPE = 'resources/fetch-canvas-tainting-iframe.html';
var SCRIPT = 'resources/fetch-rewrite-worker.js';
var host_info = get_host_info();
login_https(t)
.then(function() {
return service_worker_unregister_and_register(t, SCRIPT, SCOPE);
})
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return with_iframe(SCOPE); })
.then(function(frame) {
return new Promise(function(resolve, reject) {
var channel = new MessageChannel();
channel.port1.onmessage = t.step_func(function(e) {
assert_equals(e.data.results, 'finish');
frame.remove();
service_worker_unregister_and_done(t, SCOPE);
});
frame.contentWindow.postMessage({},
host_info['HTTPS_ORIGIN'],
[channel.port2]);
});
})
.catch(unreached_rejection(t));
}, 'Verify canvas tainting of fetched image in a Service Worker');
</script>
</body>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<title>Service Worker: CORS XHR of fetch()</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<body>
<script>
async_test(function(t) {
var SCOPE = 'resources/fetch-cors-xhr-iframe.html';
var SCRIPT = 'resources/fetch-rewrite-worker.js';
var host_info = get_host_info();
login_https(t)
.then(function() {
return service_worker_unregister_and_register(t, SCRIPT, SCOPE);
})
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return with_iframe(SCOPE); })
.then(function(frame) {
return new Promise(function(resolve, reject) {
var channel = new MessageChannel();
channel.port1.onmessage = t.step_func(function(e) {
assert_equals(e.data.results, 'finish');
frame.remove();
service_worker_unregister_and_done(t, SCOPE);
});
frame.contentWindow.postMessage({},
host_info['HTTPS_ORIGIN'],
[channel.port2]);
});
})
.catch(unreached_rejection(t));
}, 'Verify CORS XHR of fetch() in a Service Worker');
</script>
</body>

View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<title>Service Worker: CSP control of fetch()</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<script>
async_test(function(t) {
var SCOPE = 'resources/fetch-csp-iframe.html';
var SCRIPT = 'resources/fetch-rewrite-worker.js';
var host_info = get_host_info();
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return with_iframe(SCOPE); })
.then(function(frame) {
return new Promise(function(resolve, reject) {
var channel = new MessageChannel();
channel.port1.onmessage = t.step_func(function(e) {
assert_equals(e.data.results, 'finish');
frame.remove();
service_worker_unregister_and_done(t, SCOPE);
});
frame.contentWindow.postMessage({},
host_info['HTTPS_ORIGIN'],
[channel.port2]);
});
})
.catch(unreached_rejection(t));
}, 'Verify CSP control of fetch() in a Service Worker');
</script>

View file

@ -0,0 +1,65 @@
<!DOCTYPE html>
<title>ServiceWorker: navigator.serviceWorker.waiting</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
promise_test(function(t) {
var scope =
'resources/fetch-event-after-navigation-within-page-iframe.html' +
'?hashchange';
var worker = 'resources/simple-intercept-worker.js';
var frame;
return service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(f) {
frame = f;
return frame.contentWindow.fetch_url('simple.txt');
})
.then(function(response) {
assert_equals(response, 'intercepted by service worker');
frame.contentWindow.location.hash = 'foo';
return frame.contentWindow.fetch_url('simple.txt');
})
.then(function(response) {
assert_equals(response, 'intercepted by service worker');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
}, 'Service Worker should respond to fetch event after the hash changes');
promise_test(function(t) {
var scope =
'resources/fetch-event-after-navigation-within-page-iframe.html' +
'?pushState';
var worker = 'resources/simple-intercept-worker.js';
var frame;
return service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(f) {
frame = f;
return frame.contentWindow.fetch_url('simple.txt');
})
.then(function(response) {
assert_equals(response, 'intercepted by service worker');
frame.contentWindow.history.pushState('', '', 'bar');
return frame.contentWindow.fetch_url('simple.txt');
})
.then(function(response) {
assert_equals(response, 'intercepted by service worker');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
}, 'Service Worker should respond to fetch event after the pushState');
</script>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="resources/testharness-helpers.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
promise_test(function(t) {
var script = 'resources/fetch-event-async-respond-with-worker.js';
var scope = 'resources/simple.html';
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
return with_iframe(scope);
})
.then(function(frame) {
var channel = new MessageChannel();
var saw_message = new Promise(function(resolve) {
channel.port1.onmessage = function(e) { resolve(e.data); }
});
var worker = frame.contentWindow.navigator.serviceWorker.controller;
worker.postMessage({port: channel.port2}, [channel.port2]);
frame.remove();
return saw_message;
})
.then(function(message) {
assert_equals(message, 'PASS');
return service_worker_unregister_and_done(t, scope);
})
}, 'Calling respondWith asynchronously throws an exception');
</script>

View file

@ -0,0 +1,42 @@
<!DOCTYPE html>
<title>Service Worker: Fetch event network error</title>
<script src="/resources/testharness.js"></script>
<script src="resources/testharness-helpers.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
var resolve_test_done;
var test_done_promise = new Promise(function(resolve) {
resolve_test_done = resolve;
});
// Called by the child frame.
function notify_test_done(result) {
resolve_test_done(result);
}
promise_test(function(t) {
var scope = 'resources/fetch-event-network-error-controllee-iframe.html';
var script = 'resources/fetch-event-network-error-worker.js';
var frame;
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
return with_iframe(scope);
})
.then(function(f) {
frame = f;
return test_done_promise;
})
.then(function(result) {
frame.remove();
assert_equals(result, 'PASS');
return service_worker_unregister_and_done(t, scope);
});
}, 'Rejecting the fetch event or using preventDefault() causes a network ' +
'error');
</script>

View file

@ -0,0 +1,997 @@
<!DOCTYPE html>
<title>Service Worker: Fetch Event Redirect Handling</title>
<meta name=timeout content=long>
<script src="/resources/testharness.js"></script>
<script src="resources/testharness-helpers.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
// ------------------------
// Utilities for testing non-navigation requests that are intercepted with
// a redirect.
var host_info = get_host_info();
var worker = 'resources/fetch-rewrite-worker.js';
var frameURL = host_info['HTTPS_ORIGIN'] + base_path() +
'resources/fetch-event-redirect-iframe.html';
var baseScope = 'resources/';
var redirect = 'redirect.py';
var success = base_path() + 'resources/success.py';
function redirect_fetch_test(t, test) {
var scope = baseScope + test.name;
service_worker_unregister_and_register(t, worker, scope).then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
}).then(function() {
return with_iframe(scope + '?url=' + encodeURIComponent(frameURL));
}).then(function(frame) {
var hostKeySuffix = test['url_credentials'] ? '_WITH_CREDS' : '';
var acaorigin = '';
var host = host_info['HTTPS_ORIGIN' + hostKeySuffix];
if (test['redirect_dest'] === 'no-cors') {
host = host_info['HTTPS_REMOTE_ORIGIN' + hostKeySuffix]
} else if (test['redirect_dest'] === 'cors') {
acaorigin = '?ACAOrigin=' + encodeURIComponent(host_info['HTTPS_ORIGIN']);
host = host_info['HTTPS_REMOTE_ORIGIN' + hostKeySuffix]
}
var dest = '?Redirect=' + encodeURIComponent(host + success + acaorigin);
var expectedTypeParam = test['expected_type']
? '&expected_type=' + test['expected_type']
: '';
var url = scope +
'?url=' + encodeURIComponent(redirect + dest) +
expectedTypeParam
var p = new Promise(function(resolve, reject) {
var channel = new MessageChannel();
channel.port1.onmessage = function(e) {
frame.remove();
if (e.data.result === 'reject') {
reject(e.data.detail);
} else if (e.data.result === 'success') {
resolve(e.data.result);
} else {
resolve(e.data.detail);
}
};
frame.contentWindow.postMessage({
url: url,
request_init: test.request_init,
redirect_dest: test.redirect_dest,
}, '*', [channel.port2]);
});
if (test.should_reject) {
return assert_promise_rejects(p);
}
return p.then(function(result) {
if (result !== 'success') {
throw(new Error(result));
}
});
}).then(function() {
return service_worker_unregister_and_done(t, scope);
}).catch(unreached_rejection(t));
}
// ------------------------
// Test every combination of:
// - RequestMode (same-origin, cors, no-cors)
// - RequestRedirect (manual, follow, error)
// - redirect destination origin (same-origin, cors, no-cors)
// - redirect destination credentials (no user/pass, user/pass)
//
// TODO: add navigation requests
// TODO: add redirects to data URI and verify same-origin data-URL flag behavior
// TODO: add test where original redirect URI is cross-origin
// TODO: verify final method is correct for 301, 302, and 303
// TODO: verify CORS redirect results in all further redirects being
// considered cross origin
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-cors-redirects-to-sameorigin-nocreds',
redirect_dest: 'same-origin',
url_credentials: false,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'cors'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, cors mode Request redirected to ' +
'same-origin without credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-cors-redirects-to-nocors-nocreds',
redirect_dest: 'no-cors',
url_credentials: false,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'cors'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, cors mode Request redirected to ' +
'no-cors without credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-cors-redirects-to-cors-nocreds',
redirect_dest: 'cors',
url_credentials: false,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'cors'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, cors mode Request redirected to ' +
'cors without credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-sameorigin-redirects-to-sameorigin-nocreds',
redirect_dest: 'same-origin',
url_credentials: false,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'same-origin'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, same-origin mode Request redirected to ' +
'same-origin without credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-sameorigin-redirects-to-nocors-nocreds',
redirect_dest: 'no-cors',
url_credentials: false,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'same-origin'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, same-origin mode Request redirected to ' +
'no-cors without credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-sameorigin-redirects-to-cors-nocreds',
redirect_dest: 'cors',
url_credentials: false,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'same-origin'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, same-origin mode Request redirected to ' +
'cors without credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-nocors-redirects-to-sameorigin-nocreds',
redirect_dest: 'same-origin',
url_credentials: false,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'no-cors'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, no-cors mode Request redirected to ' +
'same-origin without credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-nocors-redirects-to-nocors-nocreds',
redirect_dest: 'no-cors',
url_credentials: false,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'no-cors'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, no-cors mode Request redirected to ' +
'no-cors without credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-nocors-redirects-to-cors-nocreds',
redirect_dest: 'cors',
url_credentials: false,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'no-cors'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, no-cors mode Request redirected to ' +
'cors without credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-cors-redirects-to-sameorigin-creds',
redirect_dest: 'same-origin',
url_credentials: true,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'cors'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, cors mode Request redirected to ' +
'same-origin with credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-cors-redirects-to-nocors-creds',
redirect_dest: 'no-cors',
url_credentials: true,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'cors'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, cors mode Request redirected to ' +
'no-cors with credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-cors-redirects-to-cors-creds',
redirect_dest: 'cors',
url_credentials: true,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'cors'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, cors mode Request redirected to ' +
'cors with credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-sameorigin-redirects-to-sameorigin-creds',
redirect_dest: 'same-origin',
url_credentials: true,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'same-origin'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, same-origin mode Request redirected to ' +
'same-origin with credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-sameorigin-redirects-to-nocors-creds',
redirect_dest: 'no-cors',
url_credentials: true,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'same-origin'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, same-origin mode Request redirected to ' +
'no-cors with credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-sameorigin-redirects-to-cors-creds',
redirect_dest: 'cors',
url_credentials: true,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'same-origin'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, same-origin mode Request redirected to ' +
'cors with credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-nocors-redirects-to-sameorigin-creds',
redirect_dest: 'same-origin',
url_credentials: true,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'no-cors'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, no-cors mode Request redirected to ' +
'same-origin with credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-nocors-redirects-to-nocors-creds',
redirect_dest: 'no-cors',
url_credentials: true,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'no-cors'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, no-cors mode Request redirected to ' +
'no-cors with credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-manual-nocors-redirects-to-cors-creds',
redirect_dest: 'cors',
url_credentials: true,
expected_type: 'opaqueredirect',
request_init: {
redirect: 'manual',
mode: 'no-cors'
},
// should reject because only navigations can be intercepted with
// opaqueredirect responses
should_reject: true
});
}, 'Non-navigation, manual redirect, no-cors mode Request redirected to ' +
'cors with credentials should fail opaqueredirect interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-cors-redirects-to-sameorigin-nocreds',
redirect_dest: 'same-origin',
url_credentials: false,
expected_type: 'basic',
request_init: {
redirect: 'follow',
mode: 'cors'
},
should_reject: false
});
}, 'Non-navigation, follow redirect, cors mode Request redirected to ' +
'same-origin without credentials should succeed interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-cors-redirects-to-nocors-nocreds',
redirect_dest: 'no-cors',
url_credentials: false,
expected_type: 'should-not-get-a-response',
request_init: {
redirect: 'follow',
mode: 'cors'
},
// should reject because CORS requests require CORS headers on cross-origin
// resources
should_reject: true
});
}, 'Non-navigation, follow redirect, cors mode Request redirected to ' +
'no-cors without credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-cors-redirects-to-cors-nocreds',
redirect_dest: 'cors',
url_credentials: false,
expected_type: 'cors',
request_init: {
redirect: 'follow',
mode: 'cors'
},
should_reject: false
});
}, 'Non-navigation, follow redirect, cors mode Request redirected to ' +
'cors without credentials should succeed interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-sameorigin-redirects-to-sameorigin-nocreds',
redirect_dest: 'same-origin',
url_credentials: false,
expected_type: 'basic',
request_init: {
redirect: 'follow',
mode: 'same-origin'
},
should_reject: false
});
}, 'Non-navigation, follow redirect, same-origin mode Request redirected to ' +
'same-origin without credentials should succeed interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-sameorigin-redirects-to-nocors-nocreds',
redirect_dest: 'no-cors',
url_credentials: false,
expected_type: 'should-not-get-a-response',
request_init: {
redirect: 'follow',
mode: 'same-origin'
},
// should reject because same-origin requests cannot load cross-origin
// resources
should_reject: true
});
}, 'Non-navigation, follow redirect, same-origin mode Request redirected to ' +
'no-cors without credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-sameorigin-redirects-to-cors-nocreds',
redirect_dest: 'cors',
url_credentials: false,
expected_type: 'should-not-get-a-response',
request_init: {
redirect: 'follow',
mode: 'same-origin'
},
// should reject because same-origin requests cannot load cross-origin
// resources
should_reject: true
});
}, 'Non-navigation, follow redirect, same-origin mode Request redirected to ' +
'cors without credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-nocors-redirects-to-sameorigin-nocreds',
redirect_dest: 'same-origin',
url_credentials: false,
expected_type: 'basic',
request_init: {
redirect: 'follow',
mode: 'no-cors'
},
should_reject: false
});
}, 'Non-navigation, follow redirect, no-cors mode Request redirected to ' +
'same-origin without credentials should succeed interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-nocors-redirects-to-nocors-nocreds',
redirect_dest: 'no-cors',
url_credentials: false,
expected_type: 'opaque',
request_init: {
redirect: 'follow',
mode: 'no-cors'
},
should_reject: false
});
}, 'Non-navigation, follow redirect, no-cors mode Request redirected to ' +
'no-cors without credentials should succeed interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-nocors-redirects-to-cors-nocreds',
redirect_dest: 'cors',
url_credentials: false,
expected_type: 'opaque',
request_init: {
redirect: 'follow',
mode: 'no-cors'
},
should_reject: false
});
}, 'Non-navigation, follow redirect, no-cors mode Request redirected to ' +
'cors without credentials should succeed interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-cors-redirects-to-sameorigin-creds',
redirect_dest: 'same-origin',
url_credentials: true,
expected_type: 'basic',
request_init: {
redirect: 'follow',
mode: 'cors'
},
should_reject: false
});
}, 'Non-navigation, follow redirect, cors mode Request redirected to ' +
'same-origin with credentials should succeed interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-cors-redirects-to-nocors-creds',
redirect_dest: 'no-cors',
url_credentials: true,
expected_type: 'should-not-get-a-response',
request_init: {
redirect: 'follow',
mode: 'cors'
},
// should reject because CORS requests require CORS headers on cross-origin
// resources
should_reject: true
});
}, 'Non-navigation, follow redirect, cors mode Request redirected to ' +
'no-cors with credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-cors-redirects-to-cors-creds',
redirect_dest: 'cors',
url_credentials: true,
expected_type: 'cors',
request_init: {
redirect: 'follow',
mode: 'cors'
},
// should reject because CORS requests do not allow user/pass entries in
// cross-origin URLs
// NOTE: https://github.com/whatwg/fetch/issues/112
should_reject: true
});
}, 'Non-navigation, follow redirect, cors mode Request redirected to ' +
'cors with credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-sameorigin-redirects-to-sameorigin-creds',
redirect_dest: 'same-origin',
url_credentials: true,
expected_type: 'basic',
request_init: {
redirect: 'follow',
mode: 'same-origin'
},
should_reject: false
});
}, 'Non-navigation, follow redirect, same-origin mode Request redirected to ' +
'same-origin with credentials should succeed interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-sameorigin-redirects-to-nocors-creds',
redirect_dest: 'no-cors',
url_credentials: true,
expected_type: 'should-not-get-a-response',
request_init: {
redirect: 'follow',
mode: 'same-origin'
},
// should reject because same-origin requests cannot load cross-origin
// resources
should_reject: true
});
}, 'Non-navigation, follow redirect, same-origin mode Request redirected to ' +
'no-cors with credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-sameorigin-redirects-to-cors-creds',
redirect_dest: 'cors',
url_credentials: true,
expected_type: 'should-not-get-a-response',
request_init: {
redirect: 'follow',
mode: 'same-origin'
},
// should reject because same-origin requests cannot load cross-origin
// resources
should_reject: true
});
}, 'Non-navigation, follow redirect, same-origin mode Request redirected to ' +
'cors with credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-nocors-redirects-to-sameorigin-creds',
redirect_dest: 'same-origin',
url_credentials: true,
expected_type: 'basic',
request_init: {
redirect: 'follow',
mode: 'no-cors'
},
should_reject: false
});
}, 'Non-navigation, follow redirect, no-cors mode Request redirected to ' +
'same-origin with credentials should succeed interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-nocors-redirects-to-nocors-creds',
redirect_dest: 'no-cors',
url_credentials: true,
expected_type: 'opaque',
request_init: {
redirect: 'follow',
mode: 'no-cors'
},
should_reject: false
});
}, 'Non-navigation, follow redirect, no-cors mode Request redirected to ' +
'no-cors with credentials should succeed interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-follow-nocors-redirects-to-cors-creds',
redirect_dest: 'cors',
url_credentials: true,
expected_type: 'opaque',
request_init: {
redirect: 'follow',
mode: 'no-cors'
},
should_reject: false
});
}, 'Non-navigation, follow redirect, no-cors mode Request redirected to ' +
'cors with credentials should succeed interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-cors-redirects-to-sameorigin-nocreds',
redirect_dest: 'same-origin',
url_credentials: false,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'cors'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, cors mode Request redirected to ' +
'same-origin without credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-cors-redirects-to-nocors-nocreds',
redirect_dest: 'no-cors',
url_credentials: false,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'cors'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, cors mode Request redirected to ' +
'no-cors without credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-cors-redirects-to-cors-nocreds',
redirect_dest: 'cors',
url_credentials: false,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'cors'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, cors mode Request redirected to ' +
'cors without credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-sameorigin-redirects-to-sameorigin-nocreds',
redirect_dest: 'same-origin',
url_credentials: false,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'same-origin'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, same-origin mode Request redirected to ' +
'same-origin without credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-sameorigin-redirects-to-nocors-nocreds',
redirect_dest: 'no-cors',
url_credentials: false,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'same-origin'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, same-origin mode Request redirected to ' +
'no-cors without credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-sameorigin-redirects-to-cors-nocreds',
redirect_dest: 'cors',
url_credentials: false,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'same-origin'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, same-origin mode Request redirected to ' +
'cors without credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-nocors-redirects-to-sameorigin-nocreds',
redirect_dest: 'same-origin',
url_credentials: false,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'no-cors'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, no-cors mode Request redirected to ' +
'same-origin without credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-nocors-redirects-to-nocors-nocreds',
redirect_dest: 'no-cors',
url_credentials: false,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'no-cors'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, no-cors mode Request redirected to ' +
'no-cors without credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-nocors-redirects-to-cors-nocreds',
redirect_dest: 'cors',
url_credentials: false,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'no-cors'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, no-cors mode Request redirected to ' +
'cors without credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-cors-redirects-to-sameorigin-creds',
redirect_dest: 'same-origin',
url_credentials: true,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'cors'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, cors mode Request redirected to ' +
'same-origin with credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-cors-redirects-to-nocors-creds',
redirect_dest: 'no-cors',
url_credentials: true,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'cors'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, cors mode Request redirected to ' +
'no-cors with credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-cors-redirects-to-cors-creds',
redirect_dest: 'cors',
url_credentials: true,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'cors'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, cors mode Request redirected to ' +
'cors with credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-sameorigin-redirects-to-sameorigin-creds',
redirect_dest: 'same-origin',
url_credentials: true,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'same-origin'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, same-origin mode Request redirected to ' +
'same-origin with credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-sameorigin-redirects-to-nocors-creds',
redirect_dest: 'no-cors',
url_credentials: true,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'same-origin'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, same-origin mode Request redirected to ' +
'no-cors with credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-sameorigin-redirects-to-cors-creds',
redirect_dest: 'cors',
url_credentials: true,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'same-origin'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, same-origin mode Request redirected to ' +
'cors with credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-nocors-redirects-to-sameorigin-creds',
redirect_dest: 'same-origin',
url_credentials: true,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'no-cors'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, no-cors mode Request redirected to ' +
'same-origin with credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-nocors-redirects-to-nocors-creds',
redirect_dest: 'no-cors',
url_credentials: true,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'no-cors'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, no-cors mode Request redirected to ' +
'no-cors with credentials should fail interception');
async_test(function(t) {
redirect_fetch_test(t, {
name: 'nonav-error-nocors-redirects-to-cors-creds',
redirect_dest: 'cors',
url_credentials: true,
expected_type: 'error',
request_init: {
redirect: 'error',
mode: 'no-cors'
},
// should reject because requests with 'error' RequestRedirect cannot be
// redirected.
should_reject: true
});
}, 'Non-navigation, error redirect, no-cors mode Request redirected to ' +
'cors with credentials should fail interception');
</script>
</body>

View file

@ -0,0 +1,35 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="resources/testharness-helpers.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
promise_test(function(t) {
var script =
'resources/fetch-event-respond-with-stops-propagation-worker.js';
var scope = 'resources/simple.html';
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
return with_iframe(scope);
})
.then(function(frame) {
var channel = new MessageChannel();
var saw_message = new Promise(function(resolve) {
channel.port1.onmessage = function(e) { resolve(e.data); }
});
var worker = frame.contentWindow.navigator.serviceWorker.controller;
worker.postMessage({port: channel.port2}, [channel.port2]);
frame.remove();
return saw_message;
})
.then(function(message) {
assert_equals(message, 'PASS');
return service_worker_unregister_and_done(t, scope);
})
}, 'respondWith() invokes stopImmediatePropagation()');
</script>

View file

@ -0,0 +1,466 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
var worker = 'resources/fetch-event-test-worker.js';
async_test(function(t) {
var scope = 'resources/simple.html?string';
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(frame) {
assert_equals(
frame.contentDocument.body.textContent,
'Test string',
'Service Worker should respond to fetch with a test string');
assert_equals(
frame.contentDocument.contentType,
'text/plain',
'The content type of the response created with a string should be text/plain');
assert_equals(
frame.contentDocument.characterSet,
'UTF-8',
'The character set of the response created with a string should be UTF-8');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker responds to fetch event with string');
async_test(function(t) {
var scope = 'resources/simple.html?blob';
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(frame) {
assert_equals(
frame.contentDocument.body.textContent,
'Test blob',
'Service Worker should respond to fetch with a test string');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker responds to fetch event with blob body');
async_test(function(t) {
var scope = 'resources/simple.html?referrer';
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(frame) {
assert_equals(
frame.contentDocument.body.textContent,
'Referrer: ' + document.location.href,
'Service Worker should respond to fetch with the referrer URL');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker responds to fetch event with the referrer URL');
function run_referrer_policy_tests(frame, referrer, href, origin) {
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
{method: "GET", referrer: referrer})
.then(function(response) { return response.text(); })
.then(function(response_text) {
assert_equals(
response_text,
'Referrer: ' + href + '\n' +
'ReferrerPolicy: no-referrer-when-downgrade',
'Service Worker should respond to fetch with the referrer URL when a member of RequestInit is present');
var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
'/resources/simple.html?referrerFull';
return frame.contentWindow.fetch(http_url,
{method: "GET", referrer: referrer});
})
.then(function(response) { return response.text(); })
.then(function(response_text) {
assert_equals(
response_text,
'Referrer: about:client\n' +
'ReferrerPolicy: no-referrer-when-downgrade',
'Service Worker should respond to fetch with no referrer when a member of RequestInit is present with an HTTP request');
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
{referrerPolicy: "", referrer: referrer});
})
.then(function(response) { return response.text(); })
.then(function(response_text) {
assert_equals(
response_text,
'Referrer: ' + href + '\n' +
'ReferrerPolicy: no-referrer-when-downgrade',
'Service Worker should respond to fetch with the referrer with ""');
var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
'/resources/simple.html?referrerFull';
return frame.contentWindow.fetch(http_url,
{referrerPolicy: "", referrer: referrer});
})
.then(function(response) { return response.text(); })
.then(function(response_text) {
assert_equals(
response_text,
'Referrer: about:client\n' +
'ReferrerPolicy: no-referrer-when-downgrade',
'Service Worker should respond to fetch with no referrer with ""');
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
{referrerPolicy: "origin-only", referrer: referrer});
})
.then(function(response) { return response.text(); })
.then(function(response_text) {
assert_equals(
response_text,
'Referrer: ' + origin + '/' + '\n' +
'ReferrerPolicy: origin-only',
'Service Worker should respond to fetch with the referrer origin with "origin-only" and a same origin request');
var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
'/resources/simple.html?referrerFull';
return frame.contentWindow.fetch(http_url,
{referrerPolicy: "origin-only", referrer: referrer});
})
.then(function(response) { return response.text(); })
.then(function(response_text) {
assert_equals(
response_text,
'Referrer: ' + origin + '/' + '\n' +
'ReferrerPolicy: origin-only',
'Service Worker should respond to fetch with the referrer origin with "origin-only" and a cross origin request');
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
{referrerPolicy: "origin-when-cross-origin", referrer: referrer});
})
.then(function(response) { return response.text(); })
.then(function(response_text) {
assert_equals(
response_text,
'Referrer: ' + href + '\n' +
'ReferrerPolicy: origin-when-cross-origin',
'Service Worker should respond to fetch with the referrer URL with "origin-when-cross-origin" and a same origin request');
var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
'/resources/simple.html?referrerFull';
return frame.contentWindow.fetch(http_url,
{referrerPolicy: "origin-when-cross-origin", referrer: referrer});
})
.then(function(response) { return response.text(); })
.then(function(response_text) {
assert_equals(
response_text,
'Referrer: ' + origin + '/' + '\n' +
'ReferrerPolicy: origin-when-cross-origin',
'Service Worker should respond to fetch with the referrer origin with "origin-when-cross-origin" and a cross origin request');
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
{referrerPolicy: "no-referrer-when-downgrade", referrer: referrer});
})
.then(function(response) { return response.text(); })
.then(function(response_text) {
assert_equals(
response_text,
'Referrer: ' + href + '\n' +
'ReferrerPolicy: no-referrer-when-downgrade',
'Service Worker should respond to fetch with no referrer with "no-referrer-when-downgrade" and a same origin request');
var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
'/resources/simple.html?referrerFull';
return frame.contentWindow.fetch(http_url,
{referrerPolicy: "no-referrer-when-downgrade", referrer: referrer});
})
.then(function(response) { return response.text(); })
.then(function(response_text) {
assert_equals(
response_text,
'Referrer: about:client\n' +
'ReferrerPolicy: no-referrer-when-downgrade',
'Service Worker should respond to fetch with no referrer with "no-referrer-when-downgrade" and an HTTP request');
var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
'/resources/simple.html?referrerFull';
return frame.contentWindow.fetch(http_url, {referrerPolicy: "unsafe-url", referrer: referrer});
})
.then(function(response) { return response.text(); })
.then(function(response_text) {
assert_equals(
response_text,
'Referrer: ' + href + '\n' +
'ReferrerPolicy: unsafe-url',
'Service Worker should respond to fetch with no referrer with "unsafe-url"');
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
{referrerPolicy: "no-referrer", referrer: referrer});
})
.then(function(response) { return response.text(); })
.then(function(response_text) {
assert_equals(
response_text,
'Referrer: about:client\n' +
'ReferrerPolicy: no-referrer',
'Service Worker should respond to fetch with no referrer URL with "no-referrer"');
});
}
async_test(function(t) {
var scope = 'resources/simple.html?referrerPolicy';
var frame;
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(f) {
frame = f;
assert_equals(
frame.contentDocument.body.textContent,
'ReferrerPolicy: no-referrer-when-downgrade',
'Service Worker should respond to fetch with the default referrer policy');
// First, run the referrer policy tests without passing a referrer in RequestInit.
return run_referrer_policy_tests(frame, undefined, frame.contentDocument.location.href,
frame.contentDocument.location.origin);
})
.then(function() {
// Now, run the referrer policy tests while passing a referrer in RequestInit.
var referrer = get_host_info()['HTTPS_ORIGIN'] + base_path() + 'fake-referrer';
return run_referrer_policy_tests(frame, 'fake-referrer', referrer,
frame.contentDocument.location.origin);
})
.then(function() {
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker responds to fetch event with the referrer URL');
async_test(function(t) {
var scope = 'resources/simple.html?clientId';
var frame;
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(f) {
frame = f;
assert_equals(
frame.contentDocument.body.textContent,
'Client ID Not Found',
'Service Worker should respond to fetch with a client id');
return frame.contentWindow.fetch('resources/other.html?clientId');
})
.then(function(response) { return response.text(); })
.then(function(response_text) {
var new_client_id = response_text.substr(17);
assert_equals(
response_text.substr(0, 15),
'Client ID Found',
'Service Worker should respond to fetch with an existing client id');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker responds to fetch event with an existing client id');
async_test(function(t) {
var scope = 'resources/simple.html?ignore';
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(frame) {
assert_equals(frame.contentDocument.body.textContent,
'Here\'s a simple html file.\n',
'Response should come from fallback to native fetch');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker does not respond to fetch event');
async_test(function(t) {
var scope = 'resources/simple.html?null';
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(frame) {
assert_equals(frame.contentDocument.body.textContent,
'',
'Response should be the empty string');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker responds to fetch event with null response body');
async_test(function(t) {
var scope = 'resources/simple.html?fetch';
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(frame) {
assert_equals(frame.contentDocument.body.textContent,
'Here\'s an other html file.\n',
'Response should come from fetched other file');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker fetches other file in fetch event');
async_test(function(t) {
var scope = 'resources/simple.html?form-post';
var frame_name = 'xhr-post-frame';
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function(sw) {
return new Promise(function(resolve) {
var frame = document.createElement('iframe');
frame.name = frame_name;
document.body.appendChild(frame);
var form = document.createElement('form');
form.target = frame_name;
form.action = scope;
form.method = 'post';
var input1 = document.createElement('input');
input1.type = 'text';
input1.value = 'testValue1';
input1.name = 'testName1'
form.appendChild(input1);
var input2 = document.createElement('input');
input2.type = 'text';
input2.value = 'testValue2';
input2.name = 'testName2'
form.appendChild(input2);
document.body.appendChild(form);
frame.onload = function() {
document.body.removeChild(form);
resolve(frame);
};
form.submit();
});
})
.then(function(frame) {
assert_equals(frame.contentDocument.body.textContent,
'POST:application/x-www-form-urlencoded:' +
'testName1=testValue1&testName2=testValue2');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker responds to fetch event with POST form');
async_test(function(t) {
var scope = 'resources/simple.html?multiple-respond-with';
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(frame) {
assert_equals(
frame.contentDocument.body.textContent,
'(0)(1)[InvalidStateError](2)[InvalidStateError]',
'Multiple calls of respondWith must throw InvalidStateErrors.');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Multiple calls of respondWith must throw InvalidStateErrors');
async_test(function(t) {
var scope = 'resources/simple.html?used-check';
var first_frame;
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(frame) {
assert_equals(frame.contentDocument.body.textContent,
'Here\'s an other html file.\n',
'Response should come from fetched other file');
first_frame = frame;
return with_iframe(scope);
})
.then(function(frame) {
// When we access to the scope in the second time, the content of the
// response is generated inside the ServiceWorker. The body contains
// the value of bodyUsed of the first response which is already
// consumed by FetchEvent.respondWith method.
assert_equals(
frame.contentDocument.body.textContent,
'bodyUsed: true',
'event.respondWith must set the used flag.');
first_frame.remove();
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker event.respondWith must set the used flag');
async_test(function(t) {
var scope = 'resources/simple.html?fragment-check';
var fragment = '#/some/fragment';
var first_frame;
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope + fragment); })
.then(function(frame) {
assert_equals(
frame.contentDocument.body.textContent,
'Fragment Not Found',
'Service worker should not expose URL fragments.');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker must not expose FetchEvent URL fragments.');
async_test(function(t) {
var scope = 'resources/simple.html?cache';
var frame;
var cacheTypes = [
undefined, 'default', 'no-store', 'reload', 'no-cache', 'force-cache'
];
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(f) {
frame = f;
var tests = cacheTypes.map(function(type) {
return new Promise(function(resolve) {
return frame.contentWindow.fetch(scope + '=' + type,
{cache: type})
.then(function(response) { return response.text(); })
.then(function(response_text) {
var expected = (type === undefined) ? 'default' : type;
assert_equals(response_text, expected,
'Service Worker should respond to fetch with the correct type');
})
.then(resolve);
});
});
return Promise.all(tests);
})
.then(function() {
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker responds to fetch event with the correct cache types');
</script>
</body>

View file

@ -0,0 +1,221 @@
<!DOCTYPE html>
<title>Service Worker: Fetch for the frame loading.</title>
<meta name=timeout content=long>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
var worker = 'resources/fetch-rewrite-worker.js';
var path = base_path() + 'resources/fetch-access-control.py';
var host_info = get_host_info();
if (window.testRunner) {
testRunner.setCanOpenWindows();
}
function getLoadedObject(win, contentFunc, closeFunc) {
return new Promise(function(resolve) {
function done(contentString) {
var result = null;
// fetch-access-control.py returns a string like "report( <json> )".
// Eval the returned string with a report functionto get the json
// object.
try {
function report(obj) { result = obj };
eval(contentString);
} catch(e) {
// just resolve null if we get unexpected page content
}
closeFunc(win);
resolve(result);
}
// We can't catch the network error on window. So we use the timer.
var timeout = setTimeout(function() {
// Failure pages are considered cross-origin in some browsers. This
// means you cannot even .resolve() the window because the check for
// the .then property will throw. Instead, treat cross-origin
// failure pages as the empty string which will fail to parse as the
// expected json result.
var content = '';
try {
content = contentFunc(win);
} catch(e) {
// use default empty string for cross-domain window
}
done(content);
}, 10000);
win.onload = function() {
clearTimeout(timeout);
var content = contentFunc(win);
done(content);
};
});
}
function getLoadedFrameAsObject(frame) {
return getLoadedObject(frame, function(f) {
return f.contentDocument.body.textContent;
}, function(f) {
f.parentNode.removeChild(f);
});
}
function getLoadedWindowAsObject(win) {
return getLoadedObject(win, function(w) {
return w.document.body.textContent
}, function(w) {
w.close();
});
}
async_test(function(t) {
var scope = 'resources/fetch-frame-resource/frame-basic';
var frame;
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() {
frame = document.createElement('iframe');
frame.src =
scope + '?url=' +
encodeURIComponent(host_info['HTTPS_ORIGIN'] + path);
document.body.appendChild(frame);
return getLoadedFrameAsObject(frame);
})
.then(function(result) {
assert_equals(
result.jsonpResult,
'success',
'Basic type response could be loaded in the iframe.');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Basic type response could be loaded in the iframe.');
async_test(function(t) {
var scope = 'resources/fetch-frame-resource/frame-cors';
var frame;
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() {
frame = document.createElement('iframe');
frame.src =
scope + '?mode=cors&url=' +
encodeURIComponent(host_info['HTTPS_REMOTE_ORIGIN'] + path +
'?ACAOrigin=' + host_info['HTTPS_ORIGIN']);
document.body.appendChild(frame);
return getLoadedFrameAsObject(frame);
})
.then(function(result) {
assert_equals(
result.jsonpResult,
'success',
'CORS type response could be loaded in the iframe.');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'CORS type response could be loaded in the iframe.');
async_test(function(t) {
var scope = 'resources/fetch-frame-resource/frame-opaque';
var frame;
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() {
frame = document.createElement('iframe');
frame.src =
scope + '?mode=no-cors&url=' +
encodeURIComponent(host_info['HTTPS_REMOTE_ORIGIN'] + path);
document.body.appendChild(frame);
return getLoadedFrameAsObject(frame);
})
.then(function(result) {
assert_equals(
result,
null,
'Opaque type response could not be loaded in the iframe.');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Opaque type response could not be loaded in the iframe.');
async_test(function(t) {
var scope = 'resources/fetch-frame-resource/window-basic';
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() {
var win = window.open(
scope + '?url=' +
encodeURIComponent(host_info['HTTPS_ORIGIN'] + path));
return getLoadedWindowAsObject(win);
})
.then(function(result) {
assert_equals(
result.jsonpResult,
'success',
'Basic type response could be loaded in the new window.');
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Basic type response could be loaded in the new window.');
async_test(function(t) {
var scope = 'resources/fetch-frame-resource/window-cors';
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() {
var win = window.open(
scope + '?mode=cors&url=' +
encodeURIComponent(host_info['HTTPS_REMOTE_ORIGIN'] + path +
'?ACAOrigin=' + host_info['HTTPS_ORIGIN']));
return getLoadedWindowAsObject(win);
})
.then(function(result) {
assert_equals(
result.jsonpResult,
'success',
'CORS type response could be loaded in the new window.');
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'CORS type response could be loaded in the new window.');
async_test(function(t) {
var scope = 'resources/fetch-frame-resource/window-opaque';
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() {
var win = window.open(
scope + '?mode=no-cors&url=' +
encodeURIComponent(host_info['HTTPS_REMOTE_ORIGIN'] + path));
return getLoadedWindowAsObject(win);
})
.then(function(result) {
assert_equals(
result,
null,
'Opaque type response could not be loaded in the new window.');
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Opaque type response could not be loaded in the new window.');
</script>
</body>

View file

@ -0,0 +1,52 @@
<!DOCTYPE html>
<title>Service Worker: Visibility of headers during fetch.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
var worker = 'resources/fetch-rewrite-worker.js';
var path = base_path() + 'resources/fetch-access-control.py';
var host_info = get_host_info();
var frame;
async_test(function(t) {
var scope = 'resources/fetch-header-visibility-iframe.html';
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() {
frame = document.createElement('iframe');
frame.src = scope;
document.body.appendChild(frame);
// Resolve a promise when we recieve 2 success messages
return new Promise(function(resolve, reject) {
var remaining = 4;
function onMessage(e) {
if (e.data == 'PASS') {
remaining--;
if (remaining == 0) {
resolve();
} else {
return;
}
} else {
reject(e.data);
}
window.removeEventListener('message', onMessage);
}
window.addEventListener('message', onMessage);
});
})
.then(function(result) {
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Visibility of defaulted headers during interception');
</script>
</body>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<title>Service Worker: Mixed content of fetch()</title>
<meta name=timeout content=long>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<body></body>
<script>
if (window.testRunner) {
// In Chromium we need to change the setting to disallow displaying insecure
// contents.
testRunner.overridePreference('WebKitAllowDisplayingInsecureContent', false);
}
async_test(function(t) {
var host_info = get_host_info();
window.addEventListener('message', t.step_func(on_message), false);
with_iframe(
host_info['HTTPS_ORIGIN'] + base_path() +
'resources/fetch-mixed-content-iframe.html?target=inscope');
function on_message(e) {
assert_equals(e.data.results, 'finish');
t.done();
}
}, 'Verify Mixed content of fetch() in a Service Worker');
</script>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<title>Service Worker: Mixed content of fetch()</title>
<meta name=timeout content=long>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<body></body>
<script>
if (window.testRunner) {
// In Chromium we need to change the setting to disallow displaying insecure
// contents.
testRunner.overridePreference('WebKitAllowDisplayingInsecureContent', false);
}
async_test(function(t) {
var host_info = get_host_info();
window.addEventListener('message', t.step_func(on_message), false);
with_iframe(
host_info['HTTPS_ORIGIN'] + base_path() +
'resources/fetch-mixed-content-iframe.html?target=outscope');
function on_message(e) {
assert_equals(e.data.results, 'finish');
t.done();
}
}, 'Verify Mixed content of fetch() in a Service Worker');
</script>

View file

@ -0,0 +1,56 @@
<!DOCTYPE html>
<title>Service Worker: CSS's base URL must be the request URL even when fetched from other URL</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<script>
async_test(function(t) {
var SCOPE = 'resources/fetch-request-css-base-url-iframe.html';
var SCRIPT = 'resources/fetch-request-css-base-url-worker.js';
var worker;
var testDonePromise;
return service_worker_unregister_and_register(t, SCRIPT, SCOPE)
.then(function(registration) {
worker = registration.installing;
return wait_for_state(t, worker, 'activated');
})
.then(function() {
return new Promise(function(resolve) {
var channel = new MessageChannel();
testDonePromise = new Promise(function(resolveTestDone) {
channel.port1.onmessage = t.step_func(function(msg) {
if (msg.data.ready) {
resolve();
return;
}
var result = msg.data;
var base = get_host_info()['HTTPS_ORIGIN'] + base_path();
assert_equals(
result.url,
base + 'resources/dummy.png',
'The base URL while loading the images referred from CSS ' +
'must be the request URL of CSS.');
assert_equals(
result.referrer,
base + 'resources/fetch-request-css-base-url-style.css',
'While loading the image defined in CSS the referrer must ' +
'be the request URL of CSS.');
resolveTestDone();
});
});
worker.postMessage(
{port: channel.port2}, [channel.port2]);
});
})
.then(function() { return with_iframe(SCOPE); })
.then(function(f) {
return testDonePromise.then(function() {
f.remove();
return service_worker_unregister_and_done(t, SCOPE);
});
})
.catch(unreached_rejection(t));
}, 'CSS\'s base URL must be the request URL even when fetched from other URL.');
</script>

View file

@ -0,0 +1,99 @@
<!DOCTYPE html>
<title>Service Worker: FetchEvent for css image</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<script>
var url_count = 0;
var expected_results = {};
function css_image_test(frame, url, type, expexted_mode,
expected_credentials) {
var actual_url = url + (++url_count);
expected_results[actual_url] = {
url: actual_url,
mode: expexted_mode,
credentials: expected_credentials,
message: 'CSSImage load (url:' + actual_url + ' type:' + type + ')'
};
return frame.contentWindow.load_css_image(actual_url, type);
}
function css_image_set_test(frame, url, type, expexted_mode,
expected_credentials) {
var actual_url = url + (++url_count);
expected_results[actual_url] = {
url: actual_url,
mode: expexted_mode,
credentials: expected_credentials,
message: 'CSSImageSet load (url:' + actual_url + ' type:' + type + ')'
};
return frame.contentWindow.load_css_image_set(actual_url, type);
}
async_test(function(t) {
var SCOPE = 'resources/fetch-request-resources-iframe.https.html';
var SCRIPT = 'resources/fetch-request-resources-worker.js';
var host_info = get_host_info();
var LOCAL_URL =
host_info['HTTPS_ORIGIN'] + base_path() + 'resources/dummy?test';
var REMOTE_URL =
host_info['HTTPS_REMOTE_ORIGIN'] + base_path() + 'resources/dummy?test';
var worker;
var frame;
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
.then(function(registration) {
worker = registration.installing;
return wait_for_state(t, worker, 'activated');
})
.then(function() {
return new Promise(function(resolve) {
var channel = new MessageChannel();
channel.port1.onmessage = t.step_func(function(msg) {
if (msg.data.ready) {
resolve();
return;
}
var result = msg.data;
var expected = expected_results[result.url];
if (!expected) {
return;
}
assert_equals(
result.mode, expected.mode,
'mode of ' + expected.message + ' must be ' +
expected.mode + '.');
assert_equals(
result.credentials, expected.credentials,
'credentials of ' + expected.message + ' must be ' +
expected.credentials + '.');
--url_count;
delete expected_results[result.url];
if (url_count == 0) {
frame.remove();
service_worker_unregister_and_done(t, SCOPE);
}
});
worker.postMessage(
{port: channel.port2}, [channel.port2]);
});
})
.then(function() { return with_iframe(SCOPE); })
.then(function(f) {
frame = f;
css_image_test(f, LOCAL_URL, 'backgroundImage', 'no-cors', 'include');
css_image_test(f, REMOTE_URL, 'backgroundImage', 'no-cors', 'include');
css_image_test(f, LOCAL_URL, 'shapeOutside', 'cors', 'same-origin');
css_image_test(f, REMOTE_URL, 'shapeOutside', 'cors', 'same-origin');
css_image_set_test(f, LOCAL_URL, 'backgroundImage', 'no-cors', 'include');
css_image_set_test(f, REMOTE_URL, 'backgroundImage', 'no-cors', 'include');
css_image_set_test(f, LOCAL_URL, 'shapeOutside', 'cors', 'same-origin');
css_image_set_test(f, REMOTE_URL, 'shapeOutside', 'cors', 'same-origin');
})
.catch(unreached_rejection(t));
}, 'Verify FetchEvent for css images.');
</script>

View file

@ -0,0 +1,113 @@
<!DOCTYPE html>
<title>Service Worker: the fallback behavior of FetchEvent</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<script>
var expected_urls = [];
function xhr_fail_test(frame, url) {
expected_urls.push(url);
return new Promise(function(resolve, reject) {
frame.contentWindow.xhr(url)
.then(function(){
reject(url + ' should fail.');
})
.catch(function(){
resolve();
});
});
}
function xhr_succeed_test(frame, url) {
expected_urls.push(url);
return new Promise(function(resolve, reject) {
frame.contentWindow.xhr(url)
.then(function(){
resolve();
})
.catch(function(){
reject(url + ' should succeed.');
});
});
}
async_test(function(t) {
var path = new URL(".", window.location).pathname;
var SCOPE = 'resources/fetch-request-fallback-iframe.html';
var SCRIPT = 'resources/fetch-request-fallback-worker.js';
var host_info = get_host_info();
var BASE_URL = host_info['HTTPS_ORIGIN'] +
path + 'resources/fetch-access-control.py?';
var OTHER_BASE_URL = host_info['HTTPS_REMOTE_ORIGIN'] +
path + 'resources/fetch-access-control.py?';
var REDIRECT_URL = host_info['HTTPS_ORIGIN'] +
path + 'resources/redirect.py?Redirect=';
var frame;
var worker;
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
.then(function(registration) {
worker = registration.installing;
return wait_for_state(t, worker, 'activated');
})
.then(function() { return with_iframe(SCOPE); })
.then(function(f) {
frame = f;
return xhr_succeed_test(frame, BASE_URL);
})
.then(function(f) {
return xhr_fail_test(frame, OTHER_BASE_URL);
})
.then(function(f) {
return xhr_succeed_test(frame, OTHER_BASE_URL + 'ACAOrigin=*');
})
.then(function(f) {
return xhr_succeed_test(frame,
REDIRECT_URL + encodeURIComponent(BASE_URL));
})
.then(function() {
return xhr_fail_test(
frame,
REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL));
})
.then(function() {
return xhr_succeed_test(
frame,
REDIRECT_URL +
encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*'));
})
.then(function() {
return new Promise(function(resolve) {
var channel = new MessageChannel();
channel.port1.onmessage = t.step_func(function(msg) {
frame.remove();
resolve(msg);
});
worker.postMessage({port: channel.port2}, [channel.port2]);
});
})
.then(function(msg) {
var requests = msg.data.requests;
assert_equals(requests.length, expected_urls.length + 1,
'The count of the requests which are passed to the ' +
'ServiceWorker must be correct.');
assert_equals(requests[0].url, new URL(SCOPE, location).toString(),
'The first request to the SW must be the request for ' +
'the page.');
assert_equals(requests[0].mode, 'navigate',
'The mode of the first request to the SW must be ' +
'navigate');
for (var i = 0; i < expected_urls.length; ++i) {
assert_equals(requests[i + 1].url, expected_urls[i],
'The URL of the request which was passed from XHR ' +
'to the ServiceWorker must be correct.');
assert_equals(requests[i + 1].mode, 'cors',
'The mode of the request which was passed from XHR ' +
'to the ServiceWorker must be cors.');
}
service_worker_unregister_and_done(t, SCOPE);
})
.catch(unreached_rejection(t));
}, 'Verify the fallback behavior of FetchEvent');
</script>

View file

@ -0,0 +1,53 @@
<!DOCTYPE html>
<title>Service Worker: the headers of FetchEvent shouldn't contain freshness headers</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<script>
async_test(function(t) {
var SCOPE = 'resources/fetch-request-no-freshness-headers-iframe.html';
var SCRIPT = 'resources/fetch-request-no-freshness-headers-worker.js';
var worker;
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
.then(function(registration) {
worker = registration.installing;
return wait_for_state(t, worker, 'activated');
})
.then(function() { return with_iframe(SCOPE); })
.then(function(frame) {
return new Promise(function(resolve) {
frame.onload = function() {
resolve(frame);
};
frame.contentWindow.location.reload();
});
})
.then(function(frame) {
return new Promise(function(resolve) {
var channel = new MessageChannel();
channel.port1.onmessage = t.step_func(function(msg) {
frame.remove();
resolve(msg);
});
worker.postMessage(
{port: channel.port2}, [channel.port2]);
});
})
.then(function(msg) {
var freshness_headers = {
'if-none-match': true,
'if-modified-since': true
};
msg.data.requests.forEach(t.step_func(function(request) {
request.headers.forEach(t.step_func(function(header) {
assert_false(
!!freshness_headers[header[0]],
header[0] + ' header must not be set in the ' +
'FetchEvent\'s request. (url = ' + request.url + ')');
}));
}))
service_worker_unregister_and_done(t, SCOPE);
})
.catch(unreached_rejection(t));
}, 'The headers of FetchEvent shouldn\'t contain freshness headers.');
</script>

View file

@ -0,0 +1,176 @@
<!DOCTYPE html>
<title>Service Worker: FetchEvent for resources</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
function assert_resolves(promise, description) {
return promise.catch(function(reason) {
throw new Error(description + ' - ' + reason.message);
});
}
function assert_rejects(promise, description) {
return promise.then(
function() { throw new Error(description); },
function() {});
}
function iframe_test(url, timeout_enabled) {
return new Promise(function(resolve, reject) {
var frame = document.createElement('iframe');
frame.src = url;
if (timeout_enabled) {
// We can't catch the network error on iframe. So we use the timer for
// failure detection.
var timer = setTimeout(function() {
reject(new Error('iframe load timeout'));
frame.remove();
}, 10000);
}
frame.onload = function() {
if (timeout_enabled)
clearTimeout(timer);
if (frame.contentDocument.body.textContent == 'Hello world\n')
resolve();
else
reject(new Error('content mismatch'));
frame.remove();
};
document.body.appendChild(frame);
});
}
promise_test(function(t) {
var SCOPE = 'resources/fetch-request-redirect-iframe.html';
var SCRIPT = 'resources/fetch-rewrite-worker.js';
var REDIRECT_URL = base_path() + 'resources/redirect.py?Redirect=';
var IMAGE_URL = base_path() + 'resources/square.png';
var AUDIO_URL = base_path() + 'resources/silence.oga';
var XHR_URL = base_path() + 'resources/simple.txt';
var HTML_URL = base_path() + 'resources/dummy.html';
var REDIRECT_TO_IMAGE_URL = REDIRECT_URL + encodeURIComponent(IMAGE_URL);
var REDIRECT_TO_AUDIO_URL = REDIRECT_URL + encodeURIComponent(AUDIO_URL);
var REDIRECT_TO_XHR_URL = REDIRECT_URL + encodeURIComponent(XHR_URL);
var REDIRECT_TO_HTML_URL = REDIRECT_URL + encodeURIComponent(HTML_URL);
var worker;
var frame;
return service_worker_unregister_and_register(t, SCRIPT, SCOPE)
.then(function(registration) {
worker = registration.installing;
return wait_for_state(t, worker, 'activated');
})
.then(function() { return with_iframe(SCOPE); })
.then(function(f) {
frame = f;
return Promise.all([
// XMLHttpRequest tests.
assert_resolves(frame.contentWindow.xhr(XHR_URL),
'Normal XHR should succeed.'),
assert_resolves(frame.contentWindow.xhr(REDIRECT_TO_XHR_URL),
'Redirected XHR should succeed.'),
assert_resolves(
frame.contentWindow.xhr(
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
'&redirect-mode=follow'),
'Redirected XHR with Request.redirect=follow should succeed.'),
assert_rejects(
frame.contentWindow.xhr(
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
'&redirect-mode=error'),
'Redirected XHR with Request.redirect=error should fail.'),
assert_rejects(
frame.contentWindow.xhr(
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
'&redirect-mode=manual'),
'Redirected XHR with Request.redirect=manual should fail.'),
// Image loading tests.
assert_resolves(frame.contentWindow.load_image(IMAGE_URL),
'Normal image resource should be loaded.'),
assert_resolves(
frame.contentWindow.load_image(REDIRECT_TO_IMAGE_URL),
'Redirected image resource should be loaded.'),
assert_resolves(
frame.contentWindow.load_image(
'./?url=' + encodeURIComponent(REDIRECT_TO_IMAGE_URL) +
'&redirect-mode=follow'),
'Loading redirected image with Request.redirect=follow should' +
' succeed.'),
assert_rejects(
frame.contentWindow.load_image(
'./?url=' + encodeURIComponent(REDIRECT_TO_IMAGE_URL) +
'&redirect-mode=error'),
'Loading redirected image with Request.redirect=error should ' +
'fail.'),
assert_rejects(
frame.contentWindow.load_image(
'./?url=' + encodeURIComponent(REDIRECT_TO_IMAGE_URL) +
'&redirect-mode=manual'),
'Loading redirected image with Request.redirect=manual should' +
' fail.'),
// Audio loading tests.
assert_resolves(frame.contentWindow.load_audio(AUDIO_URL),
'Normal audio resource should be loaded.'),
assert_resolves(
frame.contentWindow.load_audio(REDIRECT_TO_AUDIO_URL),
'Redirected audio resource should be loaded.'),
assert_resolves(
frame.contentWindow.load_audio(
'./?url=' + encodeURIComponent(REDIRECT_TO_AUDIO_URL) +
'&redirect-mode=follow'),
'Loading redirected audio with Request.redirect=follow should' +
' succeed.'),
assert_rejects(
frame.contentWindow.load_audio(
'./?url=' + encodeURIComponent(REDIRECT_TO_AUDIO_URL) +
'&redirect-mode=error'),
'Loading redirected audio with Request.redirect=error should ' +
'fail.'),
assert_rejects(
frame.contentWindow.load_audio(
'./?url=' + encodeURIComponent(REDIRECT_TO_AUDIO_URL) +
'&redirect-mode=manual'),
'Loading redirected audio with Request.redirect=manual should' +
' fail.'),
// Iframe tests.
assert_resolves(iframe_test(HTML_URL),
'Normal iframe loading should succeed.'),
assert_resolves(
iframe_test(REDIRECT_TO_HTML_URL),
'Normal redirected iframe loading should succeed.'),
assert_resolves(
iframe_test(SCOPE + '?url=' +
encodeURIComponent(REDIRECT_TO_HTML_URL) +
'&redirect-mode=follow'),
'Redirected iframe loading with Request.redirect=follow should'+
' succeed.'),
assert_rejects(
iframe_test(SCOPE + '?url=' +
encodeURIComponent(REDIRECT_TO_HTML_URL) +
'&redirect-mode=error',
true /* timeout_enabled */),
'Redirected iframe loading with Request.redirect=error should '+
'fail.'),
assert_resolves(
iframe_test(SCOPE + '?url=' +
encodeURIComponent(REDIRECT_TO_HTML_URL) +
'&redirect-mode=manual',
true /* timeout_enabled */),
'Redirected iframe loading with Request.redirect=manual should'+
' succeed.'),
]);
})
.then(function() {
frame.remove();
service_worker_unregister_and_done(t, SCOPE);
});
}, 'Verify redirect mode of Fetch API and ServiceWorker FetchEvent.');
</script>

View file

@ -0,0 +1,142 @@
<!DOCTYPE html>
<title>Service Worker: FetchEvent for resources</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<script>
var url_count = 0;
var expected_results = {};
function image_test(frame, url, cross_origin, expexted_mode,
expected_credentials) {
var actual_url = url + (++url_count);
expected_results[actual_url] = {
cross_origin: cross_origin,
mode: expexted_mode,
credentials: expected_credentials,
message: 'Image load (url:' +
actual_url + ' cross_origin:' + cross_origin + ')'
};
return frame.contentWindow.load_image(actual_url, cross_origin);
}
function script_test(frame, url, cross_origin, expexted_mode,
expected_credentials) {
var actual_url = url + (++url_count);
expected_results[actual_url] = {
cross_origin: cross_origin,
mode: expexted_mode,
credentials: expected_credentials,
message: 'Script load (url:' +
actual_url + ' cross_origin:' + cross_origin + ')'
};
return frame.contentWindow.load_script(actual_url, cross_origin);
}
function css_test(frame, url, cross_origin, expexted_mode,
expected_credentials) {
var actual_url = url + (++url_count);
expected_results[actual_url] = {
cross_origin: cross_origin,
mode: expexted_mode,
credentials: expected_credentials,
message: 'CSS load (url:' +
actual_url + ' cross_origin:' + cross_origin + ')'
};
return frame.contentWindow.load_css(actual_url, cross_origin);
}
function font_face_test(frame, url, expexted_mode, expected_credentials) {
var actual_url = url + (++url_count);
expected_results[actual_url] = {
url: actual_url,
mode: expexted_mode,
credentials: expected_credentials,
message: 'FontFace load (url:' + actual_url + ')'
};
return frame.contentWindow.load_font(actual_url);
}
async_test(function(t) {
var SCOPE = 'resources/fetch-request-resources-iframe.https.html';
var SCRIPT = 'resources/fetch-request-resources-worker.js';
var host_info = get_host_info();
var LOCAL_URL =
host_info['HTTPS_ORIGIN'] + base_path() + 'resources/dummy?test';
var REMOTE_URL =
host_info['HTTPS_REMOTE_ORIGIN'] + base_path() + 'resources/dummy?test';
var worker;
var frame;
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
.then(function(registration) {
worker = registration.installing;
return wait_for_state(t, worker, 'activated');
})
.then(function() {
return new Promise(function(resolve) {
var channel = new MessageChannel();
channel.port1.onmessage = t.step_func(function(msg) {
if (msg.data.ready) {
resolve();
return;
}
var result = msg.data;
var expected = expected_results[result.url];
if (!expected) {
return;
}
assert_equals(
result.mode, expected.mode,
'mode of ' + expected.message + ' must be ' +
expected.mode + '.');
assert_equals(
result.credentials, expected.credentials,
'credentials of ' + expected.message + ' must be ' +
expected.credentials + '.');
--url_count;
delete expected_results[result.url];
if (url_count == 0) {
frame.remove();
service_worker_unregister_and_done(t, SCOPE);
}
});
worker.postMessage(
{port: channel.port2}, [channel.port2]);
});
})
.then(function() { return with_iframe(SCOPE); })
.then(function(f) {
frame = f;
// TODO: Disable 'no-cors' tests for image until
// AsyncOpen2 and cookie policy is supported.
// image_test(f, LOCAL_URL, '', 'no-cors', 'include');
// image_test(f, REMOTE_URL, '', 'no-cors', 'include');
css_test(f, LOCAL_URL, '', 'no-cors', 'include');
css_test(f, REMOTE_URL, '', 'no-cors', 'include');
image_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin');
image_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include');
image_test(f, REMOTE_URL, 'anonymous', 'cors', 'omit');
image_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include');
script_test(f, LOCAL_URL, '', 'no-cors', 'include');
script_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin');
script_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include');
script_test(f, REMOTE_URL, '', 'no-cors', 'include');
script_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin');
script_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include');
css_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin');
css_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include');
css_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin');
css_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include');
font_face_test(f, LOCAL_URL, 'cors', 'same-origin');
font_face_test(f, REMOTE_URL, 'cors', 'same-origin');
})
.catch(unreached_rejection(t));
}, 'Verify FetchEvent for resources.');
</script>

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<title>Service Worker: the body of FetchEvent using XMLHttpRequest</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<script>
async_test(function(t) {
var SCOPE = 'resources/fetch-request-xhr-iframe.https.html';
var SCRIPT = 'resources/fetch-request-xhr-worker.js';
var host_info = get_host_info();
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return with_iframe(SCOPE); })
.then(function(frame) {
var channel = new MessageChannel();
channel.port1.onmessage = t.step_func(function(e) {
if (e.data.results === 'finish') {
frame.remove();
service_worker_unregister_and_done(t, SCOPE);
} else if (e.data.results == 'equals') {
assert_equals(e.data.got, e.data.expected);
}
});
frame.contentWindow.postMessage({},
host_info['HTTPS_ORIGIN'],
[channel.port2]);
})
.catch(unreached_rejection(t));
}, 'Verify the body of FetchEvent using XMLHttpRequest');
</script>

View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<title>Service Worker: the response of FetchEvent using XMLHttpRequest</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<script>
async_test(function(t) {
var SCOPE = 'resources/fetch-response-xhr-iframe.https.html';
var SCRIPT = 'resources/fetch-response-xhr-worker.js';
var host_info = get_host_info();
window.addEventListener('message', t.step_func(on_message), false);
function on_message(e) {
assert_equals(e.data.results, 'foo, bar');
t.done();
}
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
.then(function(registration) {
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return with_iframe(SCOPE); })
.then(function(frame) {
var channel = new MessageChannel();
channel.port1.onmessage = t.step_func(function(e) {
assert_equals(e.data.results, 'finish');
frame.remove();
service_worker_unregister_and_done(t, SCOPE);
});
frame.contentWindow.postMessage({},
host_info['HTTPS_ORIGIN'],
[channel.port2]);
})
.catch(unreached_rejection(t));
}, 'Verify the response of FetchEvent using XMLHttpRequest');
</script>

View file

@ -0,0 +1,63 @@
<!DOCTYPE html>
<title>Service Worker: Fetch Event Waits for Activate Event</title>
<meta name=timeout content=long>
<script src="/resources/testharness.js"></script>
<script src="resources/testharness-helpers.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
var worker = 'resources/fetch-waits-for-activate-worker.js';
var expected_url = normalizeURL(worker);
var scope = 'resources/fetch-waits-for-activate/';
async_test(function(t) {
var registration;
var frameLoadPromise;
var frame;
service_worker_unregister_and_register(t, worker, scope).then(function(reg) {
registration = reg;
return wait_for_state(t, reg.installing, 'activating');
}).then(function() {
assert_equals(registration.active.scriptURL, expected_url,
'active worker should be present');
assert_equals(registration.active.state, 'activating',
'active worker should be in activating state');
// This should block until we message the worker to tell it to complete
// the activate event.
frameLoadPromise = with_iframe(scope).then(function(f) {
frame = f;
});
// Wait some time to allow frame loading to proceed. It should not,
// however, if the fetch event is blocked on the activate. I don't
// see any way to force this race without a timeout, unfortunately.
return new Promise(function(resolve) {
setTimeout(resolve, 1000);
});
}).then(function() {
assert_equals(frame, undefined, 'frame should not be loaded');
assert_equals(registration.active.scriptURL, expected_url,
'active worker should be present');
assert_equals(registration.active.state, 'activating',
'active worker should be in activating state');
// This signals the activate event to complete. The frame should now
// load.
registration.active.postMessage('GO');
return frameLoadPromise;
}).then(function() {
assert_equals(frame.contentWindow.navigator.serviceWorker.controller.scriptURL,
expected_url, 'frame should now be loaded and controlled');
assert_equals(registration.active.state, 'activated',
'active worker should be in activated state');
frame.remove();
return service_worker_unregister_and_done(t, scope);
}).catch(unreached_rejection(t));
}, 'Fetch events should wait for the activate event to complete.');
</script>
</body>

View file

@ -0,0 +1,87 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
async_test(function(t) {
var documentURL = 'no-such-worker';
navigator.serviceWorker.getRegistration(documentURL)
.then(function(value) {
assert_equals(value, undefined,
'getRegistration should resolve with undefined');
t.done();
})
.catch(unreached_rejection(t));
}, 'getRegistration');
async_test(function(t) {
var scope = 'resources/scope/getregistration/normal';
var registration;
service_worker_unregister_and_register(t, 'resources/empty-worker.js',
scope)
.then(function(r) {
registration = r;
return navigator.serviceWorker.getRegistration(scope);
})
.then(function(value) {
assert_equals(
value, registration,
'getRegistration should resolve to the same registration object');
service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Register then getRegistration');
async_test(function(t) {
var scope = 'resources/scope/getregistration/url-with-fragment';
var documentURL = scope + '#ref';
var registration;
service_worker_unregister_and_register(t, 'resources/empty-worker.js',
scope)
.then(function(r) {
registration = r;
return navigator.serviceWorker.getRegistration(documentURL);
})
.then(function(value) {
assert_equals(
value, registration,
'getRegistration should resolve to the same registration object');
service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Register then getRegistration with a URL having a fragment');
async_test(function(t) {
var documentURL = 'http://example.com/';
navigator.serviceWorker.getRegistration(documentURL)
.then(function() {
assert_unreached(
'getRegistration with an out of origin URL should fail');
}, function(reason) {
assert_equals(
reason.name, 'SecurityError',
'getRegistration with an out of origin URL should fail');
t.done();
})
.catch(unreached_rejection(t));
}, 'getRegistration with a cross origin URL');
async_test(function(t) {
var scope = 'resources/scope/getregistration/register-unregister';
service_worker_unregister_and_register(t, 'resources/empty-worker.js',
scope)
.then(function(registration) {
return registration.unregister();
})
.then(function() {
return navigator.serviceWorker.getRegistration(scope);
})
.then(function(value) {
assert_equals(value, undefined,
'getRegistration should resolve with undefined');
t.done();
})
.catch(unreached_rejection(t));
}, 'Register then Unregister then getRegistration');
</script>

View file

@ -0,0 +1,159 @@
<!DOCTYPE html>
<title>Service Worker: getRegistrations()</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="../fetch/resources/fetch-test-helpers.sub.js"></script>
<script>
// Purge the existing registrations for the origin.
// getRegistrations() is used in order to avoid adding additional complexity
// e.g. adding an internal function.
promise_test(function(t) {
return navigator.serviceWorker.getRegistrations()
.then(function(registrations) {
return registrations.reduce(function(sequence, registration) {
return sequence.then(function() {
return registration.unregister();
});
}, Promise.resolve());
});
}, 'Purge the existing registrations.');
promise_test(function(t) {
return navigator.serviceWorker.getRegistrations()
.then(function(value) {
assert_array_equals(
value,
[],
'getRegistrations should resolve with an empty array.');
});
}, 'getRegistrations');
promise_test(function(t) {
var scope = 'resources/scope/getregistrations/normal';
var script = 'resources/empty-worker.js';
var registrations = [];
return service_worker_unregister_and_register(t, script, scope)
.then(function(r) {
registrations.push(r);
return navigator.serviceWorker.getRegistrations();
})
.then(function(value) {
assert_array_equals(
value,
registrations,
'getRegistrations should resolve with array of registrations.');
return service_worker_unregister(t, scope);
});
}, 'Register then getRegistrations');
promise_test(function(t) {
var scope1 = 'resources/scope/getregistrations/scope1';
var scope2 = 'resources/scope/getregistrations/scope2';
var script = 'resources/empty-worker.js';
var registrations = [];
return service_worker_unregister_and_register(t, script, scope1)
.then(function(r) {
registrations.push(r);
return service_worker_unregister_and_register(t, script, scope2);
})
.then(function(r) {
registrations.push(r);
return navigator.serviceWorker.getRegistrations();
})
.then(function(value) {
assert_array_equals(
value,
registrations,
'getRegistrations should resolve with array of registrations.');
return service_worker_unregister(t, scope1);
})
.then(function() {
return service_worker_unregister(t, scope2);
});
}, 'Register multiple times then getRegistrations');
promise_test(function(t) {
var scope = 'resources/scope/getregistrations/register-unregister';
var script = 'resources/empty-worker.js';
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
return registration.unregister();
})
.then(function() {
return navigator.serviceWorker.getRegistrations();
})
.then(function(value) {
assert_array_equals(
value,
[],
'getRegistrations should resolve with an empty array.');
});
}, 'Register then Unregister then getRegistrations');
promise_test(function(t) {
var host_info = get_host_info();
// Rewrite the url to point to remote origin.
var frame_same_origin_url = new URL("resources/frame-for-getregistrations.html", window.location);
var frame_url = host_info['HTTPS_REMOTE_ORIGIN'] + frame_same_origin_url.pathname;
var scope = 'resources/scope-for-getregistrations';
var script = 'resources/empty-worker.js';
var frame;
var registrations = [];
// Loads an iframe and waits for 'ready' message from it to resolve promise.
// Caller is responsible for removing frame.
function with_iframe_ready(url) {
return new Promise(function(resolve) {
var frame = document.createElement('iframe');
frame.src = url;
window.addEventListener('message', function onMessage(e) {
window.removeEventListener('message', onMessage);
if (e.data == 'ready') {
resolve(frame);
}
});
document.body.appendChild(frame);
});
}
// We need this special frame loading function because the frame is going
// to register it's own service worker and there is the possibility that that
// register() finishes after the register() for the same domain later in the
// test. So we have to wait until the cross origin register() is done, and not
// just until the frame loads.
return with_iframe_ready(frame_url)
.then(function(f) {
frame = f;
return service_worker_unregister_and_register(t, script, scope);
})
.then(function(r) {
registrations.push(r);
return navigator.serviceWorker.getRegistrations();
})
.then(function(value) {
assert_array_equals(
value,
registrations,
'getRegistrations should only return same origin registrations.');
var channel = new MessageChannel();
var resolve;
var p = new Promise(function(r) { resolve = r; });
channel.port1.onmessage = function(e) {
if (e.data == 'unregistered')
resolve();
};
frame.contentWindow.postMessage('unregister', '*', [channel.port2]);
return p;
})
.then(function() {
frame.remove();
return service_worker_unregister(t, scope);
});
}, 'getRegistrations promise resolves only with same origin registrations.');
done();
</script>

View file

@ -0,0 +1,35 @@
<!DOCTYPE html>
<title>Service Worker: Indexed DB</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
async_test(function(t) {
var scope = 'resources/blank.html';
service_worker_unregister_and_register(
t, 'resources/indexeddb-worker.js', scope)
.then(function(registration) {
var sw = registration.installing;
var messageChannel = new MessageChannel();
messageChannel.port1.onmessage = t.step_func(onMessage);
sw.postMessage({port: messageChannel.port2}, [messageChannel.port2]);
})
.catch(unreached_rejection(t));
function onMessage() {
var openRequest = indexedDB.open('db');
openRequest.onsuccess = t.step_func(function() {
var db = openRequest.result;
var tx = db.transaction('store');
var store = tx.objectStore('store');
var getRequest = store.get('key');
getRequest.onsuccess = t.step_func(function() {
assert_equals(
getRequest.result, 'value',
'The get() result should match what the worker put().');
service_worker_unregister_and_done(t, scope);
});
});
}
}, 'Verify Indexed DB operation in a Service Worker');
</script>

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="resources/testharness-helpers.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
function wait_for_install_event(worker) {
return new Promise(function(resolve) {
worker.addEventListener('statechange', function(event) {
if (worker.state == 'installed')
resolve(true);
else if (worker.state == 'redundant')
resolve(false);
});
});
}
promise_test(function(t) {
var script = 'resources/install-event-type-worker.js';
var scope = 'resources/install-event-type';
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
return wait_for_install_event(registration.installing);
})
.then(function(did_install) {
assert_true(did_install, 'The worker was installed');
})
}, 'install event type');
</script>

View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<title>ServiceWorker: navigator.serviceWorker.installing</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
// "installing" is set
async_test(function(t) {
var step = t.step_func.bind(t);
var url = 'resources/empty-worker.js';
var scope = 'resources/blank.html';
var frame;
service_worker_unregister(t, scope)
.then(step(function() { return with_iframe(scope); }))
.then(step(function(f) {
frame = f;
return navigator.serviceWorker.register(url, {scope: scope});
}))
.then(step(function(registration) {
var container = frame.contentWindow.navigator.serviceWorker;
assert_equals(container.controller, null);
assert_equals(registration.active, null);
assert_equals(registration.waiting, null);
assert_equals(registration.installing.scriptURL, normalizeURL(url));
// FIXME: Add a test for a frame created after installation.
// Should the existing frame ("frame") block activation?
}))
.then(step(function() {
frame.remove();
return service_worker_unregister_and_done(t, scope);
}))
.catch(unreached_rejection(t));
}, 'installing is set');
</script>

View file

@ -0,0 +1,56 @@
<!DOCTYPE html>
<title>Service Worker: Interfaces</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/interfaces.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
test(function() {
var EVENT_HANDLER = 'object';
verify_interface(
'ServiceWorkerContainer', navigator.serviceWorker,
{
register: 'function',
getRegistration: 'function',
oncontrollerchange: EVENT_HANDLER
});
}, 'Interfaces and attributes of ServiceWorkerContainer');
async_test(function(t) {
var EVENT_HANDLER = 'object';
var scope = 'resources/scope/interfaces-and-attributes';
service_worker_unregister_and_register(
t, 'resources/empty-worker.js', scope)
.then(function(registration) {
verify_interface(
'ServiceWorkerRegistration', registration,
{
installing: 'object',
waiting: 'object',
active: 'object',
scope: 'string',
unregister: 'function',
onupdatefound: EVENT_HANDLER
});
verify_interface(
'ServiceWorker', registration.installing,
{
scriptURL: 'string',
state: 'string',
onstatechange: EVENT_HANDLER
});
return registration.unregister();
})
.then(function() {
t.done();
})
.catch(unreached_rejection(t));
}, 'Interfaces and attributes of ServiceWorker');
service_worker_test(
'resources/interfaces-worker.sub.js',
'Interfaces and attributes in ServiceWorkerGlobalScope');
</script>

Some files were not shown because too many files have changed in this diff Show more