| // META: script=/common/subset-tests-by-key.js |
| // META: script=/common/utils.js |
| // META: script=resources/support.sub.js |
| // META: script=/fenced-frame/resources/utils.js |
| // META: variant=?include=baseline |
| // META: variant=?include=from-local |
| // META: variant=?include=from-private |
| // META: variant=?include=from-public |
| // |
| // Spec: https://wicg.github.io/private-network-access/#integration-fetch |
| // |
| // These tests verify that secure contexts can fetch subresources in fenced |
| // frames from all address spaces, provided that the target server, if more |
| // private than the initiator, respond affirmatively to preflight requests. |
| // |
| |
| setup(() => { |
| // Making sure we are in a secure context, as expected. |
| assert_true(window.isSecureContext); |
| }); |
| |
| // Source: secure local context. |
| // |
| // All fetches unaffected by Private Network Access. |
| |
| subsetTestByKey( |
| 'from-local', promise_test, t => fencedFrameFetchTest(t, { |
| source: {server: Server.HTTPS_LOCAL}, |
| target: {server: Server.HTTPS_LOCAL}, |
| fetchOptions: {method: 'GET', mode: 'cors'}, |
| expected: FetchTestResult.SUCCESS, |
| }), |
| 'local to local: no preflight required.'); |
| |
| subsetTestByKey( |
| 'from-local', promise_test, |
| t => fencedFrameFetchTest(t, { |
| source: {server: Server.HTTPS_LOCAL}, |
| target: { |
| server: Server.HTTPS_PRIVATE, |
| behavior: {response: ResponseBehavior.allowCrossOrigin()}, |
| }, |
| fetchOptions: {method: 'GET', mode: 'cors'}, |
| expected: FetchTestResult.SUCCESS, |
| }), |
| 'local to private: no preflight required.'); |
| |
| |
| subsetTestByKey( |
| 'from-local', promise_test, |
| t => fencedFrameFetchTest(t, { |
| source: {server: Server.HTTPS_LOCAL}, |
| target: { |
| server: Server.HTTPS_PUBLIC, |
| behavior: {response: ResponseBehavior.allowCrossOrigin()}, |
| }, |
| fetchOptions: {method: 'GET', mode: 'cors'}, |
| expected: FetchTestResult.SUCCESS, |
| }), |
| 'local to public: no preflight required.'); |
| |
| // Strictly speaking, the following two tests do not exercise PNA-specific |
| // logic, but they serve as a baseline for comparison, ensuring that non-PNA |
| // preflight requests are sent and handled as expected. |
| |
| subsetTestByKey( |
| 'baseline', promise_test, |
| t => fencedFrameFetchTest(t, { |
| source: {server: Server.HTTPS_LOCAL}, |
| target: { |
| server: Server.HTTPS_PUBLIC, |
| behavior: { |
| preflight: PreflightBehavior.failure(), |
| response: ResponseBehavior.allowCrossOrigin(), |
| }, |
| }, |
| fetchOptions: {method: 'PUT', mode: 'cors'}, |
| expected: FetchTestResult.FAILURE, |
| }), |
| 'local to public: PUT preflight failure.'); |
| |
| subsetTestByKey( |
| 'baseline', promise_test, |
| t => fencedFrameFetchTest(t, { |
| source: {server: Server.HTTPS_LOCAL}, |
| target: { |
| server: Server.HTTPS_PUBLIC, |
| behavior: { |
| preflight: PreflightBehavior.success(token()), |
| response: ResponseBehavior.allowCrossOrigin(), |
| } |
| }, |
| fetchOptions: {method: 'PUT', mode: 'cors'}, |
| expected: FetchTestResult.SUCCESS, |
| }), |
| 'local to public: PUT preflight success.'); |
| |
| // Generates tests of preflight behavior for a single (source, target) pair. |
| // |
| // Scenarios: |
| // |
| // - cors mode: |
| // - preflight response has non-2xx HTTP code |
| // - preflight response is missing CORS headers |
| // - preflight response is missing the PNA-specific `Access-Control` header |
| // - final response is missing CORS headers |
| // - success |
| // - success with PUT method (non-"simple" request) |
| // - no-cors mode: |
| // - 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({ |
| subsetKey, |
| source, |
| sourceDescription, |
| targetServer, |
| targetDescription, |
| }) { |
| const prefix = `${sourceDescription} to ${targetDescription}: `; |
| |
| subsetTestByKey( |
| subsetKey, promise_test, |
| t => fencedFrameFetchTest(t, { |
| source, |
| target: { |
| server: targetServer, |
| behavior: { |
| preflight: PreflightBehavior.failure(), |
| response: ResponseBehavior.allowCrossOrigin(), |
| }, |
| }, |
| fetchOptions: {method: 'GET', mode: 'cors'}, |
| expected: FetchTestResult.FAILURE, |
| }), |
| prefix + 'failed preflight.'); |
| |
| subsetTestByKey( |
| subsetKey, promise_test, |
| t => fencedFrameFetchTest(t, { |
| source, |
| target: { |
| server: targetServer, |
| behavior: { |
| preflight: PreflightBehavior.noCorsHeader(token()), |
| response: ResponseBehavior.allowCrossOrigin(), |
| }, |
| }, |
| fetchOptions: {method: 'GET', mode: 'cors'}, |
| expected: FetchTestResult.FAILURE, |
| }), |
| prefix + 'missing CORS headers on preflight response.'); |
| |
| subsetTestByKey( |
| subsetKey, promise_test, |
| t => fencedFrameFetchTest(t, { |
| source, |
| target: { |
| server: targetServer, |
| behavior: { |
| preflight: PreflightBehavior.noPnaHeader(token()), |
| response: ResponseBehavior.allowCrossOrigin(), |
| }, |
| }, |
| fetchOptions: {method: 'GET', mode: 'cors'}, |
| expected: FetchTestResult.FAILURE, |
| }), |
| prefix + 'missing PNA header on preflight response.'); |
| |
| subsetTestByKey( |
| subsetKey, promise_test, |
| t => fencedFrameFetchTest(t, { |
| source, |
| target: { |
| server: targetServer, |
| behavior: {preflight: PreflightBehavior.success(token())}, |
| }, |
| fetchOptions: {method: 'GET', mode: 'cors'}, |
| expected: FetchTestResult.FAILURE, |
| }), |
| prefix + 'missing CORS headers on final response.'); |
| |
| subsetTestByKey( |
| subsetKey, promise_test, |
| t => fencedFrameFetchTest(t, { |
| source, |
| target: { |
| server: targetServer, |
| behavior: { |
| preflight: PreflightBehavior.success(token()), |
| response: ResponseBehavior.allowCrossOrigin(), |
| }, |
| }, |
| fetchOptions: {method: 'GET', mode: 'cors'}, |
| expected: FetchTestResult.SUCCESS, |
| }), |
| prefix + 'success.'); |
| |
| subsetTestByKey( |
| subsetKey, promise_test, |
| t => fencedFrameFetchTest(t, { |
| source, |
| target: { |
| server: targetServer, |
| behavior: { |
| preflight: PreflightBehavior.success(token()), |
| response: ResponseBehavior.allowCrossOrigin(), |
| }, |
| }, |
| fetchOptions: {method: 'PUT', mode: 'cors'}, |
| expected: FetchTestResult.SUCCESS, |
| }), |
| prefix + 'PUT success.'); |
| |
| subsetTestByKey( |
| subsetKey, promise_test, t => fencedFrameFetchTest(t, { |
| source, |
| target: {server: targetServer}, |
| fetchOptions: {method: 'GET', mode: 'no-cors'}, |
| expected: FetchTestResult.FAILURE, |
| }), |
| prefix + 'no-CORS mode failed preflight.'); |
| |
| subsetTestByKey( |
| subsetKey, promise_test, |
| t => fencedFrameFetchTest(t, { |
| source, |
| target: { |
| server: targetServer, |
| behavior: {preflight: PreflightBehavior.noCorsHeader(token())}, |
| }, |
| fetchOptions: {method: 'GET', mode: 'no-cors'}, |
| expected: FetchTestResult.FAILURE, |
| }), |
| prefix + 'no-CORS mode missing CORS headers on preflight response.'); |
| |
| subsetTestByKey( |
| subsetKey, promise_test, |
| t => fencedFrameFetchTest(t, { |
| source, |
| target: { |
| server: targetServer, |
| behavior: {preflight: PreflightBehavior.noPnaHeader(token())}, |
| }, |
| fetchOptions: {method: 'GET', mode: 'no-cors'}, |
| expected: FetchTestResult.FAILURE, |
| }), |
| prefix + 'no-CORS mode missing PNA header on preflight response.'); |
| |
| subsetTestByKey( |
| subsetKey, promise_test, |
| t => fencedFrameFetchTest(t, { |
| source, |
| target: { |
| server: targetServer, |
| behavior: {preflight: PreflightBehavior.success(token())}, |
| }, |
| fetchOptions: {method: 'GET', mode: 'no-cors'}, |
| expected: FetchTestResult.OPAQUE, |
| }), |
| prefix + 'no-CORS mode success.'); |
| } |
| |
| // Source: private secure context. |
| // |
| // Fetches to the local address space require a successful preflight response |
| // carrying a PNA-specific header. |
| |
| makePreflightTests({ |
| subsetKey: 'from-private', |
| source: {server: Server.HTTPS_PRIVATE}, |
| sourceDescription: 'private', |
| targetServer: Server.HTTPS_LOCAL, |
| targetDescription: 'local', |
| }); |
| |
| subsetTestByKey( |
| 'from-private', promise_test, t => fencedFrameFetchTest(t, { |
| source: {server: Server.HTTPS_PRIVATE}, |
| target: {server: Server.HTTPS_PRIVATE}, |
| fetchOptions: {method: 'GET', mode: 'cors'}, |
| expected: FetchTestResult.SUCCESS, |
| }), |
| 'private to private: no preflight required.'); |
| |
| subsetTestByKey( |
| 'from-private', promise_test, |
| t => fencedFrameFetchTest(t, { |
| source: {server: Server.HTTPS_PRIVATE}, |
| target: { |
| server: Server.HTTPS_PRIVATE, |
| behavior: {response: ResponseBehavior.allowCrossOrigin()}, |
| }, |
| fetchOptions: {method: 'GET', mode: 'cors'}, |
| expected: FetchTestResult.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({ |
| subsetKey: 'from-public', |
| source: {server: Server.HTTPS_PUBLIC}, |
| sourceDescription: 'public', |
| targetServer: Server.HTTPS_LOCAL, |
| targetDescription: 'local', |
| }); |
| |
| makePreflightTests({ |
| subsetKey: 'from-public', |
| source: {server: Server.HTTPS_PUBLIC}, |
| sourceDescription: 'public', |
| targetServer: Server.HTTPS_PRIVATE, |
| targetDescription: 'private', |
| }); |
| |
| subsetTestByKey( |
| 'from-public', promise_test, t => fencedFrameFetchTest(t, { |
| source: {server: Server.HTTPS_PUBLIC}, |
| target: {server: Server.HTTPS_PUBLIC}, |
| fetchOptions: {method: 'GET', mode: 'cors'}, |
| expected: FetchTestResult.SUCCESS, |
| }), |
| 'public to public: no preflight required.'); |