service worker: Upstream sandboxed iframe test to WPT.
Bug: 688116, 532855, 486308
Change-Id: I0cda49c9072099fa706988c6a1aa789456af2c1e
Reviewed-on: https://chromium-review.googlesource.com/765564
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
Commit-Queue: Matt Falkenhagen <falken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#515885}
diff --git a/service-workers/service-worker/resources/sandboxed-iframe-navigator-serviceworker-iframe.html b/service-workers/service-worker/resources/sandboxed-iframe-navigator-serviceworker-iframe.html
new file mode 100644
index 0000000..1d682e4
--- /dev/null
+++ b/service-workers/service-worker/resources/sandboxed-iframe-navigator-serviceworker-iframe.html
@@ -0,0 +1,25 @@
+<script>
+window.onmessage = function(e) {
+ const id = e.data['id'];
+ try {
+ var sw = window.navigator.serviceWorker;
+ } catch (e) {
+ window.top.postMessage({
+ id: id,
+ result: 'navigator.serviceWorker failed: ' + e.name
+ }, '*');
+ return;
+ }
+
+ window.navigator.serviceWorker.getRegistration()
+ .then(function() {
+ window.top.postMessage({id: id, result:'ok'}, '*');
+ })
+ .catch(function(e) {
+ window.top.postMessage({
+ id: id,
+ result: 'getRegistration() failed: ' + e.name
+ }, '*');
+ });
+};
+</script>
diff --git a/service-workers/service-worker/sandboxed-iframe-navigator-serviceworker.https.html b/service-workers/service-worker/sandboxed-iframe-navigator-serviceworker.https.html
new file mode 100644
index 0000000..a58525f
--- /dev/null
+++ b/service-workers/service-worker/sandboxed-iframe-navigator-serviceworker.https.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<title>Accessing navigator.serviceWorker in sandboxed iframe.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<body>
+<script>
+var lastCallbackId = 0;
+var callbacks = {};
+function postMessageAndWaitResult(frame) {
+ return new Promise(function(resolve) {
+ var id = ++lastCallbackId;
+ callbacks[id] = resolve;
+ frame.contentWindow.postMessage({id:id}, '*');
+ });
+}
+
+window.onmessage = function(e) {
+ message = e.data;
+ var id = message['id'];
+ var callback = callbacks[id];
+ delete callbacks[id];
+ callback(message.result);
+};
+
+promise_test(function(t) {
+ var url = 'resources/sandboxed-iframe-navigator-serviceworker-iframe.html';
+ var frame;
+ return with_iframe(url)
+ .then(function(f) {
+ frame = f;
+ add_result_callback(() => { frame.remove(); });
+ return postMessageAndWaitResult(f);
+ })
+ .then(function(result) {
+ assert_equals(result, 'ok');
+ });
+ }, 'Accessing navigator.serviceWorker in normal iframe should not throw.');
+
+promise_test(function(t) {
+ var url = 'resources/sandboxed-iframe-navigator-serviceworker-iframe.html';
+ var frame;
+ return with_sandboxed_iframe(url, 'allow-scripts')
+ .then(function(f) {
+ frame = f;
+ add_result_callback(() => { frame.remove(); });
+ return postMessageAndWaitResult(f);
+ })
+ .then(function(result) {
+ assert_equals(
+ result,
+ 'navigator.serviceWorker failed: SecurityError');
+ });
+ }, 'Accessing navigator.serviceWorker in sandboxed iframe should throw.');
+
+promise_test(function(t) {
+ var url = 'resources/sandboxed-iframe-navigator-serviceworker-iframe.html';
+ var frame;
+ return with_sandboxed_iframe(url, 'allow-scripts allow-same-origin')
+ .then(function(f) {
+ frame = f;
+ add_result_callback(() => { frame.remove(); });
+ return postMessageAndWaitResult(f);
+ })
+ .then(function(result) {
+ assert_equals(result, 'ok');
+ });
+ },
+ 'Accessing navigator.serviceWorker in sandboxed iframe with ' +
+ 'allow-same-origin flag should not throw.');
+
+promise_test(function(t) {
+ var url = 'resources/sandboxed-iframe-navigator-serviceworker-iframe.html';
+ var frame;
+ return new Promise(function(resolve) {
+ frame = document.createElement('iframe');
+ add_result_callback(() => { frame.remove(); });
+ frame.sandbox = '';
+ frame.src = url;
+ frame.onload = resolve;
+ document.body.appendChild(frame);
+ // Switch the sandbox attribute while loading the iframe.
+ frame.sandbox = 'allow-scripts allow-same-origin';
+ })
+ .then(function() {
+ return postMessageAndWaitResult(frame)
+ })
+ .then(function(result) {
+ // The HTML spec seems to say that changing the sandbox attribute
+ // after the iframe is inserted into its parent document does not
+ // affect the sandboxing. If that's true, the frame should still
+ // act as if it still doesn't have
+ // 'allow-scripts allow-same-origin' set and throw a SecurityError.
+ //
+ // 1) From Section 4.8.5 "The iframe element":
+ // "When an iframe element is inserted into a document that has a
+ // browsing context, the user agent must create a new browsing
+ // context..."
+ // 2) "Create a new browsing context" expands to Section 7.1
+ // "Browsing contexts", which includes creating a Document and
+ // "Implement the sandboxing for document."
+ // 3) "Implement the sandboxing" expands to Section 7.6 "Sandboxing",
+ // which includes "populate document's active sandboxing flag set".
+ //
+ // It's not clear whether navigation subsequently creates a new
+ // Document, but I'm assuming it wouldn't.
+ // https://html.spec.whatwg.org/multipage/embedded-content.html#attr-iframe-sandbox
+ assert_equals(
+ result,
+ 'navigator.serviceWorker failed: SecurityError');
+ });
+ }, 'Switching iframe sandbox attribute while loading the iframe');
+
+</script>
+</body>