Bug 1308920: Part 2 - Support posting messages across windows with different addonId origins. r=billm
authorKris Maglione <maglione.k@gmail.com>
Tue, 01 Nov 2016 19:04:13 -0700
changeset 320706 36b37ea010f1baacac9513a3554c202f609a6ec9
parent 320705 0475a23b1a526c8338852d4812bdd65027bd8c1f
child 320707 d356a4425cee98a448462bfb909ade113588c33e
push id30902
push userphilringnalda@gmail.com
push dateThu, 03 Nov 2016 02:30:31 +0000
treeherdermozilla-central@ade8d4a63e57 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1308920
milestone52.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 1308920: Part 2 - Support posting messages across windows with different addonId origins. r=billm MozReview-Commit-ID: 89TD8x5cUlZ
dom/base/PostMessageEvent.cpp
toolkit/components/extensions/test/mochitest/mochitest.ini
toolkit/components/extensions/test/mochitest/test_ext_window_postMessage.html
--- a/dom/base/PostMessageEvent.cpp
+++ b/dom/base/PostMessageEvent.cpp
@@ -102,23 +102,29 @@ PostMessageEvent::Run()
     if (NS_WARN_IF(!targetPrin))
       return NS_OK;
 
     // Note: This is contrary to the spec with respect to file: URLs, which
     //       the spec groups into a single origin, but given we intentionally
     //       don't do that in other places it seems better to hold the line for
     //       now.  Long-term, we want HTML5 to address this so that we can
     //       be compliant while being safer.
-    if (!targetPrin->Equals(mProvidedPrincipal)) {
+    if (!BasePrincipal::Cast(targetPrin)->EqualsIgnoringAddonId(mProvidedPrincipal)) {
       nsAutoString providedOrigin, targetOrigin;
       nsresult rv = nsContentUtils::GetUTFOrigin(targetPrin, targetOrigin);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = nsContentUtils::GetUTFOrigin(mProvidedPrincipal, providedOrigin);
       NS_ENSURE_SUCCESS(rv, rv);
 
+      MOZ_DIAGNOSTIC_ASSERT(providedOrigin != targetOrigin ||
+                            (BasePrincipal::Cast(mProvidedPrincipal)->OriginAttributesRef() ==
+                              BasePrincipal::Cast(targetPrin)->OriginAttributesRef()),
+                            "Unexpected postMessage call to a window with mismatched "
+                            "origin attributes");
+
       const char16_t* params[] = { providedOrigin.get(), targetOrigin.get() };
 
       nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
         NS_LITERAL_CSTRING("DOM Window"), sourceDocument,
         nsContentUtils::eDOM_PROPERTIES,
         "TargetPrincipalDoesNotMatch",
         params, ArrayLength(params));
 
--- a/toolkit/components/extensions/test/mochitest/mochitest.ini
+++ b/toolkit/components/extensions/test/mochitest/mochitest.ini
@@ -90,11 +90,12 @@ skip-if = (os == 'android') # Bug 125897
 [test_ext_web_accessible_resources.html]
 skip-if = (os == 'android') # Bug 1258975 on android.
 [test_ext_webrequest.html]
 skip-if = os == 'android' # webrequest api unsupported (bug 1258975).
 [test_ext_webnavigation.html]
 skip-if = os == 'android' # port.sender.tab is undefined on Android (bug 1258975).
 [test_ext_webnavigation_filters.html]
 skip-if = os == 'android' # port.sender.tab is undefined on Android (bug 1258975).
+[test_ext_window_postMessage.html]
 [test_ext_subframes_privileges.html]
 skip-if = os == 'android' # port.sender.tab is undefined on Android (bug 1258975).
 [test_ext_xhr_capabilities.html]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/test_ext_window_postMessage.html
@@ -0,0 +1,105 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for content script</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
+  <script type="text/javascript" src="head.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<script type="text/javascript">
+"use strict";
+
+/* eslint-disable mozilla/balanced-listeners */
+
+add_task(function* test_postMessage() {
+  let extensionData = {
+    manifest: {
+      content_scripts: [
+        {
+          "matches": ["http://mochi.test/*/file_sample.html"],
+          "js": ["content_script.js"],
+          "run_at": "document_start",
+          "all_frames": true,
+        },
+      ],
+
+      web_accessible_resources: ["iframe.html"],
+    },
+
+    background() {
+      browser.test.sendMessage("iframe-url", browser.runtime.getURL("iframe.html"));
+    },
+
+    files: {
+      "content_script.js": function() {
+        window.addEventListener("message", event => {
+          if (event.data == "ping") {
+            event.source.postMessage({pong: location.href},
+                                     event.origin);
+          }
+        });
+      },
+
+      "iframe.html": `<!DOCTYPE html>
+        <html>
+          <head>
+            <meta charset="utf-8">
+            <script src="content_script.js"><\/script>
+          </head>
+        </html>`,
+    },
+  };
+
+  let createIframe = url => {
+    let iframe = document.createElement("iframe");
+    return new Promise(resolve => {
+      iframe.src = url;
+      iframe.onload = resolve;
+      document.body.appendChild(iframe);
+    }).then(() => {
+      return iframe;
+    });
+  };
+
+  let awaitMessage = () => {
+    return new Promise(resolve => {
+      let listener = event => {
+        if (event.data.pong) {
+          window.removeEventListener("message", listener);
+          resolve(event.data);
+        }
+      };
+      window.addEventListener("message", listener);
+    });
+  };
+
+  let extension = ExtensionTestUtils.loadExtension(extensionData);
+  yield extension.startup();
+
+  let iframeURL = yield extension.awaitMessage("iframe-url");
+  let testURL = SimpleTest.getTestFileURL("file_sample.html");
+
+  for (let url of [iframeURL, testURL]) {
+    info(`Testing URL ${url}`);
+
+    let iframe = yield createIframe(url);
+
+    iframe.contentWindow.postMessage(
+      "ping", url);
+
+    let pong = yield awaitMessage();
+    is(pong.pong, url, "Got expected pong");
+
+    iframe.remove();
+  }
+
+  yield extension.unload();
+});
+</script>
+
+</body>
+</html>