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:
gavin@gavinsharp.com 2007-05-16 03:02:45 -07:00
Родитель 5ceed539be
Коммит f4d5367465
63 изменённых файлов: 11485 добавлений и 271 удалений

Просмотреть файл

@ -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");

Двоичные данные
toolkit/components/passwordmgr/test/unit/key3.db Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -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")) {