- Add DOMAutoComplete event, fired on a form input element when the user

selects a completion from the popup.
- Listen for DOMAutoComplete and Blur events instead of Change events to
trigger prefilling the password field.
- Fix an off-by-one error in the multi-user password change confirmation
(the stored password was being changed for the wrong entry).
- Fix skipping multiple logins when reading the signon file.
- Add missing license for Makefile.in.
This commit is contained in:
bryner%brianryner.com 2003-08-04 00:57:26 +00:00
Родитель 58876decc1
Коммит 96c99c1a4a
4 изменённых файлов: 147 добавлений и 96 удалений

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

@ -179,7 +179,7 @@ NS_INTERFACE_MAP_BEGIN(nsPasswordManager)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsIFormSubmitObserver)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMFormListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPasswordManager)
@ -586,7 +586,8 @@ nsPasswordManager::OnStateChange(nsIWebProgress* aWebProgress,
// We can auto-prefill the username and password if there is only
// one stored login that matches the username and password field names
// on the form in question.
// on the form in question. Note that we only need to worry about a
// single login per form.
for (PRUint32 i = 0; i < formCount; ++i) {
nsCOMPtr<nsIDOMNode> formNode;
@ -613,12 +614,13 @@ nsPasswordManager::OnStateChange(nsIWebProgress* aWebProgress,
if (firstMatch) {
// We've found more than one possible signon for this form.
// Attach an onchange handler to the username field so that we can
// attempt to prefill the password after the user has
// Listen for blur and autocomplete events on the username field so
// that we can attempt to prefill the password after the user has
// entered the username.
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(userField);
targ->AddEventListener(NS_LITERAL_STRING("change"), this, PR_FALSE);
targ->AddEventListener(NS_LITERAL_STRING("blur"), this, PR_FALSE);
targ->AddEventListener(NS_LITERAL_STRING("DOMAutoComplete"), this, PR_FALSE);
firstMatch = nsnull;
break; // on to the next form
} else {
@ -634,6 +636,10 @@ nsPasswordManager::OnStateChange(nsIWebProgress* aWebProgress,
DecryptData(firstMatch->passValue, buffer);
passField->SetValue(buffer);
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(userField);
targ->AddEventListener(NS_LITERAL_STRING("blur"), this, PR_FALSE);
targ->AddEventListener(NS_LITERAL_STRING("DOMAutoComplete"), this, PR_FALSE);
}
}
@ -897,7 +903,7 @@ nsPasswordManager::Notify(nsIContent* aFormNode,
if (confirm && selection >= 0) {
changeEntry = entry;
for (PRInt32 m = 1; m < selection; ++m)
for (PRInt32 m = 0; m < selection; ++m)
changeEntry = changeEntry->next;
}
@ -942,98 +948,26 @@ nsPasswordManager::Notify(nsIContent* aFormNode,
return NS_OK;
}
// nsIDOMFormListener implementation
// nsIDOMFocusListener implementation
NS_IMETHODIMP
nsPasswordManager::Submit(nsIDOMEvent* aEvent)
{
// Note, form submission is not handled here (to do so would mean
// hooking up an event listener to each form as it's created).
// See ::Notify().
return NS_OK;
}
NS_IMETHODIMP
nsPasswordManager::Reset(nsIDOMEvent* aEvent)
nsPasswordManager::Focus(nsIDOMEvent* aEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsPasswordManager::Change(nsIDOMEvent* aEvent)
nsPasswordManager::Blur(nsIDOMEvent* aEvent)
{
// Try to prefill the password for the just-changed username.
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIDOMHTMLInputElement> userField = do_QueryInterface(target);
if (!userField)
return NS_OK;
nsCOMPtr<nsIContent> fieldContent = do_QueryInterface(userField);
nsIDocument* doc = fieldContent->GetDocument();
nsCOMPtr<nsIURI> documentURL;
doc->GetDocumentURL(getter_AddRefs(documentURL));
nsCAutoString realm;
documentURL->GetPrePath(realm);
nsAutoString userValue;
userField->GetValue(userValue);
nsAutoString fieldName;
userField->GetName(fieldName);
SignonHashEntry* hashEnt;
if (!mSignonTable.Get(realm, &hashEnt))
return NS_OK;
SignonDataEntry* foundEntry;
FindPasswordEntryInternal(hashEnt->head, userValue, nsString(),
fieldName, &foundEntry);
if (!foundEntry)
return NS_OK;
nsCOMPtr<nsIDOMHTMLFormElement> formEl;
userField->GetForm(getter_AddRefs(formEl));
if (!formEl)
return NS_OK;
nsCOMPtr<nsIForm> form = do_QueryInterface(formEl);
nsCOMPtr<nsISupports> foundNode;
form->ResolveName(foundEntry->passField, getter_AddRefs(foundNode));
nsCOMPtr<nsIDOMHTMLInputElement> passField = do_QueryInterface(foundNode);
if (!passField)
return NS_OK;
nsAutoString passValue;
DecryptData(foundEntry->passValue, passValue);
passField->SetValue(passValue);
return NS_OK;
}
NS_IMETHODIMP
nsPasswordManager::Select(nsIDOMEvent* aEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsPasswordManager::Input(nsIDOMEvent* aEvent)
{
return NS_OK;
return FillPassword(aEvent);
}
NS_IMETHODIMP
nsPasswordManager::HandleEvent(nsIDOMEvent* aEvent)
{
return NS_OK;
return FillPassword(aEvent);
}
// internal methods
/*
@ -1109,13 +1043,15 @@ nsPasswordManager::ReadSignonFile()
break;
case STATE_USERFIELD:
// Commit any completed entry
if (entry)
AddSignonData(realm, entry);
// If the line is a ., we've reached the end of this realm's entries.
if (buffer.Equals(NS_LITERAL_STRING("."))) {
if (entry) {
AddSignonData(realm, entry);
entry = nsnull;
state = STATE_REALM;
}
entry = nsnull;
state = STATE_REALM;
} else {
entry = new SignonDataEntry();
entry->userField.Assign(buffer);
@ -1375,6 +1311,65 @@ nsPasswordManager::FindPasswordEntryInternal(const SignonDataEntry* aEntry,
return NS_ERROR_FAILURE;
}
nsresult
nsPasswordManager::FillPassword(nsIDOMEvent* aEvent)
{
// Try to prefill the password for the just-changed username.
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIDOMHTMLInputElement> userField = do_QueryInterface(target);
if (!userField)
return NS_OK;
nsCOMPtr<nsIContent> fieldContent = do_QueryInterface(userField);
nsIDocument* doc = fieldContent->GetDocument();
nsCOMPtr<nsIURI> documentURL;
doc->GetDocumentURL(getter_AddRefs(documentURL));
nsCAutoString realm;
documentURL->GetPrePath(realm);
nsAutoString userValue;
userField->GetValue(userValue);
if (userValue.IsEmpty())
return NS_OK;
nsAutoString fieldName;
userField->GetName(fieldName);
SignonHashEntry* hashEnt;
if (!mSignonTable.Get(realm, &hashEnt))
return NS_OK;
SignonDataEntry* foundEntry;
FindPasswordEntryInternal(hashEnt->head, userValue, nsString(),
fieldName, &foundEntry);
if (!foundEntry)
return NS_OK;
nsCOMPtr<nsIDOMHTMLFormElement> formEl;
userField->GetForm(getter_AddRefs(formEl));
if (!formEl)
return NS_OK;
nsCOMPtr<nsIForm> form = do_QueryInterface(formEl);
nsCOMPtr<nsISupports> foundNode;
form->ResolveName(foundEntry->passField, getter_AddRefs(foundNode));
nsCOMPtr<nsIDOMHTMLInputElement> passField = do_QueryInterface(foundNode);
if (!passField)
return NS_OK;
nsAutoString passValue;
DecryptData(foundEntry->passValue, passValue);
passField->SetValue(passValue);
return NS_OK;
}
//////////////////////////////////////
// nsSingleSignonPrompt

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

@ -46,7 +46,7 @@
#include "nsIPrompt.h"
#include "nsIFormSubmitObserver.h"
#include "nsIWebProgressListener.h"
#include "nsIDOMFormListener.h"
#include "nsIDOMFocusListener.h"
/* 360565c4-2ef3-4f6a-bab9-94cca891b2a7 */
#define NS_PASSWORDMANAGER_CID \
@ -71,7 +71,7 @@ class nsPasswordManager : public nsIPasswordManager,
public nsIObserver,
public nsIFormSubmitObserver,
public nsIWebProgressListener,
public nsIDOMFormListener,
public nsIDOMFocusListener,
public nsSupportsWeakReference
{
public:
@ -118,12 +118,9 @@ public:
nsIURI* aActionURL,
PRBool* aCancelSubmit);
// nsIDOMFormListener
NS_IMETHOD Submit(nsIDOMEvent* aEvent);
NS_IMETHOD Reset(nsIDOMEvent* aEvent);
NS_IMETHOD Change(nsIDOMEvent* aEvent);
NS_IMETHOD Select(nsIDOMEvent* aEvent);
NS_IMETHOD Input(nsIDOMEvent* aEvent);
// nsIDOMFocusListener
NS_IMETHOD Focus(nsIDOMEvent* aEvent);
NS_IMETHOD Blur(nsIDOMEvent* aEvent);
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
@ -141,6 +138,8 @@ protected:
SignonDataEntry** aResult);
nsresult FillPassword(nsIDOMEvent* aEvent);
static PLDHashOperator PR_CALLBACK FindEntryEnumerator(const nsACString& aKey,
SignonHashEntry* aEntry,
void* aUserData);

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

@ -1,3 +1,40 @@
# ***** 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 the Mozilla Browser code.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 2003
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Brian Ryner <bryner@brianryner.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
# 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@

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

@ -62,6 +62,7 @@
#include "nsIFrame.h"
#include "nsIWidget.h"
#include "nsRect.h"
#include "nsIDOMDocumentEvent.h"
NS_INTERFACE_MAP_BEGIN(nsFormFillController)
NS_INTERFACE_MAP_ENTRY(nsIFormFillController)
@ -419,6 +420,25 @@ nsFormFillController::OnSearchComplete()
NS_IMETHODIMP
nsFormFillController::OnTextEntered(PRBool *_retval)
{
// Fire off a DOMAutoComplete event
nsCOMPtr<nsIDOMDocument> domDoc;
mFocusedInput->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDOMDocumentEvent> doc = do_QueryInterface(domDoc);
nsCOMPtr<nsIDOMEvent> event;
doc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
if (!event) {
NS_ERROR("Could not create DOM Event");
return NS_ERROR_FAILURE;
}
event->InitEvent(NS_LITERAL_STRING("DOMAutoComplete"), PR_TRUE, PR_TRUE);
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(mFocusedInput);
PRBool noDefault;
targ->DispatchEvent(event, &noDefault);
return NS_OK;
}