Skip to content

Commit

Permalink
Bug 771331 - make form elements fire events when <input type=password…
Browse files Browse the repository at this point in the history
…> elements are added/removed; r=smaug
  • Loading branch information
froydnj committed Jan 31, 2013
1 parent 6572a66 commit 414a18b
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 6 deletions.
1 change: 1 addition & 0 deletions browser/base/content/test/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ _BROWSER_FILES = \
browser_bug749738.js \
browser_bug763468_perwindowpb.js \
browser_bug767836_perwindowpb.js \
browser_bug771331.js \
browser_bug783614.js \
browser_bug797677.js \
browser_bug816527.js \
Expand Down
82 changes: 82 additions & 0 deletions browser/base/content/test/browser_bug771331.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const HTML_NS = "http://www.w3.org/1999/xhtml";

const INPUT_ID = "input1";
const FORM1_ID = "form1";
const FORM2_ID = "form2";
const CHANGE_INPUT_ID = "input2";

function test() {
waitForExplicitFinish();
let tab = gBrowser.selectedTab =
gBrowser.addTab("data:text/html;charset=utf-8," +
"<html><body>" +
"<form id='" + FORM1_ID + "'><input id='" + CHANGE_INPUT_ID + "'></form>" +
"<form id='" + FORM2_ID + "'></form>" +
"</body></html>");
tab.linkedBrowser.addEventListener("load", tabLoad, true);
}

function unexpectedContentEvent(evt) {
ok(false, "Received a " + evt.type + " event on content");
}

var gDoc = null;

function tabLoad() {
let tab = gBrowser.selectedTab;
tab.linkedBrowser.removeEventListener("load", tabLoad, true);
gDoc = gBrowser.selectedBrowser.contentDocument;
// These events shouldn't escape to content.
gDoc.addEventListener("DOMFormHasPassword", unexpectedContentEvent, false);
gDoc.defaultView.setTimeout(test_inputAdd, 0);
}

function test_inputAdd() {
gBrowser.addEventListener("DOMFormHasPassword", test_inputAddHandler, false);
let input = gDoc.createElementNS(HTML_NS, "input");
input.setAttribute("type", "password");
input.setAttribute("id", INPUT_ID);
input.setAttribute("data-test", "unique-attribute");
gDoc.getElementById(FORM1_ID).appendChild(input);
info("Done appending the input element");
}

function test_inputAddHandler(evt) {
gBrowser.removeEventListener(evt.type, test_inputAddHandler, false);
is(evt.target.id, FORM1_ID,
evt.type + " event targets correct form element (added password element)");
gDoc.defaultView.setTimeout(test_inputChangeForm, 0);
}

function test_inputChangeForm() {
gBrowser.addEventListener("DOMFormHasPassword", test_inputChangeFormHandler, false);
let input = gDoc.getElementById(INPUT_ID);
input.setAttribute("form", FORM2_ID);
}

function test_inputChangeFormHandler(evt) {
gBrowser.removeEventListener(evt.type, test_inputChangeFormHandler, false);
is(evt.target.id, FORM2_ID,
evt.type + " event targets correct form element (changed form)");
gDoc.defaultView.setTimeout(test_inputChangesType, 0);
}

function test_inputChangesType() {
gBrowser.addEventListener("DOMFormHasPassword", test_inputChangesTypeHandler, false);
let input = gDoc.getElementById(CHANGE_INPUT_ID);
input.setAttribute("type", "password");
}

function test_inputChangesTypeHandler(evt) {
gBrowser.removeEventListener(evt.type, test_inputChangesTypeHandler, false);
is(evt.target.id, FORM1_ID,
evt.type + " event targets correct form element (changed type)");
gDoc.defaultView.setTimeout(completeTest, 0);
}

function completeTest() {
ok(true, "Test completed");
gDoc.removeEventListener("DOMFormHasPassword", unexpectedContentEvent, false);
gBrowser.removeCurrentTab();
finish();
}
28 changes: 22 additions & 6 deletions content/html/content/src/nsHTMLFormElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,20 @@ AssertDocumentOrder(const nsTArray<nsGenericHTMLFormElement*>& aControls,
}
#endif

void
nsHTMLFormElement::PostPasswordEvent()
{
// Don't fire another add event if we have a pending add event.
if (mFormPasswordEvent.get()) {
return;
}

nsRefPtr<FormPasswordEvent> event =
new FormPasswordEvent(this, NS_LITERAL_STRING("DOMFormHasPassword"));
mFormPasswordEvent = event;
event->PostDOMEvent();
}

nsresult
nsHTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
bool aUpdateValidity, bool aNotify)
Expand Down Expand Up @@ -1157,12 +1171,14 @@ nsHTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
// If it is a password control, and the password manager has not yet been
// initialized, initialize the password manager
//
if (!gPasswordManagerInitialized && type == NS_FORM_INPUT_PASSWORD) {
// Initialize the password manager category
gPasswordManagerInitialized = true;
NS_CreateServicesFromCategory(NS_PASSWORDMANAGER_CATEGORY,
nullptr,
NS_PASSWORDMANAGER_CATEGORY);
if (type == NS_FORM_INPUT_PASSWORD) {
if (!gPasswordManagerInitialized) {
gPasswordManagerInitialized = true;
NS_CreateServicesFromCategory(NS_PASSWORDMANAGER_CATEGORY,
nullptr,
NS_PASSWORDMANAGER_CATEGORY);
}
PostPasswordEvent();
}

// Default submit element handling
Expand Down
21 changes: 21 additions & 0 deletions content/html/content/src/nsHTMLFormElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "nsThreadUtils.h"
#include "nsInterfaceHashtable.h"
#include "nsDataHashtable.h"
#include "nsAsyncDOMEvent.h"

class nsFormControlList;
class nsIMutableArray;
Expand Down Expand Up @@ -240,6 +241,26 @@ class nsHTMLFormElement : public nsGenericHTMLElement,
bool HasEverTriedInvalidSubmit() const { return mEverTriedInvalidSubmit; }

protected:
void PostPasswordEvent();
void EventHandled() { mFormPasswordEvent = nullptr; }

class FormPasswordEvent : public nsAsyncDOMEvent
{
public:
FormPasswordEvent(nsHTMLFormElement* aEventNode,
const nsAString& aEventType)
: nsAsyncDOMEvent(aEventNode, aEventType, true, true)
{}

NS_IMETHOD Run()
{
static_cast<nsHTMLFormElement*>(mEventNode.get())->EventHandled();
return nsAsyncDOMEvent::Run();
}
};

nsRefPtr<FormPasswordEvent> mFormPasswordEvent;

class RemoveElementRunnable;
friend class RemoveElementRunnable;

Expand Down

0 comments on commit 414a18b

Please sign in to comment.