Bug 984990 - Enable MessageChannel for chrome and resource:// callers, r=bz
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 05 Jun 2014 00:58:00 +0200
changeset 186768 b28cd167b6fe0d4e8630bc2c900df7cc6810aee2
parent 186767 766912d433056f9b3696705975fa7fe134d434e0
child 186769 4aff63678fd2d22c3e993d1c576dd982ee0de264
push id44427
push usercbook@mozilla.com
push dateThu, 05 Jun 2014 10:56:19 +0000
treeherdermozilla-inbound@ffcfc25479e9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs984990
milestone32.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 984990 - Enable MessageChannel for chrome and resource:// callers, r=bz
dom/base/MessageChannel.cpp
dom/base/MessageChannel.h
dom/base/nsGlobalWindow.cpp
dom/base/test/chrome.ini
dom/base/test/iframe_messageChannel_chrome.html
dom/base/test/mochitest.ini
dom/base/test/test_messageChannel.xul
dom/webidl/MessageChannel.webidl
--- a/dom/base/MessageChannel.cpp
+++ b/dom/base/MessageChannel.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MessageChannel.h"
+
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/MessageChannelBinding.h"
 #include "mozilla/dom/MessagePort.h"
 #include "nsContentUtils.h"
 #include "nsPIDOMWindow.h"
 
 namespace mozilla {
 namespace dom {
@@ -23,26 +24,48 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
 NS_INTERFACE_MAP_END
 
 namespace {
   bool gPrefInitialized = false;
   bool gPrefEnabled = false;
 
 }
 
-
 /* static */ bool
-MessageChannel::PrefEnabled()
+MessageChannel::Enabled(JSContext* aCx, JSObject* aObj)
 {
   if (!gPrefInitialized) {
     Preferences::AddBoolVarCache(&gPrefEnabled, "dom.messageChannel.enabled");
     gPrefInitialized = true;
   }
 
-  return gPrefEnabled;
+  // Enabled by pref
+  if (gPrefEnabled) {
+    return true;
+  }
+
+  // Chrome callers are allowed.
+  if (nsContentUtils::ThreadsafeIsCallerChrome()) {
+    return true;
+  }
+
+  nsCOMPtr<nsIPrincipal> principal = nsContentUtils::SubjectPrincipal();
+  MOZ_ASSERT(principal);
+
+  nsCOMPtr<nsIURI> uri;
+  if (NS_FAILED(principal->GetURI(getter_AddRefs(uri))) || !uri) {
+    return false;
+  }
+
+  bool isResource = false;
+  if (NS_FAILED(uri->SchemeIs("resource", &isResource))) {
+    return false;
+  }
+
+  return isResource;
 }
 
 MessageChannel::MessageChannel(nsPIDOMWindow* aWindow)
   : mWindow(aWindow)
 {
   MOZ_COUNT_CTOR(MessageChannel);
   SetIsDOMBinding();
 
--- a/dom/base/MessageChannel.h
+++ b/dom/base/MessageChannel.h
@@ -23,17 +23,17 @@ class MessagePort;
 
 class MessageChannel MOZ_FINAL : public nsISupports
                                , public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MessageChannel)
 
-  static bool PrefEnabled();
+  static bool Enabled(JSContext* aCx, JSObject* aGlobal);
 
 public:
   MessageChannel(nsPIDOMWindow* aWindow);
 
   ~MessageChannel();
 
   nsPIDOMWindow*
   GetParentObject() const
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7900,17 +7900,17 @@ PostMessageReadTransferStructuredClone(J
                                        uint32_t tag, void* aData,
                                        uint64_t aExtraData,
                                        void* aClosure,
                                        JS::MutableHandle<JSObject*> returnObject)
 {
   StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
   NS_ASSERTION(scInfo, "Must have scInfo!");
 
-  if (MessageChannel::PrefEnabled() && tag == SCTAG_DOM_MAP_MESSAGEPORT) {
+  if (tag == SCTAG_DOM_MAP_MESSAGEPORT) {
     MessagePort* port = static_cast<MessagePort*>(aData);
     port->BindToOwner(scInfo->window);
     scInfo->ports.Put(port, nullptr);
 
     JS::Rooted<JSObject*> obj(aCx, port->WrapObject(aCx));
     if (JS_WrapObject(aCx, &obj)) {
       MOZ_ASSERT(port->GetOwner() == scInfo->window);
       returnObject.set(obj);
@@ -7929,49 +7929,47 @@ PostMessageTransferStructuredClone(JSCon
                                    uint32_t* aTag,
                                    JS::TransferableOwnership* aOwnership,
                                    void** aContent,
                                    uint64_t* aExtraData)
 {
   StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
   NS_ASSERTION(scInfo, "Must have scInfo!");
 
-  if (MessageChannel::PrefEnabled()) {
-    MessagePortBase* port = nullptr;
-    nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
-    if (NS_SUCCEEDED(rv)) {
-      nsRefPtr<MessagePortBase> newPort;
-      if (scInfo->ports.Get(port, getter_AddRefs(newPort))) {
-        // No duplicate.
-        return false;
-      }
-
-      newPort = port->Clone();
-      scInfo->ports.Put(port, newPort);
-
-      *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
-      *aOwnership = JS::SCTAG_TMO_CUSTOM;
-      *aContent = newPort;
-      *aExtraData = 0;
-
-      return true;
-    }
+  MessagePortBase* port = nullptr;
+  nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
+  if (NS_SUCCEEDED(rv)) {
+    nsRefPtr<MessagePortBase> newPort;
+    if (scInfo->ports.Get(port, getter_AddRefs(newPort))) {
+      // No duplicate.
+      return false;
+    }
+
+    newPort = port->Clone();
+    scInfo->ports.Put(port, newPort);
+
+    *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
+    *aOwnership = JS::SCTAG_TMO_CUSTOM;
+    *aContent = newPort;
+    *aExtraData = 0;
+
+    return true;
   }
 
   return false;
 }
 
 void
 PostMessageFreeTransferStructuredClone(uint32_t aTag, JS::TransferableOwnership aOwnership,
                                        void *aContent, uint64_t aExtraData, void* aClosure)
 {
   StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
   NS_ASSERTION(scInfo, "Must have scInfo!");
 
-  if (MessageChannel::PrefEnabled() && aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
+  if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
     nsRefPtr<MessagePortBase> port(static_cast<MessagePort*>(aContent));
     scInfo->ports.Remove(port);
   }
 }
 
 JSStructuredCloneCallbacks kPostMessageCallbacks = {
   PostMessageReadStructuredClone,
   PostMessageWriteStructuredClone,
--- a/dom/base/test/chrome.ini
+++ b/dom/base/test/chrome.ini
@@ -3,11 +3,12 @@ support-files =
   file_url.jsm
   file_empty.html
 
 [test_bug715041.xul]
 [test_bug715041_removal.xul]
 [test_domrequesthelper.xul]
 [test_url.xul]
 [test_console.xul]
+[test_messageChannel.xul]
 [test_navigator_resolve_identity_xrays.xul]
 [test_sendQueryContentAndSelectionSetEvent.html]
 [test_bug1016960.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/iframe_messageChannel_chrome.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+  <script type="application/javascript">
+
+window.addEventListener('message', receiveMessage, false);
+function receiveMessage(evt) {
+  evt.data.postMessage("Hello world");
+}
+  </script>
+</body>
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -1,12 +1,13 @@
 [DEFAULT]
 support-files =
   audio.ogg
   iframe_messageChannel_cloning.html
+  iframe_messageChannel_chrome.html
   iframe_messageChannel_pingpong.html
   iframe_messageChannel_post.html
   file_empty.html
   iframe_postMessage_solidus.html
 
 [test_Image_constructor.html]
 [test_appname_override.html]
 [test_audioWindowUtils.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_messageChannel.xul
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<window title="Test for MessageChannel API"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml" id="body">
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript"><![CDATA[
+
+  ok("MessageChannel" in window, "Should MessageChannel exist?");
+
+  var channel = new MessageChannel();
+  ok(channel, "MessageChannel is created");
+
+  channel.port1.onmessage = function(evt) {
+    ok(true, "message received!");
+    SimpleTest.finish();
+  }
+
+  var ifr = document.createElement('browser');
+  ifr.setAttribute("src", "http://mochi.test:8888/tests/dom/base/test/iframe_messageChannel_chrome.html");
+  ifr.setAttribute("flex", "1");
+  ifr.addEventListener('load', function() {
+    ifr.contentWindow.postMessage(channel.port2, '*', [channel.port2]);
+  });
+
+  var body = document.getElementById("body");
+  body.appendChild(ifr);
+
+  SimpleTest.waitForExplicitFinish();
+
+  ]]></script>
+</window>
--- a/dom/webidl/MessageChannel.webidl
+++ b/dom/webidl/MessageChannel.webidl
@@ -2,13 +2,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * For more information on this interface, please see
  * http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging
  */
 
-[Constructor, Pref="dom.messageChannel.enabled"]
+[Constructor, Func="MessageChannel::Enabled"]
 interface MessageChannel {
   readonly attribute MessagePort port1;
   readonly attribute MessagePort port2;
 };