编程语言
首页 > 编程语言> > javascript – Firefox插件之间的消息

javascript – Firefox插件之间的消息

作者:互联网

我正在尝试在两个或多个插件之间实现客户端 – 服务器通信,其中每个插件同时是服务器和客户端.我使用nsIServerSocket作为客户端部分的服务器部分和websockets.这是代码:

function startServer(port) {

var listener = {
onSocketAccepted: function(serverSocket, transport) {
    console.log("Accepted connection on " + transport.host + ":" + transport.port);
    var input = transport.openInputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0);//.QueryInterface(Ci.nsIAsyncInputStream);
    var output = transport.openOutputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0);
    var sin = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream);

    try{
    sin.init(input);
    var readBytes = sin.available();
    var request = '';
    request = sin.read(readBytes);
    console.log('Received: ' + request);
    //getUrl(request);
    output.write("yes", "yes".length);
    output.flush();
    }
    finally{
    sin.close();
    input.close();
    output.close();
    }
}
}

try{
var serverSocket = Cc["@mozilla.org/network/server-socket;1"].createInstance(Ci.nsIServerSocket);
serverSocket.init(port, true, 5);
console.log("Opened socket on " + serverSocket.port);
serverSocket.asyncListen(listener);
}catch(e){
console.log(e);
}    
}

对于服务器部分,以及客户端部分的以下内容:

var address="ws://otherAddress:1234";// + port;
var window = Cc["@mozilla.org/appshell/appShellService;1"]
             .getService(Ci.nsIAppShellService)
             .hiddenDOMWindow;
ws = new window.WebSocket(address);

try{
ws.onmessage = function () {
};

ws.onopen = function(){
    console.log("connection opened");
    // Web Socket is connected. You can send data by send() method
    ws.send("lol ");
};

ws.onclose = function() {
    // websocket is closed. };
    console.log("websocket is closed");
}
}catch(evt){
console.log(evt.data);
}

客户端代码在用户单击按钮时启动….此代码部分工作,因为从控制台我看到当用户单击按钮时,服务器接收连接打开,但我无法收到消息…. ..任何人可以帮助我吗?谢谢

更新1

我在控制台中看到的消息是这样的:

"Received: GET / HTTP/1.1
Host: localhost:1234
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: resource://gre-resources
Sec-WebSocket-Key: zh/EpJRRsOAgLfPIbI1EDg==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

更新2
在nmaier和IvyLynx回答之后(非常感谢!!),我修改了我的代码插入一个完整的“ServerSocket”实现(主要是因为将来我也将传递二进制数据).这是localhost案例的代码:

var {Cc, Ci, Cu, Cr, components} = require("chrome");

// the thread manager can be important when using asynchronous mode
var thread_manager = Cc["@mozilla.org/thread-manager;1"].getService();
var socket_service = Cc["@mozilla.org/network/socket-transportservice;1"].getService(Ci.nsISocketTransportService);

// make some constructors so we don't have to worry about this later
var socket = Cc["@mozilla.org/network/serversocket;1"].createInstance(Ci.nsIServerSocket);
// set the second argument to false if you want it to listen
// to connections beyond the computer the extension runs on
socket.init(-1, true, -1);
var output_stream_bin = Cc["@mozilla.org/binaryoutputstream;1"].createInstance(Ci.nsIBinaryOutputStream);
var input_stream_bin = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);

// this is so we can easily instantiate nsIInputStreamPump, which allows us to read input streams properly
var input_stream_pump_c = Cc["@mozilla.org/network/input-stream-pump;1"];
var input_stream_base, input_stream_async_c, input_stream_async, recieved_bytes, recieved_total, input_stream_pump;
var output_stream_base, output_stream_async_c, output_stream_async, generalStream;
var client, client_input_stream, client_output_stream, client_input_stream_pump;
var data_to_send = "hi hi"; // this holds what we want to send
var socket_transport = socket_service.createTransport(null, 0, "localhost", socket.port, null);

var socket_listener = {
   onSocketAccepted: function(socket, transport){

      client = transport;

      client_input_stream = client.openInputStream(0, 0, 0);
      client_output_stream = client.openOutputStream(0, 0, 0);
      client_output_stream.QueryInterface(Ci.nsIAsyncOutputStream);
      generalStream = client_output_stream;
      client_input_stream_pump[this_transport] = input_stream_pump_c.createInstance(Ci.nsIInputStreamPump);
      client_input_stream_pump[this_transport].init(client_input_stream, -1, -1, 0, 0, false);
      client_input_stream_pump[this_transport].asyncRead(socket_reader, socket);

   },
   onStopListening: function(socket, status){
   }
};

socket.asyncListen(socket_listener);

// this guy will get called when we're ready to send data
var output_stream_callback = {
   onOutputStreamReady: function(stream){          
      output_stream_bin.setOutputStream(stream);
      output_stream_bin.writeBytes(data_to_send, data_to_send.length);
      data_to_send = "";
   }
};

var socket_reader = {
   onDataAvailable: function(request, context, stream, offset, count){

      input_stream_bin.setInputStream(stream);

      if(input_stream_bin.available() > 0){
        recieved_bytes = input_stream_bin.readByteArray(count);
        recieved_total = "";

        // this loop converts bytes to characters
        // if you don't need to pass binary data around
        // you can just use nsIScriptableInputStream instead of
        // nsIBinaryInputStream and skip this
        for (var i = 0; i < recieved_bytes.length; i++){
            recieved_total += String.fromCharCode(recieved_bytes[i]);
        }
      console.log("Received " + recieved_total)
      }else{
        stream.close();
      }
   },
   onStartRequest: function(request, context){
   },
   onStopRequest: function(request, context, status){
   }
};

require("sdk/widget").Widget({
   id: "mozilla-link",
   label: "Mozilla website",
   contentURL: data.url("icon.png"),
   onClick: listTabs

});

function listTabs() {
   //console.log(client_output_stream);

   generalStream.asyncWait(output_stream_callback,0,0,thread_manager.mainThread);
};

问题是generalStream变量.当用户点击扩展图标时我调用asyncWait方法,但我也用其他方法插入调用.每个generalStream.asyncWait都会引发以下问题(实际上,在执行扩展时,实际存在配置文件的路径):

console.error: client:
Message: TypeError: generalStream is undefined
Stack:
listTabs@resource://gre/modules/XPIProvider.jsm -> jar:file:///.../extensions/jid1-exo2NP
aadiTkqg@jetpack.xpi!/bootstrap.js -> resource://gre/modules/commonjs/toolkit/lo
ader.js -> resource://jid1-exo2npaaditkqg-at-jetpack/client/lib/main.js:742
_emitOnObject@resource://gre/modules/XPIProvider.jsm -> jar:file:///.../extensions/jid1-exo2N PaadiTkqg@jetpack.xpi!/bootstrap.js -> resource://gre/modules/commonjs/toolkit/l
oader.js -> resource://gre/modules/commonjs/sdk/deprecated/events.js:153
_emit@resource://gre/modules/XPIProvider.jsm -> jar:file:///.../extensions/jid1-exo2NPaadiTkqg@jetpack.xpi!/bootstrap.js -> resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/deprecated/events.js:123 _onEvent@resource://gre/modules/XPIProvider.jsm -> jar:file:///.../extensions/jid1-exo2NPaadi
Tkqg@jetpack.xpi!/bootstrap.js -> resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/widget.js:278
WidgetView__onEvent@resource://gre/modules/XPIProvider.jsm -> jar:file:///.../extensions/jid1-exo2NPaadiTkqg@jetpack.xpi!/bootstrap.js -> resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/widget.js:426
WC_addEventHandlers/listener/<@resource://gre/modules/XPIProvider.jsm -> jar:file:///.../extensions/jid1-exo2NPaadiTkqg@jetpack.xpi!/bootstrap.js -> resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/widget.js:884
notify@resource://gre/modules/XPIProvider.jsm -> jar:file:///.../extensions/jid1-exo2NPaadiTkqg@jetpack.xpi!/bootstrap.js -> resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/timers.js:40

解决方法:

nsISocketServer实现了一个简单的TCP /绑定服务器,但没有实现websocket协议.

>您需要在服务器套接字中自己实现the websocket protocol(包括HTTP / 1.1升级)
>或使用原始TCP套接字(通过nsISocketTransportService的nsISocketTransports).

鉴于原始TCP套接字通常是一个混乱的处理,你需要在此基础上实现一些简单的交换协议,我猜在服务器套接字中实现websocket协议的第一个选项会更容易(至少,你可以免费获得客户端实现.

PS:阻止模式是一个坏主意,因为它可能会长时间阻止UI线程.

PS:显然,有人implemented the websocket protocol already in coffee script和其他人(来自Add-on SDK团队)也实现了它in (what appears to be some form of :p) Javascript(虽然后者几乎不是自包含且难以阅读/喘气).

编辑我好奇并写了a stand-alone JS code module WebSocket server,这似乎主要是工作. :p

标签:javascript,plugins,firefox-addon,firefox-addon-sdk,xpcom
来源: https://codeday.me/bug/20190528/1173330.html