views:

963

answers:

1

What XPCOM interfaces should I use to detect opening, closing and switching of tabs and also get their associated URL from a firefox extension? I have seen instances of code that manage tabs in JS, but how about from C++ ?

+3  A: 

You can write small JS component that will reroute tab events to your C++ component using nsIObserverService.

In C++ code you can use this snippet to register your component as observer to user defined events that is used for rerouting tab events.

NS_IMETHODIMP MyCppComponent::Observe(nsISupports *aSubject,
    const char *aTopic,
    const PRUnichar *aData)
{
    if( !strcmp( aTopic, "xpcom-startup" ) )
    {
        nsCOMPtr<nsIObserverService> observerService = 
            do_GetService( "@mozilla.org/observer-service;1" );
        observerService->AddObserver( this, "my-tab-open", false );
        observerService->AddObserver( this, "my-tab-close", false );
        observerService->AddObserver( this, "my-tab-select", false );
    }
    else if( !strcmp( aTopic, "my-tab-open" ) )
    {
        /* . . . */
    }
    else if( !strcmp( aTopic, "my-tab-close" ) )
    {
        /* . . . */
    }
    else if( !strcmp( aTopic, "my-tab-select" ) )
    {
        /* . . . */
    }

    /* . . . */
}

And in helper JS component you should to subscribe to tab events and in event handlers you can extract desired data and raise user defined events to execute C++ code.

function tabOpened(event) {
    var obsSvc = CC["@mozilla.org/observer-service;1"].
        getService(CI.nsIObserverService);
    obsSvc.notifyObservers(event.target.linkedBrowser.contentWindow,
        "my-tab-open", "some data");
}

function tabClosed(event) {
    var obsSvc = CC["@mozilla.org/observer-service;1"].
        getService(CI.nsIObserverService);
    obsSvc.notifyObservers(event.target.linkedBrowser.contentWindow,
        "my-tab-close", "some data");
}

function tabSelected(event) {
    var obsSvc = CC["@mozilla.org/observer-service;1"].
        getService(CI.nsIObserverService);
    obsSvc.notifyObservers(event.target.linkedBrowser.contentWindow,
        "my-tab-select", "some data");
}

function contentWndLoad(event) {
    var obsSvc = CC["@mozilla.org/observer-service;1"].
        getService(CI.nsIObserverService);
    var browser = getMostRecentBrowserWindow().getBrowser();

    browser.tabContainer.addEventListener("TabOpen", tabOpened, false);
    browser.tabContainer.addEventListener("TabClose", tabClosed, false);
    browser.tabContainer.addEventListener("TabSelect", tabSelected, false);
}

MyJsComponent.prototype = {

    /* . . . */

    observe: function(aSubject, aTopic, aData) {
        switch(aTopic) {
            case "xpcom-startup":
                var obsSvc = CC["@mozilla.org/observer-service;1"].
                    getService(CI.nsIObserverService);
                obsSvc.addObserver(this, "toplevel-window-ready", false);
                break;

            case "toplevel-window-ready":
                aSubject.addEventListener("load", contentWndLoad, false);
                break;
        }
    }

    /* . . . */
}

Also there are some additional code that you should add to handle specific cases. For instance when user close browser window you won't receive TabClose events for opened tabs in that window... And don’t forget to unregister your observers when you longer need them.

Mladen Jankovic
Great, This was exactly what I needed, the example code will save me a lot of time!!!Thanks a million!!!
rep_movsd