chromium/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/reporting-subresource-corp.https.window.js

// META: timeout=long
// META: script=/common/utils.js
// META: script=/common/get-host-info.sub.js
// META: script=/service-workers/service-worker/resources/test-helpers.sub.js
const {ORIGIN, REMOTE_ORIGIN} = get_host_info();
const BASE = "/html/cross-origin-embedder-policy/resources";
const REPORTING_FRAME_URL = `${ORIGIN}${BASE}/reporting-empty-frame.html` +
  '?pipe=header(cross-origin-embedder-policy,credentialless)' +
  '&token=${token()}';

async function observeReports(global, expected_count) {
  const reports = [];
  const receivedEveryReports = new Promise(resolve => {
    if (expected_count == 0)
      resolve();

    const observer = new global.ReportingObserver((rs) => {
      for (const r of rs) {
        reports.push(r.toJSON());
      }
      if (expected_count <= reports.length)
        resolve();
    });
    observer.observe();

  });

  await receivedEveryReports;
  // Wait 1000ms more to catch additionnal unexpected reports.
  await new Promise(r => step_timeout(r, 1000));
  return reports;
}

async function fetchInFrame(t, frameUrl, url, expected_count) {
  const frame = await with_iframe(frameUrl);
  t.add_cleanup(() => frame.remove());

  const init = { mode: 'no-cors', cache: 'no-store' };
  let future_reports = observeReports(frame.contentWindow, expected_count);
  await frame.contentWindow.fetch(url, init).catch(() => {});

  return await future_reports;
}

function checkReport(report, contextUrl, blockedUrl, disposition, destination) {
  assert_equals(report.type, 'coep');
  assert_equals(report.url, contextUrl);
  assert_equals(report.body.type, 'corp');
  assert_equals(report.body.blockedURL, blockedUrl);
  assert_equals(report.body.disposition, disposition);
  assert_equals(report.body.destination, destination);
}

// A redirection is used, so that the initial request is same-origin and is
// proxyied through the service worker. The ServiceWorker is COEP:unsafe-none,
// so it will make the cross-origin request with credentials. The fetch will
// succeed, but the response will be blocked by CORP when entering the
// COEP:credentialless document.
// https://github.com/w3c/ServiceWorker/issues/1592
promise_test(async (t) => {
  const url = `${ORIGIN}/common/redirect.py?location=` +
       encodeURIComponent(`${REMOTE_ORIGIN}/common/text-plain.txt`);
  const WORKER_URL = `${ORIGIN}${BASE}/sw.js`;
  const reg = await service_worker_unregister_and_register(
    t, WORKER_URL, REPORTING_FRAME_URL);
  t.add_cleanup(() => reg.unregister());
  const worker = reg.installing || reg.waiting || reg.active;
  worker.addEventListener('error', t.unreached_func('Worker.onerror'));
  await wait_for_state(t, worker, 'activated');

  const reports = await fetchInFrame(t, REPORTING_FRAME_URL, url, 1);
  assert_equals(reports.length, 1);
  checkReport(reports[0], REPORTING_FRAME_URL, url, 'enforce', '');
});