Creating a Login Manager storage module

  • Revision slug: Creating_a_Login_Manager_storage_module
  • Revision title: Creating a Login Manager storage module
  • Revision id: 286666
  • Created:
  • Creator: Standard8
  • Is current revision? No
  • Comment 7 words added, 3 words removed

Revision Content

{{ Gecko_minversion_header(1.9) }} The Login Manager manages and stores user passwords. Extensions can replace the built-in password storage with their own implementation. This can be useful if you want to integrate a gecko application's password management with an existing password management system, or use your own password storage format or database.

If you just want to use the Login Manager in your extensions, refer to the article Using nsILoginManager.

Overriding the built-in Login Manager storage consists of two tasks:

  1. Implement the {{ Interface("nsILoginManagerStorage") }} interface.
  2. Register that interface in a specific category.
Some work has already been done to integrate the Login Manager with the Mac OS X keychain ({{ Bug(106400) }}) and Gnome Keyring Manager ({{ Bug(309807) }}). You should start with the existing code if you want to implement that in your extension.
To see some debugging output in the console set signon.debug to true using about:config.

Sample JavaScript implementation

The following code snippet is a JavaScript component that implements a dummy {{ Interface("nsILoginManagerStorage") }} interface. See How_to_Build_an_XPCOM_Component_in_Javascript for more details about JavaScript components.

const Cc = Components.classes;
const Ci = Components.interfaces;

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

function SampleLoginManagerStorage() {}
SampleLoginManagerStorage.prototype = {
  classDescription: "Sample nsILoginManagerStorage implementation",
  contractID: "@example.com/login-manager/storage/sample;1",
  classID: Components.ID("{364a118c-747a-4f6d-ac63-2d2998e5a5c1}"),
  QueryInterface: XPCOMUtils.generateQI([Ci.nsILoginManagerStorage]),

  // This registers the category for overriding the built-in nsILoginManagerStorage
  _xpcom_categories: [
    {
      category: "login-manager-storage",
      entry: "nsILoginManagerStorage"
    }
  ],
  

 // Console logging service, used for debugging.
  __logService : null,
  get _logService() {
    if (!this.__logService)
      this.__logService = Cc["@mozilla.org/consoleservice;1"].
                            getService(Ci.nsIConsoleService);
    return this.__logService;
  },
  log: function (message) {
    dump("SampleLoginManager: " + message + "\n");
    this._logService.logStringMessage("SampleLoginManager: " + message);
  },
  // Logs function name and arguments for debugging
  stub: function(arguments) {
    var args = [];
    for (let i = 0; i < arguments.length; i++)
      args.push(arguments[i])
    this.log("Called " + arguments.callee.name + "(" + args.join(",") + ")");
  },

  init: function SLMS_init() {
    this.stub(arguments);
  },
  initWithFile: function SLMS_initWithFile(aInputFile, aOutputFile) {
    this.stub(arguments);
  },
  addLogin: function SLMS_addLogin(login) {
    this.stub(arguments);
  },
  removeLogin: function SLMS_removeLogin(login) {
    this.stub(arguments);
  },
  modifyLogin: function SLMS_modifyLogin(oldLogin, newLogin) {
    this.stub(arguments);
  },
  getAllLogins: function SLMS_getAllLogins(count) {
    this.stub(arguments);
  },
  removeAllLogins: function SLMS_removeAllLogins() {
    this.stub(arguments);
  },
  getAllDisabledHosts: function SLMS_getAllDisabledHosts(count) {
    this.stub(arguments);
  },
  getLoginSavingEnabled: function SLMS_getLoginSavingEnabled(hostname) {
    this.stub(arguments);
  },
  setLoginSavingEnabled: function SLMS_setLoginSavingEnabled(hostname, enabled) {
    this.stub(arguments);
  },
  findLogins: function SLMS_findLogins(count, hostname, formSubmitURL, httpRealm) {
    this.stub(arguments);
  },
  countLogins: function SLMS_countLogins(aHostname, aFormSubmitURL, aHttpRealm) {
    this.stub(arguments);
  }
};

function NSGetModule(compMgr, fileSpec)
  XPCOMUtils.generateModule([SampleLoginManagerStorage]);

Sample C++ Implementation

{{ Bug(309807) }} contains a complete example. The category registration looks like this:

  nsCOMPtr<nsICategoryManager> cat =
      do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
  NS_ENSURE_STATE(cat);

  cat->AddCategoryEntry("login-manager-storage", "nsILoginManagerStorage",
                        kYourContractID, PR_TRUE, PR_TRUE, nsnull);

Don't forget to unregister the category on unload.

{{ languages( { "es": "es/Crear_un_m\u00f3dulo_de_Administrador_de_Cuentas_almacenadas", "ja": "ja/Creating_a_Login_Manager_storage_module" } ) }}

Revision Source

<p>{{ Gecko_minversion_header(1.9) }} The Login Manager manages and stores user passwords. Extensions can replace the built-in password storage with their own implementation. This can be useful if you want to integrate a gecko application's password management with an existing password management system, or use your own password storage format or database.</p>
<p>If you just want to use the Login Manager in your extensions, refer to the article <a href="/en/Using_nsILoginManager" title="en/Using_nsILoginManager">Using nsILoginManager</a>.</p>
<p>Overriding the built-in Login Manager storage consists of two tasks:</p>
<ol> <li>Implement the {{ Interface("nsILoginManagerStorage") }} interface.</li> <li>Register that interface in a specific category.</li>
</ol>
<div class="note">Some work has already been done to integrate the Login Manager with the Mac OS X keychain ({{ Bug(106400) }}) and Gnome Keyring Manager ({{ Bug(309807) }}). You should start with the existing code if you want to implement that in your extension.</div>
<div class="note">To see some debugging output in the console set <strong>signon.debug</strong> to <strong>true</strong> using about:config.</div>
<h3 id="Sample_JavaScript_implementation" name="Sample_JavaScript_implementation">Sample JavaScript implementation</h3>
<p>The following code snippet is a JavaScript component that implements a dummy {{ Interface("nsILoginManagerStorage") }} interface. See <a href="/en/How_to_Build_an_XPCOM_Component_in_Javascript" title="en/How_to_Build_an_XPCOM_Component_in_Javascript">How_to_Build_an_XPCOM_Component_in_Javascript</a> for more details about JavaScript components.</p>
<pre>const Cc = Components.classes;
const Ci = Components.interfaces;

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

function SampleLoginManagerStorage() {}
SampleLoginManagerStorage.prototype = {
  classDescription: "Sample nsILoginManagerStorage implementation",
  contractID: "@example.com/login-manager/storage/sample;1",
  classID: Components.ID("{364a118c-747a-4f6d-ac63-2d2998e5a5c1}"),
  QueryInterface: XPCOMUtils.generateQI([Ci.nsILoginManagerStorage]),

  // This registers the category for overriding the built-in nsILoginManagerStorage
  _xpcom_categories: [
    {
      category: "login-manager-storage",
      entry: "nsILoginManagerStorage"
    }
  ],
  

 // Console logging service, used for debugging.
  __logService : null,
  get _logService() {
    if (!this.__logService)
      this.__logService = Cc["@mozilla.org/consoleservice;1"].
                            getService(Ci.nsIConsoleService);
    return this.__logService;
  },
  log: function (message) {
    dump("SampleLoginManager: " + message + "\n");
    this._logService.logStringMessage("SampleLoginManager: " + message);
  },
  // Logs function name and arguments for debugging
  stub: function(arguments) {
    var args = [];
    for (let i = 0; i &lt; arguments.length; i++)
      args.push(arguments[i])
    this.log("Called " + arguments.callee.name + "(" + args.join(",") + ")");
  },

  init: function SLMS_init() {
    this.stub(arguments);
  },
  initWithFile: function SLMS_initWithFile(aInputFile, aOutputFile) {
    this.stub(arguments);
  },
  addLogin: function SLMS_addLogin(login) {
    this.stub(arguments);
  },
  removeLogin: function SLMS_removeLogin(login) {
    this.stub(arguments);
  },
  modifyLogin: function SLMS_modifyLogin(oldLogin, newLogin) {
    this.stub(arguments);
  },
  getAllLogins: function SLMS_getAllLogins(count) {
    this.stub(arguments);
  },
  removeAllLogins: function SLMS_removeAllLogins() {
    this.stub(arguments);
  },
  getAllDisabledHosts: function SLMS_getAllDisabledHosts(count) {
    this.stub(arguments);
  },
  getLoginSavingEnabled: function SLMS_getLoginSavingEnabled(hostname) {
    this.stub(arguments);
  },
  setLoginSavingEnabled: function SLMS_setLoginSavingEnabled(hostname, enabled) {
    this.stub(arguments);
  },
  findLogins: function SLMS_findLogins(count, hostname, formSubmitURL, httpRealm) {
    this.stub(arguments);
  },
  countLogins: function SLMS_countLogins(aHostname, aFormSubmitURL, aHttpRealm) {
    this.stub(arguments);
  }
};

function NSGetModule(compMgr, fileSpec)
  XPCOMUtils.generateModule([SampleLoginManagerStorage]);

</pre>
<h3 id="Sample_C.2B.2B_Implementation" name="Sample_C.2B.2B_Implementation">Sample C++ Implementation</h3>
<p>{{ Bug(309807) }} contains a complete example. The category registration looks like this:</p>
<pre>  nsCOMPtr&lt;nsICategoryManager&gt; cat =
      do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
  NS_ENSURE_STATE(cat);

  cat-&gt;AddCategoryEntry("login-manager-storage", "nsILoginManagerStorage",
                        kYourContractID, PR_TRUE, PR_TRUE, nsnull);
</pre>
<p>Don't forget to unregister the category on unload.</p>
<p>{{ languages( { "es": "es/Crear_un_m\u00f3dulo_de_Administrador_de_Cuentas_almacenadas", "ja": "ja/Creating_a_Login_Manager_storage_module" } ) }}</p>
Revert to this revision