1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
<!DOCTYPE html>
<meta charset="utf-8"/>
<title>Service Worker: Partitioned Service Workers</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="resources/partitioned-utils.js"></script>
<body>
<!-- Debugging text for both test cases -->
The 3p iframe's postMessage:
<p id="iframe_response">No message received</p>
The nested iframe's postMessage:
<p id="nested_iframe_response">No message received</p>
<script>
promise_test(async t => {
const script = './resources/partitioned-storage-sw.js'
const scope = './resources/partitioned-'
// Add service worker to this 1P context. wait_for_state() and
// service_worker_unregister_and_register() are helper functions
// for creating test ServiceWorkers defined in:
// service-workers/service-worker/resources/test-helpers.sub.js
const reg = await service_worker_unregister_and_register(t, script, scope);
t.add_cleanup(() => reg.unregister());
await wait_for_state(t, reg.installing, 'activated');
// Registers the message listener with messageEventHandler(), defined in:
// service-workers/service-worker/resources/partitioned-utils.js
self.addEventListener('message', messageEventHandler);
// Open an iframe that will create a promise within the SW.
// Defined in service-workers/service-worker/resources/partitioned-storage-sw.js:
// `waitUntilResolved.fakehtml`: URL scope that creates the promise.
// `?From1pFrame`: query param that tracks which request the service worker is
// handling.
const wait_frame_url = new URL(
'./resources/partitioned-waitUntilResolved.fakehtml?From1pFrame',
self.location);
// Loads a child iframe with wait_frame_url as the content and returns
// a promise for the data messaged from the loaded iframe.
// loadAndReturnSwData() defined in:
// service-workers/service-worker/resources/partitioned-utils.js:
const wait_frame_1p_data = await loadAndReturnSwData(t, wait_frame_url,
'iframe');
assert_equals(wait_frame_1p_data.source, 'From1pFrame',
'The data for the 1p frame came from the wrong source');
// Now create a 3p iframe that will try to resolve the SW in a 3p context.
const third_party_iframe_url = new URL(
'./resources/partitioned-service-worker-third-party-iframe.html',
get_host_info().HTTPS_ORIGIN + self.location.pathname);
// loadAndReturnSwData() creates a HTTPS_NOTSAMESITE_ORIGIN or 3p `window`
// element which embeds an iframe with the ServiceWorker and returns
// a promise of the data messaged from that frame.
const frame_3p_data = await loadAndReturnSwData(t, third_party_iframe_url, 'window');
assert_equals(frame_3p_data.source, 'From3pFrame',
'The data for the 3p frame came from the wrong source');
// Print some debug info to the main frame.
document.getElementById("iframe_response").innerHTML =
"3p iframe's has_pending: " + frame_3p_data.has_pending + " source: " +
frame_3p_data.source + ". ";
// Now do the same for the 1p iframe.
// Defined in service-workers/service-worker/resources/partitioned-storage-sw.js:
// `resolve.fakehtml`: URL scope that resolves the promise.
const resolve_frame_url = new URL(
'./resources/partitioned-resolve.fakehtml?From1pFrame', self.location);
const frame_1p_data = await loadAndReturnSwData(t, resolve_frame_url,
'iframe');
assert_equals(frame_1p_data.source, 'From1pFrame',
'The data for the 1p frame came from the wrong source');
// Both the 1p frames should have been serviced by the same service worker ID.
// If this isn't the case then that means the SW could have been deactivated
// which invalidates the test.
assert_equals(frame_1p_data.ID, wait_frame_1p_data.ID,
'The 1p frames were serviced by different service workers.');
document.getElementById("iframe_response").innerHTML +=
"1p iframe's has_pending: " + frame_1p_data.has_pending + " source: " +
frame_1p_data.source;
// If partitioning is working correctly then only the 1p iframe should see
// (and resolve) its SW's promise. Additionally the two frames should see
// different IDs.
assert_true(frame_1p_data.has_pending,
'The 1p iframe saw a pending promise in the service worker.');
assert_false(frame_3p_data.has_pending,
'The 3p iframe saw a pending promise in the service worker.');
assert_not_equals(frame_1p_data.ID, frame_3p_data.ID,
'The frames were serviced by the same service worker thread.');
}, 'Services workers under different top-level sites are partitioned.');
// Optional Test: Checking for partitioned ServiceWorkers in an A->B->A
// (nested-iframes with cross-site ancestor) scenario.
promise_test(async t => {
const script = './resources/partitioned-storage-sw.js'
const scope = './resources/partitioned-'
// Add service worker to this 1P context. wait_for_state() and
// service_worker_unregister_and_register() are helper functions
// for creating test ServiceWorkers defined in:
// service-workers/service-worker/resources/test-helpers.sub.js
const reg = await service_worker_unregister_and_register(t, script, scope);
t.add_cleanup(() => reg.unregister());
await wait_for_state(t, reg.installing, 'activated');
// Registers the message listener with messageEventHandler(), defined in:
// service-workers/service-worker/resources/partitioned-utils.js
self.addEventListener('message', messageEventHandler);
// Open an iframe that will create a promise within the SW.
// Defined in service-workers/service-worker/resources/partitioned-storage-sw.js:
// `waitUntilResolved.fakehtml`: URL scope that creates the promise.
// `?From1pFrame`: query param that tracks which request the service worker is
// handling.
const wait_frame_url = new URL(
'./resources/partitioned-waitUntilResolved.fakehtml?From1pFrame',
self.location);
// Load a child iframe with wait_frame_url as the content.
// loadAndReturnSwData() defined in:
// service-workers/service-worker/resources/partitioned-utils.js:
const wait_frame_1p_data = await loadAndReturnSwData(t, wait_frame_url,
'iframe');
assert_equals(wait_frame_1p_data.source, 'From1pFrame',
'The data for the 1p frame came from the wrong source');
// Now create a set of nested iframes in the configuration A1->B->A2
// where B is cross-site and A2 is same-site to this top-level
// site (A1). The innermost iframe of the nested iframes (A2) will
// create an additional iframe to finally resolve the ServiceWorker.
const nested_iframe_url = new URL(
'./resources/partitioned-service-worker-nested-iframe-parent.html',
get_host_info().HTTPS_NOTSAMESITE_ORIGIN + self.location.pathname);
// Create the nested iframes (which will in turn create the iframe
// with the ServiceWorker) and await on receiving its data.
const nested_iframe_data = await loadAndReturnSwData(t, nested_iframe_url, 'iframe');
assert_equals(nested_iframe_data.source, 'FromNestedFrame',
'The data for the nested iframe frame came from the wrong source');
// Print some debug info to the main frame.
document.getElementById("nested_iframe_response").innerHTML =
"Nested iframe's has_pending: " + nested_iframe_data.has_pending + " source: " +
nested_iframe_data.source + ". ";
// Now do the same for the 1p iframe.
// Defined in service-workers/service-worker/resources/partitioned-storage-sw.js:
// `resolve.fakehtml`: URL scope that resolves the promise.
const resolve_frame_url = new URL(
'./resources/partitioned-resolve.fakehtml?From1pFrame', self.location);
const frame_1p_data = await loadAndReturnSwData(t, resolve_frame_url,
'iframe');
assert_equals(frame_1p_data.source, 'From1pFrame',
'The data for the 1p frame came from the wrong source');
// Both the 1p frames should have been serviced by the same service worker ID.
// If this isn't the case then that means the SW could have been deactivated
// which invalidates the test.
assert_equals(frame_1p_data.ID, wait_frame_1p_data.ID,
'The 1p frames were serviced by different service workers.');
document.getElementById("nested_iframe_response").innerHTML +=
"1p iframe's has_pending: " + frame_1p_data.has_pending + " source: " +
frame_1p_data.source;
// If partitioning is working correctly then only the 1p iframe should see
// (and resolve) its SW's promise. Additionally, the innermost iframe of
// the nested iframes (A2 in the configuration A1->B->A2) should have a
// different service worker ID than the 1p (A1) frame.
assert_true(frame_1p_data.has_pending,
'The 1p iframe saw a pending promise in the service worker.');
assert_false(nested_iframe_data.has_pending,
'The 3p iframe saw a pending promise in the service worker.');
assert_not_equals(frame_1p_data.ID, nested_iframe_data.ID,
'The frames were serviced by the same service worker thread.');
}, 'Services workers with cross-site ancestors are partitioned.');
</script>
</body>
|