I have already developed a C# win form application and a chrome extension with native messaging (another C# console app) to fetch user's active tab url. I have also developed an msi setup in WiX to write under the registry (HKLM/SOFTWARE/Wow6432Node/Google/Chrome/Extensions and HKLM\SOFTWARE\Wow6432Node\Google\Chrome\NativeMessagingHosts) programmatically and tested the installation of the chrome extension by running the setup on different Windows 7 machines. I am publishing this extension on chrome web store and then I shall install the extension on several client computers.

I want to accomplish the same with Mozilla Firefox. I am newbie in this field and going through some Firefox developers guides (XPCOM, js-ctypes etc.) and getting little confused with multiple links.

It would be of great help if anyone can guide me towards the exact solution. Please note that, 1) I have to install the extension programmatically through the same msi package which already contains my own C# app and the chrome extension with native app and 2) the client machines will be Windows only but any version (XP (optional), 7, 8, Server anything).

EDIT:
According to Noitidart's answer, I have made an ffext.xpi from the 4 files (bootstrap.js, myWorker.js, chrome.manifest, install.rdf) and uploaded and installed on firefox, with no error, but nothing happens. At first, I am concentrating on the browser extension part and not the native for now and I just want to have a listener inside the js files such that whenever I switch to a different firefox tab or firefox window, an alert should show up from the browser itself (not from native at this moment) displaying the active tab's URL. I don't even understand how the js files will get called or executed, how this line myWorker.addEventListener('message', handleMessageFromWorker); will work or if I need to add some other listener. Nothing is happening at all. How to debug or proceed from here? Please help.

1

There are 1 answers

1
Noitidart On

To get the current url of the window do this:

aDOMWindow.gBrowser.currentURI.spec

To access all windows do this:

            Cu.import('resource://gre/modules/Services.jsm');
            let DOMWindows = Services.wm.getEnumerator(null);
            while (DOMWindows.hasMoreElements()) {
                let aDOMWindow = DOMWindows.getNext();
                if (aDOMWindow.gBrowser) {
                    var currentURL = aDOMWindow.gBrowser.currentURI;
                }
            }

If you don't check for gBrowser the aDOMWindow.location will be a chrome path, very likely.

So putting this togather with a ChromeWorker (the ChromeWorker will access the js-ctypes) template here: https://github.com/Noitidart/ChromeWorker (this template is the bare minimum needed for communication between ChromeWorker and your js file, in this case bootstrap.js) (bootstrap.js is the js file that is required and is run, the 4 startup,shutdown,install,uninstall functions are required in bootstrap.js)

From bootstrap.js we would do, for now lets do it in startup:

function startup() {
    loadAndSetupWorker(); //must do after startup
    myWorker.postMessage({
        aTopic: 'currentURL',
        aURL: Services.wm.getMostRecentWindow('navigator:browser').gBrowser.currentURI.spec // recent window of type navigator:browser always has gBrowser
        aLinkedPanel: Services.wm.getMostRecentWindow('navigator:browser').gBrowser.selectedTab.getAttribute('linkedpanel') //we use this to make sure to get the right tab/window on message back
    });
}

Then in worker we'll do something like this:

self.onmessage = function(msg) {
    switch (msg.data.aTopic) {
        case 'currentURL':
            var ret = msgBox(0, "alert from ctypes on windows, the url is:" + msg.data.aURL, "ctypes alert windows", MB_OK);
            self.postMessage({
                aTopic: 'currentURL-reply',
                theLinkedPanel: msg.data.aLinkedPanel,
                aResponde: aRet
            });
            break;
        default:
            throw 'no aTopic on incoming message to ChromeWorker';
    }
}

Then back in bootstrap.js we'll receive this message and do something with it:

function handleMessageFromWorker(msg) {
    console.log('incoming message from worker, msg:', msg);
    switch (msg.data.aTopic) {
        case 'currentURL-reply':
            let DOMWindows = Services.wm.getEnumerator('navigator:browser');
            while (DOMWindows.hasMoreElements()) {
                let aDOMWindow = DOMWindows.getNext();
                if (aDOMWindow.gBrowser && aDOMWindow.gBrowser.selectedTab.getAttribute('linkedpanel') == msg.data.theLinkedPanel) {
                    //this is our window, as the currently selected tab linkedpanel is same as one the worker dealt with
                    var currentURL = aDOMWindow.gBrowser.currentURI;
                    aDOMWindow.gBrowser.selectedTab.contentWindow.alert('the user was prompted with js-ctypes and the user clicked on:' + aRet);
                    break;
                }
            }
            break;
        default:
            console.error('no handle for msg from worker of aTopic:', msg.data.aTopic);
    }
}

so what this example does, is on install/startup of addon it gets the most recent browser windows url. it sends it to ctypes, ctypes throws a os level alert, and then ctypes sends back what the user clicked, then bootstrap.js finds that same window and that tab and with a javascript alert it tells what the jsctypes os level msgbox return value was.