зеркало из https://github.com/mozilla/pjs.git
Bug 378667: Better "passwords for given realm" query support. r=gavin
This commit is contained in:
Родитель
91e5a21d63
Коммит
e3136176b4
|
@ -319,10 +319,7 @@ function realmHasPasswords(location) {
|
|||
var realm = makeURI(location).prePath;
|
||||
var passwordManager = Components.classes["@mozilla.org/login-manager;1"]
|
||||
.getService(Components.interfaces.nsILoginManager);
|
||||
var passwords = passwordManager.getAllLogins({});
|
||||
|
||||
// XXX untested
|
||||
return passwords.some(function (login) { return (login.hostname == realm); });
|
||||
return passwordManager.countLogins(realm, "", "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -180,6 +180,28 @@ interface nsILoginManager : nsISupports {
|
|||
[retval, array, size_is(count)] out nsILoginInfo logins);
|
||||
|
||||
|
||||
/**
|
||||
* Search for logins matching the specified criteria, as with
|
||||
* findLogins(). This interface only returns the number of matching
|
||||
* logins (and not the logins themselves), which allows a caller to
|
||||
* check for logins without causing the user to be prompted for a master
|
||||
* password to decrypt the logins.
|
||||
*
|
||||
* @param aHostname
|
||||
* The hostname to restrict searches to.
|
||||
* @param aActionURL
|
||||
* The URL to which a form login will be submitted. To match any
|
||||
* form login, specify an empty string. To not match any form
|
||||
* login, specify null.
|
||||
* @param aHttpRealm
|
||||
* The HTTP Realm for which the login applies. To match logins for
|
||||
* any realm, specify an empty string. To not match logins for any
|
||||
* realm, specify null.
|
||||
*/
|
||||
unsigned long countLogins(in AString aHostname, in AString aActionURL,
|
||||
in AString aHttpRealm);
|
||||
|
||||
|
||||
/**
|
||||
* Generate results for a userfield autocomplete menu.
|
||||
*
|
||||
|
|
|
@ -202,4 +202,26 @@ interface nsILoginManagerStorage : nsISupports {
|
|||
void findLogins(out unsigned long count, in AString aHostname,
|
||||
in AString aActionURL, in AString aHttpRealm,
|
||||
[retval, array, size_is(count)] out nsILoginInfo logins);
|
||||
|
||||
|
||||
/**
|
||||
* Search for logins matching the specified criteria, as with
|
||||
* findLogins(). This interface only returns the number of matching
|
||||
* logins (and not the logins themselves), which allows a caller to
|
||||
* check for logins without causing the user to be prompted for a master
|
||||
* password to decrypt the logins.
|
||||
*
|
||||
* @param aHostname
|
||||
* The hostname to restrict searches to.
|
||||
* @param aActionURL
|
||||
* The URL to which a form login will be submitted. To match any
|
||||
* form login, specify an empty string. To not match any form
|
||||
* login, specify null.
|
||||
* @param aHttpRealm
|
||||
* The HTTP Realm for which the login applies. To match logins for
|
||||
* any realm, specify an empty string. To not match logins for any
|
||||
* realm, specify null.
|
||||
*/
|
||||
unsigned long countLogins(in AString aHostname, in AString aActionURL,
|
||||
in AString aHttpRealm);
|
||||
};
|
||||
|
|
|
@ -470,8 +470,7 @@ LoginManager.prototype = {
|
|||
/*
|
||||
* findLogins
|
||||
*
|
||||
* Search the known logins for entries matching the specified criteria
|
||||
* for a protocol login (eg HTTP Auth).
|
||||
* Search for the known logins for entries matching the specified criteria.
|
||||
*/
|
||||
findLogins : function (count, hostname, formSubmitURL, httpRealm) {
|
||||
this.log("Searching for logins matching host: " + hostname +
|
||||
|
@ -482,6 +481,20 @@ LoginManager.prototype = {
|
|||
},
|
||||
|
||||
|
||||
/*
|
||||
* countLogins
|
||||
*
|
||||
* Search for the known logins for entries matching the specified criteria,
|
||||
* returns only the count.
|
||||
*/
|
||||
countLogins : function (hostname, formSubmitURL, httpRealm) {
|
||||
this.log("Counting logins matching host: " + hostname +
|
||||
", formSubmitURL: " + formSubmitURL + ", httpRealm: " + httpRealm);
|
||||
|
||||
return this._storage.countLogins(hostname, formSubmitURL, httpRealm);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* getLoginSavingEnabled
|
||||
*
|
||||
|
|
|
@ -324,32 +324,12 @@ LoginManagerStorage_legacy.prototype = {
|
|||
*
|
||||
*/
|
||||
findLogins : function (count, hostname, formSubmitURL, httpRealm) {
|
||||
var hostLogins = this._logins[hostname];
|
||||
if (hostLogins == null) {
|
||||
count.value = 0;
|
||||
return [];
|
||||
}
|
||||
var userCanceled;
|
||||
|
||||
var result = [], userCanceled;
|
||||
|
||||
for each (var login in hostLogins) {
|
||||
|
||||
// If looking for an HTTP login, make sure the httpRealms match.
|
||||
if (httpRealm != login.httpRealm)
|
||||
continue;
|
||||
|
||||
// If looking for a form login, make sure the action URLs match
|
||||
// ...unless the stored login is blank (not null), which means
|
||||
// login was stored before we started keeping the action URL.
|
||||
if (formSubmitURL != login.formSubmitURL &&
|
||||
login.formSubmitURL != "")
|
||||
continue;
|
||||
|
||||
result.push(login);
|
||||
}
|
||||
var logins = this._searchLogins(hostname, formSubmitURL, httpRealm);
|
||||
|
||||
// Decrypt entries found for the caller.
|
||||
[result, userCanceled] = this._decryptLogins(result);
|
||||
[logins, userCanceled] = this._decryptLogins(logins);
|
||||
|
||||
// We want to throw in this case, so that the Login Manager
|
||||
// knows to stop processing forms on the page so the user isn't
|
||||
|
@ -357,8 +337,19 @@ LoginManagerStorage_legacy.prototype = {
|
|||
if (userCanceled)
|
||||
throw "User canceled Master Password entry";
|
||||
|
||||
count.value = result.length; // needed for XPCOM
|
||||
return result;
|
||||
count.value = logins.length; // needed for XPCOM
|
||||
return logins;
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* countLogins
|
||||
*
|
||||
*/
|
||||
countLogins : function (hostname, formSubmitURL, httpRealm) {
|
||||
var logins = this._searchLogins(hostname, formSubmitURL, httpRealm);
|
||||
|
||||
return logins.length;
|
||||
},
|
||||
|
||||
|
||||
|
@ -369,6 +360,54 @@ LoginManagerStorage_legacy.prototype = {
|
|||
|
||||
|
||||
|
||||
/*
|
||||
* _searchLogins
|
||||
*
|
||||
*/
|
||||
_searchLogins : function (hostname, formSubmitURL, httpRealm) {
|
||||
var hostLogins = this._logins[hostname];
|
||||
if (hostLogins == null)
|
||||
return [];
|
||||
|
||||
var result = [], userCanceled;
|
||||
|
||||
for each (var login in hostLogins) {
|
||||
|
||||
// If search arg is null, skip login unless it doesn't specify a
|
||||
// httpRealm (ie, it's also null). If the seach arg is an empty
|
||||
// string, always match.
|
||||
if (httpRealm == null) {
|
||||
if (login.httpRealm != null)
|
||||
continue;
|
||||
} else if (httpRealm != "") {
|
||||
// Make sure the realms match. If search arg is null,
|
||||
// only match if login doesn't specify a realm (is null)
|
||||
if (httpRealm != login.httpRealm)
|
||||
continue;
|
||||
}
|
||||
|
||||
// If search arg is null, skip login unless it doesn't specify a
|
||||
// action URL (ie, it's also null). If the seach arg is an empty
|
||||
// string, always match.
|
||||
if (formSubmitURL == null) {
|
||||
if (login.formSubmitURL != null)
|
||||
continue;
|
||||
} else if (formSubmitURL != "") {
|
||||
// If the stored login is blank (not null), that means the
|
||||
// login was stored before we started keeping the action
|
||||
// URL, so always match. Unless the search g
|
||||
if (login.formSubmitURL != "" &&
|
||||
formSubmitURL != login.formSubmitURL)
|
||||
continue;
|
||||
}
|
||||
|
||||
result.push(login);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* _getSignonsFile
|
||||
*
|
||||
|
@ -547,7 +586,11 @@ LoginManagerStorage_legacy.prototype = {
|
|||
|
||||
// Line is the action URL
|
||||
case STATE.ACTIONURL:
|
||||
entry.formSubmitURL = line.value;
|
||||
var formSubmitURL = line.value;
|
||||
if (!formSubmitURL && entry.httpRealm)
|
||||
entry.formSubmitURL = null;
|
||||
else
|
||||
entry.formSubmitURL = formSubmitURL;
|
||||
processEntry = true;
|
||||
parseState = STATE.USERFIELD;
|
||||
break;
|
||||
|
|
|
@ -112,6 +112,14 @@ testdesc = "Initialize with signons-05.txt (0 disabled, 1 login)";
|
|||
|
||||
LoginTest.initStorage(storage, INDIR, "signons-05.txt");
|
||||
LoginTest.checkStorageData(storage, [], [testuser1]);
|
||||
// counting logins matching host
|
||||
do_check_eq(1, storage.countLogins("http://dummyhost.mozilla.org", "", null));
|
||||
// counting logins matching host (login has blank actionURL)
|
||||
do_check_eq(1, storage.countLogins("http://dummyhost.mozilla.org", "foo", null));
|
||||
// counting logins (don't match form login for HTTP search)
|
||||
do_check_eq(0, storage.countLogins("http://dummyhost.mozilla.org", null, ""));
|
||||
// counting logins (don't match a bogus hostname)
|
||||
do_check_eq(0, storage.countLogins("blah", "", ""));
|
||||
|
||||
|
||||
/* ========== 9 ========== */
|
||||
|
@ -128,6 +136,14 @@ testdesc = "Initialize with signons-07.txt (0 disabled, 2 logins on same host)";
|
|||
|
||||
LoginTest.initStorage(storage, INDIR, "signons-07.txt");
|
||||
LoginTest.checkStorageData(storage, [], [testuser1, testuser2]);
|
||||
// counting logins matching host
|
||||
do_check_eq(2, storage.countLogins("http://dummyhost.mozilla.org", "", null));
|
||||
// counting logins matching host (login has blank actionURL)
|
||||
do_check_eq(2, storage.countLogins("http://dummyhost.mozilla.org", "foo", null));
|
||||
// counting logins (don't match form login for HTTP search)
|
||||
do_check_eq(0, storage.countLogins("http://dummyhost.mozilla.org", null, ""));
|
||||
// counting logins (don't match a bogus hostname)
|
||||
do_check_eq(0, storage.countLogins("blah", "", ""));
|
||||
|
||||
|
||||
/* ========== 11 ========== */
|
||||
|
@ -150,6 +166,10 @@ for (i = 1; i <= 500; i++) {
|
|||
}
|
||||
LoginTest.checkStorageData(storage, disabledHosts, logins);
|
||||
|
||||
// counting all logins for dummyhost
|
||||
do_check_eq(500, storage.countLogins("http://dummyhost.site.org", "", ""));
|
||||
// counting all logins for dummyhost-1
|
||||
do_check_eq(1, storage.countLogins("http://dummyhost-1.site.org", "", ""));
|
||||
|
||||
} catch (e) {
|
||||
throw "FAILED in test #" + testnum + " -- " + testdesc + ": " + e;
|
||||
|
|
|
@ -198,6 +198,14 @@ LoginTest.initStorage(storage, OUTDIR, "output-05.txt", null, null);
|
|||
testdesc = "Verify output-05.txt";
|
||||
LoginTest.checkStorageData(storage, [], [dummyuser1, dummyuser2, dummyuser3]);
|
||||
|
||||
// count dummyhost2 logins
|
||||
do_check_eq(2, storage.countLogins("http://dummyhost2.mozilla.org", "", ""));
|
||||
// count dummyhost logins
|
||||
do_check_eq(1, storage.countLogins("http://dummyhost.mozilla.org", "", ""));
|
||||
|
||||
// count dummyhost2 logins w/ specific formSubmitURL
|
||||
do_check_eq(2, storage.countLogins("http://dummyhost2.mozilla.org", "http://cgi.site.com", ""));
|
||||
|
||||
/* ========== 10 ========== */
|
||||
testnum++;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче