Bug 1404910 - WebSocket should consider the corrent top-level window principal, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 04 Oct 2017 14:18:19 +0200
changeset 385843 c543c0a50db700883b57c052710c97b5ef731e1f
parent 385842 396ff2a152d77a0c28f09fefc8b0a96659f2d4ba
child 385844 381e276f35340f607ad5b5df2f053a6529b1c8cc
push id32669
push userarchaeopteryx@coole-files.de
push dateThu, 12 Oct 2017 21:58:56 +0000
treeherdermozilla-central@25aad10380b1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1404910
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1404910 - WebSocket should consider the corrent top-level window principal, r=smaug
dom/base/WebSocket.cpp
dom/base/test/iframe_webSocket_sandbox.html
dom/base/test/mochitest.ini
dom/base/test/test_webSocket_sandbox.html
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -1661,28 +1661,27 @@ WebSocketImpl::Init(JSContext* aCx,
       nsCOMPtr<nsIGlobalObject> globalObject(GetEntryGlobal());
       if (globalObject) {
         principal = globalObject->PrincipalOrNull();
       }
 
       nsCOMPtr<nsPIDOMWindowInner> innerWindow;
 
       while (true) {
-        if (principal) {
-          bool isNullPrincipal = true;
-          isNullPrincipal = principal->GetIsNullPrincipal();
-          if (isNullPrincipal || nsContentUtils::IsSystemPrincipal(principal)) {
-            break;
-          }
+        if (principal && !principal->GetIsNullPrincipal()) {
+          break;
         }
 
         if (!innerWindow) {
           innerWindow = do_QueryInterface(globalObject);
-          if (NS_WARN_IF(!innerWindow)) {
-            return NS_ERROR_DOM_SECURITY_ERR;
+          if (!innerWindow) {
+            // If we are in a XPConnect sandbox or in a JS component,
+            // innerWindow will be null. There is nothing on top of this to be
+            // considered.
+            break;
           }
         }
 
         nsCOMPtr<nsPIDOMWindowOuter> parentWindow =
           innerWindow->GetScriptableParent();
         if (NS_WARN_IF(!parentWindow)) {
           return NS_ERROR_DOM_SECURITY_ERR;
         }
new file mode 100644
--- /dev/null
+++ b/dom/base/test/iframe_webSocket_sandbox.html
@@ -0,0 +1,65 @@
+<html><body>
+<iframe id="frame" sandbox="allow-scripts allow-popups"></iframe>
+<script type="application/javascript;version=1.8">
+onmessage = function(e) {
+  parent.postMessage(e.data, '*');
+}
+
+var ifr = document.getElementById('frame');
+
+if (location.search == '?nested') {
+  var url = new URL(location);
+  url.search = "";
+  ifr.src = url.href;
+} else if (location.search == '?popup') {
+  var url = new URL(location);
+  url.search = "?opener";
+
+  ifr.srcdoc = "<html><script>" +
+    "window.open('" + url.href + "', 'foobar');" +
+    "onmessage = function(e) { " +
+    "  parent.postMessage(e.data, '*'); " +
+    "}" +
+  "</scr" + "ipt></html>";
+} else if (location.search == '?opener') {
+  try{
+    var socket = new WebSocket('ws://mochi.test:8888/tests/dom/base/test/file_websocket_basic');
+    socket.onerror = function(e) {
+      opener.postMessage('WS onerror', '*');
+      close();
+    };
+    socket.onopen = function(event) {
+      opener.postMessage('WS onopen', '*');
+      close();
+    };
+  } catch(e) {
+    if (e.name == 'SecurityError') {
+      opener.postMessage('WS Throws!', '*');
+    } else {
+      opener.postMessage('WS Throws something else!', '*');
+    }
+    close();
+  }
+} else {
+  ifr.srcdoc = `
+  <html><script>
+  try{
+    var socket = new WebSocket('ws://mochi.test:8888/tests/dom/base/test/file_websocket_basic');
+    socket.onerror = function(e) {
+      parent.postMessage('WS onerror', '*');
+    };
+    socket.onopen = function(event) {
+      parent.postMessage('WS onopen', '*');
+    };
+  } catch(e) {
+    if (e.name == 'SecurityError') {
+      parent.postMessage('WS Throws!', '*');
+    } else {
+      parent.postMessage('WS Throws something else!', '*');
+    }
+  }
+  </scr`+`ipt>
+  </html>`;
+}
+</script>
+</body></html>
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -801,16 +801,19 @@ tags = audiochannel
 [test_webaudioNotificationStopOnNavigation.html]
 tags = audiochannel
 [test_websocket_basic.html]
 skip-if = toolkit == 'android'
 [test_websocket_hello.html]
 skip-if = toolkit == 'android'
 [test_websocket_permessage_deflate.html]
 skip-if = toolkit == 'android'
+[test_webSocket_sandbox.html]
+skip-if = toolkit == 'android'
+support-files = iframe_webSocket_sandbox.html
 [test_websocket1.html]
 skip-if = toolkit == 'android'
 [test_websocket2.html]
 skip-if = toolkit == 'android'
 [test_websocket3.html]
 skip-if = toolkit == 'android'
 [test_websocket4.html]
 skip-if = toolkit == 'android'
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_webSocket_sandbox.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1252751</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<div id="container"></div>
+<iframe id="frame"></iframe>
+<script type="application/javascript;version=1.8">
+var urls = [ "https://example.com/tests/dom/base/test/iframe_webSocket_sandbox.html",
+             "https://example.com/tests/dom/base/test/iframe_webSocket_sandbox.html?nested",
+             "https://example.com/tests/dom/base/test/iframe_webSocket_sandbox.html?popup" ];
+
+onmessage = function(e) {
+  is(e.data, "WS Throws!", "ws://URI cannot be used by a https iframe");
+  runTest();
+}
+
+function runTest() {
+  if (!urls.length) {
+    SimpleTest.finish();
+    return;
+  }
+
+  document.getElementById("frame").src = urls.shift();
+}
+
+SimpleTest.waitForExplicitFinish();
+runTest();
+</script>
+</body>
+</html>