--- a/toolkit/components/extensions/ExtensionChild.jsm
+++ b/toolkit/components/extensions/ExtensionChild.jsm
@@ -21,16 +21,18 @@ const Cr = Components.results;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionParent",
"resource://gre/modules/ExtensionParent.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "MessageChannel",
"resource://gre/modules/MessageChannel.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "NativeApp",
+ "resource://gre/modules/NativeMessaging.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
"resource://gre/modules/PromiseUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Schemas",
"resource://gre/modules/Schemas.jsm");
XPCOMUtils.defineLazyGetter(this, "ParentAPIManager",
() => ExtensionParent.ParentAPIManager);
@@ -99,16 +101,20 @@ class Port {
receiveMessage: ({data}) => this.disconnectByOtherEnd(data),
}, this.handlerBase);
MessageChannel.addListener(this.receiverMMs, "Extension:Port:Disconnect", this.disconnectHandler);
this.context.callOnClose(this);
}
+ static getNextID() {
+ return `${gNextPortId++}-${Services.appinfo.uniqueProcessID}`;
+ }
+
api() {
let portObj = Cu.createObjectIn(this.context.cloneScope);
let portError = null;
let publicAPI = {
name: this.name,
disconnect: () => {
@@ -256,16 +262,24 @@ class Port {
this._sendMessage("Extension:Port:Disconnect", error);
}
close() {
this.disconnect();
}
}
+class NativePort extends Port {
+ postMessage(data) {
+ data = NativeApp.encodeMessage(this.context, data);
+
+ return super.postMessage(data);
+ }
+}
+
/**
* Each extension context gets its own Messenger object. It handles the
* basics of sendMessage, onMessage, connect and onConnect.
*
* @param {BaseContext} context The context to which this Messenger is tied.
* @param {Array<nsIMessageListenerManager>} messageManagers
* The message managers used to receive messages (e.g. onMessage/onConnect
* requests).
@@ -311,16 +325,21 @@ class Messenger {
} else if (error.result != MessageChannel.RESULT_NO_RESPONSE) {
return Promise.reject({message: error.message});
}
});
return this.context.wrapPromise(promise, responseCallback);
}
+ sendNativeMessage(messageManager, msg, recipient, responseCallback) {
+ msg = NativeApp.encodeMessage(this.context, msg);
+ return this.sendMessage(messageManager, msg, recipient, responseCallback);
+ }
+
onMessage(name) {
return new SingletonEventManager(this.context, name, callback => {
let listener = {
messageFilterPermissive: this.optionalFilter,
messageFilterStrict: this.filter,
filterMessage: (sender, recipient) => {
// Ignore the message if it was sent by this Messenger.
@@ -359,35 +378,48 @@ class Messenger {
MessageChannel.addListener(this.messageManagers, "Extension:Message", listener);
return () => {
MessageChannel.removeListener(this.messageManagers, "Extension:Message", listener);
};
}).api();
}
- connectGetRawPort(messageManager, name, recipient) {
- let portId = `${gNextPortId++}-${Services.appinfo.uniqueProcessID}`;
- let port = new Port(this.context, messageManager, this.messageManagers, name, portId, null, recipient);
- let msg = {name, portId};
- this._sendMessage(messageManager, "Extension:Connect", msg, recipient)
- .catch(e => {
- if (e.result === MessageChannel.RESULT_NO_HANDLER) {
- e = {message: "Could not establish connection. Receiving end does not exist."};
- } else if (e.result === MessageChannel.RESULT_DISCONNECTED) {
- e = null;
- }
- port.disconnectByOtherEnd(e);
- });
- return port;
+ _connect(messageManager, port, recipient) {
+ let msg = {
+ name: port.name,
+ portId: port.id,
+ };
+
+ this._sendMessage(messageManager, "Extension:Connect", msg, recipient).catch(error => {
+ if (error.result === MessageChannel.RESULT_NO_HANDLER) {
+ error = {message: "Could not establish connection. Receiving end does not exist."};
+ } else if (error.result === MessageChannel.RESULT_DISCONNECTED) {
+ error = null;
+ }
+ port.disconnectByOtherEnd(error);
+ });
+
+ return port.api();
}
connect(messageManager, name, recipient) {
- let port = this.connectGetRawPort(messageManager, name, recipient);
- return port.api();
+ let portId = Port.getNextID();
+
+ let port = new Port(this.context, messageManager, this.messageManagers, name, portId, null, recipient);
+
+ return this._connect(messageManager, port, recipient);
+ }
+
+ connectNative(messageManager, name, recipient) {
+ let portId = Port.getNextID();
+
+ let port = new NativePort(this.context, messageManager, this.messageManagers, name, portId, null, recipient);
+
+ return this._connect(messageManager, port, recipient);
}
onConnect(name) {
return new SingletonEventManager(this.context, name, callback => {
let listener = {
messageFilterPermissive: this.optionalFilter,
messageFilterStrict: this.filter,
--- a/toolkit/components/extensions/ext-c-runtime.js
+++ b/toolkit/components/extensions/ext-c-runtime.js
@@ -1,11 +1,9 @@
"use strict";
-XPCOMUtils.defineLazyModuleGetter(this, "NativeApp",
- "resource://gre/modules/NativeMessaging.jsm");
function runtimeApiFactory(context) {
let {extension} = context;
return {
runtime: {
onConnect: context.messenger.onConnect("runtime.onConnect"),
@@ -57,32 +55,26 @@ function runtimeApiFactory(context) {
return context.messenger.sendMessage(context.messageManager, message, recipient, responseCallback);
},
connectNative(application) {
let recipient = {
childId: context.childManager.id,
toNativeApp: application,
};
- let rawPort = context.messenger.connectGetRawPort(context.messageManager, "", recipient);
- let port = rawPort.api();
- port.postMessage = message => {
- message = NativeApp.encodeMessage(context, message);
- rawPort.postMessage(message);
- };
- return port;
+
+ return context.messenger.connectNative(context.messageManager, "", recipient);
},
sendNativeMessage(application, message) {
let recipient = {
childId: context.childManager.id,
toNativeApp: application,
};
- message = NativeApp.encodeMessage(context, message);
- return context.messenger.sendMessage(context.messageManager, message, recipient);
+ return context.messenger.sendNativeMessage(context.messageManager, message, recipient);
},
get lastError() {
return context.lastError;
},
getManifest() {
return Cu.cloneInto(extension.manifest, context.cloneScope);