I've written a Firefox extension that sets up a connection between FF
and the Komodo IDE.
Here's the FF code that sets up the connection, standard stuff (error-
handling removed
for clarity):

var transportService =
    Components.classes["@mozilla.org/network/socket-transport-service;
1"]
    .getService(Components.interfaces.nsISocketTransportService);
this.transport = transportService.createTransport(null, 0,
this.host_name, this.host_port, null);
this.transport.setTimeout(Components.interfaces.nsISocketTransport.TIMEOUT_CONNECT,
5);
this.raw_istream = this.transport.openInputStream(0, 0, 0);
this.ostream = this.transport.openOutputStream(0,0,0);
this.istream = Components.classes["@mozilla.org/binaryinputstream;1"]
    .createInstance(Components.interfaces.nsIBinaryInputStream);
this.istream.setInputStream(this.raw_istream);

At this point this.transport isAlive() is false, although we know from
the Komodo side that
very shortly the connection will be made.  Here's how we wait for the
connection in FF2:

eq = Components.classes["@mozilla.org/event-queue-service;1"]
     .getService(Components.interfaces.nsIEventQueueService);
eventTarget = eq.getSpecialEventQueue(eq.UI_THREAD_EVENT_QUEUE);
this.transport.setEventSink(this, eventTarget);
// ...
onTransportStatus : function(transport, status) {
  if (status  ==
Components.interfaces.nsISocketTransport.STATUS_CONNECTED_TO) {
        this.onConnect();
  }
},

This doesn't work with FF3, as event-queue-service was dropped from
Moz 1.9

I've tried three approaches, but only the worst, #3, works.  Here are
my stabs:

#1:

// Try using the main thread as an event sink for the transport:

var mainThread = Components.classes["@mozilla.org/thread-manager;1"]
                 .getService(Components.interfaces.nsIThreadManager).mainThread;
this.transport.setEventSink(this, mainThread);

-- doesn't work: the onTransportStatus  method is never invoked.

#2:
connect : function(host, port) {
// ...
var mainThread = Components.classes["@mozilla.org/thread-manager;1"]
    .getService(Components.interfaces.nsIThreadManager).mainThread;
var asyncOutputStream =
this.ostream.QueryInterface(Components.interfaces.nsIAsyncOutputStream);
asyncOutputStream.asyncWait(this, 0, 0, mainThread);
// ...
},

onOutputStreamReady : function(ignoredArg) {
    if (!this.transport) {
        this.handler.onNotify(this, "connect-failed",
"onOutputStreamReady: no transport");
        return;
    }
    this.onConnect();
},

onConnect: function() {
    if (!this.transport.isAlive()) {
        this.handler.onNotify(this, "connect-failed", "Unable to
connect; Transport not alive");
        this.disconnect();
        return;
    }
    // We connected, finish initializating
    this.continuation_func.call(this.continuation_obj);
}, //...

This fails: when the onOutputStreamReady callback fires,
this.transport.isAlive()
returns false.

BTW, the protocol starts off with Firefox writing an init-packet to
Komodo, which
is why I call asyncWait on the output-stream, not the input-stream.
I'm not sure why
this means that the onInputStreamReady cb isn't invoked, but that's
what I'm
seeing.

Changing the values of the aRequestedCount (0, 1, or 1024)
and aEventTarget (mainThread or null) fields seems to have no effect.

#3: The brute force technique:

Set up a background thread and have it poll this.transport() until
it's alive.  Then
have the background thread dispatch a callback to the main thread,
where
the main thread calls onConnect(), and everything works fine.

We would rather not do it this way.

Any suggestions on how to make either of the first two techniques
work?

Thanks,
Eric
_______________________________________________
dev-tech-network mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-network

Reply via email to