mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-16 20:27:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
1
testing/web-platform/tests/service-workers/OWNERS
Normal file
1
testing/web-platform/tests/service-workers/OWNERS
Normal file
|
|
@ -0,0 +1 @@
|
|||
@ehsan
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
@inexorabletash
|
||||
@wanderview
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache Storage: Verify that Window and Workers see same storage</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Empty doc</title>
|
||||
|
|
@ -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');
|
||||
});
|
||||
};
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Controlled frame for Cache API test with credentials</title>
|
||||
<script>
|
||||
|
||||
function xhr(url, username, password) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var xhr = new XMLHttpRequest(), async = true;
|
||||
xhr.open('GET', url, async, username, password);
|
||||
xhr.send();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState !== XMLHttpRequest.DONE)
|
||||
return;
|
||||
if (xhr.status === 200) {
|
||||
resolve(xhr.responseText);
|
||||
} else {
|
||||
reject(new Error(xhr.statusText));
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
window.onmessage = function(e) {
|
||||
Promise.all(e.data.map(function(item) {
|
||||
return xhr(item.name, item.username, item.password);
|
||||
}))
|
||||
.then(function() {
|
||||
navigator.serviceWorker.controller.postMessage('keys');
|
||||
navigator.serviceWorker.onmessage = function(e) {
|
||||
window.parent.postMessage(e.data, '*');
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
</script>
|
||||
<body>
|
||||
Hello? Yes, this is iframe.
|
||||
</body>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
var cache_name = 'credentials';
|
||||
|
||||
function assert_equals(actual, expected, message) {
|
||||
if (!Object.is(actual, expected))
|
||||
throw Error(message + ': expected: ' + expected + ', actual: ' + actual);
|
||||
}
|
||||
|
||||
self.onfetch = function(e) {
|
||||
if (!/\.txt$/.test(e.request.url)) return;
|
||||
var content = e.request.url;
|
||||
var cache;
|
||||
e.respondWith(
|
||||
self.caches.open(cache_name)
|
||||
.then(function(result) {
|
||||
cache = result;
|
||||
return cache.put(e.request, new Response(content));
|
||||
})
|
||||
|
||||
.then(function() { return cache.match(e.request); })
|
||||
.then(function(result) { return result.text(); })
|
||||
.then(function(text) {
|
||||
assert_equals(text, content, 'Cache.match() body should match');
|
||||
})
|
||||
|
||||
.then(function() { return cache.matchAll(e.request); })
|
||||
.then(function(results) {
|
||||
assert_equals(results.length, 1, 'Should have one response');
|
||||
return results[0].text();
|
||||
})
|
||||
.then(function(text) {
|
||||
assert_equals(text, content, 'Cache.matchAll() body should match');
|
||||
})
|
||||
|
||||
.then(function() { return self.caches.match(e.request); })
|
||||
.then(function(result) { return result.text(); })
|
||||
.then(function(text) {
|
||||
assert_equals(text, content, 'CacheStorage.match() body should match');
|
||||
})
|
||||
|
||||
.then(function() {
|
||||
return new Response('dummy');
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
self.onmessage = function(e) {
|
||||
if (e.data === 'keys') {
|
||||
self.caches.open(cache_name)
|
||||
.then(function(cache) { return cache.keys(); })
|
||||
.then(function(requests) {
|
||||
var urls = requests.map(function(request) { return request.url; });
|
||||
self.clients.matchAll().then(function(clients) {
|
||||
clients.forEach(function(client) {
|
||||
client.postMessage(urls);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
def main(request, response):
|
||||
return int(request.GET["status"]), [], ""
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1 @@
|
|||
a simple text file
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
(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);
|
||||
}
|
||||
|
||||
// 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('')
|
||||
},
|
||||
|
||||
{
|
||||
name: 'non_2xx_response',
|
||||
request: new Request('http://example.com/non2xx'),
|
||||
response: new Response('', {status: 404, statusText: 'nope'})
|
||||
},
|
||||
|
||||
{
|
||||
name: 'error_response',
|
||||
request: new Request('http://example.com/error'),
|
||||
response: Response.error()
|
||||
},
|
||||
];
|
||||
|
||||
// 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'}})
|
||||
}
|
||||
];
|
||||
|
||||
// Run |test_function| with a Cache object and a map of entries. 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 = {};
|
||||
return Promise.all(entries.map(function(entry) {
|
||||
hash[entry.name] = entry;
|
||||
return cache.put(entry.request.clone(),
|
||||
entry.response.clone())
|
||||
.catch(function(e) {
|
||||
assert_unreached(
|
||||
'Test setup failed for entry ' + entry.name + ': ' + e);
|
||||
});
|
||||
}))
|
||||
.then(function() {
|
||||
assert_equals(Object.keys(hash).length, entries.length);
|
||||
})
|
||||
.then(function() {
|
||||
return test_function(cache, hash);
|
||||
});
|
||||
}, 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;
|
||||
var actual_headers = [];
|
||||
var 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);
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
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.');
|
||||
return cache.match('../resources/simple.txt');
|
||||
})
|
||||
.then(function(response) {
|
||||
assert_class_string(response, 'Response',
|
||||
'Cache.add should put a resource in the cache.');
|
||||
return response.text();
|
||||
})
|
||||
.then(function(body) {
|
||||
assert_equals(body, 'a simple text file\n',
|
||||
'Cache.add should retrieve the correct body.');
|
||||
});
|
||||
}, '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',
|
||||
{method: 'POST', body: 'This is a body.'});
|
||||
return assert_promise_rejects(
|
||||
cache.add(request),
|
||||
new TypeError(),
|
||||
'Cache.add should throw a TypeError for non-GET requests.');
|
||||
}, 'Cache.add called with POST request');
|
||||
|
||||
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) {
|
||||
var request = new Request('../resources/simple.txt');
|
||||
return request.text()
|
||||
.then(function() {
|
||||
assert_false(request.bodyUsed);
|
||||
})
|
||||
.then(function() {
|
||||
return cache.add(request);
|
||||
});
|
||||
}, 'Cache.add with request with null body (not consumed)');
|
||||
|
||||
cache_test(function(cache) {
|
||||
return assert_promise_rejects(
|
||||
cache.add('this-does-not-exist-please-dont-create-it'),
|
||||
new TypeError(),
|
||||
'Cache.add should reject if response is !ok');
|
||||
}, 'Cache.add with request that results in a status of 404');
|
||||
|
||||
cache_test(function(cache) {
|
||||
return assert_promise_rejects(
|
||||
cache.add('../resources/fetch-status.php?status=500'),
|
||||
new TypeError(),
|
||||
'Cache.add should reject if response is !ok');
|
||||
}, '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) {
|
||||
return cache.addAll([])
|
||||
.then(function(result) {
|
||||
assert_equals(result, undefined,
|
||||
'Cache.addAll should resolve with undefined on ' +
|
||||
'success.');
|
||||
return cache.keys();
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_equals(result.length, 0,
|
||||
'There should be no entry in the cache.');
|
||||
});
|
||||
}, 'Cache.addAll with an empty array');
|
||||
|
||||
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.');
|
||||
return Promise.all(
|
||||
urls.map(function(url) { return cache.match(url); }));
|
||||
})
|
||||
.then(function(responses) {
|
||||
assert_class_string(
|
||||
responses[0], 'Response',
|
||||
'Cache.addAll should put a resource in the cache.');
|
||||
assert_class_string(
|
||||
responses[1], 'Response',
|
||||
'Cache.addAll should put a resource in the cache.');
|
||||
assert_class_string(
|
||||
responses[2], 'Response',
|
||||
'Cache.addAll should put a resource in the cache.');
|
||||
return Promise.all(
|
||||
responses.map(function(response) { return response.text(); }));
|
||||
})
|
||||
.then(function(bodies) {
|
||||
assert_equals(
|
||||
bodies[0], 'a simple text file\n',
|
||||
'Cache.add should retrieve the correct body.');
|
||||
assert_equals(
|
||||
bodies[2], '<!DOCTYPE html>\n<title>Empty doc</title>\n',
|
||||
'Cache.add should retrieve the correct body.');
|
||||
});
|
||||
}, '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.');
|
||||
return Promise.all(
|
||||
urls.map(function(url) { return cache.match(url); }));
|
||||
})
|
||||
.then(function(responses) {
|
||||
assert_class_string(
|
||||
responses[0], 'Response',
|
||||
'Cache.addAll should put a resource in the cache.');
|
||||
assert_class_string(
|
||||
responses[1], 'Response',
|
||||
'Cache.addAll should put a resource in the cache.');
|
||||
assert_class_string(
|
||||
responses[2], 'Response',
|
||||
'Cache.addAll should put a resource in the cache.');
|
||||
return Promise.all(
|
||||
responses.map(function(response) { return response.text(); }));
|
||||
})
|
||||
.then(function(bodies) {
|
||||
assert_equals(
|
||||
bodies[0], 'a simple text file\n',
|
||||
'Cache.add should retrieve the correct body.');
|
||||
assert_equals(
|
||||
bodies[2], '<!DOCTYPE html>\n<title>Empty doc</title>\n',
|
||||
'Cache.add should retrieve the correct body.');
|
||||
});
|
||||
}, '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 assert_promise_rejects(
|
||||
cache.addAll(requests),
|
||||
new TypeError(),
|
||||
'Cache.addAll should reject with TypeError if any request fails')
|
||||
.then(function() {
|
||||
return Promise.all(urls.map(function(url) { return cache.match(url); }));
|
||||
})
|
||||
.then(function(matches) {
|
||||
assert_array_equals(
|
||||
matches,
|
||||
[undefined, undefined, undefined],
|
||||
'If any response fails, no response should be added to cache');
|
||||
});
|
||||
}, '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();
|
||||
|
|
@ -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();
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
if (self.importScripts) {
|
||||
importScripts('/resources/testharness.js');
|
||||
importScripts('../resources/testharness-helpers.js');
|
||||
importScripts('../resources/test-helpers.js');
|
||||
}
|
||||
|
||||
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.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.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.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.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.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.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.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.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');
|
||||
|
||||
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.clone(), {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');
|
||||
|
||||
prepopulated_cache_test(simple_entries, function(cache, entries) {
|
||||
var response = entries.non_2xx_response.response;
|
||||
return cache.match(entries.non_2xx_response.request.url)
|
||||
.then(function(result) {
|
||||
assert_response_equals(
|
||||
result, entries.non_2xx_response.response,
|
||||
'Cache.match should return a Response object that has the ' +
|
||||
'same properties as a stored non-2xx response.');
|
||||
});
|
||||
}, 'Cache.match with a non-2xx Response');
|
||||
|
||||
prepopulated_cache_test(simple_entries, function(cache, entries) {
|
||||
var response = entries.error_response.response;
|
||||
return cache.match(entries.error_response.request.url)
|
||||
.then(function(result) {
|
||||
assert_response_equals(
|
||||
result, entries.error_response.response,
|
||||
'Cache.match should return a Response object that has the ' +
|
||||
'same properties as a stored network error response.');
|
||||
});
|
||||
}, 'Cache.match with a network error Response');
|
||||
|
||||
done();
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
if (self.importScripts) {
|
||||
importScripts('/resources/testharness.js');
|
||||
importScripts('../resources/testharness-helpers.js');
|
||||
importScripts('../resources/test-helpers.js');
|
||||
}
|
||||
|
||||
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.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.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.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.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.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.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.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(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.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');
|
||||
|
||||
done();
|
||||
|
|
@ -0,0 +1,305 @@
|
|||
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 make the body disturbed.');
|
||||
var request = new Request(test_url);
|
||||
return cache.put(request, response).then(() => {
|
||||
assert_unreached('cache.put should be rejected');
|
||||
}, () => {});
|
||||
});
|
||||
}, 'Cache.put with a used response body');
|
||||
|
||||
cache_test(function(cache) {
|
||||
var response = new Response(test_body);
|
||||
return cache.put(new Request(test_url), response)
|
||||
.then(function() {
|
||||
assert_throws(new TypeError(), () => response.body.getReader());
|
||||
});
|
||||
}, 'getReader() after Cache.put');
|
||||
|
||||
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');
|
||||
|
||||
cache_test(function(cache) {
|
||||
var url = 'foo.html';
|
||||
var redirectURL = 'http://example.com/foo-bar.html';
|
||||
var redirectResponse = Response.redirect(redirectURL);
|
||||
assert_equals(redirectResponse.headers.get('Location'), redirectURL,
|
||||
'Response.redirect() should set Location header.');
|
||||
return cache.put(url, redirectResponse.clone())
|
||||
.then(function() {
|
||||
return cache.match(url);
|
||||
})
|
||||
.then(function(response) {
|
||||
assert_response_equals(response, redirectResponse,
|
||||
'Redirect response is reproduced by the Cache API');
|
||||
assert_equals(response.headers.get('Location'), redirectURL,
|
||||
'Location header is preserved by Cache API.');
|
||||
});
|
||||
}, 'Cache.put should store Response.redirect() correctly');
|
||||
|
||||
done();
|
||||
|
|
@ -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();
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
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_equals(response, undefined,
|
||||
'The match with bad cache name should resolve to ' +
|
||||
'undefined.');
|
||||
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();
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
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 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();
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache.add and Cache.addAll</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#cache-add">
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
service_worker_test('../script-tests/cache-add.js');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache.delete</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#cache-delete">
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
service_worker_test('../script-tests/cache-delete.js');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache.match</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#cache-match">
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
service_worker_test('../script-tests/cache-match.js');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache.matchAll</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#cache-matchall">
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
service_worker_test('../script-tests/cache-matchAll.js');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache.put</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#cache-put">
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
service_worker_test('../script-tests/cache-put.js');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CacheStorage.keys</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#cache-storage">
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
service_worker_test('../script-tests/cache-storage-keys.js');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CacheStorage.match</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#cache-storage-match">
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
service_worker_test('../script-tests/cache-storage-match.js');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CacheStorage</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#cache-storage">
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
service_worker_test('../script-tests/cache-storage.js');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Cache Storage: Verify credentials are respected by Cache operations</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#cache-storage">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||
<style>iframe { display: none; }</style>
|
||||
<script>
|
||||
|
||||
var worker = "../resources/credentials-worker.js";
|
||||
var scope = "../resources/credentials-iframe.html";
|
||||
promise_test(function(t) {
|
||||
return self.caches.delete('credentials')
|
||||
.then(function() {
|
||||
return service_worker_unregister_and_register(t, worker, scope)
|
||||
})
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(function(frame) {
|
||||
frame.contentWindow.postMessage([
|
||||
{name: 'file.txt', username: 'aa', password: 'bb'},
|
||||
{name: 'file.txt', username: 'cc', password: 'dd'},
|
||||
{name: 'file.txt'}
|
||||
], '*');
|
||||
return new Promise(function(resolve, reject) {
|
||||
window.onmessage = t.step_func(function(e) {
|
||||
resolve(e.data);
|
||||
});
|
||||
});
|
||||
})
|
||||
.then(function(data) {
|
||||
assert_equals(data.length, 3, 'three entries should be present');
|
||||
assert_equals(data.filter(function(url) { return /@/.test(url); }).length, 2,
|
||||
'two entries should contain credentials');
|
||||
assert_true(data.some(function(url) { return /aa:bb@/.test(url); }),
|
||||
'entry with credentials aa:bb should be present');
|
||||
assert_true(data.some(function(url) { return /cc:dd@/.test(url); }),
|
||||
'entry with credentials cc:dd should be present');
|
||||
});
|
||||
}, "Cache API matching includes credentials");
|
||||
</script>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache Storage: Cache.add and Cache.addAll</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache Storage: Cache.delete</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache Storage: Cache.match</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache.matchAll</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#cache-matchall">
|
||||
<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-matchAll.js"></script>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache Storage: Cache.put</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache Storage: CacheStorage.keys</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache Storage: CacheStorage.match</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache Storage: CacheStorage</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache Storage: Verify access in sandboxed iframes</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache.add and Cache.addAll</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache.delete</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache.match</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache.matchAll</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#cache-matchall">
|
||||
<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-matchAll.js'));
|
||||
</script>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cache.put</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CacheStorage.keys</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CacheStorage.match</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CacheStorage</title>
|
||||
<link rel="help" href="https://w3c.github.io/ServiceWorker/#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>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<title>ServiceWorkerGlobalScope: registration</title>
|
||||
<script src='/resources/testharness.js'></script>
|
||||
<script src='/resources/testharnessreport.js'></script>
|
||||
<script src='../resources/test-helpers.sub.js'></script>
|
||||
<script>
|
||||
|
||||
promise_test(function(t) {
|
||||
var script = 'resources/registration-attribute-worker.js';
|
||||
var scope = 'resources/scope/registration-attribute';
|
||||
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(frame) {
|
||||
var expected_events_seen = [
|
||||
'updatefound',
|
||||
'install',
|
||||
'statechange(installed)',
|
||||
'statechange(activating)',
|
||||
'activate',
|
||||
'statechange(activated)',
|
||||
'fetch',
|
||||
];
|
||||
|
||||
assert_equals(
|
||||
frame.contentDocument.body.textContent,
|
||||
expected_events_seen.toString(),
|
||||
'Service Worker should respond to fetch');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
});
|
||||
}, 'Verify registration attribute on ServiceWorkerGlobalScope');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
importScripts('../../resources/test-helpers.sub.js');
|
||||
importScripts('../../resources/worker-testharness.js');
|
||||
|
||||
var events_seen = [];
|
||||
|
||||
assert_equals(
|
||||
self.registration.scope,
|
||||
normalizeURL('scope/registration-attribute'),
|
||||
'On worker script evaluation, registration attribute should be set');
|
||||
assert_equals(
|
||||
self.registration.installing,
|
||||
null,
|
||||
'On worker script evaluation, installing worker should be null');
|
||||
assert_equals(
|
||||
self.registration.waiting,
|
||||
null,
|
||||
'On worker script evaluation, waiting worker should be null');
|
||||
assert_equals(
|
||||
self.registration.active,
|
||||
null,
|
||||
'On worker script evaluation, active worker should be null');
|
||||
|
||||
self.registration.addEventListener('updatefound', function() {
|
||||
events_seen.push('updatefound');
|
||||
|
||||
assert_equals(
|
||||
self.registration.scope,
|
||||
normalizeURL('scope/registration-attribute'),
|
||||
'On updatefound event, registration attribute should be set');
|
||||
assert_equals(
|
||||
self.registration.installing.scriptURL,
|
||||
normalizeURL('registration-attribute-worker.js'),
|
||||
'On updatefound event, installing worker should be set');
|
||||
assert_equals(
|
||||
self.registration.waiting,
|
||||
null,
|
||||
'On updatefound event, waiting worker should be null');
|
||||
assert_equals(
|
||||
self.registration.active,
|
||||
null,
|
||||
'On updatefound event, active worker should be null');
|
||||
|
||||
assert_equals(
|
||||
self.registration.installing.state,
|
||||
'installing',
|
||||
'On updatefound event, worker should be in the installing state');
|
||||
|
||||
var worker = self.registration.installing;
|
||||
self.registration.installing.addEventListener('statechange', function() {
|
||||
events_seen.push('statechange(' + worker.state + ')');
|
||||
});
|
||||
});
|
||||
|
||||
self.addEventListener('install', function(e) {
|
||||
events_seen.push('install');
|
||||
|
||||
assert_equals(
|
||||
self.registration.scope,
|
||||
normalizeURL('scope/registration-attribute'),
|
||||
'On install event, registration attribute should be set');
|
||||
assert_equals(
|
||||
self.registration.installing.scriptURL,
|
||||
normalizeURL('registration-attribute-worker.js'),
|
||||
'On install event, installing worker should be set');
|
||||
assert_equals(
|
||||
self.registration.waiting,
|
||||
null,
|
||||
'On install event, waiting worker should be null');
|
||||
assert_equals(
|
||||
self.registration.active,
|
||||
null,
|
||||
'On install event, active worker should be null');
|
||||
|
||||
assert_equals(
|
||||
self.registration.installing.state,
|
||||
'installing',
|
||||
'On install event, worker should be in the installing state');
|
||||
});
|
||||
|
||||
self.addEventListener('activate', function(e) {
|
||||
events_seen.push('activate');
|
||||
|
||||
assert_equals(
|
||||
self.registration.scope,
|
||||
normalizeURL('scope/registration-attribute'),
|
||||
'On activate event, registration attribute should be set');
|
||||
assert_equals(
|
||||
self.registration.installing,
|
||||
null,
|
||||
'On activate event, installing worker should be null');
|
||||
assert_equals(
|
||||
self.registration.waiting,
|
||||
null,
|
||||
'On activate event, waiting worker should be null');
|
||||
assert_equals(
|
||||
self.registration.active.scriptURL,
|
||||
normalizeURL('registration-attribute-worker.js'),
|
||||
'On activate event, active worker should be set');
|
||||
|
||||
assert_equals(
|
||||
self.registration.active.state,
|
||||
'activating',
|
||||
'On activate event, worker should be in the activating state');
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', function(e) {
|
||||
events_seen.push('fetch');
|
||||
|
||||
assert_equals(
|
||||
self.registration.scope,
|
||||
normalizeURL('scope/registration-attribute'),
|
||||
'On fetch event, registration attribute should be set');
|
||||
assert_equals(
|
||||
self.registration.installing,
|
||||
null,
|
||||
'On fetch event, installing worker should be null');
|
||||
assert_equals(
|
||||
self.registration.waiting,
|
||||
null,
|
||||
'On fetch event, waiting worker should be null');
|
||||
assert_equals(
|
||||
self.registration.active.scriptURL,
|
||||
normalizeURL('registration-attribute-worker.js'),
|
||||
'On fetch event, active worker should be set');
|
||||
|
||||
assert_equals(
|
||||
self.registration.active.state,
|
||||
'activated',
|
||||
'On fetch event, worker should be in the activated state');
|
||||
|
||||
e.respondWith(new Response(events_seen));
|
||||
});
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
function matchQuery(query) {
|
||||
return self.location.href.indexOf(query) != -1;
|
||||
}
|
||||
|
||||
if (matchQuery('?evaluation'))
|
||||
self.registration.unregister();
|
||||
|
||||
self.addEventListener('install', function(e) {
|
||||
if (matchQuery('?install'))
|
||||
self.registration.unregister();
|
||||
});
|
||||
|
||||
self.addEventListener('activate', function(e) {
|
||||
if (matchQuery('?activate'))
|
||||
self.registration.unregister();
|
||||
});
|
||||
|
||||
self.addEventListener('message', function(e) {
|
||||
self.registration.unregister()
|
||||
.then(function(result) {
|
||||
e.data.port.postMessage({result: result});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
importScripts('../../resources/test-helpers.sub.js');
|
||||
importScripts('../../resources/worker-testharness.js');
|
||||
|
||||
var events_seen = [];
|
||||
|
||||
self.registration.addEventListener('updatefound', function() {
|
||||
events_seen.push('updatefound');
|
||||
});
|
||||
|
||||
self.addEventListener('activate', function(e) {
|
||||
events_seen.push('activate');
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', function(e) {
|
||||
events_seen.push('fetch');
|
||||
e.respondWith(new Response(events_seen));
|
||||
});
|
||||
|
||||
self.addEventListener('message', function(e) {
|
||||
events_seen.push('message');
|
||||
self.registration.update();
|
||||
});
|
||||
|
||||
// update() during the script evaluation should be ignored.
|
||||
self.registration.update();
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import os
|
||||
import time
|
||||
|
||||
def main(request, response):
|
||||
# update() does not bypass cache so set the max-age to 0 such that update()
|
||||
# can find a new version in the network.
|
||||
headers = [('Cache-Control', 'max-age: 0'),
|
||||
('Content-Type', 'application/javascript')]
|
||||
with open(os.path.join(os.path.dirname(__file__),
|
||||
'update-worker.js'), 'r') as file:
|
||||
script = file.read()
|
||||
# Return a different script for each access.
|
||||
return headers, '// %s\n%s' % (time.time(), script)
|
||||
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
<!DOCTYPE html>
|
||||
<title>ServiceWorkerGlobalScope: unregister</title>
|
||||
<script src='/resources/testharness.js'></script>
|
||||
<script src='/resources/testharnessreport.js'></script>
|
||||
<script src='../resources/test-helpers.sub.js'></script>
|
||||
<script>
|
||||
|
||||
promise_test(function(t) {
|
||||
var script = 'resources/unregister-worker.js?evaluation';
|
||||
var scope = 'resources/scope/unregister-on-script-evaluation';
|
||||
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'redundant');
|
||||
})
|
||||
.then(function() {
|
||||
return navigator.serviceWorker.getRegistration(scope);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_equals(
|
||||
result,
|
||||
undefined,
|
||||
'After unregister(), the registration should not found');
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
});
|
||||
}, 'Unregister on script evaluation');
|
||||
|
||||
promise_test(function(t) {
|
||||
var script = 'resources/unregister-worker.js?install';
|
||||
var scope = 'resources/scope/unregister-on-install-event';
|
||||
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'redundant');
|
||||
})
|
||||
.then(function() {
|
||||
return navigator.serviceWorker.getRegistration(scope);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_equals(
|
||||
result,
|
||||
undefined,
|
||||
'After unregister(), the registration should not found');
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
});
|
||||
}, 'Unregister on installing event');
|
||||
|
||||
promise_test(function(t) {
|
||||
var script = 'resources/unregister-worker.js?activate';
|
||||
var scope = 'resources/scope/unregister-on-activate-event';
|
||||
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'redundant');
|
||||
})
|
||||
.then(function() {
|
||||
return navigator.serviceWorker.getRegistration(scope);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_equals(
|
||||
result,
|
||||
undefined,
|
||||
'After unregister(), the registration should not found');
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
});
|
||||
}, 'Unregister on activate event');
|
||||
|
||||
promise_test(function(t) {
|
||||
var script = 'resources/unregister-worker.js';
|
||||
var scope = 'resources/unregister-controlling-worker.html';
|
||||
|
||||
var controller;
|
||||
var frame;
|
||||
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
controller = frame.contentWindow.navigator.serviceWorker.controller;
|
||||
|
||||
assert_equals(
|
||||
controller.scriptURL,
|
||||
normalizeURL(script),
|
||||
'Service worker should control a new document')
|
||||
|
||||
// Wait for the completion of unregister() on the worker.
|
||||
var channel = new MessageChannel();
|
||||
var promise = new Promise(function(resolve) {
|
||||
channel.port1.onmessage = t.step_func(function(e) {
|
||||
assert_true(e.data.result,
|
||||
'unregister() should successfully finish');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
controller.postMessage({port: channel.port2}, [channel.port2]);
|
||||
return promise;
|
||||
})
|
||||
.then(function() {
|
||||
return navigator.serviceWorker.getRegistration(scope);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_equals(
|
||||
result,
|
||||
undefined,
|
||||
'After unregister(), the registration should not found');
|
||||
assert_equals(
|
||||
frame.contentWindow.navigator.serviceWorker.controller,
|
||||
controller,
|
||||
'After unregister(), the worker should still control the document');
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(function(new_frame) {
|
||||
assert_equals(
|
||||
new_frame.contentWindow.navigator.serviceWorker.controller,
|
||||
null,
|
||||
'After unregister(), the worker should not control a new document');
|
||||
|
||||
frame.remove();
|
||||
new_frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
}, 'Unregister controlling service worker');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<title>ServiceWorkerGlobalScope: update</title>
|
||||
<script src='/resources/testharness.js'></script>
|
||||
<script src='/resources/testharnessreport.js'></script>
|
||||
<script src='../resources/test-helpers.sub.js'></script>
|
||||
<script>
|
||||
|
||||
promise_test(function(t) {
|
||||
var script = 'resources/update-worker.py';
|
||||
var scope = 'resources/scope/update';
|
||||
var registration;
|
||||
var frame1;
|
||||
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(r) {
|
||||
registration = r;
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame1 = f;
|
||||
registration.active.postMessage('update');
|
||||
return wait_for_update(t, registration);
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(frame2) {
|
||||
var expected_events_seen = [
|
||||
'updatefound', // by register().
|
||||
'activate',
|
||||
'fetch',
|
||||
'message',
|
||||
'updatefound', // by update() in the message handler.
|
||||
'fetch',
|
||||
];
|
||||
assert_equals(
|
||||
frame2.contentDocument.body.textContent,
|
||||
expected_events_seen.toString(),
|
||||
'events seen by the worker');
|
||||
frame1.remove();
|
||||
frame2.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
});
|
||||
}, 'Update a registration on ServiceWorkerGlobalScope');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: registration events</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
promise_test(function(t) {
|
||||
var script = 'resources/empty-worker.js';
|
||||
var scope = 'resources/blank.html';
|
||||
var registration;
|
||||
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(registration) {
|
||||
var sw = registration.installing;
|
||||
|
||||
return new Promise(t.step_func(function(resolve) {
|
||||
sw.onstatechange = t.step_func(function() {
|
||||
if (sw.state === 'installed') {
|
||||
assert_equals(registration.active, null,
|
||||
'installed event should be fired before activating service worker');
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}));
|
||||
})
|
||||
.then(function() {
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'installed event should be fired before activating service worker');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Activation occurs after registration</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
var t = async_test('activation occurs after registration');
|
||||
t.step(function() {
|
||||
var scope = 'resources/blank.html';
|
||||
var registration;
|
||||
|
||||
service_worker_unregister_and_register(
|
||||
t, 'resources/empty-worker.js', scope)
|
||||
.then(function(r) {
|
||||
registration = r;
|
||||
assert_equals(
|
||||
r.installing.state,
|
||||
'installing',
|
||||
'worker should be in the "installing" state upon registration');
|
||||
return wait_for_state(t, r.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>service worker: activation</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
// Registers, waits for activation, then unregisters on a dummy scope.
|
||||
//
|
||||
// This helper can be used in tests that assert that activation doesn't happen.
|
||||
// It would not be sufficient to check the .waiting/.active properties once,
|
||||
// since activation could be scheduled and just hasn't happened yet. Since this
|
||||
// helper shows that activation of another registration completed, we can be
|
||||
// sure that activation really will not happen.
|
||||
function wait_for_activation_on_dummy_scope(t) {
|
||||
var dummy_scope = 'resources/there/is/no/there/there';
|
||||
var registration;
|
||||
return navigator.serviceWorker.register('resources/empty-worker.js',
|
||||
{ scope: dummy_scope })
|
||||
.then(r => {
|
||||
registration = r;
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(() => registration.unregister());
|
||||
}
|
||||
// Returns {registration, iframe}, where |registration| has an active and
|
||||
// waiting worker. The active worker controls |iframe| and has an inflight
|
||||
// message event that can be finished by calling
|
||||
// |registration.active.postMessage('go')|.
|
||||
function setup_activation_test(t, scope, worker_url) {
|
||||
var registration;
|
||||
var iframe;
|
||||
return navigator.serviceWorker.getRegistration(scope)
|
||||
.then(r => {
|
||||
if (r)
|
||||
return r.unregister();
|
||||
})
|
||||
.then(() => {
|
||||
// Create an in-scope iframe. Do this prior to registration to avoid
|
||||
// racing between an update triggered by navigation and the update()
|
||||
// call below.
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(f => {
|
||||
iframe = f;
|
||||
// Create an active worker.
|
||||
return navigator.serviceWorker.register(worker_url, { scope: scope });
|
||||
})
|
||||
.then(r => {
|
||||
registration = r;
|
||||
add_result_callback(() => registration.unregister());
|
||||
return wait_for_state(t, r.installing, 'activated');
|
||||
})
|
||||
.then(() => {
|
||||
// Check that the frame was claimed.
|
||||
assert_not_equals(
|
||||
iframe.contentWindow.navigator.serviceWorker.controller, null);
|
||||
// Create an in-flight request.
|
||||
registration.active.postMessage('wait');
|
||||
// Now there is both a controllee and an in-flight request.
|
||||
// Initiate an update.
|
||||
return registration.update();
|
||||
})
|
||||
.then(() => {
|
||||
// Wait for a waiting worker.
|
||||
return wait_for_state(t, registration.installing, 'installed');
|
||||
})
|
||||
.then(() => {
|
||||
return wait_for_activation_on_dummy_scope(t);
|
||||
})
|
||||
.then(() => {
|
||||
assert_not_equals(registration.waiting, null);
|
||||
assert_not_equals(registration.active, null);
|
||||
return Promise.resolve({registration: registration, iframe: iframe});
|
||||
});
|
||||
}
|
||||
promise_test(t => {
|
||||
var scope = 'resources/no-controllee';
|
||||
var worker_url = 'resources/mint-new-worker.py';
|
||||
var registration;
|
||||
var iframe;
|
||||
var new_worker;
|
||||
return setup_activation_test(t, scope, worker_url)
|
||||
.then(result => {
|
||||
registration = result.registration;
|
||||
iframe = result.iframe;
|
||||
// Finish the in-flight request.
|
||||
registration.active.postMessage('go');
|
||||
return wait_for_activation_on_dummy_scope(t);
|
||||
})
|
||||
.then(() => {
|
||||
// The new worker is still waiting. Remove the frame and it should
|
||||
// activate.
|
||||
new_worker = registration.waiting;
|
||||
assert_equals(new_worker.state, 'installed');
|
||||
var reached_active = wait_for_state(t, new_worker, 'activating');
|
||||
iframe.remove();
|
||||
return reached_active;
|
||||
})
|
||||
.then(() => {
|
||||
assert_equals(new_worker, registration.active);
|
||||
});
|
||||
}, 'loss of controllees triggers activation');
|
||||
promise_test(t => {
|
||||
var scope = 'resources/no-request';
|
||||
var worker_url = 'resources/mint-new-worker.py';
|
||||
var registration;
|
||||
var iframe;
|
||||
var new_worker;
|
||||
return setup_activation_test(t, scope, worker_url)
|
||||
.then(result => {
|
||||
registration = result.registration;
|
||||
iframe = result.iframe;
|
||||
// Remove the iframe.
|
||||
iframe.remove();
|
||||
return new Promise(resolve => setTimeout(resolve, 0));
|
||||
})
|
||||
.then(() => {
|
||||
// Finish the request.
|
||||
new_worker = registration.waiting;
|
||||
var reached_active = wait_for_state(t, new_worker, 'activating');
|
||||
registration.active.postMessage('go');
|
||||
return reached_active;
|
||||
})
|
||||
.then(() => {
|
||||
assert_equals(registration.active, new_worker);
|
||||
});
|
||||
}, 'finishing a request triggers activation');
|
||||
promise_test(t => {
|
||||
var scope = 'resources/skip-waiting';
|
||||
var worker_url = 'resources/mint-new-worker.py?skip-waiting';
|
||||
var registration;
|
||||
var new_worker;
|
||||
return setup_activation_test(t, scope, worker_url)
|
||||
.then(result => {
|
||||
registration = result.registration;
|
||||
// Finish the request. The iframe does not need to be removed because
|
||||
// skipWaiting() was called.
|
||||
new_worker = registration.waiting;
|
||||
var reached_active = wait_for_state(t, new_worker, 'activating');
|
||||
registration.active.postMessage('go');
|
||||
return reached_active;
|
||||
})
|
||||
.then(() => {
|
||||
assert_equals(registration.active, new_worker);
|
||||
});
|
||||
}, 'skipWaiting bypasses no controllee requirement');
|
||||
|
||||
// This test is not really about activation, but otherwise is very
|
||||
// similar to the other tests here.
|
||||
promise_test(t => {
|
||||
var scope = 'resources/unregister';
|
||||
var worker_url = 'resources/mint-new-worker.py';
|
||||
var registration;
|
||||
var iframe;
|
||||
var new_worker;
|
||||
return setup_activation_test(t, scope, worker_url)
|
||||
.then(result => {
|
||||
registration = result.registration;
|
||||
iframe = result.iframe;
|
||||
// Remove the iframe.
|
||||
iframe.remove();
|
||||
return registration.unregister();
|
||||
})
|
||||
.then(() => {
|
||||
// The unregister operation should wait for the active worker to
|
||||
// finish processing its events before clearing the registration.
|
||||
new_worker = registration.waiting;
|
||||
var reached_redundant = wait_for_state(t, new_worker, 'redundant');
|
||||
registration.active.postMessage('go');
|
||||
return reached_redundant;
|
||||
})
|
||||
.then(() => {
|
||||
assert_equals(registration.installing, null);
|
||||
assert_equals(registration.waiting, null);
|
||||
assert_equals(registration.active, null);
|
||||
});
|
||||
}, 'finishing a request triggers unregister');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<!DOCTYPE html>
|
||||
<title>ServiceWorker: navigator.serviceWorker.active</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
// "active" is set
|
||||
async_test(function(t) {
|
||||
var step = t.step_func.bind(t);
|
||||
var url = 'resources/empty-worker.js';
|
||||
var scope = 'resources/blank.html';
|
||||
var frame;
|
||||
var registration;
|
||||
|
||||
service_worker_unregister(t, scope)
|
||||
.then(step(function() { return with_iframe(scope); }))
|
||||
.then(step(function(f) {
|
||||
frame = f;
|
||||
return navigator.serviceWorker.register(url, {scope: scope});
|
||||
}))
|
||||
.then(step(function(r) {
|
||||
registration = r;
|
||||
return wait_for_state(t, r.installing, 'activating');
|
||||
}))
|
||||
.then(step(function() {
|
||||
var container = frame.contentWindow.navigator.serviceWorker;
|
||||
assert_equals(
|
||||
container.controller,
|
||||
null,
|
||||
'On activating state a document should not have a controller');
|
||||
assert_equals(
|
||||
registration.active.scriptURL,
|
||||
normalizeURL(url),
|
||||
'On activating state a document should have an active worker ');
|
||||
assert_equals(
|
||||
registration.waiting,
|
||||
null,
|
||||
'On activating state a document should not have a waiting worker');
|
||||
assert_equals(
|
||||
registration.installing,
|
||||
null,
|
||||
'On activating state a document should not have an installing ' +
|
||||
'worker');
|
||||
|
||||
// FIXME: Add a test for a frame created after installation.
|
||||
// Should the existing frame ("frame") block activation?
|
||||
}))
|
||||
.then(step(function() {
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
}))
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'active is set');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
var INSTALL_APPCACHE_URL = "resources/appcache-ordering.install.html";
|
||||
var IS_APPCACHED_URL = "resources/appcache-ordering.is-appcached.html";
|
||||
var SERVICE_WORKER_SCOPE = "resources/appcache-ordering";
|
||||
var SERVICE_WORKER_SCRIPT = "resources/empty-worker.js";
|
||||
|
||||
var resolve_install_appcache = undefined;
|
||||
var reject_install_appcache = undefined;
|
||||
|
||||
var frames = [];
|
||||
|
||||
// Called by the INSTALL_APPCACHE_URL child frame.
|
||||
function notify_appcache_installed(success) {
|
||||
if (success)
|
||||
resolve_install_appcache();
|
||||
else
|
||||
reject_install_appcache();
|
||||
}
|
||||
|
||||
function install_appcache() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var frame = document.createElement('iframe');
|
||||
frames.push(frame);
|
||||
frame.src = INSTALL_APPCACHE_URL;
|
||||
document.body.appendChild(frame);
|
||||
resolve_install_appcache = function() {
|
||||
document.body.removeChild(frame);
|
||||
resolve();
|
||||
};
|
||||
reject_install_appcache = function() {
|
||||
document.body.removeChild(frame);
|
||||
reject();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
var resolve_is_appcached = undefined;
|
||||
|
||||
// Called by the IS_APPCACHED_URL child frame.
|
||||
function notify_is_appcached(is) {
|
||||
resolve_is_appcached(is);
|
||||
}
|
||||
|
||||
function is_appcached() {
|
||||
return new Promise(function(resolve) {
|
||||
var frame = document.createElement('iframe');
|
||||
frames.push(frame);
|
||||
frame.src = IS_APPCACHED_URL;
|
||||
document.body.appendChild(frame);
|
||||
resolve_is_appcached = function(is) {
|
||||
document.body.removeChild(frame);
|
||||
resolve(is);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
service_worker_unregister(t, SERVICE_WORKER_SCOPE)
|
||||
.then(function() {
|
||||
return install_appcache();
|
||||
})
|
||||
.then(function() {
|
||||
return is_appcached();
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_true(result, 'appcache should initially be utilized');
|
||||
return service_worker_unregister_and_register(
|
||||
t, SERVICE_WORKER_SCRIPT, SERVICE_WORKER_SCOPE);
|
||||
})
|
||||
.then(function(r) {
|
||||
return wait_for_state(t, r.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return is_appcached();
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_false(result, 'but serviceworkers should take priority');
|
||||
frames.forEach(function(f) { f.remove(); });
|
||||
service_worker_unregister_and_done(t, SERVICE_WORKER_SCOPE);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'serviceworkers take priority over appcaches');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: claim client not using registration</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="resources/testharness-helpers.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
promise_test(function(t) {
|
||||
var init_scope = 'resources/blank.html?not-using-init';
|
||||
var claim_scope = 'resources/blank.html?not-using';
|
||||
var init_worker_url = 'resources/empty.js';
|
||||
var claim_worker_url = 'resources/claim-worker.js';
|
||||
var claim_worker, claim_registration, frame1, frame2;
|
||||
return service_worker_unregister_and_register(
|
||||
t, init_worker_url, init_scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return Promise.all(
|
||||
[with_iframe(init_scope), with_iframe(claim_scope)]);
|
||||
})
|
||||
.then(function(frames) {
|
||||
frame1 = frames[0];
|
||||
frame2 = frames[1];
|
||||
assert_equals(
|
||||
frame1.contentWindow.navigator.serviceWorker.controller.scriptURL,
|
||||
normalizeURL(init_worker_url),
|
||||
'Frame1 controller should not be null');
|
||||
assert_equals(
|
||||
frame2.contentWindow.navigator.serviceWorker.controller, null,
|
||||
'Frame2 controller should be null');
|
||||
return navigator.serviceWorker.register(claim_worker_url,
|
||||
{scope: claim_scope});
|
||||
})
|
||||
.then(function(registration) {
|
||||
claim_worker = registration.installing;
|
||||
claim_registration = registration;
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
var saw_controllerchanged = new Promise(function(resolve) {
|
||||
frame2.contentWindow.navigator.serviceWorker.oncontrollerchange =
|
||||
function() { resolve(); }
|
||||
});
|
||||
var channel = new MessageChannel();
|
||||
var saw_message = new Promise(function(resolve) {
|
||||
channel.port1.onmessage = t.step_func(function(e) {
|
||||
assert_equals(e.data, 'PASS',
|
||||
'Worker call to claim() should fulfill.');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
claim_worker.postMessage({port: channel.port2}, [channel.port2]);
|
||||
return Promise.all([saw_controllerchanged, saw_message]);
|
||||
})
|
||||
.then(function() {
|
||||
assert_equals(
|
||||
frame1.contentWindow.navigator.serviceWorker.controller.scriptURL,
|
||||
normalizeURL(init_worker_url),
|
||||
'Frame1 should not be influenced');
|
||||
assert_equals(
|
||||
frame2.contentWindow.navigator.serviceWorker.controller.scriptURL,
|
||||
normalizeURL(claim_worker_url),
|
||||
'Frame2 should be controlled by the new registration');
|
||||
frame1.remove();
|
||||
frame2.remove();
|
||||
return claim_registration.unregister();
|
||||
})
|
||||
.then(function() {
|
||||
return service_worker_unregister_and_done(t, init_scope);
|
||||
});
|
||||
}, 'Test claim client which is not using registration');
|
||||
|
||||
promise_test(function(t) {
|
||||
var scope = 'resources/blank.html?longer-matched';
|
||||
var claim_scope = 'resources/blank.html?longer';
|
||||
var claim_worker_url = 'resources/claim-worker.js';
|
||||
var installing_worker_url = 'resources/empty-worker.js';
|
||||
var frame, claim_worker;
|
||||
return with_iframe(scope)
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return navigator.serviceWorker.register(
|
||||
claim_worker_url, {scope: claim_scope});
|
||||
})
|
||||
.then(function(registration) {
|
||||
claim_worker = registration.installing;
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return navigator.serviceWorker.register(
|
||||
installing_worker_url, {scope: scope});
|
||||
})
|
||||
.then(function() {
|
||||
var channel = new MessageChannel();
|
||||
var saw_message = new Promise(function(resolve) {
|
||||
channel.port1.onmessage = t.step_func(function(e) {
|
||||
assert_equals(e.data, 'PASS',
|
||||
'Worker call to claim() should fulfill.');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
claim_worker.postMessage({port: channel.port2}, [channel.port2]);
|
||||
return saw_message;
|
||||
})
|
||||
.then(function() {
|
||||
assert_equals(
|
||||
frame.contentWindow.navigator.serviceWorker.controller, null,
|
||||
'Frame should not be claimed when a longer-matched ' +
|
||||
'registration exists');
|
||||
frame.remove();
|
||||
return service_worker_unregister(t, claim_scope);
|
||||
})
|
||||
.then(function() {
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
});
|
||||
}, 'Test claim client when there\'s a longer-matched registration not ' +
|
||||
'already used by the page');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: claim client using registration</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="resources/testharness-helpers.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
|
||||
promise_test(function(t) {
|
||||
var scope = 'resources/';
|
||||
var frame_url = 'resources/blank.html?using-different-registration';
|
||||
var url1 = 'resources/empty.js';
|
||||
var url2 = 'resources/claim-worker.js';
|
||||
var worker, sw_registration, frame;
|
||||
return service_worker_unregister_and_register(t, url1, scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return with_iframe(frame_url);
|
||||
})
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return navigator.serviceWorker.register(url2, {scope: frame_url});
|
||||
})
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
sw_registration = registration;
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
var saw_controllerchanged = new Promise(function(resolve) {
|
||||
frame.contentWindow.navigator.serviceWorker.oncontrollerchange =
|
||||
function() { resolve(); }
|
||||
});
|
||||
var channel = new MessageChannel();
|
||||
var saw_message = new Promise(function(resolve) {
|
||||
channel.port1.onmessage = t.step_func(function(e) {
|
||||
assert_equals(e.data, 'PASS',
|
||||
'Worker call to claim() should fulfill.');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
worker.postMessage({port: channel.port2}, [channel.port2]);
|
||||
return Promise.all([saw_controllerchanged, saw_message]);
|
||||
})
|
||||
.then(function() {
|
||||
assert_equals(
|
||||
frame.contentWindow.navigator.serviceWorker.controller.scriptURL,
|
||||
normalizeURL(url2),
|
||||
'Frame1 controller scriptURL should be changed to url2');
|
||||
frame.remove();
|
||||
return sw_registration.unregister();
|
||||
})
|
||||
.then(function() {
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
});
|
||||
}, 'Test worker claims client which is using another registration');
|
||||
|
||||
promise_test(function(t) {
|
||||
var scope = 'resources/blank.html?using-same-registration';
|
||||
var url1 = 'resources/empty.js';
|
||||
var url2 = 'resources/claim-worker.js';
|
||||
var frame, worker;
|
||||
return service_worker_unregister_and_register(t, url1, scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return navigator.serviceWorker.register(url2, {scope: scope});
|
||||
})
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, registration.installing, 'installed');
|
||||
})
|
||||
.then(function() {
|
||||
var channel = new MessageChannel();
|
||||
var saw_message = new Promise(function(resolve) {
|
||||
channel.port1.onmessage = t.step_func(function(e) {
|
||||
assert_equals(e.data, 'FAIL: exception: InvalidStateError',
|
||||
'Worker call to claim() should reject with ' +
|
||||
'InvalidStateError');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
worker.postMessage({port: channel.port2}, [channel.port2]);
|
||||
return saw_message;
|
||||
})
|
||||
.then(function() {
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
});
|
||||
}, 'Test for the waiting worker claims a client which is using the the ' +
|
||||
'same registration');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Service Worker: WindowClient.navigate</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
function wait_for_message(msg) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var get_message_data = function get_message_data(e) {
|
||||
window.removeEventListener("message", get_message_data);
|
||||
resolve(e.data);
|
||||
}
|
||||
window.addEventListener("message", get_message_data, false);
|
||||
});
|
||||
}
|
||||
|
||||
function run_test(controller, clientId, test) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = function(e) {
|
||||
resolve(e.data);
|
||||
};
|
||||
var message = {
|
||||
port: channel.port2,
|
||||
test: test,
|
||||
clientId: clientId,
|
||||
};
|
||||
controller.postMessage(
|
||||
message, [channel.port2]);
|
||||
});
|
||||
}
|
||||
|
||||
promise_test(function(t) {
|
||||
var worker = "resources/client-navigate-worker.js";
|
||||
var scope = "resources/client-navigate-frame.html";
|
||||
var controller, frame, clientId;
|
||||
|
||||
return service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(reg => wait_for_state(t, reg.installing, "activated"))
|
||||
.then(___ => with_iframe(scope))
|
||||
.then(f => {
|
||||
frame = f;
|
||||
controller = frame.contentWindow.navigator.serviceWorker.controller;
|
||||
fetch_tests_from_worker(controller);
|
||||
return wait_for_message()
|
||||
})
|
||||
.then(({id}) => clientId = id)
|
||||
.then(___ => run_test(controller, clientId, "test_client_navigate_success"))
|
||||
.then(({result, url}) => {
|
||||
assert_equals(result, "test_client_navigate_success");
|
||||
assert_equals(
|
||||
url, new URL("resources/client-navigated-frame.html",
|
||||
location).toString());
|
||||
assert_equals(
|
||||
frame.contentWindow.location.href,
|
||||
new URL("resources/client-navigated-frame.html",
|
||||
location).toString());
|
||||
})
|
||||
.catch(unreached_rejection(t))
|
||||
.then(___ => service_worker_unregister(t, scope));
|
||||
}, "Frame location should update on successful navigation");
|
||||
|
||||
promise_test(function(t) {
|
||||
var worker = "resources/client-navigate-worker.js";
|
||||
var scope = "resources/client-navigate-frame.html";
|
||||
var controller, frame, clientId;
|
||||
|
||||
return service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(reg => wait_for_state(t, reg.installing, "activated"))
|
||||
.then(___ => with_iframe(scope))
|
||||
.then(f => {
|
||||
frame = f;
|
||||
controller = frame.contentWindow.navigator.serviceWorker.controller;
|
||||
fetch_tests_from_worker(controller);
|
||||
return wait_for_message()
|
||||
})
|
||||
.then(({id}) => clientId = id)
|
||||
.then(___ => run_test(controller, clientId, "test_client_navigate_redirect"))
|
||||
.then(({result, url}) => {
|
||||
assert_equals(result, "test_client_navigate_redirect");
|
||||
assert_equals(url, "");
|
||||
assert_throws(null, function() { return frame.contentWindow.location.href });
|
||||
})
|
||||
.catch(unreached_rejection(t))
|
||||
.then(___ => service_worker_unregister(t, scope));
|
||||
}, "Frame location should not be accessible after redirect");
|
||||
|
||||
promise_test(function(t) {
|
||||
var worker = "resources/client-navigate-worker.js";
|
||||
var scope = "resources/client-navigate-frame.html";
|
||||
var controller, frame, clientId;
|
||||
|
||||
return service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(reg => wait_for_state(t, reg.installing, "activated"))
|
||||
.then(___ => with_iframe(scope))
|
||||
.then(f => {
|
||||
frame = f;
|
||||
controller = frame.contentWindow.navigator.serviceWorker.controller;
|
||||
fetch_tests_from_worker(controller);
|
||||
return wait_for_message()
|
||||
})
|
||||
.then(({id}) => clientId = id)
|
||||
.then(___ => run_test(controller, clientId, "test_client_navigate_failure"))
|
||||
.then(({result, url}) => {
|
||||
assert_equals(result, "test_client_navigate_failure");
|
||||
assert_equals(
|
||||
frame.contentWindow.location.href,
|
||||
new URL("resources/client-navigate-frame.html",
|
||||
location).toString());
|
||||
frame.contentWindow.document.body.style = "background-color: green"
|
||||
})
|
||||
.catch(unreached_rejection(t))
|
||||
.then(___ => service_worker_unregister(t, scope));
|
||||
}, "Frame location should not update on failed navigation");
|
||||
</script>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Clients.get across origins</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
var host_info = get_host_info();
|
||||
|
||||
var scope = 'resources/blank.html?clients-get';
|
||||
var t = async_test('Test Clients.get() cross origin');
|
||||
var other_origin_iframe = host_info['HTTPS_REMOTE_ORIGIN'] + base_path() +
|
||||
'resources/clients-get-other-origin.html';
|
||||
var myOriginClientId;
|
||||
t.step(function() {
|
||||
service_worker_unregister_and_register(
|
||||
t, 'resources/clients-get-worker.js', scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(function(frame1) {
|
||||
myOriginClientId = frame1.contentDocument.body.textContent;
|
||||
return with_iframe(other_origin_iframe);
|
||||
})
|
||||
.then(function(frame2) {
|
||||
window.addEventListener('message', on_message_other_origin, false);
|
||||
frame2.contentWindow.postMessage(
|
||||
{clientId: myOriginClientId,
|
||||
message: 'get_client_id'},
|
||||
host_info['HTTPS_REMOTE_ORIGIN']);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
});
|
||||
|
||||
function on_message_other_origin(e) {
|
||||
assert_equals(e.data.result, undefined);
|
||||
t.done();
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Clients.get</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
var host_info = get_host_info();
|
||||
|
||||
var scope = 'resources/clients-get-frame.html';
|
||||
var t = async_test('Test Clients.get()');
|
||||
var clientIds = [];
|
||||
var frame;
|
||||
t.step(function() {
|
||||
service_worker_unregister_and_register(
|
||||
t, 'resources/clients-get-worker.js', scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return with_iframe(scope + '#1');
|
||||
})
|
||||
.then(function(frame1) {
|
||||
frame1.focus();
|
||||
return wait_for_clientId();
|
||||
})
|
||||
.then(function(clientId) {
|
||||
clientIds.push(clientId);
|
||||
return with_iframe(scope + '#2');
|
||||
})
|
||||
.then(function(frame2) {
|
||||
frame = frame2;
|
||||
return wait_for_clientId();
|
||||
})
|
||||
.then(function(clientId) {
|
||||
clientIds.push(clientId);
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = t.step_func(on_message);
|
||||
frame.contentWindow.navigator.serviceWorker.controller.postMessage(
|
||||
{port:channel.port2, clientIds:clientIds,
|
||||
message: 'get_client_ids'}, [channel.port2]);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
});
|
||||
|
||||
function wait_for_clientId() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
function get_client_id(e) {
|
||||
window.removeEventListener("message", get_client_id);
|
||||
resolve(e.data.clientId);
|
||||
}
|
||||
window.addEventListener("message", get_client_id, false);
|
||||
});
|
||||
}
|
||||
|
||||
var expected = [
|
||||
/* visibilityState, focused, url, frameType */
|
||||
['visible', true, new URL(scope + '#1', location).toString(), 'nested'],
|
||||
['visible', false, new URL(scope + '#2', location).toString(), 'nested'],
|
||||
undefined
|
||||
];
|
||||
|
||||
function on_message(e) {
|
||||
assert_equals(e.data.length, 3);
|
||||
assert_array_equals(e.data[0], expected[0]);
|
||||
assert_array_equals(e.data[1], expected[1]);
|
||||
assert_equals(e.data[2], expected[2]);
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Clients.matchAll with various clientTypes</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
var scope = 'resources/clients-matchall-client-types';
|
||||
var iframe_url = scope + '-iframe.html';
|
||||
var shared_worker_url = scope + '-shared-worker.js';
|
||||
|
||||
/* visibilityState, focused, url, frameType */
|
||||
var expected_without_type = [
|
||||
['visible', true, new URL(iframe_url, location).href, 'nested']
|
||||
];
|
||||
var expected_with_window = [
|
||||
['visible', true, new URL(iframe_url, location).href, 'nested']
|
||||
];
|
||||
var expected_with_shared_worker = [
|
||||
[,,new URL(shared_worker_url, location).href, 'none']
|
||||
];
|
||||
var expected_with_all = [
|
||||
['visible', true, new URL(iframe_url, location).href, 'nested'],
|
||||
[,,new URL(shared_worker_url, location).href, 'none']
|
||||
];
|
||||
|
||||
function test_matchall(frame, expected, query_options) {
|
||||
// Make sure the frame gets focus.
|
||||
frame.focus();
|
||||
expected.sort(function(a, b) { return a[2] > b[2] ? 1 : -1; });
|
||||
return new Promise(function(resolve, reject) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = function(e) {
|
||||
assert_equals(e.data.length, expected.length);
|
||||
for (var i = 0; i < e.data.length; i++)
|
||||
assert_array_equals(e.data[i], expected[i]);
|
||||
resolve();
|
||||
};
|
||||
frame.contentWindow.navigator.serviceWorker.controller.postMessage(
|
||||
{port:channel.port2, options:query_options},
|
||||
[channel.port2]);
|
||||
});
|
||||
}
|
||||
|
||||
promise_test(function(t) {
|
||||
var frame;
|
||||
return service_worker_unregister_and_register(
|
||||
t, 'resources/clients-matchall-worker.js', scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(iframe_url); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return new Promise(function(resolve, reject) {
|
||||
var w = new SharedWorker(shared_worker_url);
|
||||
w.port.onmessage = resolve;
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
return test_matchall(frame, expected_without_type, {});
|
||||
})
|
||||
.then(function() {
|
||||
return test_matchall(frame, expected_with_window, {type:'window'});
|
||||
})
|
||||
//.then(function() {
|
||||
// return test_matchall(frame, expected_with_shared_worker,
|
||||
// {type:'sharedworker'});
|
||||
// })
|
||||
//.then(function() {
|
||||
// return test_matchall(frame, expected_with_all, {type:'all'});
|
||||
// })
|
||||
.then(function() {
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
});
|
||||
}, 'Verify matchAll() with various client types');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Clients.matchAll with includeUncontrolled</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
var base_url = 'resources/blank.html'; // This is out-of-scope.
|
||||
var scope = base_url + '?clients-matchAll-includeUncontrolled';
|
||||
var frames = [];
|
||||
|
||||
// Creates 3 iframes, 2 for in-scope and 1 for out-of-scope.
|
||||
// The frame opened for scope + '#2' is returned via a promise.
|
||||
function create_iframes(scope) {
|
||||
return with_iframe(base_url)
|
||||
.then(function(frame0) {
|
||||
frames.push(frame0);
|
||||
return with_iframe(scope + '#1');
|
||||
})
|
||||
.then(function(frame1) {
|
||||
frames.push(frame1);
|
||||
return with_iframe(scope + '#2');
|
||||
})
|
||||
.then(function(frame2) {
|
||||
frames.push(frame2);
|
||||
return frame2;
|
||||
})
|
||||
}
|
||||
|
||||
var expected_without_include_uncontrolled = [
|
||||
/* visibilityState, focused, url, frameType */
|
||||
['visible', false, new URL(scope + '#1', location).toString(), 'nested'],
|
||||
['visible', true, new URL(scope + '#2', location).toString(), 'nested']
|
||||
];
|
||||
|
||||
var expected_with_include_uncontrolled = [
|
||||
/* visibilityState, focused, url, frameType */
|
||||
['visible', true, location.href, 'top-level'],
|
||||
['visible', false, new URL(scope + '#1', location).toString(), 'nested'],
|
||||
['visible', true, new URL(scope + '#2', location).toString(), 'nested'],
|
||||
['visible', false, new URL(base_url, location).toString(), 'nested']
|
||||
];
|
||||
|
||||
function test_matchall(frame, expected, query_options) {
|
||||
// Make sure we have focus for '#2' frame and its parent window.
|
||||
frame.focus();
|
||||
frame.contentWindow.focus();
|
||||
expected.sort(function(a, b) { return a[2] > b[2] ? 1 : -1; });
|
||||
return new Promise(function(resolve, reject) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = function(e) {
|
||||
// Ignore hidden clients which may be coming from background tabs, or
|
||||
// clients unrelated to this test.
|
||||
var data = e.data.filter(function(info) {
|
||||
return info[0] == 'visible' &&
|
||||
info[2].indexOf('service-worker') > -1;
|
||||
});
|
||||
data.sort(function(a, b) { return a[2] > b[2] ? 1 : -1; });
|
||||
assert_equals(data.length, expected.length);
|
||||
for (var i = 0; i < data.length; i++)
|
||||
assert_array_equals(data[i], expected[i]);
|
||||
resolve(frame);
|
||||
};
|
||||
frame.contentWindow.navigator.serviceWorker.controller.postMessage(
|
||||
{port:channel.port2, options:query_options},
|
||||
[channel.port2]);
|
||||
});
|
||||
}
|
||||
|
||||
// Run clients.matchAll without and with includeUncontrolled=true.
|
||||
// (We want to run the two tests sequentially in the same async_test
|
||||
// so that we can use the same set of iframes without intefering each other.
|
||||
async_test(function(t) {
|
||||
service_worker_unregister_and_register(
|
||||
t, 'resources/clients-matchall-worker.js', scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() { return create_iframes(scope); })
|
||||
.then(function(frame) {
|
||||
return test_matchall(frame, expected_without_include_uncontrolled);
|
||||
})
|
||||
.then(function(frame) {
|
||||
return test_matchall(frame, expected_with_include_uncontrolled,
|
||||
{includeUncontrolled:true});
|
||||
})
|
||||
.then(function() {
|
||||
frames.forEach(function(f) { f.remove() });
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify matchAll() respect includeUncontrolled');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Clients.matchAll</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
var scope = 'resources/blank.html?clients-matchAll';
|
||||
var t = async_test('Test Clients.matchAll()');
|
||||
var frames = [];
|
||||
t.step(function() {
|
||||
service_worker_unregister_and_register(
|
||||
t, 'resources/clients-matchall-worker.js', scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope + '#1'); })
|
||||
.then(function(frame1) {
|
||||
frames.push(frame1);
|
||||
frame1.focus();
|
||||
return with_iframe(scope + '#2');
|
||||
})
|
||||
.then(function(frame2) {
|
||||
frames.push(frame2);
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = t.step_func(onMessage);
|
||||
frame2.contentWindow.navigator.serviceWorker.controller.postMessage(
|
||||
{port:channel.port2}, [channel.port2]);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
});
|
||||
|
||||
var expected = [
|
||||
/* visibilityState, focused, url, frameType */
|
||||
['visible', true, new URL(scope + '#1', location).toString(), 'nested'],
|
||||
['visible', false, new URL(scope + '#2', location).toString(), 'nested']
|
||||
];
|
||||
|
||||
function onMessage(e) {
|
||||
assert_equals(e.data.length, 2);
|
||||
assert_array_equals(e.data[0], expected[0]);
|
||||
assert_array_equals(e.data[1], expected[1]);
|
||||
frames.forEach(function(f) { f.remove(); });
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Controller on load</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
var t = async_test('controller is cleared on disconnected window');
|
||||
t.step(function() {
|
||||
var url = 'resources/empty-worker.js';
|
||||
var scope = 'resources/blank.html';
|
||||
var registration;
|
||||
var controller;
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, url, scope)
|
||||
.then(t.step_func(function(swr) {
|
||||
registration = swr;
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
}))
|
||||
.then(t.step_func(function() {
|
||||
return with_iframe(scope)
|
||||
}))
|
||||
.then(t.step_func(function(f) {
|
||||
frame = f;
|
||||
var w = frame.contentWindow;
|
||||
var swc = w.navigator.serviceWorker;
|
||||
assert_true(swc.controller instanceof w.ServiceWorker,
|
||||
'controller should be a ServiceWorker object');
|
||||
|
||||
frame.remove();
|
||||
|
||||
assert_equals(swc.controller, null,
|
||||
'disconnected frame should not be controlled');
|
||||
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
}))
|
||||
.catch(unreached_rejection(t));
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Controller on load</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
var t = async_test('controller is set for a controlled document');
|
||||
t.step(function() {
|
||||
var url = 'resources/empty-worker.js';
|
||||
var scope = 'resources/blank.html';
|
||||
var registration;
|
||||
var controller;
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, url, scope)
|
||||
.then(t.step_func(function(swr) {
|
||||
registration = swr;
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
}))
|
||||
.then(t.step_func(function() {
|
||||
return with_iframe(scope)
|
||||
}))
|
||||
.then(t.step_func(function(f) {
|
||||
frame = f;
|
||||
var w = frame.contentWindow;
|
||||
controller = w.navigator.serviceWorker.controller;
|
||||
assert_true(controller instanceof w.ServiceWorker,
|
||||
'controller should be a ServiceWorker object');
|
||||
assert_equals(controller.scriptURL, normalizeURL(url));
|
||||
|
||||
// objects from different windows should not be equal
|
||||
assert_not_equals(controller, registration.active);
|
||||
|
||||
return w.navigator.serviceWorker.getRegistration();
|
||||
}))
|
||||
.then(t.step_func(function(frameRegistration) {
|
||||
// SW objects from same window should be equal
|
||||
assert_equals(frameRegistration.active, controller);
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
}))
|
||||
.catch(unreached_rejection(t));
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Controller on reload</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
promise_test(function(t) {
|
||||
var scope = 'resources/blank.html';
|
||||
var frame;
|
||||
var registration;
|
||||
var controller;
|
||||
return service_worker_unregister(t, scope)
|
||||
.then(function() {
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return frame.contentWindow.navigator.serviceWorker.register(
|
||||
'resources/empty-worker.js', {scope: scope});
|
||||
})
|
||||
.then(function(swr) {
|
||||
registration = swr;
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
var w = frame.contentWindow;
|
||||
assert_equals(w.navigator.serviceWorker.controller, null,
|
||||
'controller should be null until the document is ' +
|
||||
'reloaded');
|
||||
return new Promise(function(resolve) {
|
||||
frame.onload = function() { resolve(); }
|
||||
w.location.reload();
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
var w = frame.contentWindow;
|
||||
controller = w.navigator.serviceWorker.controller;
|
||||
assert_true(controller instanceof w.ServiceWorker,
|
||||
'controller should be a ServiceWorker object upon reload');
|
||||
|
||||
// objects from separate windows should not be equal
|
||||
assert_not_equals(controller, registration.active);
|
||||
|
||||
return w.navigator.serviceWorker.getRegistration();
|
||||
})
|
||||
.then(function(frameRegistration) {
|
||||
assert_equals(frameRegistration.active, controller);
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
});
|
||||
}, 'controller is set upon reload after registration');
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="resources/testharness-helpers.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
promise_test(function(t) {
|
||||
var script = 'resources/extendable-event-async-waituntil.js';
|
||||
var scope = 'resources/async-waituntil';
|
||||
var worker;
|
||||
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
var channel = new MessageChannel();
|
||||
var saw_message = new Promise(function(resolve) {
|
||||
channel.port1.onmessage = function(e) { resolve(e.data); }
|
||||
});
|
||||
worker.postMessage({port: channel.port2}, [channel.port2]);
|
||||
return saw_message;
|
||||
})
|
||||
.then(function(message) {
|
||||
assert_equals(message, 'PASS');
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
}, 'Calling waitUntil asynchronously throws an exception');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
<!DOCTYPE html>
|
||||
<title>ExtendableEvent: waitUntil</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
function runTest(test, scope, onRegister) {
|
||||
var script = 'resources/extendable-event-waituntil.js?' + scope;
|
||||
service_worker_unregister_and_register(test, script, scope)
|
||||
.then(function(registration) {
|
||||
onRegister(registration.installing);
|
||||
});
|
||||
}
|
||||
|
||||
// Sends a SYN to the worker and asynchronously listens for an ACK; sets
|
||||
// |obj.synced| to true once ack'd.
|
||||
function syncWorker(test, worker, obj) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = test.step_func(function(e) {
|
||||
var message = e.data;
|
||||
assert_equals(message, 'SYNC',
|
||||
'Should receive sync message from worker.');
|
||||
obj.synced = true;
|
||||
channel.port1.postMessage('ACK');
|
||||
});
|
||||
worker.postMessage({port: channel.port2}, [channel.port2]);
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
// Passing scope as the test switch for worker script.
|
||||
var scope = 'resources/install-fulfilled';
|
||||
var onRegister = function(worker) {
|
||||
var obj = {};
|
||||
wait_for_state(t, worker, 'installed')
|
||||
.then(function() {
|
||||
assert_true(
|
||||
obj.synced,
|
||||
'state should be "installed" after the waitUntil promise ' +
|
||||
'for "oninstall" is fulfilled.');
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
syncWorker(t, worker, obj);
|
||||
};
|
||||
runTest(t, scope, onRegister);
|
||||
}, 'Test install event waitUntil fulfilled');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/install-multiple-fulfilled';
|
||||
var onRegister = function(worker) {
|
||||
var obj1 = {};
|
||||
var obj2 = {};
|
||||
wait_for_state(t, worker, 'installed')
|
||||
.then(function() {
|
||||
assert_true(
|
||||
obj1.synced && obj2.synced,
|
||||
'state should be "installed" after all waitUntil promises ' +
|
||||
'for "oninstall" are fulfilled.');
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
syncWorker(t, worker, obj1);
|
||||
syncWorker(t, worker, obj2);
|
||||
};
|
||||
runTest(t, scope, onRegister);
|
||||
}, 'Test ExtendableEvent multiple waitUntil fulfilled.');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/install-reject-precedence';
|
||||
var onRegister = function(worker) {
|
||||
wait_for_state(t, worker, 'redundant')
|
||||
.then(function() {
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
};
|
||||
runTest(t, scope, onRegister);
|
||||
}, 'Test ExtendableEvent waitUntil reject precedence.');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/activate-fulfilled';
|
||||
var onRegister = function(worker) {
|
||||
var obj = {};
|
||||
wait_for_state(t, worker, 'activating')
|
||||
.then(function() {
|
||||
syncWorker(t, worker, obj);
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
assert_true(
|
||||
obj.synced,
|
||||
'state should be "activated" after the waitUntil promise ' +
|
||||
'for "onactivate" is fulfilled.');
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
};
|
||||
runTest(t, scope, onRegister);
|
||||
}, 'Test activate event waitUntil fulfilled');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/install-rejected';
|
||||
var onRegister = function(worker) {
|
||||
wait_for_state(t, worker, 'redundant')
|
||||
.then(function() {
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
};
|
||||
runTest(t, scope, onRegister);
|
||||
}, 'Test install event waitUntil rejected');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/activate-rejected';
|
||||
var onRegister = function(worker) {
|
||||
wait_for_state(t, worker, 'activated')
|
||||
.then(function() {
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
};
|
||||
runTest(t, scope, onRegister);
|
||||
}, 'Test activate event waitUntil rejected.');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: canvas tainting of the fetched image using cached responses</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<body>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
var SCOPE = 'resources/fetch-canvas-tainting-iframe.html?cache';
|
||||
var SCRIPT = 'resources/fetch-rewrite-worker.js';
|
||||
var host_info = get_host_info();
|
||||
|
||||
login_https(t)
|
||||
.then(function() {
|
||||
return service_worker_unregister_and_register(t, SCRIPT, SCOPE);
|
||||
})
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(frame) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = t.step_func(function(e) {
|
||||
assert_equals(e.data.results, 'finish');
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, SCOPE);
|
||||
});
|
||||
frame.contentWindow.postMessage({},
|
||||
host_info['HTTPS_ORIGIN'],
|
||||
[channel.port2]);
|
||||
});
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify canvas tainting of fetched image in a Service Worker');
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: canvas tainting of the fetched image</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<body>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
var SCOPE = 'resources/fetch-canvas-tainting-iframe.html';
|
||||
var SCRIPT = 'resources/fetch-rewrite-worker.js';
|
||||
var host_info = get_host_info();
|
||||
|
||||
login_https(t)
|
||||
.then(function() {
|
||||
return service_worker_unregister_and_register(t, SCRIPT, SCOPE);
|
||||
})
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(frame) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = t.step_func(function(e) {
|
||||
assert_equals(e.data.results, 'finish');
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, SCOPE);
|
||||
});
|
||||
frame.contentWindow.postMessage({},
|
||||
host_info['HTTPS_ORIGIN'],
|
||||
[channel.port2]);
|
||||
});
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify canvas tainting of fetched image in a Service Worker');
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: CORS XHR of fetch()</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<body>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
var SCOPE = 'resources/fetch-cors-xhr-iframe.html';
|
||||
var SCRIPT = 'resources/fetch-rewrite-worker.js';
|
||||
var host_info = get_host_info();
|
||||
|
||||
login_https(t)
|
||||
.then(function() {
|
||||
return service_worker_unregister_and_register(t, SCRIPT, SCOPE);
|
||||
})
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(frame) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = t.step_func(function(e) {
|
||||
assert_equals(e.data.results, 'finish');
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, SCOPE);
|
||||
});
|
||||
frame.contentWindow.postMessage({},
|
||||
host_info['HTTPS_ORIGIN'],
|
||||
[channel.port2]);
|
||||
});
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify CORS XHR of fetch() in a Service Worker');
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: CSP control of fetch()</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
var SCOPE = 'resources/fetch-csp-iframe.html';
|
||||
var SCRIPT = 'resources/fetch-rewrite-worker.js';
|
||||
var host_info = get_host_info();
|
||||
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(frame) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = t.step_func(function(e) {
|
||||
assert_equals(e.data.results, 'finish');
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, SCOPE);
|
||||
});
|
||||
frame.contentWindow.postMessage({},
|
||||
host_info['HTTPS_ORIGIN'],
|
||||
[channel.port2]);
|
||||
});
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify CSP control of fetch() in a Service Worker');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE html>
|
||||
<title>ServiceWorker: navigator.serviceWorker.waiting</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
promise_test(function(t) {
|
||||
var scope =
|
||||
'resources/fetch-event-after-navigation-within-page-iframe.html' +
|
||||
'?hashchange';
|
||||
var worker = 'resources/simple-intercept-worker.js';
|
||||
var frame;
|
||||
|
||||
return service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return frame.contentWindow.fetch_url('simple.txt');
|
||||
})
|
||||
.then(function(response) {
|
||||
assert_equals(response, 'intercepted by service worker');
|
||||
frame.contentWindow.location.hash = 'foo';
|
||||
return frame.contentWindow.fetch_url('simple.txt');
|
||||
})
|
||||
.then(function(response) {
|
||||
assert_equals(response, 'intercepted by service worker');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
}, 'Service Worker should respond to fetch event after the hash changes');
|
||||
|
||||
promise_test(function(t) {
|
||||
var scope =
|
||||
'resources/fetch-event-after-navigation-within-page-iframe.html' +
|
||||
'?pushState';
|
||||
var worker = 'resources/simple-intercept-worker.js';
|
||||
var frame;
|
||||
|
||||
return service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return frame.contentWindow.fetch_url('simple.txt');
|
||||
})
|
||||
.then(function(response) {
|
||||
assert_equals(response, 'intercepted by service worker');
|
||||
frame.contentWindow.history.pushState('', '', 'bar');
|
||||
return frame.contentWindow.fetch_url('simple.txt');
|
||||
})
|
||||
.then(function(response) {
|
||||
assert_equals(response, 'intercepted by service worker');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
}, 'Service Worker should respond to fetch event after the pushState');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="resources/testharness-helpers.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
promise_test(function(t) {
|
||||
var script = 'resources/fetch-event-async-respond-with-worker.js';
|
||||
var scope = 'resources/simple.html';
|
||||
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(function(frame) {
|
||||
var channel = new MessageChannel();
|
||||
var saw_message = new Promise(function(resolve) {
|
||||
channel.port1.onmessage = function(e) { resolve(e.data); }
|
||||
});
|
||||
var worker = frame.contentWindow.navigator.serviceWorker.controller;
|
||||
|
||||
worker.postMessage({port: channel.port2}, [channel.port2]);
|
||||
frame.remove();
|
||||
return saw_message;
|
||||
})
|
||||
.then(function(message) {
|
||||
assert_equals(message, 'PASS');
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
}, 'Calling respondWith asynchronously throws an exception');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Fetch event network error</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="resources/testharness-helpers.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
var resolve_test_done;
|
||||
|
||||
var test_done_promise = new Promise(function(resolve) {
|
||||
resolve_test_done = resolve;
|
||||
});
|
||||
|
||||
// Called by the child frame.
|
||||
function notify_test_done(result) {
|
||||
resolve_test_done(result);
|
||||
}
|
||||
|
||||
promise_test(function(t) {
|
||||
var scope = 'resources/fetch-event-network-error-controllee-iframe.html';
|
||||
var script = 'resources/fetch-event-network-error-worker.js';
|
||||
var frame;
|
||||
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return test_done_promise;
|
||||
})
|
||||
.then(function(result) {
|
||||
frame.remove();
|
||||
assert_equals(result, 'PASS');
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
});
|
||||
}, 'Rejecting the fetch event or using preventDefault() causes a network ' +
|
||||
'error');
|
||||
</script>
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="resources/testharness-helpers.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
promise_test(function(t) {
|
||||
var script =
|
||||
'resources/fetch-event-respond-with-stops-propagation-worker.js';
|
||||
var scope = 'resources/simple.html';
|
||||
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(function(frame) {
|
||||
var channel = new MessageChannel();
|
||||
var saw_message = new Promise(function(resolve) {
|
||||
channel.port1.onmessage = function(e) { resolve(e.data); }
|
||||
});
|
||||
var worker = frame.contentWindow.navigator.serviceWorker.controller;
|
||||
|
||||
worker.postMessage({port: channel.port2}, [channel.port2]);
|
||||
frame.remove();
|
||||
return saw_message;
|
||||
})
|
||||
.then(function(message) {
|
||||
assert_equals(message, 'PASS');
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
}, 'respondWith() invokes stopImmediatePropagation()');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,575 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
var worker = 'resources/fetch-event-test-worker.js';
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?string';
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(frame) {
|
||||
assert_equals(
|
||||
frame.contentDocument.body.textContent,
|
||||
'Test string',
|
||||
'Service Worker should respond to fetch with a test string');
|
||||
assert_equals(
|
||||
frame.contentDocument.contentType,
|
||||
'text/plain',
|
||||
'The content type of the response created with a string should be text/plain');
|
||||
assert_equals(
|
||||
frame.contentDocument.characterSet,
|
||||
'UTF-8',
|
||||
'The character set of the response created with a string should be UTF-8');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker responds to fetch event with string');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?blob';
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(frame) {
|
||||
assert_equals(
|
||||
frame.contentDocument.body.textContent,
|
||||
'Test blob',
|
||||
'Service Worker should respond to fetch with a test string');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker responds to fetch event with blob body');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?referrer';
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(frame) {
|
||||
assert_equals(
|
||||
frame.contentDocument.body.textContent,
|
||||
'Referrer: ' + document.location.href,
|
||||
'Service Worker should respond to fetch with the referrer URL');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker responds to fetch event with the referrer URL');
|
||||
|
||||
function run_referrer_policy_tests(frame, referrer, href, origin) {
|
||||
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
|
||||
{method: "GET", referrer: referrer})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text,
|
||||
'Referrer: ' + href + '\n' +
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
'Service Worker should respond to fetch with the referrer URL when a member of RequestInit is present');
|
||||
var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
|
||||
'/resources/simple.html?referrerFull';
|
||||
return frame.contentWindow.fetch(http_url,
|
||||
{method: "GET", referrer: referrer});
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text,
|
||||
'Referrer: about:client\n' +
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
'Service Worker should respond to fetch with no referrer when a member of RequestInit is present with an HTTP request');
|
||||
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
|
||||
{referrerPolicy: "", referrer: referrer});
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text,
|
||||
'Referrer: ' + href + '\n' +
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
'Service Worker should respond to fetch with the referrer with ""');
|
||||
var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
|
||||
'/resources/simple.html?referrerFull';
|
||||
return frame.contentWindow.fetch(http_url,
|
||||
{referrerPolicy: "", referrer: referrer});
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text,
|
||||
'Referrer: about:client\n' +
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
'Service Worker should respond to fetch with no referrer with ""');
|
||||
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
|
||||
{referrerPolicy: "origin", referrer: referrer});
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text,
|
||||
'Referrer: ' + origin + '/' + '\n' +
|
||||
'ReferrerPolicy: origin',
|
||||
'Service Worker should respond to fetch with the referrer origin with "origin" and a same origin request');
|
||||
var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
|
||||
'/resources/simple.html?referrerFull';
|
||||
return frame.contentWindow.fetch(http_url,
|
||||
{referrerPolicy: "origin", referrer: referrer});
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text,
|
||||
'Referrer: ' + origin + '/' + '\n' +
|
||||
'ReferrerPolicy: origin',
|
||||
'Service Worker should respond to fetch with the referrer origin with "origin" and a cross origin request');
|
||||
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
|
||||
{referrerPolicy: "origin-when-cross-origin", referrer: referrer});
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text,
|
||||
'Referrer: ' + href + '\n' +
|
||||
'ReferrerPolicy: origin-when-cross-origin',
|
||||
'Service Worker should respond to fetch with the referrer URL with "origin-when-cross-origin" and a same origin request');
|
||||
var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
|
||||
'/resources/simple.html?referrerFull';
|
||||
return frame.contentWindow.fetch(http_url,
|
||||
{referrerPolicy: "origin-when-cross-origin", referrer: referrer});
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text,
|
||||
'Referrer: ' + origin + '/' + '\n' +
|
||||
'ReferrerPolicy: origin-when-cross-origin',
|
||||
'Service Worker should respond to fetch with the referrer origin with "origin-when-cross-origin" and a cross origin request');
|
||||
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
|
||||
{referrerPolicy: "no-referrer-when-downgrade", referrer: referrer});
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text,
|
||||
'Referrer: ' + href + '\n' +
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
'Service Worker should respond to fetch with no referrer with "no-referrer-when-downgrade" and a same origin request');
|
||||
var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
|
||||
'/resources/simple.html?referrerFull';
|
||||
return frame.contentWindow.fetch(http_url,
|
||||
{referrerPolicy: "no-referrer-when-downgrade", referrer: referrer});
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text,
|
||||
'Referrer: about:client\n' +
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
'Service Worker should respond to fetch with no referrer with "no-referrer-when-downgrade" and an HTTP request');
|
||||
var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
|
||||
'/resources/simple.html?referrerFull';
|
||||
return frame.contentWindow.fetch(http_url, {referrerPolicy: "unsafe-url", referrer: referrer});
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text,
|
||||
'Referrer: ' + href + '\n' +
|
||||
'ReferrerPolicy: unsafe-url',
|
||||
'Service Worker should respond to fetch with no referrer with "unsafe-url"');
|
||||
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
|
||||
{referrerPolicy: "no-referrer", referrer: referrer});
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text,
|
||||
'Referrer: about:client\n' +
|
||||
'ReferrerPolicy: no-referrer',
|
||||
'Service Worker should respond to fetch with no referrer URL with "no-referrer"');
|
||||
});
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?referrerPolicy';
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
assert_equals(
|
||||
frame.contentDocument.body.textContent,
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
'Service Worker should respond to fetch with the default referrer policy');
|
||||
// First, run the referrer policy tests without passing a referrer in RequestInit.
|
||||
return run_referrer_policy_tests(frame, undefined, frame.contentDocument.location.href,
|
||||
frame.contentDocument.location.origin);
|
||||
})
|
||||
.then(function() {
|
||||
// Now, run the referrer policy tests while passing a referrer in RequestInit.
|
||||
var referrer = get_host_info()['HTTPS_ORIGIN'] + base_path() + 'fake-referrer';
|
||||
return run_referrer_policy_tests(frame, 'fake-referrer', referrer,
|
||||
frame.contentDocument.location.origin);
|
||||
})
|
||||
.then(function() {
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker responds to fetch event with the referrer URL');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?clientId';
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
assert_equals(
|
||||
frame.contentDocument.body.textContent,
|
||||
'Client ID Not Found',
|
||||
'Service Worker should respond to fetch with a client id');
|
||||
return frame.contentWindow.fetch('resources/other.html?clientId');
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
var new_client_id = response_text.substr(17);
|
||||
assert_equals(
|
||||
response_text.substr(0, 15),
|
||||
'Client ID Found',
|
||||
'Service Worker should respond to fetch with an existing client id');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker responds to fetch event with an existing client id');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?ignore';
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(frame) {
|
||||
assert_equals(frame.contentDocument.body.textContent,
|
||||
'Here\'s a simple html file.\n',
|
||||
'Response should come from fallback to native fetch');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker does not respond to fetch event');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?null';
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(frame) {
|
||||
assert_equals(frame.contentDocument.body.textContent,
|
||||
'',
|
||||
'Response should be the empty string');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker responds to fetch event with null response body');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?fetch';
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(frame) {
|
||||
assert_equals(frame.contentDocument.body.textContent,
|
||||
'Here\'s an other html file.\n',
|
||||
'Response should come from fetched other file');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker fetches other file in fetch event');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?form-post';
|
||||
var frame_name = 'xhr-post-frame';
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function(sw) {
|
||||
return new Promise(function(resolve) {
|
||||
var frame = document.createElement('iframe');
|
||||
frame.name = frame_name;
|
||||
document.body.appendChild(frame);
|
||||
var form = document.createElement('form');
|
||||
form.target = frame_name;
|
||||
form.action = scope;
|
||||
form.method = 'post';
|
||||
var input1 = document.createElement('input');
|
||||
input1.type = 'text';
|
||||
input1.value = 'testValue1';
|
||||
input1.name = 'testName1'
|
||||
form.appendChild(input1);
|
||||
var input2 = document.createElement('input');
|
||||
input2.type = 'text';
|
||||
input2.value = 'testValue2';
|
||||
input2.name = 'testName2'
|
||||
form.appendChild(input2);
|
||||
document.body.appendChild(form);
|
||||
frame.onload = function() {
|
||||
document.body.removeChild(form);
|
||||
resolve(frame);
|
||||
};
|
||||
form.submit();
|
||||
});
|
||||
})
|
||||
.then(function(frame) {
|
||||
assert_equals(frame.contentDocument.body.textContent,
|
||||
'POST:application/x-www-form-urlencoded:' +
|
||||
'testName1=testValue1&testName2=testValue2');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker responds to fetch event with POST form');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?multiple-respond-with';
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(frame) {
|
||||
assert_equals(
|
||||
frame.contentDocument.body.textContent,
|
||||
'(0)(1)[InvalidStateError](2)[InvalidStateError]',
|
||||
'Multiple calls of respondWith must throw InvalidStateErrors.');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Multiple calls of respondWith must throw InvalidStateErrors');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?used-check';
|
||||
var first_frame;
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(frame) {
|
||||
assert_equals(frame.contentDocument.body.textContent,
|
||||
'Here\'s an other html file.\n',
|
||||
'Response should come from fetched other file');
|
||||
first_frame = frame;
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(function(frame) {
|
||||
// When we access to the scope in the second time, the content of the
|
||||
// response is generated inside the ServiceWorker. The body contains
|
||||
// the value of bodyUsed of the first response which is already
|
||||
// consumed by FetchEvent.respondWith method.
|
||||
assert_equals(
|
||||
frame.contentDocument.body.textContent,
|
||||
'bodyUsed: true',
|
||||
'event.respondWith must set the used flag.');
|
||||
first_frame.remove();
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker event.respondWith must set the used flag');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?fragment-check';
|
||||
var fragment = '#/some/fragment';
|
||||
var first_frame;
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope + fragment); })
|
||||
.then(function(frame) {
|
||||
assert_equals(
|
||||
frame.contentDocument.body.textContent,
|
||||
'Fragment Found :' + fragment,
|
||||
'Service worker should expose URL fragments in request.');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker must not expose FetchEvent URL fragments.');
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?cache';
|
||||
var frame;
|
||||
var cacheTypes = [
|
||||
undefined, 'default', 'no-store', 'reload', 'no-cache', 'force-cache', 'only-if-cached'
|
||||
];
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
assert_equals(frame.contentWindow.document.body.textContent, 'default');
|
||||
var tests = cacheTypes.map(function(type) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var init = {cache: type};
|
||||
if (type === 'only-if-cached') {
|
||||
// For privacy reasons, for the time being, only-if-cached
|
||||
// requires the mode to be same-origin.
|
||||
init.mode = 'same-origin';
|
||||
}
|
||||
return frame.contentWindow.fetch(scope + '=' + type, init)
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
var expected = (type === undefined) ? 'default' : type;
|
||||
assert_equals(response_text, expected,
|
||||
'Service Worker should respond to fetch with the correct type');
|
||||
})
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
frame.addEventListener('load', function onLoad() {
|
||||
frame.removeEventListener('load', onLoad);
|
||||
try {
|
||||
assert_equals(frame.contentWindow.document.body.textContent,
|
||||
'no-cache');
|
||||
resolve();
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
frame.contentWindow.location.reload();
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker responds to fetch event with the correct cache types');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?eventsource';
|
||||
var frame;
|
||||
|
||||
function test_eventsource(opts) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var eventSource = new frame.contentWindow.EventSource(scope, opts);
|
||||
eventSource.addEventListener('message', function(msg) {
|
||||
eventSource.close();
|
||||
try {
|
||||
var data = JSON.parse(msg.data);
|
||||
assert_equals(data.mode, 'cors',
|
||||
'EventSource should make CORS requests.');
|
||||
assert_equals(data.cache, 'no-store',
|
||||
'EventSource should bypass the http cache.');
|
||||
var expectedCredentials = opts.withCredentials ? 'include'
|
||||
: 'same-origin';
|
||||
assert_equals(data.credentials, expectedCredentials,
|
||||
'EventSource should pass correct credentials mode.');
|
||||
resolve();
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
eventSource.addEventListener('error', function(e) {
|
||||
eventSource.close();
|
||||
reject('The EventSource fired an error event.');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return test_eventsource({ withCredentials: false });
|
||||
})
|
||||
.then(function() {
|
||||
return test_eventsource({ withCredentials: true });
|
||||
})
|
||||
.then(function() {
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker should intercept EventSource');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/simple.html?integrity';
|
||||
var frame;
|
||||
var integrity_metadata = 'gs0nqru8KbsrIt5YToQqS9fYao4GQJXtcId610g7cCU=';
|
||||
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
// A request has associated integrity metadata (a string).
|
||||
// Unless stated otherwise, it is the empty string.
|
||||
assert_equals(
|
||||
frame.contentDocument.body.textContent, '');
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
return frame.contentWindow.fetch(scope,
|
||||
{'integrity': integrity_metadata})
|
||||
.then(function(response) {
|
||||
return response.text();
|
||||
})
|
||||
.then(function(response_text) {
|
||||
// Should get the same integrity metadata.
|
||||
assert_equals(response_text, integrity_metadata,
|
||||
'Service Worker should respond to fetch with the correct integrity');
|
||||
})
|
||||
.then(resolve())
|
||||
.catch(reject());
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Service Worker responds to fetch event with the correct integrity_metadata');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Fetch for the frame loading.</title>
|
||||
<meta name=timeout content=long>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
var worker = 'resources/fetch-rewrite-worker.js';
|
||||
var path = base_path() + 'resources/fetch-access-control.py';
|
||||
var host_info = get_host_info();
|
||||
|
||||
if (window.testRunner) {
|
||||
testRunner.setCanOpenWindows();
|
||||
}
|
||||
|
||||
function getLoadedObject(win, contentFunc, closeFunc) {
|
||||
return new Promise(function(resolve) {
|
||||
function done(contentString) {
|
||||
var result = null;
|
||||
// fetch-access-control.py returns a string like "report( <json> )".
|
||||
// Eval the returned string with a report functionto get the json
|
||||
// object.
|
||||
try {
|
||||
function report(obj) { result = obj };
|
||||
eval(contentString);
|
||||
} catch(e) {
|
||||
// just resolve null if we get unexpected page content
|
||||
}
|
||||
closeFunc(win);
|
||||
resolve(result);
|
||||
}
|
||||
|
||||
// We can't catch the network error on window. So we use the timer.
|
||||
var timeout = setTimeout(function() {
|
||||
// Failure pages are considered cross-origin in some browsers. This
|
||||
// means you cannot even .resolve() the window because the check for
|
||||
// the .then property will throw. Instead, treat cross-origin
|
||||
// failure pages as the empty string which will fail to parse as the
|
||||
// expected json result.
|
||||
var content = '';
|
||||
try {
|
||||
content = contentFunc(win);
|
||||
} catch(e) {
|
||||
// use default empty string for cross-domain window
|
||||
}
|
||||
done(content);
|
||||
}, 10000);
|
||||
|
||||
win.onload = function() {
|
||||
clearTimeout(timeout);
|
||||
var content = contentFunc(win);
|
||||
done(content);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function getLoadedFrameAsObject(frame) {
|
||||
return getLoadedObject(frame, function(f) {
|
||||
return f.contentDocument.body.textContent;
|
||||
}, function(f) {
|
||||
f.parentNode.removeChild(f);
|
||||
});
|
||||
}
|
||||
|
||||
function getLoadedWindowAsObject(win) {
|
||||
return getLoadedObject(win, function(w) {
|
||||
return w.document.body.textContent
|
||||
}, function(w) {
|
||||
w.close();
|
||||
});
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/fetch-frame-resource/frame-basic';
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
frame = document.createElement('iframe');
|
||||
frame.src =
|
||||
scope + '?url=' +
|
||||
encodeURIComponent(host_info['HTTPS_ORIGIN'] + path);
|
||||
document.body.appendChild(frame);
|
||||
return getLoadedFrameAsObject(frame);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_equals(
|
||||
result.jsonpResult,
|
||||
'success',
|
||||
'Basic type response could be loaded in the iframe.');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Basic type response could be loaded in the iframe.');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/fetch-frame-resource/frame-cors';
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
frame = document.createElement('iframe');
|
||||
frame.src =
|
||||
scope + '?mode=cors&url=' +
|
||||
encodeURIComponent(host_info['HTTPS_REMOTE_ORIGIN'] + path +
|
||||
'?ACAOrigin=' + host_info['HTTPS_ORIGIN']);
|
||||
document.body.appendChild(frame);
|
||||
return getLoadedFrameAsObject(frame);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_equals(
|
||||
result.jsonpResult,
|
||||
'success',
|
||||
'CORS type response could be loaded in the iframe.');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'CORS type response could be loaded in the iframe.');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/fetch-frame-resource/frame-opaque';
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
frame = document.createElement('iframe');
|
||||
frame.src =
|
||||
scope + '?mode=no-cors&url=' +
|
||||
encodeURIComponent(host_info['HTTPS_REMOTE_ORIGIN'] + path);
|
||||
document.body.appendChild(frame);
|
||||
return getLoadedFrameAsObject(frame);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_equals(
|
||||
result,
|
||||
null,
|
||||
'Opaque type response could not be loaded in the iframe.');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Opaque type response could not be loaded in the iframe.');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/fetch-frame-resource/window-basic';
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
var win = window.open(
|
||||
scope + '?url=' +
|
||||
encodeURIComponent(host_info['HTTPS_ORIGIN'] + path));
|
||||
return getLoadedWindowAsObject(win);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_equals(
|
||||
result.jsonpResult,
|
||||
'success',
|
||||
'Basic type response could be loaded in the new window.');
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Basic type response could be loaded in the new window.');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/fetch-frame-resource/window-cors';
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
var win = window.open(
|
||||
scope + '?mode=cors&url=' +
|
||||
encodeURIComponent(host_info['HTTPS_REMOTE_ORIGIN'] + path +
|
||||
'?ACAOrigin=' + host_info['HTTPS_ORIGIN']));
|
||||
return getLoadedWindowAsObject(win);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_equals(
|
||||
result.jsonpResult,
|
||||
'success',
|
||||
'CORS type response could be loaded in the new window.');
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'CORS type response could be loaded in the new window.');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/fetch-frame-resource/window-opaque';
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
var win = window.open(
|
||||
scope + '?mode=no-cors&url=' +
|
||||
encodeURIComponent(host_info['HTTPS_REMOTE_ORIGIN'] + path));
|
||||
return getLoadedWindowAsObject(win);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert_equals(
|
||||
result,
|
||||
null,
|
||||
'Opaque type response could not be loaded in the new window.');
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Opaque type response could not be loaded in the new window.');
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Visibility of headers during fetch.</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
var worker = 'resources/fetch-rewrite-worker.js';
|
||||
var path = base_path() + 'resources/fetch-access-control.py';
|
||||
var host_info = get_host_info();
|
||||
var frame;
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/fetch-header-visibility-iframe.html';
|
||||
service_worker_unregister_and_register(t, worker, scope)
|
||||
.then(function(reg) {
|
||||
return wait_for_state(t, reg.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
frame = document.createElement('iframe');
|
||||
frame.src = scope;
|
||||
document.body.appendChild(frame);
|
||||
|
||||
// Resolve a promise when we recieve 2 success messages
|
||||
return new Promise(function(resolve, reject) {
|
||||
var remaining = 4;
|
||||
function onMessage(e) {
|
||||
if (e.data == 'PASS') {
|
||||
remaining--;
|
||||
if (remaining == 0) {
|
||||
resolve();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reject(e.data);
|
||||
}
|
||||
|
||||
window.removeEventListener('message', onMessage);
|
||||
}
|
||||
window.addEventListener('message', onMessage);
|
||||
});
|
||||
})
|
||||
.then(function(result) {
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Visibility of defaulted headers during interception');
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Mixed content of fetch()</title>
|
||||
<meta name=timeout content=long>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<body></body>
|
||||
<script>
|
||||
if (window.testRunner) {
|
||||
// In Chromium we need to change the setting to disallow displaying insecure
|
||||
// contents.
|
||||
testRunner.overridePreference('WebKitAllowDisplayingInsecureContent', false);
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
var host_info = get_host_info();
|
||||
window.addEventListener('message', t.step_func(on_message), false);
|
||||
with_iframe(
|
||||
host_info['HTTPS_ORIGIN'] + base_path() +
|
||||
'resources/fetch-mixed-content-iframe.html?target=inscope');
|
||||
function on_message(e) {
|
||||
assert_equals(e.data.results, 'finish');
|
||||
t.done();
|
||||
}
|
||||
}, 'Verify Mixed content of fetch() in a Service Worker');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Mixed content of fetch()</title>
|
||||
<meta name=timeout content=long>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<body></body>
|
||||
<script>
|
||||
if (window.testRunner) {
|
||||
// In Chromium we need to change the setting to disallow displaying insecure
|
||||
// contents.
|
||||
testRunner.overridePreference('WebKitAllowDisplayingInsecureContent', false);
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
var host_info = get_host_info();
|
||||
window.addEventListener('message', t.step_func(on_message), false);
|
||||
with_iframe(
|
||||
host_info['HTTPS_ORIGIN'] + base_path() +
|
||||
'resources/fetch-mixed-content-iframe.html?target=outscope');
|
||||
function on_message(e) {
|
||||
assert_equals(e.data.results, 'finish');
|
||||
t.done();
|
||||
}
|
||||
}, 'Verify Mixed content of fetch() in a Service Worker');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: CSS's base URL must be the request URL even when fetched from other URL</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
var SCOPE = 'resources/fetch-request-css-base-url-iframe.html';
|
||||
var SCRIPT = 'resources/fetch-request-css-base-url-worker.js';
|
||||
var worker;
|
||||
var testDonePromise;
|
||||
|
||||
return service_worker_unregister_and_register(t, SCRIPT, SCOPE)
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return new Promise(function(resolve) {
|
||||
var channel = new MessageChannel();
|
||||
testDonePromise = new Promise(function(resolveTestDone) {
|
||||
channel.port1.onmessage = t.step_func(function(msg) {
|
||||
if (msg.data.ready) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
var result = msg.data;
|
||||
var base = get_host_info()['HTTPS_ORIGIN'] + base_path();
|
||||
assert_equals(
|
||||
result.url,
|
||||
base + 'resources/dummy.png',
|
||||
'The base URL while loading the images referred from CSS ' +
|
||||
'must be the request URL of CSS.');
|
||||
assert_equals(
|
||||
result.referrer,
|
||||
base + 'resources/fetch-request-css-base-url-style.css',
|
||||
'While loading the image defined in CSS the referrer must ' +
|
||||
'be the request URL of CSS.');
|
||||
resolveTestDone();
|
||||
});
|
||||
});
|
||||
worker.postMessage(
|
||||
{port: channel.port2}, [channel.port2]);
|
||||
});
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(f) {
|
||||
return testDonePromise.then(function() {
|
||||
f.remove();
|
||||
return service_worker_unregister_and_done(t, SCOPE);
|
||||
});
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'CSS\'s base URL must be the request URL even when fetched from other URL.');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,176 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: FetchEvent for css image</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<script>
|
||||
var SCOPE = 'resources/fetch-request-resources-iframe.https.html';
|
||||
var SCRIPT = 'resources/fetch-request-resources-worker.js';
|
||||
var host_info = get_host_info();
|
||||
var LOCAL_URL =
|
||||
host_info['HTTPS_ORIGIN'] + base_path() + 'resources/dummy?test';
|
||||
var REMOTE_URL =
|
||||
host_info['HTTPS_REMOTE_ORIGIN'] + base_path() + 'resources/dummy?test';
|
||||
|
||||
function css_image_test(expected_results, frame, url, type,
|
||||
expected_mode, expected_credentials) {
|
||||
expected_results[url] = {
|
||||
url: url,
|
||||
mode: expected_mode,
|
||||
credentials: expected_credentials,
|
||||
message: 'CSSImage load (url:' + url + ' type:' + type + ')'
|
||||
};
|
||||
return frame.contentWindow.load_css_image(url, type);
|
||||
}
|
||||
|
||||
function css_image_set_test(expected_results, frame, url, type,
|
||||
expected_mode, expected_credentials) {
|
||||
expected_results[url] = {
|
||||
url: url,
|
||||
mode: expected_mode,
|
||||
credentials: expected_credentials,
|
||||
message: 'CSSImageSet load (url:' + url + ' type:' + type + ')'
|
||||
};
|
||||
return frame.contentWindow.load_css_image_set(url, type);
|
||||
}
|
||||
|
||||
function create_message_promise(t, expected_results, frame,
|
||||
worker, test_count, scope) {
|
||||
return new Promise(function(resolve) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = t.step_func(function(msg) {
|
||||
if (msg.data.ready) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
var result = msg.data;
|
||||
var expected = expected_results[result.url];
|
||||
if (!expected) {
|
||||
return;
|
||||
}
|
||||
assert_equals(
|
||||
result.mode, expected.mode,
|
||||
'mode of ' + expected.message + ' must be ' +
|
||||
expected.mode + '.');
|
||||
assert_equals(
|
||||
result.credentials, expected.credentials,
|
||||
'credentials of ' + expected.message + ' must be ' +
|
||||
expected.credentials + '.');
|
||||
--test_count;
|
||||
delete expected_results[result.url];
|
||||
if (test_count == 0) {
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
}
|
||||
});
|
||||
worker.postMessage(
|
||||
{port: channel.port2}, [channel.port2]);
|
||||
});
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = SCOPE + "?img=backgroundImage";
|
||||
var test_count = 2;
|
||||
var expected_results = {};
|
||||
var worker;
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, SCRIPT, scope)
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return create_message_promise(t, expected_results, frame,
|
||||
worker, test_count, scope);
|
||||
})
|
||||
.then(function() {
|
||||
css_image_test(expected_results, frame, LOCAL_URL + Date.now(),
|
||||
'backgroundImage', 'no-cors', 'include');
|
||||
css_image_test(expected_results, frame, REMOTE_URL + Date.now(),
|
||||
'backgroundImage', 'no-cors', 'include');
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify FetchEvent for css image (backgroundImage).');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = SCOPE + "?img=shapeOutside";
|
||||
var test_count = 2;
|
||||
var expected_results = {};
|
||||
var worker;
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, SCRIPT, scope)
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return create_message_promise(t, expected_results, frame,
|
||||
worker, test_count, scope);
|
||||
})
|
||||
.then(function() {
|
||||
css_image_test(expected_results, frame, LOCAL_URL + Date.now(),
|
||||
'shapeOutside', 'cors', 'same-origin');
|
||||
css_image_test(expected_results, frame, REMOTE_URL + Date.now(),
|
||||
'shapeOutside', 'cors', 'same-origin');
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify FetchEvent for css image (shapeOutside).');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = SCOPE + "?img_set=backgroundImage";
|
||||
var test_count = 2;
|
||||
var expected_results = {};
|
||||
var worker;
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, SCRIPT, scope)
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return create_message_promise(t, expected_results, frame,
|
||||
worker, test_count, scope);
|
||||
})
|
||||
.then(function() {
|
||||
css_image_set_test(expected_results, frame, LOCAL_URL + Date.now(),
|
||||
'backgroundImage', 'no-cors', 'include');
|
||||
css_image_set_test(expected_results, frame, REMOTE_URL + Date.now(),
|
||||
'backgroundImage', 'no-cors', 'include');
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify FetchEvent for css image-set (backgroundImage).');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = SCOPE + "?img_set=shapeOutside";
|
||||
var test_count = 2;
|
||||
var expected_results = {};
|
||||
var worker;
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, SCRIPT, scope)
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return create_message_promise(t, expected_results, frame,
|
||||
worker, test_count, scope);
|
||||
})
|
||||
.then(function() {
|
||||
css_image_set_test(expected_results, frame, LOCAL_URL + Date.now(),
|
||||
'shapeOutside', 'cors', 'same-origin');
|
||||
css_image_set_test(expected_results, frame, REMOTE_URL + Date.now(),
|
||||
'shapeOutside', 'cors', 'same-origin');
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify FetchEvent for css image-set (shapeOutside).');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: the fallback behavior of FetchEvent</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<script>
|
||||
var expected_urls = [];
|
||||
|
||||
function xhr_fail_test(frame, url) {
|
||||
expected_urls.push(url);
|
||||
return new Promise(function(resolve, reject) {
|
||||
frame.contentWindow.xhr(url)
|
||||
.then(function(){
|
||||
reject(url + ' should fail.');
|
||||
})
|
||||
.catch(function(){
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function xhr_succeed_test(frame, url) {
|
||||
expected_urls.push(url);
|
||||
return new Promise(function(resolve, reject) {
|
||||
frame.contentWindow.xhr(url)
|
||||
.then(function(){
|
||||
resolve();
|
||||
})
|
||||
.catch(function(){
|
||||
reject(url + ' should succeed.');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
var path = new URL(".", window.location).pathname;
|
||||
var SCOPE = 'resources/fetch-request-fallback-iframe.html';
|
||||
var SCRIPT = 'resources/fetch-request-fallback-worker.js';
|
||||
var host_info = get_host_info();
|
||||
var BASE_URL = host_info['HTTPS_ORIGIN'] +
|
||||
path + 'resources/fetch-access-control.py?';
|
||||
var OTHER_BASE_URL = host_info['HTTPS_REMOTE_ORIGIN'] +
|
||||
path + 'resources/fetch-access-control.py?';
|
||||
var REDIRECT_URL = host_info['HTTPS_ORIGIN'] +
|
||||
path + 'resources/redirect.py?Redirect=';
|
||||
var frame;
|
||||
var worker;
|
||||
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return xhr_succeed_test(frame, BASE_URL);
|
||||
})
|
||||
.then(function(f) {
|
||||
return xhr_fail_test(frame, OTHER_BASE_URL);
|
||||
})
|
||||
.then(function(f) {
|
||||
return xhr_succeed_test(frame, OTHER_BASE_URL + 'ACAOrigin=*');
|
||||
})
|
||||
.then(function(f) {
|
||||
return xhr_succeed_test(frame,
|
||||
REDIRECT_URL + encodeURIComponent(BASE_URL));
|
||||
})
|
||||
.then(function() {
|
||||
return xhr_fail_test(
|
||||
frame,
|
||||
REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL));
|
||||
})
|
||||
.then(function() {
|
||||
return xhr_succeed_test(
|
||||
frame,
|
||||
REDIRECT_URL +
|
||||
encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*'));
|
||||
})
|
||||
.then(function() {
|
||||
return new Promise(function(resolve) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = t.step_func(function(msg) {
|
||||
frame.remove();
|
||||
resolve(msg);
|
||||
});
|
||||
worker.postMessage({port: channel.port2}, [channel.port2]);
|
||||
});
|
||||
})
|
||||
.then(function(msg) {
|
||||
var requests = msg.data.requests;
|
||||
assert_equals(requests.length, expected_urls.length + 1,
|
||||
'The count of the requests which are passed to the ' +
|
||||
'ServiceWorker must be correct.');
|
||||
assert_equals(requests[0].url, new URL(SCOPE, location).toString(),
|
||||
'The first request to the SW must be the request for ' +
|
||||
'the page.');
|
||||
assert_equals(requests[0].mode, 'navigate',
|
||||
'The mode of the first request to the SW must be ' +
|
||||
'navigate');
|
||||
for (var i = 0; i < expected_urls.length; ++i) {
|
||||
assert_equals(requests[i + 1].url, expected_urls[i],
|
||||
'The URL of the request which was passed from XHR ' +
|
||||
'to the ServiceWorker must be correct.');
|
||||
assert_equals(requests[i + 1].mode, 'cors',
|
||||
'The mode of the request which was passed from XHR ' +
|
||||
'to the ServiceWorker must be cors.');
|
||||
}
|
||||
service_worker_unregister_and_done(t, SCOPE);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify the fallback behavior of FetchEvent');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: the headers of FetchEvent shouldn't contain freshness headers</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
var SCOPE = 'resources/fetch-request-no-freshness-headers-iframe.html';
|
||||
var SCRIPT = 'resources/fetch-request-no-freshness-headers-worker.js';
|
||||
var worker;
|
||||
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(frame) {
|
||||
return new Promise(function(resolve) {
|
||||
frame.onload = function() {
|
||||
resolve(frame);
|
||||
};
|
||||
frame.contentWindow.location.reload();
|
||||
});
|
||||
})
|
||||
.then(function(frame) {
|
||||
return new Promise(function(resolve) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = t.step_func(function(msg) {
|
||||
frame.remove();
|
||||
resolve(msg);
|
||||
});
|
||||
worker.postMessage(
|
||||
{port: channel.port2}, [channel.port2]);
|
||||
});
|
||||
})
|
||||
.then(function(msg) {
|
||||
var freshness_headers = {
|
||||
'if-none-match': true,
|
||||
'if-modified-since': true
|
||||
};
|
||||
msg.data.requests.forEach(t.step_func(function(request) {
|
||||
request.headers.forEach(t.step_func(function(header) {
|
||||
assert_false(
|
||||
!!freshness_headers[header[0]],
|
||||
header[0] + ' header must not be set in the ' +
|
||||
'FetchEvent\'s request. (url = ' + request.url + ')');
|
||||
}));
|
||||
}))
|
||||
service_worker_unregister_and_done(t, SCOPE);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'The headers of FetchEvent shouldn\'t contain freshness headers.');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,372 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: FetchEvent for resources</title>
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
|
||||
function assert_resolves(promise, description) {
|
||||
return promise.catch(function(reason) {
|
||||
throw new Error(description + ' - ' + reason.message);
|
||||
});
|
||||
}
|
||||
|
||||
function assert_rejects(promise, description) {
|
||||
return promise.then(
|
||||
function() { throw new Error(description); },
|
||||
function() {});
|
||||
}
|
||||
|
||||
function iframe_test(url, timeout_enabled) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var frame = document.createElement('iframe');
|
||||
frame.src = url;
|
||||
if (timeout_enabled) {
|
||||
// We can't catch the network error on iframe. So we use the timer for
|
||||
// failure detection.
|
||||
var timer = setTimeout(function() {
|
||||
reject(new Error('iframe load timeout'));
|
||||
frame.remove();
|
||||
}, 10000);
|
||||
}
|
||||
frame.onload = function() {
|
||||
if (timeout_enabled)
|
||||
clearTimeout(timer);
|
||||
if (frame.contentDocument.body.textContent == 'Hello world\n')
|
||||
resolve();
|
||||
else
|
||||
reject(new Error('content mismatch'));
|
||||
frame.remove();
|
||||
};
|
||||
document.body.appendChild(frame);
|
||||
});
|
||||
}
|
||||
|
||||
promise_test(function(t) {
|
||||
var SCOPE = 'resources/fetch-request-redirect-iframe.html';
|
||||
var SCRIPT = 'resources/fetch-rewrite-worker.js';
|
||||
var REDIRECT_URL = base_path() + 'resources/redirect.py?Redirect=';
|
||||
var IMAGE_URL = base_path() + 'resources/square.png';
|
||||
var AUDIO_URL = base_path() + 'resources/silence.oga';
|
||||
var XHR_URL = base_path() + 'resources/simple.txt';
|
||||
var HTML_URL = base_path() + 'resources/dummy.html';
|
||||
|
||||
var REDIRECT_TO_IMAGE_URL = REDIRECT_URL + encodeURIComponent(IMAGE_URL);
|
||||
var REDIRECT_TO_AUDIO_URL = REDIRECT_URL + encodeURIComponent(AUDIO_URL);
|
||||
var REDIRECT_TO_XHR_URL = REDIRECT_URL + encodeURIComponent(XHR_URL);
|
||||
var REDIRECT_TO_HTML_URL = REDIRECT_URL + encodeURIComponent(HTML_URL);
|
||||
|
||||
var worker;
|
||||
var frame;
|
||||
return service_worker_unregister_and_register(t, SCRIPT, SCOPE)
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return Promise.all([
|
||||
// XMLHttpRequest tests.
|
||||
assert_resolves(frame.contentWindow.xhr(XHR_URL),
|
||||
'Normal XHR should succeed.'),
|
||||
assert_resolves(frame.contentWindow.xhr(REDIRECT_TO_XHR_URL),
|
||||
'Redirected XHR should succeed.'),
|
||||
assert_resolves(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
|
||||
'&redirect-mode=follow'),
|
||||
'Redirected XHR with Request.redirect=follow should succeed.'),
|
||||
assert_rejects(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
|
||||
'&redirect-mode=error'),
|
||||
'Redirected XHR with Request.redirect=error should fail.'),
|
||||
assert_rejects(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
|
||||
'&redirect-mode=manual'),
|
||||
'Redirected XHR with Request.redirect=manual should fail.'),
|
||||
|
||||
// Image loading tests.
|
||||
assert_resolves(frame.contentWindow.load_image(IMAGE_URL),
|
||||
'Normal image resource should be loaded.'),
|
||||
assert_resolves(
|
||||
frame.contentWindow.load_image(REDIRECT_TO_IMAGE_URL),
|
||||
'Redirected image resource should be loaded.'),
|
||||
assert_resolves(
|
||||
frame.contentWindow.load_image(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_IMAGE_URL) +
|
||||
'&redirect-mode=follow'),
|
||||
'Loading redirected image with Request.redirect=follow should' +
|
||||
' succeed.'),
|
||||
assert_rejects(
|
||||
frame.contentWindow.load_image(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_IMAGE_URL) +
|
||||
'&redirect-mode=error'),
|
||||
'Loading redirected image with Request.redirect=error should ' +
|
||||
'fail.'),
|
||||
assert_rejects(
|
||||
frame.contentWindow.load_image(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_IMAGE_URL) +
|
||||
'&redirect-mode=manual'),
|
||||
'Loading redirected image with Request.redirect=manual should' +
|
||||
' fail.'),
|
||||
|
||||
// Audio loading tests.
|
||||
assert_resolves(frame.contentWindow.load_audio(AUDIO_URL),
|
||||
'Normal audio resource should be loaded.'),
|
||||
assert_resolves(
|
||||
frame.contentWindow.load_audio(REDIRECT_TO_AUDIO_URL),
|
||||
'Redirected audio resource should be loaded.'),
|
||||
assert_resolves(
|
||||
frame.contentWindow.load_audio(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_AUDIO_URL) +
|
||||
'&redirect-mode=follow'),
|
||||
'Loading redirected audio with Request.redirect=follow should' +
|
||||
' succeed.'),
|
||||
assert_rejects(
|
||||
frame.contentWindow.load_audio(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_AUDIO_URL) +
|
||||
'&redirect-mode=error'),
|
||||
'Loading redirected audio with Request.redirect=error should ' +
|
||||
'fail.'),
|
||||
assert_rejects(
|
||||
frame.contentWindow.load_audio(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_AUDIO_URL) +
|
||||
'&redirect-mode=manual'),
|
||||
'Loading redirected audio with Request.redirect=manual should' +
|
||||
' fail.'),
|
||||
|
||||
// Iframe tests.
|
||||
assert_resolves(iframe_test(HTML_URL),
|
||||
'Normal iframe loading should succeed.'),
|
||||
assert_resolves(
|
||||
iframe_test(REDIRECT_TO_HTML_URL),
|
||||
'Normal redirected iframe loading should succeed.'),
|
||||
assert_rejects(
|
||||
iframe_test(SCOPE + '?url=' +
|
||||
encodeURIComponent(REDIRECT_TO_HTML_URL) +
|
||||
'&redirect-mode=follow',
|
||||
true /* timeout_enabled */),
|
||||
'Redirected iframe loading with Request.redirect=follow should'+
|
||||
' fail.'),
|
||||
assert_rejects(
|
||||
iframe_test(SCOPE + '?url=' +
|
||||
encodeURIComponent(REDIRECT_TO_HTML_URL) +
|
||||
'&redirect-mode=error',
|
||||
true /* timeout_enabled */),
|
||||
'Redirected iframe loading with Request.redirect=error should '+
|
||||
'fail.'),
|
||||
assert_resolves(
|
||||
iframe_test(SCOPE + '?url=' +
|
||||
encodeURIComponent(REDIRECT_TO_HTML_URL) +
|
||||
'&redirect-mode=manual',
|
||||
true /* timeout_enabled */),
|
||||
'Redirected iframe loading with Request.redirect=manual should'+
|
||||
' succeed.'),
|
||||
]);
|
||||
})
|
||||
.then(function() {
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, SCOPE);
|
||||
});
|
||||
}, 'Verify redirect mode of Fetch API and ServiceWorker FetchEvent.');
|
||||
|
||||
// test for reponse.redirected
|
||||
promise_test(function(t) {
|
||||
var SCOPE = 'resources/fetch-request-redirect-iframe.html';
|
||||
var SCRIPT = 'resources/fetch-rewrite-worker.js';
|
||||
var REDIRECT_URL = base_path() + 'resources/redirect.py?Redirect=';
|
||||
var XHR_URL = base_path() + 'resources/simple.txt';
|
||||
var IMAGE_URL = base_path() + 'resources/square.png';
|
||||
|
||||
var REDIRECT_TO_XHR_URL = REDIRECT_URL + encodeURIComponent(XHR_URL);
|
||||
|
||||
var host_info = get_host_info();
|
||||
|
||||
var CROSS_ORIGIN_URL = host_info['HTTPS_REMOTE_ORIGIN'] + IMAGE_URL;
|
||||
|
||||
var REDIRECT_TO_CROSS_ORIGIN = REDIRECT_URL +
|
||||
encodeURIComponent(CROSS_ORIGIN_URL + '?ACAOrigin=*');
|
||||
|
||||
var worker;
|
||||
var frame;
|
||||
return service_worker_unregister_and_register(t, SCRIPT, SCOPE)
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return Promise.all([
|
||||
// XMLHttpRequest tests.
|
||||
assert_resolves(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(XHR_URL) +
|
||||
'&expected_redirected=false' +
|
||||
'&expected_resolves=true'),
|
||||
'Normal XHR should be resolved and response should not be ' +
|
||||
'redirected.'),
|
||||
assert_resolves(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
|
||||
'&expected_redirected=true' +
|
||||
'&expected_resolves=true'),
|
||||
'Redirected XHR should be resolved and response should be ' +
|
||||
'redirected.'),
|
||||
|
||||
// tests for request's mode = cors
|
||||
assert_resolves(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(XHR_URL) +
|
||||
'&mode=cors' +
|
||||
'&expected_redirected=false' +
|
||||
'&expected_resolves=true'),
|
||||
'Normal XHR should be resolved and response should not be ' +
|
||||
'redirected even with CORS mode.'),
|
||||
assert_resolves(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
|
||||
'&mode=cors' +
|
||||
'&redirect-mode=follow' +
|
||||
'&expected_redirected=true' +
|
||||
'&expected_resolves=true'),
|
||||
'Redirected XHR should be resolved and response.redirected ' +
|
||||
'should be redirected with CORS mode.'),
|
||||
|
||||
// tests for request's mode = no-cors
|
||||
// The response.redirect should be false since we will not add
|
||||
// redirected url list when redirect-mode is not follow.
|
||||
assert_rejects(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
|
||||
'&mode=no-cors' +
|
||||
'&redirect-mode=manual' +
|
||||
'&expected_redirected=false' +
|
||||
'&expected_resolves=false'),
|
||||
'Redirected XHR should be reject and response should be ' +
|
||||
'redirected with NO-CORS mode and redirect-mode=manual.'),
|
||||
|
||||
// tests for redirecting to a cors
|
||||
assert_resolves(
|
||||
frame.contentWindow.load_image(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_CROSS_ORIGIN) +
|
||||
'&mode=no-cors' +
|
||||
'&redirect-mode=follow' +
|
||||
'&expected_redirected=false' +
|
||||
'&expected_resolves=true'),
|
||||
'Redirected COS image should be reject and response should ' +
|
||||
'not be redirected with NO-CORS mode.'),
|
||||
]);
|
||||
})
|
||||
.then(function() {
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, SCOPE);
|
||||
});
|
||||
}, 'Verify redirected of Response(Fetch API) and ServiceWorker FetchEvent.');
|
||||
|
||||
// test for reponse.redirected after cached
|
||||
promise_test(function(t) {
|
||||
var SCOPE = 'resources/fetch-request-redirect-iframe.html';
|
||||
var SCRIPT = 'resources/fetch-rewrite-worker.js';
|
||||
var REDIRECT_URL = base_path() + 'resources/redirect.py?Redirect=';
|
||||
var XHR_URL = base_path() + 'resources/simple.txt';
|
||||
var IMAGE_URL = base_path() + 'resources/square.png';
|
||||
|
||||
var REDIRECT_TO_XHR_URL = REDIRECT_URL + encodeURIComponent(XHR_URL);
|
||||
|
||||
var host_info = get_host_info();
|
||||
|
||||
var CROSS_ORIGIN_URL = host_info['HTTPS_REMOTE_ORIGIN'] + IMAGE_URL;
|
||||
|
||||
var REDIRECT_TO_CROSS_ORIGIN = REDIRECT_URL +
|
||||
encodeURIComponent(CROSS_ORIGIN_URL + '?ACAOrigin=*');
|
||||
|
||||
var worker;
|
||||
var frame;
|
||||
return service_worker_unregister_and_register(t, SCRIPT, SCOPE)
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return Promise.all([
|
||||
// XMLHttpRequest tests.
|
||||
assert_resolves(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(XHR_URL) +
|
||||
'&expected_redirected=false' +
|
||||
'&expected_resolves=true' +
|
||||
'&cache'),
|
||||
'Normal XHR should be resolved and response should not be ' +
|
||||
'redirected.'),
|
||||
assert_resolves(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
|
||||
'&expected_redirected=true' +
|
||||
'&expected_resolves=true' +
|
||||
'&cache'),
|
||||
'Redirected XHR should be resolved and response should be ' +
|
||||
'redirected.'),
|
||||
|
||||
// tests for request's mode = cors
|
||||
assert_resolves(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(XHR_URL) +
|
||||
'&mode=cors' +
|
||||
'&expected_redirected=false' +
|
||||
'&expected_resolves=true' +
|
||||
'&cache'),
|
||||
'Normal XHR should be resolved and response should not be ' +
|
||||
'redirected even with CORS mode.'),
|
||||
assert_resolves(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
|
||||
'&mode=cors' +
|
||||
'&redirect-mode=follow' +
|
||||
'&expected_redirected=true' +
|
||||
'&expected_resolves=true' +
|
||||
'&cache'),
|
||||
'Redirected XHR should be resolved and response.redirected ' +
|
||||
'should be redirected with CORS mode.'),
|
||||
|
||||
// tests for request's mode = no-cors
|
||||
// The response.redirect should be false since we will not add
|
||||
// redirected url list when redirect-mode is not follow.
|
||||
assert_rejects(
|
||||
frame.contentWindow.xhr(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_XHR_URL) +
|
||||
'&mode=no-cors' +
|
||||
'&redirect-mode=manual' +
|
||||
'&expected_redirected=false' +
|
||||
'&expected_resolves=false' +
|
||||
'&cache'),
|
||||
'Redirected XHR should be reject and response should be ' +
|
||||
'redirected with NO-CORS mode and redirect-mode=manual.'),
|
||||
|
||||
// tests for redirecting to a cors
|
||||
assert_resolves(
|
||||
frame.contentWindow.load_image(
|
||||
'./?url=' + encodeURIComponent(REDIRECT_TO_CROSS_ORIGIN) +
|
||||
'&mode=no-cors' +
|
||||
'&redirect-mode=follow' +
|
||||
'&expected_redirected=false' +
|
||||
'&expected_resolves=true' +
|
||||
'&cache'),
|
||||
'Redirected COS image should be reject and response should ' +
|
||||
'not be redirected with NO-CORS mode.'),
|
||||
]);
|
||||
})
|
||||
.then(function() {
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, SCOPE);
|
||||
});
|
||||
}, 'Verify redirected of Response(Fetch API), Cache API and ServiceWorker ' +
|
||||
'FetchEvent.');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: FetchEvent for resources</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<script>
|
||||
var url_count = 0;
|
||||
var expected_results = {};
|
||||
|
||||
function image_test(frame, url, cross_origin, expected_mode,
|
||||
expected_credentials) {
|
||||
var actual_url = url + (++url_count);
|
||||
expected_results[actual_url] = {
|
||||
cross_origin: cross_origin,
|
||||
mode: expected_mode,
|
||||
credentials: expected_credentials,
|
||||
integrity: '',
|
||||
message: 'Image load (url:' +
|
||||
actual_url + ' cross_origin:' + cross_origin + ')'
|
||||
};
|
||||
return frame.contentWindow.load_image(actual_url, cross_origin);
|
||||
}
|
||||
|
||||
function script_test(frame, url, cross_origin, expected_mode,
|
||||
expected_credentials) {
|
||||
var actual_url = url + (++url_count);
|
||||
expected_results[actual_url] = {
|
||||
cross_origin: cross_origin,
|
||||
mode: expected_mode,
|
||||
credentials: expected_credentials,
|
||||
integrity: '',
|
||||
message: 'Script load (url:' +
|
||||
actual_url + ' cross_origin:' + cross_origin + ')'
|
||||
};
|
||||
return frame.contentWindow.load_script(actual_url, cross_origin);
|
||||
}
|
||||
|
||||
function css_test(frame, url, cross_origin, expected_mode,
|
||||
expected_credentials) {
|
||||
var actual_url = url + (++url_count);
|
||||
expected_results[actual_url] = {
|
||||
cross_origin: cross_origin,
|
||||
mode: expected_mode,
|
||||
credentials: expected_credentials,
|
||||
integrity: '',
|
||||
message: 'CSS load (url:' +
|
||||
actual_url + ' cross_origin:' + cross_origin + ')'
|
||||
};
|
||||
return frame.contentWindow.load_css(actual_url, cross_origin);
|
||||
}
|
||||
|
||||
function font_face_test(frame, url, expected_mode, expected_credentials) {
|
||||
var actual_url = url + (++url_count);
|
||||
expected_results[actual_url] = {
|
||||
url: actual_url,
|
||||
mode: expected_mode,
|
||||
credentials: expected_credentials,
|
||||
integrity: '',
|
||||
message: 'FontFace load (url:' + actual_url + ')'
|
||||
};
|
||||
return frame.contentWindow.load_font(actual_url);
|
||||
}
|
||||
|
||||
function script_integrity_test(frame, url, integrity, expected_integrity) {
|
||||
var actual_url = url + (++url_count);
|
||||
expected_results[actual_url] = {
|
||||
url: actual_url,
|
||||
mode: 'no-cors',
|
||||
credentials: 'include',
|
||||
integrity: expected_integrity,
|
||||
message: 'Script load (url:' + actual_url + ')'
|
||||
};
|
||||
return frame.contentWindow.load_script_with_integrity(actual_url, integrity);
|
||||
}
|
||||
|
||||
function css_integrity_test(frame, url, integrity, expected_integrity) {
|
||||
var actual_url = url + (++url_count);
|
||||
expected_results[actual_url] = {
|
||||
url: actual_url,
|
||||
mode: 'no-cors',
|
||||
credentials: 'include',
|
||||
integrity: expected_integrity,
|
||||
message: 'CSS load (url:' + actual_url + ')'
|
||||
};
|
||||
return frame.contentWindow.load_css_with_integrity(actual_url, integrity);
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
var SCOPE = 'resources/fetch-request-resources-iframe.https.html';
|
||||
var SCRIPT = 'resources/fetch-request-resources-worker.js';
|
||||
var host_info = get_host_info();
|
||||
var LOCAL_URL =
|
||||
host_info['HTTPS_ORIGIN'] + base_path() + 'resources/dummy?test';
|
||||
var REMOTE_URL =
|
||||
host_info['HTTPS_REMOTE_ORIGIN'] + base_path() + 'resources/dummy?test';
|
||||
var worker;
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
|
||||
.then(function(registration) {
|
||||
worker = registration.installing;
|
||||
return wait_for_state(t, worker, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return new Promise(function(resolve) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = t.step_func(function(msg) {
|
||||
if (msg.data.ready) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
var result = msg.data;
|
||||
var expected = expected_results[result.url];
|
||||
if (!expected) {
|
||||
return;
|
||||
}
|
||||
assert_equals(
|
||||
result.mode, expected.mode,
|
||||
'mode of ' + expected.message + ' must be ' +
|
||||
expected.mode + '.');
|
||||
assert_equals(
|
||||
result.credentials, expected.credentials,
|
||||
'credentials of ' + expected.message + ' must be ' +
|
||||
expected.credentials + '.');
|
||||
assert_equals(
|
||||
result.integrity, expected.integrity,
|
||||
'integrity of ' + expected.message + ' must be ' +
|
||||
expected.integrity + '.');
|
||||
--url_count;
|
||||
delete expected_results[result.url];
|
||||
if (url_count == 0) {
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, SCOPE);
|
||||
}
|
||||
});
|
||||
worker.postMessage(
|
||||
{port: channel.port2}, [channel.port2]);
|
||||
});
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
|
||||
image_test(f, LOCAL_URL, '', 'no-cors', 'include');
|
||||
image_test(f, REMOTE_URL, '', 'no-cors', 'include');
|
||||
css_test(f, LOCAL_URL, '', 'no-cors', 'include');
|
||||
css_test(f, REMOTE_URL, '', 'no-cors', 'include');
|
||||
|
||||
image_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin');
|
||||
image_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include');
|
||||
image_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin');
|
||||
image_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include');
|
||||
|
||||
script_test(f, LOCAL_URL, '', 'no-cors', 'include');
|
||||
script_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin');
|
||||
script_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include');
|
||||
script_test(f, REMOTE_URL, '', 'no-cors', 'include');
|
||||
script_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin');
|
||||
script_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include');
|
||||
|
||||
css_test(f, LOCAL_URL, 'anonymous', 'cors', 'same-origin');
|
||||
css_test(f, LOCAL_URL, 'use-credentials', 'cors', 'include');
|
||||
css_test(f, REMOTE_URL, 'anonymous', 'cors', 'same-origin');
|
||||
css_test(f, REMOTE_URL, 'use-credentials', 'cors', 'include');
|
||||
|
||||
font_face_test(f, LOCAL_URL, 'cors', 'same-origin');
|
||||
font_face_test(f, REMOTE_URL, 'cors', 'same-origin');
|
||||
|
||||
script_integrity_test(f, LOCAL_URL, ' ', ' ');
|
||||
script_integrity_test(f, LOCAL_URL,
|
||||
'This is not a valid integrity because it has no dashes',
|
||||
'This is not a valid integrity because it has no dashes');
|
||||
script_integrity_test(f, LOCAL_URL, 'sha256-', 'sha256-');
|
||||
script_integrity_test(f, LOCAL_URL, 'sha256-foo?123', 'sha256-foo?123');
|
||||
script_integrity_test(f, LOCAL_URL, 'sha256-foo sha384-abc ', 'sha256-foo sha384-abc ');
|
||||
script_integrity_test(f, LOCAL_URL, 'sha256-foo sha256-abc', 'sha256-foo sha256-abc');
|
||||
|
||||
css_integrity_test(f, LOCAL_URL, ' ', ' ');
|
||||
css_integrity_test(f, LOCAL_URL,
|
||||
'This is not a valid integrity because it has no dashes',
|
||||
'This is not a valid integrity because it has no dashes');
|
||||
css_integrity_test(f, LOCAL_URL, 'sha256-', 'sha256-');
|
||||
css_integrity_test(f, LOCAL_URL, 'sha256-foo?123', 'sha256-foo?123');
|
||||
css_integrity_test(f, LOCAL_URL, 'sha256-foo sha384-abc ', 'sha256-foo sha384-abc ');
|
||||
css_integrity_test(f, LOCAL_URL, 'sha256-foo sha256-abc', 'sha256-foo sha256-abc');
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify FetchEvent for resources.');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: the body of FetchEvent using XMLHttpRequest</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
var SCOPE = 'resources/fetch-request-xhr-iframe.https.html';
|
||||
var SCRIPT = 'resources/fetch-request-xhr-worker.js';
|
||||
var host_info = get_host_info();
|
||||
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(frame) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = t.step_func(function(e) {
|
||||
if (e.data.results === 'finish') {
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, SCOPE);
|
||||
} else if (e.data.results == 'equals') {
|
||||
assert_equals(e.data.got, e.data.expected);
|
||||
}
|
||||
});
|
||||
frame.contentWindow.postMessage({},
|
||||
host_info['HTTPS_ORIGIN'],
|
||||
[channel.port2]);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify the body of FetchEvent using XMLHttpRequest');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: the response of FetchEvent using XMLHttpRequest</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
var SCOPE = 'resources/fetch-response-xhr-iframe.https.html';
|
||||
var SCRIPT = 'resources/fetch-response-xhr-worker.js';
|
||||
var host_info = get_host_info();
|
||||
|
||||
window.addEventListener('message', t.step_func(on_message), false);
|
||||
function on_message(e) {
|
||||
assert_equals(e.data.results, 'foo, bar');
|
||||
t.done();
|
||||
}
|
||||
|
||||
service_worker_unregister_and_register(t, SCRIPT, SCOPE)
|
||||
.then(function(registration) {
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() { return with_iframe(SCOPE); })
|
||||
.then(function(frame) {
|
||||
var channel = new MessageChannel();
|
||||
channel.port1.onmessage = t.step_func(function(e) {
|
||||
assert_equals(e.data.results, 'finish');
|
||||
frame.remove();
|
||||
service_worker_unregister_and_done(t, SCOPE);
|
||||
});
|
||||
frame.contentWindow.postMessage({},
|
||||
host_info['HTTPS_ORIGIN'],
|
||||
[channel.port2]);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Verify the response of FetchEvent using XMLHttpRequest');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Fetch Event Waits for Activate Event</title>
|
||||
<meta name=timeout content=long>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="resources/testharness-helpers.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
var worker = 'resources/fetch-waits-for-activate-worker.js';
|
||||
var expected_url = normalizeURL(worker);
|
||||
var scope = 'resources/fetch-waits-for-activate/';
|
||||
|
||||
async_test(function(t) {
|
||||
var registration;
|
||||
var frameLoadPromise;
|
||||
var frame;
|
||||
service_worker_unregister_and_register(t, worker, scope).then(function(reg) {
|
||||
registration = reg;
|
||||
return wait_for_state(t, reg.installing, 'activating');
|
||||
}).then(function() {
|
||||
assert_equals(registration.active.scriptURL, expected_url,
|
||||
'active worker should be present');
|
||||
assert_equals(registration.active.state, 'activating',
|
||||
'active worker should be in activating state');
|
||||
|
||||
// This should block until we message the worker to tell it to complete
|
||||
// the activate event.
|
||||
frameLoadPromise = with_iframe(scope).then(function(f) {
|
||||
frame = f;
|
||||
});
|
||||
|
||||
// Wait some time to allow frame loading to proceed. It should not,
|
||||
// however, if the fetch event is blocked on the activate. I don't
|
||||
// see any way to force this race without a timeout, unfortunately.
|
||||
return new Promise(function(resolve) {
|
||||
setTimeout(resolve, 1000);
|
||||
});
|
||||
}).then(function() {
|
||||
assert_equals(frame, undefined, 'frame should not be loaded');
|
||||
assert_equals(registration.active.scriptURL, expected_url,
|
||||
'active worker should be present');
|
||||
assert_equals(registration.active.state, 'activating',
|
||||
'active worker should be in activating state');
|
||||
|
||||
// This signals the activate event to complete. The frame should now
|
||||
// load.
|
||||
registration.active.postMessage('GO');
|
||||
return frameLoadPromise;
|
||||
}).then(function() {
|
||||
assert_equals(frame.contentWindow.navigator.serviceWorker.controller.scriptURL,
|
||||
expected_url, 'frame should now be loaded and controlled');
|
||||
assert_equals(registration.active.state, 'activated',
|
||||
'active worker should be in activated state');
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
}).catch(unreached_rejection(t));
|
||||
}, 'Fetch events should wait for the activate event to complete.');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
var documentURL = 'no-such-worker';
|
||||
navigator.serviceWorker.getRegistration(documentURL)
|
||||
.then(function(value) {
|
||||
assert_equals(value, undefined,
|
||||
'getRegistration should resolve with undefined');
|
||||
t.done();
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'getRegistration');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/scope/getregistration/normal';
|
||||
var registration;
|
||||
service_worker_unregister_and_register(t, 'resources/empty-worker.js',
|
||||
scope)
|
||||
.then(function(r) {
|
||||
registration = r;
|
||||
return navigator.serviceWorker.getRegistration(scope);
|
||||
})
|
||||
.then(function(value) {
|
||||
assert_equals(
|
||||
value, registration,
|
||||
'getRegistration should resolve to the same registration object');
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Register then getRegistration');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/scope/getregistration/url-with-fragment';
|
||||
var documentURL = scope + '#ref';
|
||||
var registration;
|
||||
service_worker_unregister_and_register(t, 'resources/empty-worker.js',
|
||||
scope)
|
||||
.then(function(r) {
|
||||
registration = r;
|
||||
return navigator.serviceWorker.getRegistration(documentURL);
|
||||
})
|
||||
.then(function(value) {
|
||||
assert_equals(
|
||||
value, registration,
|
||||
'getRegistration should resolve to the same registration object');
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Register then getRegistration with a URL having a fragment');
|
||||
|
||||
async_test(function(t) {
|
||||
var documentURL = 'http://example.com/';
|
||||
navigator.serviceWorker.getRegistration(documentURL)
|
||||
.then(function() {
|
||||
assert_unreached(
|
||||
'getRegistration with an out of origin URL should fail');
|
||||
}, function(reason) {
|
||||
assert_equals(
|
||||
reason.name, 'SecurityError',
|
||||
'getRegistration with an out of origin URL should fail');
|
||||
t.done();
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'getRegistration with a cross origin URL');
|
||||
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/scope/getregistration/register-unregister';
|
||||
service_worker_unregister_and_register(t, 'resources/empty-worker.js',
|
||||
scope)
|
||||
.then(function(registration) {
|
||||
return registration.unregister();
|
||||
})
|
||||
.then(function() {
|
||||
return navigator.serviceWorker.getRegistration(scope);
|
||||
})
|
||||
.then(function(value) {
|
||||
assert_equals(value, undefined,
|
||||
'getRegistration should resolve with undefined');
|
||||
t.done();
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'Register then Unregister then getRegistration');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: getRegistrations()</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script src="resources/get-host-info.sub.js"></script>
|
||||
<script src="../fetch/resources/fetch-test-helpers.sub.js"></script>
|
||||
<script>
|
||||
// Purge the existing registrations for the origin.
|
||||
// getRegistrations() is used in order to avoid adding additional complexity
|
||||
// e.g. adding an internal function.
|
||||
promise_test(function(t) {
|
||||
return navigator.serviceWorker.getRegistrations()
|
||||
.then(function(registrations) {
|
||||
return registrations.reduce(function(sequence, registration) {
|
||||
return sequence.then(function() {
|
||||
return registration.unregister();
|
||||
});
|
||||
}, Promise.resolve());
|
||||
});
|
||||
}, 'Purge the existing registrations.');
|
||||
|
||||
promise_test(function(t) {
|
||||
return navigator.serviceWorker.getRegistrations()
|
||||
.then(function(value) {
|
||||
assert_array_equals(
|
||||
value,
|
||||
[],
|
||||
'getRegistrations should resolve with an empty array.');
|
||||
});
|
||||
}, 'getRegistrations');
|
||||
|
||||
promise_test(function(t) {
|
||||
var scope = 'resources/scope/getregistrations/normal';
|
||||
var script = 'resources/empty-worker.js';
|
||||
var registrations = [];
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(r) {
|
||||
registrations.push(r);
|
||||
return navigator.serviceWorker.getRegistrations();
|
||||
})
|
||||
.then(function(value) {
|
||||
assert_array_equals(
|
||||
value,
|
||||
registrations,
|
||||
'getRegistrations should resolve with array of registrations.');
|
||||
return service_worker_unregister(t, scope);
|
||||
});
|
||||
}, 'Register then getRegistrations');
|
||||
|
||||
promise_test(function(t) {
|
||||
var scope1 = 'resources/scope/getregistrations/scope1';
|
||||
var scope2 = 'resources/scope/getregistrations/scope2';
|
||||
var script = 'resources/empty-worker.js';
|
||||
var registrations = [];
|
||||
return service_worker_unregister_and_register(t, script, scope1)
|
||||
.then(function(r) {
|
||||
registrations.push(r);
|
||||
return service_worker_unregister_and_register(t, script, scope2);
|
||||
})
|
||||
.then(function(r) {
|
||||
registrations.push(r);
|
||||
return navigator.serviceWorker.getRegistrations();
|
||||
})
|
||||
.then(function(value) {
|
||||
assert_array_equals(
|
||||
value,
|
||||
registrations,
|
||||
'getRegistrations should resolve with array of registrations.');
|
||||
return service_worker_unregister(t, scope1);
|
||||
})
|
||||
.then(function() {
|
||||
return service_worker_unregister(t, scope2);
|
||||
});
|
||||
}, 'Register multiple times then getRegistrations');
|
||||
|
||||
promise_test(function(t) {
|
||||
var scope = 'resources/scope/getregistrations/register-unregister';
|
||||
var script = 'resources/empty-worker.js';
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(registration) {
|
||||
return registration.unregister();
|
||||
})
|
||||
.then(function() {
|
||||
return navigator.serviceWorker.getRegistrations();
|
||||
})
|
||||
.then(function(value) {
|
||||
assert_array_equals(
|
||||
value,
|
||||
[],
|
||||
'getRegistrations should resolve with an empty array.');
|
||||
});
|
||||
}, 'Register then Unregister then getRegistrations');
|
||||
|
||||
promise_test(function(t) {
|
||||
var scope = 'resources/scope/getregistrations/register-unregister-controlled';
|
||||
var script = 'resources/empty-worker.js';
|
||||
var registrations;
|
||||
var frame;
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(r) {
|
||||
registration = r;
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(function() {
|
||||
return with_iframe(scope);
|
||||
})
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return registration.unregister();
|
||||
})
|
||||
.then(function() {
|
||||
return navigator.serviceWorker.getRegistrations();
|
||||
})
|
||||
.then(function(value) {
|
||||
assert_array_equals(
|
||||
value,
|
||||
[],
|
||||
'getRegistrations should resolve with an empty array.');
|
||||
assert_equals(registration.installing, null);
|
||||
assert_equals(registration.waiting, null);
|
||||
assert_equals(registration.active.state, 'activated');
|
||||
frame.remove();
|
||||
});
|
||||
}, 'Register then Unregister with controlled frame then getRegistrations');
|
||||
|
||||
promise_test(function(t) {
|
||||
var host_info = get_host_info();
|
||||
// Rewrite the url to point to remote origin.
|
||||
var frame_same_origin_url = new URL("resources/frame-for-getregistrations.html", window.location);
|
||||
var frame_url = host_info['HTTPS_REMOTE_ORIGIN'] + frame_same_origin_url.pathname;
|
||||
var scope = 'resources/scope-for-getregistrations';
|
||||
var script = 'resources/empty-worker.js';
|
||||
var frame;
|
||||
var registrations = [];
|
||||
|
||||
// Loads an iframe and waits for 'ready' message from it to resolve promise.
|
||||
// Caller is responsible for removing frame.
|
||||
function with_iframe_ready(url) {
|
||||
return new Promise(function(resolve) {
|
||||
var frame = document.createElement('iframe');
|
||||
frame.src = url;
|
||||
window.addEventListener('message', function onMessage(e) {
|
||||
window.removeEventListener('message', onMessage);
|
||||
if (e.data == 'ready') {
|
||||
resolve(frame);
|
||||
}
|
||||
});
|
||||
document.body.appendChild(frame);
|
||||
});
|
||||
}
|
||||
|
||||
// We need this special frame loading function because the frame is going
|
||||
// to register it's own service worker and there is the possibility that that
|
||||
// register() finishes after the register() for the same domain later in the
|
||||
// test. So we have to wait until the cross origin register() is done, and not
|
||||
// just until the frame loads.
|
||||
return with_iframe_ready(frame_url)
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
return service_worker_unregister_and_register(t, script, scope);
|
||||
})
|
||||
.then(function(r) {
|
||||
registrations.push(r);
|
||||
return navigator.serviceWorker.getRegistrations();
|
||||
})
|
||||
.then(function(value) {
|
||||
assert_array_equals(
|
||||
value,
|
||||
registrations,
|
||||
'getRegistrations should only return same origin registrations.');
|
||||
|
||||
var channel = new MessageChannel();
|
||||
var resolve;
|
||||
var p = new Promise(function(r) { resolve = r; });
|
||||
|
||||
channel.port1.onmessage = function(e) {
|
||||
if (e.data == 'unregistered')
|
||||
resolve();
|
||||
};
|
||||
frame.contentWindow.postMessage('unregister', '*', [channel.port2]);
|
||||
return p;
|
||||
})
|
||||
.then(function() {
|
||||
frame.remove();
|
||||
return service_worker_unregister(t, scope);
|
||||
});
|
||||
}, 'getRegistrations promise resolves only with same origin registrations.');
|
||||
|
||||
done();
|
||||
</script>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: Indexed DB</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
async_test(function(t) {
|
||||
var scope = 'resources/blank.html';
|
||||
service_worker_unregister_and_register(
|
||||
t, 'resources/indexeddb-worker.js', scope)
|
||||
.then(function(registration) {
|
||||
var sw = registration.installing;
|
||||
var messageChannel = new MessageChannel();
|
||||
messageChannel.port1.onmessage = t.step_func(onMessage);
|
||||
sw.postMessage({port: messageChannel.port2}, [messageChannel.port2]);
|
||||
})
|
||||
.catch(unreached_rejection(t));
|
||||
|
||||
function onMessage() {
|
||||
var openRequest = indexedDB.open('db');
|
||||
openRequest.onsuccess = t.step_func(function() {
|
||||
var db = openRequest.result;
|
||||
var tx = db.transaction('store');
|
||||
var store = tx.objectStore('store');
|
||||
var getRequest = store.get('key');
|
||||
getRequest.onsuccess = t.step_func(function() {
|
||||
assert_equals(
|
||||
getRequest.result, 'value',
|
||||
'The get() result should match what the worker put().');
|
||||
service_worker_unregister_and_done(t, scope);
|
||||
});
|
||||
});
|
||||
}
|
||||
}, 'Verify Indexed DB operation in a Service Worker');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="resources/testharness-helpers.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
function wait_for_install_event(worker) {
|
||||
return new Promise(function(resolve) {
|
||||
worker.addEventListener('statechange', function(event) {
|
||||
if (worker.state == 'installed')
|
||||
resolve(true);
|
||||
else if (worker.state == 'redundant')
|
||||
resolve(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
promise_test(function(t) {
|
||||
var script = 'resources/install-event-type-worker.js';
|
||||
var scope = 'resources/install-event-type';
|
||||
return service_worker_unregister_and_register(t, script, scope)
|
||||
.then(function(registration) {
|
||||
return wait_for_install_event(registration.installing);
|
||||
})
|
||||
.then(function(did_install) {
|
||||
assert_true(did_install, 'The worker was installed');
|
||||
})
|
||||
}, 'install event type');
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<title>ServiceWorker: navigator.serviceWorker.installing</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
// "installing" is set
|
||||
async_test(function(t) {
|
||||
var step = t.step_func.bind(t);
|
||||
var url = 'resources/empty-worker.js';
|
||||
var scope = 'resources/blank.html';
|
||||
var frame;
|
||||
|
||||
service_worker_unregister(t, scope)
|
||||
.then(step(function() { return with_iframe(scope); }))
|
||||
.then(step(function(f) {
|
||||
frame = f;
|
||||
return navigator.serviceWorker.register(url, {scope: scope});
|
||||
}))
|
||||
.then(step(function(registration) {
|
||||
var container = frame.contentWindow.navigator.serviceWorker;
|
||||
assert_equals(container.controller, null);
|
||||
assert_equals(registration.active, null);
|
||||
assert_equals(registration.waiting, null);
|
||||
assert_equals(registration.installing.scriptURL, normalizeURL(url));
|
||||
|
||||
// FIXME: Add a test for a frame created after installation.
|
||||
// Should the existing frame ("frame") block activation?
|
||||
}))
|
||||
.then(step(function() {
|
||||
frame.remove();
|
||||
return service_worker_unregister_and_done(t, scope);
|
||||
}))
|
||||
.catch(unreached_rejection(t));
|
||||
}, 'installing is set');
|
||||
</script>
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue