Update web-platform-tests to revision b'ee6da9d71d0268d7fdb04e8e5b26858f46ee0cc4'

This commit is contained in:
WPT Sync Bot 2022-01-20 04:38:55 +00:00 committed by cybai
parent 4401622eb1
commit b77ad115f6
16832 changed files with 270819 additions and 87621 deletions

View file

@ -1,137 +0,0 @@
<!DOCTYPE html>
<title>CSP for subresource WebBundle (blocked cases)</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<meta
http-equiv="Content-Security-Policy"
content="
script-src
urn:
https://web-platform.test:8444/resources/testharness.js
https://web-platform.test:8444/resources/testharnessreport.js
'unsafe-inline';
img-src
https://web-platform.test:8444/web-bundle/resources/wbn/subresource.wbn;
frame-src
urn:;
report-to
csp-group"
>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<link rel="webbundle" href="../resources/wbn/subresource.wbn"
resources="https://web-platform.test:8444/web-bundle/resources/wbn/fail.png" />
<link rel="webbundle" href="../resources/wbn/urn-uuid.wbn"
resources="urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720
urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae" />
<script>
const bundle_url = 'https://web-platform.test:8444/web-bundle/resources/wbn/urn-uuid.wbn';
function expect_violation() {
return new Promise(resolve => {
document.addEventListener('securitypolicyviolation', (e) => {
e.stopPropagation();
resolve(e);
}, {once: true});
});
}
function getReportID() {
const cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
const name_value = cookies[i].split('=');
const cookieName = name_value[0].trim();
if (cookieName === 'csp-blocked-report-id') {
return name_value[1].trim();
}
}
}
function sortReportsByEffectiveDirective(reports) {
reports.sort(function(report1, report2) {
return report1.body.effectiveDirective.localeCompare(
report2.body.effectiveDirective);
});
}
promise_test(async () => {
const p = expect_violation();
const img = document.createElement('img');
const error_promise = new Promise(resolve => {
img.onerror = resolve;
});
img.src = 'https://web-platform.test:8444/web-bundle/resources/wbn/fail.png';
document.body.appendChild(img);
const e = await p;
assert_equals(e.blockedURI, img.src);
await error_promise;
}, 'URL matching of CSP should be done based on the subresource URL, ' +
'not on the bundle URL, when the subresource URL is HTTPS URL.');
promise_test(async () => {
const urn_uuid = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const p = expect_violation();
const script = document.createElement('script');
script.src = urn_uuid;
document.body.appendChild(script);
const e = await p;
// Currently Chromium is reporting the bundle URL.
// TODO(crbug.com/1208659): Consider deeper integration with CSP for
// providing the both URLs.
assert_equals(e.blockedURI, bundle_url);
assert_equals(e.violatedDirective, 'script-src-elem');
}, 'URL matching of script-src CSP should be done based on the bundle URL ' +
'when the subresource URL is urn:uuid URL.');
promise_test(async () => {
const urn_uuid = 'urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae';
const p = expect_violation();
const iframe = document.createElement('iframe');
iframe.src = urn_uuid;
const load_promise = new Promise(resolve => {
iframe.addEventListener('load', resolve);
});
document.body.appendChild(iframe);
const e = await p;
// Currently Chromium is reporting the bundle URL.
// TODO(crbug.com/1208659): Consider deeper integration with CSP for
// providing the both URLs.
assert_equals(e.blockedURI, bundle_url);
assert_equals(e.violatedDirective, 'frame-src');
// Make sure that the blocked iframe load is finished.
await load_promise;
// The blocked iframe is cross-origin. So accessing
// iframe.contentWindow.location should throw a SecurityError.
assert_throws_dom(
"SecurityError",
() => { iframe.contentWindow.location.href; });
}, 'URL matching of frame-src CSP should be done based on the bundle URL ' +
'when the frame URL is urn:uuid URL.');
promise_test(async () => {
const retrieve_report_url =
"/reporting/resources/report.py?op=retrieve_report&timeout=3&reportID=" +
getReportID();
const reports = await (await fetch(retrieve_report_url)).json();
sortReportsByEffectiveDirective(reports);
assert_equals(reports.length, 3, "Report count.");
assert_equals(reports[0].body.blockedURL, bundle_url);
assert_equals(reports[0].body.effectiveDirective, 'frame-src');
assert_equals(
reports[1].body.blockedURL,
'https://web-platform.test:8444/web-bundle/resources/wbn/fail.png');
assert_equals(reports[1].body.effectiveDirective, 'img-src',);
assert_equals(reports[2].body.blockedURL, bundle_url);
assert_equals(reports[2].body.effectiveDirective, 'script-src-elem');
}, 'Check the CSP violation reports.');
</script>
</body>

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<title>Accept: request header in webbundle requests</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'link';
</script>
<body>
<script src="resources/accept-header-test.js"></script>
</body>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<title>COEP for WebBundle subresource loading</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<link rel="help" href="https://html.spec.whatwg.org/multipage/origin.html#coep" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<!--
This wpt should run on an origin different from https://www1.web-platform.test:8444/,
from where cross-orign WebBundles are served.
This test uses a cross-origin WebBundle,
https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp.wbn,
which is served with an Access-Control-Allow-Origin response header.
`corp.wbn` includes three subresources:
a. `no-corp.js`, which doesn't include a Cross-Origin-Resource-Policy response header.
b. `corp-same-origin.js`, which includes a Cross-Origin-Resource-Policy: same-origin response header.
c. `corp-cross-origin.js`, which includes a Cross-Origin-Resource-Policy: cross-origin response header.
-->
<link
rel="webbundle"
href="https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp.wbn"
resources="https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/no-corp.js
https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp-same-origin.js
https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp-cross-origin.js
urn:uuid:5eafff38-e0a0-4661-bde0-434255aa9d93
urn:uuid:7e13b47a-8b91-4a0e-997c-993a5e2f3a34
urn:uuid:86d5b696-8867-4454-8b07-51239a0817f7"
/>
<script src="resources/coep-test.js"></script>
</body>

View file

@ -0,0 +1 @@
Cross-Origin-Embedder-Policy: require-corp

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<title>CORP for WebBundle subresource loading</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md#cors-and-corp-for-subresource-requests" />
<link rel="help" href="https://fetch.spec.whatwg.org/#cross-origin-resource-policy-header" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<!--
This wpt should run on an origin different from https://www1.web-platform.test:8444/,
from where cross-orign WebBundles are served.
This test uses a cross-origin WebBundle,
https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp.wbn,
which is served with an Access-Control-Allow-Origin response header.
`corp.wbn` includes three subresources:
a. `no-corp.js`, which doesn't include a Cross-Origin-Resource-Policy response header.
b. `corp-same-origin.js`, which includes a Cross-Origin-Resource-Policy: same-origin response header.
c. `corp-cross-origin.js`, which includes a Cross-Origin-Resource-Policy: cross-origin response header.
-->
<link
rel="webbundle"
href="https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp.wbn"
resources="https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/no-corp.js
https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp-same-origin.js
https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp-cross-origin.js
urn:uuid:5eafff38-e0a0-4661-bde0-434255aa9d93
urn:uuid:7e13b47a-8b91-4a0e-997c-993a5e2f3a34
urn:uuid:86d5b696-8867-4454-8b07-51239a0817f7"
/>
<script src="resources/corp-test.js"></script>
</body>

View file

@ -2,7 +2,7 @@
<title>Cross origin WebBundle subresource loading (error case)</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<link
rel="help"
@ -37,18 +37,23 @@
"anonymous",
"use-credentials",
]) {
const link = await addLinkAndWaitForError(
prefix + "cross-origin.wbn",
resources,
crossorigin_attribute_value
);
for (const version_suffix of [
"-b1", // b1
"", // for b2
]) {
const link = await addLinkAndWaitForError(
prefix + "cross-origin" + version_suffix + ".wbn",
resources,
crossorigin_attribute_value
);
// A subresource in the bundle can not be used in any case.
for (const resource of resources) {
await fetchAndWaitForReject(resource);
await addScriptAndWaitForError(resource);
// A subresource in the bundle can not be used in any case.
for (const resource of resources) {
await fetchAndWaitForReject(resource);
await addScriptAndWaitForError(resource);
}
link.remove();
}
link.remove();
}
}, "Use CORS if crossorigin=anonymous or crossorigin=use-credential is specified. A cross origin bundle must not be loaded unless a server returns a valid Access-Control-Allow-Origin header.");
</script>

View file

@ -1,6 +1,6 @@
<!DOCTYPE html>
<title>Cross origin WebBundle subresource loading</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md" />
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<link rel="help" href="https://html.spec.whatwg.org/multipage/#cors-settings-attribute" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
@ -32,33 +32,38 @@
"anonymous",
"use-credentials",
]) {
const link = await addLinkAndWaitForLoad(
prefix + "cross-origin.wbn",
resources,
crossorigin_attribute_value
);
for (const version_suffix of [
"-b1", // b1
"", // for b2
]) {
const link = await addLinkAndWaitForLoad(
prefix + "cross-origin" + version_suffix + ".wbn",
resources,
crossorigin_attribute_value
);
// Can fetch a subresource which has a valid Access-Control-Allow-Origin response header.
const response = await fetch(prefix + "resource.cors.js");
assert_true(response.ok);
const text = await response.text();
assert_equals(text, "scriptLoaded('resource.cors.js');");
// Can fetch a subresource which has a valid Access-Control-Allow-Origin response header.
const response = await fetch(prefix + "resource.cors.js");
assert_true(response.ok);
const text = await response.text();
assert_equals(text, "scriptLoaded('resource.cors.js');");
// Can not fetch a subresource which does NOT have a valid
// Access-Control-Allow-Origin response header.
await fetchAndWaitForReject(prefix + "resource.no-cors.js");
// Can not fetch a subresource which does NOT have a valid
// Access-Control-Allow-Origin response header.
await fetchAndWaitForReject(prefix + "resource.no-cors.js");
// Both subresource js can be loaded via a <script> element, which doesn't use cors.
for (const resource of resources) {
const scriptEvaluted = new Promise((resolve, reject) => {
window.scriptLoaded = resolve;
});
const script = document.createElement("script");
script.src = resource;
document.body.appendChild(script);
await scriptEvaluted;
// Both subresource js can be loaded via a <script> element, which doesn't use cors.
for (const resource of resources) {
const scriptEvaluted = new Promise((resolve, reject) => {
window.scriptLoaded = resolve;
});
const script = document.createElement("script");
script.src = resource;
document.body.appendChild(script);
await scriptEvaluted;
}
link.remove();
}
link.remove();
}
}, "request's mode must be cors. A server should return a valid Access-Control-Allow-Origin header if a bundle is a cross origin bundle.");
</script>

View file

@ -4,7 +4,7 @@
</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<link
rel="help"
@ -30,15 +30,15 @@
// Make sure to set a cookie for a cross-origin domain from where a cross
// origin bundle is served.
const setCookiePromise = fetch(
"https://{{domains[www1]}}:{{ports[https][0]}}/cookies/resources/set-cookie.py?name=milk&path=/web-bundle/subresource-loading/",
"https://{{domains[www1]}}:{{ports[https][0]}}/cookies/resources/set-cookie.py?name=milk&path=/web-bundle/subresource-loading/resources/",
{
mode: "no-cors",
credentials: "include",
}
);
const same_origin_bundle = "./check-cookie-and-return-bundle.py";
const cross_origin_bundle = "https://{{domains[www1]}}:{{ports[https][0]}}/web-bundle/subresource-loading/check-cookie-and-return-bundle.py";
const same_origin_bundle = "./resources/check-cookie-and-return-bundle.py";
const cross_origin_bundle = "https://{{domains[www1]}}:{{ports[https][0]}}/web-bundle/subresource-loading/resources/check-cookie-and-return-bundle.py";
promise_test(async () => {
const link = document.createElement("link");

View file

@ -2,20 +2,22 @@
<title>CSP for subresource WebBundle (allowed cases)</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<meta
http-equiv="Content-Security-Policy"
content="
script-src
https://web-platform.test:8444/web-bundle/resources/wbn/urn-uuid.wbn
https://web-platform.test:8444/web-bundle/resources/wbn/uuid-in-package.wbn
https://web-platform.test:8444/resources/testharness.js
https://web-platform.test:8444/resources/testharnessreport.js
'unsafe-inline';
img-src
https://web-platform.test:8444/web-bundle/resources/wbn/pass.png;
frame-src
https://web-platform.test:8444/web-bundle/resources/wbn/urn-uuid.wbn"
https://web-platform.test:8444/web-bundle/resources/wbn/urn-uuid.wbn
https://web-platform.test:8444/web-bundle/resources/wbn/uuid-in-package.wbn"
>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
@ -25,6 +27,9 @@
<link rel="webbundle" href="../resources/wbn/urn-uuid.wbn"
resources="urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720
urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae" />
<link rel="webbundle" href="../resources/wbn/uuid-in-package.wbn"
resources="uuid-in-package:020111b3-437a-4c5c-ae07-adb6bbffb720
uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ae" />
<script>
promise_test(() => {
return new Promise((resolve, reject) => {
@ -49,6 +54,18 @@
}, 'URL matching of script-src CSP should be done based on the bundle URL ' +
'when the subresource URL is urn:uuid URL.');
promise_test(async () => {
const result = await new Promise((resolve) => {
// This function will be called from the script.
window.report_result = resolve;
const script = document.createElement('script');
script.src = 'uuid-in-package:020111b3-437a-4c5c-ae07-adb6bbffb720';
document.body.appendChild(script);
});
assert_equals(result, 'OK');
}, 'URL matching of script-src CSP should be done based on the bundle URL ' +
'when the subresource URL is uuid-in-package: URL.');
promise_test(async () => {
const frame_url = 'urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae';
const iframe = document.createElement('iframe');
@ -64,6 +81,21 @@
}, 'URL matching of frame-src CSP should be done based on the bundle URL ' +
'when the frame URL is urn:uuid URL.');
promise_test(async () => {
const frame_url = 'uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ae';
const iframe = document.createElement('iframe');
iframe.src = frame_url;
const load_promise = new Promise((resolve) => {
iframe.addEventListener('load', resolve);
});
document.body.appendChild(iframe);
await load_promise;
assert_equals(
await evalInIframe(iframe, 'location.href'),
frame_url);
}, 'URL matching of frame-src CSP should be done based on the bundle URL ' +
'when the frame URL is uuid-in-package: URL.');
async function evalInIframe(iframe, code) {
const message_promise = new Promise((resolve) => {
window.addEventListener(

View file

@ -0,0 +1,158 @@
<!DOCTYPE html>
<title>CSP for subresource WebBundle (blocked cases)</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<meta
http-equiv="Content-Security-Policy"
content="
script-src
urn:
https://web-platform.test:8444/resources/testharness.js
https://web-platform.test:8444/resources/testharnessreport.js
'unsafe-inline';
img-src
https://web-platform.test:8444/web-bundle/resources/wbn/subresource.wbn;
frame-src
urn:;
report-to
csp-group"
>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<link rel="webbundle" href="../resources/wbn/subresource.wbn"
resources="https://web-platform.test:8444/web-bundle/resources/wbn/fail.png" />
<link rel="webbundle" href="../resources/wbn/urn-uuid.wbn"
resources="urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720
urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae" />
<link rel="webbundle" href="../resources/wbn/uuid-in-package.wbn"
resources="uuid-in-package:020111b3-437a-4c5c-ae07-adb6bbffb720
uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ae" />
<script>
const urn_bundle_url = 'https://web-platform.test:8444/web-bundle/resources/wbn/urn-uuid.wbn';
const uuid_bundle_url = 'https://web-platform.test:8444/web-bundle/resources/wbn/uuid-in-package.wbn';
function expect_violation() {
return new Promise(resolve => {
document.addEventListener('securitypolicyviolation', (e) => {
e.stopPropagation();
resolve(e);
}, {once: true});
});
}
function getReportID() {
const cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
const name_value = cookies[i].split('=');
const cookieName = name_value[0].trim();
if (cookieName === 'csp-blocked-report-id') {
return name_value[1].trim();
}
}
}
function sortReportsByEffectiveDirective(reports) {
reports.sort((report1, report2) =>
report1.body.effectiveDirective.localeCompare(report2.body.effectiveDirective)
|| report1.body.blockedURL.localeCompare(report2.body.blockedURL)
);
}
promise_test(async () => {
const p = expect_violation();
const img = document.createElement('img');
const error_promise = new Promise(resolve => {
img.onerror = resolve;
});
img.src = 'https://web-platform.test:8444/web-bundle/resources/wbn/fail.png';
document.body.appendChild(img);
const e = await p;
assert_equals(e.blockedURI, img.src);
await error_promise;
}, 'URL matching of CSP should be done based on the subresource URL, ' +
'not on the bundle URL, when the subresource URL is HTTPS URL.');
const testCases = [
{
prefix: 'urn:uuid:',
bundle_url: urn_bundle_url
},
{
prefix: 'uuid-in-package:',
bundle_url: uuid_bundle_url
}
];
for (const params of testCases) {
promise_test(async () => {
const urn_uuid = params.prefix + '020111b3-437a-4c5c-ae07-adb6bbffb720';
const p = expect_violation();
const script = document.createElement('script');
script.src = urn_uuid;
document.body.appendChild(script);
const e = await p;
// Currently Chromium is reporting the bundle URL.
// TODO(crbug.com/1208659): Consider deeper integration with CSP for
// providing the both URLs.
assert_equals(e.blockedURI, params.bundle_url);
assert_equals(e.violatedDirective, 'script-src-elem');
}, 'URL matching of script-src CSP should be done based on the bundle URL ' +
`when the subresource URL is ${params.prefix} URL.`);
promise_test(async () => {
const urn_uuid = params.prefix + '429fcc4e-0696-4bad-b099-ee9175f023ae';
const p = expect_violation();
const iframe = document.createElement('iframe');
iframe.src = urn_uuid;
const load_promise = new Promise(resolve => {
iframe.addEventListener('load', resolve);
});
document.body.appendChild(iframe);
const e = await p;
// Currently Chromium is reporting the bundle URL.
// TODO(crbug.com/1208659): Consider deeper integration with CSP for
// providing the both URLs.
assert_equals(e.blockedURI, params.bundle_url);
assert_equals(e.violatedDirective, 'frame-src');
// Make sure that the blocked iframe load is finished.
await load_promise;
// The blocked iframe is cross-origin. So accessing
// iframe.contentWindow.location should throw a SecurityError.
assert_throws_dom(
"SecurityError",
() => { iframe.contentWindow.location.href; });
}, 'URL matching of frame-src CSP should be done based on the bundle URL ' +
`when the frame URL is ${params.prefix} URL.`);
}
promise_test(async () => {
const retrieve_report_url =
"/reporting/resources/report.py?op=retrieve_report&timeout=3&reportID=" +
getReportID();
const reports = await (await fetch(retrieve_report_url)).json();
sortReportsByEffectiveDirective(reports);
assert_equals(reports.length, 5, "Report count.");
assert_equals(reports[0].body.blockedURL, urn_bundle_url);
assert_equals(reports[0].body.effectiveDirective, 'frame-src');
assert_equals(reports[1].body.blockedURL, uuid_bundle_url);
assert_equals(reports[1].body.effectiveDirective, 'frame-src');
assert_equals(
reports[2].body.blockedURL,
'https://web-platform.test:8444/web-bundle/resources/wbn/fail.png');
assert_equals(reports[2].body.effectiveDirective, 'img-src',);
assert_equals(reports[3].body.blockedURL, urn_bundle_url);
assert_equals(reports[3].body.effectiveDirective, 'script-src-elem');
assert_equals(reports[4].body.blockedURL, uuid_bundle_url);
assert_equals(reports[4].body.effectiveDirective, 'script-src-elem');
}, 'Check the CSP violation reports.');
</script>
</body>

View file

@ -2,7 +2,7 @@
<title>A link element with rel="webbundle"</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<title>On-going subresource loading should fail immediately when the web bundle element is removed</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'link';
</script>
<body>
<script src="resources/element-removal-test.js"></script>
</body>

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<title>A nested bundle is not supported</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'link';
</script>
<body>
<link rel="webbundle" href="https://web-platform.test:8444/web-bundle/resources/wbn/nested-main.wbn"
resources="https://web-platform.test:8444/web-bundle/resources/wbn/nested-sub.wbn" />
<script src="resources/nested-bundle-test.js"></script>
</body>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<title>Web Bundle fetching failed due to a network error</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'link';
</script>
<body>
<script src="resources/network-error-test.sub.js"></script>
</body>

View file

@ -2,7 +2,7 @@
<title>A link element with rel="webbundle" in no secure context</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<title>Web Bundle fetching failed due to not found error</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'link';
</script>
<body>
<script src="resources/not-found-test.js"></script>
</body>

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<title>Path restriction on subresource loading with WebBundles (b1 version)</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<link
rel="webbundle"
href="../resources/wbn/path-restriction-b1.wbn"
resources="/web-bundle/resources/wbn/resource.js
/web-bundle/resources/wbn/sub/resource.js
/web-bundle/resources/wbn-resource.js
/web-bundle/resources/wbn1/resource.js
/web-bundle/resources/other/resource.js
/web-bundle/resources/resource.js"
/>
<script src="resources/path-restriction-test.js"></script>
</body>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<title>Path restriction on subresource loading with WebBundles</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<link
rel="webbundle"
href="../resources/wbn/path-restriction.wbn"
resources="/web-bundle/resources/wbn/resource.js
/web-bundle/resources/wbn/sub/resource.js
/web-bundle/resources/wbn-resource.js
/web-bundle/resources/wbn1/resource.js
/web-bundle/resources/other/resource.js
/web-bundle/resources/resource.js"
/>
/>
<script src="resources/path-restriction-test.js"></script>
</body>

View file

@ -0,0 +1,39 @@
<!DOCTYPE html>
<title>Relative Url in cross origin web bundle</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<link
rel="webbundle"
href="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url.wbn"
resources="
//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url-file.js
//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url/start-with-double-slash-cors.js
//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url/start-with-slash.js
//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url/subdirectory-path.js
//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/starts-with-two-dots.js
//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/starts-with-two-dots-out-of-scope.js
" />
<script>
const loaded_scripts = [];
function scriptLoaded(file) {
loaded_scripts.push(file);
}
const failed_scripts = [];
function scriptFailed(file) {
failed_scripts.push(file);
}
</script>
<script src="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url-file.js"></script>
<script src="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url/start-with-double-slash-cors.js"></script>
<script src="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url/start-with-slash.js"></script>
<script src="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url/subdirectory-path.js"></script>
<script src="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/starts-with-two-dots.js"></script>
<script src="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/starts-with-two-dots-out-of-scope.js"
onerror="scriptFailed('starts-with-two-dots-out-of-scope.js')"></script>
<script src="resources/relative-url-in-web-bundle-cors-test.js"></script>
</body>

View file

@ -0,0 +1,39 @@
<!DOCTYPE html>
<title>Relative Url in web bundle</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<link
rel="webbundle"
href="../resources/wbn/relative-url.wbn"
resources="
../resources/wbn/relative-url-file.js
../resources/wbn/relative-url/start-with-double-slash.js
../resources/wbn/relative-url/start-with-slash.js
../resources/wbn/relative-url/subdirectory-path.js
../resources/wbn/starts-with-two-dots.js
../resources/starts-with-two-dots-out-of-scope.js
" />
<script>
const loaded_scripts = [];
function scriptLoaded(file) {
loaded_scripts.push(file);
}
const failed_scripts = [];
function scriptFailed(file) {
failed_scripts.push(file);
}
</script>
<script src="../resources/wbn/relative-url-file.js"></script>
<script src="../resources/wbn/relative-url/start-with-double-slash.js"></script>
<script src="../resources/wbn/relative-url/start-with-slash.js"></script>
<script src="../resources/wbn/relative-url/subdirectory-path.js"></script>
<script src="../resources/wbn/starts-with-two-dots.js"></script>
<script src="../resources/starts-with-two-dots-out-of-scope.js"
onerror="scriptFailed('starts-with-two-dots-out-of-scope.js')"></script>
<script src="resources/relative-url-in-web-bundle-test.js"></script>
</body>

View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<title>Subresource loading using relative URLs in the 'resources' and 'scopes' attributes with a base element</title>
<base href="../resources/wbn/">
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<link
rel="webbundle"
href="static-element.wbn"
resources="static-element/resources/script.js"/>
<script id="script" src="static-element/resources/script.js"></script>
<link
rel="webbundle"
href="dynamic1.wbn"
scopes="dynamic/resource"/>
<script src="/web-bundle/subresource-loading/resources/relative-url-with-base-test.js"></script>
</body>

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<title>Subresource loading using relative URLs in the 'resources' attribute</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'link';
</script>
<body>
<link
rel="webbundle"
href="../resources/wbn/static-element.wbn"
resources="/web-bundle/resources/wbn/static-element/resources/script.js"/>
<script id="script" src="/web-bundle/resources/wbn/static-element/resources/script.js"></script>
<script src="resources/relative-url-test.js"></script>
</body>

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<title>Request's destination must be "webbundle" with the link-based API</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'link';
</script>
<body>
<script src="resources/request-destination-test.sub.js"></script>
</body>

View file

@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Resource timing attributes are consistent for the same-origin subresources.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'link';
</script>
<body>
<script src="resources/resource-timing-attributes-consistent-test.sub.js"></script>
</body>

View file

@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Resource timing entries present for urn:uuid resources</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'link';
</script>
<body>
<script src="resources/resource-timing-test.js"></script>
</body>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<title>Web Bundle fetching and the inner resouirce fetching should skip service worker</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'link';
</script>
<body>
<script src="resources/service-worker-controlled-test.js"></script>
</body>

View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<title>WebBundle subresource loading for static elements with a base element</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<base href="../resources/wbn/static-element/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<link
rel="webbundle"
href="../static-element.wbn"
resources="
https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/script.js
https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/style.css
https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/style-imported-from-file.css
https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/style-imported-from-tag.css"
scopes="https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/scopes/"
/>
<style type="text/css">
@import 'resources/style-imported-from-tag.css';
@import 'scopes/style-imported-from-tag.css';
</style>
<link href="resources/style.css" rel=stylesheet>
<link href="scopes/style.css" rel=stylesheet>
<script src="resources/script.js"></script>
<script src="scopes/script.js"></script>
<script src="out-of-scope/script.js"></script>
<script src="/web-bundle/subresource-loading/resources/static-element-with-test.js"></script>
</body>

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<title>WebBundle subresource loading for static elements</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<link
rel="webbundle"
href="../resources/wbn/static-element.wbn"
resources="
https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/script.js
https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/style.css
https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/style-imported-from-file.css
https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/style-imported-from-tag.css"
scopes="https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/scopes/"
/>
<style type="text/css">
@import '../resources/wbn/static-element/resources/style-imported-from-tag.css';
@import '../resources/wbn/static-element/scopes/style-imported-from-tag.css';
</style>
<link href="../resources/wbn/static-element/resources/style.css" rel=stylesheet>
<link href="../resources/wbn/static-element/scopes/style.css" rel=stylesheet>
<script src="../resources/wbn/static-element/resources/script.js"></script>
<script src="../resources/wbn/static-element/scopes/script.js"></script>
<script src="../resources/wbn/static-element/out-of-scope/script.js"></script>
<script src="resources/static-element-with-test.js"></script>
</body>

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<title>Subframe loading from Web Bundles</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'link';
</script>
<body>
<script src="resources/subframe-from-web-bundle-test.js"></script>
</body>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<title>Subresource loading with link rel="webbundle"</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'link';
</script>
<body>
<link id="link-web-bundle" rel="webbundle" href="../resources/wbn/subresource.wbn" resources="https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/root.js
https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/submodule.js" />
<script src="resources/subresource-load-test.sub.js"></script>
<script>
promise_test(async () => {
const wbn_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/subresource.wbn?test-resources-update';
const resource_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/submodule.js';
const element = await addWebBundleElementAndWaitForLoad(wbn_url, /*resources=*/[]);
changeWebBundleResourcesInPlace(element, [resource_url]);
const resp = await fetch(resource_url, { cache: 'no-store' });
assert_true(resp.ok);
assert_equals(performance.getEntriesByName(wbn_url).length, 1);
document.body.removeChild(element);
}, 'Updating resource attribute should not reload the bundle');
</script>
</body>

View file

@ -0,0 +1,7 @@
promise_test(async () => {
await addWebBundleElementAndWaitForLoad(
'../resources/check-accept-header-and-return-bundle.py',
/*resources=*/[]);
},
'"Accept:" header in a request for a bundle should contain ' +
'application/webbundle MIME type.');

View file

@ -17,7 +17,7 @@ def main(request, response):
cookie = request.cookies.first(b"milk", None)
if (cookie is not None) and cookie.value == b"1":
with open(
os.path.join(os.path.dirname(__file__), "../resources/wbn/subresource.wbn"),
os.path.join(os.path.dirname(__file__), "../../resources/wbn/subresource.wbn"),
"rb",
) as f:
return (200, headers, f.read())

View file

@ -0,0 +1,75 @@
async function expectCOEPReport(func) {
const reportsPromise = new Promise((resolve) => {
const observer = new ReportingObserver((reports) => {
observer.disconnect();
resolve(reports.map(r => r.toJSON()));
});
observer.observe();
});
await func();
const reports = await reportsPromise;
assert_equals(reports.length, 1);
assert_equals(reports[0].type, "coep");
assert_equals(reports[0].url, location.href);
return reports[0];
}
const prefix = 'https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/';
const no_corp_url = 'urn:uuid:5eafff38-e0a0-4661-bde0-434255aa9d93';
const corp_same_origin_url = 'urn:uuid:7e13b47a-8b91-4a0e-997c-993a5e2f3a34';
const corp_cross_origin_url = 'urn:uuid:86d5b696-8867-4454-8b07-51239a0817f7';
promise_test(async () => {
const report = await expectCOEPReport(async () => {
await addScriptAndWaitForError(prefix + 'no-corp.js');
});
assert_equals(report.body.blockedURL, prefix + 'no-corp.js');
assert_equals(report.body.type, "corp");
assert_equals(report.body.disposition, "enforce");
assert_equals(report.body.destination, "script");
}, "Cross-origin subresource without Cross-Origin-Resource-Policy: header should be blocked and generate a report.");
promise_test(async () => {
await addScriptAndWaitForError(prefix + 'corp-same-origin.js');
}, "Cross-origin subresource with Cross-Origin-Resource-Policy: same-origin should be blocked.");
promise_test(async () => {
await addScriptAndWaitForExecution(prefix + 'corp-cross-origin.js');
}, "Cross-origin subresource with Cross-Origin-Resource-Policy: cross-origin should be loaded.");
promise_test(async () => {
const report = await expectCOEPReport(async () => {
const iframe = document.createElement('iframe');
iframe.src = no_corp_url;
document.body.appendChild(iframe);
});
assert_equals(report.body.blockedURL, no_corp_url);
assert_equals(report.body.type, "corp");
assert_equals(report.body.disposition, "enforce");
assert_equals(report.body.destination, "iframe");
}, "Urn:uuid iframe without Cross-Origin-Resource-Policy: header should be blocked and generate a report.");
promise_test(async () => {
const report = await expectCOEPReport(async () => {
const iframe = document.createElement('iframe');
iframe.src = corp_same_origin_url;
document.body.appendChild(iframe);
});
assert_equals(report.body.blockedURL, corp_same_origin_url);
assert_equals(report.body.type, "corp");
assert_equals(report.body.disposition, "enforce");
assert_equals(report.body.destination, "iframe");
}, "Urn:uuid iframe with Cross-Origin-Resource-Policy: same-origin should be blocked and generate a report.");
promise_test(async () => {
const iframe = document.createElement('iframe');
iframe.src = corp_cross_origin_url;
await addElementAndWaitForLoad(iframe);
assert_equals(
await evalInIframe(iframe, 'location.href'),
corp_cross_origin_url);
}, "Urn:uuid iframe with Cross-Origin-Resource-Policy: cross-origin should not be blocked.");

View file

@ -0,0 +1,23 @@
promise_test(async () => {
const prefix = 'https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/';
await addScriptAndWaitForExecution(prefix + 'no-corp.js');
await addScriptAndWaitForError(prefix + 'corp-same-origin.js');
await addScriptAndWaitForExecution(prefix + 'corp-cross-origin.js');
}, "Subresource loading from WebBundles should respect Cross-Origin-Resource-Policy header.");
promise_test(async () => {
const no_corp_url = 'urn:uuid:5eafff38-e0a0-4661-bde0-434255aa9d93';
const corp_same_origin_url = 'urn:uuid:7e13b47a-8b91-4a0e-997c-993a5e2f3a34';
const corp_cross_origin_url = 'urn:uuid:86d5b696-8867-4454-8b07-51239a0817f7';
await iframeLocationTest(no_corp_url);
await iframeLocationTest(corp_same_origin_url);
await iframeLocationTest(corp_cross_origin_url);
}, "Urn:uuid iframes should not be blocked regardless of the Cross-Origin-Resource-Policy header, if Cross-Origin-Embedder-Policy is not set.");
async function iframeLocationTest(url) {
const iframe = document.createElement('iframe');
iframe.src = url;
await addElementAndWaitForLoad(iframe);
assert_equals(await evalInIframe(iframe, 'location.href'), url);
}

View file

@ -0,0 +1,13 @@
promise_test(async () => {
const element = createWebBundleElement(
'/xhr/resources/delay.py?ms=100000',
['/xhr/resources/dummy']);
document.body.appendChild(element);
const waitUntilFail = new Promise((resolve) => {
fetch("/xhr/resources/dummy").then(() => {}, resolve);
});
document.body.removeChild(element);
await waitUntilFail;
},
'On-going subresource loading should fail immediately when the element is ' +
'removed.');

View file

@ -0,0 +1,12 @@
promise_test(async () => {
const response = await fetch('/web-bundle/resources/wbn/nested-sub.wbn');
assert_true(response.ok);
}, 'A nested bundle can be fetched');
promise_test(async () => {
await addWebBundleElementAndWaitForError(
'/web-bundle/resources/wbn/nested-sub.wbn',
['/web-bundle/resources/wbn/root.js']);
const response = await fetch('/web-bundle/resources/wbn/root.js');
assert_false(response.ok);
}, 'Subresources in a nested bundle should not be loaded');

View file

@ -0,0 +1,15 @@
// This test uses a non-existing WebBundle from a non-existent host, which makes
// Web Bundle fetching fail due to a network error. The intent of is to check if
// failing to fetch a WebBundle also makes subresource fetch requests fail.
promise_test(async () => {
const prefix = 'https://{{hosts[][nonexistent]}}/';
const resources = [
prefix + 'resource.js',
];
const link = await addWebBundleElementAndWaitForError(
prefix + 'non-existing.wbn',
resources);
// Can not fetch a subresource because Web Bundle fetch failed.
await fetchAndWaitForReject(prefix + 'resource.js');
}, 'Subresource fetch requests for non-existing Web Bundle should fail.');

View file

@ -0,0 +1,17 @@
// This test uses a non-existing WebBundle,
// /web-bundle/resources/wbn/cors/non-existing.wbn.
// The intent of this test is to check if failing to fetch a WebBundle due to
// not found error also makes subresource fetch requests fail.
promise_test(async () => {
const prefix = '/web-bundle/resources/wbn/';
const resources = [
prefix + 'resource.js',
];
const element = await createWebBundleElement(
prefix + 'non-existing.wbn',
resources);
document.body.appendChild(element);
// Can not fetch a subresource because Web Bundle fetch failed.
await fetchAndWaitForReject(prefix + 'resource.js');
}, 'Subresource fetch requests for non-existing Web Bundle should fail.');

View file

@ -0,0 +1,23 @@
promise_test(async () => {
const resources = [
"/web-bundle/resources/wbn/resource.js",
"/web-bundle/resources/wbn/sub/resource.js",
];
for (const resource of resources) {
const response = await fetch(resource);
assert_true(response.ok, resource + " should be loaded");
}
}, "Subresources should be loaded.");
promise_test(async () => {
const resources = [
"/web-bundle/resources/wbn-resource.js",
"/web-bundle/resources/wbn1/resource.js",
"/web-bundle/resources/other/resource.js",
"/web-bundle/resources/resource.js",
];
for (const resource of resources) {
const response = await fetch(resource);
assert_false(response.ok, resource + " should not be loaded");
}
}, "Subresources should not be loaded due to path restriction.");

View file

@ -0,0 +1,17 @@
promise_test(async (t) => {
assert_array_equals(
loaded_scripts,
[
'relative-url-file.js',
'start-with-double-slash-cors.js',
'start-with-slash.js',
'subdirectory-path.js',
'starts-with-two-dots.js',
]);
assert_array_equals(
failed_scripts,
[
'starts-with-two-dots-out-of-scope.js',
]);
},
'Relative Url in web bundle.');

View file

@ -0,0 +1,17 @@
promise_test(async (t) => {
assert_array_equals(
loaded_scripts,
[
'relative-url-file.js',
'start-with-double-slash.js',
'start-with-slash.js',
'subdirectory-path.js',
'starts-with-two-dots.js',
]);
assert_array_equals(
failed_scripts,
[
'starts-with-two-dots-out-of-scope.js',
]);
},
'Relative Url in web bundle.');

View file

@ -0,0 +1,79 @@
// This test tries to load 'script.js' subresource from a static-element.wbn,
// using a relative URL instead of an absolute one with a <link> and <script>
// elements directly in the document (they are used only for this test).
promise_test(async () => {
assert_equals(resources_script_result, 'loaded from webbundle');
},
'A subresource script.js should be loaded from WebBundle using the relative ' +
'URL.');
// Simple load of a root.js subresource from subresource.wbn using a relative
// URL.
promise_test(async () => {
const resource_url = '/web-bundle/resources/wbn/root.js';
const element = createWebBundleElement(
'../resources/wbn/subresource.wbn',
[resource_url]);
document.body.appendChild(element);
const response = await fetch(resource_url);
assert_true(response.ok);
const root = await response.text();
assert_equals(root, 'export * from \'./submodule.js\';\n');
}, 'Subresources with relative URLs should be loaded from the WebBundle.');
// Simple load of a root.js subresource from subresource.wbn using an
// incorrect relative URL leading to a failed fetch.
promise_test(async () => {
const resource_url = 'web-bundle/resources/wbn/root.js';
const element = createWebBundleElement(
'../resources/wbn/subresource.wbn',
[resource_url]);
document.body.appendChild(element);
const response = await fetch(resource_url);
assert_false(response.ok);
}, 'Wrong relative URL should result in a failed fetch.');
// Simple load of subresources under a scope from dynamic1.wbn using a relative
// URL.
promise_test(async () => {
const resource_scope = '/web-bundle/resources/wbn/dynamic/resource';
const element = createWebBundleElement(
'../resources/wbn/dynamic1.wbn',
[], {scopes: [resource_scope]});
document.body.appendChild(element);
const module = await import('/web-bundle/resources/wbn/dynamic/resource1.js');
assert_equals(module.result, 'resource1 from dynamic1.wbn');
const module2 = await import('/web-bundle/resources/wbn/dynamic/resource2.js');
assert_equals(module2.result, 'resource2 from dynamic1.wbn');
const module3 = await import('/web-bundle/resources/wbn/dynamic/resource3.js');
assert_equals(module3.result, 'resource3 from dynamic1.wbn');
const module4 = await import('/web-bundle/resources/wbn/dynamic/resource4.js');
assert_equals(module4.result, 'resource4 from dynamic1.wbn');
}, 'Subresources inside the scope specified with relative URL should be loaded from the WebBundle.');
// Simple load of subresources under a scope from dynamic1.wbn using a relative
// URL. As the scope URL is wrong, the fetch should fail.
promise_test(async () => {
const resource_scope = '/web-bundle/resources/wbn/dynami/';
const element = createWebBundleElement(
'../resources/wbn/dynamic1.wbn',
[], {scopes: [resource_scope]});
document.body.appendChild(element);
const result_promise = new Promise((resolve) => {
// This function will be called from script.js
window.report_result = resolve;
});
const script = document.createElement('script');
script.src = '/web-bundle/resources/wbn/dynamic/classic_script.js';
document.body.appendChild(script);
assert_equals(await result_promise, 'classic script from network');
}, 'No subresources should be loaded from the bundle when the relative url of the scope is wrong');

View file

@ -0,0 +1,25 @@
test(() => {
assert_equals(resources_script_result, 'loaded from webbundle');
},
'A subresource script.js should be loaded from WebBundle using the relative ' +
'URL and a base element.');
promise_test(async () => {
const module = await import("/web-bundle/resources/wbn/dynamic/resource1.js");
assert_equals(module.result, "resource1 from dynamic1.wbn");
const module2 = await import("/web-bundle/resources/wbn/dynamic/resource2.js");
assert_equals(module2.result, "resource2 from dynamic1.wbn");
const module3 = await import("/web-bundle/resources/wbn/dynamic/resource3.js");
assert_equals(module3.result, "resource3 from dynamic1.wbn");
const module4 = await import("/web-bundle/resources/wbn/dynamic/resource4.js");
assert_equals(module4.result, "resource4 from dynamic1.wbn");
const result_promise = new Promise((resolve) => {
// This function will be called from script.js
window.report_result = resolve;
});
const script = document.createElement('script');
script.src = "/web-bundle/resources/wbn/dynamic/classic_script.js";
document.body.appendChild(script);
assert_equals(await result_promise, "classic script from network");
}, "Subresources that start with 'resource' should be loaded from dynamic1.wbn while others from network.");

View file

@ -0,0 +1,37 @@
// check-sec-fetch-dest-header-and-return-bundle.py returns a valid format
// bundle only if a 'Sec-Fetch-Dest: webbundle' header is present in a request.
// Otherwise, returns an empty body with 400 status code.
//
// In this wpt, we assume that a <link> element fires a load event correctly if
// a valid format webbundle is returned.
const same_origin_bundle =
'../resources/check-sec-fetch-dest-header-and-return-bundle.py';
const cross_origin_bundle =
'https://{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/check-sec-fetch-dest-header-and-return-bundle.py';
promise_test(async () => {
for (const bundle of [same_origin_bundle, cross_origin_bundle]) {
const element = createWebBundleElement(
bundle,
/*resources=*/[]);
await addElementAndWaitForLoad(element);
element.remove();
}
},
'"Sec-Fetch-Dest: webbundle" header must be present in a request for a bundle' +
' with the <link>-based API.');
promise_test(async () => {
const res = await fetch(same_origin_bundle);
assert_false(res.ok);
},
'"Sec-Fetch-Dest: webbundle" header must not be present in a fetch request' +
' for a same-origin resource.');
promise_test(async () => {
const res = await fetch(cross_origin_bundle);
assert_false(res.ok);
},
'"Sec-Fetch-Dest: webbundle" header must not be present in a fetch request' +
' for a cross-origin resource.');

View file

@ -0,0 +1,61 @@
promise_test(async t => {
const bundle_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic1.wbn?pipe=trickle(d0.5)';
const script_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js';
const element = createWebBundleElement(
'../resources/wbn/dynamic1.wbn?pipe=trickle(d0.5)',
/*resources=*/[script_url]);
document.body.appendChild(element);
var script_entries = 0;
var web_bundle_entries = 0;
var web_bundle_entry, script_entry;
const promise = new Promise(resolve => {
new PerformanceObserver(t.step_func(entryList => {
var entries = entryList.getEntriesByType('resource');
for (var i = 0; i < entries.length; ++i) {
if (entries[i].name === script_url) {
script_entry = entries[i];
script_entries++;
}
if (entries[i].name === bundle_url) {
web_bundle_entry = entries[i];
web_bundle_entries++;
}
}
if (web_bundle_entries > 0 && script_entries > 0) {
// Check timestamps.
assert_greater_than_equal(
script_entry.responseStart,
script_entry.requestStart + 500);
assert_greater_than_equal(
script_entry.responseStart,
web_bundle_entry.responseStart);
assert_greater_than_equal(
script_entry.responseEnd,
script_entry.responseStart);
assert_greater_than_equal(
script_entry.requestStart,
script_entry.connectEnd);
assert_greater_than_equal(
script_entry.responseEnd,
script_entry.responseStart);
// Check sizes.
assert_greater_than(script_entry.encodedBodySize, 0);
assert_equals(
script_entry.transferSize,
script_entry.encodedBodySize + 300);
assert_equals(
script_entry.encodedBodySize,
script_entry.decodedBodySize);
resolve();
}
})).observe({entryTypes: ['resource']});
});
const script = document.createElement('script');
script.type = 'module';
script.src = script_url;
document.body.appendChild(script);
return promise;
},
'Timestamp attributes filled in resource timing entries should be consistent.');

View file

@ -0,0 +1,40 @@
promise_test(async t => {
const frame_id = 'urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae';
const script_id = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const element = createWebBundleElement(
'../resources/wbn/urn-uuid.wbn',
/*resources=*/[frame_id, script_id]);
document.body.appendChild(element);
let iframe_entries = 0;
let script_entries = 0;
// Declare the report_result function as outputting into stderr
// because it is used in the WebBundle script to report the script load.
window.report_result = console.error;
const promise = new Promise(resolve => {
new PerformanceObserver(t.step_func(entryList => {
let entries = entryList.getEntriesByType('resource');
for (let i = 0; i < entries.length; ++i) {
// Ignore any entries for the test harness files if present.
if (/testharness(report)?\.js/.test(entries[i].name)) {
continue;
}
if (entries[i].name === frame_id)
++iframe_entries;
if (entries[i].name === script_id)
++script_entries;
}
if (iframe_entries == 1 && script_entries == 1) {
resolve();
}
})).observe({entryTypes: ['resource']});
});
// Add iframe and the script so we get the ResourceTiming
const iframe = document.createElement('iframe');
iframe.src = frame_id;
document.body.appendChild(iframe);
const script = document.createElement('script');
script.src = script_id;
document.body.appendChild(script);
return promise;
}, 'Each urn:uuid resource should have exactly 1 ResourceTiming entry.');

View file

@ -0,0 +1,102 @@
async function registerServiceWorkerAndReturnActiveWorker(t, script, scope) {
const reg = await navigator.serviceWorker.register(script, {scope: scope});
t.add_cleanup(() => reg.unregister());
if (reg.active)
return reg.active;
const worker = reg.installing || reg.waiting;
await new Promise((resolve) => {
worker.addEventListener('statechange', (event) => {
if (event.target.state == 'activated')
resolve();
});
});
return worker;
}
async function getRequestedUrls(worker) {
return new Promise(resolve => {
navigator.serviceWorker.addEventListener(
'message',
e => {resolve(e.data);},
{once: true})
worker.postMessage(null);
});
}
promise_test(async (t) => {
const iframe_path = './resources/service-worker-controlled-iframe.html';
const iframe_url = new URL(iframe_path, location).href
// Register a service worker.
const worker = await registerServiceWorkerAndReturnActiveWorker(
t,
'./resources/service-worker-for-request-monitor.js',
iframe_path);
// Load an iframe which is controlled by the service worker.
const iframe = await new Promise(resolve => {
const frame = document.createElement('iframe');
t.add_cleanup(() => frame.remove());
frame.src = iframe_url;
frame.onload = () => { resolve(frame); };
document.body.appendChild(frame);
});
// The iframe request should be intercepted by the service worker.
assert_array_equals(await getRequestedUrls(worker), [iframe_url]);
// Add a web bundle element in the service worker controlled iframe.
const frame_id = 'urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae';
const script_id = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const element = createWebBundleElement(
'../../resources/wbn/urn-uuid.wbn',
/*resources=*/[frame_id, script_id]);
const element_load_promise = new Promise(resolve => {
element.addEventListener('load', () => {resolve();});
});
iframe.contentDocument.body.appendChild(element);
await element_load_promise;
// The web bundle request should not be intercepted by the service worker.
assert_array_equals(await getRequestedUrls(worker), []);
// Add an urn uuid URL script element in the service worker controlled
// iframe.
const result_promise = new Promise(resolve => {
// window.report_result() method will be called by the injected script.
iframe.contentWindow.report_result = resolve;
});
const script = iframe.contentDocument.createElement('script');
script.src = script_id;
iframe.contentDocument.body.appendChild(script);
assert_equals(await result_promise, 'OK');
// The urn uuld URL script request should not be intercepted by the
// service worker.
assert_array_equals(await getRequestedUrls(worker), []);
// Add an urn uuid URL iframe element in the service worker controlled
// iframe.
const inner_iframe = iframe.contentDocument.createElement('iframe');
inner_iframe.src = frame_id;
const load_promise = new Promise(resolve => {
inner_iframe.addEventListener('load', () => {resolve();});
});
iframe.contentDocument.body.appendChild(inner_iframe);
await load_promise;
// The urn uuld URL iframe request should not intercepted by the service
// worker.
assert_array_equals(await getRequestedUrls(worker), []);
// Check if the urn uuid URL iframe element is loaded correctly.
const message_promise = new Promise(resolve => {
window.addEventListener(
'message',
e => {resolve(e.data);},
{once: true});
});
// location.href is evaluated in the urn uuid URL iframe element.
inner_iframe.contentWindow.postMessage('location.href', '*');
assert_equals(await message_promise, frame_id);
},
'Both Web Bundle request and Subresource fetch requests inside the Web ' +
'Bundle should skip the service worker.');

View file

@ -0,0 +1,12 @@
let request_urls = [];
self.addEventListener('fetch', e => {
request_urls.push(e.request.url);
e.respondWith(fetch(e.request));
});
self.addEventListener('message', e => {
e.source.postMessage(request_urls);
request_urls = [];
});

View file

@ -0,0 +1,18 @@
promise_test(async () => {
assert_equals(resources_script_result, 'loaded from webbundle');
assert_equals(scopes_script_result, 'loaded from webbundle');
assert_equals(out_of_scope_script_result, 'loaded from network');
['resources_', 'scopes_'].forEach((type) => {
['style_target',
'style_imported_from_file_target',
'style_imported_from_tag_target'].forEach((target) => {
const element = document.createElement('div');
element.id = type + target;
document.body.appendChild(element);
assert_equals(window.getComputedStyle(element).color,
'rgb(0, 0, 255)',
element.id + ' color must be blue');
});
});
}, 'Subresources from static elements should be loaded from web bundle.');

View file

@ -0,0 +1,116 @@
promise_test(async (t) => {
const bundle_url = '../resources/wbn/urn-uuid.wbn';
const frame_url = 'urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae';
const iframe = await createWebBundleElementAndIframe(t, bundle_url, frame_url);
// The iframe is cross-origin. So accessing iframe.contentWindow.location
// should throw a SecurityError.
assert_throws_dom(
"SecurityError",
() => { iframe.contentWindow.location.href; });
}, 'The urn:uuid URL iframe must be cross-origin.');
promise_test(async (t) => {
const bundle_url = '../resources/wbn/uuid-in-package.wbn';
const frame_url = 'uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ae';
const iframe = await createWebBundleElementAndIframe(t, bundle_url, frame_url);
// The iframe is cross-origin. So accessing iframe.contentWindow.location
// should throw a SecurityError.
assert_throws_dom(
"SecurityError",
() => { iframe.contentWindow.location.href; });
}, 'The uuid-in-package: URL iframe must be cross-origin.');
uuid_iframe_test(
'location.href',
['urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae',
'uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ae'],
'location.href in opaque-origin iframe.');
uuid_iframe_test(
'(' + (() => {
try {
let result = window.localStorage;
return 'no error';
} catch (e) {
return e.name;
}
}).toString() + ')()',
'SecurityError',
'Accesing window.localStorage should throw a SecurityError.');
uuid_iframe_test(
'(' + (() => {
try {
let result = window.sessionStorage;
return 'no error';
} catch (e) {
return e.name;
}
}).toString() + ')()',
'SecurityError',
'Accesing window.sessionStorage should throw a SecurityError.');
uuid_iframe_test(
'(' + (() => {
try {
let result = document.cookie;
return 'no error';
} catch (e) {
return e.name;
}
}).toString() + ')()',
'SecurityError',
'Accesing document.cookie should throw a SecurityError.');
uuid_iframe_test(
'(' + (() => {
try {
let request = window.indexedDB.open("db");
return 'no error';
} catch (e) {
return e.name;
}
}).toString() + ')()',
'SecurityError',
'Opening an indexedDB should throw a SecurityError.');
uuid_iframe_test(
'window.caches === undefined',
true,
'window.caches should be undefined.');
function uuid_iframe_test(code, expected, name) {
if (!Array.isArray(expected)) {
expected = [expected, expected];
}
promise_test(async (t) => {
const bundle_url = '../resources/wbn/urn-uuid.wbn';
const frame_url = 'urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae';
const iframe = await createWebBundleElementAndIframe(t, bundle_url, frame_url);
assert_equals(await evalInIframe(iframe, code), expected[0]);
}, name + '(urn:uuid)');
promise_test(async (t) => {
const bundle_url = '../resources/wbn/uuid-in-package.wbn';
const frame_url = 'uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ae';
const iframe = await createWebBundleElementAndIframe(t, bundle_url, frame_url);
assert_equals(await evalInIframe(iframe, code), expected[1]);
}, name + 'uuid-in-package');
}
async function createWebBundleElementAndIframe(t, bundle_url, frame_url) {
const element = createWebBundleElement(bundle_url, [frame_url]);
document.body.appendChild(element);
const iframe = document.createElement('iframe');
t.add_cleanup(() => {
document.body.removeChild(element);
document.body.removeChild(iframe);
});
iframe.src = frame_url;
const load_promise = new Promise((resolve) => {
iframe.addEventListener('load', resolve);
});
document.body.appendChild(iframe);
await load_promise;
return iframe;
}

View file

@ -0,0 +1,307 @@
promise_test(async () => {
const module = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/root.js');
assert_equals(module.result, 'OK');
}, 'Subresource loading with WebBundle');
promise_test(async () => {
const response = await fetch('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/root.js');
const text = await response.text();
assert_equals(text, 'export * from \'./submodule.js\';\n');
}, 'Subresource loading with WebBundle (Fetch API)');
promise_test(t => {
const url =
'/common/redirect.py?location=https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/root.js';
return promise_rejects_js(t, TypeError, import(url));
}, 'Subresource loading with WebBundle shouldn\'t affect redirect');
promise_test(async () => {
const element = createWebBundleElement(
'../resources/wbn/dynamic1-b1.wbn',
[
'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js',
'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource2.js',
'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource4.js'
]);
document.body.appendChild(element);
const module = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js');
assert_equals(module.result, 'resource1 from dynamic1.wbn');
document.body.removeChild(element);
}, 'Subresource loading from a b1 bundle');
promise_test(async () => {
const classic_script_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/classic_script.js';
const element = createWebBundleElement(
'../resources/wbn/dynamic1-b1.wbn',
[classic_script_url]);
document.body.appendChild(element);
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic1.wbn');
const new_element = removeAndAppendNewElementWithUpdatedRule(element, {url: '../resources/wbn/dynamic2-b1.wbn'});
// Loading the classic script should not reuse the previously loaded
// script. So in this case, the script must be loaded from dynamic2-b1.wbn.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic2.wbn');
document.body.removeChild(new_element);
// And in this case, the script must be loaded from network.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from network');
}, 'Dynamically loading classic script from a \'b1\' web bundle with resources attribute');
promise_test(async () => {
const element = createWebBundleElement(
'../resources/wbn/dynamic1.wbn',
[
'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js',
'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource2.js',
'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource4.js'
]);
document.body.appendChild(element);
const module = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js');
assert_equals(module.result, 'resource1 from dynamic1.wbn');
const new_element = removeAndAppendNewElementWithUpdatedRule(element, {url: '../resources/wbn/dynamic2-b1.wbn'});
const module2 = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource2.js');
assert_equals(module2.result, 'resource2 from dynamic2.wbn');
// A resource not specified in the resources attribute, but in the bundle.
const module3 = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource3.js');
assert_equals(module3.result, 'resource3 from network');
document.body.removeChild(new_element);
const module4 = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource4.js');
assert_equals(module4.result, 'resource4 from network');
// Module scripts are stored to the Document's module map once loaded.
// So import()ing the same module script will reuse the previously loaded
// script.
const module_second = await import('https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js');
assert_equals(module_second.result, 'resource1 from dynamic1.wbn');
}, 'Dynamically adding / updating / removing the webbundle element.');
promise_test(async () => {
const classic_script_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/classic_script.js';
const element = createWebBundleElement(
'../resources/wbn/dynamic1.wbn',
[classic_script_url]);
document.body.appendChild(element);
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic1.wbn');
const new_element = removeAndAppendNewElementWithUpdatedRule(element, {url: '../resources/wbn/dynamic2-b1.wbn'});
// Loading the classic script should not reuse the previously loaded
// script. So in this case, the script must be loaded from dynamic2.wbn.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic2.wbn');
document.body.removeChild(new_element);
// And in this case, the script must be loaded from network.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from network');
}, 'Dynamically loading classic script from web bundle');
promise_test(async (t) => {
// To avoid caching mechanism, this test is using fetch() API with
// { cache: 'no-store' } to load the resource.
const classic_script_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/classic_script.js';
assert_equals(
await (await fetch(classic_script_url)).text(),
'window.report_result(\'classic script from network\');\n');
const element1 = createWebBundleElement(
'../resources/wbn/dynamic1.wbn',
[classic_script_url]);
document.body.appendChild(element1);
t.add_cleanup(() => {
if (element1.parentElement)
element1.parentElement.removeChild(element1);
});
assert_equals(
await (await fetch(classic_script_url, { cache: 'no-store' })).text(),
'window.report_result(\'classic script from dynamic1.wbn\');\n');
const element2 = createWebBundleElement(
'../resources/wbn/dynamic2.wbn',
[classic_script_url]);
document.body.appendChild(element2);
t.add_cleanup(() => {
if (element2.parentElement)
element2.parentElement.removeChild(element2);
});
assert_equals(
await (await fetch(classic_script_url, { cache: 'no-store' })).text(),
'window.report_result(\'classic script from dynamic2.wbn\');\n');
document.body.removeChild(element2);
assert_equals(
await (await fetch(classic_script_url, { cache: 'no-store' })).text(),
'window.report_result(\'classic script from dynamic1.wbn\');\n');
document.body.removeChild(element1);
assert_equals(
await (await fetch(classic_script_url, { cache: 'no-store' })).text(),
'window.report_result(\'classic script from network\');\n');
}, 'Multiple web bundle elements. The last added element must be refered.');
promise_test(async () => {
const classic_script_url = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/classic_script.js';
const scope = 'https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/';
const element = createWebBundleElement(
'../resources/wbn/dynamic1.wbn',
[],
{scopes: [scope]});
document.body.appendChild(element);
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic1.wbn');
const new_element = removeAndAppendNewElementWithUpdatedRule(element, {url: '../resources/wbn/dynamic2.wbn'});
// Loading the classic script should not reuse the previously loaded
// script. So in this case, the script must be loaded from dynamic2.wbn.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic2.wbn');
// Changes the scope not to hit the classic_script.js.
const new_element2 = removeAndAppendNewElementWithUpdatedRule(new_element, {scopes: [scope + 'dummy']});
// And in this case, the script must be loaded from network.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from network');
// Adds the scope to hit the classic_script.js.
const new_element3 = removeAndAppendNewElementWithUpdatedRule(new_element2, {scopes: [scope + 'dummy', scope + 'classic_']});
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic2.wbn');
document.body.removeChild(new_element3);
// And in this case, the script must be loaded from network.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from network');
}, 'Dynamically loading classic script from web bundle with scopes');
promise_test(() => {
return addWebBundleElementAndWaitForLoad(
'../resources/wbn/dynamic1.wbn?test-event',
/*resources=*/[],
{crossOrigin: undefined});
}, 'The webbundle element fires a load event on load success');
promise_test((t) => {
return addWebBundleElementAndWaitForError(
'../resources/wbn/nonexistent.wbn',
/*resources=*/[],
{crossOrigin: undefined});
}, 'The webbundle element fires an error event on load failure');
promise_test(async () => {
const module_script_url = 'https://www1.{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js';
const element = createWebBundleElement(
'../resources/wbn/dynamic1-crossorigin.wbn',
[module_script_url]);
document.body.appendChild(element);
const module = await import(module_script_url);
assert_equals(module.result, 'resource1 from network');
}, 'Subresource URL must be same-origin with bundle URL');
promise_test(async () => {
const module_script_url = 'https://www1.{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/dynamic/resource1.js';
const element = createWebBundleElement(
'../resources/wbn/dynamic1-crossorigin-b1.wbn',
[module_script_url]);
document.body.appendChild(element);
const module = await import(module_script_url);
assert_equals(module.result, 'resource1 from network');
}, 'Subresource URL must be same-origin with bundle URL (for \'b1\' bundles too)');
promise_test(async () => {
const url = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const element = createWebBundleElement(
'../resources/wbn/urn-uuid.wbn',
[url]);
document.body.appendChild(element);
assert_equals(await loadScriptAndWaitReport(url), 'OK');
document.body.removeChild(element);
}, 'Subresource loading with urn:uuid: URL with resources attribute');
promise_test(async () => {
const url = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const element = createWebBundleElement(
'../resources/wbn/urn-uuid.wbn',
[],
{scopes: ['urn:uuid:']});
document.body.appendChild(element);
assert_equals(await loadScriptAndWaitReport(url), 'OK');
document.body.removeChild(element);
}, 'Subresource loading with urn:uuid: URL with scopes attribute');
promise_test(async () => {
const url = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const element = createWebBundleElement(
'../resources/wbn/urn-uuid-b1.wbn',
[url]);
document.body.appendChild(element);
assert_equals(await loadScriptAndWaitReport(url), 'OK');
document.body.removeChild(element);
}, 'Subresource loading with urn:uuid: URL of a \'b1\' bundle with resources attribute');
promise_test(async () => {
const url = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const element = createWebBundleElement(
'../resources/wbn/urn-uuid-b1.wbn',
[],
{scopes: ['urn:uuid:']});
document.body.appendChild(element);
assert_equals(await loadScriptAndWaitReport(url), 'OK');
document.body.removeChild(element);
}, 'Subresource loading with urn:uuid: URL of a \'b1\' bundle with scopes attribute');
promise_test(async () => {
const url = 'uuid-in-package:020111b3-437a-4c5c-ae07-adb6bbffb720';
const element = createWebBundleElement(
'../resources/wbn/uuid-in-package.wbn',
[url]);
document.body.appendChild(element);
assert_equals(await loadScriptAndWaitReport(url), 'OK');
document.body.removeChild(element);
}, 'Subresource loading with uuid-in-package: URL with resources attribute');
promise_test(async () => {
const url = 'uuid-in-package:020111b3-437a-4c5c-ae07-adb6bbffb720';
const element = createWebBundleElement(
'../resources/wbn/uuid-in-package.wbn',
[],
{scopes: ['uuid-in-package:']});
document.body.appendChild(element);
assert_equals(await loadScriptAndWaitReport(url), 'OK');
document.body.removeChild(element);
}, 'Subresource loading with uuid-in-package: URL with scopes attribute');
async function loadScriptAndWaitReport(script_url) {
const result_promise = new Promise((resolve) => {
// This function will be called from script.js
window.report_result = resolve;
});
const script = document.createElement('script');
script.src = script_url;
document.body.appendChild(script);
return result_promise;
}
function removeAndAppendNewElementWithUpdatedRule(element, new_rule) {
const new_element = createNewWebBundleElementWithUpdatedRule(element, new_rule);
element.remove();
document.body.appendChild(new_element);
return new_element;
}

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<title>Accept: request header in webbundle requests</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'script';
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<body>
<script src="resources/accept-header-test.js"></script>
</body>

View file

@ -0,0 +1,42 @@
<!DOCTYPE html>
<title>COEP for WebBundle subresource loading</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<link rel="help" href="https://html.spec.whatwg.org/multipage/origin.html#coep" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<!--
This wpt should run on an origin different from https://www1.web-platform.test:8444/,
from where cross-orign WebBundles are served.
This test uses a cross-origin WebBundle,
https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp.wbn,
which is served with an Access-Control-Allow-Origin response header.
`corp.wbn` includes three subresources:
a. `no-corp.js`, which doesn't include a Cross-Origin-Resource-Policy response header.
b. `corp-same-origin.js`, which includes a Cross-Origin-Resource-Policy: same-origin response header.
c. `corp-cross-origin.js`, which includes a Cross-Origin-Resource-Policy: cross-origin response header.
-->
<script type="webbundle">
{
"source": "https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp.wbn",
"resources": [
"https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/no-corp.js",
"https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp-same-origin.js",
"https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp-cross-origin.js",
"urn:uuid:5eafff38-e0a0-4661-bde0-434255aa9d93",
"urn:uuid:7e13b47a-8b91-4a0e-997c-993a5e2f3a34",
"urn:uuid:86d5b696-8867-4454-8b07-51239a0817f7"
]
}
</script>
<script>
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<script src="resources/coep-test.js"></script>
</body>

View file

@ -0,0 +1,2 @@
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: cross-origin

View file

@ -0,0 +1,42 @@
<!DOCTYPE html>
<title>CORP for WebBundle subresource loading</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md#cors-and-corp-for-subresource-requests" />
<link rel="help" href="https://fetch.spec.whatwg.org/#cross-origin-resource-policy-header" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<!--
This wpt should run on an origin different from https://www1.web-platform.test:8444/,
from where cross-orign WebBundles are served.
This test uses a cross-origin WebBundle,
https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp.wbn,
which is served with an Access-Control-Allow-Origin response header.
`corp.wbn` includes three subresources:
a. `no-corp.js`, which doesn't include a Cross-Origin-Resource-Policy response header.
b. `corp-same-origin.js`, which includes a Cross-Origin-Resource-Policy: same-origin response header.
c. `corp-cross-origin.js`, which includes a Cross-Origin-Resource-Policy: cross-origin response header.
-->
<script type="webbundle">
{
"source": "https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp.wbn",
"resources": [
"https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/no-corp.js",
"https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp-same-origin.js",
"https://www1.web-platform.test:8444/web-bundle/resources/wbn/cors/corp-cross-origin.js",
"urn:uuid:5eafff38-e0a0-4661-bde0-434255aa9d93",
"urn:uuid:7e13b47a-8b91-4a0e-997c-993a5e2f3a34",
"urn:uuid:86d5b696-8867-4454-8b07-51239a0817f7"
]
}
</script>
<script>
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<script src="resources/corp-test.js"></script>
</body>

View file

@ -0,0 +1,151 @@
<!DOCTYPE html>
<title>
Credentials in WebBundle subresource loading
</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md#requests-mode-and-credentials-mode"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<script>
// In this wpt, we test a request's credential mode, which controls
// whether UA sends a credential or not to fetch a bundle.
// If UA sends a credential, check-cookie-and-return-{cross-oriigin}-bundle.py
// returns a valid format webbundle. Then, a subresource fetch should be successful.
// Otherwise, a subresource fetch should be rejected.
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = "script";
setup(() => {
assert_true(HTMLScriptElement.supports("webbundle"));
});
document.cookie = "milk=1; path=/";
// Make sure to set a cookie for a cross-origin domain from where a cross
// origin bundle is served.
const setCookiePromise = fetch(
"https://{{domains[www1]}}:{{ports[https][0]}}/cookies/resources/set-cookie.py?name=milk&path=/web-bundle/resources/",
{
mode: "no-cors",
credentials: "include",
}
);
const same_origin_bundle = "../resources/check-cookie-and-return-bundle.py";
const cross_origin_bundle = "https://{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/check-cookie-and-return-bundle.py?bundle=cross-origin";
const same_origin_bundle_subresource = "../resources/wbn/root.js";
const cross_origin_bundle_subresource = "https://{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/simple-cross-origin.txt";
async function assertSubresourceCanBeFetched() {
const response = await fetch(same_origin_bundle_subresource);
const text = await response.text();
assert_equals(text, "export * from './submodule.js';\n");
}
async function assertCrossOriginSubresourceCanBeFetched() {
const response = await fetch(cross_origin_bundle_subresource);
const text = await response.text();
assert_equals(text, "hello from simple-cross-origin.txt");
}
function createScriptWebBundle(credentials) {
const options = {};
if (credentials) {
options.credentials = credentials;
}
return createWebBundleElement(same_origin_bundle, [same_origin_bundle_subresource], options);
}
function createScriptWebBundleCrossOrigin(credentials) {
const options = {};
if (credentials) {
options.credentials = credentials;
}
return createWebBundleElement(cross_origin_bundle, [cross_origin_bundle_subresource], options);
}
promise_test(async (t) => {
const script = createScriptWebBundle();
document.body.append(script);
t.add_cleanup(() => script.remove());
await assertSubresourceCanBeFetched();
}, "The default should send a credential to a same origin bundle");
promise_test(async (t) => {
const script = createScriptWebBundle("invalid");
document.body.append(script);
t.add_cleanup(() => script.remove());
await assertSubresourceCanBeFetched();
}, "An invalid value should send a credential to a same origin bundle");
promise_test(async (t) => {
const script = createScriptWebBundle("omit");
document.body.append(script);
t.add_cleanup(() => script.remove());
return promise_rejects_js(t, TypeError, fetch(same_origin_bundle_subresource))
}, "'omit' should not send a credential to a same origin bundle");
promise_test(async (t) => {
const script = createScriptWebBundle("same-origin");
document.body.append(script);
t.add_cleanup(() => script.remove());
await assertSubresourceCanBeFetched();
}, "'same-origin' should send a credential to a same origin bundle");
promise_test(async (t) => {
const script = createScriptWebBundle("include");
document.body.append(script);
t.add_cleanup(() => script.remove());
await assertSubresourceCanBeFetched();
}, "'include' should send a credential to a same origin bundle");
promise_test(async (t) => {
await setCookiePromise;
const script = createScriptWebBundleCrossOrigin("omit");
document.body.append(script);
t.add_cleanup(() => script.remove());
return promise_rejects_js(t, TypeError, fetch(cross_origin_bundle_subresource))
}, "'omit' should not send a credential to a cross origin bundle");
promise_test(async (t) => {
await setCookiePromise;
const script = createScriptWebBundleCrossOrigin("same-origin");
document.body.append(script);
t.add_cleanup(() => script.remove());
return promise_rejects_js(t, TypeError, fetch(cross_origin_bundle_subresource))
}, "'same-origin' should not send a credential to a cross origin bundle");
promise_test(async (t) => {
await setCookiePromise;
const script = createScriptWebBundleCrossOrigin("include");
document.body.append(script);
t.add_cleanup(() => script.remove());
await assertCrossOriginSubresourceCanBeFetched();
}, "'include' should send a credential to a cross origin bundle");
promise_test(async (t) => {
const script = createScriptWebBundleCrossOrigin("invalid");
document.body.append(script);
t.add_cleanup(() => script.remove());
return promise_rejects_js(t, TypeError, fetch(cross_origin_bundle_subresource))
}, "An invalid value should not send a credential to a cross origin bundle");
</script>
</body>

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<title>On-going subresource loading should fail immediately when the web bundle element is removed</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'script';
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<body>
<script src="resources/element-removal-test.js"></script>
</body>

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<title>A nested bundle is not supported</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'script';
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<body>
<script type="webbundle">
{
"source": "/web-bundle/resources/wbn/nested-main.wbn",
"resources": ["/web-bundle/resources/wbn/nested-sub.wbn"]
}
</script>
<script src="resources/nested-bundle-test.js"></script>
</body>

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<title>Web Bundle fetching failed due to a network error</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'script';
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<body>
<script src="resources/network-error-test.sub.js"></script>
</body>

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<title>Web Bundle fetching failed due to not found error</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'script';
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<body>
<script src="resources/not-found-test.js"></script>
</body>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<title>Path restriction on subresource loading with WebBundles</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script type="webbundle">
{
"source": "../resources/wbn/path-restriction.wbn",
"resources": [
"/web-bundle/resources/wbn/resource.js",
"/web-bundle/resources/wbn/sub/resource.js",
"/web-bundle/resources/wbn-resource.js",
"/web-bundle/resources/wbn1/resource.js",
"/web-bundle/resources/other/resource.js",
"/web-bundle/resources/resource.js"
]
}
</script>
<script>
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<script src="resources/path-restriction-test.js"></script>
</body>

View file

@ -0,0 +1,45 @@
<!DOCTYPE html>
<title>Relative Url in cross origin web bundle</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<script type="webbundle">
{
"source": "//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url.wbn",
"resources": [
"//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url-file.js",
"//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url/start-with-double-slash-cors.js",
"//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url/start-with-slash.js",
"//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url/subdirectory-path.js",
"//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/starts-with-two-dots.js",
"//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/starts-with-two-dots-out-of-scope.js"
]
}
</script>
<script>
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
const loaded_scripts = [];
function scriptLoaded(file) {
loaded_scripts.push(file);
}
const failed_scripts = [];
function scriptFailed(file) {
failed_scripts.push(file);
}
</script>
<script src="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url-file.js"></script>
<script src="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url/start-with-double-slash-cors.js"></script>
<script src="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url/start-with-slash.js"></script>
<script src="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/relative-url/subdirectory-path.js"></script>
<script src="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/wbn/starts-with-two-dots.js"></script>
<script src="//{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/starts-with-two-dots-out-of-scope.js"
onerror="scriptFailed('starts-with-two-dots-out-of-scope.js')"></script>
<script src="resources/relative-url-in-web-bundle-cors-test.js"></script>
</body>

View file

@ -0,0 +1,45 @@
<!DOCTYPE html>
<title>Relative Url in web bundle</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<script type="webbundle">
{
"source": "../resources/wbn/relative-url.wbn",
"resources": [
"relative-url-file.js",
"relative-url/start-with-double-slash.js",
"relative-url/start-with-slash.js",
"relative-url/subdirectory-path.js",
"starts-with-two-dots.js",
"starts-with-two-dots-out-of-scope.js"
]
}
</script>
<script>
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
const loaded_scripts = [];
function scriptLoaded(file) {
loaded_scripts.push(file);
}
const failed_scripts = [];
function scriptFailed(file) {
failed_scripts.push(file);
}
</script>
<script src="../resources/wbn/relative-url-file.js"></script>
<script src="../resources/wbn/relative-url/start-with-double-slash.js"></script>
<script src="../resources/wbn/relative-url/start-with-slash.js"></script>
<script src="../resources/wbn/relative-url/subdirectory-path.js"></script>
<script src="../resources/wbn/starts-with-two-dots.js"></script>
<script src="../resources/starts-with-two-dots-out-of-scope.js"
onerror="scriptFailed('starts-with-two-dots-out-of-scope.js')"></script>
<script src="resources/relative-url-in-web-bundle-test.js"></script>
</body>

View file

@ -0,0 +1,81 @@
<!DOCTYPE html>
<title>Subresource loading using relative URLs in the 'resources'</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = "script";
setup(() => {
assert_true(HTMLScriptElement.supports("webbundle"));
});
</script>
<body>
<script>
let script;
function cleanUp() {
if (script) {
script.remove();
}
}
function createScriptWebBundle(resource) {
return createWebBundleElement(
"../resources/wbn/subresource.wbn",
/*resources=*/ [resource]
);
}
async function assertResourceCanBeFetched() {
const response = await fetch(`../resources/wbn/root.js`);
const text = await response.text();
assert_equals(text, "export * from './submodule.js';\n");
}
async function assertResourceNotFound() {
const response = await fetch(`../resources/wbn/root.js`);
const status = await response.status;
assert_equals(status, 404);
}
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("root.js");
document.body.append(script);
await assertResourceCanBeFetched();
}, "A relative URL, 'root.js', should be resolved on the bundle's URL");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("./root.js");
document.body.append(script);
await assertResourceCanBeFetched();
}, "Use './root.js', starting with dot");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("../wbn/root.js");
document.body.append(script);
await assertResourceCanBeFetched();
}, "Use '../wbn/root.js', starting with two dots");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("/web-bundle/resources/wbn/root.js");
document.body.append(script);
await assertResourceCanBeFetched();
}, "Use '/web-bundle/resources/wbn/root.js', starting with slash");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("unrelated-relative-url.js");
document.body.append(script);
await assertResourceNotFound();
}, "A resource should not be found");
</script>
</body>

View file

@ -0,0 +1,84 @@
<!DOCTYPE html>
<title>
Subresource loading using relative URLs in the 'scopes'
</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = "script";
setup(() => {
assert_true(HTMLScriptElement.supports("webbundle"));
});
</script>
<body>
<script>
let script;
function cleanUp() {
if (script) {
script.remove();
}
}
function createScriptWebBundle(scope) {
return createWebBundleElement(
"../resources/wbn/relative-url.wbn",
/*resources=*/ [],
{ scopes: [scope] }
);
}
async function assertResourceCanBeFetched() {
const response = await fetch("../resources/wbn/relative-url/subdirectory-path.js");
const text = await response.text();
assert_equals(text, "scriptLoaded('subdirectory-path.js');");
}
async function assertResourceNotFound() {
const response = await fetch("../resources/wbn/relative-url/subdirectory-path.js");
const status = await response.status;
assert_equals(status, 404);
}
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("relative-url");
document.body.append(script);
await assertResourceCanBeFetched();
}, "A relative URL, 'relative-url', should be resolved on the bundle's URL");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("./relative-url");
document.body.append(script);
await assertResourceCanBeFetched();
}, "Use './relative-url', starting with dot");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("../wbn/relative-url");
document.body.append(script);
await assertResourceCanBeFetched();
}, "Use '../wbn/relative-url', starting with two dots");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("/web-bundle/resources/wbn/relative-url");
document.body.append(script);
await assertResourceCanBeFetched();
}, "Use '/web-bundle/resources/wbn/relative-url', starting with slash");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script = createScriptWebBundle("unrelated-scope");
document.body.append(script);
await assertResourceNotFound();
}, "A resource should not be found");
</script>
</body>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<title>WebBundle subresource loading with relative URLs for static elements</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script type="webbundle">
{
"source": "../resources/wbn/static-element.wbn",
"resources": [
"static-element/resources/script.js"
],
"scopes": [
"static-element/scopes"
]
}
</script>
<script src="../resources/wbn/static-element/resources/script.js"></script>
<script src="../resources/wbn/static-element/scopes/script.js"></script>
<script src="../resources/wbn/static-element/out-of-scope/script.js"></script>
<script>
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
promise_test(async () => {
assert_equals(resources_script_result, 'loaded from webbundle');
assert_equals(scopes_script_result, 'loaded from webbundle');
assert_equals(out_of_scope_script_result, 'loaded from network');
}, 'Subresources from static elements should be loaded from web bundle.');
</script>
</body>

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<title>Subresource loading using relative URLs in the 'resources' attribute with a base element</title>
<base href="../resources/wbn/">
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script type="webbundle">
{
"source": "static-element.wbn",
"resources": ["static-element/resources/script.js"]
}
</script>
<script id="script" src="static-element/resources/script.js"></script>
<script type="webbundle">
{
"source": "dynamic1.wbn",
"scopes": ["dynamic/resource"]
}
</script>
<script>
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<script src="/web-bundle/subresource-loading/resources/relative-url-with-base-test.js"></script>
</body>

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<title>Request's destination must be "webbundle" with the script-based API</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'script';
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<body>
<script src="resources/request-destination-test.sub.js"></script>
</body>

View file

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Resource timing attributes are consistent for the same-origin subresources.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'script';
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<body>
<script src="resources/resource-timing-attributes-consistent-test.sub.js"></script>
</body>

View file

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Resource timing entries present for urn:uuid resources</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'script';
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<body>
<script src="resources/resource-timing-test.js"></script>
</body>

View file

@ -0,0 +1,322 @@
<!DOCTYPE html>
<title>script type="webbundle" reuses webbundle resources</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = "script";
setup(() => {
assert_true(HTMLScriptElement.supports("webbundle"));
});
const wbn_url = "../resources/wbn/subresource.wbn";
const wbn_suffix = "subresource.wbn";
const resource1 = "root.js";
const resource2 = "submodule.js";
const resource1_url = `../resources/wbn/${resource1}`;
const resource2_url = `../resources/wbn/${resource2}`;
let script1;
let script2;
function cleanUp() {
if (script1) {
script1.remove();
}
if (script2) {
script2.remove();
}
}
async function assertResource1CanBeFetched() {
const response = await fetch(resource1_url);
const text = await response.text();
assert_equals(text, "export * from './submodule.js';\n");
}
async function assertResource1CanNotBeFetched() {
const response = await fetch(resource1_url);
assert_equals(response.status, 404);
}
async function assertResource2CanBeFetched() {
const response = await fetch(resource2_url);
const text = await response.text();
assert_equals(text, "export const result = 'OK';\n");
}
function createScriptWebBundle1() {
return createWebBundleElement(wbn_url, /*resources=*/ [resource1]);
}
function createScriptWebBundle2(options) {
return createWebBundleElement(wbn_url, /*resources=*/ [resource2], /*options=*/ options);
}
async function appendScriptWebBundle1AndFetchResource1() {
clearWebBundleFetchCount();
script1 = createScriptWebBundle1();
document.body.append(script1);
await assertResource1CanBeFetched();
assert_equals(webBundleFetchCount(wbn_suffix), 1);
}
function clearWebBundleFetchCount() {
performance.clearResourceTimings();
}
function webBundleFetchCount(web_bundle_suffix) {
return performance
.getEntriesByType("resource")
.filter((e) => e.name.endsWith(web_bundle_suffix)).length;
}
promise_test(async (t) => {
t.add_cleanup(cleanUp);
await appendScriptWebBundle1AndFetchResource1();
clearWebBundleFetchCount();
// Append script2 without removing script1.
// script2 should fetch the wbn again.
script2 = createScriptWebBundle2();
document.body.appendChild(script2);
await assertResource1CanBeFetched()
await assertResource2CanBeFetched();
assert_equals(webBundleFetchCount(wbn_suffix), 1);
}, "A webbundle should be fetched again when new script element is appended.");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
await appendScriptWebBundle1AndFetchResource1();
clearWebBundleFetchCount();
// Remove script1, then append script2
// script2 should reuse webbundle resources.
script1.remove();
script2 = createScriptWebBundle2();
document.body.append(script2);
await assertResource1CanNotBeFetched();
await assertResource2CanBeFetched();
assert_equals(webBundleFetchCount(wbn_suffix), 0);
}, "'remove(), then append()' should reuse webbundle resources");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
clearWebBundleFetchCount();
script1 = createScriptWebBundle1();
await addElementAndWaitForLoad(script1);
clearWebBundleFetchCount();
// Remove script1, then append script2
// script2 should reuse webbundle resources.
// And it should also fire a load event.
script1.remove();
script2 = createScriptWebBundle2();
await addElementAndWaitForLoad(script2);
await assertResource1CanNotBeFetched();
await assertResource2CanBeFetched();
assert_equals(webBundleFetchCount(wbn_suffix), 0);
}, "'remove(), then append()' should reuse webbundle resources and both scripts should fire load events");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script1 = createWebBundleElement("nonexistent.wbn", []);
await addElementAndWaitForError(script1);
// Remove script1, then append script2
// script2 should reuse webbundle resources (but we don't verify that).
// And it should also fire an error event.
script1.remove();
script2 = createWebBundleElement("nonexistent.wbn", []);
await addElementAndWaitForError(script2);
}, "'remove(), then append()' should reuse webbundle resources and both scripts should fire error events");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
await appendScriptWebBundle1AndFetchResource1();
clearWebBundleFetchCount();
// Remove script1, then append script2 with an explicit 'same-origin' credentials mode.
script1.remove();
script2 = createScriptWebBundle2({ credentials: "same-origin" });
document.body.append(script2);
await assertResource1CanNotBeFetched();
await assertResource2CanBeFetched();
assert_equals(webBundleFetchCount(wbn_suffix), 0);
}, "Should reuse webbundle resources if a credential mode is same");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
await appendScriptWebBundle1AndFetchResource1();
clearWebBundleFetchCount();
// Remove script1, then append script2 with a different credentials mode.
script1.remove();
script2 = createScriptWebBundle2({ credentials: "omit" });
document.body.append(script2);
await assertResource1CanNotBeFetched();
await assertResource2CanBeFetched();
assert_equals(webBundleFetchCount(wbn_suffix), 1);
}, "Should not reuse webbundle resources if a credentials mode is different (same-origin vs omit)");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
await appendScriptWebBundle1AndFetchResource1();
clearWebBundleFetchCount();
// Remove script1, then append script2 with a different credentials mode.
script1.remove();
script2 = createScriptWebBundle2({ credentials: "include" });
document.body.append(script2);
await assertResource1CanNotBeFetched();
await assertResource2CanBeFetched();
assert_equals(webBundleFetchCount(wbn_suffix), 1);
}, "Should not reuse webbundle resources if a credential mode is different (same-origin vs include");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
await appendScriptWebBundle1AndFetchResource1();
clearWebBundleFetchCount();
// Remove script1, then append the removed one.
script1.remove();
document.body.append(script1);
await assertResource1CanNotBeFetched();
assert_equals(webBundleFetchCount(wbn_suffix), 0);
}, "'remove(), then append()' for the same element should reuse webbundle resources");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
await appendScriptWebBundle1AndFetchResource1();
clearWebBundleFetchCount();
// Multiple 'remove(), then append()' for the same element.
script1.remove();
document.body.append(script1);
script1.remove();
document.body.append(script1);
await assertResource1CanNotBeFetched();
assert_equals(webBundleFetchCount(wbn_suffix), 0);
}, "Multiple 'remove(), then append()' for the same element should reuse webbundle resources");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
await appendScriptWebBundle1AndFetchResource1();
clearWebBundleFetchCount();
// Remove script1.
script1.remove();
// Then append script2 in a separet task.
await new Promise(resolve => t.step_timeout(resolve, 0));
script2 = createScriptWebBundle2();
document.body.append(script2);
await assertResource1CanNotBeFetched();
await assertResource2CanBeFetched();
assert_equals(webBundleFetchCount(wbn_suffix), 1);
}, "'remove(), then append() in a separate task' should not reuse webbundle resources");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
await appendScriptWebBundle1AndFetchResource1();
clearWebBundleFetchCount();
// Use replaceWith() to replace script1 with script2.
// script2 should reuse webbundle resources.
script2 = createScriptWebBundle2();
script1.replaceWith(script2);
await assertResource1CanNotBeFetched();
await assertResource2CanBeFetched();
assert_equals(webBundleFetchCount(wbn_suffix), 0);
}, "replaceWith() should reuse webbundle resources.");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
await appendScriptWebBundle1AndFetchResource1();
clearWebBundleFetchCount();
// Move script1 to another document. Then append script2.
// script2 should reuse webbundle resources.
const another_document = new Document();
another_document.append(script1);
script2 = createScriptWebBundle2();
document.body.append(script2);
await assertResource1CanNotBeFetched();
await assertResource2CanBeFetched();
assert_equals(webBundleFetchCount(wbn_suffix), 0);
// TODO: Test the following cases:
// - The resources are not loaded from the webbundle in the new Document
// (Probably better to use a <iframe>.contentDocument)
// - Even if we move the script element back to the original Document,
// even immediately, the resources are not loaded from the webbundle in the
// original Document.
}, "append() should reuse webbundle resoruces even if the old script was moved to another document.");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
clearWebBundleFetchCount();
script1 = createWebBundleElement(wbn_url + "?pipe=trickle(d0.1)", resource1);
document.body.appendChild(script1);
// While script1 is still loading, remove it and make script2
// reuse the resources.
script1.remove();
script2 = createWebBundleElement(wbn_url + "?pipe=trickle(d0.1)", resource2);
await addElementAndWaitForLoad(script2);
assert_equals(webBundleFetchCount(wbn_suffix + "?pipe=trickle(d0.1)"), 1);
}, "Even if the bundle is still loading, we should reuse the resources.");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script1 = createScriptWebBundle1();
document.body.appendChild(script1);
// Don't wait for the load event for script1.
script1.remove();
script2 = createScriptWebBundle2();
// Load event should be fired for script2 regardless of
// whether script1 fired a load or not.
await addElementAndWaitForLoad(script2);
}, "When reusing the resources with script2, a load event should be fired regardless of if the script1 fired a load");
promise_test(async (t) => {
t.add_cleanup(cleanUp);
script1 = createWebBundleElement("nonexistent.wbn", []);
document.body.appendChild(script1);
// Don't wait for the error event for script1.
script1.remove();
script2 = createWebBundleElement("nonexistent.wbn", []);
// Error event should be fired for script2 regardless of
// whether script1 fired an error event or not.
await addElementAndWaitForError(script2);
}, "When reusing the resources with script2, an error event should be fired regardless of if the script1 fired an error");
</script>
</body>

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<title>Web Bundle fetching and the inner resouirce fetching should skip service worker</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'script';
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<body>
<script src="resources/service-worker-controlled-test.js"></script>
</body>

View file

@ -0,0 +1,41 @@
<!DOCTYPE html>
<title>WebBundle subresource loading for static elements with a base element</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<base href="../resources/wbn/static-element/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script type="webbundle">
{
"source": "../static-element.wbn",
"resources": [
"https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/script.js",
"https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/style.css",
"https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/style-imported-from-file.css",
"https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/style-imported-from-tag.css"
],
"scopes": [
"https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/scopes/"
]
}
</script>
<style type="text/css">
@import 'resources/style-imported-from-tag.css';
@import 'scopes/style-imported-from-tag.css';
</style>
<link href="resources/style.css" rel=stylesheet>
<link href="scopes/style.css" rel=stylesheet>
<script src="resources/script.js"></script>
<script src="scopes/script.js"></script>
<script src="out-of-scope/script.js"></script>
<script>
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<script src="/web-bundle/subresource-loading/resources/static-element-with-test.js"></script>
</body>

View file

@ -0,0 +1,40 @@
<!DOCTYPE html>
<title>WebBundle subresource loading for static elements</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script type="webbundle">
{
"source": "../resources/wbn/static-element.wbn",
"resources": [
"https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/script.js",
"https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/style.css",
"https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/style-imported-from-file.css",
"https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/resources/style-imported-from-tag.css"
],
"scopes": [
"https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/static-element/scopes/"
]
}
</script>
<style type="text/css">
@import '../resources/wbn/static-element/resources/style-imported-from-tag.css';
@import '../resources/wbn/static-element/scopes/style-imported-from-tag.css';
</style>
<link href="../resources/wbn/static-element/resources/style.css" rel=stylesheet>
<link href="../resources/wbn/static-element/scopes/style.css" rel=stylesheet>
<script src="../resources/wbn/static-element/resources/script.js"></script>
<script src="../resources/wbn/static-element/scopes/script.js"></script>
<script src="../resources/wbn/static-element/out-of-scope/script.js"></script>
<script>
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<script src="resources/static-element-with-test.js"></script>
</body>

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<title>Subframe loading from Web Bundles</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'script';
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<body>
<script src="resources/subframe-from-web-bundle-test.js"></script>
</body>

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<title>Subresource loading with script type="webbundle"</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<script>
window.TEST_WEB_BUNDLE_ELEMENT_TYPE = 'script';
setup(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
});
</script>
<body>
<script type="webbundle">
{
"source": "../resources/wbn/subresource.wbn",
"resources": [
"https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/root.js",
"https://{{domains[]}}:{{ports[https][0]}}/web-bundle/resources/wbn/submodule.js"
]
}
</script>
<script src="resources/subresource-load-test.sub.js"></script>
</body>

View file

@ -0,0 +1,16 @@
<DOCTYPE html>
<html>
<title>HTMLScriptElement.supports webbundle</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
test(() => {
assert_true(HTMLScriptElement.supports('webbundle'));
}, 'HTMLScriptElement.supports returns true for \'webbundle\'');
test(() => {
assert_false(HTMLScriptElement.supports(' webbundle'));
assert_false(HTMLScriptElement.supports('webbundle '));
assert_false(HTMLScriptElement.supports('WEBBUNDLE'));
}, 'HTMLScriptElement.supports returns false for unsupported types');
</script>

View file

@ -1,120 +0,0 @@
<!DOCTYPE html>
<title>Subframe loading from Web Bundles</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
const frame_url = 'urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae';
promise_test(async (t) => {
const iframe = await createLinkAndIframe(t);
// The urn:uuid URL iframe is cross-origin. So accessing
// iframe.contentWindow.location should throws a SecurityError.
assert_throws_dom(
"SecurityError",
() => { iframe.contentWindow.location.href; });
}, 'The urn:uuid URL iframe must be cross-origin.');
urn_uuid_iframe_test(
'location.href',
frame_url,
'location.href in urn uuid iframe.');
urn_uuid_iframe_test(
'(' + (() => {
try {
let result = window.localStorage;
return 'no error';
} catch (e) {
return e.name;
}
}).toString() + ')()',
'SecurityError',
'Accesing window.localStorage should throw a SecurityError.');
urn_uuid_iframe_test(
'(' + (() => {
try {
let result = window.sessionStorage;
return 'no error';
} catch (e) {
return e.name;
}
}).toString() + ')()',
'SecurityError',
'Accesing window.sessionStorage should throw a SecurityError.');
urn_uuid_iframe_test(
'(' + (() => {
try {
let result = document.cookie;
return 'no error';
} catch (e) {
return e.name;
}
}).toString() + ')()',
'SecurityError',
'Accesing document.cookie should throw a SecurityError.');
urn_uuid_iframe_test(
'(' + (() => {
try {
let request = window.indexedDB.open("db");
return 'no error';
} catch (e) {
return e.name;
}
}).toString() + ')()',
'SecurityError',
'Opening an indexedDB should throw a SecurityError.');
urn_uuid_iframe_test(
'window.caches === undefined',
true,
'window.caches should be undefined.');
function urn_uuid_iframe_test(code, expected, name) {
promise_test(async (t) => {
const iframe = await createLinkAndIframe(t);
assert_equals(await evalInIframe(iframe, code), expected);
}, name);
}
async function createLinkAndIframe(t) {
const link = document.createElement('link');
link.rel = 'webbundle';
link.href = '../resources/wbn/urn-uuid.wbn';
link.resources = frame_url;
document.body.appendChild(link);
const iframe = document.createElement('iframe');
t.add_cleanup(() => {
document.body.removeChild(link);
document.body.removeChild(iframe);
});
iframe.src = frame_url;
const load_promise = new Promise((resolve) => {
iframe.addEventListener('load', resolve);
});
document.body.appendChild(iframe);
await load_promise;
return iframe;
}
async function evalInIframe(iframe, code) {
const message_promise = new Promise((resolve) => {
const listener = (e) => {
window.removeEventListener('message', listener);
resolve(e.data);
}
window.addEventListener('message', listener);
});
iframe.contentWindow.postMessage(code,'*');
return message_promise;
}
</script>
</body>

View file

@ -1,21 +0,0 @@
<!DOCTYPE html>
<title>Accept: request header in webbundle requests</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<script>
promise_test(async () => {
const link = document.createElement("link");
link.rel = "webbundle";
link.href = "../resources/check-accept-header-and-return-bundle.py";
await addElementAndWaitForLoad(link);
link.remove();
}, '"Accept:" header in a request for a bundle should contain application/webbundle MIME type');
</script>
</body>

View file

@ -1,251 +0,0 @@
<!DOCTYPE html>
<title>Subresource loading with link rel="webbundle"</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<link id="link-web-bundle" rel="webbundle" href="../resources/wbn/subresource.wbn" resources="https://web-platform.test:8444/web-bundle/resources/wbn/root.js
https://web-platform.test:8444/web-bundle/resources/wbn/submodule.js" />
<script>
promise_test(async () => {
const module = await import('https://web-platform.test:8444/web-bundle/resources/wbn/root.js');
assert_equals(module.result, 'OK');
}, "Subresource loading with WebBundle");
promise_test(async () => {
const response = await fetch('https://web-platform.test:8444/web-bundle/resources/wbn/root.js');
const text = await response.text();
assert_equals(text, "export * from './submodule.js';\n");
}, "Subresource loading with WebBundle (Fetch API)");
promise_test(t => {
const url =
'/common/redirect.py?location=https://web-platform.test:8444/web-bundle/resources/wbn/root.js';
return promise_rejects_js(t, TypeError, import(url));
}, "Subresource loading with WebBundle shouldn't affect redirect");
promise_test(async () => {
const link = document.createElement("link");
link.rel = "webbundle";
link.href = "../resources/wbn/dynamic1.wbn";
link.resources.add('https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/resource1.js',
'https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/resource2.js',
'https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/resource4.js');
document.body.appendChild(link);
const module = await import('https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/resource1.js');
assert_equals(module.result, 'resource1 from dynamic1.wbn');
link.href = "../resources/wbn/dynamic2.wbn";
const module2 = await import('https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/resource2.js');
assert_equals(module2.result, 'resource2 from dynamic2.wbn');
// A resource not specified in the resources attribute, but in the bundle.
const module3 = await import('https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/resource3.js');
assert_equals(module3.result, 'resource3 from network');
document.body.removeChild(link);
const module4 = await import('https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/resource4.js');
assert_equals(module4.result, 'resource4 from network');
// Module scripts are stored to the Document's module map once loaded.
// So import()ing the same module script will reuse the previously loaded
// script.
const module_second = await import('https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/resource1.js');
assert_equals(module_second.result, 'resource1 from dynamic1.wbn');
}, 'Dynamically adding / updating / removing "<link rel=webbundle>"');
promise_test(async () => {
const classic_script_url = 'https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/classic_script.js';
const link = document.createElement("link");
link.rel = "webbundle";
link.href = "../resources/wbn/dynamic1.wbn";
link.resources.add(classic_script_url);
document.body.appendChild(link);
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic1.wbn');
link.href = "../resources/wbn/dynamic2.wbn";
// Loading the classic script should not reuse the previously loaded
// script. So in this case, the script must be loaded from dynamic2.wbn.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic2.wbn');
document.body.removeChild(link);
// And in this case, the script must be loaded from network.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from network');
}, 'Dynamically loading classic script from web bundle with link.resources');
promise_test(async (t) => {
// To avoid caching mechanism, this test is using fetch() API with
// { cache: 'no-store' } to load the resource.
const classic_script_url = 'https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/classic_script.js';
assert_equals(
await (await fetch(classic_script_url)).text(),
'window.report_result(\'classic script from network\');\n');
const link1 = document.createElement("link");
link1.rel = "webbundle";
link1.href = "../resources/wbn/dynamic1.wbn";
link1.resources.add(classic_script_url);
document.body.appendChild(link1);
t.add_cleanup(() => {
if (link1.parentElement)
link1.parentElement.removeChild(link1);
});
assert_equals(
await (await fetch(classic_script_url, { cache: 'no-store' })).text(),
'window.report_result(\'classic script from dynamic1.wbn\');\n');
const link2 = document.createElement("link");
link2.rel = "webbundle";
link2.href = "../resources/wbn/dynamic2.wbn";
link2.resources.add(classic_script_url);
document.body.appendChild(link2);
t.add_cleanup(() => {
if (link2.parentElement)
link2.parentElement.removeChild(link2);
});
assert_equals(
await (await fetch(classic_script_url, { cache: 'no-store' })).text(),
'window.report_result(\'classic script from dynamic2.wbn\');\n');
document.body.removeChild(link2);
assert_equals(
await (await fetch(classic_script_url, { cache: 'no-store' })).text(),
'window.report_result(\'classic script from dynamic1.wbn\');\n');
document.body.removeChild(link1);
assert_equals(
await (await fetch(classic_script_url, { cache: 'no-store' })).text(),
'window.report_result(\'classic script from network\');\n');
}, 'Multiple web bundle links. The last added link must be refered.');
promise_test(async () => {
const classic_script_url = 'https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/classic_script.js';
const scope = 'https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/';
const link = document.createElement("link");
link.rel = "webbundle";
link.href = "../resources/wbn/dynamic1.wbn";
link.scopes.add(scope);
document.body.appendChild(link);
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic1.wbn');
link.href = "../resources/wbn/dynamic2.wbn";
// Loading the classic script should not reuse the previously loaded
// script. So in this case, the script must be loaded from dynamic2.wbn.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic2.wbn');
// Changes the scope not to hit the classic_script.js.
link.scopes = scope + 'dummy';
// And in this case, the script must be loaded from network.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from network');
// Adds the scope to hit the classic_script.js.
link.scopes.add(scope + 'classic_');
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from dynamic2.wbn');
document.body.removeChild(link);
// And in this case, the script must be loaded from network.
assert_equals(
await loadScriptAndWaitReport(classic_script_url),
'classic script from network');
}, 'Dynamically loading classic script from web bundle with link.scopes');
promise_test(() => {
return addLinkAndWaitForLoad("../resources/wbn/dynamic1.wbn?test-event");
}, '<link rel="webbundle"> fires a load event on load success');
promise_test((t) => {
return addLinkAndWaitForError("../resources/wbn/nonexistent.wbn");
}, '<link rel="webbundle"> fires an error event on load failure');
promise_test(async () => {
const link = document.createElement('link');
link.rel = 'webbundle';
link.href = '../resources/wbn/dynamic1-crossorigin.wbn';
link.resources = 'https://www1.web-platform.test:8444/web-bundle/resources/wbn/dynamic/resource1.js';
document.body.appendChild(link);
const module = await import(link.resources);
assert_equals(module.result, 'resource1 from network');
}, 'Subresource URL must be same-origin with bundle URL');
promise_test(async () => {
const url = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const link = document.createElement('link');
link.rel = 'webbundle';
link.href = '../resources/wbn/urn-uuid.wbn';
link.resources = url;
document.body.appendChild(link);
assert_equals(await loadScriptAndWaitReport(url), 'OK');
document.body.removeChild(link);
}, 'Subresource loading with urn:uuid: URL with link.resources');
promise_test(async () => {
const url = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const link = document.createElement('link');
link.rel = 'webbundle';
link.href = '../resources/wbn/urn-uuid.wbn';
link.scopes = 'urn:uuid:';
document.body.appendChild(link);
assert_equals(await loadScriptAndWaitReport(url), 'OK');
document.body.removeChild(link);
}, 'Subresource loading with urn:uuid: URL with link.scopes');
promise_test(async () => {
const wbn_url = 'https://web-platform.test:8444/web-bundle/resources/wbn/subresource.wbn?test-resources-update';
const resource_url = 'https://web-platform.test:8444/web-bundle/resources/wbn/submodule.js';
const link = await addLinkAndWaitForLoad(wbn_url);
link.resources.add(resource_url);
const resp = await fetch(resource_url, { cache: 'no-store' });
assert_true(resp.ok);
assert_equals(performance.getEntriesByName(wbn_url).length, 1);
}, 'Updating resource= attribute should not reload the bundle');
function addLinkAndWaitForLoad(url) {
return new Promise((resolve, reject) => {
const link = document.createElement("link");
link.rel = "webbundle";
link.href = url;
link.onload = () => resolve(link);
link.onerror = reject;
document.body.appendChild(link);
});
}
function addLinkAndWaitForError(url) {
return new Promise((resolve, reject) => {
const link = document.createElement("link");
link.rel = "webbundle";
link.href = url;
link.onload = reject;
link.onerror = () => resolve(link);
document.body.appendChild(link);
});
}
async function loadScriptAndWaitReport(script_url) {
const result_promise = new Promise((resolve) => {
// This function will be called from script.js
window.report_result = resolve;
});
const script = document.createElement('script');
script.src = script_url;
document.body.appendChild(script);
return result_promise;
}
</script>
</body>

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<title>On-going subresource loading should fail immediately when a link element is removed</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
promise_test(async () => {
const link = document.createElement("link");
link.rel = "webbundle";
link.href = "/xhr/resources/delay.py?ms=100000";
link.resources.add("https://web-platform.test:8444/xhr/resources/dummy");
document.body.appendChild(link);
const waitUntilFail = new Promise((resolve) => {
fetch("https://web-platform.test:8444/xhr/resources/dummy").then(() => {},
resolve);
});
document.body.removeChild(link);
await waitUntilFail;
}, "On-going subresource loading should fail immediately when a link element is removed.");
</script>
</body>

View file

@ -1,41 +0,0 @@
<!DOCTYPE html>
<title>A nested bundle is not supported</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<link rel="webbundle" href="https://web-platform.test:8444/web-bundle/resources/wbn/nested-main.wbn"
resources="https://web-platform.test:8444/web-bundle/resources/wbn/nested-sub.wbn" />
<script>
promise_test(async () => {
const response = await fetch(
"https://web-platform.test:8444/web-bundle/resources/wbn/nested-sub.wbn"
);
assert_true(response.ok);
}, "A nested bundle can be fetched");
promise_test(async () => {
await addLinkAndWaitForError(
"https://web-platform.test:8444/web-bundle/resources/wbn/nested-sub.wbn",
"https://web-platform.test:8444/web-bundle/resources/wbn/root.js"
);
const response = await fetch(
"https://web-platform.test:8444/web-bundle/resources/wbn/root.js"
);
assert_false(response.ok);
}, "Subresources in a nested bundle should not be loaded");
function addLinkAndWaitForError(url, resources) {
return new Promise((resolve, reject) => {
const link = document.createElement("link");
link.rel = "webbundle";
link.href = url;
link.resources = resources;
link.onload = reject;
link.onerror = () => resolve();
document.body.appendChild(link);
});
}
</script>
</body>

View file

@ -1,31 +0,0 @@
<!DOCTYPE html>
<title>Web Bundle fetching failed due to a network error</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<!--
This test uses a non-existing WebBundle from a non-existent host, which makes
Web Bundle fetching fail due to a network error. The intent of is to chech if
failing to fetch a WebBundle also makes subresource fetch requests fail.
-->
<script>
promise_test(async () => {
const prefix =
"https://{{hosts[][nonexistent]}}/";
const resources = [
prefix + "resource.js",
];
const link = await addLinkAndWaitForError(
prefix + "non-existing.wbn",
resources,
undefined
);
// Can not fetch a subresource because Web Bundle fetch failed.
await fetchAndWaitForReject(prefix + "resource.js");
}, "Subresource fetch requests for non-existing Web Bundle should fail.");
</script>
</body>

View file

@ -1,45 +0,0 @@
<!DOCTYPE html>
<title>Path restriction on subresource loading with WebBundles</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<link
rel="webbundle"
href="../resources/wbn/path-restriction.wbn"
resources="https://web-platform.test:8444/web-bundle/resources/wbn/resource.js
https://web-platform.test:8444/web-bundle/resources/wbn/sub/resource.js
https://web-platform.test:8444/web-bundle/resources/wbn-resource.js
https://web-platform.test:8444/web-bundle/resources/wbn1/resource.js
https://web-platform.test:8444/web-bundle/resources/other/resource.js
https://web-platform.test:8444/web-bundle/resources/resource.js"
/>
<script>
promise_test(async () => {
const resources = [
"https://web-platform.test:8444/web-bundle/resources/wbn/resource.js",
"https://web-platform.test:8444/web-bundle/resources/wbn/sub/resource.js",
];
for (const resource of resources) {
const response = await fetch(resource);
assert_true(response.ok, resource + " should be loaded");
}
}, "Subresources should be loaded.");
promise_test(async () => {
const resources = [
"https://web-platform.test:8444/web-bundle/resources/wbn-resource.js",
"https://web-platform.test:8444/web-bundle/resources/wbn1/resource.js",
"https://web-platform.test:8444/web-bundle/resources/other/resource.js",
"https://web-platform.test:8444/web-bundle/resources/resource.js",
];
for (const resource of resources) {
const response = await fetch(resource);
assert_false(response.ok, resource + " should not be loaded");
}
}, "Subresources should not be loaded due to path restriction.");
</script>
</body>

View file

@ -1,27 +0,0 @@
<!DOCTYPE html>
<title>Subresource loading using relative URLs in the 'resources' attribute with a base element</title>
<base href="../resources/wbn/static-element/">
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<link
rel="webbundle"
href="../static-element.wbn"
resources="resources/script.js"/>
<script id="script" src="resources/script.js"></script>
<script>
const onLoadPromise = new Promise((resolve) => {
window.addEventListener('load', resolve, false);
});
promise_test(async () => {
await onLoadPromise;
assert_equals(resources_script_result, 'loaded from webbundle');
}, "A subresource script.js should be loaded from WebBundle using the relative URL and a base element.");
</script>
</body>

View file

@ -1,60 +0,0 @@
<!DOCTYPE html>
<title>Subresource loading using relative URLs in the 'resources' attribute</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<link
rel="webbundle"
href="../resources/wbn/static-element.wbn"
resources="/web-bundle/resources/wbn/static-element/resources/script.js"/>
<script id="script" src="/web-bundle/resources/wbn/static-element/resources/script.js"></script>
<script>
const onLoadPromise = new Promise((resolve) => {
window.addEventListener('load', resolve, false);
});
/*
This test tries to load 'script.js' subresource from a static-element.wbn, using
a relative URL instead of an absolute one with a <link> and <script> elements
directly in the document (they are used only for this test).
*/
promise_test(async () => {
await onLoadPromise;
assert_equals(resources_script_result, 'loaded from webbundle');
}, "A subresource script.js should be loaded from WebBundle using the relative URL.");
// Simple load of a root.js subresource from subresource.wbn using a relative URL.
promise_test(async () => {
const link = document.createElement("link");
const resource_url = '/web-bundle/resources/wbn/root.js';
link.rel = "webbundle";
link.href = "../resources/wbn/subresource.wbn";
link.resources.add(resource_url);
document.body.appendChild(link);
const response = await fetch(resource_url);
assert_true(response.ok);
const root = await response.text();
assert_equals(root, "export * from './submodule.js';\n");
}, "Subresources with relative URLs should be loaded from the WebBundle.");
// Simple load of a root.js subresource from subresource.wbn using an
// incorrect relative URL leading to a failed fetch.
promise_test(async () => {
const link = document.createElement("link");
const resource_url = 'web-bundle/resources/wbn/root.js';
link.rel = "webbundle";
link.href = "../resources/wbn/subresource.wbn";
link.resources.add(resource_url);
document.body.appendChild(link);
const response = await fetch(resource_url);
assert_false(response.ok);
}, "Wrong relative URL should result in a failed fetch.");
</script>
</body>

View file

@ -1,44 +0,0 @@
<!DOCTYPE html>
<title>Request's destination must be "webbundle" with the link-based API</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<script>
// check-sec-fetch-dest-header-and-return-bundle.py returns a valid format
// bundle only if a "Sec-Fetch-Dest: webbundle" header is present in a request.
// Otherwise, returns an empty body with 400 status code.
//
// In this wpt, we assume that a <link> element fires a load event correctly if
// a valid format webbundle is returned.
const same_origin_bundle =
"../resources/check-sec-fetch-dest-header-and-return-bundle.py";
const cross_origin_bundle =
"https://{{domains[www1]}}:{{ports[https][0]}}/web-bundle/resources/check-sec-fetch-dest-header-and-return-bundle.py";
promise_test(async () => {
for (const bundle of [same_origin_bundle, cross_origin_bundle]) {
const link = document.createElement("link");
link.rel = "webbundle";
link.href = bundle;
await addElementAndWaitForLoad(link);
link.remove();
}
}, '"Sec-Fetch-Dest: webbundle" header must be present in a request for a bundle with the <link>-based API.');
promise_test(async () => {
const res = await fetch(same_origin_bundle);
assert_false(res.ok);
}, '"Sec-Fetch-Dest: webbundle" header must not be present in a fetch request for a same-origin resource.');
promise_test(async () => {
const res = await fetch(cross_origin_bundle);
assert_false(res.ok);
}, '"Sec-Fetch-Dest: webbundle" header must not be present in a fetch request for a cross-origin resource.');
</script>
</body>

View file

@ -1,62 +0,0 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Resource timing attributes are consistent for the same-origin subresources.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
promise_test(async t => {
const link = document.createElement("link");
link.rel = "webbundle";
link.href = "../resources/wbn/dynamic1.wbn?pipe=trickle(d0.5)";
link.resources.add('https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/resource1.js');
const script_id = 'https://web-platform.test:8444/web-bundle/resources/wbn/dynamic/resource1.js';
document.body.appendChild(link);
var script_entries = 0;
var web_bundle_entries = 0;
var web_bundle_entry, script_entry;
const promise = new Promise(resolve => {
new PerformanceObserver(t.step_func(entryList => {
var entries = entryList.getEntriesByType("resource");
for (var i = 0; i < entries.length; ++i) {
if (entries[i].name === script_id) {
script_entry = entries[i];
script_entries++;
}
if (entries[i].name === 'https://web-platform.test:8444/web-bundle/resources/wbn/dynamic1.wbn?pipe=trickle(d0.5)') {
web_bundle_entry = entries[i];
web_bundle_entries++;
}
}
if (web_bundle_entries > 0 && script_entries > 0) {
// Check timestamps.
assert_greater_than_equal(script_entry.responseStart, script_entry.requestStart + 500);
assert_greater_than_equal(script_entry.responseStart, web_bundle_entry.responseStart);
assert_greater_than_equal(script_entry.responseEnd, script_entry.responseStart);
assert_greater_than_equal(script_entry.requestStart, script_entry.connectEnd);
assert_greater_than_equal(script_entry.responseEnd, script_entry.responseStart);
// Check sizes.
assert_greater_than(script_entry.encodedBodySize, 0);
assert_equals(script_entry.transferSize, script_entry.encodedBodySize + 300);
assert_equals(script_entry.encodedBodySize, script_entry.decodedBodySize);
resolve();
}
})).observe({entryTypes: ["resource"]});
});
const script = document.createElement("script");
script.type = "module";
script.src = script_id;
document.body.appendChild(script);
return promise;
}, '"Timestamp attributes filled in resource timing entries should be consistent."');
</script>
<h1>Resource timing attributes are consistent</h1>
<p>
This test verifies that attributes filled in the PerformanceResourceTiming entries for subresources
loaded from the WebBundle are consistent.
</p>
<div id="log"></div>
</body>

View file

@ -1,56 +0,0 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Resource timing entries present for urn:uuid resources</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
promise_test(async t => {
const frame_id = 'urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae';
const script_id = 'urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720';
const link = document.createElement("link");
link.rel = "webbundle";
link.href = "../resources/wbn/urn-uuid.wbn";
link.resources.add(frame_id, script_id);
document.body.appendChild(link);
var iframe_entries = 0;
var script_entries = 0;
// Declare the report_result function as outputting into stderr
// because it is used in the WebBundle script to report the script load.
window.report_result = console.error;
const promise = new Promise(resolve => {
new PerformanceObserver(t.step_func(entryList => {
var entries = entryList.getEntriesByType("resource");
for (var i = 0; i < entries.length; ++i) {
// Ignore any entries for the test harness files if present.
if (/testharness(report)?\.js/.test(entries[i].name)) {
continue;
}
if (entries[i].name === frame_id)
++iframe_entries;
if (entries[i].name === script_id)
++script_entries;
}
if (iframe_entries == 1 && script_entries == 1) {
resolve();
}
})).observe({entryTypes: ["resource"]});
});
// Add iframe and the script so we get the ResourceTiming
const iframe = document.createElement("iframe");
iframe.src = frame_id;
document.body.appendChild(iframe);
const script = document.createElement("script");
script.src = script_id;
document.body.appendChild(script);
return promise;
}, '"Each urn:uuid resource should have exactly 1 ResourceTiming entry."');
</script>
<h1>Resource timing entries present for urn:uuid resources</h1>
<p>
This test makes sure that ResourceTiming entries (exactly 1 per resource) are created for urn:uuid resources served from a webbundle.
</p>
<div id="log"></div>
</body>

View file

@ -1,56 +0,0 @@
<!DOCTYPE html>
<title>WebBundle subresource loading for static elements with a base element</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md"
/>
<base href="../resources/wbn/static-element/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<link
rel="webbundle"
href="../static-element.wbn"
resources="
https://web-platform.test:8444/web-bundle/resources/wbn/static-element/resources/script.js
https://web-platform.test:8444/web-bundle/resources/wbn/static-element/resources/style.css
https://web-platform.test:8444/web-bundle/resources/wbn/static-element/resources/style-imported-from-file.css
https://web-platform.test:8444/web-bundle/resources/wbn/static-element/resources/style-imported-from-tag.css"
scopes="https://web-platform.test:8444/web-bundle/resources/wbn/static-element/scopes/"
/>
<style type="text/css">
@import 'resources/style-imported-from-tag.css';
@import 'scopes/style-imported-from-tag.css';
</style>
<link href="resources/style.css" rel=stylesheet>
<link href="scopes/style.css" rel=stylesheet>
<script src="resources/script.js"></script>
<script src="scopes/script.js"></script>
<script src="out-of-scope/script.js"></script>
<script>
const onLoadPromise = new Promise((resolve) => {
window.addEventListener('load', resolve, false);
});
promise_test(async () => {
await onLoadPromise;
assert_equals(resources_script_result, 'loaded from webbundle');
assert_equals(scopes_script_result, 'loaded from webbundle');
assert_equals(out_of_scope_script_result, 'loaded from network');
['resources_', 'scopes_'].forEach((type) => {
['style_target',
'style_imported_from_file_target',
'style_imported_from_tag_target'].forEach((target) => {
const element = document.createElement('div');
element.id = type + target;
document.body.appendChild(element);
assert_equals(window.getComputedStyle(element).color,
'rgb(0, 0, 255)',
element.id + ' color must be blue');
});
});
}, "Subresources from static elements should be loaded from web bundle.");
</script>
</body>

View file

@ -1,55 +0,0 @@
<!DOCTYPE html>
<title>WebBundle subresource loading for static elements</title>
<link
rel="help"
href="https://github.com/WICG/webpackage/blob/master/explainers/subresource-loading.md"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<link
rel="webbundle"
href="../resources/wbn/static-element.wbn"
resources="
https://web-platform.test:8444/web-bundle/resources/wbn/static-element/resources/script.js
https://web-platform.test:8444/web-bundle/resources/wbn/static-element/resources/style.css
https://web-platform.test:8444/web-bundle/resources/wbn/static-element/resources/style-imported-from-file.css
https://web-platform.test:8444/web-bundle/resources/wbn/static-element/resources/style-imported-from-tag.css"
scopes="https://web-platform.test:8444/web-bundle/resources/wbn/static-element/scopes/"
/>
<style type="text/css">
@import '../resources/wbn/static-element/resources/style-imported-from-tag.css';
@import '../resources/wbn/static-element/scopes/style-imported-from-tag.css';
</style>
<link href="../resources/wbn/static-element/resources/style.css" rel=stylesheet>
<link href="../resources/wbn/static-element/scopes/style.css" rel=stylesheet>
<script src="../resources/wbn/static-element/resources/script.js"></script>
<script src="../resources/wbn/static-element/scopes/script.js"></script>
<script src="../resources/wbn/static-element/out-of-scope/script.js"></script>
<script>
const onLoadPromise = new Promise((resolve) => {
window.addEventListener('load', resolve, false);
});
promise_test(async () => {
await onLoadPromise;
assert_equals(resources_script_result, 'loaded from webbundle');
assert_equals(scopes_script_result, 'loaded from webbundle');
assert_equals(out_of_scope_script_result, 'loaded from network');
['resources_', 'scopes_'].forEach((type) => {
['style_target',
'style_imported_from_file_target',
'style_imported_from_tag_target'].forEach((target) => {
const element = document.createElement('div');
element.id = type + target;
document.body.appendChild(element);
assert_equals(window.getComputedStyle(element).color,
'rgb(0, 0, 255)',
element.id + ' color must be blue');
});
});
}, "Subresources from static elements should be loaded from web bundle.");
</script>
</body>

View file

@ -1,33 +0,0 @@
<!DOCTYPE html>
<title>Web Bundle fetching failed due to not found error</title>
<link rel="help" href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/test-helpers.js"></script>
<body>
<!--
This test uses a non-existing WebBundle,
https://web-platform.test:8444/web-bundle/resources/wbn/cors/non-existing.wbn.
The intent of this test is to check if failing to fetch a WebBundle due to not
found error also makes subresource fetch requests fail.
-->
<script>
promise_test(async () => {
const prefix =
"https://web-platform.test:8444/web-bundle/resources/wbn/";
const resources = [
prefix + "resource.js",
];
const link = await addLinkAndWaitForError(
prefix + "non-existing.wbn",
resources,
undefined
);
// Can not fetch a subresource because Web Bundle fetch failed.
await fetchAndWaitForReject(prefix + "resource.js");
}, "Subresource fetch requests for non-existing Web Bundle should fail.");
</script>
</body>