зеркало из https://github.com/mozilla/pjs.git
Bug 374723: re-design password manager API and implement in JS rather than C++, patch by Justin Dolske <dolske@mozilla.com>, r=mconnor, r=me
This commit is contained in:
Родитель
5ceed539be
Коммит
f4d5367465
|
@ -969,7 +969,8 @@ toolkit/components/history/Makefile
|
|||
toolkit/components/history/public/Makefile
|
||||
toolkit/components/history/src/Makefile
|
||||
toolkit/components/passwordmgr/Makefile
|
||||
toolkit/components/passwordmgr/base/Makefile
|
||||
toolkit/components/passwordmgr/public/Makefile
|
||||
toolkit/components/passwordmgr/src/Makefile
|
||||
toolkit/components/passwordmgr/content/Makefile
|
||||
toolkit/components/passwordmgr/test/Makefile
|
||||
toolkit/components/places/Makefile
|
||||
|
|
|
@ -1023,6 +1023,9 @@ function delayedStartup()
|
|||
|
||||
window.addEventListener("keypress", ctrlNumberTabSelection, false);
|
||||
|
||||
// Ensure login manager is up and running.
|
||||
Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||
|
||||
if (gMustLoadSidebar) {
|
||||
var sidebar = document.getElementById("sidebar");
|
||||
var sidebarBox = document.getElementById("sidebar-box");
|
||||
|
|
|
@ -139,7 +139,7 @@ var security = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Open the password manager window
|
||||
* Open the login manager window
|
||||
*/
|
||||
viewPasswords : function()
|
||||
{
|
||||
|
@ -313,18 +313,12 @@ function realmHasPasswords(location) {
|
|||
return false;
|
||||
|
||||
var realm = makeURI(location).prePath;
|
||||
var passwordManager = Components.classes["@mozilla.org/passwordmanager;1"]
|
||||
.getService(Components.interfaces.nsIPasswordManager);
|
||||
var e = passwordManager.enumerator;
|
||||
while (e.hasMoreElements()) {
|
||||
var next = e.getNext().QueryInterface(Components.interfaces.nsIPassword);
|
||||
if (!next)
|
||||
continue;
|
||||
var passwordManager = Components.classes["@mozilla.org/login-manager;1"]
|
||||
.getService(Components.interfaces.nsILoginManager);
|
||||
var passwords = passwordManager.getAllLogins({});
|
||||
|
||||
if (realm == next.host)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
// XXX untested
|
||||
return passwords.some(function (login) { return (login.hostname == realm); });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -194,24 +194,17 @@ Sanitizer.prototype = {
|
|||
passwords: {
|
||||
clear: function ()
|
||||
{
|
||||
var pwmgr = Components.classes["@mozilla.org/passwordmanager;1"]
|
||||
.getService(Components.interfaces.nsIPasswordManager);
|
||||
var e = pwmgr.enumerator;
|
||||
var passwds = [];
|
||||
while (e.hasMoreElements()) {
|
||||
var passwd = e.getNext().QueryInterface(Components.interfaces.nsIPassword);
|
||||
passwds.push(passwd);
|
||||
}
|
||||
|
||||
for (var i = 0; i < passwds.length; ++i)
|
||||
pwmgr.removeUser(passwds[i].host, passwds[i].user);
|
||||
var pwmgr = Components.classes["@mozilla.org/login-manager;1"]
|
||||
.getService(Components.interfaces.nsILoginManager);
|
||||
pwmgr.removeAllLogins();
|
||||
},
|
||||
|
||||
get canClear()
|
||||
{
|
||||
var pwmgr = Components.classes["@mozilla.org/passwordmanager;1"]
|
||||
.getService(Components.interfaces.nsIPasswordManager);
|
||||
return pwmgr.enumerator.hasMoreElements();
|
||||
var pwmgr = Components.classes["@mozilla.org/login-manager;1"]
|
||||
.getService(Components.interfaces.nsILoginManager);
|
||||
var logins = pwmgr.getAllLogins({});
|
||||
return (logins.length > 0);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ REQUIRES = \
|
|||
libreg \
|
||||
browsercomps \
|
||||
toolkitcomps \
|
||||
passwordmgr \
|
||||
pref \
|
||||
rdf \
|
||||
satchel \
|
||||
|
|
|
@ -79,8 +79,8 @@
|
|||
#include "nsIGlobalHistory.h"
|
||||
#include "nsIRDFRemoteDataSource.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIPasswordManager.h"
|
||||
#include "nsIPasswordManagerInternal.h"
|
||||
#include "nsILoginManager.h"
|
||||
#include "nsILoginInfo.h"
|
||||
#include "nsIFormHistory.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIRDFContainer.h"
|
||||
|
@ -755,7 +755,7 @@ static GUID IEPStoreSiteAuthGUID = { 0x5e7e8100, 0x9138, 0x11d1, { 0x94, 0x5a, 0
|
|||
// username as a value in each such subkey's value list. If we have a match,
|
||||
// we assume that the subkey (with its uniquifier prefix) is a login field.
|
||||
//
|
||||
// With this information, we call Password Manager's "AddUserFull" method
|
||||
// With this information, we call Password Manager's "AddLogin" method
|
||||
// providing this detail. We don't need to provide the password field name,
|
||||
// we have no means of retrieving this info from IE, and the Password Manager
|
||||
// knows to hunt for a password field near the login field if none is specified.
|
||||
|
@ -808,7 +808,7 @@ nsIEProfileMigrator::CopyPasswords(PRBool aReplace)
|
|||
// We bail out if that's the case, because we can't handle those yet.
|
||||
// However, if everything is all and well, we convert the itemName to a realm
|
||||
// string that the password manager can work with and save this login
|
||||
// via AddUser.
|
||||
// via AddLogin.
|
||||
|
||||
nsresult
|
||||
nsIEProfileMigrator::MigrateSiteAuthSignons(IPStore* aPStore)
|
||||
|
@ -817,7 +817,7 @@ nsIEProfileMigrator::MigrateSiteAuthSignons(IPStore* aPStore)
|
|||
|
||||
NS_ENSURE_ARG_POINTER(aPStore);
|
||||
|
||||
nsCOMPtr<nsIPasswordManager> pwmgr(do_GetService("@mozilla.org/passwordmanager;1"));
|
||||
nsCOMPtr<nsILoginManager> pwmgr(do_GetService("@mozilla.org/login-manager;1"));
|
||||
if (!pwmgr)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -843,22 +843,31 @@ nsIEProfileMigrator::MigrateSiteAuthSignons(IPStore* aPStore)
|
|||
break;
|
||||
}
|
||||
|
||||
nsAutoString realm(itemName);
|
||||
if (Substring(realm, 0, 6).EqualsLiteral("DPAPI:")) // often FTP logins
|
||||
nsAutoString host(itemName), realm;
|
||||
if (Substring(host, 0, 6).EqualsLiteral("DPAPI:")) // often FTP logins
|
||||
password = NULL; // We can't handle these yet
|
||||
|
||||
if (password) {
|
||||
int idx;
|
||||
idx = realm.FindChar('/');
|
||||
idx = host.FindChar('/');
|
||||
if (idx) {
|
||||
realm.Replace(idx, 1, NS_LITERAL_STRING(" ("));
|
||||
realm.Append(')');
|
||||
realm.Assign(Substring(host, idx));
|
||||
host.Assign(Substring(host, 0, idx));
|
||||
}
|
||||
// XXX: username and password are always ASCII in IPStore?
|
||||
// If not, are they in UTF-8 or the default codepage? (ref. bug 41489)
|
||||
pwmgr->AddUser(NS_ConvertUTF16toUTF8(realm),
|
||||
NS_ConvertASCIItoUTF16((char *)data),
|
||||
NS_ConvertASCIItoUTF16((char *)password));
|
||||
nsresult rv;
|
||||
|
||||
ncCOMPtr<nsILoginInfo> aLogin (do_CreateInstance(NS_LOGININFO_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// TODO: Need to pass in nulls here, but XPCOM whines. Might be able
|
||||
// just pass in EmptyString(), and then force a flush to disk and
|
||||
// reinit, which should correct things in the storage module.
|
||||
|
||||
//aLogin->Init(host, nsnull, realm, data, password, nsnull, nsnull);
|
||||
|
||||
//pwmgr->AddLogin(aLogin);
|
||||
}
|
||||
::CoTaskMemFree(data);
|
||||
}
|
||||
|
@ -1000,7 +1009,7 @@ nsIEProfileMigrator::ResolveAndMigrateSignons(IPStore* aPStore, nsVoidArray* aSi
|
|||
void
|
||||
nsIEProfileMigrator::EnumerateUsernames(const nsAString& aKey, PRUnichar* aData, unsigned long aCount, nsVoidArray* aSignonsFound)
|
||||
{
|
||||
nsCOMPtr<nsIPasswordManagerInternal> pwmgr(do_GetService("@mozilla.org/passwordmanager;1"));
|
||||
nsCOMPtr<nsILoginManager> pwmgr(do_GetService("@mozilla.org/login-manager;1"));
|
||||
if (!pwmgr)
|
||||
return;
|
||||
|
||||
|
@ -1018,7 +1027,15 @@ nsIEProfileMigrator::EnumerateUsernames(const nsAString& aKey, PRUnichar* aData,
|
|||
// Bingo! Found a username in the saved data for this item. Now, add a Signon.
|
||||
nsDependentString usernameStr(sd->user), passStr(sd->pass);
|
||||
nsDependentCString realm(sd->realm);
|
||||
pwmgr->AddUserFull(realm, usernameStr, passStr, aKey, EmptyString());
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsILoginInfo> aLogin (do_CreateInstance(NS_LOGININFO_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aLogin->Init(realm, EmptyString(), nsnull, usernameStr, passStr, aKey, EmptyString());
|
||||
|
||||
pwmgr->AddLogin(aLogin);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,9 @@
|
|||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsICookieManager2.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPasswordManagerInternal.h"
|
||||
#include "nsILoginInfo.h"
|
||||
#include "nsILoginManager.h"
|
||||
#include "nsILoginManagerStorage.h"
|
||||
#include "nsIPrefLocalizedString.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
@ -682,12 +684,40 @@ nsSeamonkeyProfileMigrator::CopyPasswords(PRBool aReplace)
|
|||
if (aReplace)
|
||||
rv = CopyFile(fileName, fileName);
|
||||
else {
|
||||
nsCOMPtr<nsIFile> seamonkeyPasswordsFile;
|
||||
mSourceProfile->Clone(getter_AddRefs(seamonkeyPasswordsFile));
|
||||
seamonkeyPasswordsFile->Append(fileName);
|
||||
// Get the password manager, which is the destination for the passwords
|
||||
// being migrated. Also create a new instance of the legacy password
|
||||
// storage component, which we'll use to slurp in the signons from
|
||||
// Seamonkey's signons.txt.
|
||||
nsCOMPtr<nsILoginManager> pwmgr(
|
||||
do_GetService("@mozilla.org/login-manager;1"));
|
||||
nsCOMPtr<nsILoginManagerStorage> importer(
|
||||
do_CreateInstance("@mozilla.org/login-manager/storage/legacy;1"));
|
||||
|
||||
nsCOMPtr<nsIPasswordManagerInternal> pmi(do_GetService("@mozilla.org/passwordmanager;1"));
|
||||
rv = pmi->ReadPasswords(seamonkeyPasswordsFile);
|
||||
nsString pathName;
|
||||
nsCOMPtr<nsIFile> profileDir(do_QueryInterface(mSourceProfile));
|
||||
profileDir->GetPath(pathName);
|
||||
|
||||
importer->InitWithFile(pathName, fileName, EmptyString());
|
||||
|
||||
nsresult rv;
|
||||
PRUint32 count;
|
||||
nsILoginInfo **logins;
|
||||
|
||||
rv = importer->GetAllLogins(&count, &logins);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
for (count--; count >= 0; count--) {
|
||||
pwmgr->AddLogin(logins[count]);
|
||||
}
|
||||
NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
|
||||
|
||||
PRUnichar **hostnames;
|
||||
rv = importer->GetAllDisabledHosts(&count, &hostnames);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
for (count--; count >= 0; count--) {
|
||||
pwmgr->SetLoginSavingEnabled(nsDependentString(hostnames[count]),
|
||||
PR_FALSE);
|
||||
}
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, hostnames);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -1261,9 +1261,10 @@ nsHTMLFormElement::AddElement(nsIFormControl* aChild,
|
|||
if (!gPasswordManagerInitialized && type == NS_FORM_INPUT_PASSWORD) {
|
||||
// Initialize the password manager category
|
||||
gPasswordManagerInitialized = PR_TRUE;
|
||||
NS_CreateServicesFromCategory(NS_PASSWORDMANAGER_CATEGORY,
|
||||
nsnull,
|
||||
NS_PASSWORDMANAGER_CATEGORY);
|
||||
// TODO
|
||||
//NS_CreateServicesFromCategory(NS_PASSWORDMANAGER_CATEGORY,
|
||||
// nsnull,
|
||||
// NS_PASSWORDMANAGER_CATEGORY);
|
||||
}
|
||||
|
||||
// Default submit element handling
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#
|
||||
# Contributor(s):
|
||||
# Brian Ryner <bryner@brianryner.com>
|
||||
# Justin Dolske <dolske@mozilla.com>
|
||||
#
|
||||
# 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
|
||||
|
@ -42,7 +43,7 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = base content
|
||||
DIRS = public src content
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS += test
|
||||
|
|
|
@ -58,9 +58,10 @@ var signonsTreeView = {
|
|||
getCellText : function(row,column) {
|
||||
var rv="";
|
||||
if (column.id=="siteCol") {
|
||||
rv = signons[row].host;
|
||||
rv = signons[row].hostname;
|
||||
if (signons[row].httpRealm) { rv += " (" + signons[row].httpRealm + ")"; }
|
||||
} else if (column.id=="userCol") {
|
||||
rv = signons[row].user;
|
||||
rv = signons[row].username;
|
||||
} else if (column.id=="passwordCol") {
|
||||
rv = signons[row].password;
|
||||
}
|
||||
|
@ -75,64 +76,15 @@ var signonsTreeView = {
|
|||
getCellProperties : function(row,column,prop) {}
|
||||
};
|
||||
|
||||
function Signon(number, host, user, rawuser, password) {
|
||||
this.number = number;
|
||||
this.host = host;
|
||||
this.user = user;
|
||||
this.rawuser = rawuser;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
function LoadSignons() {
|
||||
// loads signons into table
|
||||
var enumerator = passwordmanager.enumerator;
|
||||
var count = 0;
|
||||
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var nextPassword;
|
||||
try {
|
||||
nextPassword = enumerator.getNext();
|
||||
} catch(e) {
|
||||
/* user supplied invalid database key */
|
||||
window.close();
|
||||
return false;
|
||||
}
|
||||
nextPassword = nextPassword.QueryInterface(Components.interfaces.nsIPassword);
|
||||
var host = nextPassword.host;
|
||||
var user;
|
||||
var password;
|
||||
// try/catch in case decryption fails (invalid signon entry)
|
||||
try {
|
||||
user = nextPassword.user;
|
||||
password = nextPassword.password;
|
||||
} catch (e) {
|
||||
// hide this entry
|
||||
dump("could not decrypt user/password for host " + host + "\n");
|
||||
continue;
|
||||
}
|
||||
var rawuser = user;
|
||||
|
||||
// if no username supplied, try to parse it out of the url
|
||||
if (user == "") {
|
||||
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
try {
|
||||
user = ioService.newURI(host, null, null).username;
|
||||
if (user == "") {
|
||||
user = "<>";
|
||||
}
|
||||
} catch(e) {
|
||||
user = "<>";
|
||||
}
|
||||
}
|
||||
|
||||
signons[count] = new Signon(count++, host, user, rawuser, password);
|
||||
}
|
||||
signons = passwordmanager.getAllLogins({});
|
||||
signonsTreeView.rowCount = signons.length;
|
||||
|
||||
// sort and display the table
|
||||
signonsTree.treeBoxObject.view = signonsTreeView;
|
||||
SignonColumnSort('host');
|
||||
SignonColumnSort('hostname');
|
||||
|
||||
// disable "remove all signons" button if there are no signons
|
||||
var element = document.getElementById("removeAllSignons");
|
||||
|
@ -226,7 +178,7 @@ function ConfirmShowPasswords() {
|
|||
|
||||
function FinalizeSignonDeletions() {
|
||||
for (var s=0; s<deletedSignons.length; s++) {
|
||||
passwordmanager.removeUser(deletedSignons[s].host, deletedSignons[s].rawuser);
|
||||
passwordmanager.removeLogin(deletedSignons[s]);
|
||||
}
|
||||
deletedSignons.length = 0;
|
||||
}
|
||||
|
|
|
@ -68,10 +68,10 @@
|
|||
onselect="SignonSelected();">
|
||||
<treecols>
|
||||
<treecol id="siteCol" label="&treehead.site.label;" flex="5"
|
||||
onclick="SignonColumnSort('host');" persist="width"/>
|
||||
onclick="SignonColumnSort('hostname');" persist="width"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="userCol" label="&treehead.username.label;" flex="2"
|
||||
onclick="SignonColumnSort('user');" persist="width"/>
|
||||
onclick="SignonColumnSort('username');" persist="width"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="passwordCol" label="&treehead.password.label;" flex="2"
|
||||
onclick="SignonColumnSort('password');" persist="width"
|
||||
|
|
|
@ -60,7 +60,8 @@ var showingPasswords = false;
|
|||
|
||||
function Startup() {
|
||||
// xpconnect to password manager interfaces
|
||||
passwordmanager = Components.classes["@mozilla.org/passwordmanager;1"].getService(Components.interfaces.nsIPasswordManager);
|
||||
passwordmanager = Components.classes["@mozilla.org/login-manager;1"]
|
||||
.getService(Components.interfaces.nsILoginManager);
|
||||
|
||||
// be prepared to reload the display if anything changes
|
||||
kObserverService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
|
||||
|
@ -83,13 +84,13 @@ var signonReloadDisplay = {
|
|||
if (topic == "signonChanged") {
|
||||
if (state == "signons") {
|
||||
signons.length = 0;
|
||||
if (lastSignonSortColumn == "host") {
|
||||
if (lastSignonSortColumn == "hostname") {
|
||||
lastSignonSortAscending = !lastSignonSortAscending; // prevents sort from being reversed
|
||||
}
|
||||
LoadSignons();
|
||||
} else if (state == "rejects") {
|
||||
rejects.length = 0;
|
||||
if (lastRejectSortColumn == "host") {
|
||||
if (lastRejectSortColumn == "hostname") {
|
||||
lastRejectSortAscending = !lastRejectSortAscending; // prevents sort from being reversed
|
||||
}
|
||||
LoadRejects();
|
||||
|
@ -254,8 +255,14 @@ function SortTree(tree, view, table, column, lastSortColumn, lastSortAscending,
|
|||
*/
|
||||
function CompareLowerCase(first, second) {
|
||||
|
||||
var firstLower = first.toLowerCase();
|
||||
var secondLower = second.toLowerCase();
|
||||
// Are we sorting nsILoginInfo entries or just strings?
|
||||
if (first.hostname) {
|
||||
firstLower = first.hostname.toLowerCase();
|
||||
secondLower = second.hostname.toLowerCase();
|
||||
} else {
|
||||
firstLower = first.toLowerCase();
|
||||
secondLower = second.toLowerCase();
|
||||
}
|
||||
|
||||
if (firstLower < secondLower) {
|
||||
return -1;
|
||||
|
|
|
@ -73,14 +73,8 @@ function Reject(number, host) {
|
|||
}
|
||||
|
||||
function LoadRejects() {
|
||||
var enumerator = passwordmanager.rejectEnumerator;
|
||||
var count = 0;
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var nextReject = enumerator.getNext();
|
||||
nextReject = nextReject.QueryInterface(Components.interfaces.nsIPassword);
|
||||
var host = nextReject.host;
|
||||
rejects[count] = new Reject(count++, host);
|
||||
}
|
||||
var hosts = passwordmanager.getAllDisabledHosts({});
|
||||
rejects = hosts.map(function(host, i) { return new Reject(i, host); });
|
||||
rejectsTreeView.rowCount = rejects.length;
|
||||
|
||||
// sort and display the table
|
||||
|
@ -118,7 +112,7 @@ function DeleteAllRejects() {
|
|||
|
||||
function FinalizeRejectDeletions() {
|
||||
for (var r=0; r<deletedRejects.length; r++) {
|
||||
passwordmanager.removeReject(deletedRejects[r].host);
|
||||
passwordmanager.setLoginSavingEnabled(deletedRejects[r].host, true);
|
||||
}
|
||||
deletedRejects.length = 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
# ***** 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) 2007
|
||||
# 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 *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = passwordmgr
|
||||
XPIDL_MODULE = passwordmgr
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsILoginInfo.idl \
|
||||
nsILoginManager.idl \
|
||||
nsILoginManagerStorage.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,147 @@
|
|||
/* ***** 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) 2007
|
||||
* 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(a437458b-baca-4a71-a839-13861a2fd538)]
|
||||
|
||||
/**
|
||||
* An object containing information for a login stored by the
|
||||
* password manager.
|
||||
*/
|
||||
interface nsILoginInfo : nsISupports {
|
||||
/**
|
||||
* The hostname the login applies to.
|
||||
*
|
||||
* For logins obtained from HTML forms, the login is formatted like
|
||||
* a URL. For example: "http://www.site.com" A port number (":123")
|
||||
* may be appended in some cases.
|
||||
*
|
||||
* For logins obtained from a HTTP or FTP protocol authentication,
|
||||
* the hostname is not a URL format, but does always have the port
|
||||
* number appended. For example "www.site.com:80".
|
||||
*/
|
||||
attribute AString hostname;
|
||||
|
||||
/**
|
||||
* The URL a form-based login was submitted to.
|
||||
*
|
||||
* For logins obtained from HTML forms, this field is the |action|
|
||||
* attribute from the |form| element, with the path removed. For
|
||||
* example "http://www.site.com". [Forms with no |action| attribute
|
||||
* default to submitting to their origin URL, so we store that.]
|
||||
*
|
||||
* For logins obtained from a HTTP or FTP protocol authentication,
|
||||
* this field is NULL.
|
||||
*/
|
||||
attribute AString formSubmitURL;
|
||||
|
||||
/**
|
||||
* The HTTP Realm a login was requested for.
|
||||
*
|
||||
* When an HTTP server sends a 401 result, the WWW-Authenticate
|
||||
* header includes a realm to identify the "protection space." See
|
||||
* RFC2617.
|
||||
*
|
||||
* For logins obtained from HTML forms, this field is NULL.
|
||||
*/
|
||||
attribute AString httpRealm;
|
||||
|
||||
/**
|
||||
* The username for the login.
|
||||
*/
|
||||
attribute AString username;
|
||||
|
||||
/**
|
||||
* The |name| attribute for the username input field.
|
||||
*
|
||||
* For logins obtained from a HTTP or FTP protocol authentication,
|
||||
* this field is NULL.
|
||||
*/
|
||||
attribute AString usernameField;
|
||||
|
||||
/**
|
||||
* The password for the login.
|
||||
*/
|
||||
attribute AString password;
|
||||
|
||||
/**
|
||||
* The |name| attribute for the password input field.
|
||||
*
|
||||
* For logins obtained from a HTTP or FTP protocol authentication,
|
||||
* this field is NULL.
|
||||
*/
|
||||
attribute AString passwordField;
|
||||
|
||||
/**
|
||||
* Initialize a newly created nsLoginInfo object.
|
||||
*
|
||||
* The arguments are the fields for the new object.
|
||||
*/
|
||||
void init(in AString aHostname,
|
||||
in AString aFormSubmitURL, in AString aHttpRealm,
|
||||
in AString aUsername, in AString aPassword,
|
||||
in AString aUsernameField, in AString aPasswordField);
|
||||
|
||||
/**
|
||||
* Test for equality with another nsILoginInfo object.
|
||||
*
|
||||
* @param aLoginInfo
|
||||
* The other object to test.
|
||||
*
|
||||
* NOTE: The formSubmitURL field is not strictly checked. A blank (but
|
||||
* not NULL) value will match any value (except null) in the other
|
||||
* object's formSubmitURL field. The blank value indicates the login
|
||||
* was stored before bug 360493 was fixed.
|
||||
*/
|
||||
boolean equals(in nsILoginInfo aLoginInfo);
|
||||
|
||||
/**
|
||||
* Test for equality with another nsILoginInfo object, with the
|
||||
* password fields ignored.
|
||||
*
|
||||
* @param aLoginInfo
|
||||
* The other object to test.
|
||||
*/
|
||||
boolean equalsIgnorePassword(in nsILoginInfo aLoginInfo);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
||||
#define NS_LOGININFO_CONTRACTID "@mozilla.org/login-manager/loginInfo;1"
|
||||
|
||||
%}
|
|
@ -0,0 +1,199 @@
|
|||
/* ***** 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) 2007
|
||||
* 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"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsILoginInfo;
|
||||
interface nsIAutoCompleteResult;
|
||||
interface nsIDOMHTMLInputElement;
|
||||
|
||||
[scriptable, uuid(579f45b7-682f-479f-9085-3f8075488803)]
|
||||
|
||||
interface nsILoginManager : nsISupports {
|
||||
|
||||
/**
|
||||
* Store a new login in the login manager.
|
||||
*
|
||||
* @param aLogin
|
||||
* The login to be added.
|
||||
*/
|
||||
void addLogin(in nsILoginInfo aLogin);
|
||||
|
||||
|
||||
/**
|
||||
* Remove a login from the login manager.
|
||||
*
|
||||
* @param aLogin
|
||||
* The login to be removed.
|
||||
*/
|
||||
void removeLogin(in nsILoginInfo aLogin);
|
||||
|
||||
|
||||
/**
|
||||
* Modify an existing login in the login manager.
|
||||
*
|
||||
* @param aLogin
|
||||
* The login to be modified.
|
||||
*/
|
||||
void modifyLogin(in nsILoginInfo oldLogin, in nsILoginInfo newLogin);
|
||||
|
||||
|
||||
/**
|
||||
* Clear all logins known to login manager.
|
||||
*
|
||||
* The browser sanitization feature allows the user to clear any stored
|
||||
* passwords. This interface allows that to be done without gettng each
|
||||
* login first (which might require knowing the master password).
|
||||
*
|
||||
*/
|
||||
void removeAllLogins();
|
||||
|
||||
|
||||
/**
|
||||
* Fetch all logins in the login manager. An array is always returned;
|
||||
* if there are no logins the array is empty.
|
||||
*
|
||||
* @param count
|
||||
* The number of elements in the array. JS callers can simply use
|
||||
* the array's .length property, and supply an dummy object for
|
||||
* this out param. For example: |getAllLogins({})|
|
||||
* @param logins
|
||||
* An array of nsILoginInfo objects.
|
||||
*
|
||||
* NOTE: This can be called from JS as:
|
||||
* var logins = pwmgr.getAllLogins({});
|
||||
* (|logins| is an array).
|
||||
*/
|
||||
void getAllLogins(out unsigned long count,
|
||||
[retval, array, size_is(count)] out nsILoginInfo logins);
|
||||
|
||||
|
||||
/**
|
||||
* Obtain a list of all hosts for which password saving is disabled.
|
||||
*
|
||||
* @param count
|
||||
* The number of elements in the array. JS callers can simply use
|
||||
* the array's .length property, and supply an dummy object for
|
||||
* this out param. For example: |getAllDisabledHosts({})|
|
||||
* @param hostnames
|
||||
* An array of hostname strings, in origin URL format without a
|
||||
* pathname. For example: "https://www.site.com".
|
||||
*
|
||||
* NOTE: This can be called from JS as:
|
||||
* var logins = pwmgr.getDisabledAllLogins({});
|
||||
*/
|
||||
void getAllDisabledHosts(out unsigned long count,
|
||||
[retval, array, size_is(count)] out wstring hostnames);
|
||||
|
||||
|
||||
/**
|
||||
* Check to see if saving logins has been disabled for a host.
|
||||
*
|
||||
* @param aHost
|
||||
* The hostname to check. This argument should be in the origin
|
||||
* URL format, without a pathname. For example: "http://foo.com".
|
||||
*/
|
||||
boolean getLoginSavingEnabled(in AString aHost);
|
||||
|
||||
|
||||
/**
|
||||
* Disable (or enable) storing logins for the specified host. When
|
||||
* disabled, the login manager will not prompt to store logins for
|
||||
* that host. Existing logins are not affected.
|
||||
*
|
||||
* @param aHost
|
||||
* The hostname to set. This argument should be in the origin
|
||||
* URL format, without a pathname. For example: "http://foo.com".
|
||||
* @param isEnabled
|
||||
* Specify if saving logins should be enabled (true) or
|
||||
* disabled (false)
|
||||
*/
|
||||
void setLoginSavingEnabled(in AString aHost, in boolean isEnabled);
|
||||
|
||||
|
||||
/**
|
||||
* Search for logins matching the specified criteria. Called when looking
|
||||
* for logins that might be applicable to a form or authentication request.
|
||||
*
|
||||
* @param count
|
||||
* The number of elements in the array. JS callers can simply use
|
||||
* the array's .length property, and supply an dummy object for
|
||||
* this out param. For example: |findLogins({}, hostname, ...)|
|
||||
* @param aHostname
|
||||
* The hostname to restict searches to. When looking for form
|
||||
* logins, this argument should be in origin URL format, without
|
||||
* a pathname. For example: "http://www.site.com". For protocol
|
||||
* logins (http//ftp), it should be the hostname with a port
|
||||
* appended. For example: "www.bar.com:443".
|
||||
* @param aActionURL
|
||||
* For form logins, this argument should be the URL to which the
|
||||
* form will be submitted. For protocol logins, specify null.
|
||||
* @param aHttpRealm
|
||||
* For protocol logins, this argument should be the HTTP Realm
|
||||
* for which the login applies. This is obtained from the
|
||||
* WWW-Authenticate header. See RFC2617. For form logins,
|
||||
* specify null.
|
||||
* @param logins
|
||||
* An array of nsILoginInfo objects.
|
||||
*
|
||||
* NOTE: This can be called from JS as:
|
||||
* var logins = pwmgr.findLogins({}, hostname, ...);
|
||||
*
|
||||
*/
|
||||
void findLogins(out unsigned long count, in AString aHostname,
|
||||
in AString aActionURL, in AString aHttpRealm,
|
||||
[retval, array, size_is(count)] out nsILoginInfo logins);
|
||||
|
||||
|
||||
/**
|
||||
* Generate results for a userfield autocomplete menu.
|
||||
*
|
||||
* NOTE: This interface is provided for use only by the FormFillController,
|
||||
* which calls it directly. This isn't really ideal, it should
|
||||
* probably be callback registered through the FFC.
|
||||
*/
|
||||
nsIAutoCompleteResult autoCompleteSearch(in AString aSearchString,
|
||||
in nsIAutoCompleteResult aPreviousResult,
|
||||
in nsIDOMHTMLInputElement aElement);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
||||
#define NS_LOGINMANAGER_CONTRACTID "@mozilla.org/login-manager;1"
|
||||
|
||||
%}
|
|
@ -0,0 +1,207 @@
|
|||
/* ***** 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) 2007
|
||||
* 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"
|
||||
|
||||
interface nsILoginInfo;
|
||||
|
||||
[scriptable, uuid(18b5acbd-36dc-496d-9212-6f1a3c068a84)]
|
||||
|
||||
/*
|
||||
* NOTE: This interface is intended to be implemented by modules
|
||||
* providing storage mechanisms for the login manager.
|
||||
* Other code should use the login manager's interfaces
|
||||
* (nsILoginManager), and should not call storage modules
|
||||
* directly.
|
||||
*/
|
||||
interface nsILoginManagerStorage : nsISupports {
|
||||
/**
|
||||
* Initialize the component. Not invoked automatically.
|
||||
*/
|
||||
void init();
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the component, but override the default filename
|
||||
* locations. This is primarily used to the unit tests and profile
|
||||
* migration.
|
||||
*
|
||||
* @param aPathname
|
||||
* Directory to use for the input and output files
|
||||
* @param aInputFilename
|
||||
* Filename to read for stored logins.
|
||||
* @param aOutputFilename
|
||||
* If non-null, filename to output logins to.
|
||||
*
|
||||
*/
|
||||
void initWithFile(in AString aPathname,
|
||||
in AString aInputFilename, in AString aOutputFilename);
|
||||
|
||||
|
||||
/**
|
||||
* Store a new login.
|
||||
*
|
||||
* @param aLogin
|
||||
* The login to be added.
|
||||
*/
|
||||
void addLogin(in nsILoginInfo aLogin);
|
||||
|
||||
|
||||
/**
|
||||
* Remove a login from the login manager.
|
||||
*
|
||||
* @param aLogin
|
||||
* The login to be removed.
|
||||
*/
|
||||
void removeLogin(in nsILoginInfo aLogin);
|
||||
|
||||
|
||||
/**
|
||||
* Modify an existing login in the login manager.
|
||||
*
|
||||
* @param aLogin
|
||||
* The login to be modified.
|
||||
*/
|
||||
void modifyLogin(in nsILoginInfo oldLogin, in nsILoginInfo newLogin);
|
||||
|
||||
|
||||
/**
|
||||
* Clear all stored logins.
|
||||
*
|
||||
* The browser sanitization feature allows the user to clear any stored
|
||||
* passwords. This interface allows that to be done without gettng each
|
||||
* login first (which might require knowing the master password).
|
||||
*
|
||||
*/
|
||||
void removeAllLogins();
|
||||
|
||||
|
||||
/**
|
||||
* Fetch all logins in the login manager. An array is always returned;
|
||||
* if there are no logins the array is empty.
|
||||
*
|
||||
* @param count
|
||||
* The number of elements in the array. JS callers can simply use
|
||||
* the array's .length property, and supply an dummy object for
|
||||
* this out param. For example: |getAllLogins({})|
|
||||
* @param logins
|
||||
* An array of nsILoginInfo objects.
|
||||
*
|
||||
* NOTE: This can be called from JS as:
|
||||
* var logins = pwmgr.getAllLogins({});
|
||||
* (|logins| is an array).
|
||||
*/
|
||||
void getAllLogins(out unsigned long count,
|
||||
[retval, array, size_is(count)] out nsILoginInfo logins);
|
||||
|
||||
|
||||
/**
|
||||
* Obtain a list of all hosts for which password saving is disabled.
|
||||
*
|
||||
* @param count
|
||||
* The number of elements in the array. JS callers can simply use
|
||||
* the array's .length property, and supply an dummy object for
|
||||
* this out param. For example: |getAllDisabledHosts({})|
|
||||
* @param hostnames
|
||||
* An array of hostname strings, in origin URL format without a
|
||||
* pathname. For example: "https://www.site.com".
|
||||
*
|
||||
* NOTE: This can be called from JS as:
|
||||
* var logins = pwmgr.getDisabledAllLogins({});
|
||||
*/
|
||||
void getAllDisabledHosts(out unsigned long count,
|
||||
[retval, array, size_is(count)] out wstring hostnames);
|
||||
|
||||
|
||||
/**
|
||||
* Check to see if saving logins has been disabled for a host.
|
||||
*
|
||||
* @param aHost
|
||||
* The hostname to check. This argument should be in the origin
|
||||
* URL format, without a pathname. For example: "http://foo.com".
|
||||
*/
|
||||
boolean getLoginSavingEnabled(in AString aHost);
|
||||
|
||||
|
||||
/**
|
||||
* Disable (or enable) storing logins for the specified host. When
|
||||
* disabled, the login manager will not prompt to store logins for
|
||||
* that host. Existing logins are not affected.
|
||||
*
|
||||
* @param aHost
|
||||
* The hostname to set. This argument should be in the origin
|
||||
* URL format, without a pathname. For example: "http://foo.com".
|
||||
* @param isEnabled
|
||||
* Specify if saving logins should be enabled (true) or
|
||||
* disabled (false)
|
||||
*/
|
||||
void setLoginSavingEnabled(in AString aHost, in boolean isEnabled);
|
||||
|
||||
|
||||
/**
|
||||
* Search for logins matching the specified criteria. Called when looking
|
||||
* for logins that might be applicable to a form or authentication request.
|
||||
*
|
||||
* @param count
|
||||
* The number of elements in the array. JS callers can simply use
|
||||
* the array's .length property, and supply an dummy object for
|
||||
* this out param. For example: |findLogins({}, hostname, ...)|
|
||||
* @param aHostname
|
||||
* The hostname to restict searches to. When looking for form
|
||||
* logins, this argument should be in origin URL format, without
|
||||
* a pathname. For example: "http://www.site.com". For protocol
|
||||
* logins (http//ftp), it should be the hostname with a port
|
||||
* appended. For example: "www.bar.com:443".
|
||||
* @param aActionURL
|
||||
* For form logins, this argument should be the URL to which the
|
||||
* form will be submitted. For protocol logins, specify null.
|
||||
* @param aHttpRealm
|
||||
* For protocol logins, this argument should be the HTTP Realm
|
||||
* for which the login applies. This is obtained from the
|
||||
* WWW-Authenticate header. See RFC2617. For form logins,
|
||||
* specify null.
|
||||
* @param logins
|
||||
* An array of nsILoginInfo objects.
|
||||
*
|
||||
* NOTE: This can be called from JS as:
|
||||
* var logins = pwmgr.findLogins({}, hostname, ...);
|
||||
*
|
||||
*/
|
||||
void findLogins(out unsigned long count, in AString aHostname,
|
||||
in AString aActionURL, in AString aHttpRealm,
|
||||
[retval, array, size_is(count)] out nsILoginInfo logins);
|
||||
};
|
|
@ -0,0 +1,54 @@
|
|||
# ***** 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) 2007
|
||||
# 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 *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = passwordmgr
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
nsLoginManager.js \
|
||||
nsLoginManagerPrompter.js \
|
||||
nsLoginInfo.js \
|
||||
storage-Legacy.js \
|
||||
$(NULL)
|
||||
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,161 @@
|
|||
/* ***** 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) 2007
|
||||
* 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 ***** */
|
||||
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
function nsLoginInfo() {}
|
||||
|
||||
nsLoginInfo.prototype = {
|
||||
|
||||
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 : null,
|
||||
formSubmitURL : null,
|
||||
httpRealm : null,
|
||||
username : null,
|
||||
password : null,
|
||||
usernameField : null,
|
||||
passwordField : null,
|
||||
|
||||
init : function (aHostname, aFormSubmitURL, aHttpRealm,
|
||||
aUsername, aPassword,
|
||||
aUsernameField, aPasswordField) {
|
||||
this.hostname = aHostname;
|
||||
this.formSubmitURL = aFormSubmitURL;
|
||||
this.httpRealm = aHttpRealm;
|
||||
this.username = aUsername;
|
||||
this.password = aPassword;
|
||||
this.usernameField = aUsernameField;
|
||||
this.passwordField = aPasswordField;
|
||||
},
|
||||
|
||||
equalsIgnorePassword : function (aLogin) {
|
||||
if (this.hostname != aLogin.hostname)
|
||||
return false;
|
||||
|
||||
// If either formSubmitURL is blank (but not null), then match.
|
||||
if (this.formSubmitURL != "" && aLogin.formSubmitURL != "" &&
|
||||
this.formSubmitURL != aLogin.formSubmitURL)
|
||||
return false;
|
||||
|
||||
if (this.httpRealm != aLogin.httpRealm)
|
||||
return false;
|
||||
|
||||
if (this.username != aLogin.username)
|
||||
return false;
|
||||
|
||||
if (this.usernameField != aLogin.usernameField)
|
||||
return false;
|
||||
|
||||
// The .password and .passwordField values are ignored.
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
equals : function (aLogin) {
|
||||
if (!this.equalsIgnorePassword(aLogin) ||
|
||||
this.password != aLogin.password ||
|
||||
this.passwordField != aLogin.passwordField)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // end of nsLoginInfo implementation
|
||||
|
||||
|
||||
|
||||
|
||||
// Boilerplate code for component registration...
|
||||
var gModule = {
|
||||
registerSelf: function(componentManager, fileSpec, location, type) {
|
||||
componentManager = componentManager.QueryInterface(
|
||||
Ci.nsIComponentRegistrar);
|
||||
for each (var obj in this._objects)
|
||||
componentManager.registerFactoryLocation(obj.CID,
|
||||
obj.className, obj.contractID,
|
||||
fileSpec, location, type);
|
||||
},
|
||||
|
||||
unregisterSelf: function (componentManager, location, type) {
|
||||
for each (var obj in this._objects)
|
||||
componentManager.unregisterFactoryLocation(obj.CID, location);
|
||||
},
|
||||
|
||||
getClassObject: function(componentManager, cid, iid) {
|
||||
if (!iid.equals(Ci.nsIFactory))
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
for (var key in this._objects) {
|
||||
if (cid.equals(this._objects[key].CID))
|
||||
return this._objects[key].factory;
|
||||
}
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
_objects: {
|
||||
service: {
|
||||
CID : Components.ID("{0f2f347c-1e4f-40cc-8efd-792dea70a85e}"),
|
||||
contractID : "@mozilla.org/login-manager/loginInfo;1",
|
||||
className : "LoginInfo",
|
||||
factory : LoginInfoFactory = {
|
||||
createInstance: function(aOuter, aIID) {
|
||||
if (aOuter != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
var svc = new nsLoginInfo();
|
||||
return svc.QueryInterface(aIID);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
canUnload: function(componentManager) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
function NSGetModule(compMgr, fileSpec) {
|
||||
return gModule;
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,424 @@
|
|||
/* ***** 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) 2007
|
||||
* 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 ***** */
|
||||
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
/*
|
||||
* LoginManagerPromptFactory
|
||||
*
|
||||
* Implements nsIPromptFactory
|
||||
*
|
||||
* Invoked by NS_NewAuthPrompter2()
|
||||
* [embedding/components/windowwatcher/src/nsPrompt.cpp]
|
||||
*/
|
||||
function LoginManagerPromptFactory() {}
|
||||
|
||||
LoginManagerPromptFactory.prototype = {
|
||||
|
||||
QueryInterface : function (iid) {
|
||||
const interfaces = [Ci.nsIPromptFactory, Ci.nsISupports];
|
||||
if (!interfaces.some( function(v) { return iid.equals(v) } ))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
},
|
||||
|
||||
_promptService : null,
|
||||
_pwmgr : null,
|
||||
|
||||
_initialized : false,
|
||||
|
||||
getPrompt : function (aWindow, aIID) {
|
||||
|
||||
if (!this._initialized) {
|
||||
// Login manager service
|
||||
this._pwmgr = Cc["@mozilla.org/login-manager;1"]
|
||||
.getService(Ci.nsILoginManager);
|
||||
|
||||
// Prompt service for user interaction
|
||||
this._promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Ci.nsIPromptService2);
|
||||
|
||||
this._initialized = true;
|
||||
}
|
||||
|
||||
if (!aIID.equals(Ci.nsIAuthPrompt2))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
|
||||
var prompter = new LoginManagerPrompter();
|
||||
prompter.init(this._pwmgr, this._promptService, aWindow);
|
||||
prompter.QueryInterface(Ci.nsIAuthPrompt2);
|
||||
|
||||
return prompter;
|
||||
}
|
||||
}; // end of LoginManagerPromptFactory implementation
|
||||
|
||||
|
||||
|
||||
|
||||
/* ==================== LoginManagerPrompter ==================== */
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* LoginManagerPrompter
|
||||
*
|
||||
* Implements nsIAuthPrompt2.
|
||||
*
|
||||
* Invoked by a channel for protocol-based authentication (eg HTTP
|
||||
* Authenticate, FTP login)
|
||||
*/
|
||||
function LoginManagerPrompter() {}
|
||||
LoginManagerPrompter.prototype = {
|
||||
|
||||
QueryInterface : function (iid) {
|
||||
var interfaces = [Ci.nsIAuthPrompt2, Ci.nsISupports];
|
||||
if (!interfaces.some( function(v) { return iid.equals(v) } ))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
__logService : null, // Console logging service, used for debugging.
|
||||
get _logService() {
|
||||
if (!this.__logService)
|
||||
this.__logService = Cc["@mozilla.org/consoleservice;1"]
|
||||
.getService(Ci.nsIConsoleService);
|
||||
return this.__logService;
|
||||
},
|
||||
|
||||
_promptService : null,
|
||||
_pwmgr : null,
|
||||
_window : null,
|
||||
|
||||
_debug : false,
|
||||
|
||||
|
||||
init : function (aPWManager, aPromptService, aWindow) {
|
||||
this._pwmgr = aPWManager;
|
||||
this._promptService = aPromptService;
|
||||
this._window = aWindow;
|
||||
|
||||
this.log("===== initialized =====");
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* log
|
||||
*
|
||||
* Internal function for logging debug messages to the Error Console window.
|
||||
*/
|
||||
log : function (message) {
|
||||
if (!this._debug)
|
||||
return;
|
||||
|
||||
dump("Pwmgr Prompter: " + message + "\n");
|
||||
this._logService.logStringMessage("Pwmgr Prompter: " + message);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* promptAuth
|
||||
*
|
||||
* Implementation of nsIAuthPrompt2.
|
||||
*
|
||||
* nsIChannel aChannel
|
||||
* int aLevel
|
||||
* nsIAuthInformation aAuthInfo
|
||||
* boolean aConfirm
|
||||
*/
|
||||
promptAuth : function (aChannel, aLevel, aAuthInfo, aConfirm) {
|
||||
var rememberLogin = false;
|
||||
var selectedLogin = null;
|
||||
var checkboxLabel = null;
|
||||
|
||||
this.log("===== promptAuth called =====");
|
||||
|
||||
var hostname, httpRealm;
|
||||
[hostname, httpRealm] = this._GetAuthKey(aChannel, aAuthInfo);
|
||||
|
||||
if (this._pwmgr.getLoginSavingEnabled(hostname)) {
|
||||
checkboxLabel = this.getLocalizedString("rememberPassword");
|
||||
|
||||
|
||||
var foundLogins = this._pwmgr.findLogins({},
|
||||
hostname, null, httpRealm);
|
||||
|
||||
// XXX Like the original code, we can't deal with multiple
|
||||
// account selection. (bug 227632)
|
||||
if (foundLogins.length > 0) {
|
||||
selectedLogin = foundLogins[0];
|
||||
this._SetAuthInfo(aAuthInfo, selectedLogin.username,
|
||||
selectedLogin.password);
|
||||
rememberLogin = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if checkboxLabel is null, the checkbox won't be shown at all.
|
||||
var checkbox = { value : rememberLogin };
|
||||
|
||||
var ok = this._promptService.promptAuth(this._window, aChannel,
|
||||
aLevel, aAuthInfo, checkboxLabel, checkbox);
|
||||
rememberLogin = checkbox.value;
|
||||
|
||||
if (ok && rememberLogin) {
|
||||
var newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"]
|
||||
.createInstance(Ci.nsILoginInfo);
|
||||
newLogin.init(hostname, null, httpRealm,
|
||||
aAuthInfo.username, aAuthInfo.password,
|
||||
"", "");
|
||||
|
||||
// If we didn't find an existing login, or if the username
|
||||
// changed, save as a new login.
|
||||
if (!selectedLogin ||
|
||||
aAuthInfo.username != selectedLogin.username) {
|
||||
|
||||
// add as new
|
||||
this.log("Adding login for " + aAuthInfo.username +
|
||||
" @ " + hostname + " (" + httpRealm + ")");
|
||||
this._pwmgr.addLogin(newLogin);
|
||||
|
||||
} else if (selectedLogin &&
|
||||
aAuthInfo.password != selectedLogin.password) {
|
||||
|
||||
this.log("Updating password for " + aAuthInfo.username +
|
||||
" @ " + hostname + " (" + httpRealm + ")");
|
||||
// update password
|
||||
this._pwmgr.modifyLogin(foundLogins[0], newLogin);
|
||||
|
||||
} else {
|
||||
this.log("Login unchanged, no further action needed.");
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
},
|
||||
|
||||
asyncPromptAuth : function () {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
// From /netwerk/base/public/nsNetUtil.h....
|
||||
/**
|
||||
* This function is a helper to get a protocol's default port if the
|
||||
* URI does not specify a port explicitly. Returns -1 if protocol has no
|
||||
* concept of ports or if there was an error getting the port.
|
||||
*/
|
||||
_GetRealPort : function (aURI) {
|
||||
var port = aURI.port;
|
||||
|
||||
if (port != -1)
|
||||
return port; // explicitly specified
|
||||
|
||||
// Otherwise, we have to get the default port from the protocol handler
|
||||
// Need the scheme first
|
||||
var scheme = aURI.scheme;
|
||||
|
||||
var ioService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
|
||||
var handler = ioService.getProtocolHandler(scheme);
|
||||
port = handler.defaultPort;
|
||||
|
||||
return port;
|
||||
},
|
||||
|
||||
|
||||
// From: /embedding/components/windowwatcher/public/nsPromptUtils.h
|
||||
// Args: nsIChannel, nsIAuthInformation, boolean, string, int
|
||||
_GetAuthHostPort : function (aChannel, aAuthInfo) {
|
||||
|
||||
// Have to distinguish proxy auth and host auth here...
|
||||
var flags = aAuthInfo.flags;
|
||||
|
||||
if (flags & (Ci.nsIAuthInformation.AUTH_PROXY)) {
|
||||
// TODO: untested...
|
||||
var proxied = aChannel.QueryInterface(Ci.nsIProxiedChannel);
|
||||
if (!proxied)
|
||||
throw "proxy auth needs nsIProxiedChannel";
|
||||
|
||||
var info = proxied.proxyInfo;
|
||||
if (!info)
|
||||
throw "proxy auth needs nsIProxyInfo";
|
||||
|
||||
var idnhost = info.host;
|
||||
var port = info.port;
|
||||
|
||||
var idnService = Cc["@mozilla.org/network/idn-service;1"]
|
||||
.getService(Ci.nsIIDNService);
|
||||
host = idnService.convertUTF8toACE(idnhost);
|
||||
} else {
|
||||
var host = aChannel.URI.host;
|
||||
var port = this._GetRealPort(aChannel.URI);
|
||||
}
|
||||
|
||||
return [host, port];
|
||||
},
|
||||
|
||||
|
||||
// From: /embedding/components/windowwatcher/public/nsPromptUtils.h
|
||||
// Args: nsIChannel, nsIAuthInformation
|
||||
_GetAuthKey : function (aChannel, aAuthInfo) {
|
||||
var key = "";
|
||||
// HTTP does this differently from other protocols
|
||||
var http = aChannel.QueryInterface(Ci.nsIHttpChannel);
|
||||
if (!http) {
|
||||
key = aChannel.URI.prePath;
|
||||
this.log("_GetAuthKey: got http channel, key is: " + key);
|
||||
return key;
|
||||
}
|
||||
|
||||
var [host, port] = this._GetAuthHostPort(aChannel, aAuthInfo);
|
||||
|
||||
var realm = aAuthInfo.realm;
|
||||
|
||||
key += host;
|
||||
key += ':';
|
||||
key += port;
|
||||
|
||||
this.log("_GetAuthKey got host: " + key + " and realm: " + realm);
|
||||
|
||||
return [key, realm];
|
||||
},
|
||||
|
||||
|
||||
// From: /embedding/components/windowwatcher/public/nsPromptUtils.h
|
||||
// Args: nsIAuthInformation, string, string
|
||||
/**
|
||||
* Given a username (possibly in DOMAIN\user form) and password, parses the
|
||||
* domain out of the username if necessary and sets domain, username and
|
||||
* password on the auth information object.
|
||||
*/
|
||||
_SetAuthInfo : function (aAuthInfo, username, password) {
|
||||
var flags = aAuthInfo.flags;
|
||||
if (flags & Ci.nsIAuthInformation.NEED_DOMAIN) {
|
||||
// Domain is separated from username by a backslash
|
||||
var idx = username.indexOf("\\");
|
||||
if (idx == -1) {
|
||||
aAuthInfo.username = username;
|
||||
} else {
|
||||
aAuthInfo.domain = username.substring(0, idx);
|
||||
aAuthInfo.username = username.substring(idx+1);
|
||||
}
|
||||
} else {
|
||||
aAuthInfo.username = username;
|
||||
}
|
||||
aAuthInfo.password = password;
|
||||
},
|
||||
|
||||
|
||||
_bundle : null,
|
||||
getLocalizedString : function (key) {
|
||||
|
||||
if (!this._bundle) {
|
||||
var bunService = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService);
|
||||
this._bundle = bunService.createBundle(
|
||||
"chrome://passwordmgr/locale/passwordmgr.properties");
|
||||
|
||||
if (!this._bundle)
|
||||
throw "String bundle not present!";
|
||||
}
|
||||
|
||||
return this._bundle.GetStringFromName(key);
|
||||
}
|
||||
}; // end of LoginManagerPrompter implementation
|
||||
|
||||
|
||||
|
||||
|
||||
// Boilerplate code...
|
||||
var gModule = {
|
||||
registerSelf: function(componentManager, fileSpec, location, type) {
|
||||
componentManager = componentManager.QueryInterface(
|
||||
Ci.nsIComponentRegistrar);
|
||||
for each (var obj in this._objects)
|
||||
componentManager.registerFactoryLocation(obj.CID,
|
||||
obj.className, obj.contractID,
|
||||
fileSpec, location, type);
|
||||
},
|
||||
|
||||
unregisterSelf: function (componentManager, location, type) {
|
||||
for each (var obj in this._objects)
|
||||
componentManager.unregisterFactoryLocation(obj.CID, location);
|
||||
},
|
||||
|
||||
getClassObject: function(componentManager, cid, iid) {
|
||||
if (!iid.equals(Ci.nsIFactory))
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
for (var key in this._objects) {
|
||||
if (cid.equals(this._objects[key].CID))
|
||||
return this._objects[key].factory;
|
||||
}
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
_objects: {
|
||||
service: {
|
||||
CID : Components.ID("{447fc780-1d28-412a-91a1-466d48129c65}"),
|
||||
contractID : "@mozilla.org/passwordmanager/authpromptfactory;1",
|
||||
className : "LoginManagerPromptFactory",
|
||||
factory : LoginManagerPromptFactory_Factory = {
|
||||
singleton : null,
|
||||
createInstance: function (aOuter, aIID) {
|
||||
if (aOuter != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
if (this.singleton == null) {
|
||||
var svc = new LoginManagerPromptFactory();
|
||||
this.singleton = svc;
|
||||
} else {
|
||||
svc = this.singleton;
|
||||
}
|
||||
return svc.QueryInterface(aIID);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
canUnload: function(componentManager) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
function NSGetModule(compMgr, fileSpec) {
|
||||
return gModule;
|
||||
}
|
|
@ -0,0 +1,712 @@
|
|||
/* ***** 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) 2007
|
||||
* 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 ***** */
|
||||
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
function LoginManagerStorage_legacy() { };
|
||||
|
||||
LoginManagerStorage_legacy.prototype = {
|
||||
|
||||
QueryInterface : function (iid) {
|
||||
const interfaces = [Ci.nsILoginManagerStorage, Ci.nsISupports];
|
||||
if (!interfaces.some( function(v) { return iid.equals(v) } ))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
},
|
||||
|
||||
__logService : null, // Console logging service, used for debugging.
|
||||
get _logService() {
|
||||
if (!this.__logService)
|
||||
this.__logService = Cc["@mozilla.org/consoleservice;1"]
|
||||
.getService(Ci.nsIConsoleService);
|
||||
return this.__logService;
|
||||
},
|
||||
|
||||
__decoderRing : null, // nsSecretDecoderRing service
|
||||
get _decoderRing() {
|
||||
if (!this.__decoderRing)
|
||||
this.__decoderRing = Cc["@mozilla.org/security/sdr;1"]
|
||||
.getService(Ci.nsISecretDecoderRing);
|
||||
return this.__decoderRing;
|
||||
},
|
||||
|
||||
_prefBranch : null, // Preferences service
|
||||
|
||||
_datafile : null, // name of datafile (usually "signons2.txt")
|
||||
_datapath : null, // path to datafile (usually profile directory)
|
||||
_debug : false, // mirrors signon.debug
|
||||
|
||||
|
||||
/*
|
||||
* Core datastructures
|
||||
*
|
||||
* EG: _logins["http://site.com"][0].password
|
||||
* EG: _disabledHosts["never.site.com"]
|
||||
*/
|
||||
_logins : null,
|
||||
_disabledHosts : null,
|
||||
|
||||
|
||||
/*
|
||||
* log
|
||||
*
|
||||
* Internal function for logging debug messages to the Error Console.
|
||||
*/
|
||||
log : function (message) {
|
||||
if (!this._debug)
|
||||
return;
|
||||
dump("PwMgr Storage: " + message + "\n");
|
||||
this._logService.logStringMessage("PwMgr Storage: " + message);
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
/* ==================== Public Methods ==================== */
|
||||
|
||||
|
||||
|
||||
|
||||
initWithFile : function(aPath, aInputFilename, aOutputFilename) {
|
||||
this._datapath = aPath;
|
||||
this._datafile = aInputFilename;
|
||||
|
||||
this.init();
|
||||
|
||||
if (aOutputFilename && aOutputFilename.length) {
|
||||
this._datafile = aOutputFilename;
|
||||
this._writeFile(aPath, aOutputFilename);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* init
|
||||
*
|
||||
* Initialize this storage component and load stored passwords from disk.
|
||||
*/
|
||||
init : function () {
|
||||
this._logins = {};
|
||||
this._disabledHosts = {};
|
||||
|
||||
// Connect to the correct preferences branch.
|
||||
this._prefBranch = Cc["@mozilla.org/preferences-service;1"]
|
||||
.getService(Ci.nsIPrefService);
|
||||
this._prefBranch = this._prefBranch.getBranch("signon.");
|
||||
this._prefBranch.QueryInterface(Ci.nsIPrefBranch2);
|
||||
|
||||
if (this._prefBranch.prefHasUserValue("debug"))
|
||||
this._debug = this._prefBranch.getBoolPref("debug");
|
||||
|
||||
// Check to see if the internal PKCS#11 token has been initialized.
|
||||
// If not, set a blank password.
|
||||
var tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"]
|
||||
.getService(Ci.nsIPK11TokenDB);
|
||||
|
||||
var token = tokenDB.getInternalKeyToken();
|
||||
if (token.needsUserInit) {
|
||||
this.log("Initializing key3.db with default blank password.");
|
||||
token.initPassword("");
|
||||
}
|
||||
|
||||
// Get the location of the user's profile.
|
||||
if (!this._datapath) {
|
||||
var DIR_SERVICE = new Components.Constructor(
|
||||
"@mozilla.org/file/directory_service;1", "nsIProperties");
|
||||
this._datapath = (new DIR_SERVICE()).get("ProfD", Ci.nsIFile).path;
|
||||
}
|
||||
|
||||
if (!this._datafile)
|
||||
this._datafile = this._prefBranch.getCharPref("SignonFileName2");
|
||||
|
||||
var importFile = null;
|
||||
if (!this._doesFileExist(this._datapath, this._datafile)) {
|
||||
this.log("SignonFilename2 file does not exist. (file=" +
|
||||
this._datafile + ") path=(" + this._datapath + ")");
|
||||
|
||||
// Try reading the old file
|
||||
importFile = this._prefBranch.getCharPref("SignonFileName");
|
||||
if (!this._doesFileExist(this._datapath, importFile)) {
|
||||
this.log("SignonFilename1 file does not exist. (file=" +
|
||||
importFile + ") path=(" + this._datapath + ")");
|
||||
this.log("Creating new signons file...");
|
||||
importFile = null;
|
||||
this._writeFile(this._datapath, this._datafile);
|
||||
}
|
||||
}
|
||||
|
||||
// Read in the stored login data.
|
||||
if (importFile) {
|
||||
this.log("Importing " + importFile);
|
||||
this._readFile(this._datapath, importFile);
|
||||
|
||||
this._writeFile(this._datapath, this._datafile);
|
||||
} else {
|
||||
this._readFile(this._datapath, this._datafile);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* addLogin
|
||||
*
|
||||
*/
|
||||
addLogin : function (login) {
|
||||
var key = login.hostname;
|
||||
|
||||
// If first entry for key, create an Array to hold it's logins.
|
||||
if (!this._logins[key])
|
||||
this._logins[key] = [];
|
||||
|
||||
this._logins[key].push(login);
|
||||
|
||||
this._writeFile(this._datapath, this._datafile);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* removeLogin
|
||||
*
|
||||
*/
|
||||
removeLogin : function (login) {
|
||||
var key = login.hostname;
|
||||
var logins = this._logins[key];
|
||||
|
||||
if (!logins)
|
||||
throw "No logins found for hostname (" + key + ")";
|
||||
|
||||
for (var i = 0; i < logins.length; i++) {
|
||||
if (logins[i].equals(login)) {
|
||||
logins.splice(i, 1); // delete that login from array.
|
||||
break;
|
||||
// Note that if there are duplicate entries, they'll
|
||||
// have to be deleted one-by-one.
|
||||
}
|
||||
}
|
||||
|
||||
// Did we delete all the logins for this host?
|
||||
if (logins.length == 0)
|
||||
delete this._logins[key];
|
||||
|
||||
this._writeFile(this._datapath, this._datafile);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* modifyLogin
|
||||
*
|
||||
*/
|
||||
modifyLogin : function (oldLogin, newLogin) {
|
||||
this.removeLogin(oldLogin);
|
||||
this.addLogin(newLogin);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* getAllLogins
|
||||
*
|
||||
* Returns an array of nsAccountInfo.
|
||||
*/
|
||||
getAllLogins : function (count) {
|
||||
var result = [];
|
||||
|
||||
// Each entry is an array -- append the array entries to |result|.
|
||||
for each (var hostLogins in this._logins) {
|
||||
result = result.concat(hostLogins);
|
||||
}
|
||||
|
||||
count.value = result.length; // needed for XPCOM
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* clearAllLogins
|
||||
*
|
||||
* Clears all logins from storage.
|
||||
*/
|
||||
clearAllLogins : function () {
|
||||
this._logins = {};
|
||||
// Disabled hosts kept, as one presumably doesn't want to erase those.
|
||||
|
||||
this._writeFile(this._datapath, this._datafile);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* getAllDisabledHosts
|
||||
*
|
||||
*/
|
||||
getAllDisabledHosts : function (count) {
|
||||
var result = [];
|
||||
|
||||
for (var hostname in this._disabledHosts) {
|
||||
result.push(hostname);
|
||||
}
|
||||
|
||||
count.value = result.length; // needed for XPCOM
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* getLoginSavingEnabled
|
||||
*
|
||||
*/
|
||||
getLoginSavingEnabled : function (hostname) {
|
||||
return !this._disabledHosts[hostname];
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* setLoginSavingEnabled
|
||||
*
|
||||
*/
|
||||
setLoginSavingEnabled : function (hostname, enabled) {
|
||||
if (enabled)
|
||||
delete this._disabledHosts[hostname];
|
||||
else
|
||||
this._disabledHosts[hostname] = true;
|
||||
|
||||
this._writeFile(this._datapath, this._datafile);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* findLogins
|
||||
*
|
||||
*/
|
||||
findLogins : function (count, hostname, formSubmitURL, httpRealm) {
|
||||
var hostLogins = this._logins[hostname];
|
||||
if (hostLogins == null) {
|
||||
count.value = 0;
|
||||
return [];
|
||||
}
|
||||
|
||||
var result = [];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
count.value = result.length; // needed for XPCOM
|
||||
return result;
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
/* ==================== Internal Methods ==================== */
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* _readFile
|
||||
*
|
||||
*/
|
||||
_readFile : function (pathname, filename) {
|
||||
var oldFormat = false;
|
||||
var writeOnFinish = false;
|
||||
|
||||
this.log("Reading passwords from " + pathname + "/" + filename);
|
||||
|
||||
var file = Cc["@mozilla.org/file/local;1"]
|
||||
.createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(pathname);
|
||||
file.append(filename);
|
||||
|
||||
var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
inputStream.init(file, 0x01, -1, null); // RD_ONLY, -1=default perm
|
||||
var lineStream = inputStream.QueryInterface(Ci.nsILineInputStream);
|
||||
var line = { value: "" };
|
||||
|
||||
const STATE = { HEADER : 0, REJECT : 1, REALM : 2,
|
||||
USERFIELD : 3, USERVALUE : 4,
|
||||
PASSFIELD : 5, PASSVALUE : 6, ACTIONURL : 7 };
|
||||
var parseState = STATE.HEADER;
|
||||
|
||||
var nsLoginInfo = new Components.Constructor(
|
||||
"@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo);
|
||||
var processEntry = false;
|
||||
|
||||
do {
|
||||
var hasMore = lineStream.readLine(line);
|
||||
|
||||
switch (parseState) {
|
||||
// Check file header
|
||||
case STATE.HEADER:
|
||||
if (line.value == "#2c") {
|
||||
oldFormat = true;
|
||||
} else if (line.value != "#2d") {
|
||||
this.log("invalid file header (" + line.value + ")");
|
||||
throw "invalid file header in " + filename;
|
||||
// We could disable later writing to file, so we
|
||||
// don't clobber whatever it is. ...however, that
|
||||
// would mean corrupt files are not self-healing.
|
||||
return;
|
||||
}
|
||||
parseState++;
|
||||
break;
|
||||
|
||||
// Line is a hostname for which passwords should never be saved.
|
||||
case STATE.REJECT:
|
||||
if (line.value == ".") {
|
||||
parseState++;
|
||||
break;
|
||||
}
|
||||
|
||||
this._disabledHosts[line.value] = true;
|
||||
|
||||
break;
|
||||
|
||||
// Line is a hostname, saved login(s) will follow
|
||||
case STATE.REALM:
|
||||
var hostrealm = line.value;
|
||||
|
||||
// Format is "http://site.com", with "(some realm)"
|
||||
// appended if it's a HTTP-Auth login.
|
||||
const realmFormat = /^(.+?)( \(.*\))?$/; // XXX .* or .+?
|
||||
var matches = realmFormat.exec(hostrealm);
|
||||
|
||||
var hostname, httpRealm;
|
||||
if (matches && matches.length == 3) {
|
||||
hostname = matches[1];
|
||||
httpRealm = matches[2] ?
|
||||
matches[2].slice(2, -1) : null;
|
||||
} else {
|
||||
if (hostrealm != "") {
|
||||
// Uhoh. This shouldn't happen, but try to deal.
|
||||
this.log("Error parsing host/realm: " + hostrealm);
|
||||
}
|
||||
hostname = hostrealm;
|
||||
httpRealm = null;
|
||||
}
|
||||
|
||||
parseState++;
|
||||
break;
|
||||
|
||||
// Line is the HTML 'name' attribute for the username field
|
||||
// (or "." to indicate end of hostrealm)
|
||||
case STATE.USERFIELD:
|
||||
if (line.value == ".") {
|
||||
parseState = STATE.REALM;
|
||||
break;
|
||||
}
|
||||
|
||||
var entry = new nsLoginInfo();
|
||||
entry.hostname = hostname;
|
||||
entry.httpRealm = httpRealm;
|
||||
|
||||
entry.usernameField = line.value;
|
||||
parseState++;
|
||||
break;
|
||||
|
||||
// Line is a username
|
||||
case STATE.USERVALUE:
|
||||
entry.username = this._decrypt(line.value);
|
||||
parseState++;
|
||||
break;
|
||||
|
||||
// Line is the HTML 'name' attribute for the password field,
|
||||
// with a leading '*' character
|
||||
case STATE.PASSFIELD:
|
||||
entry.passwordField = line.value.substr(1);
|
||||
parseState++;
|
||||
break;
|
||||
|
||||
// Line is a password
|
||||
case STATE.PASSVALUE:
|
||||
entry.password = this._decrypt(line.value);
|
||||
if (oldFormat) {
|
||||
entry.formSubmitURL = "";
|
||||
processEntry = true;
|
||||
parseState = STATE.USERFIELD;
|
||||
} else {
|
||||
parseState++;
|
||||
}
|
||||
break;
|
||||
|
||||
// Line is the action URL
|
||||
case STATE.ACTIONURL:
|
||||
entry.formSubmitURL = line.value;
|
||||
processEntry = true;
|
||||
parseState = STATE.USERFIELD;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (processEntry) {
|
||||
if (entry.username == "" && entry.password == "") {
|
||||
// Discard bogus entry, and update the file when done.
|
||||
writeOnFinish = true;
|
||||
} else {
|
||||
if (!this._logins[hostname])
|
||||
this._logins[hostname] = [];
|
||||
this._logins[hostname].push(entry);
|
||||
}
|
||||
entry = null;
|
||||
processEntry = false;
|
||||
}
|
||||
} while (hasMore);
|
||||
|
||||
lineStream.close();
|
||||
|
||||
if (writeOnFinish)
|
||||
this._writeFile(pathname, filename);
|
||||
|
||||
return;
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* _writeFile
|
||||
*
|
||||
*/
|
||||
_writeFile : function (pathname, filename) {
|
||||
function writeLine(data) {
|
||||
data += "\r\n";
|
||||
outputStream.write(data, data.length);
|
||||
}
|
||||
|
||||
this.log("Writing passwords to " + pathname + "/" + filename);
|
||||
|
||||
var file = Cc["@mozilla.org/file/local;1"]
|
||||
.createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(pathname);
|
||||
file.append(filename);
|
||||
|
||||
var outputStream = Cc["@mozilla.org/network/safe-file-output-stream;1"]
|
||||
.createInstance(Ci.nsIFileOutputStream);
|
||||
outputStream.QueryInterface(Ci.nsISafeOutputStream);
|
||||
|
||||
// WR_ONLY|CREAT|TRUNC
|
||||
outputStream.init(file, 0x02 | 0x08 | 0x20, 0600, null);
|
||||
|
||||
// write file version header
|
||||
writeLine("#2d");
|
||||
|
||||
// write disabled logins list
|
||||
for (var hostname in this._disabledHosts) {
|
||||
writeLine(hostname);
|
||||
}
|
||||
|
||||
// write end-of-reject-list marker
|
||||
writeLine(".");
|
||||
|
||||
for (var hostname in this._logins) {
|
||||
function sortByRealm(a,b) {
|
||||
a = a.httpRealm;
|
||||
b = b.httpRealm;
|
||||
|
||||
if (!a && !b)
|
||||
return 0;
|
||||
|
||||
if (!a || a < b)
|
||||
return -1;
|
||||
|
||||
if (!b || b > a)
|
||||
return 1;
|
||||
|
||||
return 0; // a==b, neither is null
|
||||
}
|
||||
|
||||
// Sort logins by httpRealm. This allows us to group multiple
|
||||
// logins for the same realm together.
|
||||
this._logins[hostname].sort(sortByRealm);
|
||||
|
||||
|
||||
// write each login known for the host
|
||||
var lastRealm = null;
|
||||
var firstEntry = true;
|
||||
for each (var login in this._logins[hostname]) {
|
||||
|
||||
// If this login is for a new realm, start a new entry.
|
||||
if (login.httpRealm != lastRealm || firstEntry) {
|
||||
// end previous entry, if needed.
|
||||
if (!firstEntry)
|
||||
writeLine(".");
|
||||
|
||||
var hostrealm = login.hostname;
|
||||
if (login.httpRealm)
|
||||
hostrealm += " (" + login.httpRealm + ")";
|
||||
|
||||
writeLine(hostrealm);
|
||||
}
|
||||
|
||||
firstEntry = false;
|
||||
|
||||
var encUsername = this._encrypt(login.username);
|
||||
var encPassword = this._encrypt(login.password);
|
||||
|
||||
writeLine((login.usernameField ? login.usernameField : ""));
|
||||
writeLine(encUsername);
|
||||
writeLine("*" +
|
||||
(login.passwordField ? login.passwordField : ""));
|
||||
writeLine(encPassword);
|
||||
writeLine((login.formSubmitURL ? login.formSubmitURL : ""));
|
||||
|
||||
lastRealm = login.httpRealm;
|
||||
}
|
||||
|
||||
// write end-of-host marker
|
||||
writeLine(".");
|
||||
}
|
||||
|
||||
// [if there were no hosts, no end-of-host marker (".") needed]
|
||||
|
||||
outputStream.finish();
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* _encrypt
|
||||
*
|
||||
*/
|
||||
_encrypt : function (plainText) {
|
||||
return this._decoderRing.encryptString(plainText);
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* decrypt
|
||||
*
|
||||
*/
|
||||
_decrypt : function (cipherText) {
|
||||
var plainText = null;
|
||||
|
||||
if (cipherText.charAt(0) == '~') {
|
||||
// The pre-Mozilla-1.0 file format obscured entries by
|
||||
// base64-encoding them. These entries are signaled by a leading
|
||||
// '~' character.
|
||||
// This file format is no longer supported.
|
||||
|
||||
throw "!!!!! base64 encoded passwords not supported !!!!!";
|
||||
}
|
||||
|
||||
try {
|
||||
plainText = this._decoderRing.decryptString(cipherText);
|
||||
} catch (e) {
|
||||
this.log("Failed to decrypt string: " + cipherText);
|
||||
}
|
||||
|
||||
return plainText;
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* _doesFileExist
|
||||
*
|
||||
*/
|
||||
_doesFileExist : function (filepath, filename) {
|
||||
var file = Cc["@mozilla.org/file/local;1"]
|
||||
.createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(filepath);
|
||||
file.append(filename);
|
||||
|
||||
return file.exists();
|
||||
}
|
||||
}; // end of nsLoginManagerStorage_legacy implementation
|
||||
|
||||
|
||||
|
||||
|
||||
// Boilerplate code for component registration...
|
||||
var gModule = {
|
||||
registerSelf: function(componentManager, fileSpec, location, type) {
|
||||
componentManager = componentManager.QueryInterface(
|
||||
Ci.nsIComponentRegistrar);
|
||||
for each (var obj in this._objects)
|
||||
componentManager.registerFactoryLocation(obj.CID,
|
||||
obj.className, obj.contractID,
|
||||
fileSpec, location, type);
|
||||
},
|
||||
|
||||
unregisterSelf: function (componentManager, location, type) {
|
||||
for each (var obj in this._objects)
|
||||
componentManager.unregisterFactoryLocation(obj.CID, location);
|
||||
},
|
||||
|
||||
getClassObject: function(componentManager, cid, iid) {
|
||||
if (!iid.equals(Ci.nsIFactory))
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
for (var key in this._objects) {
|
||||
if (cid.equals(this._objects[key].CID))
|
||||
return this._objects[key].factory;
|
||||
}
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
_objects: {
|
||||
service: {
|
||||
CID : Components.ID("{e09e4ca6-276b-4bb4-8b71-0635a3a2a007}"),
|
||||
contractID : "@mozilla.org/login-manager/storage/legacy;1",
|
||||
className : "LoginManagerStorage_legacy",
|
||||
factory : aFactory = {
|
||||
createInstance: function(aOuter, aIID) {
|
||||
if (aOuter != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
var svc = new LoginManagerStorage_legacy();
|
||||
return svc.QueryInterface(aIID);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
canUnload: function(componentManager) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
function NSGetModule(compMgr, fileSpec) {
|
||||
return gModule;
|
||||
}
|
|
@ -63,6 +63,8 @@ MOCHI_TESTS = \
|
|||
test_bug_360493_2.html \
|
||||
$(NULL)
|
||||
|
||||
XPCSHELL_TESTS = unit
|
||||
|
||||
# This test doesn't pass because we can't ensure a cross-platform
|
||||
# event that occurs between DOMContentLoaded and Pageload
|
||||
# test_bug_221634.html
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test initialization for Password Manager</title>
|
||||
<title>Test initialization for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Password Manager test: initialization.
|
||||
Login Manager test: initialization.
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
@ -16,54 +16,65 @@ Password Manager test: initialization.
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: initialization **/
|
||||
/** Test for Login Manager: initialization **/
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
|
||||
// Get the pwmgr service
|
||||
var Cc_pwmgr = Components.classes["@mozilla.org/passwordmanager;1"];
|
||||
ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/passwordmanager;1]");
|
||||
var Cc_pwmgr = Components.classes["@mozilla.org/login-manager;1"];
|
||||
ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/login-manager;1]");
|
||||
|
||||
var Ci_pwmgr = Components.interfaces.nsIPasswordManager;
|
||||
ok(Ci_pwmgr != null, "Access Ci.nsIPasswordManager");
|
||||
var Ci_pwmgr = Components.interfaces.nsILoginManager;
|
||||
ok(Ci_pwmgr != null, "Access Ci.nsILoginManager");
|
||||
|
||||
var pwmgr = Cc_pwmgr.getService(Ci_pwmgr);
|
||||
ok(pwmgr != null, "pwmgr getService()");
|
||||
|
||||
|
||||
// Make sure it's not already initialized somehow
|
||||
var count, enum;
|
||||
count = 0;
|
||||
enum = pwmgr.enumerator;
|
||||
while (enum.hasMoreElements()) { count++; enum.getNext(); }
|
||||
ok(count == 0, "ensure no pre-existing logins");
|
||||
if (count != 0) { throw "Aborting test."; }
|
||||
var logins = pwmgr.getAllLogins({});
|
||||
ok(logins != null, "getAllLogins()");
|
||||
is(logins.length, 0, "ensure no pre-existing logins");
|
||||
if (logins.length != 0) { throw "aborting test init -- found existing logins"; }
|
||||
|
||||
count = 0;
|
||||
enum = pwmgr.rejectEnumerator;
|
||||
while (enum.hasMoreElements()) { count++; enum.getNext(); }
|
||||
ok(count == 0, "ensure no pre-existing disabled logins");
|
||||
if (count != 0) { throw "Aborting test"; }
|
||||
var disabledHosts = pwmgr.getAllDisabledHosts({});
|
||||
ok(disabledHosts != null, "getAllDisabledHosts()");
|
||||
is(disabledHosts.length, 0, "ensure no pre-existing disabled hosts");
|
||||
if (disabledHosts.length != 0) { throw "aborting test init -- found existing disabled hosts"; }
|
||||
|
||||
|
||||
// Get nsLoginInfo constructor for simpler code
|
||||
var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Components.interfaces.nsILoginInfo);
|
||||
ok(nsLoginInfo != null, "nsLoginInfo constructor");
|
||||
|
||||
|
||||
pwmgr = pwmgr.QueryInterface(Components.interfaces.nsIPasswordManagerInternal);
|
||||
// Add some logins for testing.
|
||||
const TESTHOST = "http://localhost:8888";
|
||||
for (var u = 1; u <= 15; u++) {
|
||||
pwmgr.addUserFull2(TESTHOST, "testuser"+u, "testpass"+u, "uname"+u, "pword"+u, TESTHOST);
|
||||
function initLogin(login, username, ufieldName, password, pfieldName, hostname, formSubmitURL) {
|
||||
login.username = username;
|
||||
login.usernameField = ufieldName;
|
||||
login.password = password;
|
||||
login.passwordField = pfieldName;
|
||||
login.hostname = hostname;
|
||||
login.formSubmitURL = formSubmitURL
|
||||
login.httpRealm = null;
|
||||
}
|
||||
|
||||
for (var u = 1; u <= 10; u++) {
|
||||
// TODO: don't really need |new| here, could even detect possible breakage with refs to user objs
|
||||
login = new nsLoginInfo();
|
||||
ok(login != null, "Adding login #" + u);
|
||||
|
||||
initLogin(login, "testuser"+u, "uname"+u, "testpass"+u, "pword"+u,
|
||||
"http://localhost:8888", "http://localhost:8888");
|
||||
|
||||
pwmgr.addLogin(login);
|
||||
}
|
||||
|
||||
// Simple check to see if everything was added fine.
|
||||
count = 0;
|
||||
enum = pwmgr.enumerator;
|
||||
while (enum.hasMoreElements()) { count++; enum.getNext(); }
|
||||
ok(count == 15, "check number of added logins");
|
||||
|
||||
count = 0;
|
||||
enum = pwmgr.rejectEnumerator;
|
||||
while (enum.hasMoreElements()) { count++; enum.getNext(); }
|
||||
ok(count == 0, "check no disable logins");
|
||||
var logins = pwmgr.getAllLogins({});
|
||||
ok(logins != null, "getAllLogins()");
|
||||
is(logins.length, 10, "check expected final number of logins");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Password Manager</title>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Password Manager test: simple form fill
|
||||
Login Manager test: simple form fill
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
|
@ -44,7 +44,7 @@ Password Manager test: simple form fill
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: form fill, multiple forms. **/
|
||||
/** Test for Login Manager: form fill, multiple forms. **/
|
||||
|
||||
// Make sure that all forms in a document are processed.
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Password Manager</title>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Password Manager test: forms with no password fields
|
||||
Login Manager test: forms with no password fields
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
|
@ -39,7 +39,7 @@ Password Manager test: forms with no password fields
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: form fill, no password fields. **/
|
||||
/** Test for Login Manager: form fill, no password fields. **/
|
||||
|
||||
function startTest() {
|
||||
is($_("uname1").value, "", "Checking for unfilled username 1");
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Password Manager</title>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Password Manager test: forms with 1 password field
|
||||
Login Manager test: forms with 1 password field
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
|
@ -43,7 +43,7 @@ Password Manager test: forms with 1 password field
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: simple form fill **/
|
||||
/** Test for Login Manager: simple form fill **/
|
||||
|
||||
function startTest() {
|
||||
// Check username
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Password Manager</title>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Password Manager test: forms with 2 password fields (form filling)
|
||||
Login Manager test: forms with 2 password fields (form filling)
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
|
@ -73,7 +73,7 @@ Password Manager test: forms with 2 password fields (form filling)
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: form fill, 2 password fields **/
|
||||
/** Test for Login Manager: form fill, 2 password fields **/
|
||||
|
||||
// This test simply checks to make sure pwmgr can autofill forms with 2 password fields.
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Password Manager</title>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Password Manager test: forms with 2 password fields (adding new logins)
|
||||
Login Manager test: forms with 2 password fields (adding new logins)
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
|
@ -73,7 +73,7 @@ Password Manager test: forms with 2 password fields (adding new logins)
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: form fill, 2 password fields **/
|
||||
/** Test for Login Manager: form fill, 2 password fields **/
|
||||
|
||||
// If a form has two password fields, other things may be going on....
|
||||
//
|
||||
|
@ -145,7 +145,11 @@ function startTest() {
|
|||
|
||||
|
||||
var button = getFormSubmitButton(1);
|
||||
button.click();
|
||||
//button.click();
|
||||
|
||||
// TODO: form submission checking disabled until we can auto-accept the save-password dialog.
|
||||
// (this test worked with the old password manager because it ignored this case of forms).
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,21 +198,19 @@ function getFormSubmitButton(formNum) {
|
|||
function countLogins() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
var count = 0;
|
||||
var enum = pwmgr.enumerator;
|
||||
while (enum.hasMoreElements()) { count++; enum.getNext(); }
|
||||
var logins = pwmgr.getAllLogins({});
|
||||
|
||||
return count;
|
||||
return logins.length;
|
||||
}
|
||||
|
||||
// Get the pwmgr service
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
var Cc_pwmgr = Components.classes["@mozilla.org/passwordmanager;1"];
|
||||
ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/passwordmanager;1]");
|
||||
var Cc_pwmgr = Components.classes["@mozilla.org/login-manager;1"];
|
||||
ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/login-manager;1]");
|
||||
|
||||
var Ci_pwmgr = Components.interfaces.nsIPasswordManager;
|
||||
ok(Ci_pwmgr != null, "Access Ci.nsIPasswordManager");
|
||||
var Ci_pwmgr = Components.interfaces.nsILoginManager;
|
||||
ok(Ci_pwmgr != null, "Access Ci.nsILoginManager");
|
||||
|
||||
var pwmgr = Cc_pwmgr.getService(Ci_pwmgr);
|
||||
ok(pwmgr != null, "pwmgr getService()");
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Password Manager</title>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Password Manager test: forms with 3 password fields (form filling)
|
||||
Login Manager test: forms with 3 password fields (form filling)
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
|
@ -110,7 +110,7 @@ Password Manager test: forms with 3 password fields (form filling)
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: form fill, 3 password fields **/
|
||||
/** Test for Login Manager: form fill, 3 password fields **/
|
||||
|
||||
// Test to make sure 3-password forms are filled properly.
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Password Manager</title>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="endTest();">
|
||||
Password Manager test: 221634
|
||||
Login Manager test: 221634
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
@ -25,7 +25,7 @@ Password Manager test: 221634
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: 221634 (password manager needs to fill in forms before the page finishes loading) **/
|
||||
/** Test for Login Manager: 221634 (password manager needs to fill in forms before the page finishes loading) **/
|
||||
|
||||
var dclHappened = false;
|
||||
var testHappened = false;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Password Manager</title>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Password Manager test: 227640
|
||||
Login Manager test: 227640
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
@ -146,7 +146,7 @@ Password Manager test: 227640
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: 227640 (password is saved even when the password field has autocomplete="off") **/
|
||||
/** Test for Login Manager: 227640 (password is saved even when the password field has autocomplete="off") **/
|
||||
|
||||
// This test ensures that pwmgr does not save a username or password when
|
||||
// autocomplete=off is present.
|
||||
|
@ -220,21 +220,19 @@ function getFormSubmitButton(formNum) {
|
|||
function countLogins() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
var count = 0;
|
||||
var enum = pwmgr.enumerator;
|
||||
while (enum.hasMoreElements()) { count++; enum.getNext(); }
|
||||
var logins = pwmgr.getAllLogins({});
|
||||
|
||||
return count;
|
||||
return logins.length;
|
||||
}
|
||||
|
||||
// Get the pwmgr service
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
var Cc_pwmgr = Components.classes["@mozilla.org/passwordmanager;1"];
|
||||
ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/passwordmanager;1]");
|
||||
var Cc_pwmgr = Components.classes["@mozilla.org/login-manager;1"];
|
||||
ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/login-manager;1]");
|
||||
|
||||
var Ci_pwmgr = Components.interfaces.nsIPasswordManager;
|
||||
ok(Ci_pwmgr != null, "Access Ci.nsIPasswordManager");
|
||||
var Ci_pwmgr = Components.interfaces.nsILoginManager;
|
||||
ok(Ci_pwmgr != null, "Access Ci.nsILoginManager");
|
||||
|
||||
var pwmgr = Cc_pwmgr.getService(Ci_pwmgr);
|
||||
ok(pwmgr != null, "pwmgr getService()");
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Password Manager</title>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Password Manager test: 242956
|
||||
Login Manager test: 242956
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<!-- pword1 is not a type=password input -->
|
||||
|
@ -109,7 +109,7 @@ Password Manager test: 242956
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: 242956 (Stored password is inserted into a readable text input on a second page) **/
|
||||
/** Test for Login Manager: 242956 (Stored password is inserted into a readable text input on a second page) **/
|
||||
|
||||
// Make sure that pwmgr only puts passwords into type=password <input>s.
|
||||
// Might as well test the converse, too (username in password field).
|
||||
|
@ -145,13 +145,11 @@ function startTest() {
|
|||
input = form.elements[0];
|
||||
is(input.type, "text", "confirming user field 4 type");
|
||||
is(input.name, "uname4", "confirming user field 4 name");
|
||||
//is(input.value, "testuser4", "checking user field 4 value");
|
||||
todo(input.value == "testuser4", "ignore bogus <input> and fill testuser4");
|
||||
is(input.value, "testuser4", "checking user field 4 value");
|
||||
input = form.elements[1];
|
||||
is(input.type, "password", "confirming legit password field 4 type");
|
||||
is(input.name, "pword4", "confirming legit password field 4 type");
|
||||
//is(input.value, "testpass4", "checking legit password field 4 value");
|
||||
todo(input.value == "testpass4", "ignore bogus <input> and fill testpass4");
|
||||
is(input.value, "testpass4", "checking legit password field 4 value");
|
||||
input = form.elements[2];
|
||||
is(input.type, "text", "confirming bogus password field 4 type");
|
||||
is(input.name, "pword4", "confirming bogus password field 4 name");
|
||||
|
@ -162,8 +160,7 @@ function startTest() {
|
|||
input = form.elements[0];
|
||||
is(input.type, "text", "confirming legit user field 5 type");
|
||||
is(input.name, "uname5", "confirming legit user field 5 name");
|
||||
//is(input.value, "testuser5", "checking legit user field 5 value");
|
||||
todo(input.value == "testuser5", "ignore bogus <input> and fill testuser5");
|
||||
is(input.value, "testuser5", "checking legit user field 5 value");
|
||||
input = form.elements[1];
|
||||
is(input.type, "password", "confirming bogus user field 5 type");
|
||||
is(input.name, "uname5", "confirming bogus user field 5 name");
|
||||
|
@ -171,8 +168,7 @@ function startTest() {
|
|||
input = form.elements[2];
|
||||
is(input.type, "password", "confirming password field 5 ");
|
||||
is(input.name, "pword5", "confirming password field 5 ");
|
||||
//is(input.value, "testpass5", "checking password field 5 value");
|
||||
todo(input.value == "testpass5", "ignore bogus <input> and fill testpass5");
|
||||
is(input.value, "testpass5", "checking password field 5 value");
|
||||
|
||||
form = document.forms[5];
|
||||
input = form.elements[0];
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Password Manager</title>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Password Manager test: 270558
|
||||
Login Manager test: 270558
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
@ -91,7 +91,7 @@ Password Manager test: 270558
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: 270558 (Password manager should not fill in username and
|
||||
/** Test for Login Manager: 270558 (Password manager should not fill in username and
|
||||
password if the username field is pre-filled by the server to a different username.
|
||||
(frequent problem with phpBB admin interface)) **/
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Password Manager</title>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Password Manager test: 360493
|
||||
Login Manager test: 360493
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
@ -108,7 +108,7 @@ Password Manager test: 360493
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: 360493 (Cross-Site Forms + Password Manager = Security Failure) **/
|
||||
/** Test for Login Manager: 360493 (Cross-Site Forms + Password Manager = Security Failure) **/
|
||||
|
||||
// This test is designed to make sure variations on the form's |action| and |method|
|
||||
// continue to work with the fix for 360493.
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Password Manager</title>
|
||||
<title>Test for Login Manager</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="pwmgr_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Password Manager test: 360493
|
||||
Login Manager test: 360493
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
@ -129,7 +129,7 @@ Password Manager test: 360493
|
|||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Password Manger: 360493 (Cross-Site Forms + Password Manager = Security Failure) **/
|
||||
/** Test for Login Manager: 360493 (Cross-Site Forms + Password Manager = Security Failure) **/
|
||||
|
||||
function startTest() {
|
||||
for (var i = 1; i <= 8; i++) {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#2c
|
|
@ -0,0 +1,3 @@
|
|||
#2d
|
||||
http://www.nsa.gov
|
||||
.
|
|
@ -0,0 +1,3 @@
|
|||
#2d
|
||||
http://www.nsa.gov
|
||||
.
|
|
@ -0,0 +1,2 @@
|
|||
#2d
|
||||
.
|
|
@ -0,0 +1,9 @@
|
|||
#2d
|
||||
.
|
||||
http://dummyhost.mozilla.org
|
||||
put_user_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECIfQXnNdOlcABBCrqWo0hzkpOPmpGiybiVkU
|
||||
*put_pw_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECO2TxG6B5o66BBA1PUI/iSkl1G020imhKgEa
|
||||
|
||||
.
|
|
@ -0,0 +1,16 @@
|
|||
#2d
|
||||
.
|
||||
http://dummyhost.mozilla.org
|
||||
put_user_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECCcwyTNPm0qJBBD10w5WFcQ7eMIMGSTujH3k
|
||||
*put_pw_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECOqroi20oiqbBBC2UnpoZC9M/pkem9Csfzeg
|
||||
|
||||
.
|
||||
http://dummyhost2.mozilla.org
|
||||
put_user2_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECKRdcGvGFLweBBBPN2MNaaw6NUUkkj0CebX+
|
||||
*put_pw2_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECPFh9cwe24C1BBA3dcR+4B6G5kmb/oE+9zFT
|
||||
http://cgi.site.com
|
||||
.
|
|
@ -0,0 +1,14 @@
|
|||
#2d
|
||||
.
|
||||
http://dummyhost2.mozilla.org
|
||||
put_user2_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECI/wcg7naww1BBD/ookfBmtc2MX0g8Xyr51f
|
||||
*put_pw2_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECAoufABHZExXBBDEjlmK9AmpFcp8ODsdgofN
|
||||
http://cgi.site.com
|
||||
put_user3_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECK+7oqm6qJyjBBCu0Nxgl+ebE25bMcl4/RnT
|
||||
*put_pw3_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECA//vIyOIl4oBBALsaRqgn86jFYdZioff78I
|
||||
http://cgi.site.com
|
||||
.
|
|
@ -0,0 +1,21 @@
|
|||
#2d
|
||||
.
|
||||
http://dummyhost2.mozilla.org
|
||||
put_user3_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECKfHgxwiNXmTBBDcGLjIy+oENYOm1q221TOt
|
||||
*put_pw3_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECA+Z8io0HuoEBBAeIuKN+GhWoUBTe2BXMXFi
|
||||
http://cgi.site.com
|
||||
put_user2_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECHyVmW8pKofcBBBpItqB2fSkoRy5QpsDqRLC
|
||||
*put_pw2_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECOeOPkiPdHytBBCiyHzAsUTV5lJsf5DODskj
|
||||
http://cgi.site.com
|
||||
.
|
||||
http://dummyhost.mozilla.org
|
||||
put_user_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECH8TQwm4TZZvBBA5QKgtqCn/M56QolF8ul4i
|
||||
*put_pw_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECO9sv4sGVI+aBBDFwhQekg9Gzw1dpx41zp6D
|
||||
|
||||
.
|
|
@ -0,0 +1,2 @@
|
|||
thisHeaderIsInvalid
|
||||
|
|
@ -0,0 +1 @@
|
|||
#2c
|
|
@ -0,0 +1,3 @@
|
|||
#2c
|
||||
http://www.disabled.com
|
||||
.
|
|
@ -0,0 +1,4 @@
|
|||
#2c
|
||||
http://www.disabled.com
|
||||
.
|
||||
.
|
|
@ -0,0 +1,8 @@
|
|||
#2c
|
||||
.
|
||||
http://dummyhost.mozilla.org
|
||||
put_user_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECEnlbhAkNBbBBBCexD5eaffSLGH/ORiFlQ4X
|
||||
*put_pw_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECHmiTaseYjkkBBAA0ILJTFSa5CnlpD5PTEYR
|
||||
.
|
|
@ -0,0 +1,9 @@
|
|||
#2c
|
||||
https://www.site.net
|
||||
.
|
||||
http://dummyhost.mozilla.org
|
||||
put_user_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECEnlbhAkNBbBBBCexD5eaffSLGH/ORiFlQ4X
|
||||
*put_pw_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECHmiTaseYjkkBBAA0ILJTFSa5CnlpD5PTEYR
|
||||
.
|
|
@ -0,0 +1,12 @@
|
|||
#2c
|
||||
.
|
||||
http://dummyhost.mozilla.org
|
||||
put_user_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECEnlbhAkNBbBBBCexD5eaffSLGH/ORiFlQ4X
|
||||
*put_pw_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECHmiTaseYjkkBBAA0ILJTFSa5CnlpD5PTEYR
|
||||
put_user2_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECN3Gv1qOhoVxBBCgfjGGL+0PJ9iqP/uAHp2c
|
||||
*put_pw2_here
|
||||
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECMOQnjGpKF9jBBAoXZIkQ9BSElkS5s6L51qX
|
||||
.
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1 @@
|
|||
#2c
|
|
@ -0,0 +1,42 @@
|
|||
// Copied from components/places/tests/unit/head_bookmarks.js
|
||||
|
||||
const NS_APP_USER_PROFILE_50_DIR = "ProfD";
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const Cr = Components.results;
|
||||
|
||||
// If there's no location registered for the profile direcotry, register one now.
|
||||
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||
var profileDir = null;
|
||||
|
||||
try {
|
||||
profileDir = dirSvc.get(NS_APP_USER_PROFILE_50_DIR, Ci.nsIFile);
|
||||
} catch (e) {}
|
||||
|
||||
if (!profileDir) {
|
||||
// Register our own provider for the profile directory.
|
||||
// It will simply return the current directory.
|
||||
var provider = {
|
||||
getFile: function(prop, persistent) {
|
||||
persistent.value = true;
|
||||
if (prop == NS_APP_USER_PROFILE_50_DIR) {
|
||||
return dirSvc.get("CurProcD", Ci.nsIFile); //TODO point this elsewhere, where we can install key3.db?
|
||||
}
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
},
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Ci.nsIDirectoryServiceProvider) ||
|
||||
iid.equals(Ci.nsISupports)) {
|
||||
return this;
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
};
|
||||
dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider);
|
||||
}
|
||||
|
||||
|
||||
// Get key3.db into the proper place.
|
||||
var keydb = do_get_file("toolkit/components/passwordmgr/test/unit/key3.db");
|
||||
profileDir = dirSvc.get(NS_APP_USER_PROFILE_50_DIR, Ci.nsIFile);
|
||||
keydb.copyTo(profileDir, "key3.db");
|
Двоичный файл не отображается.
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* Test suite for storage-Legacy.js -- exercises reading from on-disk storage.
|
||||
*
|
||||
* This test interfaces directly with the legacy password storage module, by passing the normal
|
||||
* password manager usage.
|
||||
*
|
||||
*/
|
||||
|
||||
var DIR_SERVICE = new Components.Constructor(
|
||||
"@mozilla.org/file/directory_service;1", "nsIProperties");
|
||||
var TESTDIR = (new DIR_SERVICE()).get("ProfD", Ci.nsIFile).path;
|
||||
|
||||
function initStorage(filename, storage, expectedError) {
|
||||
var e, caughtError = false;
|
||||
|
||||
var file = do_get_file("toolkit/components/passwordmgr/test/unit/data/" + filename);
|
||||
|
||||
try {
|
||||
storage.initWithFile(file.parent.path, file.leafName, null);
|
||||
} catch (e) { caughtError = true; var err = e;}
|
||||
|
||||
if (expectedError) {
|
||||
if (!caughtError) { throw "Component should have returned an error (" + expectedError + "), but did not."; }
|
||||
|
||||
if (!expectedError.test(err)) { throw "Expected error was of wrong type: expected (" + expectedError + "), got " + err; }
|
||||
|
||||
// We got the expected error, so make a note in the test log. Don't Panic!
|
||||
dump("...that error was expected.\n\n");
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
// Compare info from component to what we expected.
|
||||
function checkStorageData(storage, ref_disabledHosts, ref_logins) {
|
||||
|
||||
var stor_disabledHosts = storage.getAllDisabledHosts({});
|
||||
do_check_eq(ref_disabledHosts.length, stor_disabledHosts.length);
|
||||
|
||||
|
||||
var stor_logins = storage.getAllLogins({});
|
||||
do_check_eq(ref_logins.length, stor_logins.length);
|
||||
|
||||
/*
|
||||
* Check values of the disabled list. We check both "x in y" and "y in x"
|
||||
* to make sure any differences are explicitly noted.
|
||||
*/
|
||||
var i, j, found;
|
||||
for (i = 0; i < ref_disabledHosts.length; i++) {
|
||||
for (j = 0; !found && j < stor_disabledHosts.length; j++) {
|
||||
found = (ref_disabledHosts[i] == stor_disabledHosts[j]);
|
||||
}
|
||||
do_check_true(found || stor_disabledHosts.length == 0);
|
||||
}
|
||||
for (j = 0; j < stor_disabledHosts.length; j++) {
|
||||
for (i = 0; !found && i < ref_disabledHosts.length; i++) {
|
||||
found = (ref_disabledHosts[i] == stor_disabledHosts[j]);
|
||||
}
|
||||
do_check_true(found || stor_disabledHosts.length == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check values of the logins list. We check both "x in y" and "y in x"
|
||||
* to make sure any differences are explicitly noted.
|
||||
*/
|
||||
for (i = 0; i < ref_logins.length; i++) {
|
||||
for (j = 0; !found && j < stor_logins.length; j++) {
|
||||
found = ref_logins[i].equals(stor_logins[j]);
|
||||
}
|
||||
do_check_true(found || stor_logins.length == 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
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);
|
||||
|
||||
testuser1 = new nsLoginInfo;
|
||||
testuser1.hostname = "http://dummyhost.mozilla.org";
|
||||
testuser1.formSubmitURL = "";
|
||||
testuser1.username = "dummydude";
|
||||
testuser1.password = "itsasecret";
|
||||
testuser1.usernameField = "put_user_here";
|
||||
testuser1.passwordField = "put_pw_here";
|
||||
testuser1.httpRealm = null;
|
||||
|
||||
testuser2 = new nsLoginInfo;
|
||||
testuser2.hostname = "http://dummyhost.mozilla.org";
|
||||
testuser2.formSubmitURL = "";
|
||||
testuser2.username = "dummydude2";
|
||||
testuser2.password = "itsasecret2";
|
||||
testuser2.usernameField = "put_user2_here";
|
||||
testuser2.passwordField = "put_pw2_here";
|
||||
testuser2.httpRealm = null;
|
||||
|
||||
var logins, disabledHosts;
|
||||
|
||||
dump("/* ========== 1 ========== */\n");
|
||||
var testnum = 1;
|
||||
var testdesc = "Initial connection to storage module"
|
||||
|
||||
var storage = Cc["@mozilla.org/login-manager/storage/legacy;1"].createInstance(Ci.nsILoginManagerStorage);
|
||||
if (!storage) throw "Couldn't create storage instance.";
|
||||
|
||||
|
||||
dump("/* ========== 2 ========== */\n");
|
||||
testnum++;
|
||||
testdesc = "[ensuring file doesn't exist]";
|
||||
// XXX skip this test
|
||||
if (0) {
|
||||
var filename="this-file-does-not-exist-"+Math.floor(Math.random() * 10000);
|
||||
var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(TESTDIR);
|
||||
file.append(filename);
|
||||
var exists = file.exists();
|
||||
if (exists) {
|
||||
// Go ahead and remove the file, so that this failure doesn't repeat itself w/o intervention.
|
||||
file.remove(false);
|
||||
do_check_false(exists);
|
||||
}
|
||||
|
||||
testdesc = "Initialize with a non-existant data file";
|
||||
|
||||
initStorage(filename, storage, null);
|
||||
checkStorageData(storage, [], []);
|
||||
|
||||
file.remove(false);
|
||||
}
|
||||
|
||||
dump("/* ========== 3 ========== */\n");
|
||||
testnum++;
|
||||
testdesc = "Initialize with signons-00.txt (a zero-length file)";
|
||||
|
||||
initStorage("signons-00.txt", storage, /invalid file header/);
|
||||
checkStorageData(storage, [], []);
|
||||
|
||||
|
||||
/* ========== 4 ========== */
|
||||
testnum++;
|
||||
testdesc = "Initialize with signons-01.txt (bad file header)";
|
||||
|
||||
initStorage("signons-01.txt", storage, /invalid file header/);
|
||||
checkStorageData(storage, [], []);
|
||||
|
||||
|
||||
/* ========== 5 ========== */
|
||||
testnum++;
|
||||
testdesc = "Initialize with signons-02.txt (valid, but empty)";
|
||||
|
||||
initStorage("signons-02.txt", storage, null);
|
||||
checkStorageData(storage, [], []);
|
||||
|
||||
|
||||
/* ========== 6 ========== */
|
||||
testnum++;
|
||||
testdesc = "Initialize with signons-03.txt (1 disabled, 0 logins)";
|
||||
|
||||
initStorage("signons-03.txt", storage, null);
|
||||
|
||||
disabledHosts = ["http://www.disabled.com"];
|
||||
checkStorageData(storage, disabledHosts, []);
|
||||
|
||||
|
||||
/* ========== 7 ========== */
|
||||
testnum++;
|
||||
testdesc = "Initialize with signons-06.txt (1 disabled, 0 logins, extra '.')";
|
||||
// XXX I'm not sure if the extra dot is possible with any released code, but
|
||||
// it seems likely that a 3rd party program might do this, since it's
|
||||
// consistant with how signons.txt looks when there's at least 1 login.
|
||||
// So, well test it anyway to be sure we don't accidently break this hypothetical case.
|
||||
|
||||
initStorage("signons-04.txt", storage, null);
|
||||
|
||||
disabledHosts = ["http://www.disabled.com"];
|
||||
checkStorageData(storage, disabledHosts, []);
|
||||
|
||||
|
||||
/* ========== 8 ========== */
|
||||
testnum++;
|
||||
testdesc = "Initialize with signons-05.txt (0 disabled, 1 login)";
|
||||
|
||||
initStorage("signons-05.txt", storage, null);
|
||||
|
||||
logins = [testuser1];
|
||||
checkStorageData(storage, [], logins);
|
||||
|
||||
|
||||
/* ========== 9 ========== */
|
||||
testnum++;
|
||||
testdesc = "Initialize with signons-06.txt (1 disabled, 1 login)";
|
||||
|
||||
initStorage("signons-06.txt", storage, null);
|
||||
|
||||
disabledHosts = ["https://www.site.net"];
|
||||
logins = [testuser1];
|
||||
checkStorageData(storage, disabledHosts, logins);
|
||||
|
||||
|
||||
/* ========== 10 ========== */
|
||||
testnum++;
|
||||
testdesc = "Initialize with signons-07.txt (0 disabled, 2 logins for same host)";
|
||||
|
||||
initStorage("signons-07.txt", storage, null);
|
||||
|
||||
logins = [testuser1, testuser2];
|
||||
checkStorageData(storage, [], logins);
|
||||
|
||||
|
||||
/* ========== 11 ========== */
|
||||
testnum++;
|
||||
testdesc = "Initialize with signons-08.txt (1000 disabled, 1000 logins)";
|
||||
|
||||
initStorage("signons-08.txt", storage, null);
|
||||
|
||||
disabledHosts = [];
|
||||
for (var i = 1; i <= 1000; i++) {
|
||||
disabledHosts.push("http://host-" + i + ".site.com");
|
||||
}
|
||||
|
||||
logins = [];
|
||||
for (i = 1; i <= 500; i++) {
|
||||
logins.push("http://dummyhost.site.org");
|
||||
}
|
||||
for (i = 1; i <= 500; i++) {
|
||||
logins.push("http://dummyhost-" + i + ".site.org");
|
||||
}
|
||||
checkStorageData(storage, disabledHosts, logins);
|
||||
|
||||
|
||||
// XXX more test ideas...
|
||||
// * old/new formats (header, actionURL)
|
||||
// * HTTP realm testing
|
||||
// * various newline types for cross-platform compat. checking
|
||||
|
||||
} catch (e) {
|
||||
throw "FAILED in test #" + testnum + " -- " + testdesc + ": " + e; }
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* Test suite for storage-Legacy.js -- exercises writing to on-disk storage.
|
||||
*
|
||||
* This test interfaces directly with the legacy password storage module, by passing the normal
|
||||
* password manager usage.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
var DIR_SERVICE = new Components.Constructor(
|
||||
"@mozilla.org/file/directory_service;1", "nsIProperties");
|
||||
var TESTDIR = (new DIR_SERVICE()).get("ProfD", Ci.nsIFile).path;
|
||||
|
||||
var REFDIR = TESTDIR;
|
||||
|
||||
function areFilesIdentical(pathname1, filename1, pathname2, filename2) {
|
||||
var file1 = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
var file2 = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
file1.initWithPath(pathname1);
|
||||
file2.initWithPath(pathname2);
|
||||
file1.append(filename1);
|
||||
file2.append(filename2);
|
||||
if (!file1.exists()) { throw("areFilesIdentical: file " + filename1 + " does not exist."); }
|
||||
if (!file2.exists()) { throw("areFilesIdentical: file " + filename2 + " does not exist."); }
|
||||
|
||||
var inputStream1 = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
|
||||
var inputStream2 = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
|
||||
inputStream1.init(file1, 0x01, 0600, null); // RD_ONLY
|
||||
inputStream2.init(file2, 0x01, 0600, null); // RD_ONLY
|
||||
|
||||
const PR_UINT32_MAX = 0xffffffff; // read whole file
|
||||
var md5 = Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);
|
||||
|
||||
md5.init(md5.MD5);
|
||||
md5.updateFromStream(inputStream1, PR_UINT32_MAX);
|
||||
var hash1 = md5.finish(true);
|
||||
|
||||
md5.init(md5.MD5);
|
||||
md5.updateFromStream(inputStream2, PR_UINT32_MAX);
|
||||
var hash2 = md5.finish(true);
|
||||
|
||||
inputStream1.close();
|
||||
inputStream2.close();
|
||||
|
||||
var identical = (hash1 == hash2);
|
||||
|
||||
return identical;
|
||||
}
|
||||
|
||||
|
||||
function initStorage(inputfile, outputfile, path, storage, expectedError) {
|
||||
var e, caughtError = false;
|
||||
|
||||
try {
|
||||
storage.initWithFile(path, inputfile, outputfile);
|
||||
} catch (e) { caughtError = true; var err = e;}
|
||||
|
||||
if (expectedError) {
|
||||
if (!caughtError) { throw "Component should have returned an error (" + expectedError + "), but did not."; }
|
||||
|
||||
if (!expectedError.test(err)) { throw "Expected error was of wrong type: expected (" + expectedError + "), got " + err; }
|
||||
|
||||
// We got the expected error, so make a note in the test log. Don't Panic!
|
||||
dump("...that error was expected.\n\n");
|
||||
} else if (caughtError) {
|
||||
throw "Component threw unexpected error: " + err;
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
// Compare info from component to what we expected.
|
||||
function checkStorageData(storage, ref_disabledHosts, ref_logins) {
|
||||
|
||||
var stor_disabledHosts = storage.getAllDisabledHosts({});
|
||||
do_check_eq(ref_disabledHosts.length, stor_disabledHosts.length);
|
||||
|
||||
|
||||
var stor_logins = storage.getAllLogins({});
|
||||
do_check_eq(ref_logins.length, stor_logins.length);
|
||||
|
||||
/*
|
||||
* Check values of the disabled list. We check both "x in y" and "y in x"
|
||||
* to make sure any differences are explicitly noted.
|
||||
*/
|
||||
var i, j, found;
|
||||
for (i = 0; i < ref_disabledHosts.length; i++) {
|
||||
for (j = 0; !found && j < stor_disabledHosts.length; j++) {
|
||||
found = (ref_disabledHosts[i] == stor_disabledHosts[j]);
|
||||
}
|
||||
do_check_true(found || stor_disabledHosts.length == 0);
|
||||
}
|
||||
for (j = 0; j < stor_disabledHosts.length; j++) {
|
||||
for (i = 0; !found && i < ref_disabledHosts.length; i++) {
|
||||
found = (ref_disabledHosts[i] == stor_disabledHosts[j]);
|
||||
}
|
||||
do_check_true(found || stor_disabledHosts.length == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check values of the logins list. We check both "x in y" and "y in x"
|
||||
* to make sure any differences are explicitly noted.
|
||||
*/
|
||||
var ref, stor;
|
||||
for (i = 0; i < ref_logins.length; i++) {
|
||||
for (j = 0; !found && j < stor_logins.length; j++) {
|
||||
found = ref_logins[i].equals(stor_logins[j]);
|
||||
}
|
||||
do_check_true(found || stor_logins.length == 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function run_test() {
|
||||
|
||||
//TODO need to get our reference files into the profile dir?
|
||||
//TODO skip test for the moment
|
||||
return;
|
||||
|
||||
try {
|
||||
|
||||
|
||||
/* ========== 0 ========== */
|
||||
var testnum = 0;
|
||||
var testdesc = "Initial connection to storage module"
|
||||
|
||||
var storage = Cc["@mozilla.org/login-manager/storage/legacy;1"].createInstance(Ci.nsILoginManagerStorage);
|
||||
if (!storage) throw "Couldn't create storage instance.";
|
||||
|
||||
|
||||
/* ========== 1 ========== */
|
||||
testnum++;
|
||||
var testdesc = "Create nsILoginInfo instances for testing with"
|
||||
|
||||
var dummyuser1 = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
|
||||
var dummyuser2 = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
|
||||
var dummyuser3 = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
|
||||
|
||||
dummyuser1.hostname = "http://dummyhost.mozilla.org";
|
||||
dummyuser1.username = "dummydude";
|
||||
dummyuser1.usernameField = "put_user_here";
|
||||
dummyuser1.password = "itsasecret";
|
||||
dummyuser1.passwordField = "put_pw_here";
|
||||
dummyuser1.formSubmitURL = "";
|
||||
dummyuser1.httpRealm = null;
|
||||
|
||||
dummyuser2.hostname = "http://dummyhost2.mozilla.org";
|
||||
dummyuser2.username = "dummydude2";
|
||||
dummyuser2.usernameField = "put_user2_here";
|
||||
dummyuser2.password = "itsasecret2";
|
||||
dummyuser2.passwordField = "put_pw2_here";
|
||||
dummyuser2.formSubmitURL = "http://cgi.site.com";
|
||||
dummyuser2.httpRealm = null;
|
||||
|
||||
dummyuser3.hostname = "http://dummyhost2.mozilla.org";
|
||||
dummyuser3.username = "dummydude3";
|
||||
dummyuser3.usernameField = "put_user3_here";
|
||||
dummyuser3.password = "itsasecret3";
|
||||
dummyuser3.passwordField = "put_pw3_here";
|
||||
dummyuser3.formSubmitURL = "http://cgi.site.com";
|
||||
dummyuser3.httpRealm = null;
|
||||
|
||||
var logins, disabledHosts;
|
||||
|
||||
/* ========== 2 ========== */
|
||||
testnum++;
|
||||
|
||||
testdesc = "[ensuring file doesn't exist]";
|
||||
var filename="non-existant-file-"+Math.floor(Math.random() * 10000);
|
||||
var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(TESTDIR);
|
||||
file.append(filename);
|
||||
var exists = file.exists();
|
||||
if (exists) {
|
||||
// Go ahead and remove the file, so that this failure doesn't repeat itself w/o intervention.
|
||||
file.remove(false);
|
||||
do_check_false(exists);
|
||||
}
|
||||
|
||||
testdesc = "Initialize with no existing file";
|
||||
initStorage(filename, null, TESTDIR, storage, null);
|
||||
|
||||
checkStorageData(storage, [], []);
|
||||
|
||||
testdesc = "Add 1 disabled host only";
|
||||
storage.setLoginSavingEnabled("http://www.nsa.gov", false);
|
||||
disabledHosts = ["http://www.nsa.gov"];
|
||||
checkStorageData(storage, disabledHosts, []);
|
||||
|
||||
// Make sure the filename stays non-existant for future tests.
|
||||
testdesc = "[moving file and checking contents]";
|
||||
file.moveTo(null, "output-00.txt");
|
||||
do_check_true(areFilesIdentical(TESTDIR, "output-00.txt", REFDIR, "reference-output-00.txt"));
|
||||
|
||||
|
||||
/* ========== 3 ========== */
|
||||
testnum++;
|
||||
|
||||
testdesc = "[copying empty file to testing name]";
|
||||
file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(REFDIR);
|
||||
file.append("signons-empty.txt");
|
||||
var file2 = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
file2.initWithPath(TESTDIR);
|
||||
file2.append("output-01.txt");
|
||||
|
||||
// Make sure the .copyTo will work is the test already ran once.
|
||||
if (file2.exists()) { file2.remove(false); }
|
||||
|
||||
// Copy empty reference file to the file we're going to use.
|
||||
do_check_true(file.exists());
|
||||
file.copyTo(null, "output-01.txt");
|
||||
do_check_true(areFilesIdentical(TESTDIR, "output-01.txt", REFDIR, "reference-empty.txt"));
|
||||
|
||||
testdesc = "Initialize with existing file (valid, but empty)";
|
||||
initStorage("output-01.txt", null, TESTDIR, storage, null);
|
||||
checkStorageData(storage, [], []);
|
||||
|
||||
testdesc = "Add 1 disabled host only";
|
||||
storage.setLoginSavingEnabled("http://www.nsa.gov", false);
|
||||
|
||||
disabledHosts = ["http://www.nsa.gov"];
|
||||
checkStorageData(storage, disabledHosts, []);
|
||||
do_check_true(areFilesIdentical(TESTDIR, "output-01.txt", REFDIR, "reference-output-01a.txt"));
|
||||
|
||||
testdesc = "Remove disabled host only";
|
||||
storage.setLoginSavingEnabled("http://www.nsa.gov", true);
|
||||
|
||||
checkStorageData(storage, [], []);
|
||||
do_check_true(areFilesIdentical(TESTDIR, "output-01.txt", REFDIR, "reference-output-01b.txt"));
|
||||
|
||||
|
||||
/* ========== 4 ========== */
|
||||
testnum++;
|
||||
|
||||
testdesc = "[clear data and reinitialize with signons-empty.txt]";
|
||||
initStorage("signons-empty.txt", "output-02.txt", TESTDIR, storage, null);
|
||||
|
||||
// Previous tests made sure we can write to an existing file, so now just tweak component
|
||||
// to output elsewhere.
|
||||
testdesc = "Add 1 login only";
|
||||
storage.addLogin(dummyuser1);
|
||||
|
||||
testdesc = "[flush and reload for verification]";
|
||||
initStorage("output-02.txt", null, TESTDIR, storage, null);
|
||||
|
||||
testdesc = "Verify output-02.txt";
|
||||
checkStorageData(storage, [], [dummyuser1]);
|
||||
|
||||
// We can't do file comparions, because the encrypted data gets
|
||||
// a different salt each time it's written. But we'll do this
|
||||
// one test here to make sure it's actually happening.
|
||||
do_check_false(areFilesIdentical(TESTDIR, "output-02.txt", REFDIR, "reference-output-02.txt"));
|
||||
|
||||
|
||||
/* ========== 5 ========== */
|
||||
testnum++;
|
||||
|
||||
testdesc = "[clear data and reinitialize with signons-empty.txt]";
|
||||
initStorage("signons-empty.txt", "output-03.txt", TESTDIR, storage, null);
|
||||
|
||||
testdesc = "Add 1 disabled host only";
|
||||
storage.setLoginSavingEnabled("http://www.nsa.gov", false);
|
||||
|
||||
testdesc = "[flush and reload for verification]";
|
||||
initStorage("output-03.txt", null, TESTDIR, storage, null);
|
||||
|
||||
testdesc = "Verify output-03.txt";
|
||||
checkStorageData(storage, ["http://www.nsa.gov"], []);
|
||||
|
||||
|
||||
/* ========== 6 ========== */
|
||||
testnum++;
|
||||
|
||||
testdesc = "[clear data and reinitialize with signons-empty.txt]";
|
||||
initStorage("signons-empty.txt", "output-04.txt", TESTDIR, storage, null);
|
||||
|
||||
testdesc = "Add 1 disabled host and 1 login";
|
||||
storage.setLoginSavingEnabled("http://www.nsa.gov", false);
|
||||
storage.addLogin(dummyuser1);
|
||||
|
||||
testdesc = "[flush and reload for verification]";
|
||||
initStorage("output-04.txt", null, TESTDIR, storage, null);
|
||||
|
||||
testdesc = "Verify output-04.txt";
|
||||
checkStorageData(storage, ["http://www.nsa.gov"], [dummyuser1]);
|
||||
|
||||
|
||||
/* ========== 7 ========== */
|
||||
testnum++;
|
||||
|
||||
testdesc = "[clear data and reinitialize with signons-empty.txt]";
|
||||
initStorage("signons-empty.txt", "output-03.txt", TESTDIR, storage, null);
|
||||
|
||||
testdesc = "Add 2 logins (to different hosts)";
|
||||
storage.addLogin(dummyuser1);
|
||||
storage.addLogin(dummyuser2);
|
||||
|
||||
testdesc = "[flush and reload for verification]";
|
||||
initStorage("output-03.txt", null, TESTDIR, storage, null);
|
||||
|
||||
testdesc = "Verify output-03.txt";
|
||||
checkStorageData(storage, [], [dummyuser2, dummyuser1]);
|
||||
|
||||
|
||||
/* ========== 8 ========== */
|
||||
testnum++;
|
||||
|
||||
testdesc = "[clear data and reinitialize with signons-empty.txt]";
|
||||
initStorage("signons-empty.txt", "output-04.txt", TESTDIR, storage, null);
|
||||
|
||||
testdesc = "Add 2 logins (to same host)";
|
||||
storage.addLogin(dummyuser2);
|
||||
storage.addLogin(dummyuser3);
|
||||
|
||||
testdesc = "[flush and reload for verification]";
|
||||
initStorage("output-04.txt", null, TESTDIR, storage, null);
|
||||
|
||||
testdesc = "Verify output-04.txt";
|
||||
logins = [dummyuser3, dummyuser2];
|
||||
checkStorageData(storage, [], logins);
|
||||
|
||||
|
||||
/* ========== 9 ========== */
|
||||
testnum++;
|
||||
|
||||
testdesc = "[clear data and reinitialize with signons-empty.txt]";
|
||||
initStorage("signons-empty.txt", "output-05.txt", TESTDIR, storage, null);
|
||||
|
||||
testdesc = "Add 3 logins (2 to same host)";
|
||||
storage.addLogin(dummyuser3);
|
||||
storage.addLogin(dummyuser1);
|
||||
storage.addLogin(dummyuser2);
|
||||
|
||||
testdesc = "[flush and reload for verification]";
|
||||
initStorage("output-05.txt", null, TESTDIR, storage, null);
|
||||
|
||||
testdesc = "Verify output-05.txt";
|
||||
logins = [dummyuser1, dummyuser2, dummyuser3];
|
||||
checkStorageData(storage, [], logins);
|
||||
|
||||
/* ========== 10 ========== */
|
||||
testnum++;
|
||||
|
||||
testdesc = "Final sanity test to make sure signons-empty.txt wasn't modified.";
|
||||
do_check_true(areFilesIdentical(TESTDIR, "signons-empty.txt", REFDIR, "reference-empty.txt"));
|
||||
|
||||
|
||||
// test writing a file that already contained entries
|
||||
// test overwriting a file early
|
||||
// test permissions on output file (osx/unix)
|
||||
// test starting with an invalid file, and a non-existant file.
|
||||
// excercise the case where we immediately write the data on init, if we find empty entries
|
||||
// test writing a gazillion entries
|
||||
|
||||
} catch (e) { throw ("FAILED in test #" + testnum + " -- " + testdesc + ": " + e); }
|
||||
};
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
interface nsIDocShell;
|
||||
interface nsIAutoCompletePopup;
|
||||
interface nsIDOMHTMLInputElement;
|
||||
|
||||
/*
|
||||
* nsIFormFillController is an interface for controlling form fill behavior
|
||||
|
@ -49,7 +50,7 @@ interface nsIAutoCompletePopup;
|
|||
* global nsIAutoCompleteController service.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(872F07F3-ED11-47c6-B7CF-246DB53379FB)]
|
||||
[scriptable, uuid(07f0a0dc-f6e9-4cdd-a55f-56d770523a4c)]
|
||||
interface nsIFormFillController : nsISupports
|
||||
{
|
||||
/*
|
||||
|
@ -66,4 +67,13 @@ interface nsIFormFillController : nsISupports
|
|||
* @param docShell - The docShell to detach from
|
||||
*/
|
||||
void detachFromBrowser(in nsIDocShell docShell);
|
||||
|
||||
/*
|
||||
* Mark the specified <input> element as being managed by password manager.
|
||||
* Autocomplete requests will be handed off to the password manager, and will
|
||||
* not be stored in form history.
|
||||
*
|
||||
* @param aInput - The HTML <input> element to tag
|
||||
*/
|
||||
void markAsLoginManagerField(in nsIDOMHTMLInputElement aInput);
|
||||
};
|
||||
|
|
|
@ -69,6 +69,7 @@ REQUIRES = \
|
|||
pref \
|
||||
windowwatcher \
|
||||
toolkitcomps \
|
||||
passwordmgr \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = nsFormFillController.cpp \
|
||||
|
@ -78,14 +79,9 @@ REQUIRES += storage morkreader
|
|||
CPPSRCS += nsStorageFormHistory.cpp
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../../passwordmgr/base \
|
||||
-I$(srcdir)/../../build \
|
||||
$(NULL)
|
||||
|
||||
SHARED_LIBRARY_LIBS = \
|
||||
../../passwordmgr/base/$(LIB_PREFIX)passwordmgr_s.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DSO_LIBS = gkgfx
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -69,8 +69,7 @@
|
|||
#include "nsRect.h"
|
||||
#include "nsIDOMDocumentEvent.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsPasswordManager.h"
|
||||
#include "nsSingleSignonPrompt.h"
|
||||
#include "nsILoginManager.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "nsToolkitCompsCID.h"
|
||||
|
@ -105,9 +104,10 @@ nsFormFillController::nsFormFillController() :
|
|||
mSuppressOnInput(PR_FALSE)
|
||||
{
|
||||
mController = do_GetService("@mozilla.org/autocomplete/controller;1");
|
||||
|
||||
mLoginManager = do_GetService("@mozilla.org/login-manager;1");
|
||||
mDocShells = do_CreateInstance("@mozilla.org/supports-array;1");
|
||||
mPopups = do_CreateInstance("@mozilla.org/supports-array;1");
|
||||
mPwmgrInputs.Init();
|
||||
}
|
||||
|
||||
nsFormFillController::~nsFormFillController()
|
||||
|
@ -184,6 +184,23 @@ nsFormFillController::DetachFromBrowser(nsIDocShell *aDocShell)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFormFillController::MarkAsLoginManagerField(nsIDOMHTMLInputElement *aInput)
|
||||
{
|
||||
/*
|
||||
* The Login Manager can supply autocomplete results for username fields,
|
||||
* when a user has multiple logins stored for a site. It uses this
|
||||
* interface to indicate that the form manager shouldn't handle the
|
||||
* autocomplete. The form manager also checks for this tag when saving
|
||||
* form history (so it doesn't save usernames).
|
||||
*/
|
||||
mPwmgrInputs.Put(aInput, 1);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//// nsIAutoCompleteInput
|
||||
|
||||
|
@ -479,37 +496,34 @@ nsFormFillController::GetConsumeRollupEvent(PRBool *aConsumeRollupEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//// nsIAutoCompleteSearch
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFormFillController::StartSearch(const nsAString &aSearchString, const nsAString &aSearchParam,
|
||||
nsIAutoCompleteResult *aPreviousResult, nsIAutoCompleteObserver *aListener)
|
||||
{
|
||||
nsCOMPtr<nsIAutoCompleteResult> result;
|
||||
|
||||
// If the login manager has indicated it's responsible for this field, let it
|
||||
// handle the autocomplete. Otherwise, handle with form history.
|
||||
PRInt32 dummy;
|
||||
if (mPwmgrInputs.Get(mFocusedInput, &dummy)) {
|
||||
// XXX aPreviousResult shouldn't ever be a historyResult type, since we're not letting
|
||||
// satchel manage the field?
|
||||
mLoginManager->AutoCompleteSearch(aSearchString,
|
||||
aPreviousResult,
|
||||
mFocusedInput,
|
||||
getter_AddRefs(result));
|
||||
} else {
|
||||
#ifdef MOZ_STORAGE_SATCHEL
|
||||
// This assumes that FormHistory uses nsIAutoCompleteSimpleResult,
|
||||
// while PasswordManager does not.
|
||||
nsCOMPtr<nsIAutoCompleteSimpleResult> historyResult;
|
||||
#else
|
||||
nsCOMPtr<nsIAutoCompleteMdbResult2> historyResult;
|
||||
#endif
|
||||
historyResult = do_QueryInterface(aPreviousResult);
|
||||
|
||||
nsPasswordManager* passMgr = nsPasswordManager::GetInstance();
|
||||
if (!passMgr)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Only hand off a previous result to the password manager if it's
|
||||
// a password manager result (i.e. not an nsIAutoCompleteMdb/SimpleResult).
|
||||
|
||||
if (!passMgr->AutoCompleteSearch(aSearchString,
|
||||
historyResult ? nsnull : aPreviousResult,
|
||||
mFocusedInput,
|
||||
getter_AddRefs(result)))
|
||||
{
|
||||
nsFormHistory *history = nsFormHistory::GetInstance();
|
||||
if (history) {
|
||||
history->AutoCompleteSearch(aSearchParam,
|
||||
|
@ -518,7 +532,6 @@ nsFormFillController::StartSearch(const nsAString &aSearchString, const nsAStrin
|
|||
getter_AddRefs(result));
|
||||
}
|
||||
}
|
||||
NS_RELEASE(passMgr);
|
||||
|
||||
aListener->OnSearchResult(this, result);
|
||||
|
||||
|
@ -537,9 +550,40 @@ nsFormFillController::StopSearch()
|
|||
NS_IMETHODIMP
|
||||
nsFormFillController::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsAutoString type;
|
||||
aEvent->GetType(type);
|
||||
|
||||
if (type.EqualsLiteral("pagehide")) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(target);
|
||||
if (!domDoc)
|
||||
return NS_OK;
|
||||
|
||||
mPwmgrInputs.Enumerate(RemoveForDOMDocumentEnumerator, domDoc);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* static */ PLDHashOperator PR_CALLBACK
|
||||
nsFormFillController::RemoveForDOMDocumentEnumerator(nsISupports* aKey,
|
||||
PRInt32& aEntry,
|
||||
void* aUserData)
|
||||
{
|
||||
nsIDOMDocument* domDoc = NS_STATIC_CAST(nsIDOMDocument*, aUserData);
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> element = do_QueryInterface(aKey);
|
||||
nsCOMPtr<nsIDOMDocument> elementDoc;
|
||||
element->GetOwnerDocument(getter_AddRefs(elementDoc));
|
||||
if (elementDoc == domDoc)
|
||||
return PL_DHASH_REMOVE;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//// nsIDOMFocusListener
|
||||
|
||||
|
@ -919,6 +963,10 @@ nsFormFillController::AddWindowListeners(nsIDOMWindow *aWindow)
|
|||
NS_STATIC_CAST(nsIDOMFocusListener *, this),
|
||||
PR_TRUE);
|
||||
|
||||
target->AddEventListener(NS_LITERAL_STRING("pagehide"),
|
||||
NS_STATIC_CAST(nsIDOMFocusListener *, this),
|
||||
PR_TRUE);
|
||||
|
||||
target->AddEventListener(NS_LITERAL_STRING("mousedown"),
|
||||
NS_STATIC_CAST(nsIDOMMouseListener *, this),
|
||||
PR_TRUE);
|
||||
|
@ -974,6 +1022,10 @@ nsFormFillController::RemoveWindowListeners(nsIDOMWindow *aWindow)
|
|||
NS_STATIC_CAST(nsIDOMFocusListener *, this),
|
||||
PR_TRUE);
|
||||
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("pagehide"),
|
||||
NS_STATIC_CAST(nsIDOMFocusListener *, this),
|
||||
PR_TRUE);
|
||||
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("mousedown"),
|
||||
NS_STATIC_CAST(nsIDOMMouseListener *, this),
|
||||
PR_TRUE);
|
||||
|
@ -1125,38 +1177,12 @@ nsFormFillController::GetIndexOfDocShell(nsIDocShell *aDocShell)
|
|||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsFormHistory, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormFillController)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsPasswordManager, nsPasswordManager::GetInstance)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSingleSignonPrompt)
|
||||
#if defined(MOZ_STORAGE_SATCHEL) && defined(MOZ_MORKREADER)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormHistoryImporter)
|
||||
#endif
|
||||
|
||||
static void PR_CALLBACK nsFormHistoryModuleDtor(nsIModule* self)
|
||||
{
|
||||
nsPasswordManager::Shutdown();
|
||||
}
|
||||
|
||||
static const nsModuleComponentInfo components[] =
|
||||
{
|
||||
{ "Password Manager",
|
||||
NS_PASSWORDMANAGER_CID,
|
||||
NS_PASSWORDMANAGER_CONTRACTID,
|
||||
nsPasswordManagerConstructor,
|
||||
nsPasswordManager::Register,
|
||||
nsPasswordManager::Unregister },
|
||||
|
||||
{ "Password Manager",
|
||||
NS_PASSWORDMANAGER_CID,
|
||||
NS_PWMGR_AUTHPROMPTFACTORY,
|
||||
nsPasswordManagerConstructor,
|
||||
nsPasswordManager::Register,
|
||||
nsPasswordManager::Unregister },
|
||||
|
||||
{ "Single Signon Prompt",
|
||||
NS_SINGLE_SIGNON_PROMPT_CID,
|
||||
"@mozilla.org/wallet/single-sign-on-prompt;1",
|
||||
nsSingleSignonPromptConstructor },
|
||||
|
||||
{ "HTML Form History",
|
||||
NS_FORMHISTORY_CID,
|
||||
NS_FORMHISTORY_CONTRACTID,
|
||||
|
@ -1180,5 +1206,5 @@ static const nsModuleComponentInfo components[] =
|
|||
#endif
|
||||
};
|
||||
|
||||
NS_IMPL_NSGETMODULE_WITH_DTOR(satchel, components, nsFormHistoryModuleDtor)
|
||||
NS_IMPL_NSGETMODULE(satchel, components)
|
||||
|
||||
|
|
|
@ -54,9 +54,11 @@
|
|||
#include "nsIDOMContextMenuListener.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsILoginManager.h"
|
||||
|
||||
class nsFormHistory;
|
||||
|
||||
|
@ -138,15 +140,21 @@ protected:
|
|||
inline nsIDOMWindow *GetWindowForDocShell(nsIDocShell *aDocShell);
|
||||
inline PRInt32 GetIndexOfDocShell(nsIDocShell *aDocShell);
|
||||
|
||||
static PLDHashOperator PR_CALLBACK RemoveForDOMDocumentEnumerator(nsISupports* aKey,
|
||||
PRInt32& aEntry,
|
||||
void* aUserData);
|
||||
// members //////////////////////////////////////////
|
||||
|
||||
nsCOMPtr<nsIAutoCompleteController> mController;
|
||||
nsCOMPtr<nsILoginManager> mLoginManager;
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> mFocusedInput;
|
||||
nsCOMPtr<nsIAutoCompletePopup> mFocusedPopup;
|
||||
|
||||
nsCOMPtr<nsISupportsArray> mDocShells;
|
||||
nsCOMPtr<nsISupportsArray> mPopups;
|
||||
|
||||
nsDataHashtable<nsISupportsHashKey,PRInt32> mPwmgrInputs;
|
||||
|
||||
PRUint32 mTimeout;
|
||||
PRUint32 mMinResultsForPopup;
|
||||
PRUint32 mMaxRows;
|
||||
|
|
|
@ -360,6 +360,9 @@ nsFormHistory::Notify(nsIDOMHTMLFormElement* formElt, nsIDOMWindowInternal* aWin
|
|||
if (!type.LowerCaseEqualsLiteral("text"))
|
||||
continue;
|
||||
|
||||
// TODO: If Login Manager marked this input, don't save it. The login
|
||||
// manager will deal with remembering it.
|
||||
|
||||
nsAutoString autocomplete;
|
||||
inputElt->GetAttribute(kAutoComplete, autocomplete);
|
||||
if (!autocomplete.LowerCaseEqualsLiteral("off")) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче