diff --git a/html/browsers/browsing-the-web/remote-context-helper/resources/executor.sub.html b/html/browsers/browsing-the-web/remote-context-helper/resources/executor.sub.html
index 38f4429d91e4ee..95ecb349319fe9 100644
--- a/html/browsers/browsing-the-web/remote-context-helper/resources/executor.sub.html
+++ b/html/browsers/browsing-the-web/remote-context-helper/resources/executor.sub.html
@@ -9,6 +9,8 @@
'sec-fetch-mode': '{{header_or_default(sec-fetch-mode, absent)}}',
'sec-fetch-site': '{{header_or_default(sec-fetch-site, absent)}}',
'sec-fetch-dest': '{{header_or_default(sec-fetch-dest, absent)}}',
+ 'purpose': "{{header_or_default(Purpose, absent)}}",
+ 'sec-purpose': "{{header_or_default(Sec-Purpose, absent)}}",
'referer': '{{header_or_default(referer, absent)}}',
};
requestExecutor();
diff --git a/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js b/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
index 6978cef83211e5..7de980f11f8df4 100644
--- a/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
+++ b/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
@@ -161,95 +161,6 @@
*/
const DEFAULT_CONTEXT_CONFIG = new RemoteContextConfig();
- /**
- * This class represents a configuration for creating remote contexts. This is
- * the entry-point
- * for creating remote contexts, providing @see addWindow .
- */
- class RemoteContextHelper {
- /**
- * @param {RemoteContextConfig|object} config The configuration
- * for this remote context.
- */
- constructor(config) {
- this.config = RemoteContextConfig.ensure(config);
- }
-
- /**
- * Creates a new remote context and returns a `RemoteContextWrapper` giving
- * access to it.
- * @private
- * @param {Object} options
- * @param {(url: string) => Promise} options.executorCreator A
- * function that takes a URL and causes the browser to navigate some
- * window to that URL, e.g. via an iframe or a new window.
- * @param {RemoteContextConfig|object} [options.extraConfig] If supplied,
- * extra configuration for this remote context to be merged with
- * `this`'s existing config. If it's not a `RemoteContextConfig`, it
- * will be used to construct a new one.
- * @returns {Promise}
- */
- async createContext({
- executorCreator,
- extraConfig,
- isWorker = false,
- }) {
- const config =
- this.config.merged(RemoteContextConfig.ensure(extraConfig));
-
- const origin = finalizeOrigin(config.origin);
- const url = new URL(
- isWorker ? WORKER_EXECUTOR_PATH : WINDOW_EXECUTOR_PATH, origin);
-
- // UUID is needed for executor.
- const uuid = token();
- url.searchParams.append('uuid', uuid);
-
- if (config.headers) {
- addHeaders(url, config.headers);
- }
- for (const script of config.scripts) {
- url.searchParams.append('script', makeAbsolute(script));
- }
-
- if (config.startOn) {
- url.searchParams.append('startOn', config.startOn);
- }
-
- await executorCreator(url.href);
- return new RemoteContextWrapper(new RemoteContext(uuid), this, url.href);
- }
-
- /**
- * Creates a window with a remote context. @see createContext for
- * @param {RemoteContextConfig|object} [extraConfig] Will be
- * merged with `this`'s config.
- * @param {Object} [options]
- * @param {string} [options.target] Passed to `window.open` as the
- * 2nd argument
- * @param {string} [options.features] Passed to `window.open` as the
- * 3rd argument
- * @returns {Promise}
- */
- addWindow(extraConfig, options) {
- return this.createContext({
- executorCreator: windowExecutorCreator(options),
- extraConfig,
- });
- }
-
- async createContextWithUrl(extraConfig) {
- let saveUrl;
- let wrapper = await this.createContext({
- executorCreator: (url) => {saveUrl = url},
- extraConfig,
- });
- return [wrapper, saveUrl];
- }
- }
- // Export this class.
- self.RemoteContextHelper = RemoteContextHelper;
-
/**
* Attaches header to the URL. See
* https://web-platform-tests.org/writing-tests/server-pipes.html#headers
@@ -330,6 +241,15 @@
return this.context.execute_script(fn, args);
}
+ /**
+ * Returns a JavaScript object containing a subset of the request headers.
+ * The specific headers that are recorded are in ./executor.sub.html.
+ * @returns {Object}
+ */
+ async getRequestHeaders() {
+ return this.executeScript(() => window.requestHeaders);
+ }
+
/**
* Adds a string of HTML to the executor's document.
* @param {string} html
@@ -530,4 +450,103 @@
}
}
}
+
+
+ /**
+ * This class represents a configuration for creating remote contexts. This is
+ * the entry-point
+ * for creating remote contexts, providing @see addWindow .
+ */
+ class RemoteContextHelper {
+ /**
+ * The constructor to use when creating new remote context wrappers.
+ * Can be overridden by subclasses.
+ */
+ static RemoteContextWrapper = RemoteContextWrapper;
+
+ /**
+ * @param {RemoteContextConfig|object} config The configuration
+ * for this remote context.
+ */
+ constructor(config) {
+ this.config = RemoteContextConfig.ensure(config);
+ }
+
+ /**
+ * Creates a new remote context and returns a `RemoteContextWrapper` giving
+ * access to it.
+ * @private
+ * @param {Object} options
+ * @param {(url: string) => Promise} options.executorCreator A
+ * function that takes a URL and causes the browser to navigate some
+ * window to that URL, e.g. via an iframe or a new window.
+ * @param {RemoteContextConfig|object} [options.extraConfig] If supplied,
+ * extra configuration for this remote context to be merged with
+ * `this`'s existing config. If it's not a `RemoteContextConfig`, it
+ * will be used to construct a new one.
+ * @param {Function} [options.remoteContextWrapperConstructor] If supplied,
+ * the constructor to use when creating the returned
+ * `RemoteContextWrapper`. (Useful for subclassing.)
+ * @returns {Promise}
+ */
+ async createContext({
+ executorCreator,
+ extraConfig,
+ isWorker = false
+ }) {
+ const config =
+ this.config.merged(RemoteContextConfig.ensure(extraConfig));
+
+ const origin = finalizeOrigin(config.origin);
+ const url = new URL(
+ isWorker ? WORKER_EXECUTOR_PATH : WINDOW_EXECUTOR_PATH, origin);
+
+ // UUID is needed for executor.
+ const uuid = token();
+ url.searchParams.append('uuid', uuid);
+
+ if (config.headers) {
+ addHeaders(url, config.headers);
+ }
+ for (const script of config.scripts) {
+ url.searchParams.append('script', makeAbsolute(script));
+ }
+
+ if (config.startOn) {
+ url.searchParams.append('startOn', config.startOn);
+ }
+
+ await executorCreator(url.href);
+ return new this.constructor.RemoteContextWrapper(new RemoteContext(uuid), this, url.href);
+ }
+
+ /**
+ * Creates a window with a remote context. @see createContext for
+ * @param {RemoteContextConfig|object} [extraConfig] Will be
+ * merged with `this`'s config.
+ * @param {Object} [options]
+ * @param {string} [options.target] Passed to `window.open` as the
+ * 2nd argument
+ * @param {string} [options.features] Passed to `window.open` as the
+ * 3rd argument
+ * @returns {Promise}
+ */
+ addWindow(extraConfig, options) {
+ return this.createContext({
+ executorCreator: windowExecutorCreator(options),
+ extraConfig,
+ });
+ }
+
+ async createContextWithUrl(extraConfig) {
+ let saveUrl;
+ let wrapper = await this.createContext({
+ executorCreator: (url) => {saveUrl = url},
+ extraConfig,
+ });
+ return [wrapper, saveUrl];
+ }
+ }
+ // Export this class.
+ self.RemoteContextHelper = RemoteContextHelper;
}
diff --git a/speculation-rules/common/invalid-rules.https.html b/speculation-rules/common/invalid-rules.https.html
new file mode 100644
index 00000000000000..0c3d042574fb64
--- /dev/null
+++ b/speculation-rules/common/invalid-rules.https.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/speculation-rules/prerender/script-supports-speculationrules.html b/speculation-rules/common/script-supports-speculationrules.html
similarity index 90%
rename from speculation-rules/prerender/script-supports-speculationrules.html
rename to speculation-rules/common/script-supports-speculationrules.html
index 2dc856fce5da7c..7446f2b6b5f2f8 100644
--- a/speculation-rules/prerender/script-supports-speculationrules.html
+++ b/speculation-rules/common/script-supports-speculationrules.html
@@ -1,15 +1,14 @@
-
HTMLScriptElement.supports speculationrules
-
+
diff --git a/speculation-rules/prefetch/invalid-rules.https.html b/speculation-rules/prefetch/invalid-rules.https.html
deleted file mode 100644
index 0fdfacde643958..00000000000000
--- a/speculation-rules/prefetch/invalid-rules.https.html
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/speculation-rules/prerender/activation-start.html b/speculation-rules/prerender/activation-start.html
index 7aee20c3465dcf..421d5694bb88f6 100644
--- a/speculation-rules/prerender/activation-start.html
+++ b/speculation-rules/prerender/activation-start.html
@@ -16,9 +16,9 @@
promise_test(async t => {
const ACTIVATION_DELAY = 10;
- const rcHelper = new RemoteContextHelper();
+ const rcHelper = new PrerenderingRemoteContextHelper();
const referrerRC = await rcHelper.addWindow(undefined, { features: 'noopener' });
- const prerenderedRC = await addPrerenderRC(referrerRC);
+ const prerenderedRC = await referrerRC.createPrerenderedContext();
const iframeRC = await prerenderedRC.addIframe();
assert_equals(
@@ -36,7 +36,7 @@
// Wait ACTIVATION_DELAY ms before activation.
await new Promise(resolve => t.step_timeout(resolve, ACTIVATION_DELAY));
- await activatePrerenderRC(referrerRC, prerenderedRC);
+ await referrerRC.navigateExpectingPrerenderingActivation(prerenderedRC);
assert_greater_than_equal(
await getActivationStart(prerenderedRC),
diff --git a/speculation-rules/prerender/credentialed-prerender-not-opt-in.html b/speculation-rules/prerender/credentialed-prerender-not-opt-in.html
index 697382a6dc8569..fe3bae6fae4057 100644
--- a/speculation-rules/prerender/credentialed-prerender-not-opt-in.html
+++ b/speculation-rules/prerender/credentialed-prerender-not-opt-in.html
@@ -15,9 +15,9 @@
setup(() => assertSpeculationRulesIsSupported());
promise_test(async t => {
- const rcHelper = new RemoteContextHelper();
+ const rcHelper = new PrerenderingRemoteContextWrapper();
const referrerRC = await rcHelper.addWindow({origin: 'HTTPS_ORIGIN'}, { features: 'noopener' });
- const prerenderedRC = await addPrerenderRC(referrerRC, {origin: 'HTTPS_REMOTE_ORIGIN'});
+ const prerenderedRC = await referrerRC.createPrerenderedContext({origin: 'HTTPS_REMOTE_ORIGIN'});
// Because the prerender doesn't use opt-in header, it is expected to be canceled.
// And the navigation is expected to create another page instead of activation.
diff --git a/speculation-rules/prerender/credentialed-prerender-opt-in.html b/speculation-rules/prerender/credentialed-prerender-opt-in.html
index 91626bafce677b..21c88775f0081c 100644
--- a/speculation-rules/prerender/credentialed-prerender-opt-in.html
+++ b/speculation-rules/prerender/credentialed-prerender-opt-in.html
@@ -17,8 +17,11 @@
promise_test(async t => {
const rcHelper = new RemoteContextHelper();
const referrerRC = await rcHelper.addWindow({origin: 'HTTPS_ORIGIN'}, { features: 'noopener' });
- const prerenderedRC = await addPrerenderRC(referrerRC, {origin: 'HTTPS_REMOTE_ORIGIN', headers: [['Supports-Loading-Mode', 'credentialed-prerender']] });
+ const prerenderedRC = await referrerRC.createPrerenderedContext({
+ origin: 'HTTPS_REMOTE_ORIGIN',
+ headers: [['Supports-Loading-Mode', 'credentialed-prerender']]
+ });
- await activatePrerenderRC(referrerRC, prerenderedRC);
+ await referrerRC.navigateExpectingPrerenderingActivation(prerenderedRC);
});
diff --git a/speculation-rules/prerender/referrer-policy-mismatch.html b/speculation-rules/prerender/referrer-policy-mismatch.html
index fa2d424660a367..a5f08832056274 100644
--- a/speculation-rules/prerender/referrer-policy-mismatch.html
+++ b/speculation-rules/prerender/referrer-policy-mismatch.html
@@ -15,17 +15,17 @@
setup(() => assertSpeculationRulesIsSupported());
promise_test(async t => {
- const rcHelper = new RemoteContextHelper();
+ const rcHelper = new PrerenderingRemoteContextHelper();
const referrerRC = await rcHelper.addWindow(undefined, { features: "noopener" });
await setReferrerPolicy(referrerRC, "strict-origin-when-cross-origin");
- const prerenderedRC = await addPrerenderRC(referrerRC);
+ const prerenderedRC = await referrerRC.createPrerenderedContext();
const referrerURL = await referrerRC.executeScript(() => location.href);
assert_equals(await prerenderedRC.executeScript(() => document.prerendering), true);
assert_equals(await prerenderedRC.executeScript(() => document.referrer), referrerURL);
- await activatePrerenderRC(referrerRC, prerenderedRC, url => {
+ await referrerRC.navigateExpectingPrerenderingActivation(prerenderedRC, url => {
const a = document.createElement("a");
a.href = url;
a.referrerPolicy = "no-referrer";
@@ -37,17 +37,17 @@
}, 'prerendered with "strict-origin-when-cross-origin", activated with "no-referrer"');
promise_test(async t => {
- const rcHelper = new RemoteContextHelper();
+ const rcHelper = new PrerenderingRemoteContextHelper();
const referrerRC = await rcHelper.addWindow(undefined, { features: "noopener" });
await setReferrerPolicy(referrerRC, "strict-origin-when-cross-origin");
- const prerenderedRC = await addPrerenderRC(referrerRC);
+ const prerenderedRC = await referrerRC.createPrerenderedContext();
const referrerURL = await referrerRC.executeScript(() => location.href);
assert_equals(await prerenderedRC.executeScript(() => document.prerendering), true);
assert_equals(await prerenderedRC.executeScript(() => document.referrer), referrerURL);
- await activatePrerenderRC(referrerRC, prerenderedRC, url => {
+ await referrerRC.navigateExpectingPrerenderingActivation(prerenderedRC, url => {
const a = document.createElement("a");
a.href = url;
a.referrerPolicy = "strict-origin";
@@ -59,10 +59,10 @@
}, 'prerendered with "strict-origin-when-cross-origin", activated with "strict-origin"');
promise_test(async t => {
- const rcHelper = new RemoteContextHelper();
+ const rcHelper = new PrerenderingRemoteContextHelper();
const referrerRC = await rcHelper.addWindow(undefined, { features: "noopener" });
await setReferrerPolicy(referrerRC, "strict-origin");
- const prerenderedRC = await addPrerenderRC(referrerRC);
+ const prerenderedRC = await referrerRC.createPrerenderedContext();
const referrerURL = await referrerRC.executeScript(() => location.href);
const referrerOrigin = (new URL(referrerURL)).origin + "/";
@@ -70,7 +70,7 @@
assert_equals(await prerenderedRC.executeScript(() => document.prerendering), true);
assert_equals(await prerenderedRC.executeScript(() => document.referrer), referrerOrigin);
- await activatePrerenderRC(referrerRC, prerenderedRC, url => {
+ await referrerRC.navigateExpectingPrerenderingActivation(prerenderedRC, url => {
const a = document.createElement("a");
a.href = url;
a.referrerPolicy = "unsafe-url";
diff --git a/speculation-rules/prerender/resources/utils.js b/speculation-rules/prerender/resources/utils.js
index f012d2d0e41ef6..0387f6dfd9b1b9 100644
--- a/speculation-rules/prerender/resources/utils.js
+++ b/speculation-rules/prerender/resources/utils.js
@@ -322,99 +322,68 @@ function test_prerender_defer(fn, label) {
}, label);
}
-/**
- * Starts prerendering a page from the given referrer `RemoteContextWrapper`,
- * using `