michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: "use strict"; michael@0: michael@0: module.metadata = { michael@0: "stability": "unstable" michael@0: }; michael@0: michael@0: const { Cc, Ci, CC } = require("chrome"); michael@0: const { uri: ADDON_URI } = require("../self"); michael@0: const loginManager = Cc["@mozilla.org/login-manager;1"]. michael@0: getService(Ci.nsILoginManager); michael@0: const { URL: parseURL } = require("../url"); michael@0: const LoginInfo = CC("@mozilla.org/login-manager/loginInfo;1", michael@0: "nsILoginInfo", "init"); michael@0: michael@0: function filterMatchingLogins(loginInfo) michael@0: Object.keys(this).every(function(key) loginInfo[key] === this[key], this); michael@0: michael@0: /** michael@0: * Removes `user`, `password` and `path` fields from the given `url` if it's michael@0: * 'http', 'https' or 'ftp'. All other URLs are returned unchanged. michael@0: * @example michael@0: * http://user:pass@www.site.com/foo/?bar=baz#bang -> http://www.site.com michael@0: */ michael@0: function normalizeURL(url) { michael@0: let { scheme, host, port } = parseURL(url); michael@0: // We normalize URL only if it's `http`, `https` or `ftp`. All other types of michael@0: // URLs (`resource`, `chrome`, etc..) should not be normalized as they are michael@0: // used with add-on associated credentials path. michael@0: return scheme === "http" || scheme === "https" || scheme === "ftp" ? michael@0: scheme + "://" + (host || "") + (port ? ":" + port : "") : michael@0: url michael@0: } michael@0: michael@0: function Login(options) { michael@0: let login = Object.create(Login.prototype); michael@0: Object.keys(options || {}).forEach(function(key) { michael@0: if (key === 'url') michael@0: login.hostname = normalizeURL(options.url); michael@0: else if (key === 'formSubmitURL') michael@0: login.formSubmitURL = options.formSubmitURL ? michael@0: normalizeURL(options.formSubmitURL) : null; michael@0: else if (key === 'realm') michael@0: login.httpRealm = options.realm; michael@0: else michael@0: login[key] = options[key]; michael@0: }); michael@0: michael@0: return login; michael@0: } michael@0: Login.prototype.toJSON = function toJSON() { michael@0: return { michael@0: url: this.hostname || ADDON_URI, michael@0: realm: this.httpRealm || null, michael@0: formSubmitURL: this.formSubmitURL || null, michael@0: username: this.username || null, michael@0: password: this.password || null, michael@0: usernameField: this.usernameField || '', michael@0: passwordField: this.passwordField || '', michael@0: } michael@0: }; michael@0: Login.prototype.toLoginInfo = function toLoginInfo() { michael@0: let { url, realm, formSubmitURL, username, password, usernameField, michael@0: passwordField } = this.toJSON(); michael@0: michael@0: return new LoginInfo(url, formSubmitURL, realm, username, password, michael@0: usernameField, passwordField); michael@0: }; michael@0: michael@0: function loginToJSON(value) Login(value).toJSON() michael@0: michael@0: /** michael@0: * Returns array of `nsILoginInfo` objects that are stored in the login manager michael@0: * and have all the properties with matching values as a given `options` object. michael@0: * @param {Object} options michael@0: * @returns {nsILoginInfo[]} michael@0: */ michael@0: exports.search = function search(options) { michael@0: return loginManager.getAllLogins() michael@0: .filter(filterMatchingLogins, Login(options)) michael@0: .map(loginToJSON); michael@0: }; michael@0: michael@0: /** michael@0: * Stores login info created from the given `options` to the applications michael@0: * built-in login management system. michael@0: * @param {Object} options. michael@0: */ michael@0: exports.store = function store(options) { michael@0: loginManager.addLogin(Login(options).toLoginInfo()); michael@0: }; michael@0: michael@0: /** michael@0: * Removes login info from the applications built-in login management system. michael@0: * _Please note: When removing a login info the specified properties must michael@0: * exactly match to the one that is already stored or exception will be thrown._ michael@0: * @param {Object} options. michael@0: */ michael@0: exports.remove = function remove(options) { michael@0: loginManager.removeLogin(Login(options).toLoginInfo()); michael@0: };