Skip to content

Commit

Permalink
[Private Network Access] Add window open tests
Browse files Browse the repository at this point in the history
These test cases are mostly borrowed from the iframe.tentative tests.
However, instead of loading a grandchild iframe, they open a window
instead. We don't need to use timeout like in iframe tests because
`window.open` returns `null` if the open fails.

Since the top-level PNA hasn't been implemented yet, all test cases that
expect a failure will fail.

Bug: 1431155
Change-Id: I639d0c56c2e1556273333a79793f67ffa14a4149
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5011032
Commit-Queue: Jonathan Hao <phao@chromium.org>
Reviewed-by: Yifan Luo <lyf@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1222864}
  • Loading branch information
johnathan79717 authored and chromium-wpt-export-bot committed Nov 10, 2023
1 parent a4f9d35 commit f7df61f
Show file tree
Hide file tree
Showing 6 changed files with 329 additions and 3 deletions.
5 changes: 3 additions & 2 deletions fetch/private-network-access/iframe.tentative.https.window.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
//
// Spec: https://wicg.github.io/private-network-access/#integration-fetch
//
// These tests verify that contexts can navigate iframes to less-public address
// spaces iff the target server responds affirmatively to preflight requests.
// These tests verify that secure contexts can navigate iframes to less-public
// address spaces iff the target server responds affirmatively to preflight
// requests.
//
// This file covers only those tests that must execute in a secure context.
// Other tests are defined in: iframe.tentative.window.js
Expand Down
2 changes: 1 addition & 1 deletion fetch/private-network-access/iframe.tentative.window.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// less-public address spaces, and can navigate them otherwise.
//
// This file covers only those tests that must execute in a non secure context.
// Other tests are defined in: iframe.https.window.js
// Other tests are defined in: iframe.tentative.https.window.js

setup(() => {
// Making sure we are in a non secure context, as expected.
Expand Down
11 changes: 11 additions & 0 deletions fetch/private-network-access/resources/opener.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Opener</title>
<body></body>
<script>
window.onmessage = (event) => {
const { url } = event.data;
const popup = window.open(url);
parent.postMessage(popup ? "success" : "failure", "*");
};
</script>
20 changes: 20 additions & 0 deletions fetch/private-network-access/resources/support.sub.js
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,26 @@ async function iframeTest(t, { source, target, expected }) {
assert_equals(result, expected);
}

const WindowOpenTestResult = {
SUCCESS: "success",
FAILURE: "failure",
};

async function windowOpenTest(t, { source, target, expected }) {
const targetUrl = preflightUrl(target);

const sourceUrl =
resolveUrl("resources/opener.html", sourceResolveOptions(source));
sourceUrl.searchParams.set("url", targetUrl);

const iframe = await appendIframe(t, document, sourceUrl);
const reply = futureMessage({ source: iframe.contentWindow });

iframe.contentWindow.postMessage({ url: targetUrl.href }, "*");

assert_equals(await reply, expected);
}

// Similar to `iframeTest`, but replaced iframes with fenced frames.
async function fencedFrameTest(t, { source, target, expected }) {
// Allows running tests in parallel.
Expand Down
200 changes: 200 additions & 0 deletions fetch/private-network-access/window-open.tentative.https.window.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
// META: script=/common/dispatcher/dispatcher.js
// META: script=/common/utils.js
// META: script=resources/support.sub.js
//
// These tests verify that secure contexts can navigate iframes to less-public
// address spaces iff the target server responds affirmatively to preflight
// requests.

setup(() => {
assert_true(window.isSecureContext);
});

// Source: secure local context.
//
// All fetches unaffected by Private Network Access.

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTPS_LOCAL },
target: { server: Server.HTTPS_LOCAL },
expected: WindowOpenTestResult.SUCCESS,
}), "local to local: no preflight required.");

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTPS_LOCAL },
target: { server: Server.HTTPS_PRIVATE },
expected: WindowOpenTestResult.SUCCESS,
}), "local to private: no preflight required.");

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTPS_LOCAL },
target: { server: Server.HTTPS_PUBLIC },
expected: WindowOpenTestResult.SUCCESS,
}), "local to public: no preflight required.");

// Generates tests of preflight behavior for a single (source, target) pair.
//
// Scenarios:
//
// - parent navigates child:
// - preflight response has non-2xx HTTP code
// - preflight response is missing CORS headers
// - preflight response is missing the PNA-specific `Access-Control` header
// - success
//
function makePreflightTests({
key,
sourceName,
sourceServer,
sourceTreatAsPublic,
targetName,
targetServer,
}) {
const prefix =
`${sourceName} to ${targetName}: `;

const source = {
server: sourceServer,
treatAsPublic: sourceTreatAsPublic,
};

promise_test_parallel(t => windowOpenTest(t, {
source,
target: {
server: targetServer,
behavior: { preflight: PreflightBehavior.failure() },
},
expected: WindowOpenTestResult.FAILURE,
}), prefix + "failed preflight.");

promise_test_parallel(t => windowOpenTest(t, {
source,
target: {
server: targetServer,
behavior: { preflight: PreflightBehavior.noCorsHeader(token()) },
},
expected: WindowOpenTestResult.FAILURE,
}), prefix + "missing CORS headers.");

promise_test_parallel(t => windowOpenTest(t, {
source,
target: {
server: targetServer,
behavior: { preflight: PreflightBehavior.noPnaHeader(token()) },
},
expected: WindowOpenTestResult.FAILURE,
}), prefix + "missing PNA header.");

promise_test_parallel(t => windowOpenTest(t, {
source,
target: {
server: targetServer,
behavior: { preflight: PreflightBehavior.success(token()) },
},
expected: WindowOpenTestResult.SUCCESS,
}), prefix + "success.");
}

// Source: private secure context.
//
// Fetches to the local address space require a successful preflight response
// carrying a PNA-specific header.

makePreflightTests({
sourceServer: Server.HTTPS_PRIVATE,
sourceName: 'private',
targetServer: Server.HTTPS_LOCAL,
targetName: 'local',
});

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTPS_PRIVATE },
target: { server: Server.HTTPS_PRIVATE },
expected: WindowOpenTestResult.SUCCESS,
}), "private to private: no preflight required.");

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTPS_PRIVATE },
target: { server: Server.HTTPS_PUBLIC },
expected: WindowOpenTestResult.SUCCESS,
}), "private to public: no preflight required.");

// Source: public secure context.
//
// Fetches to the local and private address spaces require a successful
// preflight response carrying a PNA-specific header.

makePreflightTests({
sourceServer: Server.HTTPS_PUBLIC,
sourceName: "public",
targetServer: Server.HTTPS_LOCAL,
targetName: "local",
});

makePreflightTests({
sourceServer: Server.HTTPS_PUBLIC,
sourceName: "public",
targetServer: Server.HTTPS_PRIVATE,
targetName: "private",
});

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTPS_PUBLIC },
target: { server: Server.HTTPS_PUBLIC },
expected: WindowOpenTestResult.SUCCESS,
}), "public to public: no preflight required.");

// The following tests verify that `CSP: treat-as-public-address` makes
// documents behave as if they had been served from a public IP address.

makePreflightTests({
sourceServer: Server.HTTPS_LOCAL,
sourceTreatAsPublic: true,
sourceName: "treat-as-public-address",
targetServer: Server.OTHER_HTTPS_LOCAL,
targetName: "local",
});

promise_test_parallel(
t => windowOpenTest(t, {
source: {
server: Server.HTTPS_LOCAL,
treatAsPublic: true,
},
target: {server: Server.HTTPS_LOCAL},
expected: WindowOpenTestResult.SUCCESS,
}),
'treat-as-public-address to local (same-origin): no preflight required.');

makePreflightTests({
sourceServer: Server.HTTPS_LOCAL,
sourceTreatAsPublic: true,
sourceName: 'treat-as-public-address',
targetServer: Server.HTTPS_PRIVATE,
targetName: 'private',
});

promise_test_parallel(
t => windowOpenTest(t, {
source: {
server: Server.HTTPS_LOCAL,
treatAsPublic: true,
},
target: {server: Server.HTTPS_PUBLIC},
expected: WindowOpenTestResult.SUCCESS,
}),
'treat-as-public-address to public: no preflight required.');

promise_test_parallel(
t => windowOpenTest(t, {
source: {
server: Server.HTTPS_LOCAL,
treatAsPublic: true,
},
target: {
server: Server.HTTPS_PUBLIC,
behavior: {preflight: PreflightBehavior.optionalSuccess(token())}
},
expected: WindowOpenTestResult.SUCCESS,
}),
'treat-as-public-address to local: optional preflight');
94 changes: 94 additions & 0 deletions fetch/private-network-access/window-open.tentative.window.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// META: script=/common/dispatcher/dispatcher.js
// META: script=/common/utils.js
// META: script=resources/support.sub.js
//
// Spec: https://wicg.github.io/private-network-access/
//
// These tests verify that non-secure contexts cannot open a new window to
// less-public address spaces.

setup(() => {
// Making sure we are in a non secure context, as expected.
assert_false(window.isSecureContext);
});

promise_test(t => windowOpenTest(t, {
source: { server: Server.HTTP_LOCAL },
target: { server: Server.HTTP_LOCAL },
expected: WindowOpenTestResult.SUCCESS,
}), "local to local: no preflight required.");

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTP_LOCAL },
target: { server: Server.HTTP_PRIVATE },
expected: WindowOpenTestResult.SUCCESS,
}), "local to private: no preflight required.");

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTP_LOCAL },
target: { server: Server.HTTP_PUBLIC },
expected: WindowOpenTestResult.SUCCESS,
}), "local to public: no preflight required.");

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTP_PRIVATE },
target: { server: Server.HTTP_LOCAL },
expected: WindowOpenTestResult.FAILURE,
}), "private to local: failure.");

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTP_PRIVATE },
target: { server: Server.HTTP_PRIVATE },
expected: WindowOpenTestResult.SUCCESS,
}), "private to private: no preflight required.");

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTP_PRIVATE },
target: { server: Server.HTTP_PUBLIC },
expected: WindowOpenTestResult.SUCCESS,
}), "private to public: no preflight required.");

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTP_PUBLIC },
target: { server: Server.HTTP_LOCAL },
expected: WindowOpenTestResult.FAILURE,
}), "public to local: failure.");

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTP_PUBLIC },
target: { server: Server.HTTP_PRIVATE },
expected: WindowOpenTestResult.FAILURE,
}), "public to private: failure.");

promise_test_parallel(t => windowOpenTest(t, {
source: { server: Server.HTTP_PUBLIC },
target: { server: Server.HTTP_PUBLIC },
expected: WindowOpenTestResult.SUCCESS,
}), "public to public: no preflight required.");

promise_test_parallel(t => windowOpenTest(t, {
source: {
server: Server.HTTP_LOCAL,
treatAsPublic: true,
},
target: { server: Server.HTTP_LOCAL },
expected: WindowOpenTestResult.FAILURE,
}), "treat-as-public-address to local: failure.");

promise_test_parallel(t => windowOpenTest(t, {
source: {
server: Server.HTTP_LOCAL,
treatAsPublic: true,
},
target: { server: Server.HTTP_PRIVATE },
expected: WindowOpenTestResult.FAILURE,
}), "treat-as-public-address to private: failure.");

promise_test_parallel(t => windowOpenTest(t, {
source: {
server: Server.HTTP_LOCAL,
treatAsPublic: true,
},
target: { server: Server.HTTP_PUBLIC },
expected: WindowOpenTestResult.SUCCESS,
}), "treat-as-public-address to public: no preflight required.");

0 comments on commit f7df61f

Please sign in to comment.