Import Cobalt 19.master.0.203780
Includes the following patches:
https://cobalt-review.googlesource.com/c/cobalt/+/5210
by errong.leng@samsung.com
https://cobalt-review.googlesource.com/c/cobalt/+/5270
by linus.wang@samsung.com
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/common.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/common.https.html
new file mode 100644
index 0000000..d5f7d24
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/common.https.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<title>Cache Storage: Verify that Window and Workers see same storage</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/testharness-helpers.js"></script>
+<script>
+
+function wait_for_message(worker) {
+ return new Promise(function(resolve) {
+ worker.addEventListener('message', function listener(e) {
+ resolve(e.data);
+ worker.removeEventListener('message', listener);
+ });
+ });
+}
+
+promise_test(function(t) {
+ var cache_name = 'common-test';
+ return self.caches.delete(cache_name)
+ .then(function() {
+ var worker = new Worker('resources/common-worker.js');
+ worker.postMessage({name: cache_name});
+ return wait_for_message(worker);
+ })
+ .then(function(message) {
+ return self.caches.open(cache_name);
+ })
+ .then(function(cache) {
+ return Promise.all([
+ cache.match('https://example.com/a'),
+ cache.match('https://example.com/b'),
+ cache.match('https://example.com/c')
+ ]);
+ })
+ .then(function(responses) {
+ return Promise.all(responses.map(
+ function(response) { return response.text(); }
+ ));
+ })
+ .then(function(bodies) {
+ assert_equals(bodies[0], 'a',
+ 'Body should match response put by worker');
+ assert_equals(bodies[1], 'b',
+ 'Body should match response put by worker');
+ assert_equals(bodies[2], 'c',
+ 'Body should match response put by worker');
+ });
+}, 'Window sees cache puts by Worker');
+
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/resources/blank.html b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/blank.html
new file mode 100644
index 0000000..a3c3a46
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/blank.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<title>Empty doc</title>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/resources/common-worker.js b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/common-worker.js
new file mode 100644
index 0000000..d0e8544
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/common-worker.js
@@ -0,0 +1,15 @@
+self.onmessage = function(e) {
+ var cache_name = e.data.name;
+
+ self.caches.open(cache_name)
+ .then(function(cache) {
+ return Promise.all([
+ cache.put('https://example.com/a', new Response('a')),
+ cache.put('https://example.com/b', new Response('b')),
+ cache.put('https://example.com/c', new Response('c'))
+ ]);
+ })
+ .then(function() {
+ self.postMessage('ok');
+ });
+};
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/resources/fetch-status.py b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/fetch-status.py
new file mode 100644
index 0000000..71f13eb
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/fetch-status.py
@@ -0,0 +1,2 @@
+def main(request, response):
+ return int(request.GET["status"]), [], ""
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/resources/iframe.html b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/iframe.html
new file mode 100644
index 0000000..a2f1e50
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/iframe.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>ok</title>
+<script>
+window.onmessage = function(e) {
+ var id = e.data.id;
+ try {
+ var name = 'checkallowed';
+ self.caches.open(name).then(function (cache) {
+ self.caches.delete(name);
+ window.parent.postMessage({id: id, result: 'allowed'}, '*');
+ }).catch(function(e) {
+ window.parent.postMessage({id: id, result: 'denied', name: e.name, message: e.message}, '*');
+ });
+ } catch (e) {
+ window.parent.postMessage({id: id, result: 'unexpecteddenied', name: e.name, message: e.message}, '*');
+ }
+};
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/resources/simple.txt b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/simple.txt
new file mode 100644
index 0000000..9e3cb91
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/simple.txt
@@ -0,0 +1 @@
+a simple text file
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/resources/test-helpers.js b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/test-helpers.js
new file mode 100644
index 0000000..9111095
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/test-helpers.js
@@ -0,0 +1,37 @@
+(function() {
+ var next_cache_index = 1;
+
+ // Returns a promise that resolves to a newly created Cache object. The
+ // returned Cache will be destroyed when |test| completes.
+ function create_temporary_cache(test) {
+ var uniquifier = String(++next_cache_index);
+ var cache_name = self.location.pathname + '/' + uniquifier;
+
+ test.add_cleanup(function() {
+ self.caches.delete(cache_name);
+ });
+
+ return self.caches.delete(cache_name)
+ .then(function() {
+ return self.caches.open(cache_name);
+ });
+ }
+
+ self.create_temporary_cache = create_temporary_cache;
+})();
+
+// Runs |test_function| with a temporary unique Cache passed in as the only
+// argument. The function is run as a part of Promise chain owned by
+// promise_test(). As such, it is expected to behave in a manner identical (with
+// the exception of the argument) to a function passed into promise_test().
+//
+// E.g.:
+// cache_test(function(cache) {
+// // Do something with |cache|, which is a Cache object.
+// }, "Some Cache test");
+function cache_test(test_function, description) {
+ promise_test(function(test) {
+ return create_temporary_cache(test)
+ .then(test_function);
+ }, description);
+}
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/resources/testharness-helpers.js b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/testharness-helpers.js
new file mode 100644
index 0000000..4566705
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/resources/testharness-helpers.js
@@ -0,0 +1,100 @@
+/*
+ * testharness-helpers contains various useful extensions to testharness.js to
+ * allow them to be used across multiple tests before they have been
+ * upstreamed. This file is intended to be usable from both document and worker
+ * environments, so code should for example not rely on the DOM.
+ */
+
+// Returns a promise that fulfills after the provided |promise| is fulfilled.
+// The |test| succeeds only if |promise| rejects with an exception matching
+// |code|. Accepted values for |code| follow those accepted for assert_throws().
+// The optional |description| describes the test being performed.
+//
+// E.g.:
+// assert_promise_rejects(
+// new Promise(...), // something that should throw an exception.
+// 'NotFoundError',
+// 'Should throw NotFoundError.');
+//
+// assert_promise_rejects(
+// new Promise(...),
+// new TypeError(),
+// 'Should throw TypeError');
+function assert_promise_rejects(promise, code, description) {
+ return promise.then(
+ function() {
+ throw 'assert_promise_rejects: ' + description + ' Promise did not reject.';
+ },
+ function(e) {
+ if (code !== undefined) {
+ assert_throws(code, function() { throw e; }, description);
+ }
+ });
+}
+
+// Helper for testing with Headers objects. Compares Headers instances
+// by serializing |expected| and |actual| to arrays and comparing.
+function assert_header_equals(actual, expected, description) {
+ assert_class_string(actual, "Headers", description);
+ var header, actual_headers = [], expected_headers = [];
+ for (header of actual)
+ actual_headers.push(header[0] + ": " + header[1]);
+ for (header of expected)
+ expected_headers.push(header[0] + ": " + header[1]);
+ assert_array_equals(actual_headers, expected_headers,
+ description + " Headers differ.");
+}
+
+// Helper for testing with Response objects. Compares simple
+// attributes defined on the interfaces, as well as the headers. It
+// does not compare the response bodies.
+function assert_response_equals(actual, expected, description) {
+ assert_class_string(actual, "Response", description);
+ ["type", "url", "status", "ok", "statusText"].forEach(function(attribute) {
+ assert_equals(actual[attribute], expected[attribute],
+ description + " Attributes differ: " + attribute + ".");
+ });
+ assert_header_equals(actual.headers, expected.headers, description);
+}
+
+// Assert that the two arrays |actual| and |expected| contain the same
+// set of Responses as determined by assert_response_equals. The order
+// is not significant.
+//
+// |expected| is assumed to not contain any duplicates.
+function assert_response_array_equivalent(actual, expected, description) {
+ assert_true(Array.isArray(actual), description);
+ assert_equals(actual.length, expected.length, description);
+ expected.forEach(function(expected_element) {
+ // assert_response_in_array treats the first argument as being
+ // 'actual', and the second as being 'expected array'. We are
+ // switching them around because we want to be resilient
+ // against the |actual| array containing duplicates.
+ assert_response_in_array(expected_element, actual, description);
+ });
+}
+
+// Asserts that two arrays |actual| and |expected| contain the same
+// set of Responses as determined by assert_response_equals(). The
+// corresponding elements must occupy corresponding indices in their
+// respective arrays.
+function assert_response_array_equals(actual, expected, description) {
+ assert_true(Array.isArray(actual), description);
+ assert_equals(actual.length, expected.length, description);
+ actual.forEach(function(value, index) {
+ assert_response_equals(value, expected[index],
+ description + " : object[" + index + "]");
+ });
+}
+
+// Equivalent to assert_in_array, but uses assert_response_equals.
+function assert_response_in_array(actual, expected_array, description) {
+ assert_true(expected_array.some(function(element) {
+ try {
+ assert_response_equals(actual, element);
+ return true;
+ } catch (e) {
+ return false;
+ }
+ }), description);
+}
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-add.js b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-add.js
new file mode 100644
index 0000000..49b8db4
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-add.js
@@ -0,0 +1,135 @@
+if (self.importScripts) {
+ importScripts('/resources/testharness.js');
+ importScripts('../resources/testharness-helpers.js');
+ importScripts('../resources/test-helpers.js');
+}
+
+cache_test(function(cache) {
+ return assert_promise_rejects(
+ cache.add(),
+ new TypeError(),
+ 'Cache.add should throw a TypeError when no arguments are given.');
+ }, 'Cache.add called with no arguments');
+
+cache_test(function(cache) {
+ return cache.add('../resources/simple.txt')
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.add should resolve with undefined on success.');
+ });
+ }, 'Cache.add called with relative URL specified as a string');
+
+cache_test(function(cache) {
+ return assert_promise_rejects(
+ cache.add('javascript://this-is-not-http-mmkay'),
+ new TypeError(),
+ 'Cache.add should throw a TypeError for non-HTTP/HTTPS URLs.');
+ }, 'Cache.add called with non-HTTP/HTTPS URL');
+
+cache_test(function(cache) {
+ var request = new Request('../resources/simple.txt');
+ return cache.add(request)
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.add should resolve with undefined on success.');
+ });
+ }, 'Cache.add called with Request object');
+
+cache_test(function(cache) {
+ var request = new Request('../resources/simple.txt');
+ return cache.add(request)
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.add should resolve with undefined on success.');
+ })
+ .then(function() {
+ return cache.add(request);
+ })
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.add should resolve with undefined on success.');
+ });
+ }, 'Cache.add called twice with the same Request object');
+
+cache_test(function(cache) {
+ return cache.add('this-does-not-exist-please-dont-create-it')
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.add should resolve with undefined on success.');
+ });
+ }, 'Cache.add with request that results in a status of 404');
+
+cache_test(function(cache) {
+ return cache.add('../resources/fetch-status.py?status=500')
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.add should resolve with undefined on success.');
+ });
+ }, 'Cache.add with request that results in a status of 500');
+
+cache_test(function(cache) {
+ return assert_promise_rejects(
+ cache.addAll(),
+ new TypeError(),
+ 'Cache.addAll with no arguments should throw TypeError.');
+ }, 'Cache.addAll with no arguments');
+
+cache_test(function(cache) {
+ // Assumes the existence of ../resources/simple.txt and ../resources/blank.html
+ var urls = ['../resources/simple.txt', undefined, '../resources/blank.html'];
+ return assert_promise_rejects(
+ cache.addAll(),
+ new TypeError(),
+ 'Cache.addAll should throw TypeError for an undefined argument.');
+ }, 'Cache.addAll with a mix of valid and undefined arguments');
+
+cache_test(function(cache) {
+ // Assumes the existence of ../resources/simple.txt and ../resources/blank.html
+ var urls = ['../resources/simple.txt', self.location.href, '../resources/blank.html'];
+ return cache.addAll(urls)
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.addAll should resolve with undefined on ' +
+ 'success.');
+ });
+ }, 'Cache.addAll with string URL arguments');
+
+cache_test(function(cache) {
+ // Assumes the existence of ../resources/simple.txt and ../resources/blank.html
+ var urls = ['../resources/simple.txt', self.location.href, '../resources/blank.html'];
+ var requests = urls.map(function(url) {
+ return new Request(url);
+ });
+ return cache.addAll(requests)
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.addAll should resolve with undefined on ' +
+ 'success.');
+ });
+ }, 'Cache.addAll with Request arguments');
+
+cache_test(function(cache) {
+ // Assumes that ../resources/simple.txt and ../resources/blank.html exist. The second
+ // resource does not.
+ var urls = ['../resources/simple.txt', 'this-resource-should-not-exist', '../resources/blank.html'];
+ var requests = urls.map(function(url) {
+ return new Request(url);
+ });
+ return cache.addAll(requests)
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.addAll should resolve with undefined on ' +
+ 'success.');
+ });
+ }, 'Cache.addAll with a mix of succeeding and failing requests');
+
+cache_test(function(cache) {
+ var request = new Request('../resources/simple.txt');
+ return assert_promise_rejects(
+ cache.addAll([request, request]),
+ 'InvalidStateError',
+ 'Cache.addAll should throw InvalidStateError if the same request is added ' +
+ 'twice.');
+ }, 'Cache.addAll called with the same Request object specified twice');
+
+done();
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-delete.js b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-delete.js
new file mode 100644
index 0000000..75a474c
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-delete.js
@@ -0,0 +1,96 @@
+if (self.importScripts) {
+ importScripts('/resources/testharness.js');
+ importScripts('../resources/testharness-helpers.js');
+ importScripts('../resources/test-helpers.js');
+}
+
+var test_url = 'https://example.com/foo';
+
+// Construct a generic Request object. The URL is |test_url|. All other fields
+// are defaults.
+function new_test_request() {
+ return new Request(test_url);
+}
+
+// Construct a generic Response object.
+function new_test_response() {
+ return new Response('Hello world!', { status: 200 });
+}
+
+cache_test(function(cache) {
+ return assert_promise_rejects(
+ cache.delete(),
+ new TypeError(),
+ 'Cache.delete should reject with a TypeError when called with no ' +
+ 'arguments.');
+ }, 'Cache.delete with no arguments');
+
+cache_test(function(cache) {
+ return cache.put(new_test_request(), new_test_response())
+ .then(function() {
+ return cache.delete(test_url);
+ })
+ .then(function(result) {
+ assert_true(result,
+ 'Cache.delete should resolve with "true" if an entry ' +
+ 'was successfully deleted.');
+ return cache.match(test_url);
+ })
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.delete should remove matching entries from cache.');
+ });
+ }, 'Cache.delete called with a string URL');
+
+cache_test(function(cache) {
+ var request = new Request(test_url);
+ return cache.put(request, new_test_response())
+ .then(function() {
+ return cache.delete(request);
+ })
+ .then(function(result) {
+ assert_true(result,
+ 'Cache.delete should resolve with "true" if an entry ' +
+ 'was successfully deleted.');
+ });
+ }, 'Cache.delete called with a Request object');
+
+cache_test(function(cache) {
+ return cache.delete(test_url)
+ .then(function(result) {
+ assert_false(result,
+ 'Cache.delete should resolve with "false" if there ' +
+ 'are no matching entries.');
+ });
+ }, 'Cache.delete with a non-existent entry');
+
+var cache_entries = {
+ a: {
+ request: new Request('http://example.com/abc'),
+ response: new Response('')
+ },
+
+ b: {
+ request: new Request('http://example.com/b'),
+ response: new Response('')
+ },
+
+ a_with_query: {
+ request: new Request('http://example.com/abc?q=r'),
+ response: new Response('')
+ }
+};
+
+function prepopulated_cache_test(test_function, description) {
+ cache_test(function(cache) {
+ return Promise.all(Object.keys(cache_entries).map(function(k) {
+ return cache.put(cache_entries[k].request.clone(),
+ cache_entries[k].response.clone());
+ }))
+ .then(function() {
+ return test_function(cache);
+ });
+ }, description);
+}
+
+done();
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-match.js b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-match.js
new file mode 100644
index 0000000..02cf6cf
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-match.js
@@ -0,0 +1,442 @@
+if (self.importScripts) {
+ importScripts('/resources/testharness.js');
+ importScripts('../resources/testharness-helpers.js');
+ importScripts('../resources/test-helpers.js');
+}
+
+// A set of Request/Response pairs to be used with prepopulated_cache_test().
+var simple_entries = [
+ {
+ name: 'a',
+ request: new Request('http://example.com/a'),
+ response: new Response('')
+ },
+
+ {
+ name: 'b',
+ request: new Request('http://example.com/b'),
+ response: new Response('')
+ },
+
+ {
+ name: 'a_with_query',
+ request: new Request('http://example.com/a?q=r'),
+ response: new Response('')
+ },
+
+ {
+ name: 'A',
+ request: new Request('http://example.com/A'),
+ response: new Response('')
+ },
+
+ {
+ name: 'a_https',
+ request: new Request('https://example.com/a'),
+ response: new Response('')
+ },
+
+ {
+ name: 'a_org',
+ request: new Request('http://example.org/a'),
+ response: new Response('')
+ },
+
+ {
+ name: 'cat',
+ request: new Request('http://example.com/cat'),
+ response: new Response('')
+ },
+
+ {
+ name: 'catmandu',
+ request: new Request('http://example.com/catmandu'),
+ response: new Response('')
+ },
+
+ {
+ name: 'cat_num_lives',
+ request: new Request('http://example.com/cat?lives=9'),
+ response: new Response('')
+ },
+
+ {
+ name: 'cat_in_the_hat',
+ request: new Request('http://example.com/cat/in/the/hat'),
+ response: new Response('')
+ }
+];
+
+// A set of Request/Response pairs to be used with prepopulated_cache_test().
+// These contain a mix of test cases that use Vary headers.
+var vary_entries = [
+ {
+ name: 'vary_cookie_is_cookie',
+ request: new Request('http://example.com/c',
+ {headers: {'Cookies': 'is-for-cookie'}}),
+ response: new Response('',
+ {headers: {'Vary': 'Cookies'}})
+ },
+
+ {
+ name: 'vary_cookie_is_good',
+ request: new Request('http://example.com/c',
+ {headers: {'Cookies': 'is-good-enough-for-me'}}),
+ response: new Response('',
+ {headers: {'Vary': 'Cookies'}})
+ },
+
+ {
+ name: 'vary_cookie_absent',
+ request: new Request('http://example.com/c'),
+ response: new Response('',
+ {headers: {'Vary': 'Cookies'}})
+ }
+];
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.matchAll('not-present-in-the-cache')
+ .then(function(result) {
+ assert_response_array_equivalent(
+ result, [],
+ 'Cache.matchAll should resolve with an empty array on failure.');
+ });
+ }, 'Cache.matchAll with no matching entries');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.match('not-present-in-the-cache')
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.match failures should resolve with undefined.');
+ });
+ }, 'Cache.match with no matching entries');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.matchAll(entries.a.request.url)
+ .then(function(result) {
+ assert_response_array_equals(result, [entries.a.response],
+ 'Cache.matchAll should match by URL.');
+ });
+ }, 'Cache.matchAll with URL');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.match(entries.a.request.url)
+ .then(function(result) {
+ assert_response_equals(result, entries.a.response,
+ 'Cache.match should match by URL.');
+ });
+ }, 'Cache.match with URL');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.matchAll(entries.a.request)
+ .then(function(result) {
+ assert_response_array_equals(
+ result, [entries.a.response],
+ 'Cache.matchAll should match by Request.');
+ });
+ }, 'Cache.matchAll with Request');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.match(entries.a.request)
+ .then(function(result) {
+ assert_response_equals(result, entries.a.response,
+ 'Cache.match should match by Request.');
+ });
+ }, 'Cache.match with Request');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.matchAll(new Request(entries.a.request.url))
+ .then(function(result) {
+ assert_response_array_equals(
+ result, [entries.a.response],
+ 'Cache.matchAll should match by Request.');
+ });
+ }, 'Cache.matchAll with new Request');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.match(new Request(entries.a.request.url))
+ .then(function(result) {
+ assert_response_equals(result, entries.a.response,
+ 'Cache.match should match by Request.');
+ });
+ }, 'Cache.match with new Request');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.matchAll(entries.a.request,
+ {ignoreSearch: true})
+ .then(function(result) {
+ assert_response_array_equivalent(
+ result,
+ [
+ entries.a.response,
+ entries.a_with_query.response
+ ],
+ 'Cache.matchAll with ignoreSearch should ignore the ' +
+ 'search parameters of cached request.');
+ });
+ },
+ 'Cache.matchAll with ignoreSearch option (request with no search ' +
+ 'parameters)');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.match(entries.a.request,
+ {ignoreSearch: true})
+ .then(function(result) {
+ assert_response_in_array(
+ result,
+ [
+ entries.a.response,
+ entries.a_with_query.response
+ ],
+ 'Cache.match with ignoreSearch should ignore the ' +
+ 'search parameters of cached request.');
+ });
+ },
+ 'Cache.match with ignoreSearch option (request with no search ' +
+ 'parameters)');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.matchAll(entries.a_with_query.request,
+ {ignoreSearch: true})
+ .then(function(result) {
+ assert_response_array_equivalent(
+ result,
+ [
+ entries.a.response,
+ entries.a_with_query.response
+ ],
+ 'Cache.matchAll with ignoreSearch should ignore the ' +
+ 'search parameters of request.');
+ });
+ },
+ 'Cache.matchAll with ignoreSearch option (request with search parameter)');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.match(entries.a_with_query.request,
+ {ignoreSearch: true})
+ .then(function(result) {
+ assert_response_in_array(
+ result,
+ [
+ entries.a.response,
+ entries.a_with_query.response
+ ],
+ 'Cache.match with ignoreSearch should ignore the ' +
+ 'search parameters of request.');
+ });
+ },
+ 'Cache.match with ignoreSearch option (request with search parameter)');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.matchAll(entries.cat.request.url + '#mouse')
+ .then(function(result) {
+ assert_response_array_equivalent(
+ result,
+ [
+ entries.cat.response,
+ ],
+ 'Cache.matchAll should ignore URL fragment.');
+ });
+ }, 'Cache.matchAll with URL containing fragment');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.match(entries.cat.request.url + '#mouse')
+ .then(function(result) {
+ assert_response_equals(result, entries.cat.response,
+ 'Cache.match should ignore URL fragment.');
+ });
+ }, 'Cache.match with URL containing fragment');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.matchAll('http')
+ .then(function(result) {
+ assert_response_array_equivalent(
+ result, [],
+ 'Cache.matchAll should treat query as a URL and not ' +
+ 'just a string fragment.');
+ });
+ }, 'Cache.matchAll with string fragment "http" as query');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ return cache.match('http')
+ .then(function(result) {
+ assert_equals(
+ result, undefined,
+ 'Cache.match should treat query as a URL and not ' +
+ 'just a string fragment.');
+ });
+ }, 'Cache.match with string fragment "http" as query');
+
+prepopulated_cache_test(vary_entries, function(cache, entries) {
+ return cache.matchAll('http://example.com/c')
+ .then(function(result) {
+ assert_response_array_equivalent(
+ result,
+ [
+ entries.vary_cookie_absent.response
+ ],
+ 'Cache.matchAll should exclude matches if a vary header is ' +
+ 'missing in the query request, but is present in the cached ' +
+ 'request.');
+ })
+
+ .then(function() {
+ return cache.matchAll(
+ new Request('http://example.com/c',
+ {headers: {'Cookies': 'none-of-the-above'}}));
+ })
+ .then(function(result) {
+ assert_response_array_equivalent(
+ result,
+ [
+ ],
+ 'Cache.matchAll should exclude matches if a vary header is ' +
+ 'missing in the cached request, but is present in the query ' +
+ 'request.');
+ })
+
+ .then(function() {
+ return cache.matchAll(
+ new Request('http://example.com/c',
+ {headers: {'Cookies': 'is-for-cookie'}}));
+ })
+ .then(function(result) {
+ assert_response_array_equivalent(
+ result,
+ [entries.vary_cookie_is_cookie.response],
+ 'Cache.matchAll should match the entire header if a vary header ' +
+ 'is present in both the query and cached requests.');
+ });
+ }, 'Cache.matchAll with responses containing "Vary" header');
+
+prepopulated_cache_test(vary_entries, function(cache, entries) {
+ return cache.match('http://example.com/c')
+ .then(function(result) {
+ assert_response_in_array(
+ result,
+ [
+ entries.vary_cookie_absent.response
+ ],
+ 'Cache.match should honor "Vary" header.');
+ });
+ }, 'Cache.match with responses containing "Vary" header');
+
+prepopulated_cache_test(vary_entries, function(cache, entries) {
+ return cache.matchAll('http://example.com/c',
+ {ignoreVary: true})
+ .then(function(result) {
+ assert_response_array_equivalent(
+ result,
+ [
+ entries.vary_cookie_is_cookie.response,
+ entries.vary_cookie_is_good.response,
+ entries.vary_cookie_absent.response,
+ ],
+ 'Cache.matchAll should honor "ignoreVary" parameter.');
+ });
+ }, 'Cache.matchAll with "ignoreVary" parameter');
+
+cache_test(function(cache) {
+ var request = new Request('http://example.com');
+ var response;
+ var request_url = new URL('../resources/simple.txt', location.href).href;
+ return fetch(request_url)
+ .then(function(fetch_result) {
+ response = fetch_result;
+ assert_equals(
+ response.url, request_url,
+ '[https://fetch.spec.whatwg.org/#dom-response-url] ' +
+ 'Reponse.url should return the URL of the response.');
+ return cache.put(request, response.clone());
+ })
+ .then(function() {
+ return cache.match(request.url);
+ })
+ .then(function(result) {
+ assert_response_equals(
+ result, response,
+ 'Cache.match should return a Response object that has the same ' +
+ 'properties as the stored response.');
+ return cache.match(response.url);
+ })
+ .then(function(result) {
+ assert_equals(
+ result, undefined,
+ 'Cache.match should not match cache entry based on response URL.');
+ });
+ }, 'Cache.match with Request and Response objects with different URLs');
+
+cache_test(function(cache) {
+ var request_url = new URL('../resources/simple.txt', location.href).href;
+ return fetch(request_url)
+ .then(function(fetch_result) {
+ return cache.put(new Request(request_url), fetch_result);
+ })
+ .then(function() {
+ return cache.match(request_url);
+ })
+ .then(function(result) {
+ return result.text();
+ })
+ .then(function(body_text) {
+ assert_equals(body_text, 'a simple text file\n',
+ 'Cache.match should return a Response object with a ' +
+ 'valid body.');
+ })
+ .then(function() {
+ return cache.match(request_url);
+ })
+ .then(function(result) {
+ return result.text();
+ })
+ .then(function(body_text) {
+ assert_equals(body_text, 'a simple text file\n',
+ 'Cache.match should return a Response object with a ' +
+ 'valid body each time it is called.');
+ });
+ }, 'Cache.match invoked multiple times for the same Request/Response');
+
+prepopulated_cache_test(simple_entries, function(cache, entries) {
+ var request = new Request(entries.a.request, { method: 'POST' });
+ return cache.match(request)
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.match should not find a match');
+ });
+ }, 'Cache.match with POST Request');
+
+// Helpers ---
+
+// Run |test_function| with a Cache object as its only parameter. Prior to the
+// call, the Cache is populated by cache entries from |entries|. The latter is
+// expected to be an Object mapping arbitrary keys to objects of the form
+// {request: <Request object>, response: <Response object>}. There's no
+// guarantee on the order in which entries will be added to the cache.
+//
+// |test_function| should return a Promise that can be used with promise_test.
+function prepopulated_cache_test(entries, test_function, description) {
+ cache_test(function(cache) {
+ var p = Promise.resolve();
+ var hash = {};
+ entries.forEach(function(entry) {
+ p = p.then(function() {
+ return cache.put(entry.request.clone(),
+ entry.response.clone())
+ .catch(function(e) {
+ assert_unreached('Test setup failed for entry ' +
+ entry.name + ': ' + e);
+ });
+ });
+ hash[entry.name] = entry;
+ });
+ p = p.then(function() {
+ assert_equals(Object.keys(hash).length, entries.length);
+ });
+
+ return p.then(function() {
+ return test_function(cache, hash);
+ });
+ }, description);
+}
+
+done();
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-put.js b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-put.js
new file mode 100644
index 0000000..1d0a5b9
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-put.js
@@ -0,0 +1,281 @@
+if (self.importScripts) {
+ importScripts('/resources/testharness.js');
+ importScripts('../resources/testharness-helpers.js');
+ importScripts('../resources/test-helpers.js');
+}
+
+var test_url = 'https://example.com/foo';
+var test_body = 'Hello world!';
+
+cache_test(function(cache) {
+ var request = new Request(test_url);
+ var response = new Response(test_body);
+ return cache.put(request, response)
+ .then(function(result) {
+ assert_equals(result, undefined,
+ 'Cache.put should resolve with undefined on success.');
+ });
+ }, 'Cache.put called with simple Request and Response');
+
+cache_test(function(cache) {
+ var test_url = new URL('../resources/simple.txt', location.href).href;
+ var request = new Request(test_url);
+ var response;
+ return fetch(test_url)
+ .then(function(fetch_result) {
+ response = fetch_result.clone();
+ return cache.put(request, fetch_result);
+ })
+ .then(function() {
+ return cache.match(test_url);
+ })
+ .then(function(result) {
+ assert_response_equals(result, response,
+ 'Cache.put should update the cache with ' +
+ 'new request and response.');
+ return result.text();
+ })
+ .then(function(body) {
+ assert_equals(body, 'a simple text file\n',
+ 'Cache.put should store response body.');
+ });
+ }, 'Cache.put called with Request and Response from fetch()');
+
+cache_test(function(cache) {
+ var request = new Request(test_url);
+ var response = new Response(test_body);
+ assert_false(request.bodyUsed,
+ '[https://fetch.spec.whatwg.org/#dom-body-bodyused] ' +
+ 'Request.bodyUsed should be initially false.');
+ return cache.put(request, response)
+ .then(function() {
+ assert_false(request.bodyUsed,
+ 'Cache.put should not mark empty request\'s body used');
+ });
+ }, 'Cache.put with Request without a body');
+
+cache_test(function(cache) {
+ var request = new Request(test_url);
+ var response = new Response();
+ assert_false(response.bodyUsed,
+ '[https://fetch.spec.whatwg.org/#dom-body-bodyused] ' +
+ 'Response.bodyUsed should be initially false.');
+ return cache.put(request, response)
+ .then(function() {
+ assert_false(response.bodyUsed,
+ 'Cache.put should not mark empty response\'s body used');
+ });
+ }, 'Cache.put with Response without a body');
+
+cache_test(function(cache) {
+ var request = new Request(test_url);
+ var response = new Response(test_body);
+ return cache.put(request, response.clone())
+ .then(function() {
+ return cache.match(test_url);
+ })
+ .then(function(result) {
+ assert_response_equals(result, response,
+ 'Cache.put should update the cache with ' +
+ 'new Request and Response.');
+ });
+ }, 'Cache.put with a Response containing an empty URL');
+
+cache_test(function(cache) {
+ var request = new Request(test_url);
+ var response = new Response('', {
+ status: 200,
+ headers: [['Content-Type', 'text/plain']]
+ });
+ return cache.put(request, response)
+ .then(function() {
+ return cache.match(test_url);
+ })
+ .then(function(result) {
+ assert_equals(result.status, 200, 'Cache.put should store status.');
+ assert_equals(result.headers.get('Content-Type'), 'text/plain',
+ 'Cache.put should store headers.');
+ return result.text();
+ })
+ .then(function(body) {
+ assert_equals(body, '',
+ 'Cache.put should store response body.');
+ });
+ }, 'Cache.put with an empty response body');
+
+cache_test(function(cache) {
+ var test_url = new URL('../resources/fetch-status.py?status=500', location.href).href;
+ var request = new Request(test_url);
+ var response;
+ return fetch(test_url)
+ .then(function(fetch_result) {
+ assert_equals(fetch_result.status, 500,
+ 'Test framework error: The status code should be 500.');
+ response = fetch_result.clone();
+ return cache.put(request, fetch_result);
+ })
+ .then(function() {
+ return cache.match(test_url);
+ })
+ .then(function(result) {
+ assert_response_equals(result, response,
+ 'Cache.put should update the cache with ' +
+ 'new request and response.');
+ return result.text();
+ })
+ .then(function(body) {
+ assert_equals(body, '',
+ 'Cache.put should store response body.');
+ });
+ }, 'Cache.put with HTTP 500 response');
+
+cache_test(function(cache) {
+ var alternate_response_body = 'New body';
+ var alternate_response = new Response(alternate_response_body,
+ { statusText: 'New status' });
+ return cache.put(new Request(test_url),
+ new Response('Old body', { statusText: 'Old status' }))
+ .then(function() {
+ return cache.put(new Request(test_url), alternate_response.clone());
+ })
+ .then(function() {
+ return cache.match(test_url);
+ })
+ .then(function(result) {
+ assert_response_equals(result, alternate_response,
+ 'Cache.put should replace existing ' +
+ 'response with new response.');
+ return result.text();
+ })
+ .then(function(body) {
+ assert_equals(body, alternate_response_body,
+ 'Cache put should store new response body.');
+ });
+ }, 'Cache.put called twice with matching Requests and different Responses');
+
+cache_test(function(cache) {
+ var first_url = test_url;
+ var second_url = first_url + '#(O_o)';
+ var alternate_response_body = 'New body';
+ var alternate_response = new Response(alternate_response_body,
+ { statusText: 'New status' });
+ return cache.put(new Request(first_url),
+ new Response('Old body', { statusText: 'Old status' }))
+ .then(function() {
+ return cache.put(new Request(second_url), alternate_response.clone());
+ })
+ .then(function() {
+ return cache.match(test_url);
+ })
+ .then(function(result) {
+ assert_response_equals(result, alternate_response,
+ 'Cache.put should replace existing ' +
+ 'response with new response.');
+ return result.text();
+ })
+ .then(function(body) {
+ assert_equals(body, alternate_response_body,
+ 'Cache put should store new response body.');
+ });
+ }, 'Cache.put called twice with request URLs that differ only by a fragment');
+
+cache_test(function(cache) {
+ var url = 'http://example.com/foo';
+ return cache.put(url, new Response('some body'))
+ .then(function() { return cache.match(url); })
+ .then(function(response) { return response.text(); })
+ .then(function(body) {
+ assert_equals(body, 'some body',
+ 'Cache.put should accept a string as request.');
+ });
+ }, 'Cache.put with a string request');
+
+cache_test(function(cache) {
+ return assert_promise_rejects(
+ cache.put(new Request(test_url), 'Hello world!'),
+ new TypeError(),
+ 'Cache.put should only accept a Response object as the response.');
+ }, 'Cache.put with an invalid response');
+
+cache_test(function(cache) {
+ return assert_promise_rejects(
+ cache.put(new Request('file:///etc/passwd'),
+ new Response(test_body)),
+ new TypeError(),
+ 'Cache.put should reject non-HTTP/HTTPS requests with a TypeError.');
+ }, 'Cache.put with a non-HTTP/HTTPS request');
+
+cache_test(function(cache) {
+ var response = new Response(test_body);
+ return cache.put(new Request('relative-url'), response.clone())
+ .then(function() {
+ return cache.match(new URL('relative-url', location.href).href);
+ })
+ .then(function(result) {
+ assert_response_equals(result, response,
+ 'Cache.put should accept a relative URL ' +
+ 'as the request.');
+ });
+ }, 'Cache.put with a relative URL');
+
+cache_test(function(cache) {
+ var request = new Request('http://example.com/foo', { method: 'HEAD' });
+ return assert_promise_rejects(
+ cache.put(request, new Response(test_body)),
+ new TypeError(),
+ 'Cache.put should throw a TypeError for non-GET requests.');
+ }, 'Cache.put with a non-GET request');
+
+cache_test(function(cache) {
+ return assert_promise_rejects(
+ cache.put(new Request(test_url), null),
+ new TypeError(),
+ 'Cache.put should throw a TypeError for a null response.');
+ }, 'Cache.put with a null response');
+
+cache_test(function(cache) {
+ var request = new Request(test_url, {method: 'POST', body: test_body});
+ return assert_promise_rejects(
+ cache.put(request, new Response(test_body)),
+ new TypeError(),
+ 'Cache.put should throw a TypeError for a POST request.');
+ }, 'Cache.put with a POST request');
+
+cache_test(function(cache) {
+ var response = new Response(test_body);
+ assert_false(response.bodyUsed,
+ '[https://fetch.spec.whatwg.org/#dom-body-bodyused] ' +
+ 'Response.bodyUsed should be initially false.');
+ return response.text().then(function() {
+ assert_true(
+ response.bodyUsed,
+ '[https://fetch.spec.whatwg.org/#concept-body-consume-body] ' +
+ 'The text() method should set "body used" flag.');
+ return assert_promise_rejects(
+ cache.put(new Request(test_url), response),
+ new TypeError,
+ '[https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#cache-put] ' +
+ 'Cache put should reject with TypeError when Response ' +
+ 'body is already used.');
+ });
+ }, 'Cache.put with a used response body');
+
+cache_test(function(cache) {
+ return assert_promise_rejects(
+ cache.put(new Request(test_url),
+ new Response(test_body, { headers: { VARY: '*' }})),
+ new TypeError(),
+ 'Cache.put should reject VARY:* Responses with a TypeError.');
+ }, 'Cache.put with a VARY:* Response');
+
+cache_test(function(cache) {
+ return assert_promise_rejects(
+ cache.put(new Request(test_url),
+ new Response(test_body,
+ { headers: { VARY: 'Accept-Language,*' }})),
+ new TypeError(),
+ 'Cache.put should reject Responses with an embedded VARY:* with a ' +
+ 'TypeError.');
+ }, 'Cache.put with an embedded VARY:* Response');
+
+done();
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-storage-keys.js b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-storage-keys.js
new file mode 100644
index 0000000..4d7bc62
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-storage-keys.js
@@ -0,0 +1,36 @@
+if (self.importScripts) {
+ importScripts('/resources/testharness.js');
+ importScripts('../resources/testharness-helpers.js');
+ importScripts('../resources/test-helpers.js');
+}
+
+var test_cache_list =
+ ['', 'example', 'Another cache name', 'A', 'a', 'ex ample'];
+
+promise_test(function(test) {
+ return self.caches.keys()
+ .then(function(keys) {
+ assert_true(Array.isArray(keys),
+ 'CacheStorage.keys should return an Array.');
+ return Promise.all(keys.map(function(key) {
+ return self.caches.delete(key);
+ }));
+ })
+ .then(function() {
+ return Promise.all(test_cache_list.map(function(key) {
+ return self.caches.open(key);
+ }));
+ })
+
+ .then(function() { return self.caches.keys(); })
+ .then(function(keys) {
+ assert_true(Array.isArray(keys),
+ 'CacheStorage.keys should return an Array.');
+ assert_array_equals(keys,
+ test_cache_list,
+ 'CacheStorage.keys should only return ' +
+ 'existing caches.');
+ });
+ }, 'CacheStorage keys');
+
+done();
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-storage-match.js b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-storage-match.js
new file mode 100644
index 0000000..269df3b
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-storage-match.js
@@ -0,0 +1,126 @@
+if (self.importScripts) {
+ importScripts('/resources/testharness.js');
+ importScripts('../resources/testharness-helpers.js');
+ importScripts('../resources/test-helpers.js');
+}
+
+(function() {
+ var next_index = 1;
+
+ // Returns a transaction (request, response, and url) for a unique URL.
+ function create_unique_transaction(test) {
+ var uniquifier = String(next_index++);
+ var url = 'http://example.com/' + uniquifier;
+
+ return {
+ request: new Request(url),
+ response: new Response('hello'),
+ url: url
+ };
+ }
+
+ self.create_unique_transaction = create_unique_transaction;
+})();
+
+cache_test(function(cache) {
+ var transaction = create_unique_transaction();
+
+ return cache.put(transaction.request.clone(), transaction.response.clone())
+ .then(function() {
+ return self.caches.match(transaction.request);
+ })
+ .then(function(response) {
+ assert_response_equals(response, transaction.response,
+ 'The response should not have changed.');
+ });
+}, 'CacheStorageMatch with no cache name provided');
+
+cache_test(function(cache) {
+ var transaction = create_unique_transaction();
+
+ var test_cache_list = ['a', 'b', 'c'];
+ return cache.put(transaction.request.clone(), transaction.response.clone())
+ .then(function() {
+ return Promise.all(test_cache_list.map(function(key) {
+ return self.caches.open(key);
+ }));
+ })
+ .then(function() {
+ return self.caches.match(transaction.request);
+ })
+ .then(function(response) {
+ assert_response_equals(response, transaction.response,
+ 'The response should not have changed.');
+ });
+}, 'CacheStorageMatch from one of many caches');
+
+promise_test(function(test) {
+ var transaction = create_unique_transaction();
+
+ var test_cache_list = ['x', 'y', 'z'];
+ return Promise.all(test_cache_list.map(function(key) {
+ return self.caches.open(key);
+ }))
+ .then(function() { return caches.open('x'); })
+ .then(function(cache) {
+ return cache.put(transaction.request.clone(),
+ transaction.response.clone());
+ })
+ .then(function() {
+ return self.caches.match(transaction.request, {cacheName: 'x'});
+ })
+ .then(function(response) {
+ assert_response_equals(response, transaction.response,
+ 'The response should not have changed.');
+ })
+ .then(function() {
+ return self.caches.match(transaction.request, {cacheName: 'y'});
+ })
+ .then(function(response) {
+ assert_equals(response, undefined,
+ 'Cache y should not have a response for the request.');
+ });
+}, 'CacheStorageMatch from one of many caches by name');
+
+cache_test(function(cache) {
+ var transaction = create_unique_transaction();
+ return cache.put(transaction.url, transaction.response.clone())
+ .then(function() {
+ return self.caches.match(transaction.request);
+ })
+ .then(function(response) {
+ assert_response_equals(response, transaction.response,
+ 'The response should not have changed.');
+ });
+}, 'CacheStorageMatch a string request');
+
+promise_test(function(test) {
+ var transaction = create_unique_transaction();
+ return self.caches.match(transaction.request)
+ .then(function(response) {
+ assert_equals(response, undefined,
+ 'The response should not be found.');
+ })
+}, 'CacheStorageMatch with no cached entry');
+
+promise_test(function(test) {
+ var transaction = create_unique_transaction();
+ return self.caches.has('foo')
+ .then(function(has_foo) {
+ assert_false(has_foo, "The cache should not exist.");
+ return self.caches.match(transaction.request, {cacheName: 'foo'});
+ })
+ .then(function(response) {
+ assert_unreached('The match with bad cache name should reject.');
+ })
+ .catch(function(err) {
+ assert_equals(err.name, 'NotFoundError',
+ 'The match should reject with NotFoundError.');
+ return self.caches.has('foo');
+ })
+ .then(function(has_foo) {
+ assert_false(has_foo, "The cache should still not exist.");
+ })
+}, 'CacheStorageMatch with no caches available but name provided');
+
+done();
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-storage.js b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-storage.js
new file mode 100644
index 0000000..a8d4e7e
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/script-tests/cache-storage.js
@@ -0,0 +1,198 @@
+if (self.importScripts) {
+ importScripts('/resources/testharness.js');
+ importScripts('../resources/testharness-helpers.js');
+ importScripts('../resources/test-helpers.js');
+}
+
+promise_test(function(t) {
+ var cache_name = 'cache-storage/foo';
+ return self.caches.delete(cache_name)
+ .then(function() {
+ return self.caches.open(cache_name);
+ })
+ .then(function(cache) {
+ assert_true(cache instanceof Cache,
+ 'CacheStorage.open should return a Cache.');
+ });
+ }, 'CacheStorage.open');
+
+promise_test(function(t) {
+ // Note that this test may collide with other tests running in the same
+ // origin that also uses an empty cache name.
+ var cache_name = '';
+ return self.caches.delete(cache_name)
+ .then(function() {
+ return self.caches.open(cache_name);
+ })
+ .then(function(cache) {
+ assert_true(cache instanceof Cache,
+ 'CacheStorage.open should accept an empty name.');
+ });
+ }, 'CacheStorage.open with an empty name');
+
+promise_test(function(t) {
+ return assert_promise_rejects(
+ self.caches.open(),
+ new TypeError(),
+ 'CacheStorage.open should throw TypeError if called with no arguments.');
+ }, 'CacheStorage.open with no arguments');
+
+promise_test(function(t) {
+ var test_cases = [
+ {
+ name: 'cache-storage/lowercase',
+ should_not_match:
+ [
+ 'cache-storage/Lowercase',
+ ' cache-storage/lowercase',
+ 'cache-storage/lowercase '
+ ]
+ },
+ {
+ name: 'cache-storage/has a space',
+ should_not_match:
+ [
+ 'cache-storage/has'
+ ]
+ },
+ {
+ name: 'cache-storage/has\000_in_the_name',
+ should_not_match:
+ [
+ 'cache-storage/has',
+ 'cache-storage/has_in_the_name'
+ ]
+ }
+ ];
+ return Promise.all(test_cases.map(function(testcase) {
+ var cache_name = testcase.name;
+ return self.caches.delete(cache_name)
+ .then(function() {
+ return self.caches.open(cache_name);
+ })
+ .then(function() {
+ return self.caches.has(cache_name);
+ })
+ .then(function(result) {
+ assert_true(result,
+ 'CacheStorage.has should return true for existing ' +
+ 'cache.');
+ })
+ .then(function() {
+ return Promise.all(
+ testcase.should_not_match.map(function(cache_name) {
+ return self.caches.has(cache_name)
+ .then(function(result) {
+ assert_false(result,
+ 'CacheStorage.has should only perform ' +
+ 'exact matches on cache names.');
+ });
+ }));
+ })
+ .then(function() {
+ return self.caches.delete(cache_name);
+ });
+ }));
+ }, 'CacheStorage.has with existing cache');
+
+promise_test(function(t) {
+ return self.caches.has('cheezburger')
+ .then(function(result) {
+ assert_false(result,
+ 'CacheStorage.has should return false for ' +
+ 'nonexistent cache.');
+ });
+ }, 'CacheStorage.has with nonexistent cache');
+
+promise_test(function(t) {
+ var cache_name = 'cache-storage/open';
+ var url = '../resources/simple.txt';
+ var cache;
+ return self.caches.delete(cache_name)
+ .then(function() {
+ return self.caches.open(cache_name);
+ })
+ .then(function(result) {
+ cache = result;
+ })
+ .then(function() {
+ return cache.add('../resources/simple.txt');
+ })
+ .then(function() {
+ return self.caches.open(cache_name);
+ })
+ .then(function(result) {
+ assert_true(result instanceof Cache,
+ 'CacheStorage.open should return a Cache object');
+ assert_not_equals(result, cache,
+ 'CacheStorage.open should return a new Cache ' +
+ 'object each time its called.');
+ return Promise.all([cache.keys(), result.keys()]);
+ })
+ .then(function(results) {
+ var expected_urls = results[0].map(function(r) { return r.url });
+ var actual_urls = results[1].map(function(r) { return r.url });
+ assert_array_equals(actual_urls, expected_urls,
+ 'CacheStorage.open should return a new Cache ' +
+ 'object for the same backing store.');
+ })
+ }, 'CacheStorage.open with existing cache');
+
+promise_test(function(t) {
+ var cache_name = 'cache-storage/delete';
+
+ return self.caches.delete(cache_name)
+ .then(function() {
+ return self.caches.open(cache_name);
+ })
+ .then(function() { return self.caches.delete(cache_name); })
+ .then(function(result) {
+ assert_true(result,
+ 'CacheStorage.delete should return true after ' +
+ 'deleting an existing cache.');
+ })
+
+ .then(function() { return self.caches.has(cache_name); })
+ .then(function(cache_exists) {
+ assert_false(cache_exists,
+ 'CacheStorage.has should return false after ' +
+ 'fulfillment of CacheStorage.delete promise.');
+ });
+ }, 'CacheStorage.delete with existing cache');
+
+promise_test(function(t) {
+ return self.caches.delete('cheezburger')
+ .then(function(result) {
+ assert_false(result,
+ 'CacheStorage.delete should return false for a ' +
+ 'nonexistent cache.');
+ });
+ }, 'CacheStorage.delete with nonexistent cache');
+
+promise_test(function(t) {
+ var bad_name = 'unpaired\uD800';
+ var converted_name = 'unpaired\uFFFD'; // Don't create cache with this name.
+ return self.caches.has(converted_name)
+ .then(function(cache_exists) {
+ assert_false(cache_exists,
+ 'Test setup failure: cache should not exist');
+ })
+ .then(function() { return self.caches.open(bad_name); })
+ .then(function() { return self.caches.keys(); })
+ .then(function(keys) {
+ assert_true(keys.indexOf(bad_name) !== -1,
+ 'keys should include cache with bad name');
+ })
+ .then(function() { return self.caches.has(bad_name); })
+ .then(function(cache_exists) {
+ assert_true(cache_exists,
+ 'CacheStorage names should be not be converted.');
+ })
+ .then(function() { return self.caches.has(converted_name); })
+ .then(function(cache_exists) {
+ assert_false(cache_exists,
+ 'CacheStorage names should be not be converted.');
+ });
+ }, 'CacheStorage names are DOMStrings not USVStrings');
+
+done();
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-add.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-add.https.html
new file mode 100644
index 0000000..57e74b7
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-add.https.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>Cache.add and Cache.addAll</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-add">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../service-workers/resources/test-helpers.js"></script>
+<script>
+service_worker_test('../script-tests/cache-add.js');
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-delete.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-delete.https.html
new file mode 100644
index 0000000..7a5a43f
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-delete.https.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>Cache.delete</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-delete">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../service-workers/resources/test-helpers.js"></script>
+<script>
+service_worker_test('../script-tests/cache-delete.js');
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-match.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-match.https.html
new file mode 100644
index 0000000..859b1cd
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-match.https.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>Cache.match and Cache.matchAll</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-match">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../service-workers/resources/test-helpers.js"></script>
+<script>
+service_worker_test('../script-tests/cache-match.js');
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-put.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-put.https.html
new file mode 100644
index 0000000..d67f939
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-put.https.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>Cache.put</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-put">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../service-workers/resources/test-helpers.js"></script>
+<script>
+service_worker_test('../script-tests/cache-put.js');
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html
new file mode 100644
index 0000000..ec7e14b
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>CacheStorage.keys</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../service-workers/resources/test-helpers.js"></script>
+<script>
+service_worker_test('../script-tests/cache-storage-keys.js');
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-storage-match.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-storage-match.https.html
new file mode 100644
index 0000000..937f143
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-storage-match.https.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>CacheStorage.match</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage-match">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../service-workers/resources/test-helpers.js"></script>
+<script>
+service_worker_test('../script-tests/cache-storage-match.js');
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-storage.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-storage.https.html
new file mode 100644
index 0000000..62c6b63
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/serviceworker/cache-storage.https.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>CacheStorage</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../service-workers/resources/test-helpers.js"></script>
+<script>
+service_worker_test('../script-tests/cache-storage.js');
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-add.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-add.https.html
new file mode 100644
index 0000000..42e4b50
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-add.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Cache Storage: Cache.add and Cache.addAll</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-add">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/testharness-helpers.js"></script>
+<script src="../resources/test-helpers.js"></script>
+<script src="../script-tests/cache-add.js"></script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-delete.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-delete.https.html
new file mode 100644
index 0000000..754f785
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-delete.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Cache Storage: Cache.delete</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-delete">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/testharness-helpers.js"></script>
+<script src="../resources/test-helpers.js"></script>
+<script src="../script-tests/cache-delete.js"></script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-match.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-match.https.html
new file mode 100644
index 0000000..093df8d
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-match.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Cache Storage: Cache.match and Cache.matchAll</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-match">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/testharness-helpers.js"></script>
+<script src="../resources/test-helpers.js"></script>
+<script src="../script-tests/cache-match.js"></script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-put.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-put.https.html
new file mode 100644
index 0000000..b32cfa2
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-put.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Cache Storage: Cache.put</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-put">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/testharness-helpers.js"></script>
+<script src="../resources/test-helpers.js"></script>
+<script src="../script-tests/cache-put.js"></script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-storage-keys.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-storage-keys.https.html
new file mode 100644
index 0000000..acde773
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-storage-keys.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Cache Storage: CacheStorage.keys</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/testharness-helpers.js"></script>
+<script src="../resources/test-helpers.js"></script>
+<script src="../script-tests/cache-storage-keys.js"></script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-storage-match.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-storage-match.https.html
new file mode 100644
index 0000000..3c69d0f
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-storage-match.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Cache Storage: CacheStorage.match</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage-match">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/testharness-helpers.js"></script>
+<script src="../resources/test-helpers.js"></script>
+<script src="../script-tests/cache-storage-match.js"></script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-storage.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-storage.https.html
new file mode 100644
index 0000000..7d015e3
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/window/cache-storage.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Cache Storage: CacheStorage</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/testharness-helpers.js"></script>
+<script src="../resources/test-helpers.js"></script>
+<script src="../script-tests/cache-storage.js"></script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/window/sandboxed-iframes.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/window/sandboxed-iframes.https.html
new file mode 100644
index 0000000..648bd59
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/window/sandboxed-iframes.https.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<title>Cache Storage: Verify access in sandboxed iframes</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/testharness-helpers.js"></script>
+<script>
+
+function load_iframe(src, sandbox) {
+ return new Promise(function(resolve, reject) {
+ var iframe = document.createElement('iframe');
+ iframe.onload = function() { resolve(iframe); };
+
+ iframe.sandbox = sandbox;
+ iframe.src = src;
+
+ document.documentElement.appendChild(iframe);
+ });
+}
+
+function wait_for_message(id) {
+ return new Promise(function(resolve) {
+ self.addEventListener('message', function listener(e) {
+ if (e.data.id === id) {
+ resolve(e.data);
+ self.removeEventListener('message', listener);
+ }
+ });
+ });
+}
+
+var counter = 0;
+
+promise_test(function(t) {
+ return load_iframe('../resources/iframe.html',
+ 'allow-scripts allow-same-origin')
+ .then(function(iframe) {
+ var id = ++counter;
+ iframe.contentWindow.postMessage({id: id}, '*');
+ return wait_for_message(id);
+ })
+ .then(function(message) {
+ assert_equals(
+ message.result, 'allowed',
+ 'Access should be allowed if sandbox has allow-same-origin');
+ });
+}, 'Sandboxed iframe with allow-same-origin is allowed access');
+
+promise_test(function(t) {
+ return load_iframe('../resources/iframe.html',
+ 'allow-scripts')
+ .then(function(iframe) {
+ var id = ++counter;
+ iframe.contentWindow.postMessage({id: id}, '*');
+ return wait_for_message(id);
+ })
+ .then(function(message) {
+ assert_equals(
+ message.result, 'denied',
+ 'Access should be denied if sandbox lacks allow-same-origin');
+ assert_equals(message.name, 'SecurityError',
+ 'Failure should be a SecurityError');
+ });
+}, 'Sandboxed iframe without allow-same-origin is denied access');
+
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-add.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-add.https.html
new file mode 100644
index 0000000..8e6deeb
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-add.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Cache.add and Cache.addAll</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-add">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+fetch_tests_from_worker(new Worker('../script-tests/cache-add.js'));
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-delete.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-delete.https.html
new file mode 100644
index 0000000..2dd06f3
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-delete.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Cache.delete</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-delete">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+fetch_tests_from_worker(new Worker('../script-tests/cache-delete.js'));
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-match.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-match.https.html
new file mode 100644
index 0000000..b0926fc
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-match.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Cache.match and Cache.matchAll</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-match">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+fetch_tests_from_worker(new Worker('../script-tests/cache-match.js'));
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-put.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-put.https.html
new file mode 100644
index 0000000..8876930
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-put.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Cache.put</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-put">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+fetch_tests_from_worker(new Worker('../script-tests/cache-put.js'));
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-storage-keys.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-storage-keys.https.html
new file mode 100644
index 0000000..5c75ef8
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-storage-keys.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>CacheStorage.keys</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+fetch_tests_from_worker(new Worker('../script-tests/cache-storage-keys.js'));
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-storage-match.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-storage-match.https.html
new file mode 100644
index 0000000..4d48683
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-storage-match.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>CacheStorage.match</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage-match">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+fetch_tests_from_worker(new Worker('../script-tests/cache-storage-match.js'));
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-storage.https.html b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-storage.https.html
new file mode 100644
index 0000000..e10f5c5
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/cache-storage/worker/cache-storage.https.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>CacheStorage</title>
+<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+fetch_tests_from_worker(new Worker('../script-tests/cache-storage.js'));
+</script>
diff --git a/src/third_party/web_platform_tests/service-workers/service-workers/resources/test-helpers.js b/src/third_party/web_platform_tests/service-workers/service-workers/resources/test-helpers.js
new file mode 100644
index 0000000..147ea61
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/service-workers/resources/test-helpers.js
@@ -0,0 +1,222 @@
+// Adapter for testharness.js-style tests with Service Workers
+
+function service_worker_unregister_and_register(test, url, scope) {
+ if (!scope || scope.length == 0)
+ return Promise.reject(new Error('tests must define a scope'));
+
+ var options = { scope: scope };
+ return service_worker_unregister(test, scope)
+ .then(function() {
+ return navigator.serviceWorker.register(url, options);
+ })
+ .catch(unreached_rejection(test,
+ 'unregister and register should not fail'));
+}
+
+function service_worker_unregister(test, documentUrl) {
+ return navigator.serviceWorker.getRegistration(documentUrl)
+ .then(function(registration) {
+ if (registration)
+ return registration.unregister();
+ })
+ .catch(unreached_rejection(test, 'unregister should not fail'));
+}
+
+function service_worker_unregister_and_done(test, scope) {
+ return service_worker_unregister(test, scope)
+ .then(test.done.bind(test));
+}
+
+function unreached_fulfillment(test, prefix) {
+ return test.step_func(function(result) {
+ var error_prefix = prefix || 'unexpected fulfillment';
+ assert_unreached(error_prefix + ': ' + result);
+ });
+}
+
+// Rejection-specific helper that provides more details
+function unreached_rejection(test, prefix) {
+ return test.step_func(function(error) {
+ var reason = error.message || error.name || error;
+ var error_prefix = prefix || 'unexpected rejection';
+ assert_unreached(error_prefix + ': ' + reason);
+ });
+}
+
+// Adds an iframe to the document and returns a promise that resolves to the
+// iframe when it finishes loading. The caller is responsible for removing the
+// iframe later if needed.
+function with_iframe(url) {
+ return new Promise(function(resolve) {
+ var frame = document.createElement('iframe');
+ frame.src = url;
+ frame.onload = function() { resolve(frame); };
+ document.body.appendChild(frame);
+ });
+}
+
+function normalizeURL(url) {
+ return new URL(url, self.location).toString().replace(/#.*$/, '');
+}
+
+function wait_for_update(test, registration) {
+ if (!registration || registration.unregister == undefined) {
+ return Promise.reject(new Error(
+ 'wait_for_update must be passed a ServiceWorkerRegistration'));
+ }
+
+ return new Promise(test.step_func(function(resolve) {
+ registration.addEventListener('updatefound', test.step_func(function() {
+ resolve(registration.installing);
+ }));
+ }));
+}
+
+function wait_for_state(test, worker, state) {
+ if (!worker || worker.state == undefined) {
+ return Promise.reject(new Error(
+ 'wait_for_state must be passed a ServiceWorker'));
+ }
+ if (worker.state === state)
+ return Promise.resolve(state);
+
+ if (state === 'installing') {
+ switch (worker.state) {
+ case 'installed':
+ case 'activating':
+ case 'activated':
+ case 'redundant':
+ return Promise.reject(new Error(
+ 'worker is ' + worker.state + ' but waiting for ' + state));
+ }
+ }
+
+ if (state === 'installed') {
+ switch (worker.state) {
+ case 'activating':
+ case 'activated':
+ case 'redundant':
+ return Promise.reject(new Error(
+ 'worker is ' + worker.state + ' but waiting for ' + state));
+ }
+ }
+
+ if (state === 'activating') {
+ switch (worker.state) {
+ case 'activated':
+ case 'redundant':
+ return Promise.reject(new Error(
+ 'worker is ' + worker.state + ' but waiting for ' + state));
+ }
+ }
+
+ if (state === 'activated') {
+ switch (worker.state) {
+ case 'redundant':
+ return Promise.reject(new Error(
+ 'worker is ' + worker.state + ' but waiting for ' + state));
+ }
+ }
+
+ return new Promise(test.step_func(function(resolve) {
+ worker.addEventListener('statechange', test.step_func(function() {
+ if (worker.state === state)
+ resolve(state);
+ }));
+ }));
+}
+
+// Declare a test that runs entirely in the ServiceWorkerGlobalScope. The |url|
+// is the service worker script URL. This function:
+// - Instantiates a new test with the description specified in |description|.
+// The test will succeed if the specified service worker can be successfully
+// registered and installed.
+// - Creates a new ServiceWorker registration with a scope unique to the current
+// document URL. Note that this doesn't allow more than one
+// service_worker_test() to be run from the same document.
+// - Waits for the new worker to begin installing.
+// - Imports tests results from tests running inside the ServiceWorker.
+function service_worker_test(url, description) {
+ // If the document URL is https://example.com/document and the script URL is
+ // https://example.com/script/worker.js, then the scope would be
+ // https://example.com/script/scope/document.
+ var scope = new URL('scope' + window.location.pathname,
+ new URL(url, window.location)).toString();
+ promise_test(function(test) {
+ return service_worker_unregister_and_register(test, url, scope)
+ .then(function(registration) {
+ add_completion_callback(function() {
+ registration.unregister();
+ });
+ return wait_for_update(test, registration)
+ .then(function(worker) {
+ return fetch_tests_from_worker(worker);
+ });
+ });
+ }, description);
+}
+
+function get_host_info() {
+ var ORIGINAL_HOST = '127.0.0.1';
+ var REMOTE_HOST = 'localhost';
+ var UNAUTHENTICATED_HOST = 'example.test';
+ var HTTP_PORT = 8000;
+ var HTTPS_PORT = 8443;
+ try {
+ // In W3C test, we can get the hostname and port number in config.json
+ // using wptserve's built-in pipe.
+ // http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes
+ HTTP_PORT = eval('{{ports[http][0]}}');
+ HTTPS_PORT = eval('{{ports[https][0]}}');
+ ORIGINAL_HOST = eval('\'{{host}}\'');
+ REMOTE_HOST = 'www1.' + ORIGINAL_HOST;
+ } catch (e) {
+ }
+ return {
+ HTTP_ORIGIN: 'http://' + ORIGINAL_HOST + ':' + HTTP_PORT,
+ HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + ':' + HTTPS_PORT,
+ HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + ':' + HTTP_PORT,
+ HTTPS_REMOTE_ORIGIN: 'https://' + REMOTE_HOST + ':' + HTTPS_PORT,
+ UNAUTHENTICATED_ORIGIN: 'http://' + UNAUTHENTICATED_HOST + ':' + HTTP_PORT
+ };
+}
+
+function base_path() {
+ return location.pathname.replace(/\/[^\/]*$/, '/');
+}
+
+function test_login(test, origin, username, password, cookie) {
+ return new Promise(function(resolve, reject) {
+ with_iframe(
+ origin +
+ '/serviceworker/resources/fetch-access-control-login.html')
+ .then(test.step_func(function(frame) {
+ var channel = new MessageChannel();
+ channel.port1.onmessage = test.step_func(function() {
+ frame.remove();
+ resolve();
+ });
+ frame.contentWindow.postMessage(
+ {username: username, password: password, cookie: cookie},
+ origin, [channel.port2]);
+ }));
+ });
+}
+
+function login(test) {
+ return test_login(test, 'http://127.0.0.1:8000',
+ 'username1', 'password1', 'cookie1')
+ .then(function() {
+ return test_login(test, 'http://localhost:8000',
+ 'username2', 'password2', 'cookie2');
+ });
+}
+
+function login_https(test) {
+ return test_login(test, 'https://127.0.0.1:8443',
+ 'username1s', 'password1s', 'cookie1')
+ .then(function() {
+ return test_login(test, 'https://localhost:8443',
+ 'username2s', 'password2s', 'cookie2');
+ });
+}
diff --git a/src/third_party/web_platform_tests/service-workers/specgen.json b/src/third_party/web_platform_tests/service-workers/specgen.json
new file mode 100644
index 0000000..5d76da8
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/specgen.json
@@ -0,0 +1,658 @@
+{
+ "sections": [
+ {
+ "href": "#introduction",
+ "id": "introduction",
+ "hash": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "secno": "1",
+ "testable": false
+ },
+ {
+ "href": "#about",
+ "id": "about",
+ "hash": "8d3cf149aa73cff52328509ebbaffd933e8fb6af",
+ "secno": "1.1",
+ "testable": false
+ },
+ {
+ "href": "#dependencies",
+ "id": "dependencies",
+ "hash": "1355f2d7ec9bf4e617ee632c0db44f834c96435b",
+ "secno": "1.2",
+ "testable": false
+ },
+ {
+ "href": "#motivations",
+ "id": "motivations",
+ "hash": "92d899bc1e63a170d2324638d16f580b97b4f4d6",
+ "secno": "1.3",
+ "testable": false
+ },
+ {
+ "href": "#concepts",
+ "id": "concepts",
+ "hash": "589023372dc033b0a77be1cd01f54f5f8c3ebfa8",
+ "secno": "2",
+ "testable": false
+ },
+ {
+ "href": "#document-context",
+ "id": "document-context",
+ "hash": "34feeb18dea978349a2f76e6b17c127123b3db74",
+ "secno": "3",
+ "testable": false
+ },
+ {
+ "href": "#service-worker-obj",
+ "id": "service-worker-obj",
+ "hash": "6cbd0107199072ab86b36e72d08d5465b42e6da8",
+ "secno": "3.1",
+ "testPageHash": "8dbbc9aa4300f0203524f3e405dbf7ca462e7164",
+ "testPagePath": "stub-3.1-service-worker-obj.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-scope",
+ "id": "service-worker-scope",
+ "hash": "136f25ef227515a7be9b32c44967f68b34ad8924",
+ "secno": "3.1.1",
+ "testPageHash": "965a00b32d56192330aa9f6337072bb3633ad382",
+ "testPagePath": "stub-3.1.1-service-worker-scope.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-url",
+ "id": "service-worker-url",
+ "hash": "df66a1b4b3bfa3e7ab96fd491a6829fab1d18a88",
+ "secno": "3.1.2",
+ "testPageHash": "92f6aed1437bb39c5941b495ac6c5f342c025b38",
+ "testPagePath": "stub-3.1.2-service-worker-url.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-state",
+ "id": "service-worker-state",
+ "hash": "8f80f2b4cbb1c228867c9dd90c05cbecfc92dd77",
+ "secno": "3.1.3",
+ "testPageHash": "4aad1dc47572879fdc2c79a814ad21e1ef9a64ec",
+ "testPagePath": "stub-3.1.3-service-worker-state.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-on-state-change",
+ "id": "service-worker-on-state-change",
+ "hash": "0f8fd9d1431deacea72fe739f42992ab5a396bf2",
+ "secno": "3.1.4",
+ "testPageHash": "6bb309bccc1e7c74ade7fc4c6e400bafb60daceb",
+ "testPagePath": "stub-3.1.4-service-worker-on-state-change.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker",
+ "id": "navigator-service-worker",
+ "hash": "22f1ebbafca6976d0f4814b0fbb8f173bf919f06",
+ "secno": "3.2",
+ "testPageHash": "6d597735816a09ec774150029ed5136198f52ab7",
+ "testPagePath": "stub-3.2-navigator-service-worker.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-installing",
+ "id": "navigator-service-worker-installing",
+ "hash": "9675c3cdf5ba4b4155284e06a19e4de631645509",
+ "secno": "3.2.1",
+ "testPageHash": "2c8e56e74c130104e395de46bad20fb5d3021d95",
+ "testPagePath": "stub-3.2.1-navigator-service-worker-installing.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-waiting",
+ "id": "navigator-service-worker-waiting",
+ "hash": "88b4db92cc49109e6a15ddebdd219690d9648e76",
+ "secno": "3.2.2",
+ "testPageHash": "1cf6ed58bf5ecf963fed8c3d9211b853dab564e2",
+ "testPagePath": "stub-3.2.2-navigator-service-worker-waiting.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-active",
+ "id": "navigator-service-worker-active",
+ "hash": "0da48e885c77da60d1837197780049904789e3cb",
+ "secno": "3.2.3",
+ "testPageHash": "f5dca8c6eb5f29a0f9a5f06e25861e7f3106cc67",
+ "testPagePath": "stub-3.2.3-navigator-service-worker-active.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-controller",
+ "id": "navigator-service-worker-controller",
+ "hash": "293433ccb7bb2a22d8d5a81e788892e071b25e65",
+ "secno": "3.2.4",
+ "testPageHash": "6452f431d0765d7aa3135d18fee43e6664dcbb12",
+ "testPagePath": "stub-3.2.4-navigator-service-worker-controller.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-ready",
+ "id": "navigator-service-worker-ready",
+ "hash": "6240fde8d7168beeb95f4f36aa9e143319b2061b",
+ "secno": "3.2.5",
+ "testPageHash": "ae4fd694c88bab72f338d97bf96b7d23e2e83e87",
+ "testPagePath": "stub-3.2.5-navigator-service-worker-ready.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-getAll",
+ "id": "navigator-service-worker-getAll",
+ "hash": "292ee3af2cc8fadc24302446809d04bf2e9811a5",
+ "secno": "3.2.6",
+ "testPageHash": "4096ae712cc3e753456fbe05bb4d0cfc4399d2c9",
+ "testPagePath": "stub-3.2.6-navigator-service-worker-getAll.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-register",
+ "id": "navigator-service-worker-register",
+ "hash": "c999dc5f67126c9f0f02b25fd943a34b48cff618",
+ "secno": "3.2.7",
+ "testPageHash": "bde900b97dbb08b053ff8115775ea3b79a124b6e",
+ "testPagePath": "stub-3.2.7-navigator-service-worker-register.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-unregister",
+ "id": "navigator-service-worker-unregister",
+ "hash": "fd196f926f181563855e4683cc995405c1e611d0",
+ "secno": "3.2.8",
+ "testPageHash": "dbd99a1dcbcb629431617790a305e840495049eb",
+ "testPagePath": "stub-3.2.8-navigator-service-worker-unregister.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-onupdatefound",
+ "id": "navigator-service-worker-onupdatefound",
+ "hash": "2bb5aabaca24a68f9e6b4c4443968178eb1ccfe8",
+ "secno": "3.2.9",
+ "testPageHash": "eef0c1c39577abefb3654a6e9917ff2da657871b",
+ "testPagePath": "stub-3.2.9-navigator-service-worker-onupdatefound.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-oncontrollerchange",
+ "id": "navigator-service-worker-oncontrollerchange",
+ "hash": "c89a4ffba10d9285e07c38c28718719d87053994",
+ "secno": "3.2.10",
+ "testPageHash": "35e0ce2b8f4527ebbd75d4dfa3436fd7f8c79792",
+ "testPagePath": "stub-3.2.10-navigator-service-worker-oncontrollerchange.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-onreloadpage",
+ "id": "navigator-service-worker-onreloadpage",
+ "hash": "424441910abf2e1bdc3db658fe46827f7abe60a4",
+ "secno": "3.2.11",
+ "testPageHash": "ae614de17e5f339b65f77cafa6e0f5625491abfb",
+ "testPagePath": "stub-3.2.11-navigator-service-worker-onreloadpage.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-onerror",
+ "id": "navigator-service-worker-onerror",
+ "hash": "710f7fcd2f5340147b9e030bc5932b8242cef828",
+ "secno": "3.2.12",
+ "testPageHash": "cd62779e27151d55f14ac6ab7aa41dcf723e0ac7",
+ "testPagePath": "stub-3.2.12-navigator-service-worker-onerror.html",
+ "testable": true
+ },
+ {
+ "href": "#execution-context",
+ "id": "execution-context",
+ "hash": "ddf24f0adf58237e264c3c43cb7ab07af3013c9d",
+ "secno": "4",
+ "testable": false
+ },
+ {
+ "href": "#service-worker-global-scope",
+ "id": "service-worker-global-scope",
+ "hash": "e6b8bb7f99c125f4226fc5b6c51cf03a7437f2ef",
+ "secno": "4.1",
+ "testPageHash": "2f596b6b07bcfb71c01d75f725eb52c84e9c69dd",
+ "testPagePath": "stub-4.1-service-worker-global-scope.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-caches",
+ "id": "service-worker-global-scope-caches",
+ "hash": "43d3c9f441b3a7abd0d3a7f55d93faaceeb7d97d",
+ "secno": "4.1.1",
+ "testPageHash": "f19b91c887f6312688b66b1988147a599cd9470f",
+ "testPagePath": "stub-4.1.1-service-worker-global-scope-caches.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-clients",
+ "id": "service-worker-global-scope-clients",
+ "hash": "cb83230107645229da9776ed0fc9f7bc6fcce747",
+ "secno": "4.1.2",
+ "testPageHash": "45b3aae572f7161748fa98e97b4f2b738c3dcfef",
+ "testPagePath": "stub-4.1.2-service-worker-global-scope-clients.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-scope",
+ "id": "service-worker-global-scope-scope",
+ "hash": "08c808048b647aa9d4cc0b0a0f70b06ca89af4a3",
+ "secno": "4.1.3",
+ "testPageHash": "bfe7eaf8deb8de7d2ccfbba97640478b1c81d6c7",
+ "testPagePath": "stub-4.1.3-service-worker-global-scope-scope.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-fetch",
+ "id": "service-worker-global-scope-fetch",
+ "hash": "b66133d8a2c67f9b10c274d5b05383ff76d2cd42",
+ "secno": "4.1.4",
+ "testPageHash": "2b1ffa915afddeb099dfff23f4ecf555b0710ed4",
+ "testPagePath": "stub-4.1.4-service-worker-global-scope-fetch.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-update",
+ "id": "service-worker-global-scope-update",
+ "hash": "3ddf48cecb4d4a67a329248787dd220ce17f4eff",
+ "secno": "4.1.5",
+ "testPageHash": "15879bf45f460c0ab0c02793655096c1bca418a7",
+ "testPagePath": "stub-4.1.5-service-worker-global-scope-update.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-unregister",
+ "id": "service-worker-global-scope-unregister",
+ "hash": "fff9ef2daa5689b38a17eeb9a6bd7071098ca778",
+ "secno": "4.1.6",
+ "testPageHash": "c4bf327228628b794db9c6f2eb17519e37cea6b9",
+ "testPagePath": "stub-4.1.6-service-worker-global-scope-unregister.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-onmessage",
+ "id": "service-worker-global-scope-onmessage",
+ "hash": "bc8f6aed2d515dc7f6b0757afa02f37899082668",
+ "secno": "4.1.7",
+ "testPageHash": "9e6f2732d21871ec06e9541ea881baf962f7cdf4",
+ "testPagePath": "stub-4.1.7-service-worker-global-scope-onmessage.html",
+ "testable": true
+ },
+ {
+ "href": "#client",
+ "id": "client",
+ "hash": "47a1c10cd9e4db9a5c86d9bcf80477f771ea954c",
+ "secno": "4.2",
+ "testPageHash": "21d74c1af0b3176b029c9b62b37fe73436e0f197",
+ "testPagePath": "stub-4.2-client.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-clients",
+ "id": "service-worker-clients",
+ "hash": "c2c6f4873f07b53705a46b2bd44ba10f84dd2b56",
+ "secno": "4.3",
+ "testPageHash": "9c0366e6cfd28caaeaf940bad2b3c7ace93037f6",
+ "testPagePath": "stub-4.3-service-worker-clients.html",
+ "testable": true
+ },
+ {
+ "href": "#get-serviced-method",
+ "id": "get-serviced-method",
+ "hash": "299abaa21cf096e423edfa19755987986f742a1f",
+ "secno": "4.3.1",
+ "testPageHash": "efeb1c2dc8144c30e6628cb56b3e532531ee1e88",
+ "testPagePath": "stub-4.3.1-get-serviced-method.html",
+ "testable": true
+ },
+ {
+ "href": "#reloadall-method",
+ "id": "reloadall-method",
+ "hash": "bb4d775d261e69cbeaf65c123e949c24cf542ae7",
+ "secno": "4.3.2",
+ "testPageHash": "d1a4dde873b77201b4de745d2083bf63549b0b8b",
+ "testPagePath": "stub-4.3.2-reloadall-method.html",
+ "testable": true
+ },
+ {
+ "href": "#request-objects",
+ "id": "request-objects",
+ "hash": "65ae6c08f720a2eedb7b140f5635a5ac46ddadfc",
+ "secno": "4.4",
+ "testPageHash": "ec493c70e8a0d8d3eeb0ecaef59610aed97d298e",
+ "testPagePath": "stub-4.4-request-objects.html",
+ "testable": true
+ },
+ {
+ "href": "#response-objects",
+ "id": "response-objects",
+ "hash": "2efbff63c70ab92f93e4acd021409b9df4776882",
+ "secno": "4.5",
+ "testPageHash": "8340b69d62f111f56095c5fe9047d9215fa7aefc",
+ "testPagePath": "stub-4.5-response-objects.html",
+ "testable": true
+ },
+ {
+ "href": "#abstract-response",
+ "id": "abstract-response",
+ "hash": "bddc306a9892c0bca43e8b361c1ee22b87759e23",
+ "secno": "4.5.1",
+ "testable": false
+ },
+ {
+ "href": "#response",
+ "id": "response",
+ "hash": "6471d25755bdab0d4f72413f9367b7bb36c53a6f",
+ "secno": "4.5.2",
+ "testPageHash": "346d63cc7eb8ee412f5f704ba241205c8d437540",
+ "testPagePath": "stub-4.5.2-response.html",
+ "testable": true
+ },
+ {
+ "href": "#header",
+ "id": "header",
+ "hash": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "secno": "4.5.3",
+ "testable": false
+ },
+ {
+ "href": "#opaque-response",
+ "id": "opaque-response",
+ "hash": "df5431f4fbd26d81f2d4f567309c6a7a26dbfd4a",
+ "secno": "4.5.4",
+ "testPageHash": "85373f290cf594f0f09eb0a76bc6ef6299be595f",
+ "testPagePath": "stub-4.5.4-opaque-response.html",
+ "testable": true
+ },
+ {
+ "href": "#cors-response",
+ "id": "cors-response",
+ "hash": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "secno": "4.5.5",
+ "testable": false
+ },
+ {
+ "href": "#cache-objects",
+ "id": "cache-objects",
+ "hash": "001d0dfb8fbcbcb6443d1be2b722c9a84d6fd95b",
+ "secno": "4.6",
+ "testPageHash": "c1ef341d15a8c76d015eef57842ed10e62c02927",
+ "testPagePath": "stub-4.6-cache-objects.html",
+ "testable": true
+ },
+ {
+ "href": "#cache-lifetimes",
+ "id": "cache-lifetimes",
+ "hash": "7c73698ca9b686a0314ddf368bf8ad4ca6af392f",
+ "secno": "4.6.1",
+ "testPageHash": "f3524320a98f2fbdc5d711de82770957a7f5ec4b",
+ "testPagePath": "stub-4.6.1-cache-lifetimes.html",
+ "testable": true
+ },
+ {
+ "href": "#cache",
+ "id": "cache",
+ "hash": "bf1fe844577ab57a60eb550be24335a3321ca2ee",
+ "secno": "4.6.2",
+ "testPageHash": "c55b7b05c8e2f4b65722e16cdbcd78ffdfe1e4bf",
+ "testPagePath": "stub-4.6.2-cache.html",
+ "testable": true
+ },
+ {
+ "href": "#cache-storage",
+ "id": "cache-storage",
+ "hash": "9cdaac070f56e55d66a89cd4b6e669a04aa73b82",
+ "secno": "4.6.3",
+ "testPageHash": "ee6902f170d94cc1e3a4a00f4c90e7e19c4dff95",
+ "testPagePath": "stub-4.6.3-cache-storage.html",
+ "testable": true
+ },
+ {
+ "href": "#events",
+ "id": "events",
+ "hash": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "secno": "4.7",
+ "testable": false
+ },
+ {
+ "href": "#install-phase-event",
+ "id": "install-phase-event",
+ "hash": "8495382b418adbbed436b2002ab0155a3a295ef2",
+ "secno": "4.7.1",
+ "testPageHash": "e48e98d51936bd57d21903615203f2b78d3f4b12",
+ "testPagePath": "stub-4.7.1-install-phase-event.html",
+ "testable": true
+ },
+ {
+ "href": "#wait-until-method",
+ "id": "wait-until-method",
+ "hash": "295fb5d4932396fd13365ed2fe57aa672f1f2a56",
+ "secno": "4.7.1.1",
+ "testPageHash": "c3769e51852b8438a97c39c50fa62351a73c4ee6",
+ "testPagePath": "stub-4.7.1.1-wait-until-method.html",
+ "testable": true
+ },
+ {
+ "href": "#install-event",
+ "id": "install-event",
+ "hash": "3a0f6da1771c22ab21ddc00729433a4d95ac6782",
+ "secno": "4.7.2",
+ "testPageHash": "9a103cc461eaca3da75db583ce08f13ecd2b1a98",
+ "testPagePath": "stub-4.7.2-install-event.html",
+ "testable": true
+ },
+ {
+ "href": "#install-event-section",
+ "id": "install-event-section",
+ "hash": "4631577df2efc1a4350000461629bc1ca93dbd14",
+ "secno": "4.7.2.1",
+ "testPageHash": "32f54e74bef784d2f0ac772b44abeee06573062d",
+ "testPagePath": "stub-4.7.2.1-install-event-section.html",
+ "testable": true
+ },
+ {
+ "href": "#replace-method",
+ "id": "replace-method",
+ "hash": "b9093b05204d09748311023b4c737ede02ff8115",
+ "secno": "4.7.2.2",
+ "testPageHash": "372bed923f8c35c4923634ae27fa121919ac0fec",
+ "testPagePath": "stub-4.7.2.2-replace-method.html",
+ "testable": true
+ },
+ {
+ "href": "#activate-event",
+ "id": "activate-event",
+ "hash": "ac3d03aa0ed961fb1122850aeab92c302c55ecd0",
+ "secno": "4.7.3",
+ "testPageHash": "6241762ab1d6f430fa9b7cc8f02a00e6591c6bc6",
+ "testPagePath": "stub-4.7.3-activate-event.html",
+ "testable": true
+ },
+ {
+ "href": "#fetch-event",
+ "id": "fetch-event",
+ "hash": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "secno": "4.7.4",
+ "testable": false
+ },
+ {
+ "href": "#fetch-event-section",
+ "id": "fetch-event-section",
+ "hash": "ae24fda9664a3bd7b7fe2a8712ac469c3ee7128e",
+ "secno": "4.7.4.1",
+ "testPageHash": "393fc7b65e9f5afd18da666b6b206ccd639397cd",
+ "testPagePath": "stub-4.7.4.1-fetch-event-section.html",
+ "testable": true
+ },
+ {
+ "href": "#respond-with-method",
+ "id": "respond-with-method",
+ "hash": "7e4f010e2ec1ea0500b435cf599ba58942164457",
+ "secno": "4.7.4.2",
+ "testPageHash": "31e0acd058b9a5b722ae9f405b50bc94d31596b8",
+ "testPagePath": "stub-4.7.4.2-respond-with-method.html",
+ "testable": true
+ },
+ {
+ "href": "#default-method",
+ "id": "default-method",
+ "hash": "4d6f8f93b2e10ab0e486dbf464ff107ec1a6aa4c",
+ "secno": "4.7.4.3",
+ "testPageHash": "34e015c973887e2b3bf8b6db62f75d5d417a43cc",
+ "testPagePath": "stub-4.7.4.3-default-method.html",
+ "testable": true
+ },
+ {
+ "href": "#is-reload-attribute",
+ "id": "is-reload-attribute",
+ "hash": "6e1afd9e8940e9cd38aa7de1ed57e8c5b1a60e3d",
+ "secno": "4.7.4.4",
+ "testPageHash": "703a6469782d37be3c25e2214f897d1064acca47",
+ "testPagePath": "stub-4.7.4.4-is-reload-attribute.html",
+ "testable": true
+ },
+ {
+ "href": "#security-considerations",
+ "id": "security-considerations",
+ "hash": "5b02b143172647dd7f74f0464dffa7ec7d0e8f94",
+ "secno": "5",
+ "testable": false
+ },
+ {
+ "href": "#origin-relativity",
+ "id": "origin-relativity",
+ "hash": "72bbbd7d3d43a859af6ff9f19353210ddfcc26de",
+ "secno": "5.1",
+ "testPageHash": "1c92607dfac57b0f59654d059a4a67e0f984b84d",
+ "testPagePath": "stub-5.1-origin-relativity.html",
+ "testable": true
+ },
+ {
+ "href": "#cross-origin-resources",
+ "id": "cross-origin-resources",
+ "hash": "6176879ecfb5ae769679ceef4ee1e8889be8df92",
+ "secno": "5.2",
+ "testPageHash": "bcf85ba278c70c086645c416cee729ce753bc528",
+ "testPagePath": "stub-5.2-cross-origin-resources.html",
+ "testable": true
+ },
+ {
+ "href": "#storage-considerations",
+ "id": "storage-considerations",
+ "hash": "e101cee2062749b1a73086492377458251a5e875",
+ "secno": "6",
+ "testable": false
+ },
+ {
+ "href": "#extensibility",
+ "id": "extensibility",
+ "hash": "ef1b382bb89c52e01edad421b02b237765a21ce7",
+ "secno": "7",
+ "testable": false
+ },
+ {
+ "href": "#algorithms",
+ "id": "algorithms",
+ "hash": "d130247eab1d368efea646ff369e65f6c0c19481",
+ "secno": "8",
+ "testable": false
+ },
+ {
+ "href": "#registration-algorithm",
+ "id": "registration-algorithm",
+ "hash": "b688d090671c08ca17ea7cadc561e6d471ee099e",
+ "secno": "8.1",
+ "testable": false
+ },
+ {
+ "href": "#update-algorithm",
+ "id": "update-algorithm",
+ "hash": "679a19fef428affc83103c1eec0dbd3be40c4e2a",
+ "secno": "8.2",
+ "testable": false
+ },
+ {
+ "href": "#soft-update-algorithm",
+ "id": "soft-update-algorithm",
+ "hash": "8eb103f5cd0e595ee5e25f075e8c6239211e482a",
+ "secno": "8.3",
+ "testable": false
+ },
+ {
+ "href": "#installation-algorithm",
+ "id": "installation-algorithm",
+ "hash": "5874d9247d979009b67aedf964ae097837cfb3d9",
+ "secno": "8.4",
+ "testable": false
+ },
+ {
+ "href": "#activation-algorithm",
+ "id": "activation-algorithm",
+ "hash": "648b34baf6e7c2096a842e6d367949117843108e",
+ "secno": "8.5",
+ "testable": false
+ },
+ {
+ "href": "#on-fetch-request-algorithm",
+ "id": "on-fetch-request-algorithm",
+ "hash": "e1da43671071ec307f99cd781fc9b46353f3adfd",
+ "secno": "8.6",
+ "testable": false
+ },
+ {
+ "href": "#on-document-unload-algorithm",
+ "id": "on-document-unload-algorithm",
+ "hash": "8a7196b5dd04ad4fb9b96e16a52f4f7ac1906763",
+ "secno": "8.7",
+ "testable": false
+ },
+ {
+ "href": "#unregistration-algorithm",
+ "id": "unregistration-algorithm",
+ "hash": "0114db166d42211d0d7ab4b8e77de64a9fc97517",
+ "secno": "8.8",
+ "testable": false
+ },
+ {
+ "href": "#update-state-algorithm",
+ "id": "update-state-algorithm",
+ "hash": "2ed8a1e7479f1a8ad038aa44ccdd5e4f6b65cf05",
+ "secno": "8.9",
+ "testable": false
+ },
+ {
+ "href": "#scope-match-algorithm",
+ "id": "scope-match-algorithm",
+ "hash": "a2117fb34a8fa4ca3e832d9276477cfc1318dd1a",
+ "secno": "8.10",
+ "testable": false
+ },
+ {
+ "href": "#get-registration-algorithm",
+ "id": "get-registration-algorithm",
+ "hash": "b20332db952ba8f4b7e5f65b740a18da4a199c2e",
+ "secno": "8.11",
+ "testable": false
+ },
+ {
+ "href": "#get-newest-worker-algorithm",
+ "id": "get-newest-worker-algorithm",
+ "hash": "72dc1cbee8c98501931c411018fd1cad4376142b",
+ "secno": "8.12",
+ "testable": false
+ },
+ {
+ "href": "#acknowledgements",
+ "id": "acknowledgements",
+ "hash": "6347067ca5a574f8cc80c76d95dee568042d059b",
+ "secno": "9",
+ "testable": false
+ }
+ ],
+ "specUrl": "https://slightlyoff.github.io/ServiceWorker/spec/service_worker/"
+}
\ No newline at end of file
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.1-service-worker-obj.html b/src/third_party/web_platform_tests/service-workers/stub-3.1-service-worker-obj.html
new file mode 100644
index 0000000..588720e
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.1-service-worker-obj.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: ServiceWorker</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-obj">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Constructor()] // no-op constructor
+interface ServiceWorker : Worker {
+ readonly attribute DOMString scope;
+ readonly attribute DOMString url;
+ readonly attribute ServiceWorkerState state;
+
+ // event
+ attribute EventHandler onstatechange;
+};
+
+enum ServiceWorkerState {
+ "installing",
+ "installed",
+ "activating",
+ "activated",
+ "redundant"
+};
+</pre>
+
+<!--
+The `ServiceWorker` interface represents the document-side view of a Service
+Worker. This object provides a no-op constructor. Callers should note that only
+`ServiceWorker` objects created by the user agent (see
+`navigator.serviceWorker.installing`, `navigator.serviceWorker.waiting`,
+`navigator.serviceWorker.active` and `navigator.serviceWorker.controller`) will
+provide meaningful functionality.
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface EventHandler {};
+ interface Worker {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ ServiceWorker: ["throw new Error ('No object defined for the ServiceWorker interface')"],
+ ServiceWorkerState: ["throw new Error ('No object defined for the ServiceWorkerState enum')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.1.1-service-worker-scope.html b/src/third_party/web_platform_tests/service-workers/stub-3.1.1-service-worker-scope.html
new file mode 100644
index 0000000..47b4935
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.1.1-service-worker-scope.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: scope</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-scope">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+The `scope` of a `ServiceWorker` object reflects the [URL scope][1] of the
+associated Service Worker [registration][2]. The `scope` attribute must return
+the [serialization][3] of the URL representing the [URL scope][1] of the
+associated Service Worker [registration][2].
+
+For example, consider a document created by a navigation to
+`https://example.com/app.html` which [matches][4] via the following
+registration call which has been previously executed:
+// Script on the page https://example.com/app.html
+navigator.serviceWorker.register("/service_worker.js", { scope: "/*" });
+The value of `navigator.serviceWorker.controller.scope` will be
+`"https://example.com/*"`.
+
+
+
+[1]: #url-scope
+[2]: #registration
+[3]: http://url.spec.whatwg.org/#concept-url-serializer
+[4]: #on-fetch-request-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section scope so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.1.2-service-worker-url.html b/src/third_party/web_platform_tests/service-workers/stub-3.1.2-service-worker-url.html
new file mode 100644
index 0000000..be17bb8
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.1.2-service-worker-url.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: url</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-url">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+The `url` attribute must return the [serialization][1] of the URL of the script
+of the Service Worker, identified by its [URL scope][2], that is associated
+with the [ServiceWorkerGlobalScope][3] object. The `url` attribute is always an
+[absolute URL][4] corresponding to the script file which the Service Worker
+evaluates.
+
+In the example in section 3.1.1, the value of
+`navigator.serviceWorker.controller.url` will be
+`"https://example.com/service_worker.js"`.
+
+
+
+[1]: http://url.spec.whatwg.org/#concept-url-serializer
+[2]: #url-scope
+[3]: #service-worker-global-scope-interface
+[4]: http://url.spec.whatwg.org/#concept-absolute-url
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section url so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.1.3-service-worker-state.html b/src/third_party/web_platform_tests/service-workers/stub-3.1.3-service-worker-state.html
new file mode 100644
index 0000000..40f4da4
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.1.3-service-worker-state.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: state</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-state">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+The [ServiceWorker][1] object can be in several states. The `state` attribute
+must return the current state, which must be one of the following values
+defined in the [ServiceWorkerState][2] enumeration:
+
+`"installing"`:
+ The Service Worker represented by the [ServiceWorker][1] object has entered
+ and is running the steps in the [installation process][3]. During this
+ state, `e.waitUntil(p)` can be called inside the `oninstall` event handler
+ of the associcated [ServiceWorkerGloberScope][4] object to extend the life
+ of the [installing worker][5] until the passed [Promise][6] resolves
+ successfully. This is primarily used to ensure that the Service Worker is
+ not active until all of the core caches are populated.
+`"installed"`:
+ The Service Worker represented by the [ServiceWorker][1] object has
+ completed the steps in the [installation process][3]. The Service Worker in
+ this state is considered the [worker in waiting][7].
+`"activating"`:
+ The Service Worker represented by the [ServiceWorker][1] object has entered
+ and is running the steps in the [activation process][8]. During this state,
+ `e.waitUntil(p)` can be called inside the `onactivate` event handler of the
+ associated [ServiceWorkerGloberScope][9] object to extend the life of the
+ activating [active worker][10] until the passed [Promise][6] resolves
+ successfully. Note that no [functional events][11] are dispatched until the
+ state becomes `"activated"`.
+`"activated"`:
+ The Service Worker represented by the [ServiceWorker][1] object has
+ completed the steps in the [activation process][8]. The Service Worker in
+ this state is considered the [active worker][10] ready to [control][12] the
+ documents in matching scope upon subsequence [navigation][13].
+`"redundant"`:
+ A newly created Service Worker [registration][14] is replacing the current
+ [registration][14] of the Service Worker.
+
+
+
+[1]: #service-worker-interface
+[2]: #service-worker-state-enum
+[3]: #installation-process
+[4]: #service-worker-glober-scope-interface
+[5]: #installing-worker
+[6]: http://goo.gl/3TobQS
+[7]: #worker-in-waiting
+[8]: #activation-process
+[9]: #service-worker-global-scope-interface
+[10]: #active-worker
+[11]: #functional-events
+[12]: #document-control
+[13]: http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#navigate
+[14]: #registration
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section state so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.1.4-service-worker-on-state-change.html b/src/third_party/web_platform_tests/service-workers/stub-3.1.4-service-worker-on-state-change.html
new file mode 100644
index 0000000..3613874
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.1.4-service-worker-on-state-change.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: onstatechange</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-on-state-change">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`onstatechange` is the [event handler][1] that must be supported as attribute
+by the `[ServiceWorker][2]` object. A `statechange` event using the
+`[Event][3]` interface is dispatched on `[ServiceWorker][2]` object when the
+`state` attribute of the `ServiceWorker` object is changed.
+
+[1]: http://goo.gl/rBfiz0
+[2]: #service-worker-interface
+[3]: http://goo.gl/Mzv7Dv
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section onstatechange so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2-navigator-service-worker.html b/src/third_party/web_platform_tests/service-workers/stub-3.2-navigator-service-worker.html
new file mode 100644
index 0000000..0855d6c
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2-navigator-service-worker.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: navigator.serviceWorker</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<!--
+The `serviceWorker` attribute of the [Navigator][1] interface must return an
+instance of the `ServiceWorkerContainer` interface, which provides access to
+registration, removal, upgrade, and communication with Service Workers that are
+(or will become) active for the current document. Communication with these
+workers is provided via standard [HTML5 messaging APIs][2], and [messaging
+occurs as per usual with Web Workers][3].
+-->
+<script type=text/plain id="idl_0">
+partial interface Navigator {
+ readonly attribute ServiceWorkerContainer serviceWorker;
+};
+
+interface ServiceWorkerContainer : EventTarget {
+ [Unforgeable] readonly attribute ServiceWorker? installing;
+ [Unforgeable] readonly attribute ServiceWorker? waiting;
+ [Unforgeable] readonly attribute ServiceWorker? active;
+ [Unforgeable] readonly attribute ServiceWorker? controller;
+ readonly attribute Promise<ServiceWorker> ready;
+
+ Promise<sequence<ServiceWorker>?> getAll();
+ Promise<ServiceWorker> register(DOMString url, optional RegistrationOptionList options);
+ Promise<any> unregister(DOMString? scope);
+
+ // events
+ attribute EventHandler onupdatefound;
+ attribute EventHandler oncontrollerchange;
+ attribute EventHandler onreloadpage;
+ attribute EventHandler onerror;
+};
+
+dictionary RegistrationOptionList {
+ DOMString scope = "/*";
+};
+
+interface ReloadPageEvent : Event {
+ void waitUntil(Promise<any> f);
+};
+</script>
+
+<!--
+[1]: http://goo.gl/I7WAhg
+[2]: http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html
+[3]: http://www.w3.org/TR/workers/#dom-worker-postmessage
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface ServiceWorker {};
+ interface EventHandler {};
+ interface EventTarget {};
+ interface Event {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ Navigator: ["throw new Error ('No object defined for the Navigator interface')"],
+ ServiceWorkerContainer: ["throw new Error ('No object defined for the ServiceWorkerContainer interface')"],
+ RegistrationOptionList: ["throw new Error ('No object defined for the RegistrationOptionList dictionary')"],
+ ReloadPageEvent: ["throw new Error ('No object defined for the ReloadPageEvent interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2.1-navigator-service-worker-installing.html b/src/third_party/web_platform_tests/service-workers/stub-3.2.1-navigator-service-worker-installing.html
new file mode 100644
index 0000000..d73a35b
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2.1-navigator-service-worker-installing.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: installing</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-installing">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.installing` must return a [ServiceWorker][1] object
+representing the [installing worker][2] that is currently undergoing the
+installation process (from step 1 to step 7 of the [_Installation
+algorithm][3]) for the given [URL scope][4] in which the document may be
+[controlled][5] when the Service Worker becomes the [active worker][6].
+`navigator.serviceWorker.installing` returns `null` if no Service Worker
+[registration][7] is in the [installation process][8].
+
+[1]: #service-worker-interface
+[2]: #installing-worker
+[3]: #installation-algorithm
+[4]: #url-scope
+[5]: #document-control
+[6]: #active-worker
+[7]: #service-worker-registration-internal-interface
+[8]: #installation-process
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section installing so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2.10-navigator-service-worker-oncontrollerchange.html b/src/third_party/web_platform_tests/service-workers/stub-3.2.10-navigator-service-worker-oncontrollerchange.html
new file mode 100644
index 0000000..1e23e82
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2.10-navigator-service-worker-oncontrollerchange.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: oncontrollerchange</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-oncontrollerchange">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.oncontrollerchange` is the [event handler][1] that
+must be supported as attribute by the `[ServiceWorkerContainer][2]` object. A
+`controllerchange` event using the `[Event][3]` interface is dispatched on
+`[ServiceWorkerContainer][2]` object (See step 7 of the [_Activation
+algorithm][4]) when the associated Service Worker [registration][5] for the
+document enters the [activation process][6]. When the [activation process][6]
+is triggered by `replace()` method call within the event handler of the
+`install` event, `navigator.serviceWorker.controller` immediately reflects the
+[active worker][7] as the Service Worker that [controls][8] the document.
+
+[1]: http://goo.gl/rBfiz0
+[2]: #service-worker-container-interface
+[3]: http://goo.gl/Mzv7Dv
+[4]: #activation-algorithm
+[5]: #registration
+[6]: #activation-process
+[7]: #active-worker
+[8]: #document-control
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section oncontrollerchange so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2.11-navigator-service-worker-onreloadpage.html b/src/third_party/web_platform_tests/service-workers/stub-3.2.11-navigator-service-worker-onreloadpage.html
new file mode 100644
index 0000000..ef3fd10
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2.11-navigator-service-worker-onreloadpage.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: onreloadpage</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-onreloadpage">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.onreloadpage` is the [event handler][1] that must be
+supported as attribute by the `[ServiceWorkerContainer][2]` object. An event
+named `reloadpage` using the `[ReloadPageEvent][3]` interface is dispatched on
+`[ServiceWorkerContainer][2]` object when the page reload is triggered by the
+`[self.clients.reloadAll()][4]` method call from the [active worker][5],
+represented by its associated [ServiceWorkerGlobalScope][6] object, for the
+document.
+
+[1]: http://goo.gl/rBfiz0
+[2]: #service-worker-container-interface
+[3]: #reload-page-event-interface
+[4]: #reloadall-method
+[5]: #active-worker
+[6]: #service-worker-global-scope-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section onreloadpage so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2.12-navigator-service-worker-onerror.html b/src/third_party/web_platform_tests/service-workers/stub-3.2.12-navigator-service-worker-onerror.html
new file mode 100644
index 0000000..e254256
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2.12-navigator-service-worker-onerror.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: onerror</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-onerror">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.onerror` is the [event handler][1] that must be
+supported as attribute by the `[ServiceWorkerContainer][2]` object. An event
+named `error` using the `[ErrorEvent][3]` interface is dispatched on
+`[ServiceWorkerContainer][2]` object for any error from the associated
+`[ServiceWorker][4]` objects.
+
+[1]: http://goo.gl/rBfiz0
+[2]: #service-worker-container-interface
+[3]: http://goo.gl/FKuWgu
+[4]: #service-worker-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section onerror so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2.2-navigator-service-worker-waiting.html b/src/third_party/web_platform_tests/service-workers/stub-3.2.2-navigator-service-worker-waiting.html
new file mode 100644
index 0000000..2852d97
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2.2-navigator-service-worker-waiting.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: waiting</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-waiting">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.waiting` must return a [ServiceWorker][1] object
+representing the waiting Service Worker that is considered the [worker in
+waiting][2] for the document. `navigator.serviceWorker.waiting` returns `null`
+if there is no [worker in waiting][2] for the document.
+
+[1]: #service-worker-interface
+[2]: #worker-in-waiting
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section waiting so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2.3-navigator-service-worker-active.html b/src/third_party/web_platform_tests/service-workers/stub-3.2.3-navigator-service-worker-active.html
new file mode 100644
index 0000000..3ac45d1
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2.3-navigator-service-worker-active.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: active</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-active">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.active` must return a [ServiceWorker][1] object
+representing the [active worker][2] that is currently undergoing or completed
+the activation process (from step 4 to step 9 of the [_Activation
+algorithm][3]) for the given [URL scope][4] in which the document is controlled
+(or to be controlled). `navigator.serviceWorker.active` returns `null` if no
+Service Worker [registration][5] is in the [activation process][6].
+
+[1]: #service-worker-interface
+[2]: #active-worker
+[3]: #activation-algorithm
+[4]: #url-scope
+[5]: #service-worker-registration-internal-interface
+[6]: #activation-process
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section active so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2.4-navigator-service-worker-controller.html b/src/third_party/web_platform_tests/service-workers/stub-3.2.4-navigator-service-worker-controller.html
new file mode 100644
index 0000000..90378dd
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2.4-navigator-service-worker-controller.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: controller</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-controller">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.controller` must return a [ServiceWorker][1] object
+representing the [active worker][2] that currently handles resource requests
+for the document. `navigator.serviceWorker.controller` returns `null` if the
+current document was not [created under a Service Worker][3] (See step 6-1 of
+[_OnFetchRequest][3] algorithm) or the request is a force refresh
+(shift+refresh).
+
+[1]: #service-worker-interface
+[2]: #active-worker
+[3]: #on-fetch-request-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section controller so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2.5-navigator-service-worker-ready.html b/src/third_party/web_platform_tests/service-workers/stub-3.2.5-navigator-service-worker-ready.html
new file mode 100644
index 0000000..f3b1ca7
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2.5-navigator-service-worker-ready.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: ready</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-ready">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.ready` attribute must return the result of running
+these steps:
+
+1. Let `promise` be a newly-created [promise][1].
+2. Return `promise`.
+3. Run the following steps asynchronously:
+ 1. Let `registration` be the result of running [_ScopeMatch
+ algorithm][2] with document's url as its argument.
+ 2. If `registration` is null, then:
+ 1. Wait for the document to have a matching [registration][3].
+ 3. If the [registration][3], represented by `registration`, for the
+ document has an [active worker][4], then:
+ 1. Resolve `promise` with the [ServiceWorker][5] object associated
+ with the [active worker][4].
+ 2. Abort these steps.
+ 4. If the [registration][3], represented by `registration`, for the
+ document has a [worker in waiting][6], then:
+ 1. Resolve `promise` with the [ServiceWorker][5] object associated
+ with the [worker in waiting][6].
+ 2. Abort these steps.
+ 5. Wait until the [registration][3], represented by `registration`,
+ for the document acquires a [worker in waiting][6] through a new
+ [installation process][7].
+ 6. Resolve `promise` with the [ServiceWorker][5] object associated
+ with the [worker in waiting][6].
+Note that `ready` attribute is desinged in a way that the returned [promise][1]
+will never reject. Instead, it waits until the [promise][1] resolves with a
+newly installed [worker in waiting][6]. Hence, the `state` of the acquired
+[`ServiceWorker`][8] object is either `installed`, `activating` or `activated`.
+
+
+
+[1]: http://goo.gl/3TobQS
+[2]: #scope-match-algorithm
+[3]: #registration
+[4]: #active-worker
+[5]: #service-worker-interface
+[6]: #worker-in-waiting
+[7]: #installation-process
+[8]: #service-worker
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section ready so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2.6-navigator-service-worker-getAll.html b/src/third_party/web_platform_tests/service-workers/stub-3.2.6-navigator-service-worker-getAll.html
new file mode 100644
index 0000000..18180b9
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2.6-navigator-service-worker-getAll.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: getAll()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-getAll">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.getAll()` method must return a promise that resolves
+with the array of the ServiceWorker objects in `installing`, `installed`,
+`activating` and `activated` states.
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section getAll() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2.7-navigator-service-worker-register.html b/src/third_party/web_platform_tests/service-workers/stub-3.2.7-navigator-service-worker-register.html
new file mode 100644
index 0000000..c9253dd
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2.7-navigator-service-worker-register.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: register()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-register">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.register(url, options)` method must run the
+[Registration algorithm][1] passing `url` and `options`.`scope` as the
+arguments.
+
+[1]: #registration-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section register() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2.8-navigator-service-worker-unregister.html b/src/third_party/web_platform_tests/service-workers/stub-3.2.8-navigator-service-worker-unregister.html
new file mode 100644
index 0000000..c4c0c24
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2.8-navigator-service-worker-unregister.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: unregister()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-unregister">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.unregister(scope)` method must run the [Unregistration
+algorithm][1] passing `scope` as the argument.
+
+[1]: #unregistration-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section unregister() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-3.2.9-navigator-service-worker-onupdatefound.html b/src/third_party/web_platform_tests/service-workers/stub-3.2.9-navigator-service-worker-onupdatefound.html
new file mode 100644
index 0000000..4502b2e
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-3.2.9-navigator-service-worker-onupdatefound.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: onupdatefound</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-onupdatefound">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.onupdatefound` is the [event handler][1] that must be
+supported as attribute by the `[ServiceWorkerContainer][2]` object. An
+`updatefound` event using the `[Event][3]` interface is dispatched on
+`[ServiceWorkerContainer][2]` object (See step 4 of the [_Installation
+algorithm][4]) when the associated Service Worker [registration][5] for the
+document enters the [installation process][6] such that
+`navigator.serviceWorker.installing` becomes the new [installing worker][7].
+
+[1]: http://goo.gl/rBfiz0
+[2]: #service-worker-container-interface
+[3]: http://goo.gl/Mzv7Dv
+[4]: #installation-algorithm
+[5]: #registration
+[6]: #installation-process
+[7]: #installing-worker
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section onupdatefound so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.1-service-worker-global-scope.html b/src/third_party/web_platform_tests/service-workers/stub-4.1-service-worker-global-scope.html
new file mode 100644
index 0000000..ce6a045
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.1-service-worker-global-scope.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: ServiceWorkerGlobalScope</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Global]
+interface ServiceWorkerGlobalScope : WorkerGlobalScope {
+ readonly attribute CacheStorage caches;
+ // A container for a list of window objects, identifiable by ID, that
+ // correspond to windows (or workers) that are "controlled" by this SW
+ readonly attribute ServiceWorkerClients clients;
+ [Unforgeable] readonly attribute DOMString scope;
+
+ Promise<any> fetch((Request or ScalarValueString) request);
+
+ void update();
+ void unregister();
+
+ attribute EventHandler oninstall;
+ attribute EventHandler onactivate;
+ attribute EventHandler onfetch;
+ attribute EventHandler onbeforeevicted;
+ attribute EventHandler onevicted;
+
+ // The event.source of these MessageEvents are instances of Client
+ attribute EventHandler onmessage;
+
+ // close() method inherited from WorkerGlobalScope is not exposed.
+};
+</pre>
+
+<!--
+The `ServiceWorkerGlobalScope` interface represents the global execution
+context of a Service Worker. `ServiceWorkerGlobalScope` object provides
+generic, event-driven, time-limited script execution contexts that run at an
+origin. Once successfully [registered][1], a Service Worker is started, kept
+alive and killed by their relationship to events, not documents. Any type of
+synchronous requests MUST NOT be initiated inside of a Service Worker.
+
+[1]: #navigator-service-worker-register
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface CacheStorage {};
+ interface ServiceWorkerClients {};
+ interface Request {};
+ interface ScalarValueString {};
+ interface EventHandler {};
+ interface WorkerGlobalScope {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ ServiceWorkerGlobalScope: ["throw new Error ('No object defined for the ServiceWorkerGlobalScope interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.1.1-service-worker-global-scope-caches.html b/src/third_party/web_platform_tests/service-workers/stub-4.1.1-service-worker-global-scope-caches.html
new file mode 100644
index 0000000..4e68cc2
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.1.1-service-worker-global-scope-caches.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: caches</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-caches">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`self.caches` must return the `[CacheStorage][1]` object that is the global
+asynchronous map object for the `[ServiceWorkerGlobalScope][2]` execution
+context containing the cache objects keyed by the name of the caches. Caches
+are always enumerable via `self.caches` in insertion order (per [ECMAScript 6
+Map objects][3].)
+
+[1]: #cache-storage-interface
+[2]: #service-worker-global-scope-interface
+[3]: http://goo.gl/gNnDPO
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section caches so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.1.2-service-worker-global-scope-clients.html b/src/third_party/web_platform_tests/service-workers/stub-4.1.2-service-worker-global-scope-clients.html
new file mode 100644
index 0000000..8499c71
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.1.2-service-worker-global-scope-clients.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: clients</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-clients">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`self.clients` must return the `[ServiceWorkerClients][1]` object containing a
+list of client objects, identifiable by ID, that correspond to windows or
+workers that are [controlled][2] by this Service Worker.
+
+[1]: #service-worker-clients-interface
+[2]: #document-control
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section clients so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.1.3-service-worker-global-scope-scope.html b/src/third_party/web_platform_tests/service-workers/stub-4.1.3-service-worker-global-scope-scope.html
new file mode 100644
index 0000000..3784e1e
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.1.3-service-worker-global-scope-scope.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: scope</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-scope">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+The `scope` attribute of a [ServiceWorkerGlobalScope][1] object reflects the
+[URL scope][2] of the associated Service Worker [registration][3]. The `scope`
+attribute must return the [serialization][4] of the URL representing the [URL
+scope][2] of the associated Service Worker [registration][3].
+
+[1]: #service-worker-global-scope-interface
+[2]: #url-scope
+[3]: #registration
+[4]: http://url.spec.whatwg.org/#concept-url-serializer
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section scope so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.1.4-service-worker-global-scope-fetch.html b/src/third_party/web_platform_tests/service-workers/stub-4.1.4-service-worker-global-scope-fetch.html
new file mode 100644
index 0000000..29548a7
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.1.4-service-worker-global-scope-fetch.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: fetch(request)</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-fetch">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`self.fetch(request)` method must run these steps:
+
+1. Let `request` be a [request][1] represented by `request`.
+2. Set [`client`][2] of `request` to the [JavaScript global
+ environment][3] represented by `self` object.
+3. Let `promise` be a newly-created [promise][4].
+4. Return `promise.`
+5. Run the following steps asynchronously:
+ 1. Let `response` be the result of running [fetch algorithm][5] with
+ `request` as its argument.
+ 2. If `response` is a [network error][6], then:
+ 1. Reject `promise` with a new [DOMException][7] whose name is
+ "[NetworkError][8]".
+ 3. Else,
+ 1. Resolve `promise` with a new [Response][9] object associated
+ with `response`.
+
+
+
+[1]: http://goo.gl/ucOuXl
+[2]: http://goo.gl/Oxj4xQ
+[3]: http://goo.gl/ifwwCC
+[4]: http://goo.gl/3TobQS
+[5]: http://goo.gl/fGMifs
+[6]: http://goo.gl/jprjjc
+[7]: http://goo.gl/A0U8qC
+[8]: http://goo.gl/lud5HB
+[9]: http://goo.gl/Deazjv
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section fetch(request) so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.1.5-service-worker-global-scope-update.html b/src/third_party/web_platform_tests/service-workers/stub-4.1.5-service-worker-global-scope-update.html
new file mode 100644
index 0000000..ee9552b
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.1.5-service-worker-global-scope-update.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: update()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-update">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`update()` pings the server for an updated version of this script without
+consulting caches. `self.update()` method must run the [_SoftUpdate
+algorithm][1] passing its serviceWorkerRegistration object as the argument
+which is the result of running the [_GetRegistration algorithm][2] with
+`self.scope` as the argument. (This is conceptually the same operation that UA
+does maximum once per every 24 hours.)
+
+[1]: #soft-update-algorithm
+[2]: #get-registration-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section update() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.1.6-service-worker-global-scope-unregister.html b/src/third_party/web_platform_tests/service-workers/stub-4.1.6-service-worker-global-scope-unregister.html
new file mode 100644
index 0000000..9f76ee3
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.1.6-service-worker-global-scope-unregister.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: unregister()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-unregister">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`self.unregister()` method must run the [Unregistration algorithm][1]
+implicitly passing `self.scope` as the argument.
+
+[1]: #unregistration-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section unregister() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.1.7-service-worker-global-scope-onmessage.html b/src/third_party/web_platform_tests/service-workers/stub-4.1.7-service-worker-global-scope-onmessage.html
new file mode 100644
index 0000000..d536a2c
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.1.7-service-worker-global-scope-onmessage.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: onmessage</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-onmessage">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`self.onmessage` is the [event handler][1] that must be supported as attribute
+by the `ServiceWorkerGlobalScope` object. `ServiceWorkerGlobalScope` objects
+act as if they had an implicit `[MessagePort][2]` associated with them. This
+port is part of a channel that is set up when the worker is created, but it is
+not exposed. This object must never be garbage collected before the
+`ServiceWorkerGlobalScope` object.
+
+All messages received by that port must immediately be retargeted at the
+`ServiceWorkerGlobalScope` object. That is, an event named `message` using the
+`[MessageEvent][3]` interface is dispatched on ServiceWorkerGlobalScope object.
+The `event.source` of these `[MessageEvent][3]`s are instances of `[Client][4]`.
+
+
+
+[1]: http://goo.gl/rBfiz0
+[2]: http://goo.gl/tHBrI6
+[3]: http://goo.gl/S5e0b6
+[4]: #client-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section onmessage so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.2-client.html b/src/third_party/web_platform_tests/service-workers/stub-4.2-client.html
new file mode 100644
index 0000000..96976c1
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.2-client.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Client</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#client">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Constructor()] // no-op constructor
+interface Client {
+ readonly attribute unsigned long id;
+ void postMessage(any message, DOMString targetOrigin,
+ optional sequence<Transferable> transfer);
+};
+</pre>
+
+<!--
+The `Client` interface represents the window or the worker (defined as client)
+that is [controlled][1] by the Service Worker. This object provides a no-op
+constructor. Callers should note that only `Client` objects created by the user
+agent (see [`this.clients.getServiced()`][2]) will provide meaningful
+functionality.
+
+The `id` of a `Client` identifies the specific client object from the list of
+client objects serviced by the Service Worker. The `postMessage(message,
+targetOrigin, transfer)` method of a `[Client][3]`, when called, causes a
+`[MessageEvent][4]` to be dispatched at the client object.
+
+
+
+[1]: #document-control
+[2]: #get-serviced-method
+[3]: #client-interface
+[4]: http://goo.gl/4SLWiH
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface Transferable {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ Client: ["throw new Error ('No object defined for the Client interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.3-service-worker-clients.html b/src/third_party/web_platform_tests/service-workers/stub-4.3-service-worker-clients.html
new file mode 100644
index 0000000..beb5d59
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.3-service-worker-clients.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: ServiceWorkerClients</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-clients">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+interface ServiceWorkerClients {
+ // A list of client objects, identifiable by ID, that correspond to windows
+ // (or workers) that are "controlled" by this SW
+ Promise<sequence<Client>?> getServiced();
+ Promise<any> reloadAll();
+};
+</pre>
+
+<!--
+The `ServiceWorkerClients` interface represents a container for a list of
+`[Client][1]` objects.
+
+[1]: #client-interface
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface Client {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ ServiceWorkerClients: ["throw new Error ('No object defined for the ServiceWorkerClients interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.3.1-get-serviced-method.html b/src/third_party/web_platform_tests/service-workers/stub-4.3.1-get-serviced-method.html
new file mode 100644
index 0000000..8543bd4
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.3.1-get-serviced-method.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: getServiced()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#get-serviced-method">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+The `getServiced()` method of a `ServiceWorkerClients`, when called, returns a
+[Promise][1] that will resolve with a list of `[Client][2]` objects that are
+[controlled][3] by this Service Worker.
+
+[1]: http://goo.gl/3TobQS
+[2]: #client-interface
+[3]: #document-control
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section getServiced() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.3.2-reloadall-method.html b/src/third_party/web_platform_tests/service-workers/stub-4.3.2-reloadall-method.html
new file mode 100644
index 0000000..dd79a91
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.3.2-reloadall-method.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: reloadAll()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#reloadall-method">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`reloadAll()` provides a mechanism for the worker to request synchronized
+re-fetch of all documents whose URLs match the registration's [URL scope][1].
+An event named `reloadpage` is dispatched on the `navigator.serviceWorker`
+object of each document. The in-document handlers may allow the event to
+continue, request an extension (via [`e.waitUntil()`][2]), or cancel the
+collective reload by calling [`e.preventDefault()`][3].
+
+[1]: #url-scope
+[2]: #wait-until-method
+[3]: http://goo.gl/2zH6ie
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section reloadAll() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.4-request-objects.html b/src/third_party/web_platform_tests/service-workers/stub-4.4-request-objects.html
new file mode 100644
index 0000000..aa3502b
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.4-request-objects.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Request Objects</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#request-objects">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Constructor(optional RequestInit init)]
+interface Request {
+ attribute unsigned long timeout;
+ attribute DOMString url;
+ attribute ByteString method;
+ readonly attribute DOMString origin;
+ readonly attribute Mode mode;
+ attribute boolean synchronous;
+ attribute boolean forcePreflight;
+ attribute boolean omitCredentials;
+ readonly attribute DOMString referrer;
+ readonly attribute HeaderMap headers; // alternative: sequence<Header> headers;
+ attribute any body;
+};
+
+dictionary RequestInit {
+ unsigned long timeout = 0;
+ DOMString url;
+ boolean synchronous = false;
+ boolean forcePreflight = false;
+ boolean omitCredentials = false;
+ ByteString method = "GET";
+ HeaderMap headers;
+ any body;
+};
+
+enum Mode {
+ "same origin",
+ "tainted cross-origin",
+ "CORS",
+ "CORS-with-forced-preflight"
+};
+
+[MapClass(DOMString, DOMString)]
+interface HeaderMap {
+};
+</pre>
+
+
+
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ Request: ["throw new Error ('No object defined for the Request interface')"],
+ RequestInit: ["throw new Error ('No object defined for the RequestInit dictionary')"],
+ Mode: ["throw new Error ('No object defined for the Mode enum')"],
+ HeaderMap: ["throw new Error ('No object defined for the HeaderMap interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.5-response-objects.html b/src/third_party/web_platform_tests/service-workers/stub-4.5-response-objects.html
new file mode 100644
index 0000000..a334586
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.5-response-objects.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Response Objects</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#response-objects">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<!--
+`Response` objects model HTTP responses.
+-->
+<script type=text/plain id="idl_0">
+[Constructor]
+interface AbstractResponse {
+};
+
+interface OpaqueResponse : AbstractResponse {
+ readonly attribute unsigned short status;
+ readonly attribute ByteString statusText;
+ // Returns a filtered list of headers. See prose for details.
+ readonly attribute HeaderMap headers;
+ // No setter for headers
+ readonly attribute DOMString url;
+};
+
+interface CORSResponse : Response {
+ readonly attribute HeaderMap headers;
+};
+
+[Constructor(optional ResponseInit responseInitDict)]
+interface Response : AbstractResponse {
+ attribute unsigned short status;
+ attribute ByteString statusText;
+ readonly attribute HeaderMap headers;
+ attribute DOMString url;
+ Promise<Blob> toBlob();
+};
+
+dictionary ResponseInit {
+ unsigned short status = 200;
+ ByteString statusText = "OK";
+ HeaderMap headers;
+};
+</pre>
+
+
+
+ <script type=text/plain id="untested_idls">
+ interface HeaderMap {};
+ interface Blob {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ AbstractResponse: ["throw new Error ('No object defined for the AbstractResponse interface')"],
+ OpaqueResponse: ["throw new Error ('No object defined for the OpaqueResponse interface')"],
+ CORSResponse: ["throw new Error ('No object defined for the CORSResponse interface')"],
+ Response: ["throw new Error ('No object defined for the Response interface')"],
+ ResponseInit: ["throw new Error ('No object defined for the ResponseInit dictionary')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.5.2-response.html b/src/third_party/web_platform_tests/service-workers/stub-4.5.2-response.html
new file mode 100644
index 0000000..0a8715c
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.5.2-response.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Response</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#response">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`Response` objects are mutable and constructable. They model HTTP responses.
+The `fetch()` API returns this type for same-origin responses.
+
+It may be possible to set the `Location` header of a `Response` object to
+someplace not in the current origin but this is not a security issue.
+Cross-origin response bodies are opaque to script, and since only same-origin
+documents will encounter these responses, the only systems the Service Worker
+can "lie to" are same-origin (and therefore safe from the perspective of other
+origins).
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section Response so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.5.4-opaque-response.html b/src/third_party/web_platform_tests/service-workers/stub-4.5.4-opaque-response.html
new file mode 100644
index 0000000..1698558
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.5.4-opaque-response.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: OpaqueResponse</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#opaque-response">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`OpaqueResponse` objects are immutable but constructable. The `fetch()` API
+returns this type for cross-origin responses.
+
+Their role is to encapsulate the security properties of the web platform. As
+such, their `body` attribute will always be `undefined` and the list of
+readable `headers` is heavily filtered.
+
+`OpaqueResponse` objects may be forwarded on to rendering documents in exactly
+the same way as mutable `Response` objects.
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section OpaqueResponse so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.6-cache-objects.html b/src/third_party/web_platform_tests/service-workers/stub-4.6-cache-objects.html
new file mode 100644
index 0000000..3bb47b2
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.6-cache-objects.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Caches</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-objects">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+To allow authors to fully manage their content caches for offline use, the
+`[ServiceWorkerGlobalScope][1]` execution context provides the caching methods
+largely conforming to [ECMAScript 6 Map objects][2] with additional convenience
+methods. A domain can have multiple, named `[Cache][3]` objects, whose contents
+are entirely under the control of scripts. Caches are not shared across
+domains, and they are completely isolated from the browser's HTTP cache.
+
+[1]: #service-worker-global-scope-interface
+[2]: http://goo.gl/gNnDPO
+[3]: #cache-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section Caches so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.6.1-cache-lifetimes.html b/src/third_party/web_platform_tests/service-workers/stub-4.6.1-cache-lifetimes.html
new file mode 100644
index 0000000..9068d0c
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.6.1-cache-lifetimes.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Understanding Cache Lifetimes</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-lifetimes">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+The `[Cache][1]` instances are not part of the browser's HTTP cache. The
+`[Cache][1]` objects are exactly what authors have to manage themselves. The
+`[Cache][1]` objects do not get updated unless authors explicitly request them
+to be. The `[Cache][1]` objects do not expire unless authors delete the
+entries. The `[Cache][1]` objects do not disappear just because the Service
+Worker script is updated. That is, caches are not updated automatically.
+Updates must be manually managed. This implies that authors should version
+their caches by name and make sure to use the caches only from the version of
+the ServiceWorker that can safely operate on.
+
+[1]: #cache-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section Understanding Cache Lifetimes so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.6.2-cache.html b/src/third_party/web_platform_tests/service-workers/stub-4.6.2-cache.html
new file mode 100644
index 0000000..faee336
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.6.2-cache.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Cache</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Exposed=(Window,Worker)]
+interface Cache {
+ Promise<Response> match(RequestInfo request, optional CacheQueryOptions options);
+ Promise<sequence<Response>> matchAll(optional RequestInfo request, optional CacheQueryOptions options);
+ Promise<void> add(RequestInfo request);
+ Promise<void> addAll(sequence<RequestInfo> requests);
+ Promise<void> put(RequestInfo request, Response response);
+ Promise<boolean> delete(RequestInfo request, optional CacheQueryOptions options);
+ Promise<sequence<Request>> keys(optional RequestInfo request, optional CacheQueryOptions options);
+};
+
+dictionary CacheQueryOptions {
+ boolean ignoreSearch = false;
+ boolean ignoreMethod = false;
+ boolean ignoreVary = false;
+ DOMString cacheName;
+};
+
+dictionary CacheBatchOperation {
+ DOMString type;
+ Request request;
+ Response response;
+ CacheQueryOptions options;
+};
+</pre>
+
+
+
+ <script type=text/plain id="untested_idls">
+ interface AbstractResponse {};
+ interface Request {};
+ interface ScalarValueString {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ Cache: ["throw new Error ('No object defined for the Cache interface')"],
+ QueryParams: ["throw new Error ('No object defined for the QueryParams dictionary')"],
+ CacheIterationCallback: ["throw new Error ('No object defined for the CacheIterationCallback callback')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.6.3-cache-storage.html b/src/third_party/web_platform_tests/service-workers/stub-4.6.3-cache-storage.html
new file mode 100644
index 0000000..875220e
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.6.3-cache-storage.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: CacheStorage</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Constructor(sequence<any> iterable)]
+interface CacheStorage {
+ Promise<any> match(ScalarValueString url, optional DOMString cacheName);
+ Promise<Cache> get(DOMString key);
+ Promise<boolean> has(DOMString key);
+ Promise<any> set(DOMString key, Cache val);
+ Promise<any> clear();
+ Promise<any> delete(DOMString key);
+ void forEach(CacheStorageIterationCallback callback, optional object thisArg);
+ Promise<sequence<any>> entries();
+ Promise<sequence<DOMString>> keys();
+ Promise<sequence<Cache>> values();
+ Promise<unsigned long> size();
+};
+
+callback CacheStorageIterationCallback = void (Cache value, DOMString key, CacheStorage map);
+</pre>
+
+<!--
+**Note**:[CacheStorage][1]interface is designed to largely conform
+to[ECMAScript 6 Map objects][2]but entirely async, and with additional
+convenience methods.
+
+[1]: #cache-storage-interface
+[2]: http://goo.gl/gNnDPO
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface ScalarValueString {};
+ interface Cache {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ CacheStorage: ["throw new Error ('No object defined for the CacheStorage interface')"],
+ CacheStorageIterationCallback: ["throw new Error ('No object defined for the CacheStorageIterationCallback callback')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.7.1-install-phase-event.html b/src/third_party/web_platform_tests/service-workers/stub-4.7.1-install-phase-event.html
new file mode 100644
index 0000000..195c38d
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.7.1-install-phase-event.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: InstallPhaseEvent</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#install-phase-event">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+interface InstallPhaseEvent : Event {
+ Promise<any> waitUntil(Promise<any> f);
+};
+</pre>
+
+<!--
+Service Workers have two [Lifecycle events][1], `[install][2]` and
+`[activate][3]`. Service Workers use the `[InstallPhaseEvent][4]` interface for
+`[activate][3]` event and the `[InstallEvent][5]` interface, which inherits
+from the `[InstallPhaseEvent][4]` interface, for `[install][2]` event.
+
+[1]: #lifecycle-events
+[2]: #install-event
+[3]: #activate-event
+[4]: #install-phase-event-interface
+[5]: #install-event-interface
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface Event {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ InstallPhaseEvent: ["throw new Error ('No object defined for the InstallPhaseEvent interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.7.1.1-wait-until-method.html b/src/third_party/web_platform_tests/service-workers/stub-4.7.1.1-wait-until-method.html
new file mode 100644
index 0000000..84b730f
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.7.1.1-wait-until-method.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: event.waitUntil(f)</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#wait-until-method">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`event.waitUntil(f)` method, when called in `oninstall` or `onactivate`,
+extends the lifetime of the event. When called in `oninstall`, it delays
+treating the installing worker until the passed [Promise][1] resolves
+successfully. This is primarily used to ensure that a `ServiceWorker` is not
+active until all of the core caches it depends on are populated. When called in
+`onactivate`, it delays treating the activating worker until the passed
+[Promise][1] resolves successfully. This is primarily used to ensure that any
+[Functional events][2] are not dispatched to the `ServiceWorker` until it
+upgrades database schemas and deletes the outdated cache entries.
+
+[1]: http://goo.gl/3TobQS
+[2]: #functional-events
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section event.waitUntil(f) so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.7.2-install-event.html b/src/third_party/web_platform_tests/service-workers/stub-4.7.2-install-event.html
new file mode 100644
index 0000000..a2a5b1d
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.7.2-install-event.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: install Event</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#install-event">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+An event named `[install][1]` using the `[InstallEvent][2]` interface is
+dispatched on `ServiceWorkerGlobalScope` object when the state of the
+associated `ServiceWorker` changes its value to `installing`. (See step 3 of
+[_Installation algorithm][3])
+
+[1]: #install-event
+[2]: #install-event-interface
+[3]: #installation-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section install Event so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.7.2.1-install-event-section.html b/src/third_party/web_platform_tests/service-workers/stub-4.7.2.1-install-event-section.html
new file mode 100644
index 0000000..c305159
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.7.2.1-install-event-section.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: InstallEvent</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#install-event-section">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+interface InstallEvent : InstallPhaseEvent {
+ readonly attribute ServiceWorker? activeWorker;
+ void replace();
+};
+</pre>
+
+<!--
+Service Workers use the `[InstallEvent][1]` interface for `[install][2]` event.
+
+[1]: #install-event-interface
+[2]: #install-event
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface ServiceWorker {};
+ interface InstallPhaseEvent {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ InstallEvent: ["throw new Error ('No object defined for the InstallEvent interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.7.2.2-replace-method.html b/src/third_party/web_platform_tests/service-workers/stub-4.7.2.2-replace-method.html
new file mode 100644
index 0000000..78c916f
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.7.2.2-replace-method.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: event.replace()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#replace-method">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`replace()` interacts with `waitUntil` method in the following way:
+
+- Successful installation can be delayed by `waitUntil`, perhaps by
+ subsequent event handlers.
+- Replacement only happens upon successful installation
+- Therefore, replacement of the [active worker][1] (if any) is not
+ immediate, however it may occur as soon as the end of the current turn.
+
+
+
+[1]: #navigator-service-worker-active
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section event.replace() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.7.3-activate-event.html b/src/third_party/web_platform_tests/service-workers/stub-4.7.3-activate-event.html
new file mode 100644
index 0000000..82c049a
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.7.3-activate-event.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: activate Event</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#activate-event">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+An event named `[activate][1]` using the `[InstallPhaseEvent][2]` interface is
+dispatched on `ServiceWorkerGlobalScope` object when the state of the
+associated `ServiceWorker` changes its value to `activating`. (See step 6 of
+[_Activation algorithm][3])
+
+Service Workers use the `[InstallPhaseEvent][4]` interface for `[activate][1]`
+event.
+
+
+
+[1]: #activate-event
+[2]: #install-phase-event
+[3]: #activation-algorithm
+[4]: #install-phase-event-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section activate Event so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.7.4.1-fetch-event-section.html b/src/third_party/web_platform_tests/service-workers/stub-4.7.4.1-fetch-event-section.html
new file mode 100644
index 0000000..8555903
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.7.4.1-fetch-event-section.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: FetchEvent</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#fetch-event-section">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Constructor]
+interface FetchEvent : Event {
+ readonly attribute Request request;
+ readonly attribute Client client; // The window issuing the request.
+ readonly attribute Context context;
+ readonly attribute boolean isReload;
+
+ void respondWith(Promise<AbstractResponse> r);
+ Promise<any> forwardTo(ScalarValueString url);
+ Promise<any> default();
+};
+
+enum Context {
+ "connect",
+ "font",
+ "img",
+ "object",
+ "script",
+ "style",
+ "worker",
+ "popup",
+ "child",
+ "navigate"
+};
+</pre>
+
+<!--
+Service Workers use the `[FetchEvent][1]` interface for `[fetch][2]` event.
+
+[1]: #fetch-event-interface
+[2]: #fetch-event
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface Request {};
+ interface Client {};
+ interface AbstractResponse {};
+ interface ScalarValueString {};
+ interface Event {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ FetchEvent: ["throw new Error ('No object defined for the FetchEvent interface')"],
+ Context: ["throw new Error ('No object defined for the Context enum')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.7.4.2-respond-with-method.html b/src/third_party/web_platform_tests/service-workers/stub-4.7.4.2-respond-with-method.html
new file mode 100644
index 0000000..f178a50
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.7.4.2-respond-with-method.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: event.respondWith(r)</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#respond-with-method">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`event.respondWith(r)` method must run the steps, from step 10 to step 15,
+defined in the [_OnFetchRequest algorithm][1].
+
+The `r` argument must resolve with a [AbstractResponse][2], else a
+[NetworkError][3] is thrown. If the request is a top-level navigation and the
+return value is a [OpaqueResponse][4] (an opaque response body), a
+[NetworkError][3] is thrown. The final URL of all successful (non
+network-error) responses is the [requested][5] URL. Renderer-side security
+checks about tainting for cross-origin content are tied to the transparency (or
+opacity) of the [Response][6] body, not URLs.
+
+
+
+[1]: #on-fetch-request-algorithm
+[2]: #abstract-response-interface
+[3]: http://w3c.github.io/dom/#networkerror
+[4]: #opaque-response-interface
+[5]: #request-objects
+[6]: #response-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section event.respondWith(r) so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.7.4.3-default-method.html b/src/third_party/web_platform_tests/service-workers/stub-4.7.4.3-default-method.html
new file mode 100644
index 0000000..52a8dbd
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.7.4.3-default-method.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: event.default()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#default-method">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`event.default()` method must run these steps:
+
+1. Let `promise` be a newly-created [promise][1].
+2. Return `promise.`
+3. Run the following steps asynchronously:
+ 1. Let `request` be `event`'s `request`.
+ 2. Set `request`'s [skip service worker flag][2].
+ 3. Let `response` be the result of running [fetch algorithm][3] with
+ `request` as its argument.
+ 4. If `response` is a [network error][4], then:
+ 1. Reject `promise` with a new [DOMException][5] whose name is
+ "[NetworkError][6]".
+ 5. Else,
+ 1. Resolve `promise` with a new [Response][7] object associated
+ with `response`.
+
+
+
+[1]: http://goo.gl/3TobQS
+[2]: http://goo.gl/gP7IWW
+[3]: http://goo.gl/fGMifs
+[4]: http://goo.gl/jprjjc
+[5]: http://goo.gl/A0U8qC
+[6]: http://goo.gl/lud5HB
+[7]: http://goo.gl/Deazjv
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section event.default() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-4.7.4.4-is-reload-attribute.html b/src/third_party/web_platform_tests/service-workers/stub-4.7.4.4-is-reload-attribute.html
new file mode 100644
index 0000000..f116b68
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-4.7.4.4-is-reload-attribute.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: event.isReload</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#is-reload-attribute">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+Returns true if `event` was dispatched with the user's intention for the page
+reload, and false otherwise. Pressing the refresh button should be considered a
+reload while clicking a link and pressing the back button should not. The
+behavior of the `Ctrl+l enter` is left to the implementations of the user
+agents.
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section event.isReload so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-5.1-origin-relativity.html b/src/third_party/web_platform_tests/service-workers/stub-5.1-origin-relativity.html
new file mode 100644
index 0000000..e885de6
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-5.1-origin-relativity.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Origin Relativity</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#origin-relativity">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+One of the advanced concerns that major applications would encounter is whether
+they can be hosted from a CDN. By definition, these are servers in other
+places, often on other domains. Therefore, Service Workers cannot be hosted on
+CDNs. But they can include resources via [importScripts()][1]. The reason for
+this restriction is that Service Workers create the opportunity for a bad actor
+to turn a bad day into a bad eternity.
+
+[1]: http://goo.gl/Owcfs2
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section Origin Relativity so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/stub-5.2-cross-origin-resources.html b/src/third_party/web_platform_tests/service-workers/stub-5.2-cross-origin-resources.html
new file mode 100644
index 0000000..3a10c9e
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/stub-5.2-cross-origin-resources.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Cross-Origin Resources & CORS</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cross-origin-resources">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+Applications tend to cache items that come from a CDN or other domain. It is
+possible to request many of them directly using <script>, <img>, <video> and
+<link> elements. It would be hugely limiting if this sort of runtime
+collaboration broke when offline. Similarly, it is possible to XHR many sorts
+of off-domain resources when appropriate CORS headers are set.
+
+ServiceWorkers enable this by allowing `Cache`s to fetch and cache off-origin
+items. Some restrictions apply, however. First, unlike same-origin resources
+which are managed in the `Cache` as `[Promise][1]`s for `Response` instances,
+the objects stored are `[Promise][1]`s for `OpaqueResponse` instances.
+`OpaqueResponse` provides a much less expressive API than `Response`; the
+bodies and headers cannot be read or set, nor many of the other aspects of
+their content inspected. They can be passed to `respondWith()` and
+`forwardTo()` in the same manner as `Response`s, but cannot be meaningfully
+created programmatically. These limitations are necessary to preserve the
+security invariants of the platform. Allowing `Cache`s to store them allows
+applications to avoid re-architecting in most cases.
+
+
+
+[1]: http://goo.gl/3TobQS
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section Cross-Origin Resources & CORS so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/src/third_party/web_platform_tests/service-workers/tools/blink-import.py b/src/third_party/web_platform_tests/service-workers/tools/blink-import.py
new file mode 100644
index 0000000..87ca221
--- /dev/null
+++ b/src/third_party/web_platform_tests/service-workers/tools/blink-import.py
@@ -0,0 +1,204 @@
+import os
+import re
+import shutil
+import glob
+import tempfile
+import sys
+from collections import defaultdict
+
+here = os.path.abspath(os.path.split(__file__)[0])
+
+def get_extra_files(chromium_root):
+ return [(os.path.join(chromium_root, "LayoutTests", "http", "tests", "resources", "testharness-helpers.js"),
+ os.path.join("resources", "testharness-helpers.js"))]
+
+resources_re = re.compile("/?(?:\.\./)*resources/(testharness(?:report)?)\.js")
+
+def resources_path(line, depth):
+ return False, resources_re.sub(r"/resources/\1.js", line)
+
+php_re = re.compile("\.php")
+
+def python_to_php(line, depth):
+ return False, php_re.sub(".py", line)
+
+abs_testharness_helpers_re = re.compile("([\"'])/resources/testharness-helpers.js")
+testharness_helpers_re = re.compile("\.\./((?:\.\./)*)resources/testharness-helpers.js")
+
+def testharness_helpers(line, depth):
+ if abs_testharness_helpers_re.findall(line):
+ return False, abs_testharness_helpers_re.sub(r"\1%sresources/testharness-helpers.js" % ("../" * (depth - 1)), line)
+ return False, testharness_helpers_re.sub(r"\1resources/testharness-helpers.js", line)
+
+serviceworker_path_re = re.compile("/serviceworker/")
+def service_worker_path(line, depth):
+ return False, serviceworker_path_re.sub("/service-workers/", line)
+
+localhost_re = re.compile("localhost")
+alt_host_re = re.compile("127\.0\.0\.1")
+port_http_re = re.compile("8000")
+port_https_re = re.compile("8000")
+
+
+def server_names(line, depth):
+ line, count_0 = localhost_re.subn("{{host}}", line)
+ line, count_1 = alt_host_re.subn("{{domains[www]}}", line)
+ line, count_2 = port_http_re.subn("{{ports[http][0]}}", line)
+ line, count_3 = port_https_re.subn("{{ports[https][0]}}", line)
+
+ count = count_0 + count_1 + count_2 + count_3
+
+ return bool(count), line
+
+
+def source_paths(chromium_root):
+ for dirpath, dirnames, filenames in os.walk(chromium_root):
+ if "chromium" in dirnames:
+ dirnames.remove("chromium")
+ for filename in filenames:
+ if filename.endswith("-expected.txt") or filename.endswith(".php"):
+ continue
+ yield os.path.relpath(os.path.join(dirpath, filename), chromium_root)
+
+
+def do_subs(path, line):
+ depth = len(os.path.split(os.path.sep))
+ subs = [resources_path, python_to_php, testharness_helpers, service_worker_path, server_names]
+ file_is_template = False
+ for sub in subs:
+ added_template, line = sub(line, depth)
+ if added_template:
+ file_is_template = True
+ return file_is_template, line
+
+def get_head(git):
+ return git("rev-parse", "HEAD")
+
+def get_changes(git, path, old, new):
+ data = git("diff", "--name-status", "-z", "--no-renames", "%s..%s" % (old, new), "--", path)
+ items = data.split("\0")
+ rv = defaultdict(list)
+ for status, path in items:
+ rv[status].append(path)
+
+ return rv
+
+def copy(src_path, out_dir, rel_path):
+ dest = os.path.normpath(os.path.join(out_dir, rel_path))
+ dest_dir = os.path.split(dest)[0]
+ if not os.path.exists(dest_dir):
+ os.makedirs(dest_dir)
+ shutil.copy2(src_path, dest)
+
+def copy_local_files(local_files, out_root, tmp_dir):
+ for path in local_files:
+ rel_path = os.path.relpath(path, out_root)
+ copy(path, tmp_dir, rel_path)
+
+def copy_extra_files(chromium_root, tmp_dir):
+ for in_path, rel_path in get_extra_files(chromium_root):
+ copy(in_path, tmp_dir, rel_path)
+
+def sub_changed_filenames(filename_changes, f):
+ rv = []
+ for line in f:
+ for in_name, out_name in filename_changes.iteritems():
+ line = line.replace(in_name, out_name)
+ rv.append(line)
+ return "".join(rv)
+
+testharness_re = re.compile("<script[^>]*src=[\"']?/resources/testharness.js[\"' ][^>]*>")
+
+def is_top_level_test(path, data):
+ if os.path.splitext(path)[1] != ".html":
+ return False
+ for line in data:
+ if testharness_re.findall(line):
+ return True
+ return False
+
+def add_suffix(path, suffix):
+ root, ext = os.path.splitext(path)
+ return root + ".%s" % suffix + ext
+
+def main():
+ if "--cache-tests" in sys.argv:
+ sw_path = os.path.join("LayoutTests", "http", "tests", "cachestorage")
+ out_root = os.path.abspath(os.path.join(here, "..", "cache-storage"))
+ elif "--sw-tests" in sys.argv:
+ sw_path = os.path.join("LayoutTests", "http", "tests", "serviceworkers")
+ out_root = os.path.abspath(os.path.join(here, "..", "service-worker"))
+ else:
+ raise ValueError("Must supply either --cache-tests or --sw-tests")
+
+ chromium_root = os.path.abspath(sys.argv[1])
+
+ work_path = tempfile.mkdtemp()
+
+ test_path = os.path.join(chromium_root, sw_path)
+
+ local_files = glob.glob(os.path.normpath(os.path.join(here, "..", "resources", "*.py")))
+
+ if not os.path.exists(out_root):
+ os.mkdir(out_root)
+
+ copy_local_files(local_files, out_root, work_path)
+ copy_extra_files(chromium_root, work_path)
+
+ path_changes = {}
+
+ for path in source_paths(test_path):
+ out_path = os.path.join(work_path, path)
+ out_dir = os.path.dirname(out_path)
+ if not os.path.exists(out_dir):
+ os.makedirs(out_dir)
+ with open(os.path.join(test_path, path)) as in_f:
+ data = []
+ sub = False
+ for line in in_f:
+ sub_flag, output_line = do_subs(path, line)
+ data.append(output_line)
+ if sub_flag:
+ sub = True
+ is_test = is_top_level_test(out_path, data)
+
+ initial_path = out_path
+
+ if is_test:
+ path_1 = add_suffix(out_path, "https")
+ else:
+ path_1 = out_path
+
+ if sub:
+ path_2 = add_suffix(out_path, "sub")
+ else:
+ path_2 = path_1
+
+ if path_2 != initial_path:
+ path_changes[initial_path] = path_2
+
+ with open(path_2, "w") as out_f:
+ out_f.write("".join(data))
+
+ filename_changes = {}
+
+ for k, v in path_changes.iteritems():
+ if os.path.basename(k) in filename_changes:
+ print "Got duplicate name:" + os.path.basename(k)
+ filename_changes[os.path.basename(k)] = os.path.basename(v)
+
+ for path in source_paths(work_path):
+ full_path = os.path.join(work_path, path)
+ with open(full_path) as f:
+ data = sub_changed_filenames(filename_changes, f)
+ with open(full_path, "w") as f:
+ f.write(data)
+
+ for dirpath, dirnames, filenames in os.walk(work_path):
+ for filename in filenames:
+ in_path = os.path.join(dirpath, filename)
+ rel_path = os.path.relpath(in_path, work_path)
+ copy(in_path, out_root, rel_path)
+
+if __name__ == "__main__":
+ main()