зеркало из https://github.com/mozilla/pjs.git
Bug 477917 - expose login GUIDs through login manager API. r=gavin
This commit is contained in:
Родитель
5283b55f60
Коммит
9384b7cc85
|
@ -46,6 +46,7 @@ XPIDL_MODULE = loginmgr
|
|||
|
||||
XPIDLSRCS = \
|
||||
nsILoginInfo.idl \
|
||||
nsILoginMetaInfo.idl \
|
||||
nsILoginManager.idl \
|
||||
nsILoginManagerStorage.idl \
|
||||
nsILoginManagerPrompter.idl \
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(9c87a9bd-bf8b-4fae-bdb8-70513b2877df)]
|
||||
[scriptable, uuid(c41b7dff-6b9b-42fe-b78d-113051facb05)]
|
||||
|
||||
/**
|
||||
* An object containing information for a login stored by the
|
||||
|
@ -134,6 +134,15 @@ interface nsILoginInfo : nsISupports {
|
|||
* If true, ignore the password when checking for match.
|
||||
*/
|
||||
boolean matches(in nsILoginInfo aLoginInfo, in boolean ignorePassword);
|
||||
|
||||
/**
|
||||
* Create an identical copy of the login, duplicating all of the login's
|
||||
* nsILoginInfo and nsILoginMetaInfo properties.
|
||||
*
|
||||
* This allows code to be forwards-compatible, when additional properties
|
||||
* are added to nsILoginMetaInfo (or nsILoginInfo) in the future.
|
||||
*/
|
||||
nsILoginInfo clone();
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
|
|
@ -43,7 +43,7 @@ interface nsIAutoCompleteResult;
|
|||
interface nsIDOMHTMLInputElement;
|
||||
interface nsIDOMHTMLFormElement;
|
||||
|
||||
[scriptable, uuid(04dbfa30-4238-11dd-ae16-0800200c9a66)]
|
||||
[scriptable, uuid(9c78bfc1-422b-4f4f-ba09-f7eb3c4e72b2)]
|
||||
|
||||
interface nsILoginManager : nsISupports {
|
||||
|
||||
|
@ -52,6 +52,10 @@ interface nsILoginManager : nsISupports {
|
|||
*
|
||||
* @param aLogin
|
||||
* The login to be added.
|
||||
*
|
||||
* Default values for the login's nsILoginMetaInfo properties will be
|
||||
* created. However, if the caller specifies non-default values, they will
|
||||
* be used instead.
|
||||
*/
|
||||
void addLogin(in nsILoginInfo aLogin);
|
||||
|
||||
|
@ -61,6 +65,9 @@ interface nsILoginManager : nsISupports {
|
|||
*
|
||||
* @param aLogin
|
||||
* The login to be removed.
|
||||
*
|
||||
* The specified login must exactly match a stored login. However, the
|
||||
* values of any nsILoginMetaInfo properties are ignored.
|
||||
*/
|
||||
void removeLogin(in nsILoginInfo aLogin);
|
||||
|
||||
|
@ -68,10 +75,20 @@ interface nsILoginManager : nsISupports {
|
|||
/**
|
||||
* Modify an existing login in the login manager.
|
||||
*
|
||||
* @param aLogin
|
||||
* @param oldLogin
|
||||
* The login to be modified.
|
||||
* @param newLoginData
|
||||
* The new login values (either a nsILoginInfo or nsIProperyBag)
|
||||
*
|
||||
* If newLoginData is a nsILoginInfo, all of the old login's nsILoginInfo
|
||||
* properties are changed to the values from newLoginData (but the old
|
||||
* login's nsILoginMetaInfo properties are unmodified).
|
||||
*
|
||||
* If newLoginData is a nsIPropertyBag, only the specified properties
|
||||
* will be changed. The nsILoginMetaInfo properties of oldLogin can be
|
||||
* changed in this manner.
|
||||
*/
|
||||
void modifyLogin(in nsILoginInfo oldLogin, in nsILoginInfo newLogin);
|
||||
void modifyLogin(in nsILoginInfo oldLogin, in nsISupports newLoginData);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
interface nsIFile;
|
||||
interface nsILoginInfo;
|
||||
|
||||
[scriptable, uuid(dec624d1-18ea-40ea-8ca5-69002153c8b8)]
|
||||
[scriptable, uuid(199ebbff-4656-4a18-8da9-9401c64619f9)]
|
||||
|
||||
/*
|
||||
* NOTE: This interface is intended to be implemented by modules
|
||||
|
@ -71,30 +71,47 @@ interface nsILoginManagerStorage : nsISupports {
|
|||
|
||||
|
||||
/**
|
||||
* Store a new login.
|
||||
* Store a new login in the storage module.
|
||||
*
|
||||
* @param aLogin
|
||||
* The login to be added.
|
||||
*
|
||||
* Default values for the login's nsILoginMetaInfo properties will be
|
||||
* created. However, if the caller specifies non-default values, they will
|
||||
* be used instead.
|
||||
*/
|
||||
void addLogin(in nsILoginInfo aLogin);
|
||||
|
||||
|
||||
/**
|
||||
* Remove a login from the login manager.
|
||||
* Remove a login from the storage module.
|
||||
*
|
||||
* @param aLogin
|
||||
* The login to be removed.
|
||||
*
|
||||
* The specified login must exactly match a stored login. However, the
|
||||
* values of any nsILoginMetaInfo properties are ignored.
|
||||
*/
|
||||
void removeLogin(in nsILoginInfo aLogin);
|
||||
|
||||
|
||||
/**
|
||||
* Modify an existing login in the login manager.
|
||||
* Modify an existing login in the storage module.
|
||||
*
|
||||
* @param aLogin
|
||||
* @param oldLogin
|
||||
* The login to be modified.
|
||||
* @param newLoginData
|
||||
* The new login values (either a nsILoginInfo or nsIProperyBag)
|
||||
*
|
||||
* If newLoginData is a nsILoginInfo, all of the old login's nsILoginInfo
|
||||
* properties are changed to the values from newLoginData (but the old
|
||||
* login's nsILoginMetaInfo properties are unmodified).
|
||||
*
|
||||
* If newLoginData is a nsIPropertyBag, only the specified properties
|
||||
* will be changed. The nsILoginMetaInfo properties of oldLogin can be
|
||||
* changed in this manner.
|
||||
*/
|
||||
void modifyLogin(in nsILoginInfo oldLogin, in nsILoginInfo newLogin);
|
||||
void modifyLogin(in nsILoginInfo oldLogin, in nsISupports newLoginData);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Justin Dolske <dolske@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(867407d5-10e0-43a0-bc81-a324740534ca)]
|
||||
|
||||
/**
|
||||
* An object containing metainfo for a login stored by the login manager.
|
||||
*
|
||||
* Code using login manager can generally ignore this interface. When adding
|
||||
* logins, default value will be created. When modifying logins, these
|
||||
* properties will be unchanged unless a change is explicitly requested [by
|
||||
* using modifyLogin() with a nsIPropertyBag]. When deleting a login or
|
||||
* comparing logins, these properties are ignored.
|
||||
*/
|
||||
interface nsILoginMetaInfo : nsISupports {
|
||||
/**
|
||||
* The GUID to uniquely identify the login. This can be any arbitrary
|
||||
* string, but a format as created by nsIUUIDGenerator is recommended.
|
||||
* For example, "{d4e1a1f6-5ea0-40ee-bff5-da57982f21cf}"
|
||||
*
|
||||
* addLogin will generate a random value unless a value is provided.
|
||||
*
|
||||
* addLogin and modifyLogin will throw if the GUID already exists.
|
||||
*/
|
||||
attribute AString guid;
|
||||
};
|
|
@ -47,7 +47,7 @@ nsLoginInfo.prototype = {
|
|||
classDescription : "LoginInfo",
|
||||
contractID : "@mozilla.org/login-manager/loginInfo;1",
|
||||
classID : Components.ID("{0f2f347c-1e4f-40cc-8efd-792dea70a85e}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsILoginInfo]),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsILoginInfo, Ci.nsILoginMetaInfo]),
|
||||
|
||||
// Allow storage-Legacy.js to get at the JS object so it can
|
||||
// slap on a few extra properties for internal use.
|
||||
|
@ -55,6 +55,10 @@ nsLoginInfo.prototype = {
|
|||
return this;
|
||||
},
|
||||
|
||||
//
|
||||
// nsILoginInfo interfaces...
|
||||
//
|
||||
|
||||
hostname : null,
|
||||
formSubmitURL : null,
|
||||
httpRealm : null,
|
||||
|
@ -105,7 +109,27 @@ nsLoginInfo.prototype = {
|
|||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
clone : function() {
|
||||
let clone = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
clone.init(this.hostname, this.formSubmitURL, this.httpRealm,
|
||||
this.username, this.password,
|
||||
this.usernameField, this.passwordField);
|
||||
|
||||
// Copy nsILoginMetaInfo props
|
||||
clone.QueryInterface(Ci.nsILoginMetaInfo);
|
||||
clone.guid = this.guid;
|
||||
|
||||
return clone;
|
||||
},
|
||||
|
||||
//
|
||||
// nsILoginMetaInfo interfaces...
|
||||
//
|
||||
|
||||
guid : null
|
||||
|
||||
}; // end of nsLoginInfo implementation
|
||||
|
||||
|
|
|
@ -311,6 +311,9 @@ LoginManagerStorage_legacy.prototype = {
|
|||
*
|
||||
*/
|
||||
modifyLogin : function (oldLogin, newLogin) {
|
||||
if (newLogin instanceof Ci.nsIPropertyBag)
|
||||
throw "legacy modifyLogin with propertybag not implemented.";
|
||||
newLogin.QueryInterface(Ci.nsILoginInfo);
|
||||
// Throws if there are bogus values.
|
||||
this._checkLoginValues(newLogin);
|
||||
|
||||
|
|
|
@ -271,7 +271,17 @@ LoginManagerStorage_mozStorage.prototype = {
|
|||
throw "User canceled master password entry, login not added.";
|
||||
}
|
||||
|
||||
let guid = this._uuidService.generateUUID().toString();
|
||||
// Clone the login, so we don't modify the caller's object.
|
||||
let loginClone = login.clone();
|
||||
|
||||
// Initialize the nsILoginMetaInfo fields, unless the caller gave us values
|
||||
loginClone.QueryInterface(Ci.nsILoginMetaInfo);
|
||||
if (loginClone.guid) {
|
||||
if (!this._isGuidUnique(loginClone.guid))
|
||||
throw "specified GUID already exists";
|
||||
} else {
|
||||
loginClone.guid = this._uuidService.generateUUID().toString();
|
||||
}
|
||||
|
||||
let query =
|
||||
"INSERT INTO moz_logins " +
|
||||
|
@ -283,14 +293,14 @@ LoginManagerStorage_mozStorage.prototype = {
|
|||
":guid)";
|
||||
|
||||
let params = {
|
||||
hostname: login.hostname,
|
||||
httpRealm: login.httpRealm,
|
||||
formSubmitURL: login.formSubmitURL,
|
||||
usernameField: login.usernameField,
|
||||
passwordField: login.passwordField,
|
||||
hostname: loginClone.hostname,
|
||||
httpRealm: loginClone.httpRealm,
|
||||
formSubmitURL: loginClone.formSubmitURL,
|
||||
usernameField: loginClone.usernameField,
|
||||
passwordField: loginClone.passwordField,
|
||||
encryptedUsername: encUsername,
|
||||
encryptedPassword: encPassword,
|
||||
guid: guid
|
||||
guid: loginClone.guid
|
||||
};
|
||||
|
||||
let stmt;
|
||||
|
@ -311,7 +321,7 @@ LoginManagerStorage_mozStorage.prototype = {
|
|||
*
|
||||
*/
|
||||
removeLogin : function (login) {
|
||||
let idToDelete = this._getIdForLogin(login);
|
||||
let [idToDelete, storedLogin] = this._getIdForLogin(login);
|
||||
if (!idToDelete)
|
||||
throw "No matching logins";
|
||||
|
||||
|
@ -335,13 +345,60 @@ LoginManagerStorage_mozStorage.prototype = {
|
|||
* modifyLogin
|
||||
*
|
||||
*/
|
||||
modifyLogin : function (oldLogin, newLogin) {
|
||||
// Throws if there are bogus values.
|
||||
this._checkLoginValues(newLogin);
|
||||
|
||||
let idToModify = this._getIdForLogin(oldLogin);
|
||||
modifyLogin : function (oldLogin, newLoginData) {
|
||||
let [idToModify, oldStoredLogin] = this._getIdForLogin(oldLogin);
|
||||
if (!idToModify)
|
||||
throw "No matching logins";
|
||||
oldStoredLogin.QueryInterface(Ci.nsILoginMetaInfo);
|
||||
|
||||
let newLogin;
|
||||
if (newLoginData instanceof Ci.nsILoginInfo) {
|
||||
// Clone the existing login to get its nsILoginMetaInfo, then init it
|
||||
// with the replacement nsILoginInfo data from the new login.
|
||||
newLogin = oldStoredLogin.clone();
|
||||
newLogin.init(newLoginData.hostname,
|
||||
newLoginData.formSubmitURL, newLoginData.httpRealm,
|
||||
newLoginData.username, newLoginData.password,
|
||||
newLoginData.usernameField, newLoginData.passwordField);
|
||||
newLogin.QueryInterface(Ci.nsILoginMetaInfo);
|
||||
} else if (newLoginData instanceof Ci.nsIPropertyBag) {
|
||||
// Clone the existing login, along with all its properties.
|
||||
newLogin = oldStoredLogin.clone();
|
||||
newLogin.QueryInterface(Ci.nsILoginMetaInfo);
|
||||
|
||||
let propEnum = newLoginData.enumerator;
|
||||
while (propEnum.hasMoreElements()) {
|
||||
let prop = propEnum.getNext().QueryInterface(Ci.nsIProperty);
|
||||
switch (prop.name) {
|
||||
// nsILoginInfo properties...
|
||||
case "hostname":
|
||||
case "httpRealm":
|
||||
case "formSubmitURL":
|
||||
case "username":
|
||||
case "password":
|
||||
case "usernameField":
|
||||
case "passwordField":
|
||||
newLogin[prop.name] = prop.value;
|
||||
break;
|
||||
|
||||
// nsILoginMetaInfo properties...
|
||||
case "guid":
|
||||
newLogin.guid = prop.value;
|
||||
if (!this._isGuidUnique(newLogin.guid))
|
||||
throw "specified GUID already exists";
|
||||
break;
|
||||
|
||||
// Fail if caller requests setting an unknown property.
|
||||
default:
|
||||
throw "Unexpected propertybag item: " + prop.name;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw "newLoginData needs an expected interface!";
|
||||
}
|
||||
|
||||
// Throws if there are bogus values.
|
||||
this._checkLoginValues(newLogin);
|
||||
|
||||
// Get the encrypted value of the username and password.
|
||||
let [encUsername, encPassword, userCanceled] = this._encryptLogin(newLogin);
|
||||
|
@ -356,10 +413,12 @@ LoginManagerStorage_mozStorage.prototype = {
|
|||
"usernameField = :usernameField, " +
|
||||
"passwordField = :passwordField, " +
|
||||
"encryptedUsername = :encryptedUsername, " +
|
||||
"encryptedPassword = :encryptedPassword " +
|
||||
"encryptedPassword = :encryptedPassword, " +
|
||||
"guid = :guid " +
|
||||
"WHERE id = :id";
|
||||
|
||||
let params = {
|
||||
id: idToModify,
|
||||
hostname: newLogin.hostname,
|
||||
httpRealm: newLogin.httpRealm,
|
||||
formSubmitURL: newLogin.formSubmitURL,
|
||||
|
@ -367,8 +426,7 @@ LoginManagerStorage_mozStorage.prototype = {
|
|||
passwordField: newLogin.passwordField,
|
||||
encryptedUsername: encUsername,
|
||||
encryptedPassword: encPassword,
|
||||
id: idToModify
|
||||
// guid not changed
|
||||
guid: newLogin.guid
|
||||
};
|
||||
|
||||
let stmt;
|
||||
|
@ -552,13 +610,15 @@ LoginManagerStorage_mozStorage.prototype = {
|
|||
/*
|
||||
* _getIdForLogin
|
||||
*
|
||||
* Returns the |id| for the specified login, or null if the login was not
|
||||
* found.
|
||||
* Returns an array with two items: [id, login]. If the login was not
|
||||
* found, both items will be null. The returned login contains the actual
|
||||
* stored login (useful for looking at the actual nsILoginMetaInfo values).
|
||||
*/
|
||||
_getIdForLogin : function (login) {
|
||||
let [logins, ids] =
|
||||
this._queryLogins(login.hostname, login.formSubmitURL, login.httpRealm);
|
||||
let id = null;
|
||||
let foundLogin = null;
|
||||
|
||||
// The specified login isn't encrypted, so we need to ensure
|
||||
// the logins we're comparing with are decrypted. We decrypt one entry
|
||||
|
@ -575,11 +635,12 @@ LoginManagerStorage_mozStorage.prototype = {
|
|||
continue;
|
||||
|
||||
// We've found a match, set id and break
|
||||
foundLogin = decryptedLogin;
|
||||
id = ids[i];
|
||||
break;
|
||||
}
|
||||
|
||||
return id;
|
||||
return [id, foundLogin];
|
||||
},
|
||||
|
||||
|
||||
|
@ -614,6 +675,9 @@ LoginManagerStorage_mozStorage.prototype = {
|
|||
stmt.row.httpRealm, stmt.row.encryptedUsername,
|
||||
stmt.row.encryptedPassword, stmt.row.usernameField,
|
||||
stmt.row.passwordField);
|
||||
// set nsILoginMetaInfo values
|
||||
login.QueryInterface(Ci.nsILoginMetaInfo);
|
||||
login.guid = stmt.row.guid;
|
||||
logins.push(login);
|
||||
ids.push(stmt.row.id);
|
||||
}
|
||||
|
@ -758,6 +822,30 @@ LoginManagerStorage_mozStorage.prototype = {
|
|||
},
|
||||
|
||||
|
||||
/*
|
||||
* _isGuidUnique
|
||||
*
|
||||
* Checks to see if the specified GUID already exists.
|
||||
*/
|
||||
_isGuidUnique : function (guid) {
|
||||
let query = "SELECT COUNT(1) AS numLogins FROM moz_logins WHERE guid = :guid";
|
||||
let params = { guid: guid };
|
||||
|
||||
let stmt, numLogins;
|
||||
try {
|
||||
stmt = this._dbCreateStatement(query, params);
|
||||
stmt.step();
|
||||
numLogins = stmt.row.numLogins;
|
||||
} catch (e) {
|
||||
this.log("_isGuidUnique failed: " + e.name + " : " + e.message);
|
||||
} finally {
|
||||
stmt.reset();
|
||||
}
|
||||
|
||||
return (numLogins == 0);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* _importLegacySignons
|
||||
*
|
||||
|
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Test suite for storage-mozStorage.js
|
||||
*
|
||||
* This test interfaces directly with the mozStorage password storage module,
|
||||
* bypassing the normal password manager usage.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
const STORAGE_TYPE = "mozStorage";
|
||||
|
||||
function run_test() {
|
||||
|
||||
try {
|
||||
|
||||
var testnum = 0;
|
||||
var testdesc = "Setup of nsLoginInfo test-users";
|
||||
var nsLoginInfo = new Components.Constructor(
|
||||
"@mozilla.org/login-manager/loginInfo;1",
|
||||
Components.interfaces.nsILoginInfo);
|
||||
do_check_true(nsLoginInfo != null);
|
||||
|
||||
var testuser1 = new nsLoginInfo;
|
||||
testuser1.QueryInterface(Ci.nsILoginMetaInfo);
|
||||
testuser1.init("http://testhost1", "", null,
|
||||
"dummydude", "itsasecret", "put_user_here", "put_pw_here");
|
||||
var guid1;
|
||||
|
||||
var testuser2 = new nsLoginInfo;
|
||||
testuser2.init("http://testhost2", "", null,
|
||||
"dummydude2", "itsasecret2", "put_user2_here", "put_pw2_here");
|
||||
testuser2.QueryInterface(Ci.nsILoginMetaInfo);
|
||||
var guid2 = "{12345678-abcd-1234-abcd-987654321000}";
|
||||
testuser2.guid = guid2;
|
||||
|
||||
var testuser3 = new nsLoginInfo;
|
||||
testuser3.QueryInterface(Ci.nsILoginMetaInfo);
|
||||
testuser3.init("http://testhost3", "", null,
|
||||
"dummydude3", "itsasecret3", "put_user3_here", "put_pw3_here");
|
||||
var guid3 = "{99999999-abcd-9999-abcd-999999999999}";
|
||||
|
||||
// This login is different than testuser2, except it has the same guid.
|
||||
var testuser2dupeguid = new nsLoginInfo;
|
||||
testuser2dupeguid.QueryInterface(Ci.nsILoginMetaInfo);
|
||||
testuser2dupeguid.init("http://dupe-testhost2", "", null,
|
||||
"dupe-dummydude2", "dupe-itsasecret2", "put_user2_here", "put_pw2_here");
|
||||
testuser2dupeguid.QueryInterface(Ci.nsILoginMetaInfo);
|
||||
testuser2dupeguid.guid = guid2;
|
||||
|
||||
var isGUID = /^\{[0-9a-f\d]{8}-[0-9a-f\d]{4}-[0-9a-f\d]{4}-[0-9a-f\d]{4}-[0-9a-f\d]{12}\}$/;
|
||||
|
||||
/* ========== 1 ========== */
|
||||
var testnum = 1;
|
||||
var testdesc = "Initial connection to storage module"
|
||||
|
||||
LoginTest.deleteFile(OUTDIR, "signons-unittest6.sqlite");
|
||||
|
||||
var storage;
|
||||
storage = LoginTest.initStorage(INDIR, "signons-empty.txt", OUTDIR, "signons-unittest6.sqlite");
|
||||
var logins = storage.getAllLogins({});
|
||||
do_check_eq(logins.length, 0, "Checking for no initial logins");
|
||||
var disabledHosts = storage.getAllDisabledHosts({});
|
||||
do_check_eq(disabledHosts.length, 0, "Checking for no initial disabled hosts");
|
||||
|
||||
|
||||
/* ========== 2 ========== */
|
||||
testnum++;
|
||||
testdesc = "add user1 w/o guid";
|
||||
|
||||
storage.addLogin(testuser1);
|
||||
LoginTest.checkStorageData(storage, [], [testuser1]);
|
||||
|
||||
// Check guid
|
||||
do_check_eq(testuser1.guid, null, "caller's login shouldn't be modified");
|
||||
logins = storage.findLogins({}, "http://testhost1", "", null);
|
||||
do_check_eq(logins.length, 1, "expecting 1 login");
|
||||
logins[0].QueryInterface(Ci.nsILoginMetaInfo);
|
||||
do_check_true(isGUID.test(logins[0].guid), "testuser1 guid is set");
|
||||
guid1 = logins[0].guid;
|
||||
|
||||
/* ========== 3 ========== */
|
||||
testnum++;
|
||||
testdesc = "add user2 WITH guid";
|
||||
|
||||
storage.addLogin(testuser2);
|
||||
LoginTest.checkStorageData(storage, [], [testuser1, testuser2]);
|
||||
|
||||
// Check guid
|
||||
do_check_eq(testuser2.guid, guid2, "caller's login shouldn't be modified");
|
||||
logins = storage.findLogins({}, "http://testhost2", "", null);
|
||||
do_check_eq(logins.length, 1, "expecting 1 login");
|
||||
logins[0].QueryInterface(Ci.nsILoginMetaInfo);
|
||||
do_check_true(isGUID.test(logins[0].guid), "testuser2 guid is set");
|
||||
do_check_eq(logins[0].guid, guid2, "checking guid2");
|
||||
|
||||
/* ========== 4 ========== */
|
||||
testnum++;
|
||||
testdesc = "add user3 w/o guid";
|
||||
|
||||
storage.addLogin(testuser3);
|
||||
LoginTest.checkStorageData(storage, [], [testuser1, testuser2, testuser3]);
|
||||
logins = storage.findLogins({}, "http://testhost3", "", null);
|
||||
do_check_eq(logins.length, 1, "expecting 1 login");
|
||||
logins[0].QueryInterface(Ci.nsILoginMetaInfo);
|
||||
do_check_true(isGUID.test(logins[0].guid), "testuser3 guid is set");
|
||||
do_check_neq(logins[0].guid, guid3, "testuser3 guid is different");
|
||||
|
||||
/* ========== 5 ========== */
|
||||
testnum++;
|
||||
testdesc = "(don't) modify user1";
|
||||
|
||||
// When newlogin.guid is blank, the GUID shouldn't be changed.
|
||||
testuser1.guid = "";
|
||||
storage.modifyLogin(testuser1, testuser1);
|
||||
|
||||
// Check it
|
||||
do_check_eq(testuser1.guid, "", "caller's login shouldn't be modified");
|
||||
logins = storage.findLogins({}, "http://testhost1", "", null);
|
||||
do_check_eq(logins.length, 1, "expecting 1 login");
|
||||
logins[0].QueryInterface(Ci.nsILoginMetaInfo);
|
||||
do_check_eq(logins[0].guid, guid1, "checking guid1");
|
||||
|
||||
/* ========== 6 ========== */
|
||||
testnum++;
|
||||
testdesc = "modify user3";
|
||||
|
||||
// change the GUID to our known value
|
||||
var propbag = Cc["@mozilla.org/hash-property-bag;1"].
|
||||
createInstance(Ci.nsIWritablePropertyBag);
|
||||
propbag.setProperty("guid", guid3);
|
||||
storage.modifyLogin(testuser3, propbag);
|
||||
|
||||
// Check it
|
||||
logins = storage.findLogins({}, "http://testhost3", "", null);
|
||||
do_check_eq(logins.length, 1, "expecting 1 login");
|
||||
logins[0].QueryInterface(Ci.nsILoginMetaInfo);
|
||||
do_check_eq(logins[0].guid, guid3, "checking guid3");
|
||||
|
||||
/* ========== 7 ========== */
|
||||
testnum++;
|
||||
testdesc = "try adding a duplicate guid";
|
||||
|
||||
var ex = null;
|
||||
try {
|
||||
storage.addLogin(testuser2dupeguid);
|
||||
} catch (e) {
|
||||
ex = e;
|
||||
}
|
||||
do_check_true(/specified GUID already exists/.test(ex), "ensuring exception thrown when adding duplicate GUID");
|
||||
LoginTest.checkStorageData(storage, [], [testuser1, testuser2, testuser3]);
|
||||
|
||||
/* ========== 8 ========== */
|
||||
testnum++;
|
||||
testdesc = "try modifing to a duplicate guid";
|
||||
|
||||
propbag = Cc["@mozilla.org/hash-property-bag;1"].
|
||||
createInstance(Ci.nsIWritablePropertyBag);
|
||||
propbag.setProperty("guid", testuser2dupeguid.guid);
|
||||
|
||||
ex = null;
|
||||
try {
|
||||
storage.modifyLogin(testuser1, propbag);
|
||||
} catch (e) {
|
||||
ex = e;
|
||||
}
|
||||
do_check_true(/specified GUID already exists/.test(ex), "ensuring exception thrown when modifying to duplicate GUID");
|
||||
LoginTest.checkStorageData(storage, [], [testuser1, testuser2, testuser3]);
|
||||
|
||||
|
||||
/* ========== 9 ========== */
|
||||
testnum++;
|
||||
testdesc = "check propertybag nulls/empty strings";
|
||||
|
||||
// Set formSubmitURL to a null, and usernameField to a empty-string.
|
||||
do_check_eq(testuser3.formSubmitURL, "");
|
||||
do_check_eq(testuser3.httpRealm, null);
|
||||
do_check_eq(testuser3.usernameField, "put_user3_here");
|
||||
propbag = Cc["@mozilla.org/hash-property-bag;1"].
|
||||
createInstance(Ci.nsIWritablePropertyBag);
|
||||
propbag.setProperty("formSubmitURL", null);
|
||||
propbag.setProperty("httpRealm", "newRealm");
|
||||
propbag.setProperty("usernameField", "");
|
||||
|
||||
storage.modifyLogin(testuser3, propbag);
|
||||
|
||||
// Fixup testuser3 to match the new values.
|
||||
testuser3.formSubmitURL = null;
|
||||
testuser3.httpRealm = "newRealm";
|
||||
testuser3.usernameField = "";
|
||||
LoginTest.checkStorageData(storage, [], [testuser1, testuser2, testuser3]);
|
||||
|
||||
|
||||
/* ========== 10 ========== */
|
||||
testnum++;
|
||||
testdesc = "[reinit storage, look for expected guids]";
|
||||
|
||||
storage = LoginTest.reloadStorage(OUTDIR, "signons-unittest6.sqlite");
|
||||
LoginTest.checkStorageData(storage, [], [testuser1, testuser2, testuser3]);
|
||||
|
||||
logins = storage.findLogins({}, "http://testhost1", "", null);
|
||||
do_check_eq(logins.length, 1, "expecting 1 login");
|
||||
logins[0].QueryInterface(Ci.nsILoginMetaInfo);
|
||||
do_check_eq(logins[0].guid, guid1, "checking guid1");
|
||||
|
||||
logins = storage.findLogins({}, "http://testhost2", "", null);
|
||||
do_check_eq(logins.length, 1, "expecting 1 login");
|
||||
logins[0].QueryInterface(Ci.nsILoginMetaInfo);
|
||||
do_check_eq(logins[0].guid, guid2, "checking guid2");
|
||||
|
||||
logins = storage.findLogins({}, "http://testhost3", null, "newRealm");
|
||||
do_check_eq(logins.length, 1, "expecting 1 login");
|
||||
logins[0].QueryInterface(Ci.nsILoginMetaInfo);
|
||||
do_check_eq(logins[0].guid, guid3, "checking guid3");
|
||||
|
||||
|
||||
/* ========== 11 ========== */
|
||||
testnum++;
|
||||
testdesc = "login w/o nsILoginMetaInfo impl";
|
||||
|
||||
var wonkyDelegate = new nsLoginInfo;
|
||||
wonkyDelegate.init("http://wonky", null, "wonkyness",
|
||||
"wonkyuser", "wonkypass", "u", "p");
|
||||
|
||||
var wonkyLogin = {
|
||||
QueryInterface : function (iid) {
|
||||
var interfaces = [Ci.nsILoginInfo, Ci.nsISupports];
|
||||
if (!interfaces.some( function(v) { return iid.equals(v) }))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
},
|
||||
hostname: wonkyDelegate.hostname,
|
||||
formSubmitURL: wonkyDelegate.formSubmitURL,
|
||||
httpRealm: wonkyDelegate.httpRealm,
|
||||
username: wonkyDelegate.username,
|
||||
password: wonkyDelegate.password,
|
||||
usernameField: wonkyDelegate.usernameField,
|
||||
passwordField: wonkyDelegate.passwordField,
|
||||
equals: wonkyDelegate.equals,
|
||||
matches: wonkyDelegate.matches,
|
||||
clone: wonkyDelegate.clone
|
||||
};
|
||||
|
||||
storage.addLogin(wonkyLogin);
|
||||
LoginTest.checkStorageData(storage, [], [testuser1, testuser2, testuser3, wonkyLogin]);
|
||||
|
||||
logins = storage.findLogins({}, "http://wonky", null, "");
|
||||
do_check_eq(logins.length, 1, "expecting 1 login");
|
||||
logins[0].QueryInterface(Ci.nsILoginMetaInfo);
|
||||
do_check_true(isGUID.test(logins[0].guid), "wonky guid is set");
|
||||
|
||||
storage.modifyLogin(wonkyLogin, wonkyLogin);
|
||||
LoginTest.checkStorageData(storage, [], [testuser1, testuser2, testuser3, wonkyLogin]);
|
||||
storage.removeLogin(wonkyLogin);
|
||||
LoginTest.checkStorageData(storage, [], [testuser1, testuser2, testuser3]);
|
||||
|
||||
|
||||
LoginTest.deleteFile(OUTDIR, "signons-unittest6.sqlite");
|
||||
|
||||
} catch (e) {
|
||||
throw "FAILED in test #" + testnum + " -- " + testdesc + ": " + e;
|
||||
}
|
||||
};
|
Загрузка…
Ссылка в новой задаче