[COEP] Write WPTs for COEP inheritance from `filesystem:` URLs.

Refactor the existing tests to make it easier to integrate the new
tests, and add tests checking for proper inheritance from the URL
creator for `blob:` URLs too.

Bug: chromium:1291230
Change-Id: I9890697e1ed3c76c8ef880ce6799c40fdc5805eb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3427642
Commit-Queue: Titouan Rigoudy <titouan@chromium.org>
Reviewed-by: Asami Doi <asamidoi@chromium.org>
Reviewed-by: Antonio Sartori <antoniosartori@chromium.org>
Auto-Submit: Titouan Rigoudy <titouan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#966126}
diff --git a/html/cross-origin-embedder-policy/dedicated-worker.https.html b/html/cross-origin-embedder-policy/dedicated-worker.https.html
index cc0c470..1ba6241 100644
--- a/html/cross-origin-embedder-policy/dedicated-worker.https.html
+++ b/html/cross-origin-embedder-policy/dedicated-worker.https.html
@@ -3,110 +3,212 @@
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <script src="/common/get-host-info.sub.js"></script>
+<script src="resources/worker-support.js"></script>
 <body>
 <script>
-const HOST = get_host_info();
-const FETCH_URL = `${HOST.REMOTE_ORIGIN}/common/blank.html`;
-const WORKER_URL = new URL('resources/dedicated-worker.js', location).href;
-const WITH_COEP = '?pipe=header(cross-origin-embedder-policy,require-corp)';
 
-async function createWorker(t, frameHasCoep, workerHasCoep, workerOptions) {
-  const frame = document.createElement("iframe");
-  t.add_cleanup(() => frame.remove());
-  frame.src = '/common/blank.html';
-  if (frameHasCoep) {
-    frame.src += WITH_COEP;
-  }
-  document.body.append(frame);
+const targetUrl = resolveUrl("/common/blank.html", {
+    host: get_host_info().REMOTE_HOST,
+}).href;
 
-  await new Promise(resolve => {
-    frame.addEventListener('load', resolve, {once: true})
-  });
-  const worker = new frame.contentWindow.Worker(
-    workerHasCoep ? WORKER_URL + WITH_COEP : WORKER_URL, workerOptions);
-
-  return worker;
+function workerUrl(options) {
+  return resolveUrl("resources/dedicated-worker.js", options);
 }
 
-function waitForMessage(target) {
-  return new Promise(resolve => {
-    target.addEventListener('message', resolve, {once: true});
+async function createWorker(t, url, options) {
+  const { ownerCoep, workerOptions } = options || {};
+
+  const frameUrl = resolveUrl("/common/blank.html", {
+    coep: ownerCoep,
   });
+  const frame = await withIframe(t, frameUrl);
+
+  return new frame.contentWindow.Worker(url, workerOptions);
 }
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, false, false, {});
+  const worker = await createWorker(t, workerUrl());
   worker.onerror = t.unreached_func('Worker.onerror should not be called');
 
-  worker.postMessage(FETCH_URL);
+  worker.postMessage(targetUrl);
 
   const result = await waitForMessage(worker);
   assert_equals(result.data, 'LOADED');
 }, 'COEP: none worker in COEP: none frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, true, false, {});
+  const worker = await createWorker(t, workerUrl(), {
+    ownerCoep: "require-corp",
+  });
   await new Promise(resolve => {
     worker.onerror = resolve;
   });
 }, 'COEP: none worker in COEP: require-corp frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, false, true, {});
+  const worker = await createWorker(t, workerUrl({ coep: "require-corp" }));
   worker.onerror = t.unreached_func('Worker.onerror should not be called');
 
-  worker.postMessage(FETCH_URL);
+  worker.postMessage(targetUrl);
 
   const result = await waitForMessage(worker);
   assert_equals(result.data, 'FAILED');
 }, 'COEP: require-corp worker in COEP: none frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, true, true, {});
+  const worker = await createWorker(t, workerUrl({ coep: "require-corp" }), {
+    ownerCoep: "require-corp",
+  });
   worker.onerror = t.unreached_func('Worker.onerror should not be called');
 
-  worker.postMessage(FETCH_URL);
+  worker.postMessage(targetUrl);
 
   const result = await waitForMessage(worker);
   assert_equals(result.data, 'FAILED');
 }, 'COEP: require-corp worker in COEP: require-corp frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, false, false, {type: 'module'});
+  const worker = await createWorker(t, workerUrl(), {
+    workerOptions: { type: 'module' },
+  });
   worker.onerror = t.unreached_func('Worker.onerror should not be called');
 
-  worker.postMessage(FETCH_URL);
+  worker.postMessage(targetUrl);
 
   const result = await waitForMessage(worker);
   assert_equals(result.data, 'LOADED');
 }, 'COEP: none module worker in COEP: none frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, true, false, {type: 'module'});
+  const worker = await createWorker(t, workerUrl(), {
+    ownerCoep: "require-corp",
+    workerOptions: { type: 'module' },
+  });
   await new Promise(resolve => {
     worker.onerror = resolve;
   });
 }, 'COEP: none module worker in COEP: require-corp frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, false, true, {type: 'module'});
+  const worker = await createWorker(t, workerUrl({ coep: "require-corp" }), {
+    workerOptions: { type: 'module' },
+  });
   worker.onerror = t.unreached_func('Worker.onerror should not be called');
 
-  worker.postMessage(FETCH_URL);
+  worker.postMessage(targetUrl);
 
   const result = await waitForMessage(worker);
   assert_equals(result.data, 'FAILED');
 }, 'COEP: require-corp module worker in COEP: none frame');
 
 promise_test(async (t) => {
-  const worker = await createWorker(t, true, true, {type: 'module'});
+  const worker = await createWorker(t, workerUrl({ coep: "require-corp" }), {
+    ownerCoep: "require-corp",
+    workerOptions: { type: 'module' },
+  });
   worker.onerror = t.unreached_func('Worker.onerror should not be called');
 
-  worker.postMessage(FETCH_URL);
+  worker.postMessage(targetUrl);
 
   const result = await waitForMessage(worker);
   assert_equals(result.data, 'FAILED');
 }, 'COEP: require-corp module worker in COEP: require-corp frame');
 
+promise_test(async (t) => {
+  const url = await createLocalUrl(t, {
+    url: workerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "blob",
+  });
+
+  const worker = await createWorker(t, url, { ownerCoep: "require-corp" });
+  worker.onerror = t.unreached_func('Worker.onerror should not be called');
+
+  worker.postMessage(targetUrl);
+
+  const result = await waitForMessage(worker);
+  assert_equals(result.data, 'FAILED');
+}, "COEP: worker inherits COEP for blob URL.");
+
+promise_test(async (t) => {
+  const url = await createLocalUrl(t, {
+    url: workerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "blob",
+  });
+
+  const worker = await createWorker(t, url);
+  worker.onerror = t.unreached_func('Worker.onerror should not be called');
+
+  worker.postMessage(targetUrl);
+
+  const result = await waitForMessage(worker);
+  assert_equals(result.data, 'FAILED');
+}, "COEP: worker inherits COEP from blob URL creator, not owner.");
+
+promise_test(async (t) => {
+  const url = await createLocalUrl(t, {
+    url: workerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "data",
+  });
+
+  const worker = await createWorker(t, url, { ownerCoep: "require-corp" });
+  worker.onerror = t.unreached_func('Worker.onerror should not be called');
+
+  worker.postMessage(targetUrl);
+
+  const result = await waitForMessage(worker);
+  assert_equals(result.data, 'FAILED');
+}, "COEP: worker inherits COEP for data URL.");
+
+promise_test(async (t) => {
+  const url = await createLocalUrl(t, {
+    url: workerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "data",
+  });
+
+  const worker = await createWorker(t, url);
+  worker.onerror = t.unreached_func('Worker.onerror should not be called');
+
+  worker.postMessage(targetUrl);
+
+  const result = await waitForMessage(worker);
+  assert_equals(result.data, 'LOADED');
+}, "COEP: worker inherits COEP from owner, not data URL creator.");
+
+promise_test(async (t) => {
+  const url = await createLocalUrl(t, {
+    url: workerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "filesystem",
+  });
+
+  const worker = await createWorker(t, url, { ownerCoep: "require-corp" });
+  worker.onerror = t.unreached_func('Worker.onerror should not be called');
+
+  worker.postMessage(targetUrl);
+
+  const result = await waitForMessage(worker);
+  assert_equals(result.data, 'FAILED');
+}, "COEP: worker inherits COEP for filesystem URL.");
+
+promise_test(async (t) => {
+  const url = await createLocalUrl(t, {
+    url: workerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "filesystem",
+  });
+
+  const worker = await createWorker(t, url);
+  worker.onerror = t.unreached_func('Worker.onerror should not be called');
+
+  worker.postMessage(targetUrl);
+
+  const result = await waitForMessage(worker);
+  assert_equals(result.data, 'FAILED');
+}, "COEP: worker inherits COEP from filesystem URL creator, not owner.");
+
 </script>
 </body>
diff --git a/html/cross-origin-embedder-policy/resources/fetch-and-create-url.html b/html/cross-origin-embedder-policy/resources/fetch-and-create-url.html
new file mode 100644
index 0000000..6b0f962
--- /dev/null
+++ b/html/cross-origin-embedder-policy/resources/fetch-and-create-url.html
@@ -0,0 +1,91 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Fetch and create Blob</title>
+<script>
+  async function responseToBlob(response) {
+    let blob;
+    try {
+      blob = await response.blob();
+    } catch (e) {
+      return { error: `blob error: ${e.name}` };
+    }
+
+    return { url: URL.createObjectURL(blob) };
+  }
+
+  async function responseToData(response) {
+    const mimeType = response.headers.get("content-type");
+
+    let text;
+    try {
+      text = await response.text();
+    } catch(e) {
+      return { error: `text error: ${e.name}` };
+    }
+
+    return { url: `data:${mimeType},${encodeURIComponent(text)}` };
+  }
+
+  async function responseToFilesystem(response) {
+    if (!window.webkitRequestFileSystem) {
+      return { error: "unimplemented" };
+    }
+
+    let blob;
+    try {
+      blob = await response.blob();
+    } catch (e) {
+      return { error: `blob error: ${e.name}` };
+    }
+
+    const fs = await new Promise(resolve => {
+      window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, resolve);
+    });
+
+    const file = await new Promise(resolve => {
+      fs.root.getFile('fetch-and-create-url', { create: true }, resolve);
+    });
+
+    const writer = await new Promise(resolve => file.createWriter(resolve));
+
+    try {
+      await new Promise((resolve, reject) => {
+        writer.onwriteend = resolve;
+        writer.onerror = reject;
+        writer.write(blob);
+      });
+    } catch (e) {
+      return { error: `file write error: ${e.name}` };
+    }
+
+    return { url: file.toURL() };
+  }
+
+  async function responseToScheme(response, scheme) {
+    switch (scheme) {
+      case "blob":
+        return responseToBlob(response);
+      case "data":
+        return responseToData(response);
+      case "filesystem":
+        return responseToFilesystem(response);
+      default:
+        return { error: `unknown scheme: ${scheme}` };
+    }
+  }
+
+  async function fetchToScheme(url, scheme) {
+    let response;
+    try {
+      response = await fetch(url);
+    } catch (e) {
+      return { error: `fetch error: ${e.name}` };
+    }
+
+    return responseToScheme(response, scheme);
+  }
+
+  const params = new URL(window.location).searchParams;
+  fetchToScheme(params.get("url"), params.get("scheme"))
+    .then((message) => { parent.postMessage(message, "*"); });
+</script>
diff --git a/html/cross-origin-embedder-policy/resources/worker-support.js b/html/cross-origin-embedder-policy/resources/worker-support.js
new file mode 100644
index 0000000..860ee68
--- /dev/null
+++ b/html/cross-origin-embedder-policy/resources/worker-support.js
@@ -0,0 +1,81 @@
+// Configures `url` such that the response carries a `COEP: ${value}` header.
+//
+// `url` must be a `URL` instance.
+function setCoep(url, value) {
+  url.searchParams
+      .set("pipe", `header(cross-origin-embedder-policy,${value})`);
+}
+
+// Resolves the given `relativeUrl` relative to the current window's location.
+//
+// `options` can contain the following keys:
+//
+// - `coep`: value passed to `setCoep()`, if present.
+// - `host`: overrides the host of the returned URL.
+//
+// Returns a `URL` instance.
+function resolveUrl(relativeUrl, options) {
+  const url = new URL(relativeUrl, window.location);
+
+  if (options !== undefined) {
+    const { coep, host } = options;
+    if (coep !== undefined) {
+      setCoep(url, coep);
+    }
+    if (host !== undefined) {
+      url.host = host;
+    }
+  }
+
+  return url;
+}
+
+// Adds an iframe loaded from `url` to the current document, waiting for it to
+// load before returning.
+//
+// The returned iframe is removed from the document at the end of the test `t`.
+async function withIframe(t, url) {
+  const frame = document.createElement("iframe");
+  frame.src = url;
+
+  t.add_cleanup(() => frame.remove());
+
+  const loadedPromise = new Promise(resolve => {
+    frame.addEventListener('load', resolve, {once: true});
+  });
+  document.body.append(frame);
+  await loadedPromise;
+
+  return frame;
+}
+
+// Asynchronously waits for a single "message" event on the given `target`.
+function waitForMessage(target) {
+  return new Promise(resolve => {
+    target.addEventListener('message', resolve, {once: true});
+  });
+}
+
+// Fetches `url` from a document with COEP `creatorCoep`, then serializes it
+// and returns a URL pointing to the fetched body with the given `scheme`.
+//
+// - `creatorCoep` is passed to `setCoep()`.
+// - `scheme` may be one of: "blob", "data" or "filesystem".
+//
+// The returned URL is valid until the end of the test `t`.
+async function createLocalUrl(t, { url, creatorCoep, scheme }) {
+  const frameUrl = resolveUrl("resources/fetch-and-create-url.html", {
+    coep: creatorCoep,
+  });
+  frameUrl.searchParams.set("url", url);
+  frameUrl.searchParams.set("scheme", scheme);
+
+  const messagePromise = waitForMessage(window);
+  const frame = await withIframe(t, frameUrl);
+
+  const evt = await messagePromise;
+  const message = evt.data;
+  assert_equals(message.error, undefined, "url creation error");
+
+  return message.url;
+}
diff --git a/html/cross-origin-embedder-policy/shared-workers.https.html b/html/cross-origin-embedder-policy/shared-workers.https.html
index 82b5e50..2558f2d 100644
--- a/html/cross-origin-embedder-policy/shared-workers.https.html
+++ b/html/cross-origin-embedder-policy/shared-workers.https.html
@@ -5,6 +5,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/common/get-host-info.sub.js"></script>
+<script src="resources/worker-support.js"></script>
 <body>
 <p>Verify the Cross-Origin Embedder Policy for Shared Workers by performing a
 cross-domain "fetch" request for a resource that does not specify a COEP. Only
@@ -13,51 +14,39 @@
 <script>
 'use strict';
 
-const {ORIGIN, REMOTE_ORIGIN} = get_host_info();
-const BASE = new URL("resources", location).pathname
-const testUrl = `${REMOTE_ORIGIN}${BASE}/empty-coep.py`;
-const workerHttpUrl = `${ORIGIN}${BASE}/shared-worker-fetch.js.py`;
-let workerBlobUrl;
-let workerDataUrl;
+const testUrl = resolveUrl("resources/empty-coep.py", {
+  host: get_host_info().REMOTE_HOST,
+}).href;
 
-promise_setup(() => {
-  return fetch(workerHttpUrl)
-    .then((response) => response.text())
-    .then((text) => {
-      workerDataUrl = 'data:text/javascript;base64,' + btoa(text);
-      workerBlobUrl = URL.createObjectURL(
-        new Blob([text], { 'Content-Type': 'text/javascript' })
-      );
-    });
-});
+function makeWorkerUrl(options) {
+  return resolveUrl("resources/shared-worker-fetch.js.py", options);
+}
 
 /**
  * Create a Shared Worker within an iframe
  *
  * @param {object} t - a testharness.js subtest instance (used to reset global
  *                     state)
- * @param {string} ownerCoep - the Cross-Origin Embedder Policy of the iframe
- * @param {string} workerUrl - the URL from which the Shared Worker should be
- *                             created
+ * @param {string} url - the URL from which the Shared Worker should be
+ *                       created
+ * @param {string} options.ownerCoep - the Cross-Origin Embedder Policy of the
+                                       iframe
  */
-function create(t, ownerCoep, workerUrl) {
-  const iframe = document.createElement('iframe');
-  iframe.src = 'resources/empty-coep.py' +
-    (ownerCoep ? '?value=' + ownerCoep : '');
+async function createWorker(t, url, options) {
+  const { ownerCoep } = options || {};
+  const frameUrl = resolveUrl("/common/blank.html", { coep: ownerCoep });
 
-  return new Promise((resolve, reject) => {
-      document.body.appendChild(iframe);
-      t.add_cleanup(() => iframe.remove());
-      iframe.onload = () => resolve(iframe);
-    })
-    .then((iframe) => {
-      const sw = new iframe.contentWindow.SharedWorker(workerUrl);
+  const iframe = await withIframe(t, frameUrl);
 
-      return new Promise((resolve) => {
-        sw.port.addEventListener('message', () => resolve(sw), { once: true });
-        sw.port.start();
-      });
-    });
+  const sw = new iframe.contentWindow.SharedWorker(url);
+  sw.onerror = t.unreached_func('SharedWorker.onerror should not be called');
+
+  await new Promise((resolve) => {
+    sw.port.addEventListener('message', resolve, { once: true });
+    sw.port.start();
+  });
+
+  return sw;
 }
 
 /**
@@ -76,57 +65,164 @@
   });
 };
 
-promise_test((t) => {
-  return create(t, null, workerHttpUrl)
-    .then((worker) => fetchFromWorker(worker, testUrl))
-    .then((result) => assert_equals(result, 'success'));
+promise_test(async (t) => {
+  const worker = await createWorker(t, makeWorkerUrl());
+  const result = await fetchFromWorker(worker, testUrl);
+  assert_equals(result, 'success');
 }, 'default policy (derived from response)');
 
-promise_test((t) => {
-  return create(t, null, workerHttpUrl + '?value=require-corp')
-    .then((worker) => fetchFromWorker(worker, testUrl))
-    .then((result) => assert_equals(result, 'failure'));
+promise_test(async (t) => {
+  const worker = await createWorker(t, makeWorkerUrl({ coep: 'require-corp' }));
+  const result = await fetchFromWorker(worker, testUrl);
+  assert_equals(result, 'failure');
 }, '"require-corp" (derived from response)');
 
-promise_test((t) => {
-  return Promise.all([
-      create(t, null, workerBlobUrl),
-      create(t, null, workerBlobUrl),
-      create(t, null, workerBlobUrl)
-    ])
-    .then((workers) => fetchFromWorker(workers[0], testUrl))
-    .then((result) => assert_equals(result, 'success'));
+promise_test(async (t) => {
+  const blobUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    scheme: "blob",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, blobUrl),
+    createWorker(t, blobUrl),
+    createWorker(t, blobUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'success');
 }, 'default policy (derived from owner set due to use of local scheme - blob URL)');
 
-promise_test((t) => {
-  return Promise.all([
-      create(t, null, workerBlobUrl),
-      create(t, 'require-corp', workerBlobUrl),
-      create(t, null, workerBlobUrl)
-    ])
-    .then((workers) => fetchFromWorker(workers[0], testUrl))
-    .then((result) => assert_equals(result, 'failure'));
+promise_test(async (t) => {
+  const blobUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "blob",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, blobUrl),
+    createWorker(t, blobUrl),
+    createWorker(t, blobUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'failure');
+}, 'require-corp (derived from blob URL creator)');
+
+promise_test(async (t) => {
+  const blobUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    scheme: "blob",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, blobUrl),
+    createWorker(t, blobUrl, { ownerCoep: 'require-corp' }),
+    createWorker(t, blobUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'failure');
 }, '"require-corp" (derived from owner set due to use of local scheme - blob URL)');
 
-promise_test((t) => {
-  return Promise.all([
-      create(t, null, workerDataUrl),
-      create(t, null, workerDataUrl),
-      create(t, null, workerDataUrl)
-    ])
-    .then((workers) => fetchFromWorker(workers[0], testUrl))
-    .then((result) => assert_equals(result, 'success'));
+promise_test(async (t) => {
+  const dataUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    scheme: "data",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, dataUrl),
+    createWorker(t, dataUrl),
+    createWorker(t, dataUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'success');
 }, 'default policy (derived from owner set due to use of local scheme - data URL)');
 
-promise_test((t) => {
-  return Promise.all([
-      create(t, null, workerDataUrl),
-      create(t, 'require-corp', workerDataUrl),
-      create(t, null, workerDataUrl)
-    ])
-    .then((workers) => fetchFromWorker(workers[0], testUrl))
-    .then((result) => assert_equals(result, 'failure'));
+promise_test(async (t) => {
+  const dataUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "data",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, dataUrl),
+    createWorker(t, dataUrl),
+    createWorker(t, dataUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'success');
+}, 'default policy (not derived from data URL creator)');
+
+promise_test(async (t) => {
+  const dataUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    scheme: "data",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, dataUrl),
+    createWorker(t, dataUrl, { ownercoep: 'require-corp' }),
+    createWorker(t, dataUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'failure');
 }, '"require-corp" (derived from owner set due to use of local scheme - data URL)');
+
+promise_test(async (t) => {
+  const filesystemUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    scheme: "filesystem",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, filesystemUrl),
+    createWorker(t, filesystemUrl),
+    createWorker(t, filesystemUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'success');
+}, 'default policy (derived from owner set due to use of local scheme - filesystem URL)');
+
+promise_test(async (t) => {
+  const filesystemUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    creatorCoep: "require-corp",
+    scheme: "filesystem",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, filesystemUrl),
+    createWorker(t, filesystemUrl),
+    createWorker(t, filesystemUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'failure');
+}, 'require-corp (derived from filesystem URL creator)');
+
+promise_test(async (t) => {
+  const filesystemUrl = await createLocalUrl(t, {
+    url: makeWorkerUrl(),
+    scheme: "filesystem",
+  });
+
+  const workers = await Promise.all([
+    createWorker(t, filesystemUrl),
+    createWorker(t, filesystemUrl, { ownerCoep: 'require-corp' }),
+    createWorker(t, filesystemUrl),
+  ]);
+
+  const result = await fetchFromWorker(workers[0], testUrl);
+  assert_equals(result, 'failure');
+}, '"require-corp" (derived from owner set due to use of local scheme - filesystem URL)');
 </script>
 </body>
 </html>