Skip to content

Commit

Permalink
Add data URL worker IDBFactory opaque origin tests
Browse files Browse the repository at this point in the history
These tests verify that IDBFactory methods that should
throw in opaque origin contexts correctly do so when
called from data URL dedicated and shared workers.

Bug: None
Change-Id: I1a7e806ac464d6de1932d9952072217a9ee91bbb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3631352
Commit-Queue: Andrew Williams <awillia@google.com>
Reviewed-by: Ari Chivukula <arichiv@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1001141}
  • Loading branch information
recvfrom authored and Chromium LUCI CQ committed May 9, 2022
1 parent 6bb2523 commit 07b3477
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,46 +17,81 @@
});
}

function wait_for_message(iframe) {
function wait_for_message(recipient, source) {
return new Promise(resolve => {
self.addEventListener('message', function listener(e) {
if (e.source === iframe.contentWindow) {
recipient.onmessage = function listener(e) {
if (e.source === source) {
resolve(e.data);
self.removeEventListener('message', listener);
recipient.removeEventListener('message', listener);
}
});
});
};
})
}

const script =
'<script>' +
' window.onmessage = () => {' +
const test_code =
' const handler = (reply) => {' +
' try { ' +
' if (!indexedDB || !indexedDB.databases) {' +
' window.parent.postMessage({result: "indexedDB.databases undefined"}, "*")' +
' reply({result: "indexedDB.databases undefined"});' +
' }' +
' indexedDB.databases().then(' +
' () => window.parent.postMessage({result: "no exception"}, "*"),' +
' ex => window.parent.postMessage({result: ex.name}, "*"));' +
' () => reply({result: "no exception"}),' +
' ex => reply({result: ex.name}));' +
' } catch(e) { ' +
' window.parent.postMessage({result: e.name + " thrown, not rejected"}, "*")' +
' }'+
' reply({result: e.name + " thrown, not rejected"});' +
' }' +
' };';

const iframe_script =
'<script>' +
test_code +
' window.onmessage = () => {' +
' handler(msg => window.parent.postMessage(msg, "*"));' +
' };' +
'<\/script>';

promise_test(async t => {
const iframe = await load_iframe(script);
const iframe = await load_iframe(iframe_script);
iframe.contentWindow.postMessage({}, '*');
const message = await wait_for_message(iframe);
const message = await wait_for_message(self, iframe.contentWindow);
assert_equals(message.result, 'no exception',
'IDBFactory.databases() should not reject');
}, 'IDBFactory.databases() in non-sandboxed iframe should not reject');

promise_test(async t => {
const iframe = await load_iframe(script, 'allow-scripts');
const iframe = await load_iframe(iframe_script, 'allow-scripts');
iframe.contentWindow.postMessage({}, '*');
const message = await wait_for_message(iframe);
const message = await wait_for_message(self, iframe.contentWindow);
assert_equals(message.result, 'SecurityError',
'Promise should be rejected with SecurityError');
}, 'IDBFactory.databases() in sandboxed iframe should reject');

const worker_script = `
${test_code}
// For dedicated workers:
self.addEventListener("message", () => handler(self.postMessage));
// For shared workers:
self.addEventListener("connect", (e) => {
var port = e.ports[0];
handler(msg => port.postMessage(msg));
});
`;
const worker_data_url = "data:,".concat(encodeURIComponent(worker_script));

promise_test(async t => {
let worker = new Worker(worker_data_url);
t.add_cleanup(() => worker.terminate());
worker.postMessage({});
const message = await wait_for_message(worker, null);
assert_equals(message.result, 'SecurityError',
'Promise should be rejected with SecurityError');
}, 'IDBFactory.databases() in data URL dedicated worker should throw SecurityError');

promise_test(async t => {
let worker = new SharedWorker(worker_data_url, 'idb_databases_opaque');
worker.port.postMessage({});
const message = await wait_for_message(worker.port, null);
assert_equals(message.result, 'SecurityError',
'Promise should be rejected with SecurityError');
}, 'IDBFactory.databases() in data URL shared worker should throw SecurityError');
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,40 @@
});
}

function wait_for_message(iframe) {
function wait_for_message(recipient, source) {
return new Promise(resolve => {
self.addEventListener('message', function listener(e) {
if (e.source === iframe.contentWindow) {
recipient.onmessage = function listener(e) {
if (e.source === source) {
resolve(e.data);
self.removeEventListener('message', listener);
recipient.removeEventListener('message', listener);
}
});
});
};
})
}

const script =
'<script>' +
' window.onmessage = () => {' +
const test_code =
' const handler = (reply) => {' +
' try {' +
' const r = indexedDB.deleteDatabase("opaque-origin-test");' +
' window.parent.postMessage({result: "no exception"}, "*");' +
' reply({result: "no exception"});' +
' } catch (ex) {' +
' window.parent.postMessage({result: ex.name}, "*");' +
' reply({result: ex.name});' +
' };' +
' };';

const iframe_script =
'<script>' +
test_code +
' window.onmessage = () => {' +
' handler(msg => window.parent.postMessage(msg, "*"));' +
' };' +
'<\/script>';

promise_test(t => {
return load_iframe(script)
return load_iframe(iframe_script)
.then(iframe => {
iframe.contentWindow.postMessage({}, '*');
return wait_for_message(iframe);
return wait_for_message(self, iframe.contentWindow);
})
.then(message => {
assert_equals(message.result, 'no exception',
Expand All @@ -53,14 +59,43 @@
}, 'IDBFactory.deleteDatabase() in non-sandboxed iframe should not throw');

promise_test(t => {
return load_iframe(script, 'allow-scripts')
return load_iframe(iframe_script, 'allow-scripts')
.then(iframe => {
iframe.contentWindow.postMessage({}, '*');
return wait_for_message(iframe);
return wait_for_message(self, iframe.contentWindow);
})
.then(message => {
assert_equals(message.result, 'SecurityError',
'Exception should be SecurityError');
});
}, 'IDBFactory.deleteDatabase() in sandboxed iframe should throw SecurityError');

const worker_script = `
${test_code}
// For dedicated workers:
self.addEventListener("message", () => handler(self.postMessage));
// For shared workers:
self.addEventListener("connect", (e) => {
var port = e.ports[0];
handler(msg => port.postMessage(msg));
});
`;
const worker_data_url = "data:,".concat(encodeURIComponent(worker_script));

promise_test(async t => {
let worker = new Worker(worker_data_url);
t.add_cleanup(() => worker.terminate());
worker.postMessage({});
const message = await wait_for_message(worker, null);
assert_equals(message.result, 'SecurityError',
'Promise should be rejected with SecurityError');
}, 'IDBFactory.deleteDatabase() in data URL dedicated worker should throw SecurityError');

promise_test(async t => {
let worker = new SharedWorker(worker_data_url, 'idb_deleteDatabase_opaque');
worker.port.postMessage({});
const message = await wait_for_message(worker.port, null);
assert_equals(message.result, 'SecurityError',
'Promise should be rejected with SecurityError');
}, 'IDBFactory.deleteDatabase() in data URL shared worker should throw SecurityError');
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,44 @@
});
}

function wait_for_message(iframe) {
function wait_for_message(recipient, source) {
return new Promise(resolve => {
self.addEventListener('message', function listener(e) {
if (e.source === iframe.contentWindow) {
recipient.onmessage = function listener(e) {
if (e.source === source) {
resolve(e.data);
self.removeEventListener('message', listener);
recipient.removeEventListener('message', listener);
}
});
});
};
})
}

const script =
'<script>' +
' window.onmessage = () => {' +
const test_code =
' const handler = (reply) => {' +
' try {' +
' indexedDB.deleteDatabase("opaque-origin-test");' +
' } catch {}' +
' try {' +
' const r = indexedDB.open("opaque-origin-test");' +
' r.onupgradeneeded = () => { r.transaction.abort(); };' +
' window.parent.postMessage({result: "no exception"}, "*");' +
' reply({result: "no exception"});' +
' } catch (ex) {' +
' window.parent.postMessage({result: ex.name}, "*");' +
' reply({result: ex.name});' +
' };' +
' };';

const iframe_script =
'<script>' +
test_code +
' window.onmessage = () => {' +
' handler(msg => window.parent.postMessage(msg, "*"));' +
' };' +
'<\/script>';

promise_test(t => {
return load_iframe(script)
return load_iframe(iframe_script)
.then(iframe => {
iframe.contentWindow.postMessage({}, '*');
return wait_for_message(iframe);
return wait_for_message(self, iframe.contentWindow);
})
.then(message => {
assert_equals(message.result, 'no exception',
Expand All @@ -57,14 +63,43 @@
}, 'IDBFactory.open() in non-sandboxed iframe should not throw');

promise_test(t => {
return load_iframe(script, 'allow-scripts')
return load_iframe(iframe_script, 'allow-scripts')
.then(iframe => {
iframe.contentWindow.postMessage({}, '*');
return wait_for_message(iframe);
return wait_for_message(self, iframe.contentWindow);
})
.then(message => {
assert_equals(message.result, 'SecurityError',
'Exception should be SecurityError');
});
}, 'IDBFactory.open() in sandboxed iframe should throw SecurityError');

const worker_script = `
${test_code}
// For dedicated workers:
self.addEventListener("message", () => handler(self.postMessage));
// For shared workers:
self.addEventListener("connect", (e) => {
var port = e.ports[0];
handler(msg => port.postMessage(msg));
});
`;
const worker_data_url = "data:,".concat(encodeURIComponent(worker_script));

promise_test(async t => {
let worker = new Worker(worker_data_url);
t.add_cleanup(() => worker.terminate());
worker.postMessage({});
const message = await wait_for_message(worker, null);
assert_equals(message.result, 'SecurityError',
'Promise should be rejected with SecurityError');
}, 'IDBFactory.open() in data URL dedicated workers should throw SecurityError');

promise_test(async t => {
let worker = new SharedWorker(worker_data_url, 'idb_open_opaque');
worker.port.postMessage({});
const message = await wait_for_message(worker.port, null);
assert_equals(message.result, 'SecurityError',
'Promise should be rejected with SecurityError');
}, 'IDBFactory.open() in data URL shared workers should throw SecurityError');
</script>

0 comments on commit 07b3477

Please sign in to comment.