86 lines
2.7 KiB
JavaScript
86 lines
2.7 KiB
JavaScript
/* -*- indent-tabs-mode: nil; js-indent-level: 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/. */
|
|
|
|
import { ContentDOMReference } from "resource://gre/modules/ContentDOMReference.sys.mjs";
|
|
|
|
export class WebChannelChild extends JSWindowActorChild {
|
|
handleEvent(event) {
|
|
if (event.type === "WebChannelMessageToChrome") {
|
|
return this._onMessageToChrome(event);
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
receiveMessage(msg) {
|
|
if (msg.name === "WebChannelMessageToContent") {
|
|
return this._onMessageToContent(msg);
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
_onMessageToChrome(e) {
|
|
if (e.detail) {
|
|
if (typeof e.detail != "string") {
|
|
console.error("WebChannelMessageToChrome must only send strings");
|
|
return;
|
|
}
|
|
|
|
let eventTarget =
|
|
e.target instanceof Ci.nsIDOMWindow
|
|
? null
|
|
: ContentDOMReference.get(e.target);
|
|
this.sendAsyncMessage("WebChannelMessageToChrome", {
|
|
contentData: e.detail,
|
|
eventTarget,
|
|
});
|
|
} else {
|
|
console.error("WebChannel message failed. No message detail.");
|
|
}
|
|
}
|
|
|
|
_onMessageToContent(msg) {
|
|
if (msg.data && this.contentWindow) {
|
|
// msg.objects.eventTarget will be defined if sending a response to
|
|
// a WebChannelMessageToChrome event. An unsolicited send
|
|
// may not have an eventTarget defined, in this case send to the
|
|
// main content window.
|
|
let { eventTarget, principal } = msg.data;
|
|
if (!eventTarget) {
|
|
eventTarget = this.contentWindow;
|
|
} else {
|
|
eventTarget = ContentDOMReference.resolve(eventTarget);
|
|
}
|
|
if (!eventTarget) {
|
|
console.error("WebChannel message failed. No target.");
|
|
return;
|
|
}
|
|
|
|
// Use nodePrincipal if available, otherwise fallback to document principal.
|
|
let targetPrincipal =
|
|
eventTarget instanceof Ci.nsIDOMWindow
|
|
? eventTarget.document.nodePrincipal
|
|
: eventTarget.nodePrincipal;
|
|
|
|
if (principal.subsumes(targetPrincipal)) {
|
|
let targetWindow = this.contentWindow;
|
|
eventTarget.dispatchEvent(
|
|
new targetWindow.CustomEvent("WebChannelMessageToContent", {
|
|
detail: Cu.cloneInto(
|
|
{
|
|
id: msg.data.id,
|
|
message: msg.data.message,
|
|
},
|
|
targetWindow
|
|
),
|
|
})
|
|
);
|
|
} else {
|
|
console.error("WebChannel message failed. Principal mismatch.");
|
|
}
|
|
} else {
|
|
console.error("WebChannel message failed. No message data.");
|
|
}
|
|
}
|
|
}
|