Bug 1388674 - Use document state to track generated password fields, not just the event handlers. r=MattN
Differential Revision:
https://phabricator.services.mozilla.com/D53055
--- a/toolkit/components/passwordmgr/LoginManagerChild.jsm
+++ b/toolkit/components/passwordmgr/LoginManagerChild.jsm
@@ -211,59 +211,72 @@ const observer = {
if (!aEvent.isTrusted) {
return;
}
if (!LoginHelper.enabled) {
return;
}
- let window = aEvent.target.ownerDocument.defaultView;
+ let ownerDocument = aEvent.target.ownerDocument;
+ let window = ownerDocument.defaultView;
+ let docState = LoginManagerChild.forWindow(window).stateForDocument(
+ ownerDocument
+ );
switch (aEvent.type) {
// Used to mask fields with filled generated passwords when blurred.
case "blur": {
- let unmask = false;
- LoginManagerChild.forWindow(window)._togglePasswordFieldMasking(
- aEvent.target,
- unmask
- );
+ if (docState.generatedPasswordFields.has(aEvent.target)) {
+ let unmask = false;
+ LoginManagerChild.forWindow(window)._togglePasswordFieldMasking(
+ aEvent.target,
+ unmask
+ );
+ }
break;
}
// Used to watch for changes to fields filled with generated passwords.
case "change": {
- LoginManagerChild.forWindow(window)._generatedPasswordFilledOrEdited(
- aEvent.target
- );
+ if (docState.generatedPasswordFields.has(aEvent.target)) {
+ LoginManagerChild.forWindow(window)._generatedPasswordFilledOrEdited(
+ aEvent.target
+ );
+ }
break;
}
// Used to watch for changes to fields filled with generated passwords.
case "input": {
- LoginManagerChild.forWindow(
- window
- )._maybeStopTreatingAsGeneratedPasswordField(aEvent);
+ if (docState.generatedPasswordFields.has(aEvent.target)) {
+ LoginManagerChild.forWindow(
+ window
+ )._maybeStopTreatingAsGeneratedPasswordField(aEvent);
+ }
break;
}
case "keydown": {
if (
aEvent.keyCode == aEvent.DOM_VK_TAB ||
aEvent.keyCode == aEvent.DOM_VK_RETURN
) {
LoginManagerChild.forWindow(window).onUsernameAutocompleted(
aEvent.target
);
}
break;
}
case "focus": {
- if (aEvent.target.type == "password") {
+ if (
+ aEvent.target.type == "password" &&
+ docState.generatedPasswordFields.has(aEvent.target)
+ ) {
// Used to unmask fields with filled generated passwords when focused.
let unmask = true;
LoginManagerChild.forWindow(window)._togglePasswordFieldMasking(
aEvent.target,
unmask
);
break;
}
@@ -870,16 +883,20 @@ this.LoginManagerChild = class LoginMana
let loginFormState = this._loginFormStateByDocument.get(document);
if (!loginFormState) {
loginFormState = {
/**
* Keeps track of filled fields and values.
*/
fillsByRootElement: new WeakMap(),
/**
+ * Keeps track of fields we've filled with generated passwords
+ */
+ generatedPasswordFields: new WeakSet(),
+ /**
* Keeps track of logins that were last submitted.
*/
lastSubmittedValuesByRootElement: new WeakMap(),
loginFormRootElements: new WeakSet(),
};
this._loginFormStateByDocument.set(document, loginFormState);
}
return loginFormState;
@@ -1570,16 +1587,20 @@ this.LoginManagerChild = class LoginMana
if (!value || (event.data && event.data == value)) {
this._stopTreatingAsGeneratedPasswordField(passwordField);
}
}
_stopTreatingAsGeneratedPasswordField(passwordField) {
log("_stopTreatingAsGeneratedPasswordField");
+ let fields = this.stateForDocument(passwordField.ownerDocument)
+ .generatedPasswordFields;
+ fields.delete(passwordField);
+
// Remove all the event listeners added in _generatedPasswordFilledOrEdited
for (let eventType of ["blur", "change", "focus", "input"]) {
passwordField.removeEventListener(eventType, observer, {
capture: true,
mozSystemGroup: true,
});
}
@@ -1598,16 +1619,18 @@ this.LoginManagerChild = class LoginMana
if (!LoginHelper.enabled) {
throw new Error(
"A generated password was filled while the password manager was disabled."
);
}
let win = passwordField.ownerGlobal;
let formLikeRoot = FormLikeFactory.findRootForField(passwordField);
+ let docState = this.stateForDocument(passwordField.ownerDocument);
+ docState.generatedPasswordFields.add(passwordField);
this._highlightFilledField(passwordField);
// change: Listen for changes to the field filled with the generated password so we can preserve edits.
// input: Listen for the field getting blanked (without blurring) or a paste
for (let eventType of ["blur", "change", "focus", "input"]) {
passwordField.addEventListener(eventType, observer, {
capture: true,