summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/secure-contexts
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/secure-contexts')
-rw-r--r--testing/web-platform/tests/secure-contexts/META.yml3
-rw-r--r--testing/web-platform/tests/secure-contexts/basic-dedicated-worker.html95
-rw-r--r--testing/web-platform/tests/secure-contexts/basic-dedicated-worker.https.html95
-rw-r--r--testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.html25
-rw-r--r--testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.html16
-rw-r--r--testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.js299
-rw-r--r--testing/web-platform/tests/secure-contexts/basic-shared-worker.html69
-rw-r--r--testing/web-platform/tests/secure-contexts/basic-shared-worker.https.html67
-rw-r--r--testing/web-platform/tests/secure-contexts/postMessage-helper.html1
-rw-r--r--testing/web-platform/tests/secure-contexts/postMessage-helper.https.html1
-rw-r--r--testing/web-platform/tests/secure-contexts/server-locations.sub.js17
-rw-r--r--testing/web-platform/tests/secure-contexts/shared-worker-insecure-first.https.html111
-rw-r--r--testing/web-platform/tests/secure-contexts/shared-worker-secure-first.https.html111
-rw-r--r--testing/web-platform/tests/secure-contexts/support/dedicated-worker-script.js1
-rw-r--r--testing/web-platform/tests/secure-contexts/support/https-subframe-dedicated.html33
-rw-r--r--testing/web-platform/tests/secure-contexts/support/https-subframe-shared.html32
-rw-r--r--testing/web-platform/tests/secure-contexts/support/parent-dedicated-worker-script.js9
-rw-r--r--testing/web-platform/tests/secure-contexts/support/parent-shared-worker-script.js13
-rw-r--r--testing/web-platform/tests/secure-contexts/support/shared-worker-insecure-popup.html15
-rw-r--r--testing/web-platform/tests/secure-contexts/support/shared-worker-script.js5
20 files changed, 1018 insertions, 0 deletions
diff --git a/testing/web-platform/tests/secure-contexts/META.yml b/testing/web-platform/tests/secure-contexts/META.yml
new file mode 100644
index 0000000000..e653716628
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/META.yml
@@ -0,0 +1,3 @@
+spec: https://w3c.github.io/webappsec-secure-contexts/
+suggested_reviewers:
+ - mikewest
diff --git a/testing/web-platform/tests/secure-contexts/basic-dedicated-worker.html b/testing/web-platform/tests/secure-contexts/basic-dedicated-worker.html
new file mode 100644
index 0000000000..ecd6138ac2
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/basic-dedicated-worker.html
@@ -0,0 +1,95 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test WorkerGlobalScope.isSecureContext for HTTP creator</title>
+ <meta name="help" href="https://w3c.github.io/webappsec-secure-contexts/#monkey-patching-global-object">
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src="server-locations.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ var t1 = async_test("HTTP worker");
+ var t2 = async_test("HTTPS worker");
+ var t3 = async_test("HTTP nested worker");
+ var t4 = async_test("HTTPS nested worker");
+ var t5 = async_test("HTTP worker from HTTPS subframe");
+ var t6 = async_test("HTTPS worker from HTTPS subframe");
+
+ var w1 = new Worker(http_dir + "support/dedicated-worker-script.js");
+ w1.onmessage = t1.step_func_done(function(e) {
+ assert_false(e.data);
+ });
+ w1.onerror = t1.step_func_done(function(e) {
+ assert_unreached("isSecureContext should be supported");
+ });
+
+ try {
+ var w2 = new Worker(https_dir + "support/dedicated-worker-script.js");
+ w2.onmessage = t2.step_func_done(function(e) {
+ assert_unreached("cross-origin workers should not be loaded");
+ });
+ w2.onerror = t2.step_func_done(function(e) {
+ e.preventDefault();
+ });
+ } catch (e) {
+ // Some browsers throw for cross-origin URLs. This violates the Worker spec,
+ // but isn't actually relevant to what we're testing here.
+ t2.done();
+ }
+
+ var w3 = new Worker(http_dir + "support/parent-dedicated-worker-script.js");
+ w3.onmessage = t3.step_func_done(function(e) {
+ assert_false(e.data);
+ });
+ w3.onerror = t3.step_func_done(function(e) {
+ assert_unreached("isSecureContext should be supported");
+ });
+
+ try {
+ var w4 = new Worker(https_dir + "support/parent-dedicated-worker-script.js");
+ w4.onmessage = t4.step_func_done(function(e) {
+ assert_unreached("cross-origin workers should not be loaded");
+ });
+ w4.onerror = t4.step_func_done(function(e) {
+ e.preventDefault();
+ });
+ } catch (e) {
+ // Some browsers throw for cross-origin URLs. This violates the Worker spec,
+ // but isn't actually relevant to what we're testing here.
+ t4.done();
+ }
+
+ onmessage = function(e) {
+ var data = e.data;
+ if (data.type == "http") {
+ t5.step(function() {
+ assert_true(data.error);
+ });
+ t5.done();
+ } else if (data.type == "https") {
+ t6.step(function() {
+ assert_false(data.error, "error");
+ assert_false(data.isSecureContext, "isSecureContext");
+ });
+ t6.done();
+ } else {
+ t5.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t5.done();
+ t6.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t6.done();
+ }
+ }
+
+ var ifr = document.createElement("iframe");
+ ifr.src = https_dir + "support/https-subframe-dedicated.html";
+ document.body.appendChild(ifr);
+ </script>
+ </body>
+</html>
+
diff --git a/testing/web-platform/tests/secure-contexts/basic-dedicated-worker.https.html b/testing/web-platform/tests/secure-contexts/basic-dedicated-worker.https.html
new file mode 100644
index 0000000000..e794755cdf
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/basic-dedicated-worker.https.html
@@ -0,0 +1,95 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test WorkerGlobalScope.isSecureContext for HTTPS creator</title>
+ <meta name="help" href="https://w3c.github.io/webappsec-secure-contexts/#monkey-patching-global-object">
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src="server-locations.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ var t1 = async_test("HTTP worker");
+ var t2 = async_test("HTTPS worker");
+ var t3 = async_test("HTTP nested worker");
+ var t4 = async_test("HTTPS nested worker");
+ var t5 = async_test("HTTP worker from HTTPS subframe");
+ var t6 = async_test("HTTPS worker from HTTPS subframe");
+
+ try {
+ var w1 = new Worker(http_dir + "support/dedicated-worker-script.js");
+ w1.onmessage = t1.step_func_done(function(e) {
+ assert_unreached("cross-origin workers should not be loaded");
+ });
+ w1.onerror = t1.step_func_done(function(e) {
+ e.preventDefault();
+ });
+ } catch (e) {
+ // Some browsers throw for cross-origin URLs. This violates the Worker spec,
+ // but isn't actually relevant to what we're testing here.
+ t1.done();
+ }
+
+ var w2 = new Worker(https_dir + "support/dedicated-worker-script.js");
+ w2.onmessage = t2.step_func_done(function(e) {
+ assert_true(e.data);
+ });
+ w2.onerror = t2.step_func_done(function(e) {
+ assert_unreached("isSecureContext should be supported");
+ });
+
+ try {
+ var w3 = new Worker(http_dir + "support/parent-dedicated-worker-script.js");
+ w3.onmessage = t3.step_func_done(function(e) {
+ assert_unreached("cross-origin workers should not be loaded");
+ });
+ w3.onerror = t3.step_func_done(function(e) {
+ e.preventDefault();
+ });
+ } catch (e) {
+ // Some browsers throw for cross-origin URLs. This violates the Worker spec,
+ // but isn't actually relevant to what we're testing here.
+ t3.done();
+ }
+
+ var w4 = new Worker(https_dir + "support/parent-dedicated-worker-script.js");
+ w4.onmessage = t4.step_func_done(function(e) {
+ assert_true(e.data);
+ });
+ w4.onerror = t4.step_func_done(function(e) {
+ assert_unreached("isSecureContext should be supported");
+ });
+
+ onmessage = function(e) {
+ var data = e.data;
+ if (data.type == "http") {
+ t5.step(function() {
+ assert_true(data.error);
+ });
+ t5.done();
+ } else if (data.type == "https") {
+ t6.step(function() {
+ assert_false(data.error);
+ assert_true(data.isSecureContext);
+ });
+ t6.done();
+ } else {
+ t5.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t5.done();
+ t6.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t6.done();
+ }
+ }
+
+ var ifr = document.createElement("iframe");
+ ifr.src = https_dir + "support/https-subframe-dedicated.html";
+ document.body.appendChild(ifr);
+ </script>
+ </body>
+</html>
+
diff --git a/testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.html b/testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.html
new file mode 100644
index 0000000000..ab3c443678
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test Window.isSecureContext for HTTP creator</title>
+ <meta name="help" href="https://w3c.github.io/webappsec-secure-contexts/#monkey-patching-global-object">
+ <meta name="author" title="Jonathan Watt" href="https://jwatt.org/">
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src="server-locations.sub.js"></script>
+ <script>
+
+// This file is the equivasent of the https version, but rather than
+// having a copy of its script file we figure out the URI of the script on the
+// https server and load it here.
+let script = document.createElement("script");
+script.setAttribute("src", https_dir + "basic-popup-and-iframe-tests.https.js");
+document.head.appendChild(script);
+
+ </script>
+ </head>
+ <body onload="begin();">
+ </body>
+</html>
+
diff --git a/testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.html b/testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.html
new file mode 100644
index 0000000000..a9c7f3c883
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test Window.isSecureContext for HTTPS creator</title>
+ <meta name="help" href="https://w3c.github.io/webappsec-secure-contexts/#monkey-patching-global-object">
+ <meta name="author" title="Jonathan Watt" href="https://jwatt.org/">
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src="server-locations.sub.js"></script>
+ <script src="basic-popup-and-iframe-tests.https.js"></script>
+ </head>
+ <body onload="begin();">
+ </body>
+</html>
+
diff --git a/testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.js b/testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.js
new file mode 100644
index 0000000000..661595c4d9
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/basic-popup-and-iframe-tests.https.js
@@ -0,0 +1,299 @@
+
+/**
+ * This test checks the Secure Context state of documents for various
+ * permutations of document URI types and loading methods.
+ *
+ * The hierarchy that is tested is:
+ *
+ * creator-doc > createe-doc
+ *
+ * The creator-doc is one of:
+ *
+ * http:
+ * https:
+ *
+ * The createe-doc is loaded as either a:
+ *
+ * popup
+ * iframe
+ * sandboxed-iframe
+ *
+ * into which we load and test:
+ *
+ * http:
+ * https:
+ * blob:
+ * javascript:
+ * about:blank
+ * initial about:blank
+ * srcdoc
+ *
+ * TODO once web-platform-tests supports it:
+ * - test http://localhost
+ * - test file:
+ */
+
+
+setup({explicit_done:true});
+
+
+const host_and_dirname = location.host +
+ location.pathname.substr(0, location.pathname.lastIndexOf("/") + 1);
+
+
+// Flags to indicate where document types should be loaded for testing:
+const eLoadInPopup = (1 << 0);
+const eLoadInUnsandboxedIframe = (1 << 1);
+const eLoadInSandboxedIframe = (1 << 2);
+const eLoadInEverything = eLoadInPopup | eLoadInUnsandboxedIframe | eLoadInSandboxedIframe;
+
+// Flags indicating if a document type is expected to be a Secure Context:
+const eSecureNo = 1;
+const eSecureIfNewWindow = 2;
+const eSecureIfCreatorSecure = 3;
+
+// Flags indicating how the result of a test is obtained:
+const eResultFromPostMessage = 1;
+const eResultFromExaminationOnLoad = 2;
+const eResultFromExaminationSync = 3;
+
+
+const loadTypes = [
+ new LoadType("an http: URI",
+ eLoadInEverything,
+ http_dir + "postMessage-helper.html",
+ eSecureNo,
+ eResultFromPostMessage),
+ new LoadType("an https: URI",
+ eLoadInEverything,
+ https_dir + "postMessage-helper.https.html",
+ eSecureIfNewWindow,
+ eResultFromPostMessage),
+ new LoadType("a blob: URI",
+ eLoadInEverything,
+ URL.createObjectURL(new Blob(["<script>(opener||parent).postMessage(isSecureContext, '*')</script>"], {type: "text/html"})),
+ eSecureIfCreatorSecure,
+ eResultFromPostMessage),
+ new LoadType("a srcdoc",
+ // popup not relevant:
+ eLoadInUnsandboxedIframe | eLoadInSandboxedIframe,
+ "<script>(opener||parent).postMessage(isSecureContext, '*')</script>",
+ eSecureIfNewWindow,
+ eResultFromPostMessage),
+ new LoadType("a javascript: URI",
+ // can't load in sandbox:
+ eLoadInUnsandboxedIframe | eLoadInPopup,
+ "javascript:(opener||parent).postMessage(isSecureContext, '*')",
+ eSecureIfCreatorSecure,
+ eResultFromPostMessage),
+ new LoadType("about:blank",
+ // can't obtain state if sandboxed:
+ eLoadInUnsandboxedIframe | eLoadInPopup,
+ "about:blank",
+ eSecureIfCreatorSecure,
+ eResultFromExaminationOnLoad),
+ new LoadType("initial about:blank",
+ // can't obtain state if sandboxed:
+ eLoadInUnsandboxedIframe | eLoadInPopup,
+ "about:blank", // we don't wait for this to load, so whatever
+ eSecureIfCreatorSecure,
+ eResultFromExaminationSync),
+ new LoadType("a data: URL",
+ // can't load in a top-level browsing context
+ eLoadInUnsandboxedIframe | eLoadInSandboxedIframe,
+ "data:text/html,<script>parent.postMessage(isSecureContext, '*')</script>",
+ eSecureIfCreatorSecure,
+ eResultFromPostMessage),
+];
+
+const loadTargets = [
+ new LoadTarget("an iframe", eLoadInUnsandboxedIframe),
+ new LoadTarget("a sandboxed iframe", eLoadInSandboxedIframe),
+ new LoadTarget("a popup", eLoadInPopup),
+];
+
+
+function LoadType(description, loadInFlags, uri, expectedSecureFlag, resultFrom) {
+ this.desc = description;
+ this.loadInFlags = loadInFlags;
+ this.uri = uri;
+ this.expectedSecureFlag = expectedSecureFlag;
+ this.resultFrom = resultFrom;
+}
+
+
+function LoadTarget(description, loadInFlag) {
+ this.desc = description;
+ this.loadInFlag = loadInFlag;
+}
+
+LoadTarget.prototype.open = function(loadType) {
+ let loadTarget = this;
+ this.currentTest.step(function() {
+ assert_true((loadTarget.loadInFlag & loadType.loadInFlags) != 0,
+ loadType.desc + " cannot be tested in " + loadTarget.desc);
+ });
+ if (this.loadInFlag == eLoadInUnsandboxedIframe) {
+ let iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ iframe[loadType.desc == "a srcdoc" ? "srcdoc" : "src"] = loadType.uri;
+ return iframe;
+ }
+ if (this.loadInFlag == eLoadInSandboxedIframe) {
+ let iframe = document.body.appendChild(document.createElement("iframe"));
+ iframe.setAttribute("sandbox", "allow-scripts");
+ iframe[loadType.desc == "a srcdoc" ? "srcdoc" : "src"] = loadType.uri;
+ return iframe;
+ }
+ if (this.loadInFlag == eLoadInPopup) {
+ return window.open(loadType.uri);
+ }
+ this.currentTest.step(function() {
+ assert_unreached("Unknown load type flag: " + loadInFlags);
+ });
+ return null;
+}
+
+LoadTarget.prototype.close = function(domTarget) {
+ if (this.loadInFlag == eLoadInUnsandboxedIframe ||
+ this.loadInFlag == eLoadInSandboxedIframe) {
+ domTarget.remove();
+ return;
+ }
+ if (this.loadInFlag == eLoadInPopup) {
+ domTarget.close();
+ return;
+ }
+ this.currentTest.step(function() {
+ assert_unreached("Unknown load type flag: " + loadInFlags);
+ });
+}
+
+LoadTarget.prototype.load_and_get_result_for = function(loadType) {
+ if (!(loadType.loadInFlags & this.loadInFlag)) {
+ return Promise.reject("not applicable");
+ }
+ if (!(this.loadInFlag & eLoadInPopup) &&
+ location.protocol == "https:" &&
+ loadType.uri.substr(0,5) == "http:") {
+ // Mixed content blocker will prevent this load
+ return Promise.reject("not applicable");
+ }
+ this.currentTest = async_test("Test Window.isSecureContext in " + this.desc +
+ " loading " + loadType.desc)
+ if (loadType.resultFrom == eResultFromExaminationSync) {
+ let domTarget = this.open(loadType);
+ let isFrame = domTarget instanceof HTMLIFrameElement;
+ let result = !isFrame ?
+ domTarget.isSecureContext : domTarget.contentWindow.isSecureContext;
+ this.close(domTarget);
+ return Promise.resolve({ result: result, isFrame: isFrame});
+ }
+ let target = this;
+ if (loadType.resultFrom == eResultFromExaminationOnLoad) {
+ return new Promise(function(resolve, reject) {
+ function handleLoad(event) {
+ clearTimeout(timer);
+ let isFrame = domTarget instanceof HTMLIFrameElement;
+ let result = !isFrame ?
+ domTarget.isSecureContext : domTarget.contentWindow.isSecureContext;
+ domTarget.removeEventListener("load", handleLoad);
+ target.close(domTarget);
+ resolve({ result: result, isFrame: isFrame});
+ }
+ let domTarget = target.open(loadType);
+ domTarget.addEventListener("load", handleLoad, false);
+
+ // Some browsers don't fire `load` events for `about:blank`. That's weird, but it also
+ // isn't what we're testing here.
+ let timer = setTimeout(handleLoad, 500);
+ });
+ }
+ if (loadType.resultFrom == eResultFromPostMessage) {
+ return new Promise(function(resolve, reject) {
+ function handleMessage(event) {
+ let isFrame = domTarget instanceof HTMLIFrameElement;
+ window.removeEventListener("message", handleMessage);
+ target.close(domTarget);
+ resolve({ result: event.data, isFrame: isFrame});
+ }
+ window.addEventListener("message", handleMessage, false);
+ let domTarget = target.open(loadType);
+ });
+ }
+ return Promise.reject("unexpected 'result from' type");
+}
+
+
+let current_type_index = -1;
+let current_target_index = 0;
+
+function run_next_test() {
+ current_type_index++;
+ if (current_type_index >= loadTypes.length) {
+ current_type_index = 0;
+ current_target_index++;
+ if (current_target_index >= loadTargets.length) {
+ done();
+ return; // all test permutations complete
+ }
+ }
+ let loadTarget = loadTargets[current_target_index];
+ let loadType = loadTypes[current_type_index];
+ loadTarget.load_and_get_result_for(loadType).then(
+ function(value) {
+ run_next_test_soon();
+ loadTarget.currentTest.step(function() {
+ // If the new context is always non-secure, the assertion is straightforward.
+ if (loadType.expectedSecureFlag == eSecureNo) {
+ assert_false(value.result, loadType.desc + " in " + loadTarget.desc + " should not create a Secure Context");
+ // If the new context is always secure if opened in a new window, and it's
+ // been opened in a new window, the assertion is likewise straightforward.
+ } else if (loadType.expectedSecureFlag == eSecureIfNewWindow && !value.isFrame) {
+ assert_true(value.result, loadType.desc + " in " + loadTarget.desc + " should create a secure context regardless of its creator's state.");
+ // Otherwise, we're either dealing with a context that's secure if and only
+ // if its creator context (e.g. this window) is secure.
+ } else if ((loadType.expectedSecureFlag == eSecureIfNewWindow && value.isFrame) ||
+ (loadType.expectedSecureFlag == eSecureIfCreatorSecure)) {
+ if (!window.isSecureContext) {
+ assert_false(value.result, loadType.desc + " in " + loadTarget.desc + " should not create a Secure Context when its creator is not a Secure Context.");
+ } else {
+ assert_true(value.result, loadType.desc + " in " + loadTarget.desc + " should create a Secure Context when its creator is a Secure Context");
+ }
+ } else {
+ assert_unreached(loadType.desc + " - unknown expected secure flag: " + expectedSecureFlag);
+ }
+ loadTarget.currentTest.done();
+ });
+ },
+ function(failReason) {
+ run_next_test_soon();
+ if (failReason == "not applicable") {
+ return;
+ }
+ loadTarget.currentTest.step(function() {
+ assert_unreached(loadType.desc + " - got unexpected rejected promise");
+ });
+ }
+ );
+}
+
+function run_next_test_soon() {
+ setTimeout(run_next_test, 0);
+}
+
+function begin() {
+ test(function() {
+ if (location.protocol == "http:") {
+ assert_false(isSecureContext,
+ "http: creator should not be a Secure Context");
+ } else if (location.protocol == "https:") {
+ assert_true(isSecureContext,
+ "https: creator should be a Secure Context");
+ } else {
+ assert_unreached("Unknown location.protocol");
+ }
+ });
+ run_next_test();
+}
+
diff --git a/testing/web-platform/tests/secure-contexts/basic-shared-worker.html b/testing/web-platform/tests/secure-contexts/basic-shared-worker.html
new file mode 100644
index 0000000000..76c28a36e4
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/basic-shared-worker.html
@@ -0,0 +1,69 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test SharedWorkerGlobalScope.isSecureContext for HTTP creator</title>
+ <meta name="help" href="https://w3c.github.io/webappsec-secure-contexts/#monkey-patching-global-object">
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src="server-locations.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ var t1 = async_test("Shared worker");
+ var t2 = async_test("Nested worker in shared worker");
+ var t3 = async_test("Shared worker from https subframe");
+ var t4 = async_test("Nested worker from shared worker from https subframe");
+ // Tests for SharedWorkers used from other workers (not supported right
+ // now) would go here.
+
+ t1.step(function() {
+ var w = new SharedWorker("support/shared-worker-script.js");
+ w.port.onmessage = t1.step_func_done(function(e) {
+ assert_false(e.data);
+ });
+ w.port.start();
+ });
+
+ t2.step(function() {
+ var w = new SharedWorker("support/parent-shared-worker-script.js");
+ w.port.onmessage = t2.step_func_done(function(e) {
+ assert_false(e.data);
+ });
+ w.port.start();
+ });
+
+ onmessage = function(e) {
+ var data = e.data;
+ if (data.type == "shared") {
+ t3.step(function() {
+ assert_false(data.exception);
+ assert_false(data.error);
+ assert_false(data.isSecureContext);
+ });
+ t3.done();
+ } else if (data.type == "nested") {
+ t4.step(function() {
+ assert_false(data.exception);
+ assert_false(data.error);
+ assert_false(data.isSecureContext);
+ });
+ t4.done();
+ } else {
+ t3.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t3.done();
+ t4.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t4.done();
+ }
+ }
+
+ var ifr = document.createElement("iframe");
+ ifr.src = https_dir2 + "support/https-subframe-shared.html";
+ document.body.appendChild(ifr);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/secure-contexts/basic-shared-worker.https.html b/testing/web-platform/tests/secure-contexts/basic-shared-worker.https.html
new file mode 100644
index 0000000000..e7c78383a8
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/basic-shared-worker.https.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test SharedWorkerGlobalScope.isSecureContext for HTTP creator</title>
+ <meta name="help" href="https://w3c.github.io/webappsec-secure-contexts/#monkey-patching-global-object">
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src="server-locations.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ var t1 = async_test("Shared worker");
+ var t2 = async_test("Nested worker in shared worker");
+ var t3 = async_test("Shared worker from https subframe");
+ var t4 = async_test("Nested worker from shared worker from https subframe");
+
+ t1.step(function() {
+ var w = new SharedWorker("support/shared-worker-script.js");
+ w.port.onmessage = t1.step_func_done(function(e) {
+ assert_true(e.data);
+ });
+ w.port.start();
+ });
+
+ t2.step(function() {
+ var w = new SharedWorker("support/parent-shared-worker-script.js");
+ w.port.onmessage = t2.step_func_done(function(e) {
+ assert_true(e.data);
+ });
+ w.port.start();
+ });
+
+ onmessage = function(e) {
+ var data = e.data;
+ if (data.type == "shared") {
+ t3.step(function() {
+ assert_false(data.exception);
+ assert_false(data.error);
+ assert_true(data.isSecureContext);
+ });
+ t3.done();
+ } else if (data.type == "nested") {
+ t4.step(function() {
+ assert_false(data.exception);
+ assert_false(data.error);
+ assert_true(data.isSecureContext);
+ });
+ t4.done();
+ } else {
+ t3.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t3.done();
+ t4.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t4.done();
+ }
+ }
+
+ var ifr = document.createElement("iframe");
+ ifr.src = https_dir3 + "support/https-subframe-shared.html";
+ document.body.appendChild(ifr);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/secure-contexts/postMessage-helper.html b/testing/web-platform/tests/secure-contexts/postMessage-helper.html
new file mode 100644
index 0000000000..8971c86b27
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/postMessage-helper.html
@@ -0,0 +1 @@
+<script>(opener||parent).postMessage(isSecureContext, '*')</script>
diff --git a/testing/web-platform/tests/secure-contexts/postMessage-helper.https.html b/testing/web-platform/tests/secure-contexts/postMessage-helper.https.html
new file mode 100644
index 0000000000..8971c86b27
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/postMessage-helper.https.html
@@ -0,0 +1 @@
+<script>(opener||parent).postMessage(isSecureContext, '*')</script>
diff --git a/testing/web-platform/tests/secure-contexts/server-locations.sub.js b/testing/web-platform/tests/secure-contexts/server-locations.sub.js
new file mode 100644
index 0000000000..6b29c5328c
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/server-locations.sub.js
@@ -0,0 +1,17 @@
+var https_dir = "https://{{location[hostname]}}:{{ports[https][0]}}{{location[path]}}";
+https_dir = https_dir.substr(0, https_dir.lastIndexOf("/") + 1);
+
+var http_dir = "http://{{location[hostname]}}:{{ports[http][0]}}{{location[path]}}";
+http_dir = http_dir.substr(0, http_dir.lastIndexOf("/") + 1);
+
+var https_dir2 = "https://{{domains[www]}}:{{ports[https][0]}}{{location[path]}}";
+https_dir2 = https_dir2.substr(0, https_dir2.lastIndexOf("/") + 1);
+
+var https_dir3 = "https://{{domains[www1]}}:{{ports[https][0]}}{{location[path]}}";
+https_dir3 = https_dir3.substr(0, https_dir3.lastIndexOf("/") + 1);
+
+var https_dir4 = "https://{{domains[www2]}}:{{ports[https][0]}}{{location[path]}}";
+https_dir4 = https_dir4.substr(0, https_dir4.lastIndexOf("/") + 1);
+
+var https_dir5 = "https://{{domains[élève]}}:{{ports[https][0]}}{{location[path]}}";
+https_dir5 = https_dir5.substr(0, https_dir5.lastIndexOf("/") + 1);
diff --git a/testing/web-platform/tests/secure-contexts/shared-worker-insecure-first.https.html b/testing/web-platform/tests/secure-contexts/shared-worker-insecure-first.https.html
new file mode 100644
index 0000000000..00db9517d0
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/shared-worker-insecure-first.https.html
@@ -0,0 +1,111 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test SharedWorkerGlobalScope.isSecureContext for HTTP creator</title>
+ <meta name="help" href="https://w3c.github.io/webappsec-secure-contexts/#monkey-patching-global-object">
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src="server-locations.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ /*
+ * The goal of this test is to check that we do the right thing if the
+ * same SharedWorker is used first from an insecure context and then from
+ * a secure context.
+ *
+ * To do this, we first open an insecure (http) popup, which loads a
+ * subframe that is same-origin with us but not a secure context, since
+ * its parent is http, not https. Then this subframe loads a SharedWorker
+ * and communicates back to us whether that worker and a child dedicated
+ * worker it spawns think they are secure contexts. Async tests t3 and t4
+ * track these two workers.
+ *
+ * After we have heard from both workers in the popup, we directly load
+ * the same exact subframe ourselves and see what the workers in it
+ * report. Async tests t1 and t2 track these two workers.
+ */
+ var t1 = async_test("Shared worker in subframe");
+ var t2 = async_test("Nested worker in shared worker in subframe");
+ var t3 = async_test("Shared worker in popup");
+ var t4 = async_test("Nested worker from shared worker in popup");
+
+ var messageCount = 0;
+ var popup = null;
+ onmessage = function(e) {
+ ++messageCount;
+ // Make sure to not close the popup until we've run the iframe part of
+ // the test! We need to keep those shared workers alive.
+ if (messageCount == 4 && popup) {
+ popup.close();
+ }
+ var data = e.data;
+ if (data.type == "shared") {
+ // This is a message from our shared worker; check whether it's the
+ // one in the popup or in our subframe.
+ if (data.fromPopup) {
+ t3.step(function() {
+ assert_false(data.exception, "SharedWorker should not throw an exception.");
+ assert_false(data.error, "SharedWorker connection should not generate an error.");
+ assert_false(data.isSecureContext, "SharedWorker is not a secure context");
+ });
+ t3.done();
+ } else {
+ t1.step(function() {
+ assert_false(data.exception, "SharedWorker should not throw an exception.");
+ assert_true(data.error, "SharedWorker connection should generate an error.");
+ });
+ t1.done();
+ }
+ } else if (data.type == "nested") {
+ // This is a message from our shared worker's nested dedicated worker;
+ // check whether it's the one in the popup or in our subframe.
+ if (data.fromPopup) {
+ t4.step(function() {
+ assert_false(data.exception, "SharedWorker should not throw an exception.");
+ assert_false(data.error, "SharedWorker connection should not generate an error.");
+ assert_false(data.isSecureContext);
+ });
+ t4.done();
+ } else {
+ t2.step(function() {
+ assert_false(data.exception, "SharedWorker should not throw an exception.");
+ assert_true(data.error, "SharedWorker connection should generate an error.");
+ });
+ t2.done();
+ }
+ } else {
+ if (popup) {
+ popup.close();
+ }
+ t1.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t1.done();
+ t2.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t2.done();
+ t3.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t3.done();
+ t4.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t4.done();
+ }
+
+ if (messageCount == 2) {
+ // Got both messages from our popup; time to create our child.
+ var ifr = document.createElement("iframe");
+ ifr.src = https_dir5 + "support/https-subframe-shared.html";
+ document.body.appendChild(ifr);
+ }
+ }
+
+ popup = window.open(http_dir + "support/shared-worker-insecure-popup.html?https_dir5");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/secure-contexts/shared-worker-secure-first.https.html b/testing/web-platform/tests/secure-contexts/shared-worker-secure-first.https.html
new file mode 100644
index 0000000000..ce97a628a0
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/shared-worker-secure-first.https.html
@@ -0,0 +1,111 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test SharedWorkerGlobalScope.isSecureContext for HTTP creator</title>
+ <meta name="help" href="https://w3c.github.io/webappsec-secure-contexts/#monkey-patching-global-object">
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src="server-locations.sub.js"></script>
+ </head>
+ <body>
+ <script>
+ /*
+ * The goal of this test is to check that we do the right thing if the
+ * same SharedWorker is used first from an secure context and then from
+ * an insecure context.
+ *
+ * To do this, we load a subframe which loads a SharedWorker
+ * and communicates back to us whether that worker and a child dedicated
+ * worker it spawns think they are secure contexts. Async tests t1 and t2
+ * track these two workers.
+ *
+ * After we have heard from both workers in the subframe, we open an
+ * insecure (http) popup, which loads the same exact subframe. This
+ * subframe is still is same-origin with
+ * us but not a secure context, since its parent is http, not https. Then
+ * we wait to hear about the status of the workers in the popup's
+ * subframe. Async tests t3 and t4 track these two workers.
+ *
+ */
+ var t1 = async_test("Shared worker in subframe");
+ var t2 = async_test("Nested worker in shared worker in subframe");
+ var t3 = async_test("Shared worker in popup");
+ var t4 = async_test("Nested worker from shared worker in popup");
+
+ var messageCount = 0;
+ var popup = null;
+ onmessage = function(e) {
+ ++messageCount;
+ if (messageCount == 4 && popup) {
+ popup.close();
+ }
+ var data = e.data;
+ if (data.type == "shared") {
+ // This is a message from our shared worker; check whether it's the
+ // one in the popup or in our subframe.
+ if (data.fromPopup) {
+ t3.step(function() {
+ assert_false(data.exception, "No exception should be present.");
+ assert_true(data.error, "SharedWorker connection should error out.");
+ });
+ t3.done();
+ } else {
+ t1.step(function() {
+ assert_false(data.exception, "SharedWorker should not throw an exception.");
+ assert_false(data.error, "SharedWorker connection should not generate an error.");
+ assert_true(data.isSecureContext, "SharedWorker is a secure context");
+ });
+ t1.done();
+ }
+ } else if (data.type == "nested") {
+ // This is a message from our shared worker's nested dedicated worker;
+ // check whether it's the one in the popup or in our subframe.
+ if (data.fromPopup) {
+ t4.step(function() {
+ assert_false(data.exception, "No exception should be present.");
+ assert_true(data.error, "SharedWorker connection should error out.");
+ });
+ t4.done();
+ } else {
+ t2.step(function() {
+ assert_false(data.exception, "SharedWorker should not throw an exception.");
+ assert_false(data.error, "SharedWorker connection should not generate an error.");
+ assert_true(data.isSecureContext, "SharedWorker is a secure context");
+ });
+ t2.done();
+ }
+ } else {
+ if (popup) {
+ popup.close();
+ }
+ t1.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t1.done();
+ t2.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t2.done();
+ t3.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t3.done();
+ t4.step(function() {
+ assert_unreached("Unknown message");
+ });
+ t4.done();
+ }
+
+ if (messageCount == 2) {
+ // Got both messages from our child; time to open our popup
+ popup = window.open(http_dir + "support/shared-worker-insecure-popup.html?https_dir4");
+ }
+ }
+
+ var ifr = document.createElement("iframe");
+ ifr.src = https_dir4 + "support/https-subframe-shared.html";
+ document.body.appendChild(ifr);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/secure-contexts/support/dedicated-worker-script.js b/testing/web-platform/tests/secure-contexts/support/dedicated-worker-script.js
new file mode 100644
index 0000000000..69ffdf3442
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/support/dedicated-worker-script.js
@@ -0,0 +1 @@
+postMessage(isSecureContext);
diff --git a/testing/web-platform/tests/secure-contexts/support/https-subframe-dedicated.html b/testing/web-platform/tests/secure-contexts/support/https-subframe-dedicated.html
new file mode 100644
index 0000000000..bcf27879e8
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/support/https-subframe-dedicated.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<script src="../server-locations.sub.js"></script>
+<script>
+ try {
+ var w1 = new Worker(http_dir + "support/dedicated-worker-script.js");
+ w1.onmessage = function(e) {
+ parent.postMessage({ type: "http", error: false,
+ isSecureContext: e.data }, "*");
+ };
+ w1.onerror = function(e) {
+ parent.postMessage({ type: "http", error: true }, "*");
+ };
+ } catch (e) {
+ // Some browsers throw for cross-origin URLs. This violates the Worker spec,
+ // but isn't actually relevant to what we're testing here.
+ parent.postMessage({ type: "http", error: true }, "*");
+ }
+
+ try {
+ var w2 = new Worker(https_dir + "support/dedicated-worker-script.js");
+ w2.onmessage = function(e) {
+ parent.postMessage({ type: "https", error: false,
+ isSecureContext: e.data }, "*");
+ };
+ w2.onerror = function(e) {
+ parent.postMessage({ type: "https", error: true }, "*");
+ }
+ } catch (e) {
+ // Some browsers throw for cross-origin URLs. This violates the Worker spec,
+ // but isn't actually relevant to what we're testing here.
+ parent.postMessage({ type: "https", error: true }, "*");
+ }
+</script>
diff --git a/testing/web-platform/tests/secure-contexts/support/https-subframe-shared.html b/testing/web-platform/tests/secure-contexts/support/https-subframe-shared.html
new file mode 100644
index 0000000000..5ae7cde5b0
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/support/https-subframe-shared.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<script>
+ try {
+ var w = new SharedWorker("shared-worker-script.js");
+ w.port.onmessage = function(e) {
+ parent.postMessage({ type: "shared", error: false, exception: false,
+ isSecureContext: e.data }, "*");
+ };
+ w.onerror = function(e) {
+ parent.postMessage({ type: "shared", error: true, exception: false },
+ "*");
+ }
+ w.port.start();
+ } catch (e) {
+ parent.postMessage({ type: "shared", exception: true }, "*");
+ }
+
+ try {
+ var w = new SharedWorker("parent-shared-worker-script.js");
+ w.port.onmessage = function(e) {
+ parent.postMessage({ type: "nested", error: false, exception: false,
+ isSecureContext: e.data }, "*");
+ };
+ w.onerror = function(e) {
+ parent.postMessage({ type: "nested", error: true, exception: false },
+ "*");
+ }
+ w.port.start();
+ } catch (e) {
+ parent.postMessage({ type: "nested", exception: true }, "*");
+ }
+</script>
diff --git a/testing/web-platform/tests/secure-contexts/support/parent-dedicated-worker-script.js b/testing/web-platform/tests/secure-contexts/support/parent-dedicated-worker-script.js
new file mode 100644
index 0000000000..2b67432384
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/support/parent-dedicated-worker-script.js
@@ -0,0 +1,9 @@
+// If nested workers aren't supported, punt:
+if (typeof Worker != "undefined") {
+ var w = new Worker("dedicated-worker-script.js");
+ w.onmessage = function (e) {
+ postMessage(e.data);
+ }
+} else {
+ postMessage("Nested workers not supported.");
+}
diff --git a/testing/web-platform/tests/secure-contexts/support/parent-shared-worker-script.js b/testing/web-platform/tests/secure-contexts/support/parent-shared-worker-script.js
new file mode 100644
index 0000000000..083564a054
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/support/parent-shared-worker-script.js
@@ -0,0 +1,13 @@
+addEventListener("connect", function (e) {
+ var port = e.ports[0];
+ port.start();
+ // If nested workers aren't supported, punt:
+ if (typeof Worker != "undefined") {
+ var w = new Worker("dedicated-worker-script.js");
+ w.onmessage = function (e) {
+ port.postMessage(e.data);
+ }
+ } else {
+ port.postMessage("Nested workers not supported.");
+ }
+});
diff --git a/testing/web-platform/tests/secure-contexts/support/shared-worker-insecure-popup.html b/testing/web-platform/tests/secure-contexts/support/shared-worker-insecure-popup.html
new file mode 100644
index 0000000000..740679dc4f
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/support/shared-worker-insecure-popup.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script src="../server-locations.sub.js"></script>
+<body>
+ <script>
+ var url = self[location.search.substr(1)] + "support/https-subframe-shared.html";
+ onmessage = function(e) {
+ var data = e.data;
+ data.fromPopup = true;
+ opener.postMessage(data, "*");
+ }
+ var ifr = document.createElement("iframe");
+ ifr.src = url;
+ document.body.appendChild(ifr);
+ </script>
+</body>
diff --git a/testing/web-platform/tests/secure-contexts/support/shared-worker-script.js b/testing/web-platform/tests/secure-contexts/support/shared-worker-script.js
new file mode 100644
index 0000000000..faed70a5c8
--- /dev/null
+++ b/testing/web-platform/tests/secure-contexts/support/shared-worker-script.js
@@ -0,0 +1,5 @@
+addEventListener("connect", function (e) {
+ var port = e.ports[0];
+ port.start();
+ port.postMessage(isSecureContext);
+});