mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 677638 - MessagePorts in Structured Clone Algorithm, r=smaug
This commit is contained in:
parent
56512865a8
commit
b1842412ca
@ -82,5 +82,25 @@ MessagePort::Entangle(MessagePort* aMessagePort)
|
||||
mEntangledPort = aMessagePort;
|
||||
}
|
||||
|
||||
already_AddRefed<MessagePort>
|
||||
MessagePort::Clone(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
nsRefPtr<MessagePort> newPort = new MessagePort(aWindow);
|
||||
|
||||
// TODO Move all the events in the port message queue of original port to the
|
||||
// port message queue of new port, if any, leaving the new port's port
|
||||
// message queue in its initial disabled state.
|
||||
|
||||
if (mEntangledPort) {
|
||||
nsRefPtr<MessagePort> port = mEntangledPort;
|
||||
mEntangledPort = nullptr;
|
||||
|
||||
newPort->Entangle(port);
|
||||
port->Entangle(newPort);
|
||||
}
|
||||
|
||||
return newPort.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -49,6 +49,12 @@ public:
|
||||
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);
|
||||
|
||||
private:
|
||||
nsRefPtr<MessagePort> mEntangledPort;
|
||||
};
|
||||
|
@ -28,6 +28,7 @@ enum StructuredCloneTags {
|
||||
|
||||
// These tags are used for both main thread and workers.
|
||||
SCTAG_DOM_IMAGEDATA,
|
||||
SCTAG_DOM_MESSAGEPORT,
|
||||
|
||||
SCTAG_DOM_MAX
|
||||
};
|
||||
|
@ -189,6 +189,8 @@
|
||||
#include "prenv.h"
|
||||
#include "prprf.h"
|
||||
|
||||
#include "mozilla/dom/MessagePort.h"
|
||||
#include "mozilla/dom/MessagePortBinding.h"
|
||||
#include "mozilla/dom/indexedDB/IDBFactory.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
|
||||
@ -6750,6 +6752,7 @@ namespace {
|
||||
struct StructuredCloneInfo {
|
||||
PostMessageEvent* event;
|
||||
bool subsumes;
|
||||
nsPIDOMWindow* window;
|
||||
};
|
||||
|
||||
static JSObject*
|
||||
@ -6779,6 +6782,21 @@ PostMessageReadStructuredClone(JSContext* cx,
|
||||
}
|
||||
}
|
||||
|
||||
if (tag == SCTAG_DOM_MESSAGEPORT) {
|
||||
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())) {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const JSStructuredCloneCallbacks* runtimeCallbacks =
|
||||
js::GetContextStructuredCloneCallbacks(cx);
|
||||
|
||||
@ -6819,6 +6837,16 @@ PostMessageWriteStructuredClone(JSContext* cx,
|
||||
scInfo->event->StoreISupports(supports);
|
||||
}
|
||||
|
||||
MessagePort* port = nullptr;
|
||||
nsresult rv = UNWRAP_OBJECT(MessagePort, cx, obj, port);
|
||||
if (NS_SUCCEEDED(rv) && scInfo->subsumes) {
|
||||
nsRefPtr<MessagePort> newPort = port->Clone(scInfo->window);
|
||||
|
||||
return JS_WriteUint32Pair(writer, SCTAG_DOM_MESSAGEPORT, 0) &&
|
||||
JS_WriteBytes(writer, &newPort, sizeof(newPort)) &&
|
||||
scInfo->event->StoreISupports(newPort);
|
||||
}
|
||||
|
||||
const JSStructuredCloneCallbacks* runtimeCallbacks =
|
||||
js::GetContextStructuredCloneCallbacks(cx);
|
||||
|
||||
@ -6910,6 +6938,7 @@ PostMessageEvent::Run()
|
||||
{
|
||||
StructuredCloneInfo scInfo;
|
||||
scInfo.event = this;
|
||||
scInfo.window = targetWindow;
|
||||
|
||||
if (!buffer.read(cx, messageData.address(), &kPostMessageCallbacks,
|
||||
&scInfo)) {
|
||||
@ -7056,6 +7085,7 @@ nsGlobalWindow::PostMessageMoz(const JS::Value& aMessage,
|
||||
JSAutoStructuredCloneBuffer buffer;
|
||||
StructuredCloneInfo scInfo;
|
||||
scInfo.event = event;
|
||||
scInfo.window = this;
|
||||
|
||||
nsIPrincipal* principal = GetPrincipal();
|
||||
if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes)))
|
||||
|
@ -32,6 +32,8 @@ MOCHITEST_FILES = \
|
||||
test_setting_opener.html \
|
||||
test_error.html \
|
||||
test_messageChannel.html \
|
||||
test_messageChannel_cloning.html \
|
||||
iframe_messageChannel_cloning.html \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_CHROME_FILES = \
|
||||
|
22
dom/base/test/iframe_messageChannel_cloning.html
Normal file
22
dom/base/test/iframe_messageChannel_cloning.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
|
||||
function ok(a, msg) {
|
||||
window.parent.postMessage({ status: a ? "OK" : "KO", message: msg }, "*");
|
||||
}
|
||||
|
||||
window.addEventListener('message', receiveMessage, false);
|
||||
function receiveMessage(evt) {
|
||||
ok (evt.data, "Data received");
|
||||
ok (evt.data.port instanceof MessagePort, "Data contains a MessagePort");
|
||||
|
||||
var a = new MessageChannel();
|
||||
window.parent.postMessage({ status: "FINISH", port: a.port2 }, '*');
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
70
dom/base/test/test_messageChannel_cloning.html
Normal file
70
dom/base/test/test_messageChannel_cloning.html
Normal file
@ -0,0 +1,70 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 677638 - port cloning</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=677638">Mozilla Bug 677638</a>
|
||||
<div id="content"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
<script type="application/javascript">
|
||||
|
||||
// This test checks if MessagePorts can be shared with iframes
|
||||
function test_iframe() {
|
||||
window.addEventListener('message', receiveMessage, false);
|
||||
function receiveMessage(evt) {
|
||||
if (evt.data.status == 'OK') {
|
||||
ok(true, evt.data.message);
|
||||
} else if (evt.data.status == 'KO') {
|
||||
ok(false, evt.data.message);
|
||||
} else if (evt.data.status == 'FINISH') {
|
||||
ok (evt.data.port instanceof MessagePort, "Data contains a MessagePort");
|
||||
window.removeEventListener('message', receiveMessage);
|
||||
runTest();
|
||||
} else {
|
||||
ok(false, "Unknown message");
|
||||
}
|
||||
}
|
||||
|
||||
var a = new MessageChannel();
|
||||
ok(a, "MessageChannel created");
|
||||
|
||||
var div = document.getElementById("content");
|
||||
ok(div, "Parent exists");
|
||||
|
||||
var ifr = document.createElement("iframe");
|
||||
ifr.addEventListener("load", iframeLoaded, false);
|
||||
ifr.setAttribute('src', "iframe_messageChannel_cloning.html");
|
||||
div.appendChild(ifr);
|
||||
|
||||
function iframeLoaded() {
|
||||
ifr.contentWindow.postMessage({ port: a.port2 }, '*');
|
||||
}
|
||||
}
|
||||
|
||||
var tests = [
|
||||
test_iframe
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user