limacina
limacina

Reputation: 31

Add-on to open local folders in Firefox

I have just started making an add-on with Firefox. This add-on is written in order to open a local folder outside FF. The folder is already opened by the browser. And in the context menu you will see an option to open the folder outside the browser (I use Win7). This is the code that I used:

var contextMenu = require("context-menu");

var menuItem = contextMenu.Item({
    label: "Open Local File",
    context: contextMenu.URLContext("file:///*"),
    contentScript: 'self.on("click", function() {'+
                        'openDir(document.URL);'+
                   '});',
});

function openDir(val)
{
    if (val == "")
    {
        alert("Directory not defined");
        return;
    }
    if(navigator.userAgent.indexOf("Firefox") == -1)
    {
        alert("Currently active folder links supported only for Mozilla Firefox web browser");
        return;
    }
    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
    var localFile =
        Components.classes["@mozilla.org/file/local;1"]
        .createInstance(Components.interfaces.nsILocalFile);

    var env =
        Components.classes["@mozilla.org/process/environment;1"]
        .createInstance(Components.interfaces.nsIEnvironment);

    var systemRoot = env.get("SystemRoot");
    if (systemRoot == "")
    {
        alert("Unable to retrieve SystemRoot environment variable");
    }

    localFile.initWithPath(systemRoot + "\\explorer.exe");
    var process =
        Components.classes["@mozilla.org/process/util;1"]
        .createInstance(Components.interfaces.nsIProcess);
    process.init(localFile);
    process.run(false, Array(val), 1);
}

Now the problem is that when I save the add-on under http://builder.addons.mozilla.org/... it cannot be compiled. Instead a red box shows up with the message "XPI not built". This is the log:

GET https://builder.addons.mozilla.org/xpi/test/.../ 404 NOT FOUND 236ms

What should I do?


The modified code:

    var contextMenu = require("context-menu");

    var menuItem = contextMenu.Item({
        label: "Open Local File",
        contentScript: 'self.on("context", function(node)'+
                        '{'+
                        '  return node.ownerDocument.URL.indexOf("file:///") == 0;'+
                        '});'+
                        'self.on("click", function(node)' +
                        '{' +
                        '  self.postMessage(node.ownerDocument.URL);' +
                        '});',

        onMessage: function(url)
        {
          openDir(url);
        }

        }) ;

    function openDir(val)
    {
        var {Cc, Ci} = require("chrome");
        var ioService = Cc["@mozilla.org/network/io-service;1"]
                          .getService(Ci.nsIIOService);
        var uri = ioService.newURI(val, null, null);
        if (uri instanceof Ci.nsIFileURL && uri.file.isDirectory())
        {
          uri.file.QueryInterface(Ci.nsILocalFile).launch();
        }
    }

Upvotes: 2

Views: 2217

Answers (1)

Wladimir Palant
Wladimir Palant

Reputation: 57651

The Add-on Builder web application is there to package up your code and create an extension - Firefox merely installs the extension once it is done. You have an issue with the Add-on Builder, not one with Firefox. I can only recommend you to file a bug report.

Your code has numerous issues however:

  • It seems that you want to show your context menu item on pages using the file:/// URL scheme, not on links pointing to files. There is no predefined context for this, you will have to use the content script (see Specifying Contexts > In Content Scripts. Something like:
self.on("context", function(node)
{
  return node.ownerDocument.URL.indexOf("file:///") == 0;
});
  • Function openDir() isn't defined in the content script, it is defined in your extension. This means that you have to send a message back to your extension with the URL (see last example in Handling Menu Item Clicks). Something like this:
contentScript: 'self.on("context", ...);' +
               'self.on("click", function(node, data)' +
               '{' +
               '  self.postMessage(node.ownerDocument.URL);' +
               '});',
onMessage: function(url)
{
  openDir(url);
}
  • Checking whether your code is running in Firefox is pointless - currently, the Add-on SDK only supports Firefox.
  • You should not use the deprecated PrivilegeManager.enablePrivilege method - your code is already running with highest privileges. You will need to use chrome authority however, extensions built with the Add-on SDK by default cannot access low-level functionality.
  • You shouldn't run Windows Explorer directly, use nsILocalFile.launch(), for directories it will run Windows Explorer (or whatever action is defined in the operating system to open directories). Altogether the code in openDir() should look like this:
var {Cc, Ci} = require("chrome");
var ioService = Cc["@mozilla.org/network/io-service;1"]
                  .getService(Ci.nsIIOService);
var uri = ioService.newURI(val, null, null);
if (uri instanceof Ci.nsIFileURL && uri.file.isDirectory())
  uri.file.QueryInterface(Ci.nsILocalFile).launch();

Documentation: nsIIOService, nsIFileURL.

Upvotes: 2

Related Questions