<!DOCTYPE html>
<title>Test sharedStorage.get() in a fenced frame with network revocation.</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/utils.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="resources/utils.js"></script>
<body>
<script>
promise_setup(async () => {
// Set sharedStorage value for HTTPS_ORIGIN
await sharedStorage.set('test', 'apple');
// Set sharedStorage value for HTTPS_REMOTE_ORIGIN.
let init_iframe = await attachIFrameContext(
{origin: get_host_info().HTTPS_REMOTE_ORIGIN});
await init_iframe.execute(async () => {
await sharedStorage.set('test', 'banana');
});
});
promise_test(async (t) => {
const fencedframe = await attachFencedFrameContext(
{origin: get_host_info().HTTPS_ORIGIN});
await fencedframe.execute(async () => {
await window.fence.disableUntrustedNetwork();
let get_result = await sharedStorage.get('test');
assert_equals(get_result, 'apple');
});
}, 'Test sharedStorage.get() succeeds in a fenced frame with network ' +
'revocation.');
promise_test(async (t) => {
const fencedframe = await attachFencedFrameContext(
{origin: get_host_info().HTTPS_ORIGIN});
await fencedframe.execute(async () => {
try {
await sharedStorage.get('test');
assert_unreached('Calling get() without revoking network should throw.');
} catch (e) {
assert_equals(e.name, 'OperationError');
assert_equals(e.message, 'sharedStorage.get() is not allowed in a ' +
'fenced frame until network access for it and all descendent frames ' +
'has been revoked with window.fence.disableUntrustedNetwork()');
}
});
}, 'Test that sharedStorage.get() in a fenced frame rejects when network is ' +
'not revoked.');
promise_test(async (t) => {
const fencedframe = await attachFencedFrameContext(
{origin: get_host_info().HTTPS_REMOTE_ORIGIN});
await fencedframe.execute(async () => {
await window.fence.disableUntrustedNetwork();
let get_result = await sharedStorage.get('test');
assert_equals(get_result, 'banana');
});
}, 'Test that sharedStorage.get() can only fetch keys for its own origin ' +
'when network is revoked.');
promise_test(async (t) => {
// First, try get() in a top-level document.
try {
await sharedStorage.get('test');
assert_unreached('Call to get() in top-level document should throw.');
} catch (e) {
assert_equals(e.name, 'OperationError');
assert_equals(e.message, 'Cannot call get() outside of a fenced frame.')
}
const samesite_iframe = await attachIFrameContext(
{origin: get_host_info().HTTPS_ORIGIN});
// Then, try get() in an iframe.
await samesite_iframe.execute(async () => {
try {
await sharedStorage.get('test');
assert_unreached('Call to get() outside a fenced frame should throw.');
} catch (e) {
assert_equals(e.name, 'OperationError');
assert_equals(e.message, 'Cannot call get() outside of a fenced frame.')
}
});
}, 'Test that sharedStorage.get() rejects outside of a fenced frame.');
promise_test(async (t) => {
const fencedframe = await attachFencedFrameContext(
{origin: get_host_info().HTTPS_ORIGIN});
const destination_url = new URL('resources/dummy.html', location.href);
await fencedframe.execute(async (destination_url) => {
const nested_frame = await attachFencedFrameContext(
{origin: get_host_info().HTTPS_ORIGIN})
// Note that we do *not* await, because we need to operate in the top frame
// while the nested frame still hasn't disabled network access.
let disable_network_promise = window.fence.disableUntrustedNetwork();
let timeout_promise = new Promise(
resolve => setTimeout(() => {resolve('timeout')}, 1000));
const result =
await Promise.race([disable_network_promise, timeout_promise]);
assert_equals(result, 'timeout',
"The disableUntrustedNetwork() promise should not resolve.");
// Even though disableUntrustedNetwork() has not resolved, network calls
// should not succeed.
try {
const response_failure = await fetch(destination_url);
assert_unreached('The fetch should throw an exception.');
} catch (e) {
assert_equals(e.name, 'TypeError');
assert_equals(e.message, 'Failed to fetch');
}
// Network calls in the nested fenced frame should still succeed, since
// their network hasn't been cut off yet.
await nested_frame.execute(async (destination_url) => {
await fetch(destination_url);
}, [destination_url]);
try {
await sharedStorage.get('test');
assert_unreached('sharedStorage.get() is not allowed in a fenced frame ' +
'until network access for it and all descendent frames has been ' +
'revoked with window.fence.disableUntrustedNetwork()');
} catch (e) {
assert_equals(e.name, 'OperationError');
assert_equals(e.message, 'sharedStorage.get() is not allowed in a ' +
'fenced frame until network access for it and all descendent frames ' +
'has been revoked with window.fence.disableUntrustedNetwork()');
}
}, [destination_url]);
}, 'sharedStorage.get() fails in a top-level fenced frame with network ' +
'disabled because a nested fenced frame has not disabled network yet.');
</script>
</body>