Bug 913761 - Something is wrong when transferring MessagePort object via MessageChannel. r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Tue, 10 Sep 2013 13:42:22 -0400
changeset 159360 1585fa81edfc8e8aa4880ec470efd12e5f2919f4
parent 159359 03dbb211fd6b89f61c6e7dfd44d8545d178d741f
child 159361 efb5dda07b745080ba814af0544e29dc9b9edb58
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs913761
milestone26.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 913761 - Something is wrong when transferring MessagePort object via MessageChannel. r=smaug CLOSED TREE
dom/base/MessagePort.cpp
dom/base/MessagePort.h
dom/base/nsGlobalWindow.cpp
dom/base/test/Makefile.in
dom/base/test/test_bug913761.html
--- a/dom/base/MessagePort.cpp
+++ b/dom/base/MessagePort.cpp
@@ -105,17 +105,18 @@ struct StructuredCloneInfo
 
 static JSObject*
 PostMessageReadStructuredClone(JSContext* cx,
                                JSStructuredCloneReader* reader,
                                uint32_t tag,
                                uint32_t data,
                                void* closure)
 {
-  NS_ASSERTION(closure, "Must have closure!");
+  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
+  NS_ASSERTION(scInfo, "Must have scInfo!");
 
   if (tag == SCTAG_DOM_BLOB || tag == SCTAG_DOM_FILELIST) {
     NS_ASSERTION(!data, "Data should be empty");
 
     nsISupports* supports;
     if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
       JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
       if (global) {
@@ -134,16 +135,17 @@ PostMessageReadStructuredClone(JSContext
     NS_ASSERTION(!data, "Data should be empty");
 
     MessagePort* port;
     if (JS_ReadBytes(reader, &port, sizeof(port))) {
       JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
       if (global) {
         JS::Rooted<JSObject*> obj(cx, port->WrapObject(cx, global));
         if (JS_WrapObject(cx, obj.address())) {
+          port->BindToOwner(scInfo->mPort->GetOwner());
           return obj;
         }
       }
     }
   }
 
   const JSStructuredCloneCallbacks* runtimeCallbacks =
     js::GetContextStructuredCloneCallbacks(cx);
@@ -186,17 +188,17 @@ PostMessageWriteStructuredClone(JSContex
              JS_WriteBytes(writer, &supports, sizeof(supports)) &&
              scInfo->mEvent->StoreISupports(supports);
     }
   }
 
   MessagePort* port = nullptr;
   nsresult rv = UNWRAP_OBJECT(MessagePort, cx, obj, port);
   if (NS_SUCCEEDED(rv)) {
-    nsRefPtr<MessagePort> newPort = port->Clone(scInfo->mPort->GetOwner());
+    nsRefPtr<MessagePort> newPort = port->Clone();
 
     return JS_WriteUint32Pair(writer, SCTAG_DOM_MESSAGEPORT, 0) &&
            JS_WriteBytes(writer, &newPort, sizeof(newPort)) &&
            scInfo->mEvent->StoreISupports(newPort);
   }
 
   const JSStructuredCloneCallbacks* runtimeCallbacks =
     js::GetContextStructuredCloneCallbacks(cx);
@@ -449,19 +451,19 @@ MessagePort::Entangle(MessagePort* aMess
   MOZ_ASSERT(aMessagePort != this);
 
   Close();
 
   mEntangledPort = aMessagePort;
 }
 
 already_AddRefed<MessagePort>
-MessagePort::Clone(nsPIDOMWindow* aWindow)
+MessagePort::Clone()
 {
-  nsRefPtr<MessagePort> newPort = new MessagePort(aWindow->GetCurrentInnerWindow());
+  nsRefPtr<MessagePort> newPort = new MessagePort(nullptr);
 
   // Move all the events in the port message queue of original port.
   newPort->mMessageQueue.SwapElements(mMessageQueue);
 
   if (mEntangledPort) {
     nsRefPtr<MessagePort> port = mEntangledPort;
     mEntangledPort = nullptr;
 
--- a/dom/base/MessagePort.h
+++ b/dom/base/MessagePort.h
@@ -61,17 +61,17 @@ public:
   // new one.
   void
   Entangle(MessagePort* aMessagePort);
 
   // Duplicate this message port. This method is used by the Structured Clone
   // Algorithm and makes the new MessagePort active with the entangled
   // MessagePort of this object.
   already_AddRefed<MessagePort>
-  Clone(nsPIDOMWindow* aWindow);
+  Clone();
 
 private:
   // Dispatch events from the Message Queue using a nsRunnable.
   void Dispatch();
 
   nsRefPtr<DispatchEventRunnable> mDispatchRunnable;
 
   nsRefPtr<MessagePort> mEntangledPort;
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -6742,17 +6742,18 @@ struct StructuredCloneInfo {
 
 static JSObject*
 PostMessageReadStructuredClone(JSContext* cx,
                                JSStructuredCloneReader* reader,
                                uint32_t tag,
                                uint32_t data,
                                void* closure)
 {
-  NS_ASSERTION(closure, "Must have closure!");
+  StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
+  NS_ASSERTION(scInfo, "Must have scInfo!");
 
   if (tag == SCTAG_DOM_BLOB || tag == SCTAG_DOM_FILELIST) {
     NS_ASSERTION(!data, "Data should be empty");
 
     nsISupports* supports;
     if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
       JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
       if (global) {
@@ -6771,16 +6772,17 @@ PostMessageReadStructuredClone(JSContext
     NS_ASSERTION(!data, "Data should be empty");
 
     MessagePort* port;
     if (JS_ReadBytes(reader, &port, sizeof(port))) {
       JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
       if (global) {
         JS::Rooted<JSObject*> obj(cx, port->WrapObject(cx, global));
         if (JS_WrapObject(cx, obj.address())) {
+          port->BindToOwner(scInfo->window);
           return obj;
         }
       }
     }
   }
 
   const JSStructuredCloneCallbacks* runtimeCallbacks =
     js::GetContextStructuredCloneCallbacks(cx);
@@ -6821,17 +6823,17 @@ PostMessageWriteStructuredClone(JSContex
              JS_WriteBytes(writer, &supports, sizeof(supports)) &&
              scInfo->event->StoreISupports(supports);
   }
 
   if (MessageChannel::PrefEnabled()) {
     MessagePort* port = nullptr;
     nsresult rv = UNWRAP_OBJECT(MessagePort, cx, obj, port);
     if (NS_SUCCEEDED(rv) && scInfo->subsumes) {
-      nsRefPtr<MessagePort> newPort = port->Clone(scInfo->window);
+      nsRefPtr<MessagePort> newPort = port->Clone();
 
       return JS_WriteUint32Pair(writer, SCTAG_DOM_MESSAGEPORT, 0) &&
              JS_WriteBytes(writer, &newPort, sizeof(newPort)) &&
              scInfo->event->StoreISupports(newPort);
     }
   }
 
   const JSStructuredCloneCallbacks* runtimeCallbacks =
--- a/dom/base/test/Makefile.in
+++ b/dom/base/test/Makefile.in
@@ -30,15 +30,16 @@ MOCHITEST_FILES = \
   iframe_messageChannel_post.html \
   test_messageChannel_transferable.html \
   test_messageChannel_start.html \
   test_messageChannel_pingpong.html \
   iframe_messageChannel_pingpong.html \
   test_messageChannel_unshipped.html \
   test_messageChannel_pref.html \
   test_url.html \
+  test_bug913761.html \
   $(NULL)
 
 MOCHITEST_CHROME_FILES = \
    test_bug715041.xul \
    test_bug715041_removal.xul \
    test_domrequesthelper.xul \
    $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_bug913761.html
@@ -0,0 +1,43 @@
+
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=913761
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 913761 - basic support</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=913761">Mozilla Bug 913761</a>
+<script type="application/javascript">
+
+  function runTest() {
+    var transportChannel = new MessageChannel();
+    transportChannel.port1.onmessage = function (event) {
+      ok(true, 'Port Returned.');
+      var portToService = event.data.port;
+      portToService.onmessage = function (event) {
+        ok(true, "message received");
+        SimpleTest.finish();
+      };
+      portToService.postMessage('READY?');
+    }
+    
+    var serviceChannel = new MessageChannel();
+    serviceChannel.port1.onmessage = function (event) {
+      if (event.data == 'READY?') {
+        this.postMessage('READY!');
+      }
+    }
+    
+    transportChannel.port2.postMessage({ port: serviceChannel.port2} /* TODO: [serviceChannel.port2] */);
+  }
+
+  SimpleTest.waitForExplicitFinish();
+  SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
+</script>
+</body>
+</html>