Skip to content

Commit

Permalink
WPT: service worker: fix test for CSS base URL.
Browse files Browse the repository at this point in the history
The existing test was asserting the opposite of the standard,
which is to use the response URL. See
whatwg/fetch#146.

This CL does the following:
- Tests that a CSS stylesheet fetched via respondWith(fetch(responseUrl)
  uses responseUrl as its base URL.
- Tests that a CSS stylesheet fetched via respondWith(new Response())
  uses the response URL (which is the request URL) as its base URL.
- Changes the test to not test cross-origin stylesheets. That is more
  complex than needed for this test, and there is talk of making
  subresource requests from opaque stylesheets skip the service worker,
  which would render the test ineffective for testing base URL.
- Changes the test to use waitUntil() in the message event to try
  to ensure the service worker stays alive between the message and
  fetch events.

Bug: 911974
Change-Id: I167dfe86986ec718a50d512f862f1eb49889608b
Reviewed-on: https://chromium-review.googlesource.com/c/1362776
Commit-Queue: Matt Falkenhagen <falken@chromium.org>
Reviewed-by: Ben Kelly <wanderview@chromium.org>
Cr-Commit-Position: refs/heads/master@{#614277}
  • Loading branch information
mfalken authored and chromium-wpt-export-bot committed Dec 6, 2018
1 parent ee3ec2e commit dcb9168
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 76 deletions.
133 changes: 81 additions & 52 deletions service-workers/service-worker/fetch-request-css-base-url.https.html
Original file line number Diff line number Diff line change
@@ -1,58 +1,87 @@
<!DOCTYPE html>
<title>Service Worker: CSS's base URL must be the request URL even when fetched from other URL</title>
<title>Service Worker: CSS's base URL must be the response URL</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js?pipe=sub"></script>
<script>
promise_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) {
t.add_cleanup(function() {
return service_worker_unregister(t, SCOPE);
});

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();
});
});
}, 'CSS\'s base URL must be the request URL even when fetched from other URL.');
const SCOPE = 'resources/fetch-request-css-base-url-iframe.html';
const SCRIPT = 'resources/fetch-request-css-base-url-worker.js';
let worker;

var signalMessage;
function getNextMessage() {
return new Promise(resolve => { signalMessage = resolve; });
}

promise_test(async (t) => {
const registration = await service_worker_unregister_and_register(
t, SCRIPT, SCOPE);
worker = registration.installing;
await wait_for_state(t, worker, 'activated');
}, 'global setup');

// Creates a test concerning the base URL of a stylesheet. It loads a
// stylesheet from a controlled page. The stylesheet makes a subresource
// request for an image. The service worker messages back the details of the
// image request in order to test the base URL.
//
// The request URL for the stylesheet is under "resources/request-url-path/".
// The service worker may respond in a way such that the response URL is
// different to the request URL.
function base_url_test(params) {
promise_test(async (t) => {
let frame;
t.add_cleanup(() => {
if (frame)
frame.remove();
});

// Ask the service worker to message this page once it gets the request
// for the image.
let channel = new MessageChannel();
const sawPong = getNextMessage();
channel.port1.onmessage = (event) => {
signalMessage(event.data);
};
worker.postMessage({port:channel.port2},[channel.port2]);

// It sends a pong back immediately. This ping/pong protocol helps deflake
// the test for browsers where message/fetch ordering isn't guaranteed.
assert_equals('pong', await sawPong);

// Load the frame which will load the stylesheet that makes the image
// request.
const sawResult = getNextMessage();
frame = await with_iframe(params.framePath);
const result = await sawResult;

// Test the image request.
const base = new URL('.', document.location).href;
assert_equals(result.url,
base + params.expectImageRequestPath,
'request');
assert_equals(result.referrer,
base + params.expectImageRequestReferrer,
'referrer');
}, params.description);
}

const cssFile = 'fetch-request-css-base-url-style.css';

base_url_test({
framePath: SCOPE + '?fetch',
expectImageRequestPath: 'resources/dummy.png',
expectImageRequestReferrer: `resources/${cssFile}?fetch`,
description: 'base URL when service worker does respondWith(fetch(responseUrl)).'});

base_url_test({
framePath: SCOPE + '?newResponse',
expectImageRequestPath: 'resources/request-url-path/dummy.png',
expectImageRequestReferrer: `resources/request-url-path/${cssFile}?newResponse`,
description: 'base URL when service worker does respondWith(new Response()).'});

// Cleanup step: this must be the last promise_test.
promise_test(async (t) => {
return service_worker_unregister(t, SCOPE);
}, 'cleanup global state');
</script>
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
<link href="./fetch-request-css-base-url-style.css" rel="stylesheet" type="text/css">
<html>
<head>
<title>iframe for css base url test</title>
</head>
<body>
<script>
// Load a stylesheet. Create it dynamically so we can construct the href URL
// dynamically.
const link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
// Add "request-url-path" to the path to help distinguish the request URL from
// the response URL. Add |document.location.search| (chosen by the test main
// page) to tell the service worker how to respond to the request.
link.href = 'request-url-path/fetch-request-css-base-url-style.css' +
document.location.search;
document.head.appendChild(link);
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -1,27 +1,45 @@
importScripts('/common/get-host-info.sub.js');
importScripts('test-helpers.sub.js');
let source;
let resolveDone;
let done = new Promise(resolve => resolveDone = resolve);

var port = undefined;
// The page messages this worker to ask for the result. Keep the worker alive
// via waitUntil() until the result is sent.
self.addEventListener('message', event => {
source = event.data.port;
source.postMessage('pong');
event.waitUntil(done);
});

self.onmessage = function(e) {
var message = e.data;
if ('port' in message) {
port = message.port;
port.postMessage({ready: true});
}
};
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);

self.addEventListener('fetch', function(event) {
var url = event.request.url;
if (url.indexOf('fetch-request-css-base-url-style.css') != -1) {
event.respondWith(fetch(
get_host_info()['HTTPS_REMOTE_ORIGIN'] + base_path() +
'fetch-request-css-base-url-style.css',
{mode: 'no-cors'}));
} else if (url.indexOf('dummy.png') != -1) {
port.postMessage({
url: event.request.url,
referrer: event.request.referrer
});
// For the CSS file, respond in a way that may change the response URL,
// depending on |url.search|.
const cssPath = 'request-url-path/fetch-request-css-base-url-style.css';
if (url.pathname.indexOf(cssPath) != -1) {
// Respond with a different URL, deleting "request-url-path/".
if (url.search == '?fetch') {
event.respondWith(fetch('fetch-request-css-base-url-style.css'));
}
// Respond with new Response().
else if (url.search == '?newResponse') {
const styleString = 'body { background-image: url("./dummy.png");}';
const headers = {'content-type': 'text/css'};
event.respondWith(new Response(styleString, headers));
}
});
}

// The image request indicates what the base URL of the CSS was. Message the
// result back to the test page.
else if (url.pathname.indexOf('dummy.png') != -1) {
// For some reason |source| is undefined here when running the test manually
// in Firefox. The test author experimented with both using Client
// (event.source) and MessagePort to try to get the test to pass, but
// failed.
source.postMessage({
url: event.request.url,
referrer: event.request.referrer
});
resolveDone();
}
});

0 comments on commit dcb9168

Please sign in to comment.