зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1641412 - Pass all possible UNs/PWs to doorhanger;r=MattN,sfoster
Differential Revision: https://phabricator.services.mozilla.com/D77190
This commit is contained in:
Родитель
15284e839e
Коммит
c26d4965f3
|
@ -3751,6 +3751,7 @@ pref("signon.autofillForms", true);
|
|||
pref("signon.autofillForms.autocompleteOff", true);
|
||||
pref("signon.autofillForms.http", false);
|
||||
pref("signon.autologin.proxy", false);
|
||||
pref("signon.capture.inputChanges.enabled", true);
|
||||
pref("signon.formlessCapture.enabled", true);
|
||||
pref("signon.generation.available", true);
|
||||
// A value of "-1" disables new-password heuristics. Can be updated once Bug 1618058 is resolved.
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
const EXPORTED_SYMBOLS = ["LoginManagerChild"];
|
||||
|
||||
const PASSWORD_INPUT_ADDED_COALESCING_THRESHOLD_MS = 1;
|
||||
// The amount of time a context menu event supresses showing a
|
||||
// popup from a focus event in ms. This matches the threshold in
|
||||
// toolkit/components/satchel/nsFormFillController.cpp
|
||||
const AUTOCOMPLETE_AFTER_RIGHT_CLICK_THRESHOLD_MS = 400;
|
||||
const AUTOFILL_STATE = "-moz-autofill";
|
||||
|
||||
|
@ -236,6 +239,9 @@ const observer = {
|
|||
log("Ignoring change event on form that hasn't been user-modified");
|
||||
break;
|
||||
}
|
||||
|
||||
this._storeUserInput(docState, aEvent.target);
|
||||
|
||||
if (aEvent.target.hasBeenTypePassword) {
|
||||
let triggeredByFillingGenerated = docState.generatedPasswordFields.has(
|
||||
aEvent.target
|
||||
|
@ -392,6 +398,20 @@ const observer = {
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
_storeUserInput(docState, field) {
|
||||
if (
|
||||
!Services.prefs.getBoolPref("signon.capture.inputChanges.enabled", false)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (LoginHelper.isPasswordFieldType(field)) {
|
||||
docState.possiblePasswords.add(field.value);
|
||||
} else if (LoginHelper.isUsernameFieldType(field)) {
|
||||
docState.possibleUsernames.add(field.value);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Add this observer once for the process.
|
||||
|
@ -906,6 +926,14 @@ this.LoginManagerChild = class LoginManagerChild extends JSWindowActorChild {
|
|||
lastSubmittedValuesByRootElement: new WeakMap(),
|
||||
fieldModificationsByRootElement: new WeakMap(),
|
||||
loginFormRootElements: new WeakSet(),
|
||||
/**
|
||||
* Anything entered into an <input> that we think might be a username
|
||||
*/
|
||||
possibleUsernames: new Set(),
|
||||
/**
|
||||
* Anything entered into an <input> that we think might be a password
|
||||
*/
|
||||
possiblePasswords: new Set(),
|
||||
};
|
||||
this._loginFormStateByDocument.set(document, loginFormState);
|
||||
}
|
||||
|
@ -1702,6 +1730,10 @@ this.LoginManagerChild = class LoginManagerChild extends JSWindowActorChild {
|
|||
oldPasswordField: mockOldPassword,
|
||||
dismissedPrompt,
|
||||
triggeredByFillingGenerated,
|
||||
possibleValues: {
|
||||
usernames: docState.possibleUsernames,
|
||||
passwords: docState.possiblePasswords,
|
||||
},
|
||||
messageSent: true,
|
||||
};
|
||||
|
||||
|
|
|
@ -678,6 +678,7 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
newPasswordField,
|
||||
oldPasswordField,
|
||||
dismissedPrompt,
|
||||
possibleValues,
|
||||
}
|
||||
) {
|
||||
function recordLoginUse(login) {
|
||||
|
@ -841,7 +842,8 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
dismissedPrompt,
|
||||
notifySaved,
|
||||
autoSavedStorageGUID,
|
||||
autoFilledLoginGuid
|
||||
autoFilledLoginGuid,
|
||||
possibleValues
|
||||
);
|
||||
} else if (!existingLogin.username && formLogin.username) {
|
||||
log("...empty username update, prompting to change.");
|
||||
|
@ -853,7 +855,8 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
dismissedPrompt,
|
||||
notifySaved,
|
||||
autoSavedStorageGUID,
|
||||
autoFilledLoginGuid
|
||||
autoFilledLoginGuid,
|
||||
possibleValues
|
||||
);
|
||||
} else {
|
||||
recordLoginUse(existingLogin);
|
||||
|
@ -868,7 +871,8 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
formLogin,
|
||||
dismissedPrompt,
|
||||
notifySaved,
|
||||
autoFilledLoginGuid
|
||||
autoFilledLoginGuid,
|
||||
possibleValues
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -890,6 +894,8 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
* @param {Object?} options.usernameField
|
||||
* @param {Element?} options.oldPasswordField
|
||||
* @param {boolean} [options.triggeredByFillingGenerated = false]
|
||||
* @param {Set<String>} possibleValues.usernames
|
||||
* @param {Set<String>} possibleValues.passwords
|
||||
*/
|
||||
async _onPasswordEditedOrGenerated(
|
||||
browser,
|
||||
|
@ -901,6 +907,10 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
usernameField = null,
|
||||
oldPasswordField,
|
||||
triggeredByFillingGenerated = false,
|
||||
possibleValues = {
|
||||
usernames: new Set(),
|
||||
passwords: new Set(),
|
||||
},
|
||||
}
|
||||
) {
|
||||
log(
|
||||
|
@ -1208,7 +1218,8 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
true, // dismissed prompt
|
||||
notifySaved,
|
||||
autoSavedStorageGUID, // autoSavedLoginGuid
|
||||
autoFilledLoginGuid
|
||||
autoFilledLoginGuid,
|
||||
possibleValues
|
||||
);
|
||||
} else if (!existingLogin.username && formLogin.username) {
|
||||
log("...empty username update, prompting to change.");
|
||||
|
@ -1219,7 +1230,8 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
true, // dismissed prompt
|
||||
notifySaved,
|
||||
autoSavedStorageGUID, // autoSavedLoginGuid
|
||||
autoFilledLoginGuid
|
||||
autoFilledLoginGuid,
|
||||
possibleValues
|
||||
);
|
||||
} else {
|
||||
log("_onPasswordEditedOrGenerated: No change to existing login");
|
||||
|
@ -1238,7 +1250,8 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
true, // dismissed prompt
|
||||
notifySaved,
|
||||
autoSavedStorageGUID, // autoSavedLoginGuid
|
||||
autoFilledLoginGuid
|
||||
autoFilledLoginGuid,
|
||||
possibleValues
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1250,7 +1263,8 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
formLogin,
|
||||
true, // dismissed prompt
|
||||
notifySaved,
|
||||
autoFilledLoginGuid
|
||||
autoFilledLoginGuid,
|
||||
possibleValues
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,11 @@ class LoginManagerPrompter {
|
|||
aLogin,
|
||||
dismissed = false,
|
||||
notifySaved = false,
|
||||
autoFilledLoginGuid = ""
|
||||
autoFilledLoginGuid = "",
|
||||
possibleValues = {
|
||||
usernames: new Set(),
|
||||
passwords: new Set(),
|
||||
}
|
||||
) {
|
||||
log.debug("promptToSavePassword");
|
||||
let inPrivateBrowsing = PrivateBrowsingUtils.isBrowserPrivate(aBrowser);
|
||||
|
@ -501,6 +505,116 @@ class LoginManagerPrompter {
|
|||
showOptions.dismissed && showOptions.extraAttr == "attention"
|
||||
? ATTENTION_NOTIFICATION_TIMEOUT_MS
|
||||
: NOTIFICATION_TIMEOUT_MS;
|
||||
|
||||
let options = Object.assign(
|
||||
{
|
||||
timeout: Date.now() + timeoutMs,
|
||||
persistWhileVisible: true,
|
||||
passwordNotificationType: type,
|
||||
hideClose: true,
|
||||
eventCallback(topic) {
|
||||
switch (topic) {
|
||||
case "showing":
|
||||
log.debug("showing");
|
||||
currentNotification = this;
|
||||
|
||||
// Record the first time this instance of the doorhanger is shown.
|
||||
if (!this.timeShown) {
|
||||
histogram.add(PROMPT_DISPLAYED);
|
||||
Services.obs.notifyObservers(
|
||||
null,
|
||||
"weave:telemetry:histogram",
|
||||
histogramName
|
||||
);
|
||||
}
|
||||
|
||||
chromeDoc
|
||||
.getElementById("password-notification-password")
|
||||
.removeAttribute("focused");
|
||||
chromeDoc
|
||||
.getElementById("password-notification-username")
|
||||
.removeAttribute("focused");
|
||||
chromeDoc
|
||||
.getElementById("password-notification-username")
|
||||
.addEventListener("input", onInput);
|
||||
chromeDoc
|
||||
.getElementById("password-notification-username")
|
||||
.addEventListener("keyup", onKeyUp);
|
||||
chromeDoc
|
||||
.getElementById("password-notification-password")
|
||||
.addEventListener("keyup", onKeyUp);
|
||||
chromeDoc
|
||||
.getElementById("password-notification-password")
|
||||
.addEventListener("input", onInput);
|
||||
let toggleBtn = chromeDoc.getElementById(
|
||||
"password-notification-visibilityToggle"
|
||||
);
|
||||
|
||||
if (
|
||||
Services.prefs.getBoolPref(
|
||||
"signon.rememberSignons.visibilityToggle"
|
||||
)
|
||||
) {
|
||||
toggleBtn.addEventListener("command", onVisibilityToggle);
|
||||
toggleBtn.setAttribute("label", togglePasswordLabel);
|
||||
toggleBtn.setAttribute("accesskey", togglePasswordAccessKey);
|
||||
|
||||
let hideToggle =
|
||||
LoginHelper.isMasterPasswordSet() ||
|
||||
// Don't show the toggle when the login was autofilled
|
||||
!!autoFilledLoginGuid ||
|
||||
// Dismissed-by-default prompts should still show the toggle.
|
||||
(this.timeShown && this.wasDismissed) ||
|
||||
// If we are only adding a username then the password is
|
||||
// one that is already saved and we don't want to reveal
|
||||
// it as the submitter of this form may not be the account
|
||||
// owner, they may just be using the saved password.
|
||||
(messageStringID == "updateLoginMsgAddUsername" &&
|
||||
login.timePasswordChanged <
|
||||
Date.now() - VISIBILITY_TOGGLE_MAX_PW_AGE_MS);
|
||||
toggleBtn.setAttribute("hidden", hideToggle);
|
||||
}
|
||||
break;
|
||||
case "shown": {
|
||||
log.debug("shown");
|
||||
writeDataToUI();
|
||||
let anchorIcon = this.anchorElement;
|
||||
if (anchorIcon && this.options.extraAttr == "attention") {
|
||||
anchorIcon.removeAttribute("extraAttr");
|
||||
delete this.options.extraAttr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "dismissed":
|
||||
// Note that this can run after `showing` but before `shown` upon tab switch.
|
||||
this.wasDismissed = true;
|
||||
// Fall through.
|
||||
case "removed": {
|
||||
// Note that this can run after `showing` and `shown` for the
|
||||
// notification it's replacing.
|
||||
log.debug(topic);
|
||||
currentNotification = null;
|
||||
|
||||
let usernameField = chromeDoc.getElementById(
|
||||
"password-notification-username"
|
||||
);
|
||||
usernameField.removeEventListener("input", onInput);
|
||||
usernameField.removeEventListener("keyup", onKeyUp);
|
||||
let passwordField = chromeDoc.getElementById(
|
||||
"password-notification-password"
|
||||
);
|
||||
passwordField.removeEventListener("input", onInput);
|
||||
passwordField.removeEventListener("keyup", onKeyUp);
|
||||
passwordField.removeEventListener("command", onVisibilityToggle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
showOptions
|
||||
);
|
||||
|
||||
let notification = PopupNotifications.show(
|
||||
browser,
|
||||
notificationID,
|
||||
|
@ -508,117 +622,7 @@ class LoginManagerPrompter {
|
|||
"password-notification-icon",
|
||||
mainAction,
|
||||
secondaryActions,
|
||||
Object.assign(
|
||||
{
|
||||
timeout: Date.now() + timeoutMs,
|
||||
persistWhileVisible: true,
|
||||
passwordNotificationType: type,
|
||||
hideClose: true,
|
||||
eventCallback(topic) {
|
||||
switch (topic) {
|
||||
case "showing":
|
||||
log.debug("showing");
|
||||
currentNotification = this;
|
||||
|
||||
// Record the first time this instance of the doorhanger is shown.
|
||||
if (!this.timeShown) {
|
||||
histogram.add(PROMPT_DISPLAYED);
|
||||
Services.obs.notifyObservers(
|
||||
null,
|
||||
"weave:telemetry:histogram",
|
||||
histogramName
|
||||
);
|
||||
}
|
||||
|
||||
chromeDoc
|
||||
.getElementById("password-notification-password")
|
||||
.removeAttribute("focused");
|
||||
chromeDoc
|
||||
.getElementById("password-notification-username")
|
||||
.removeAttribute("focused");
|
||||
chromeDoc
|
||||
.getElementById("password-notification-username")
|
||||
.addEventListener("input", onInput);
|
||||
chromeDoc
|
||||
.getElementById("password-notification-username")
|
||||
.addEventListener("keyup", onKeyUp);
|
||||
chromeDoc
|
||||
.getElementById("password-notification-password")
|
||||
.addEventListener("keyup", onKeyUp);
|
||||
chromeDoc
|
||||
.getElementById("password-notification-password")
|
||||
.addEventListener("input", onInput);
|
||||
let toggleBtn = chromeDoc.getElementById(
|
||||
"password-notification-visibilityToggle"
|
||||
);
|
||||
|
||||
if (
|
||||
Services.prefs.getBoolPref(
|
||||
"signon.rememberSignons.visibilityToggle"
|
||||
)
|
||||
) {
|
||||
toggleBtn.addEventListener("command", onVisibilityToggle);
|
||||
toggleBtn.setAttribute("label", togglePasswordLabel);
|
||||
toggleBtn.setAttribute("accesskey", togglePasswordAccessKey);
|
||||
|
||||
let hideToggle =
|
||||
LoginHelper.isMasterPasswordSet() ||
|
||||
// Don't show the toggle when the login was autofilled
|
||||
!!autoFilledLoginGuid ||
|
||||
// Dismissed-by-default prompts should still show the toggle.
|
||||
(this.timeShown && this.wasDismissed) ||
|
||||
// If we are only adding a username then the password is
|
||||
// one that is already saved and we don't want to reveal
|
||||
// it as the submitter of this form may not be the account
|
||||
// owner, they may just be using the saved password.
|
||||
(messageStringID == "updateLoginMsgAddUsername" &&
|
||||
login.timePasswordChanged <
|
||||
Date.now() - VISIBILITY_TOGGLE_MAX_PW_AGE_MS);
|
||||
toggleBtn.setAttribute("hidden", hideToggle);
|
||||
}
|
||||
break;
|
||||
case "shown": {
|
||||
log.debug("shown");
|
||||
writeDataToUI();
|
||||
let anchorIcon = this.anchorElement;
|
||||
if (anchorIcon && this.options.extraAttr == "attention") {
|
||||
anchorIcon.removeAttribute("extraAttr");
|
||||
delete this.options.extraAttr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "dismissed":
|
||||
// Note that this can run after `showing` but before `shown` upon tab switch.
|
||||
this.wasDismissed = true;
|
||||
// Fall through.
|
||||
case "removed": {
|
||||
// Note that this can run after `showing` and `shown` for the
|
||||
// notification it's replacing.
|
||||
log.debug(topic);
|
||||
currentNotification = null;
|
||||
|
||||
let usernameField = chromeDoc.getElementById(
|
||||
"password-notification-username"
|
||||
);
|
||||
usernameField.removeEventListener("input", onInput);
|
||||
usernameField.removeEventListener("keyup", onKeyUp);
|
||||
let passwordField = chromeDoc.getElementById(
|
||||
"password-notification-password"
|
||||
);
|
||||
passwordField.removeEventListener("input", onInput);
|
||||
passwordField.removeEventListener("keyup", onKeyUp);
|
||||
passwordField.removeEventListener(
|
||||
"command",
|
||||
onVisibilityToggle
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
showOptions
|
||||
)
|
||||
options
|
||||
);
|
||||
|
||||
if (notifySaved) {
|
||||
|
@ -646,6 +650,11 @@ class LoginManagerPrompter {
|
|||
* @param {string} [autoSavedLoginGuid = ""]
|
||||
* A guid value for the old login to be removed if the changes match it
|
||||
* to a different login
|
||||
* @param {object} possibleValues
|
||||
* Contains values from anything that we think, but are not sure, might be
|
||||
* a username or password. Has two properties, 'usernames' and 'passwords'.
|
||||
* @param {Set<String>} possibleValues.usernames
|
||||
* @param {Set<String>} possibleValues.passwords
|
||||
*/
|
||||
promptToChangePassword(
|
||||
aBrowser,
|
||||
|
@ -654,7 +663,11 @@ class LoginManagerPrompter {
|
|||
dismissed = false,
|
||||
notifySaved = false,
|
||||
autoSavedLoginGuid = "",
|
||||
autoFilledLoginGuid = ""
|
||||
autoFilledLoginGuid = "",
|
||||
possibleValues = {
|
||||
usernames: new Set(),
|
||||
passwords: new Set(),
|
||||
}
|
||||
) {
|
||||
let login = aOldLogin.clone();
|
||||
login.origin = aNewLogin.origin;
|
||||
|
|
|
@ -28,12 +28,16 @@ interface nsILoginManagerPrompter : nsISupports {
|
|||
* a login has been saved
|
||||
* @param autoFilledLoginGuid
|
||||
* A string guid value for the login which was autofilled into the form
|
||||
* @param possibleValues
|
||||
* Contains values from anything that we think, but are not sure, might be
|
||||
* a username or password. Has two properties, 'usernames' and 'passwords'.
|
||||
*/
|
||||
void promptToSavePassword(in Element aBrowser,
|
||||
in nsILoginInfo aLogin,
|
||||
[optional] in boolean dismissed,
|
||||
[optional] in boolean notifySaved,
|
||||
[optional] in AString autoFilledLoginGuid);
|
||||
[optional] in AString autoFilledLoginGuid,
|
||||
[optional] in jsval possibleValues);
|
||||
|
||||
/**
|
||||
* Ask the user if they want to change a login's password or username.
|
||||
|
@ -53,6 +57,9 @@ interface nsILoginManagerPrompter : nsISupports {
|
|||
* match it to a different login
|
||||
* @param autoFilledLoginGuid
|
||||
* A string guid value for the login which was autofilled into the form
|
||||
* @param possibleValues
|
||||
* Contains values from anything that we think, but are not sure, might be
|
||||
* a username or password. Has two properties, 'usernames' and 'passwords'.
|
||||
*/
|
||||
void promptToChangePassword(in Element aBrowser,
|
||||
in nsILoginInfo aOldLogin,
|
||||
|
@ -60,7 +67,8 @@ interface nsILoginManagerPrompter : nsISupports {
|
|||
[optional] in boolean dismissed,
|
||||
[optional] in boolean notifySaved,
|
||||
[optional] in AString autoSavedLoginGuid,
|
||||
[optional] in AString autoFilledLoginGuid);
|
||||
[optional] in AString autoFilledLoginGuid,
|
||||
[optional] in jsval possibleValues);
|
||||
|
||||
/**
|
||||
* Ask the user if they want to change the password for one of
|
||||
|
|
Загрузка…
Ссылка в новой задаче