Commit 238d82b2 authored by Matt Falkenhagen's avatar Matt Falkenhagen Committed by Commit Bot

Reland: service worker: Add WPT tests for resultingClientId.

Reland of r592363, which was reverted due to timeouts. The timeout issue
should be fixed by r594723, which changed the mechanism of sending the
"last url" message from the navigated frame.

Other revisions from the original patch:
- Removed the unused expected_tags parameter from the default
  variant test function.
- Removed the dummy message resolver for "last url" from
  client_variant_test, which is no longer needed after the change
  mentioned above.
- Fixed a bug in redirect-worker.js's getClients(), where
  we returned instead of continued to the next iteration.

Original commit description:
> This adds a ?client variant to navigation-redirect.https.html, which
> does a lot of redirect tests. This tests the following:
> - resultingClientId is the id of the client, if one was created via
>   that request.
> - get(resultingClientId) for requests that did not create a client
>   resolves with undefined.
> - resultingClientId is reset on cross-origin redirects.
> - Client.url is the creation URL.
>
> Bug: 778497
> Change-Id: I08387e96a97df4656d800637862b67b7c8466e14
> Reviewed-on: https://chromium-review.googlesource.com/1206054
> Reviewed-by: Makoto Shimazu <shimazu@chromium.org>
> Commit-Queue: Matt Falkenhagen <falken@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#592363}

Bug: 778497
Change-Id: I770f98cef7618c89c1b54245bc89a9c53a19bd5c
Reviewed-on: https://chromium-review.googlesource.com/1250306Reviewed-by: default avatarBen Kelly <wanderview@chromium.org>
Commit-Queue: Matt Falkenhagen <falken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#595249}
parent 75d687cb
......@@ -11,6 +11,7 @@ FAIL SW-fallbacked redirect to same-origin same-scope with different hash fragme
PASS SW-fallbacked redirect to same-origin other-scope.
PASS SW-fallbacked redirect to other-origin out-scope.
PASS SW-fallbacked redirect to other-origin in-scope.
PASS SW-fallbacked redirect to other-origin and back to same-origin.
PASS SW-generated redirect to same-origin out-scope.
FAIL SW-generated redirect to same-origin out-scope with a hash fragment. assert_object_equals: Intercepted URLs should match. property "0" expected ["https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F#ref"] got ["https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F"]
FAIL SW-generated redirect to same-origin out-scope with different hash fragments. assert_object_equals: Intercepted URLs should match. property "0" expected ["https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F%23ref2#ref"] got ["https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F%23ref2"]
......
<!DOCTYPE html>
<title>Service Worker: Navigation redirection</title>
<meta name="timeout" content="long">
<!-- empty variant tests document.location and intercepted URLs -->
<meta name="variant" content="">
<!-- client variant tests the Clients API (resultingClientId and Client.url) -->
<meta name="variant" content="?client">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
......@@ -76,36 +81,208 @@ async function check_all_intercepted_urls(expected_urls) {
assert_object_equals(urls, expected_urls, 'Intercepted URLs should match.');
}
// Checks |clients| returned from a worker. Only the client matching
// |expected_final_client_tag| should be found. Returns true if a client was
// found. Note that the final client is not necessarily found by this worker,
// if the client is cross-origin.
//
// |clients| is an object like:
// {x: {found: true, id: id1, url: url1}, b: {found: false}}
function check_clients(clients,
expected_id,
expected_url,
expected_final_client_tag,
worker_name) {
let found = false;
Object.keys(clients).forEach(key => {
const info = clients[key];
if (info.found) {
assert_true(expected_final_client_tag,
`${worker_name} client tag exists`);
assert_equals(key, expected_final_client_tag,
`${worker_name} client tag matches`);
assert_equals(info.id, expected_id, `${worker_name} client id`);
assert_equals(info.url, expected_url, `${worker_name} client url`);
found = true;
}
});
return found;
}
function check_resulting_client_ids(infos, expected_infos, actual_ids, worker) {
assert_equals(infos.length, expected_infos.length,
`request length for ${worker}`);
for (var i = 0; i < infos.length; i++) {
const tag = expected_infos[i].resultingClientIdTag;
const url = expected_infos[i].url;
const actual_id = infos[i].resultingClientId;
const expected_id = actual_ids[tag];
assert_equals(typeof(actual_id), 'string',
`resultingClientId for ${url} request to ${worker}`);
if (expected_id) {
assert_equals(requestInfos[0], expected_id,
`resultingClientId for ${url} request to ${worker}`);
} else {
actual_ids[key] = actual_id;
}
}
}
// Creates an iframe and navigates to |url|, which is expected to start a chain
// of redirects.
// - |expected_last_url| is the expected window.location after the
// navigation.
//
// - |expected_request_infos| is the expected requests that the service workers
// were dispatched fetch events for. The format is:
// [
// [{url: url1}, {url: url2}], // requests from workers[0],
// [{url: url1}, // requests from workers[1],
// [{url: url1}, {url: url2}] // requests from cross-origin worker
// [
// // Requests received by workers[0].
// {url: url1, resultingClientIdTag: 'a'},
// {url: url2, resultingClientIdTag: 'a'}
// ],
// [
// // Requests received by workers[1].
// {url: url3, resultingClientIdTag: 'a'}
// ],
// [
// // Requests received by the cross-origin worker.
// {url: url4, resultingClientIdTag: 'x'}
// {url: url5, resultingClientIdTag: 'x'}
// ]
// ]
// Here, |url| is |event.request.url| and |resultingClientIdTag| represents
// |event.resultingClientId|. Since the actual client ids are not known
// beforehand, the expectation isn't the literal expected value, but all equal
// tags must map to the same actual id.
//
// - |expected_final_client_tag| is the resultingClientIdTag that is
// expected to map to the created client's id. This is null if there
// is no such tag, which can happen when the final request was a cross-origin
// redirect to out-scope, so no worker received a fetch event whose
// resultingClientId is the id of the resulting client.
//
// In the example above:
// - workers[0] receives two requests with the same resultingClientId.
// - workers[1] receives one request also with that resultingClientId.
// - The cross-origin worker receives two requests with the same
// resultingClientId which differs from the previous one.
// - Assuming |expected_final_client_tag| is 'x', then the created
// client has the id seen by the cross-origin worker above.
function redirect_test(url,
expected_last_url,
expected_request_infos,
expected_final_client_tag,
test_name) {
promise_test(async t => {
const frame = await with_iframe(url);
t.add_cleanup(() => { frame.remove(); });
const expected_intercepted_urls = expected_request_infos.map(requests => {
return requests.map(info => {
return info.url;
});
});
await check_all_intercepted_urls(expected_intercepted_urls);
const last_url = await send_to_iframe(frame, 'getLocation');
assert_equals(last_url, expected_last_url, 'Last URL should match.');
// Switch on variant.
if (document.location.search == '?client') {
return client_variant_test(url, expected_last_url, expected_request_infos,
expected_final_client_tag, test_name);
}
return default_variant_test(url, expected_last_url, expected_request_infos,
frame, test_name);
}, test_name);
}
// The default variant tests the request interception chain and
// resulting document.location.
async function default_variant_test(url,
expected_last_url,
expected_request_infos,
frame,
test_name) {
const expected_intercepted_urls = expected_request_infos.map(
requests_for_worker => {
return requests_for_worker.map(info => {
return info.url;
});
});
await check_all_intercepted_urls(expected_intercepted_urls);
const last_url = await send_to_iframe(frame, 'getLocation');
assert_equals(last_url, expected_last_url, 'Last URL should match.');
}
// The "client" variant tests the Clients API using resultingClientId.
async function client_variant_test(url,
expected_last_url,
expected_request_infos,
expected_final_client_tag,
test_name) {
// Request infos is an array like:
// [
// [{url: url1, resultingClientIdTag: tag1}],
// [{url: url2, resultingClientIdTag: tag2}],
// [{url: url3: resultingClientIdTag: tag3}]
// ]
const requestInfos = await get_all_request_infos();
// We check the actual infos against the expected ones, and learn the
// actual ids as we go.
const actual_ids = {};
check_resulting_client_ids(requestInfos[0],
expected_request_infos[0],
actual_ids,
'worker0');
check_resulting_client_ids(requestInfos[1],
expected_request_infos[1],
actual_ids,
'worker1');
check_resulting_client_ids(requestInfos[2],
expected_request_infos[2],
actual_ids,
'crossOriginWorker');
// Now |actual_ids| maps tag to actual id:
// {x: id1, b: id2, c: id3}
// Ask each worker to try to resolve the actual ids to clients.
// Only |expected_final_client_tag| should resolve to a client.
const client_infos = await get_all_clients(actual_ids);
// Client infos is an object like:
// {
// worker0: {x: {found: true, id: id1, url: url1}, b: {found: false}},
// worker1: {x: {found: true, id: id1, url: url1}},
// crossOriginWorker: {x: {found: false}}, {b: {found: false}}
// }
//
// Now check each client info. check_clients() verifies each info: only
// |expected_final_client_tag| should ever be found and the found client
// should have the expected url and id. A wrinkle is that not all workers
// will find the client, if they are cross-origin to the client. This
// means check_clients() trivially passes if no clients are found. So
// additionally check that at least one worker found the client (|found|),
// if that was expected (|expect_found|).
let found = false;
const expect_found = !!expected_final_client_tag;
const expected_id = actual_ids[expected_final_client_tag];
found = check_clients(client_infos.worker0,
expected_id,
expected_last_url,
expected_final_client_tag,
'worker0');
found = check_clients(client_infos.worker1,
expected_id,
expected_last_url,
expected_final_client_tag,
'worker1') || found;
found = check_clients(client_infos.crossOriginWorker,
expected_id,
expected_last_url,
expected_final_client_tag,
'crossOriginWorker') || found;
assert_equals(found, expect_found, 'client found');
if (!expect_found) {
// TODO(falken): Ask the other origin frame if it has a client of the
// expected URL.
}
}
window.addEventListener('message', on_message, false);
function on_message(e) {
......@@ -129,6 +306,27 @@ function send_to_iframe(frame, message) {
});
}
async function get_all_clients(actual_ids) {
const client_infos = {};
client_infos['worker0'] = await get_clients(workers[0], actual_ids);
client_infos['worker1'] = await get_clients(workers[1], actual_ids);
client_infos['crossOriginWorker'] =
await send_to_iframe(other_origin_frame,
{command: 'get_clients', actual_ids});
return client_infos;
}
function get_clients(worker, actual_ids) {
return new Promise(resolve => {
var channel = new MessageChannel();
channel.port1.onmessage = (msg) => {
resolve(msg.data.clients);
};
worker.postMessage({command: 'getClients', actual_ids, port: channel.port2},
[channel.port2]);
});
}
// Returns an array of the URLs that |worker| received fetch events for:
// [url1, url2]
async function get_intercepted_urls(worker) {
......@@ -138,7 +336,10 @@ async function get_intercepted_urls(worker) {
// Returns the requests that |worker| received fetch events for. The return
// value is an array of format:
// [{url: url1}, {url: url2}]
// [
// {url: url1, resultingClientId: id},
// {url: url2, resultingClientId: id}
// ]
function get_request_infos(worker) {
return new Promise(resolve => {
var channel = new MessageChannel();
......@@ -150,6 +351,29 @@ function get_request_infos(worker) {
});
}
// Returns an array of the requests the workers received fetch events for:
// [
// // Requests from workers[0].
// [
// {url: url1, resultingClientIdTag: tag1},
// {url: url2, resultingClientIdTag: tag1}
// ],
//
// // Requests from workers[1].
// [{url: url3, resultingClientIdTag: tag2}],
//
// // Requests from the cross-origin worker.
// []
// ]
async function get_all_request_infos() {
const request_infos = [];
request_infos.push(await get_request_infos(workers[0]));
request_infos.push(await get_request_infos(workers[1]));
request_infos.push(await send_to_iframe(other_origin_frame,
{command: 'get_request_infos'}));
return request_infos;
}
let url;
let url1;
let url2;
......@@ -159,7 +383,8 @@ url = SCOPE1;
redirect_test(
OUT_SCOPE + 'url=' + encodeURIComponent(url),
url,
[[{url}], [], []],
[[{url, resultingClientIdTag: 'x'}], [], []],
'x',
'Normal redirect to same-origin scope.');
......@@ -167,30 +392,33 @@ url = SCOPE1 + '#ref';
redirect_test(
OUT_SCOPE + 'url=' + encodeURIComponent(SCOPE1) + '#ref',
url,
[[{url}], [], []],
[[{url, resultingClientIdTag: 'x'}], [], []],
'x',
'Normal redirect to same-origin scope with a hash fragment.');
url = SCOPE1 + '#ref2';
redirect_test(
OUT_SCOPE + 'url=' + encodeURIComponent(url) + '#ref',
url,
[[{url}], [], []],
[[{url, resultingClientIdTag: 'x'}], [], []],
'x',
'Normal redirect to same-origin scope with different hash fragments.');
url = OTHER_ORIGIN_SCOPE;
redirect_test(
OUT_SCOPE + 'url=' + encodeURIComponent(url),
url,
[[], [], [{url}]],
[[], [], [{url, resultingClientIdTag: 'x'}]],
'x',
'Normal redirect to other-origin scope.');
// SW fallbacked redirect. SW doesn't handle the fetch request.
url = SCOPE1 + 'url=' + encodeURIComponent(OUT_SCOPE);
redirect_test(
url,
OUT_SCOPE,
[[{url}], [], []],
[[{url, resultingClientIdTag: 'x'}], [], []],
'x',
'SW-fallbacked redirect to same-origin out-scope.');
url1 = SCOPE1 + 'url=' + encodeURIComponent(SCOPE1);
......@@ -198,7 +426,15 @@ url2 = SCOPE1;
redirect_test(
url1,
url2,
[[{url: url1}, {url: url2}], [], []],
[
[
{url: url1, resultingClientIdTag: 'x'},
{url: url2, resultingClientIdTag: 'x'}
],
[],
[]
],
'x',
'SW-fallbacked redirect to same-origin same-scope.');
url1 = SCOPE1 + 'url=' + encodeURIComponent(SCOPE1) + '#ref';
......@@ -206,7 +442,15 @@ url2 = SCOPE1 + '#ref';
redirect_test(
url1,
url2,
[[{url: url1}, {url: url2}], [], []],
[
[
{url: url1, resultingClientIdTag: 'x'},
{url: url2, resultingClientIdTag: 'x'}
],
[],
[]
],
'x',
'SW-fallbacked redirect to same-origin same-scope with a hash fragment.');
url1 = SCOPE1 + 'url=' + encodeURIComponent(SCOPE1 + '#ref2') + '#ref';
......@@ -214,7 +458,15 @@ url2 = SCOPE1 + '#ref2';
redirect_test(
url1,
url2,
[[{url: url1}, {url: url2}], [], []],
[
[
{url: url1, resultingClientIdTag: 'x'},
{url: url2, resultingClientIdTag: 'x'}
],
[],
[]
],
'x',
'SW-fallbacked redirect to same-origin same-scope with different hash ' +
'fragments.');
......@@ -223,7 +475,12 @@ url2 = SCOPE2;
redirect_test(
url1,
url2,
[[{url: url1}], [{url: url2}], []],
[
[{url: url1, resultingClientIdTag: 'x'}],
[{url: url2, resultingClientIdTag: 'x'}],
[]
],
'x',
'SW-fallbacked redirect to same-origin other-scope.');
url1 = SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE);
......@@ -231,7 +488,8 @@ url2 = OTHER_ORIGIN_OUT_SCOPE;
redirect_test(
url1,
url2,
[[{url: url1}], [], []],
[[{url: url1, resultingClientIdTag: 'a'}], [], []],
'x',
'SW-fallbacked redirect to other-origin out-scope.');
url1 = SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE);
......@@ -239,10 +497,32 @@ url2 = OTHER_ORIGIN_SCOPE;
redirect_test(
url1,
url2,
[[{url: url1}], [], [{url: url2}]],
[
[{url: url1, resultingClientIdTag: 'a'}],
[],
[{url: url2, resultingClientIdTag: 'x'}]
],
'x',
'SW-fallbacked redirect to other-origin in-scope.');
url3 = SCOPE1;
url2 = OTHER_ORIGIN_SCOPE + 'url=' + encodeURIComponent(url3);
url1 = SCOPE1 + 'url=' + encodeURIComponent(url2);
redirect_test(
url1,
url3,
[
[
{url: url1, resultingClientIdTag: 'a'},
{url: url3, resultingClientIdTag: 'x'}
],
[],
[{url: url2, resultingClientIdTag: 'b'}]
],
'x',
'SW-fallbacked redirect to other-origin and back to same-origin.');
// SW generated redirect.
// SW: event.respondWith(Response.redirect(params['url']));
url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE);
......@@ -250,7 +530,8 @@ url2 = OUT_SCOPE;
redirect_test(
url1,
url2,
[[{url: url1}], [], []],
[[{url: url1, resultingClientIdTag: 'a'}], [], []],
null,
'SW-generated redirect to same-origin out-scope.');
url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE) + '#ref';
......@@ -258,7 +539,8 @@ url2 = OUT_SCOPE + '#ref';
redirect_test(
url1,
url2,
[[{url: url1}], [], []],
[[{url: url1, resultingClientIdTag: 'x'}], [], []],
'x',
'SW-generated redirect to same-origin out-scope with a hash fragment.');
url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE + '#ref2') + '#ref';
......@@ -266,7 +548,8 @@ url2 = OUT_SCOPE + '#ref2';
redirect_test(
url1,
url2,
[[{url: url1}], [], []],
[[{url: url1, resultingClientIdTag: 'x'}], [], []],
'x',
'SW-generated redirect to same-origin out-scope with different hash ' +
'fragments.');
......@@ -275,7 +558,15 @@ url2 = SCOPE1;
redirect_test(
url1,
url2,
[[{url: url1}, {url: url2}], [], []],
[
[
{url: url1, resultingClientIdTag: 'x'},
{url: url2, resultingClientIdTag: 'x'}
],
[],
[]
],
'x',
'SW-generated redirect to same-origin same-scope.');
url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(SCOPE2);
......@@ -283,7 +574,12 @@ url2 = SCOPE2;
redirect_test(
url1,
url2,
[[{url: url1}], [{url: url2}], []],
[
[{url: url1, resultingClientIdTag: 'x'}],
[{url: url2, resultingClientIdTag: 'x'}],
[]
],
'x',
'SW-generated redirect to same-origin other-scope.');
url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE);
......@@ -291,7 +587,8 @@ url2 = OTHER_ORIGIN_OUT_SCOPE;
redirect_test(
url1,
url2,
[[{url: url1}], [], []],
[[{url: url1, resultingClientIdTag: 'a'}], [], []],
null,
'SW-generated redirect to other-origin out-scope.');
url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE);
......@@ -300,10 +597,11 @@ redirect_test(
url1,
url2,
[
[{url: url1}],
[{url: url1, resultingClientIdTag: 'a'}],
[],
[{url: url2}]
[{url: url2, resultingClientIdTag: 'x'}]
],
'x',
'SW-generated redirect to other-origin in-scope.');
......@@ -314,7 +612,8 @@ url2 = OUT_SCOPE;
redirect_test(
url1,
url2,
[[{url: url1}], [], []],
[[{url: url1, resultingClientIdTag: 'x'}], [], []],
'x',
'SW-fetched redirect to same-origin out-scope.');
url1 = SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(SCOPE1);
......@@ -322,7 +621,15 @@ url2 = SCOPE1;
redirect_test(
url1,
url2,
[[{url: url1}, {url: url2}], [], []],
[
[
{url: url1, resultingClientIdTag: 'x'},
{url: url2, resultingClientIdTag: 'x'}
],
[],
[]
],
'x',
'SW-fetched redirect to same-origin same-scope.');
url1 = SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(SCOPE2);
......@@ -331,10 +638,11 @@ redirect_test(
url1,
url2,
[
[{url: url1}],
[{url: url2}],
[{url: url1, resultingClientIdTag: 'x'}],
[{url: url2, resultingClientIdTag: 'x'}],
[]
],
'x',
'SW-fetched redirect to same-origin other-scope.');
url1 = SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE);
......@@ -342,7 +650,8 @@ url2 = OTHER_ORIGIN_OUT_SCOPE;
redirect_test(
url1,
url2,
[[{url: url1}], [], []],
[[{url: url1, resultingClientIdTag: 'a'}], [], []],
null,
'SW-fetched redirect to other-origin out-scope.');
url1 = SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE);
......@@ -351,10 +660,11 @@ redirect_test(
url1,
url2,
[
[{url: url1}],
[{url: url1, resultingClientIdTag: 'a'}],
[],
[{url: url2}]
[{url: url2, resultingClientIdTag: 'x'}]
],
'x',
'SW-fetched redirect to other-origin in-scope.');
......@@ -366,7 +676,8 @@ url2 = OUT_SCOPE;
redirect_test(
url1,
url2,
[[{url: url1}], [], []],
[[{url: url1, resultingClientIdTag: 'x'}], [], []],
'x',
'Redirect to same-origin out-scope with opaque redirect response.');
url1 = SCOPE1 + 'sw=manual&url=' + encodeURIComponent(SCOPE1);
......@@ -374,7 +685,15 @@ url2 = SCOPE1;
redirect_test(
url1,
url2,
[[{url: url1}, {url: url2}], [], []],
[
[
{url: url1, resultingClientIdTag: 'x'},
{url: url2, resultingClientIdTag: 'x'}
],
[],
[]
],
'x',
'Redirect to same-origin same-scope with opaque redirect response.');
url1 = SCOPE1 + 'sw=manual&url=' + encodeURIComponent(SCOPE2);
......@@ -382,7 +701,12 @@ url2 = SCOPE2;
redirect_test(
url1,
url2,
[[{url: url1}], [{url: url2}], []],
[
[{url: url1, resultingClientIdTag: 'x'}],
[{url: url2, resultingClientIdTag: 'x'}],
[]
],
'x',
'Redirect to same-origin other-scope with opaque redirect response.');
url1 = SCOPE1 + 'sw=manual&url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE);
......@@ -390,7 +714,8 @@ url2 = OTHER_ORIGIN_OUT_SCOPE;
redirect_test(
url1,
url2,
[[{url: url1}], [], []],
[[{url: url1, resultingClientIdTag: 'a'}], [], []],
null,
'Redirect to other-origin out-scope with opaque redirect response.');
url1 = SCOPE1 + 'sw=manual&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE);
......@@ -398,12 +723,18 @@ url2 = OTHER_ORIGIN_SCOPE;
redirect_test(
url1,
url2,
[[{url: url1}], [], [{url: url2}]],
[
[{url: url1, resultingClientIdTag: 'a'}],
[],
[{url: url2, resultingClientIdTag: 'x'}]
],
'x',
'Redirect to other-origin in-scope with opaque redirect response.');
url= SCOPE1 + 'sw=manual&noLocationRedirect';
redirect_test(
url, url, [[{url}], [], []],
url, url, [[{url, resultingClientIdTag: 'x'}], [], []],
'x',
'No location redirect response.');
......@@ -414,7 +745,8 @@ url2 = OUT_SCOPE;
redirect_test(
url1,
url2,
[[{url: url1}], [], []],
[[{url: url1, resultingClientIdTag: 'x'}], [], []],
'x',
'Redirect to same-origin out-scope with opaque redirect response which ' +
'is passed through Cache.');
......@@ -424,10 +756,14 @@ redirect_test(
url1,
url2,
[
[{url: url1}, {url: url2}],
[
{url: url1, resultingClientIdTag: 'x'},
{url: url2, resultingClientIdTag: 'x'}
],
[],
[]
],
'x',
'Redirect to same-origin same-scope with opaque redirect response which ' +
'is passed through Cache.');
......@@ -437,10 +773,11 @@ redirect_test(
url1,
url2,
[
[{url: url1}],
[{url: url2}],
[{url: url1, resultingClientIdTag: 'x'}],
[{url: url2, resultingClientIdTag: 'x'}],
[]
],
'x',
'Redirect to same-origin other-scope with opaque redirect response which ' +
'is passed through Cache.');
......@@ -450,7 +787,8 @@ url2 = OTHER_ORIGIN_OUT_SCOPE;
redirect_test(
url1,
url2,
[[{url: url1}], [], []],
[[{url: url1, resultingClientIdTag: 'a'}], [], []],
null,
'Redirect to other-origin out-scope with opaque redirect response which ' +
'is passed through Cache.');
......@@ -461,10 +799,11 @@ redirect_test(
url1,
url2,
[
[{url: url1}],
[{url: url1, resultingClientIdTag: 'a'}],
[],
[{url: url2}],
[{url: url2, resultingClientIdTag: 'x'}],
],
'x',
'Redirect to other-origin in-scope with opaque redirect response which ' +
'is passed through Cache.');
......@@ -472,7 +811,8 @@ url = SCOPE1 + 'sw=manualThroughCache&noLocationRedirect';
redirect_test(
url,
url,
[[{url}], [], []],
[[{url, resultingClientIdTag: 'x'}], [], []],
'x',
'No location redirect response via Cache.');
// Clean up the test environment. This promise_test() needs to be the last one.
......
This is a testharness.js-based test.
PASS initialize global state
FAIL Normal redirect to same-origin scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py? request to worker0 expected "string" but got "undefined"
FAIL Normal redirect to same-origin scope with a hash fragment. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?#ref request to worker0 expected "string" but got "undefined"
FAIL Normal redirect to same-origin scope with different hash fragments. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?#ref2 request to worker0 expected "string" but got "undefined"
FAIL Normal redirect to other-origin scope. assert_equals: resultingClientId for https://www1.web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py? request to crossOriginWorker expected "string" but got "undefined"
FAIL SW-fallbacked redirect to same-origin out-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-fallbacked redirect to same-origin same-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-fallbacked redirect to same-origin same-scope with a hash fragment. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F#ref request to worker0 expected "string" but got "undefined"
FAIL SW-fallbacked redirect to same-origin same-scope with different hash fragments. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F%23ref2#ref request to worker0 expected "string" but got "undefined"
FAIL SW-fallbacked redirect to same-origin other-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope2.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-fallbacked redirect to other-origin out-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-fallbacked redirect to other-origin in-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-fallbacked redirect to other-origin and back to same-origin. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3Furl%3Dhttps%253A%252F%252Fweb-platform.test%253A8444%252Fservice-workers%252Fservice-worker%252Fresources%252Fnavigation-redirect-scope1.py%253F request to worker0 expected "string" but got "undefined"
FAIL SW-generated redirect to same-origin out-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-generated redirect to same-origin out-scope with a hash fragment. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F#ref request to worker0 expected "string" but got "undefined"
FAIL SW-generated redirect to same-origin out-scope with different hash fragments. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F%23ref2#ref request to worker0 expected "string" but got "undefined"
FAIL SW-generated redirect to same-origin same-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-generated redirect to same-origin other-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope2.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-generated redirect to other-origin out-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-generated redirect to other-origin in-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=gen&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-fetched redirect to same-origin out-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=fetch&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-fetched redirect to same-origin same-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=fetch&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-fetched redirect to same-origin other-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=fetch&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope2.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-fetched redirect to other-origin out-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=fetch&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined"
FAIL SW-fetched redirect to other-origin in-scope. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=fetch&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined"
FAIL Redirect to same-origin out-scope with opaque redirect response. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manual&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined"
FAIL Redirect to same-origin same-scope with opaque redirect response. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manual&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined"
FAIL Redirect to same-origin other-scope with opaque redirect response. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manual&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope2.py%3F request to worker0 expected "string" but got "undefined"
FAIL Redirect to other-origin out-scope with opaque redirect response. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manual&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined"
FAIL Redirect to other-origin in-scope with opaque redirect response. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manual&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined"
FAIL No location redirect response. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manual&noLocationRedirect request to worker0 expected "string" but got "undefined"
FAIL Redirect to same-origin out-scope with opaque redirect response which is passed through Cache. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manualThroughCache&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined"
FAIL Redirect to same-origin same-scope with opaque redirect response which is passed through Cache. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manualThroughCache&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined"
FAIL Redirect to same-origin other-scope with opaque redirect response which is passed through Cache. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manualThroughCache&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope2.py%3F request to worker0 expected "string" but got "undefined"
FAIL Redirect to other-origin out-scope with opaque redirect response which is passed through Cache. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manualThroughCache&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-out-scope.py%3F request to worker0 expected "string" but got "undefined"
FAIL Redirect to other-origin in-scope with opaque redirect response which is passed through Cache. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manualThroughCache&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Fnavigation-redirect-scope1.py%3F request to worker0 expected "string" but got "undefined"
FAIL No location redirect response via Cache. assert_equals: resultingClientId for https://web-platform.test:8444/service-workers/service-worker/resources/navigation-redirect-scope1.py?sw=manualThroughCache&noLocationRedirect request to worker0 expected "string" but got "undefined"
PASS clean up global state
Harness: the test ran to completion.
......@@ -44,6 +44,20 @@ function get_request_infos(worker) {
});
}
function get_clients(worker, actual_ids) {
return new Promise(function(resolve) {
var channel = new MessageChannel();
channel.port1.onmessage = (msg) => {
resolve(msg.data.clients);
};
worker.postMessage({
command: 'getClients',
actual_ids,
port: channel.port2
}, [channel.port2]);
});
}
window.addEventListener('message', on_message, false);
function on_message(e) {
......@@ -59,6 +73,11 @@ function on_message(e) {
.then(function(data) {
send_result(e.data.id, data);
});
} else if (command == 'get_clients') {
get_clients(worker, e.data.message.actual_ids)
.then(function(data) {
send_result(e.data.id, data);
});
} else if (command == 'unregister') {
registration.unregister()
.then(function() {
......
......@@ -5,6 +5,13 @@ var cacheName = 'urls-' + self.registration.scope;
var waitUntilPromiseList = [];
// Sends the requests seen by this worker. The output is:
// {
// requestInfos: [
// {url: url1, resultingClientId: id1},
// {url: url2, resultingClientId: id2},
// ]
// }
async function getRequestInfos(event) {
// Wait for fetch events to finish.
await Promise.all(waitUntilPromiseList);
......@@ -15,8 +22,11 @@ async function getRequestInfos(event) {
const requestList = await cache.keys();
const requestInfos = [];
for (let i = 0; i < requestList.length; i++) {
const response = await cache.match(requestList[i]);
const body = await response.json();
requestInfos[i] = {
url: requestList[i].url,
resultingClientId: body.resultingClientId
};
}
await caches.delete(cacheName);
......@@ -24,13 +34,50 @@ async function getRequestInfos(event) {
event.data.port.postMessage({requestInfos});
}
// Sends the results of clients.get(id) from this worker. The
// input is:
// {
// actual_ids: {a: id1, b: id2, x: id3}
// }
//
// The output is:
// {
// clients: {
// a: {found: false},
// b: {found: false},
// x: {
// id: id3,
// url: url1,
// found: true
// }
// }
// }
async function getClients(event) {
// |actual_ids| is like:
// {a: id1, b: id2, x: id3}
const actual_ids = event.data.actual_ids;
const result = {}
for (let key of Object.keys(actual_ids)) {
const id = actual_ids[key];
const client = await self.clients.get(id);
if (client === undefined)
result[key] = {found: false};
else
result[key] = {found: true, url: client.url, id: client.id};
}
event.data.port.postMessage({clients: result});
}
self.addEventListener('message', async function(event) {
if (event.data.command == 'getRequestInfos') {
event.waitUntil(getRequestInfos(event));
return;
}
// TODO(falken): Add a getClientInfos command to test Clients API.
if (event.data.command == 'getClients') {
event.waitUntil(getClients(event));
return;
}
});
function get_query_params(url) {
......@@ -49,7 +96,11 @@ function get_query_params(url) {
self.addEventListener('fetch', function(event) {
var waitUntilPromise = caches.open(cacheName).then(function(cache) {
return cache.put(event.request, new Response());
const responseBody = {};
responseBody['resultingClientId'] = event.resultingClientId;
const headers = new Headers({'Content-Type': 'application/json'});
const response = new Response(JSON.stringify(responseBody), {headers});
return cache.put(event.request, response);
});
event.waitUntil(waitUntilPromise);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment