1

I'm writing a Firefox extension that creates a socket server which will output the active tab's URL when a client makes a connection to it. I have the following code in my javascript file:

var serverSocket;

function startServer()
{
    var listener =
    {
        onSocketAccepted : function(socket, transport)
        {
            try {
                var outputString = gBrowser.currentURI.spec + "\n";
                var stream = transport.openOutputStream(0,0,0);
                stream.write(outputString,outputString.length);
                stream.close();
            } catch(ex2){ dump("::"+ex2); }
        },

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

    try {
        serverSocket = Components.classes["@mozilla.org/network/server-socket;1"]
        .createInstance(Components.interfaces.nsIServerSocket);

        serverSocket.init(7055,true,-1);
        serverSocket.asyncListen(listener);
   } catch(ex){ dump(ex); }

   document.getElementById("status").value = "Started";
}



function stopServer ()
{
    if (serverSocket) 
    serverSocket.close();
}

window.addEventListener("load", function() { startServer(); }, false);
window.addEventListener("unload", function() { stopServer(); }, false);

As it is, it works for multiple tabs in a single window. If I open multiple windows, it ignores the additional windows. I think it is creating a server socket for each window, but since they are using the same port, the additional sockets fail to initialize. I need it to create a server socket when the browser launches and continue running when I close the windows (Mac OS X). As it is, when I close a window but Firefox remains running, the socket closes and I have to restart firefox to get it up an running. How do I go about that?

Wayne
  • 59,728
  • 15
  • 131
  • 126
David
  • 7,310
  • 6
  • 41
  • 63

2 Answers2

2

Firefox extension overlays bind to window objects. One way around this is to create an XPCOM component or find one that someone else already created to allow you to build functionality without binding it to the window objects.

Of course, section #2 below on Observer Notifications may be helpful as well.

Possible workaround: #1

Instead of calling "startServer()" each time a window is opened, you could have a flag called windowCount that you could increment each time you open a new window. If windowCount is greater than 0, don't call startServer().

As windows close, you could decrement the count. Once it hits 0, stop the server.

Here is information from the Mozilla forums on this problem: http://forums.mozillazine.org/viewtopic.php?f=19&t=2030279

Possible workaround #2:

With that said, I've also found documentation for Observer Notifications, which may be helpful as there is a section on Application Startup and Shutdown: https://developer.mozilla.org/en/Observer_Notifications

UPDATE:

Here are some resources on creating XPCOM components in JavaScript and in C++:

jamesmortensen
  • 33,636
  • 11
  • 99
  • 120
  • I tried workaround # 1 but I would still only get the URL of the first window that I opened. I can't figure out why but I think going with an XPCOM component is the best route. Do you have a link to a simple example of one that I can look at? thanks. – David Jan 16 '11 at 14:34
  • @Johnny Grass - I added some links that may be helpful for creating XPCOM components. Using JavaScript is probably easier. Also, don't discount method #2 as this might not require XPCOM. XPCOM can be quite complicated in my experience. Good luck! – jamesmortensen Jan 17 '11 at 14:11
  • Thanks, I'll look into it a little more. I glanced through and got the impression that Observer Notifications required XPCOM. – David Jan 17 '11 at 19:56
1

You probably want to:

  1. Move your code into a JavaScript component
  2. Register your component as a profile-after-change observer
  3. Whenever someone makes a connection to your socket, find the active window and return its URL.

Use something like

var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
                   .getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("navigator:browser");
var spec = win ? win.getBrowser().currentURI.spec : "";
var outputString = spec + "\n";

etc.

Neil
  • 54,642
  • 8
  • 60
  • 72
  • Can I register for observer notifications if the javascript code is not in a component? Also, when I register for profile-after-change notifications, how do I differentiate startup and shutdown? – David Jan 22 '11 at 04:11
  • Only components can be automatically registered for notifications with the category manager. Other code can register for many notifications with the observer service, but profile-after-change is too early for that. In regards to your other question, you only get one profile-after-change notification; a different set of notifications fires on shutdown. – Neil Jan 22 '11 at 14:45