I expect that the majority of plugins that people create are going to be around adding custom functionality or formats, but sometimes you will want to tie Se-IDE to you service. (Much like Sauce Labs does with Sauce IDE.) Typically that tie-in needs some sort of credentials.

There are two different ways to do this. First, you could just store things as a preference and be done with it, but that has a bit of a problem around it. Namely, it gets stored in the clear in your profile’s prefs.js file and (depending on your permissions regime on disk), anyone could read it and get your credentials. This is not quite ideal.

The better way to store your credentials is through Firefox’s Login Manager.

Again, Preflight doesn’t have need for a password right now, but if it did, here is how you would protect it.

Add a new overlay to selenium-common.xul in the chrome.manifest

overlay chrome://selenium-ide/content/selenium-ide-common.xul chrome://preflight/content/overlays/preflightCommonOverlay.xul

And in the overlay, add a js file that is going to have out secure password manipulation code.

<overlay id="common_overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"><script src="chrome://preflight/content/js/secure.js" type="application/x-javascript"></script></overlay>

Here is the contents of secure.js. I’ll explain them afterwards.

var passwordManager = Components.classes["@mozilla.org/login-manager;1"].
                       getService(Components.interfaces.nsILoginManager);
var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
                      Components.interfaces.nsILoginInfo, "init");

function storeUsernameAndKey(username, key) {
    var logins = passwordManager.findLogins({}, "chrome://preflight", null, 'Username and API Key');

    if (logins.length == 0) {
        var extLoginInfo = new nsLoginInfo('chrome://preflight',
                               null, 'Username and Password',
                               username, key, "", "");
        passwordManager.addLogin(extLoginInfo);
    } else {
        var extLoginInfo = new nsLoginInfo('chrome://preflight',
                               null, 'Username and Password',
                               username, key, "", "");
        passwordManager.modifyLogin(logins[0], extLoginInfo);
    }
}

function retrievePreflightUsername() {
    var logins = passwordManager.findLogins({}, "chrome://preflight", null, 'Username and Password');
    if (logins.length == 1) {
        return logins[0].username;
    } else {
        return "";
    }
}

function retrievePreflightPassword() {
    var logins = passwordManager.findLogins({}, "chrome://preflight", null, 'Username and Password');
    if (logins.length == 1) {
        return logins[0].password;
    } else {
        return "";
    }
}

This is almost straight copy-and-paste from the Mozilla docs, but with an additional layer of wrapping added. The part that you will want to change is the chrome url. It should be the url for your plugin.

The reason why I wrapped things like this is that it allows us to do things like

var u = retrievePreflightUsername()

from anywhere in your addon’s js. (This works because we included secure.js at a very high level in the app.)

Some things to be aware of when using this

  • This does not protect your credentials from other plugins. They can just as easily make the same calls as you did and get the information. All it does it protect it from prying eyes on disk.
  • This method of dealing with password was introduced in Firefox 3.0. As a result, if you are using this you need to set the minVersion in install.rdf appropriately.