Bug 1567175, make LoginManagerContent and LoginManagerParent JS classes,r=MattN

Differential Revision: https://phabricator.services.mozilla.com/D47823

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Neil Deakin 2019-10-21 18:17:43 +00:00
Родитель c5df88ff8f
Коммит 3302428083
22 изменённых файлов: 343 добавлений и 271 удалений

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

@ -561,9 +561,9 @@ class ContextMenuChild extends JSWindowActorChild {
} = doc;
docLocation = docLocation && docLocation.spec;
let frameOuterWindowID = WebNavigationFrames.getFrameId(doc.defaultView);
let loginFillInfo = LoginManagerContent.getFieldContext(
aEvent.composedTarget
);
let loginFillInfo = LoginManagerContent.forWindow(
doc.defaultView
).getFieldContext(aEvent.composedTarget);
// The same-origin check will be done in nsContextMenu.openLinkInTab.
let parentAllowsMixedContent = !!this.docShell.mixedContentChannel;

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

@ -45,13 +45,13 @@ addEventListener("DOMFormBeforeSubmit", function(event) {
if (shouldIgnoreLoginManagerEvent(event)) {
return;
}
LoginManagerContent.onDOMFormBeforeSubmit(event);
this.LoginManagerContent.forWindow(content).onDOMFormBeforeSubmit(event);
});
addEventListener("DOMFormHasPassword", function(event) {
if (shouldIgnoreLoginManagerEvent(event)) {
return;
}
LoginManagerContent.onDOMFormHasPassword(event);
this.LoginManagerContent.forWindow(content).onDOMFormHasPassword(event);
let formLike = LoginFormFactory.createFromForm(event.originalTarget);
InsecurePasswordUtils.reportInsecurePasswords(formLike);
});
@ -59,7 +59,10 @@ addEventListener("DOMInputPasswordAdded", function(event) {
if (shouldIgnoreLoginManagerEvent(event)) {
return;
}
LoginManagerContent.onDOMInputPasswordAdded(event, content);
this.LoginManagerContent.forWindow(content).onDOMInputPasswordAdded(
event,
content
);
let formLike = LoginFormFactory.createFromField(event.originalTarget);
InsecurePasswordUtils.reportInsecurePasswords(formLike);
});

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

@ -228,7 +228,7 @@ BrowserCLH.prototype = {
if (shouldIgnoreLoginManagerEvent(event)) {
return;
}
this.LoginManagerContent.onDOMFormBeforeSubmit(event);
this.LoginManagerContent.forWindow(aWindow).onDOMFormBeforeSubmit(event);
});
aWindow.addEventListener(
"DOMFormHasPassword",
@ -236,7 +236,7 @@ BrowserCLH.prototype = {
if (shouldIgnoreLoginManagerEvent(event)) {
return;
}
this.LoginManagerContent.onDOMFormHasPassword(event);
this.LoginManagerContent.forWindow(aWindow).onDOMFormHasPassword(event);
},
options
);
@ -247,7 +247,7 @@ BrowserCLH.prototype = {
if (shouldIgnoreLoginManagerEvent(event)) {
return;
}
this.LoginManagerContent.onDOMInputPasswordAdded(
this.LoginManagerContent.forWindow(aWindow).onDOMInputPasswordAdded(
event,
event.target.ownerGlobal.top
);
@ -260,7 +260,7 @@ BrowserCLH.prototype = {
event => {
// XXXbz what about non-HTML documents??
if (ChromeUtils.getClassName(event.target) == "HTMLDocument") {
this.LoginManagerContent.onPageShow(event);
this.LoginManagerContent.forWindow(aWindow).onPageShow(event);
}
},
options

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

@ -152,9 +152,9 @@ class GeckoViewAutofill {
}
}
const [usernameField] = LoginManagerContent.getUserNameAndPasswordFields(
passwordField || aFormLike.elements[0]
);
const [usernameField] = LoginManagerContent.forWindow(
window
).getUserNameAndPasswordFields(passwordField || aFormLike.elements[0]);
const rootInfo = getInfo(aFormLike.rootElement, null, undefined, null);
rootInfo.root = rootInfo.id;

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

@ -505,7 +505,8 @@ LoginAutoComplete.prototype = {
previousResult = null;
}
let acLookupPromise = (this._autoCompleteLookupPromise = LoginManagerContent._autoCompleteSearchAsync(
let loginManager = LoginManagerContent.forWindow(aElement.ownerGlobal);
let acLookupPromise = (this._autoCompleteLookupPromise = loginManager._autoCompleteSearchAsync(
aSearchString,
previousResult,
aElement

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

@ -74,9 +74,9 @@ ChromeUtils.defineModuleGetter(
XPCOMUtils.defineLazyServiceGetter(
this,
"gNetUtil",
"@mozilla.org/network/util;1",
"nsINetUtil"
"gFormFillService",
"@mozilla.org/satchel/form-fill-controller;1",
"nsIFormFillController"
);
XPCOMUtils.defineLazyGetter(this, "log", () => {
@ -88,6 +88,13 @@ Services.cpmm.addMessageListener("clearRecipeCache", () => {
LoginRecipesContent._clearRecipeCache();
});
let gLoginManagerContentSingleton = null;
let _messages = [
"PasswordManager:loginsFound",
"PasswordManager:loginsAutoCompleted",
];
let gLastRightClickTimeStamp = Number.NEGATIVE_INFINITY;
const observer = {
@ -113,7 +120,9 @@ const observer = {
aWebProgress.DOMWindow.document
);
LoginManagerContent._onNavigation(aWebProgress.DOMWindow.document);
LoginManagerContent.forWindow(aWebProgress.DOMWindow)._onNavigation(
aWebProgress.DOMWindow.document
);
},
onStateChange(aWebProgress, aRequest, aState, aStatus) {
@ -123,7 +132,9 @@ const observer = {
) {
// Re-fill a document restored from bfcache since password field values
// aren't persisted there.
LoginManagerContent._onDocumentRestored(aWebProgress.DOMWindow.document);
LoginManagerContent.forWindow(aWebProgress.DOMWindow)._onDocumentRestored(
aWebProgress.DOMWindow.document
);
return;
}
@ -156,7 +167,9 @@ const observer = {
}
log("onStateChange handled:", channel);
LoginManagerContent._onNavigation(aWebProgress.DOMWindow.document);
LoginManagerContent.forWindow(aWebProgress.DOMWindow)._onNavigation(
aWebProgress.DOMWindow.document
);
},
// nsIObserver
@ -169,22 +182,25 @@ const observer = {
break;
}
let { focusedInput } = LoginManagerContent._formFillService;
let { focusedInput } = gFormFillService;
if (focusedInput.nodePrincipal.isNullPrincipal) {
// If we have a null principal then prevent any more password manager code from running and
// incorrectly using the document `location`.
return;
}
let window = focusedInput.ownerGlobal;
let loginManagerContent = LoginManagerContent.forWindow(window);
let style = input.controller.getStyleAt(selectedIndex);
if (style == "login" || style == "loginWithOrigin") {
let details = JSON.parse(
input.controller.getCommentAt(selectedIndex)
);
LoginManagerContent.onFieldAutoComplete(focusedInput, details.guid);
loginManagerContent.onFieldAutoComplete(focusedInput, details.guid);
} else if (style == "generatedPassword") {
LoginManagerContent._highlightFilledField(focusedInput);
LoginManagerContent._generatedPasswordFilledOrEdited(focusedInput);
loginManagerContent._highlightFilledField(focusedInput);
loginManagerContent._generatedPasswordFilledOrEdited(focusedInput);
}
break;
}
@ -201,23 +217,32 @@ const observer = {
return;
}
let window = aEvent.target.ownerDocument.defaultView;
switch (aEvent.type) {
// Used to mask fields with filled generated passwords when blurred.
case "blur": {
let unmask = false;
LoginManagerContent._togglePasswordFieldMasking(aEvent.target, unmask);
LoginManagerContent.forWindow(window)._togglePasswordFieldMasking(
aEvent.target,
unmask
);
break;
}
// Used to watch for changes to fields filled with generated passwords.
case "change": {
LoginManagerContent._generatedPasswordFilledOrEdited(aEvent.target);
LoginManagerContent.forWindow(window)._generatedPasswordFilledOrEdited(
aEvent.target
);
break;
}
// Used to watch for changes to fields filled with generated passwords.
case "input": {
LoginManagerContent._maybeStopTreatingAsGeneratedPasswordField(aEvent);
LoginManagerContent.forWindow(
window
)._maybeStopTreatingAsGeneratedPasswordField(aEvent);
break;
}
@ -226,7 +251,9 @@ const observer = {
aEvent.keyCode == aEvent.DOM_VK_TAB ||
aEvent.keyCode == aEvent.DOM_VK_RETURN
) {
LoginManagerContent.onUsernameAutocompleted(aEvent.target);
LoginManagerContent.forWindow(window).onUsernameAutocompleted(
aEvent.target
);
}
break;
}
@ -235,7 +262,7 @@ const observer = {
if (aEvent.target.type == "password") {
// Used to unmask fields with filled generated passwords when focused.
let unmask = true;
LoginManagerContent._togglePasswordFieldMasking(
LoginManagerContent.forWindow(window)._togglePasswordFieldMasking(
aEvent.target,
unmask
);
@ -243,7 +270,7 @@ const observer = {
}
// Only used for username fields.
LoginManagerContent._onUsernameFocus(aEvent);
LoginManagerContent.forWindow(window)._onUsernameFocus(aEvent);
break;
}
@ -307,7 +334,7 @@ let gAutoCompleteListener = {
return;
}
let focusedElement = LoginManagerContent._formFillService.focusedInput;
let focusedElement = gFormFillService.focusedInput;
if (
event.keyCode != event.DOM_VK_RETURN ||
focusedElement != event.target
@ -319,7 +346,7 @@ let gAutoCompleteListener = {
},
onPopupClosed(selectedRowStyle, mm) {
let focusedElement = LoginManagerContent._formFillService.focusedInput;
let focusedElement = gFormFillService.focusedInput;
let eventTarget = this.keyDownEnterForInput;
if (
!eventTarget ||
@ -337,57 +364,58 @@ let gAutoCompleteListener = {
},
};
// This object maps to the "child" process (even in the single-process case).
this.LoginManagerContent = {
__formFillService: null, // FormFillController, for username autocompleting
get _formFillService() {
if (!this.__formFillService) {
this.__formFillService = Cc[
"@mozilla.org/satchel/form-fill-controller;1"
].getService(Ci.nsIFormFillController);
this.LoginManagerContent = class LoginManagerContent {
constructor() {
/**
* WeakMap of the root element of a LoginForm to the DeferredTask to fill its fields.
*
* This is used to be able to throttle fills for a LoginForm since onDOMInputPasswordAdded gets
* dispatched for each password field added to a document but we only want to fill once per
* LoginForm when multiple fields are added at once.
*
* @type {WeakMap}
*/
this._deferredPasswordAddedTasksByRootElement = new WeakMap();
/**
* WeakMap of a document to the array of callbacks to execute when it becomes visible
*
* This is used to defer handling DOMFormHasPassword and onDOMInputPasswordAdded events when the
* containing document is hidden.
* When the document first becomes visible, any queued events will be handled as normal.
*
* @type {WeakMap}
*/
this._visibleTasksByDocument = new WeakMap();
/**
* Maps all DOM content documents in this content process, including those in
* frames, to the current state used by the Login Manager.
*/
this._loginFormStateByDocument = new WeakMap();
// Map from form login requests to information about that request.
this._requests = new Map();
// Number of outstanding requests to each manager.
this._managers = new Map();
}
static forWindow(window) {
// For now, this is a singleton.
if (!gLoginManagerContentSingleton) {
gLoginManagerContentSingleton = new LoginManagerContent();
}
return this.__formFillService;
},
return gLoginManagerContentSingleton;
}
_getRandomId() {
return Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator)
.generateUUID()
.toString();
},
_messages: [
"PasswordManager:loginsFound",
"PasswordManager:loginsAutoCompleted",
],
/**
* WeakMap of the root element of a LoginForm to the DeferredTask to fill its fields.
*
* This is used to be able to throttle fills for a LoginForm since onDOMInputPasswordAdded gets
* dispatched for each password field added to a document but we only want to fill once per
* LoginForm when multiple fields are added at once.
*
* @type {WeakMap}
*/
_deferredPasswordAddedTasksByRootElement: new WeakMap(),
/**
* WeakMap of a document to the array of callbacks to execute when it becomes visible
*
* This is used to defer handling DOMFormHasPassword and onDOMInputPasswordAdded events when the
* containing document is hidden.
* When the document first becomes visible, any queued events will be handled as normal.
*
* @type {WeakMap}
*/
_onVisibleTasksByDocument: new WeakMap(),
// Map from form login requests to information about that request.
_requests: new Map(),
// Number of outstanding requests to each manager.
_managers: new Map(),
}
_takeRequest(msg) {
let data = msg.data;
@ -399,7 +427,7 @@ this.LoginManagerContent = {
if (--count === 0) {
this._managers.delete(msg.target);
for (let message of this._messages) {
for (let message of _messages) {
msg.target.removeMessageListener(message, this);
}
} else {
@ -407,14 +435,14 @@ this.LoginManagerContent = {
}
return request;
},
}
_sendRequest(messageManager, requestData, name, messageData) {
let count;
if (!(count = this._managers.get(messageManager))) {
this._managers.set(messageManager, 1);
for (let message of this._messages) {
for (let message of _messages) {
messageManager.addMessageListener(message, this);
}
} else {
@ -430,7 +458,7 @@ this.LoginManagerContent = {
requestData.promise = deferred;
this._requests.set(requestId, requestData);
return deferred.promise;
},
}
_compareAndUpdatePreviouslySentValues(
formLikeRoot,
@ -470,12 +498,12 @@ this.LoginManagerContent = {
"_compareAndUpdatePreviouslySentValues: values not equivalent, returning false"
);
return false;
},
}
receiveMessage(msg, topWindow) {
receiveMessage(msg) {
if (msg.name == "PasswordManager:fillForm") {
this.fillForm({
topDocument: topWindow.document,
topDocument: msg.target.content.document,
loginFormOrigin: msg.data.loginFormOrigin,
loginsFound: LoginHelper.vanillaObjectsToLogins(msg.data.logins),
recipes: msg.data.recipes,
@ -521,7 +549,7 @@ this.LoginManagerContent = {
msg.data.password
);
this.fillForm({
topDocument: topWindow.document,
topDocument: msg.target.content.document,
loginFormOrigin: msg.data.origin,
loginsFound: [generatedLogin],
recipes: msg.data.recipes,
@ -538,7 +566,7 @@ this.LoginManagerContent = {
break;
}
}
},
}
/**
* Get relevant logins and recipes from the parent
@ -572,7 +600,7 @@ this.LoginManagerContent = {
"PasswordManager:findLogins",
messageData
);
},
}
_autoCompleteSearchAsync(aSearchString, aPreviousResult, aElement) {
let doc = aElement.ownerDocument;
@ -614,7 +642,7 @@ this.LoginManagerContent = {
"PasswordManager:autoCompleteLogins",
messageData
);
},
}
setupProgressListener(window) {
if (!LoginHelper.formlessCaptureEnabled) {
@ -633,7 +661,7 @@ this.LoginManagerContent = {
} catch (ex) {
// Ignore NS_ERROR_FAILURE if the progress listener was already added
}
},
}
onDOMFormBeforeSubmit(event) {
if (!event.isTrusted) {
@ -644,15 +672,15 @@ this.LoginManagerContent = {
// can grab form data before it might be modified (see bug 257781).
log("notified before form submission");
let formLike = LoginFormFactory.createFromForm(event.target);
LoginManagerContent._onFormSubmit(formLike);
},
this._onFormSubmit(formLike);
}
onDocumentVisibilityChange(event) {
if (!event.isTrusted) {
return;
}
let document = event.target;
let onVisibleTasks = this._onVisibleTasksByDocument.get(document);
let onVisibleTasks = this._visibleTasksByDocument.get(document);
if (!onVisibleTasks) {
return;
}
@ -660,8 +688,8 @@ this.LoginManagerContent = {
log("onDocumentVisibilityChange, executing queued task");
task();
}
this._onVisibleTasksByDocument.delete(document);
},
this._visibleTasksByDocument.delete(document);
}
_deferHandlingEventUntilDocumentVisible(event, document, fn) {
log(
@ -669,13 +697,13 @@ this.LoginManagerContent = {
event.type
}`
);
let onVisibleTasks = this._onVisibleTasksByDocument.get(document);
let onVisibleTasks = this._visibleTasksByDocument.get(document);
if (!onVisibleTasks) {
log(
`deferHandling, first queued event, register the visibilitychange handler`
);
onVisibleTasks = [];
this._onVisibleTasksByDocument.set(document, onVisibleTasks);
this._visibleTasksByDocument.set(document, onVisibleTasks);
document.addEventListener(
"visibilitychange",
event => {
@ -685,7 +713,7 @@ this.LoginManagerContent = {
);
}
onVisibleTasks.push(fn);
},
}
onDOMFormHasPassword(event) {
if (!event.isTrusted) {
@ -713,14 +741,14 @@ this.LoginManagerContent = {
this._processDOMFormHasPasswordEvent(event);
});
}
},
}
_processDOMFormHasPasswordEvent(event) {
let form = event.target;
let formLike = LoginFormFactory.createFromForm(form);
log("_processDOMFormHasPasswordEvent:", form, formLike);
this._fetchLoginsFromParentAndFillForm(formLike);
},
}
onDOMInputPasswordAdded(event, topWindow) {
if (!event.isTrusted) {
@ -757,7 +785,7 @@ this.LoginManagerContent = {
this._processDOMInputPasswordAddedEvent(event, topWindow);
});
}
},
}
_processDOMInputPasswordAddedEvent(event, topWindow) {
let pwField = event.originalTarget;
@ -823,7 +851,7 @@ this.LoginManagerContent = {
{ once: true }
);
}
},
}
/**
* Fetch logins from the parent for a given form and then attempt to fill it.
@ -842,20 +870,14 @@ this.LoginManagerContent = {
this._getLoginDataFromParent(form, { showMasterPassword: true })
.then(this.loginsFound.bind(this))
.catch(Cu.reportError);
},
/**
* Maps all DOM content documents in this content process, including those in
* frames, to the current state used by the Login Manager.
*/
loginFormStateByDocument: new WeakMap(),
}
/**
* Retrieves a reference to the state object associated with the given
* document. This is initialized to an object with default values.
*/
stateForDocument(document) {
let loginFormState = this.loginFormStateByDocument.get(document);
let loginFormState = this._loginFormStateByDocument.get(document);
if (!loginFormState) {
loginFormState = {
/**
@ -868,10 +890,10 @@ this.LoginManagerContent = {
lastSubmittedValuesByRootElement: new WeakMap(),
loginFormRootElements: new WeakSet(),
};
this.loginFormStateByDocument.set(document, loginFormState);
this._loginFormStateByDocument.set(document, loginFormState);
}
return loginFormState;
},
}
/**
* Perform a password fill upon user request coming from the parent process.
@ -948,7 +970,7 @@ this.LoginManagerContent = {
clobberPassword: true,
userTriggered: true,
});
},
}
loginsFound({ form, loginsFound, recipes }) {
let doc = form.ownerDocument;
@ -960,7 +982,7 @@ this.LoginManagerContent = {
LoginRecipesContent.cacheRecipes(formOrigin, doc.defaultView, recipes);
this._fillForm(form, loginsFound, recipes, { autofillForm });
},
}
/**
* Focus event handler for username fields to decide whether to show autocomplete.
@ -998,8 +1020,8 @@ this.LoginManagerContent = {
}
log("maybeOpenAutocompleteAfterFocus: Opening the autocomplete popup");
this._formFillService.showPopup();
},
gFormFillService.showPopup();
}
/**
* A username or password was autocompleted into a field.
@ -1028,7 +1050,7 @@ this.LoginManagerContent = {
this._stopTreatingAsGeneratedPasswordField(acInputField);
this._highlightFilledField(acInputField);
}
},
}
/**
* A username field was filled or tabbed away from so try fill in the
@ -1079,7 +1101,7 @@ this.LoginManagerContent = {
} else {
// Ignore the event, it's for some input we don't care about.
}
},
}
/**
* @param {LoginForm} form - the LoginForm to look for password fields in.
@ -1161,7 +1183,7 @@ this.LoginManagerContent = {
}
return pwFields;
},
}
/**
* Returns the username and password fields found in the form.
@ -1335,7 +1357,7 @@ this.LoginManagerContent = {
log("Password field (old):", oldPasswordField);
}
return [usernameField, newPasswordField, oldPasswordField];
},
}
/**
* @return true if the page requests autocomplete be disabled for the
@ -1343,7 +1365,7 @@ this.LoginManagerContent = {
*/
_isAutocompleteDisabled(element) {
return element && element.autocomplete == "off";
},
}
/**
* Fill a page that was restored from bfcache since we wouldn't receive
@ -1373,7 +1395,7 @@ this.LoginManagerContent = {
let formLike = LoginFormFactory.getForRootElement(formRoot);
this._fetchLoginsFromParentAndFillForm(formLike);
}
},
}
/**
* Trigger capture on any relevant FormLikes due to a navigation alone (not
@ -1409,7 +1431,7 @@ this.LoginManagerContent = {
let formLike = LoginFormFactory.getForRootElement(formRoot);
this._onFormSubmit(formLike);
}
},
}
/**
* Called by our observer when notified of a form submission.
@ -1548,7 +1570,7 @@ this.LoginManagerContent = {
openerTopWindowID,
dismissedPrompt,
});
},
}
_maybeStopTreatingAsGeneratedPasswordField(event) {
let passwordField = event.target;
@ -1559,7 +1581,7 @@ this.LoginManagerContent = {
if (!value || (event.data && event.data == value)) {
this._stopTreatingAsGeneratedPasswordField(passwordField);
}
},
}
_stopTreatingAsGeneratedPasswordField(passwordField) {
log("_stopTreatingAsGeneratedPasswordField");
@ -1574,7 +1596,7 @@ this.LoginManagerContent = {
// Mask the password field
this._togglePasswordFieldMasking(passwordField, false);
},
}
/**
* Notify the parent that a generated password was filled into a field or
@ -1652,7 +1674,7 @@ this.LoginManagerContent = {
username,
}
);
},
}
_togglePasswordFieldMasking(passwordField, unmask) {
let { editor } = passwordField;
@ -1677,14 +1699,14 @@ this.LoginManagerContent = {
return;
}
editor.mask();
},
}
/** Remove login field highlight when its value is cleared or overwritten.
*/
_removeFillFieldHighlight(event) {
let winUtils = event.target.ownerGlobal.windowUtils;
winUtils.removeManuallyManagedState(event.target, AUTOFILL_STATE);
},
}
/**
* Highlight login fields on autocomplete or autofill on page load.
@ -1699,7 +1721,7 @@ this.LoginManagerContent = {
mozSystemGroup: true,
once: true,
});
},
}
/**
* Filter logins for exact origin/formActionOrigin and dedupe on usernamematche
@ -1746,7 +1768,7 @@ this.LoginManagerContent = {
formActionOrigin
);
return logins;
},
}
/**
* Attempt to find the username and password fields in a form, and fill them
@ -1871,7 +1893,7 @@ this.LoginManagerContent = {
// We would also need this attached to show the insecure login
// warning, regardless of saved login.
if (usernameField) {
this._formFillService.markAsLoginManagerField(usernameField);
gFormFillService.markAsLoginManagerField(usernameField);
usernameField.addEventListener("keydown", observer);
}
@ -2106,7 +2128,7 @@ this.LoginManagerContent = {
.add(autofillResult);
if (usernameField) {
let focusedElement = this._formFillService.focusedInput;
let focusedElement = gFormFillService.focusedInput;
if (
usernameField == focusedElement &&
autofillResult !== AUTOFILL_RESULT.FILLED
@ -2114,7 +2136,7 @@ this.LoginManagerContent = {
log(
"_fillForm: Opening username autocomplete popup since the form wasn't autofilled"
);
this._formFillService.showPopup();
gFormFillService.showPopup();
}
}
}
@ -2130,7 +2152,7 @@ this.LoginManagerContent = {
"passwordmgr-processed-form"
);
}
},
}
/**
* Given a field, determine whether that field was last filled as a username
@ -2184,7 +2206,7 @@ this.LoginManagerContent = {
}
return true;
},
}
/**
* Returns the username and password fields found in the form by input
@ -2213,7 +2235,7 @@ this.LoginManagerContent = {
let recipes = LoginRecipesContent.getRecipes(formOrigin, doc.defaultView);
return this._getFormFields(form, false, recipes);
},
}
/**
* Verify if a field is a valid login form field and
@ -2261,5 +2283,5 @@ this.LoginManagerContent = {
(newPasswordField.disabled || newPasswordField.readOnly),
},
};
},
}
};

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

@ -211,12 +211,14 @@ this.LoginManagerContextMenu = {
* origin when subframes are involved.
*/
_fillTargetField(login, inputElementIdentifier, browser, formOrigin) {
LoginManagerParent.fillForm({
browser,
inputElementIdentifier,
loginFormOrigin: formOrigin,
login,
}).catch(Cu.reportError);
LoginManagerParent.getLoginManagerParent()
.fillForm({
browser,
inputElementIdentifier,
loginFormOrigin: formOrigin,
login,
})
.catch(Cu.reportError);
},
/**

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

@ -52,29 +52,46 @@ XPCOMUtils.defineLazyPreferenceGetter(
const EXPORTED_SYMBOLS = ["LoginManagerParent"];
this.LoginManagerParent = {
/**
* A map of a principal's origin (including suffixes) to a generated password string and filled flag
* so that we can offer the same password later (e.g. in a confirmation field).
*
* We don't currently evict from this cache so entries should last until the end of the browser
* session. That may change later but for now a typical session would max out at a few entries.
*/
_generatedPasswordsByPrincipalOrigin: new Map(),
let gLoginManagerParentSingleton = null;
/**
* Reference to the default LoginRecipesParent (instead of the initialization promise) for
* synchronous access. This is a temporary hack and new consumers should yield on
* recipeParentPromise instead.
*
* @type LoginRecipesParent
* @deprecated
*/
_recipeManager: null,
/**
* A map of a principal's origin (including suffixes) to a generated password string and filled flag
* so that we can offer the same password later (e.g. in a confirmation field).
*
* We don't currently evict from this cache so entries should last until the end of the browser
* session. That may change later but for now a typical session would max out at a few entries.
*/
let gGeneratedPasswordsByPrincipalOrigin = new Map();
// Tracks the last time the user cancelled the master password prompt,
// to avoid spamming master password prompts on autocomplete searches.
_lastMPLoginCancelled: Math.NEGATIVE_INFINITY,
/**
* Reference to the default LoginRecipesParent (instead of the initialization promise) for
* synchronous access. This is a temporary hack and new consumers should yield on
* recipeParentPromise instead.
*
* @type LoginRecipesParent
* @deprecated
*/
let gRecipeManager = null;
class LoginManagerParent {
constructor() {
// Tracks the last time the user cancelled the master password prompt,
// to avoid spamming master password prompts on autocomplete searches.
this._lastMPLoginCancelled = Math.NEGATIVE_INFINITY;
}
// Some unit tests need to access this.
static getGeneratedPasswordsByPrincipalOrigin() {
return gGeneratedPasswordsByPrincipalOrigin;
}
static getLoginManagerParent() {
// For now, this is a singleton.
if (!gLoginManagerParentSingleton) {
gLoginManagerParentSingleton = new LoginManagerParent();
}
return gLoginManagerParentSingleton;
}
/**
* @param {origin} formOrigin
@ -134,7 +151,11 @@ this.LoginManagerParent = {
formOrigin,
formActionOrigin
);
},
}
static receiveMessage(msg) {
LoginManagerParent.getLoginManagerParent().receiveMessage(msg);
}
// Listeners are added in BrowserGlue.jsm on desktop
// and in BrowserCLH.js on mobile.
@ -155,7 +176,7 @@ this.LoginManagerParent = {
case "PasswordManager:findRecipes": {
let formHost = new URL(data.formOrigin).host;
return this._recipeManager.getRecipesForHost(formHost);
return gRecipeManager.getRecipesForHost(formHost);
}
case "PasswordManager:onFormSubmit": {
@ -190,7 +211,7 @@ this.LoginManagerParent = {
}
return undefined;
},
}
// Observers are added in BrowserGlue.jsm on desktop
observe(subject, topic, data) {
@ -199,7 +220,7 @@ this.LoginManagerParent = {
(topic == "passwordmgr-storage-changed" && data == "removeLogin")
) {
let { origin, guid } = subject;
let generatedPW = this._generatedPasswordsByPrincipalOrigin.get(origin);
let generatedPW = gGeneratedPasswordsByPrincipalOrigin.get(origin);
// in the case where an autosaved login removed or merged into an existing login,
// clear the guid associated with the generated-password cache entry
@ -215,7 +236,7 @@ this.LoginManagerParent = {
generatedPW.storageGUID = null;
}
}
},
}
/**
* Trigger a login form fill and send relevant data (e.g. logins and recipes)
@ -227,7 +248,7 @@ this.LoginManagerParent = {
let formHost;
try {
formHost = new URL(loginFormOrigin).host;
let recipeManager = await this.recipeParentPromise;
let recipeManager = await LoginManagerParent.recipeParentPromise;
recipes = recipeManager.getRecipesForHost(formHost);
} catch (ex) {
// Some schemes e.g. chrome aren't supported by URL
@ -244,7 +265,7 @@ this.LoginManagerParent = {
logins: jsLogins,
recipes,
});
},
}
/**
* Send relevant data (e.g. logins and recipes) to the child process (LoginManagerContent).
@ -261,7 +282,7 @@ this.LoginManagerParent = {
let formHost;
try {
formHost = new URL(formOrigin).host;
let recipeManager = await this.recipeParentPromise;
let recipeManager = await LoginManagerParent.recipeParentPromise;
recipes = recipeManager.getRecipesForHost(formHost);
} catch (ex) {
// Some schemes e.g. chrome aren't supported by URL
@ -351,7 +372,7 @@ this.LoginManagerParent = {
logins: jsLogins,
recipes,
});
},
}
doAutocompleteSearch(
{
@ -448,14 +469,14 @@ this.LoginManagerParent = {
logins: jsLogins,
}
);
},
}
/**
* Expose `BrowsingContext` so we can stub it in tests.
*/
get _browsingContextGlobal() {
static get _browsingContextGlobal() {
return BrowsingContext;
},
}
getGeneratedPassword(browsingContextId) {
if (
@ -474,7 +495,7 @@ this.LoginManagerParent = {
browsingContext.currentWindowGlobal.documentPrincipal.origin;
// Use the same password if we already generated one for this origin so that it doesn't change
// with each search/keystroke and the user can easily re-enter a password in a confirmation field.
let generatedPW = this._generatedPasswordsByPrincipalOrigin.get(
let generatedPW = gGeneratedPasswordsByPrincipalOrigin.get(
framePrincipalOrigin
);
if (generatedPW) {
@ -493,12 +514,9 @@ this.LoginManagerParent = {
storageGUID: null,
value: PasswordGenerator.generatePassword(),
};
this._generatedPasswordsByPrincipalOrigin.set(
framePrincipalOrigin,
generatedPW
);
gGeneratedPasswordsByPrincipalOrigin.set(framePrincipalOrigin, generatedPW);
return generatedPW.value;
},
}
_getPrompter(browser, openerTopWindowID) {
let prompterSvc = Cc[
@ -519,7 +537,7 @@ this.LoginManagerParent = {
}
return prompterSvc;
},
}
onFormSubmit(
browser,
@ -585,7 +603,7 @@ this.LoginManagerParent = {
formActionOrigin,
});
let generatedPW = this._generatedPasswordsByPrincipalOrigin.get(origin);
let generatedPW = gGeneratedPasswordsByPrincipalOrigin.get(origin);
let autoSavedStorageGUID = "";
if (generatedPW && generatedPW.storageGUID) {
autoSavedStorageGUID = generatedPW.storageGUID;
@ -700,7 +718,7 @@ this.LoginManagerParent = {
// Prompt user to save login (via dialog or notification bar)
let prompter = this._getPrompter(browser, openerTopWindowID);
prompter.promptToSavePassword(formLogin, dismissedPrompt);
},
}
_onGeneratedPasswordFilledOrEdited({
browsingContextId,
@ -742,7 +760,7 @@ this.LoginManagerParent = {
let framePrincipalOrigin =
browsingContext.currentWindowGlobal.documentPrincipal.origin;
let generatedPW = this._generatedPasswordsByPrincipalOrigin.get(
let generatedPW = gGeneratedPasswordsByPrincipalOrigin.get(
framePrincipalOrigin
);
@ -916,22 +934,21 @@ this.LoginManagerParent = {
true, // dismissed prompt
shouldAutoSaveLogin // notifySaved
);
},
};
XPCOMUtils.defineLazyGetter(
LoginManagerParent,
"recipeParentPromise",
function() {
const { LoginRecipesParent } = ChromeUtils.import(
"resource://gre/modules/LoginRecipes.jsm"
);
this._recipeManager = new LoginRecipesParent({
defaults: Services.prefs.getStringPref("signon.recipes.path"),
});
return this._recipeManager.initializationPromise;
}
);
static get recipeParentPromise() {
if (!gRecipeManager) {
const { LoginRecipesParent } = ChromeUtils.import(
"resource://gre/modules/LoginRecipes.jsm"
);
gRecipeManager = new LoginRecipesParent({
defaults: Services.prefs.getStringPref("signon.recipes.path"),
});
}
return gRecipeManager.initializationPromise;
}
}
XPCOMUtils.defineLazyPreferenceGetter(
LoginManagerParent,

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

@ -78,7 +78,7 @@ this.LoginTestUtils = {
let { LoginManagerParent } = ChromeUtils.import(
"resource://gre/modules/LoginManagerParent.jsm"
);
LoginManagerParent._generatedPasswordsByPrincipalOrigin.clear();
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
},
/**

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

@ -75,12 +75,17 @@ add_task(async function test() {
let formLike = LoginFormFactory.createFromField(password);
info("Calling _fillForm with FormLike");
addedLogin = LoginHelper.vanillaObjectToLogin(addedLogin);
LoginManagerContent._fillForm(formLike, [addedLogin], null, {
autofillForm: true,
clobberUsername: true,
clobberPassword: true,
userTriggered: true,
});
LoginManagerContent.forWindow(content)._fillForm(
formLike,
[addedLogin],
null,
{
autofillForm: true,
clobberUsername: true,
clobberPassword: true,
userTriggered: true,
}
);
if (aUsernameRequested) {
let username = content.document.querySelector("#form-basic-username");

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

@ -752,7 +752,7 @@ add_task(async function autocomplete_generated_password_edited_no_auto_save() {
}
);
LMP._generatedPasswordsByPrincipalOrigin.clear();
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
});
add_task(async function contextmenu_fill_generated_password_and_set_username() {
@ -1029,7 +1029,7 @@ add_task(
info("autoSavedLogin, guid: " + autoSavedLogin.guid);
info("verifyLogins ok");
let passwordCacheEntry = LoginManagerParent._generatedPasswordsByPrincipalOrigin.get(
let passwordCacheEntry = LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://example.com"
);
@ -1124,7 +1124,7 @@ add_task(
// make sure the cache entry is unchanged with the removal of the auto-saved login
is(
autoSavedLogin.password,
LoginManagerParent._generatedPasswordsByPrincipalOrigin.get(
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://example.com"
).value,
"Generated password cache entry has the expected password value"
@ -1200,7 +1200,7 @@ add_task(async function autosaved_login_updated_to_existing_login_onsubmit() {
info("autoSavedLogin, guid: " + autoSavedLogin.guid);
info("verifyLogins ok");
let passwordCacheEntry = LoginManagerParent._generatedPasswordsByPrincipalOrigin.get(
let passwordCacheEntry = LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://example.com"
);
@ -1319,7 +1319,7 @@ add_task(async function autosaved_login_updated_to_existing_login_onsubmit() {
// make sure the cache entry is unchanged with the removal of the auto-saved login
is(
autoSavedLogin.password,
LoginManagerParent._generatedPasswordsByPrincipalOrigin.get(
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://example.com"
).value,
"Generated password cache entry has the expected password value"

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

@ -1,7 +1,7 @@
const DIRECTORY_PATH = "/browser/toolkit/components/passwordmgr/test/browser/";
ChromeUtils.import("resource://gre/modules/LoginHelper.jsm", this);
const { LoginManagerParent: LMP } = ChromeUtils.import(
const { LoginManagerParent } = ChromeUtils.import(
"resource://gre/modules/LoginManagerParent.jsm"
);
ChromeUtils.import("resource://testing-common/LoginTestUtils.jsm", this);

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

@ -62,7 +62,7 @@ add_task(async function test_preventDefaultAndStopPropagation() {
SpecialPowers.wrap(pword).setUserInput("generatedpass");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Before first fill");
LoginManagerContent._generatedPasswordFilledOrEdited(pword);
LoginManagerContent.forWindow(window)._generatedPasswordFilledOrEdited(pword);
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "After first fill");
synthesizeKey("KEY_Tab"); // blur
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "After blur");
@ -80,7 +80,7 @@ add_task(async function test_fieldsMaskedAfterSavedLoginFill() {
SpecialPowers.wrap(pword).setUserInput("generatedpass");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Before first fill");
LoginManagerContent._generatedPasswordFilledOrEdited(pword);
LoginManagerContent.forWindow(window)._generatedPasswordFilledOrEdited(pword);
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "After first fill");
synthesizeKey("KEY_Tab", { shiftKey: true }); // blur pw, focus un
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "After blur");
@ -105,7 +105,7 @@ add_task(async function test_fieldsMaskedAfterReplacingWholeValue() {
SpecialPowers.wrap(pword).setUserInput("generatedpass");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Before first fill");
LoginManagerContent._generatedPasswordFilledOrEdited(pword);
LoginManagerContent.forWindow(window)._generatedPasswordFilledOrEdited(pword);
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "After first fill");
synthesizeKey("KEY_Tab", { shiftKey: true }); // blur pw, focus un
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "After blur");
@ -132,7 +132,7 @@ add_task(async function test_fieldsUnmaskedAfterAddingCharacter() {
SpecialPowers.wrap(pword).setUserInput("generatedpass");
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Before first fill");
LoginManagerContent._generatedPasswordFilledOrEdited(pword);
LoginManagerContent.forWindow(window)._generatedPasswordFilledOrEdited(pword);
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "After first fill");
synthesizeKey("KEY_Tab", { shiftKey: true }); // blur pw, focus un
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "After blur");
@ -160,7 +160,7 @@ add_task(async function test_typeNotPassword() {
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Before first fill");
SpecialPowers.wrap(pword).setUserInput("generatedpass");
LoginManagerContent._generatedPasswordFilledOrEdited(pword);
LoginManagerContent.forWindow(window)._generatedPasswordFilledOrEdited(pword);
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "After first fill");
// Simulate a website doing their own unmasking and re-masking

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

@ -21,8 +21,8 @@ function initLogins() {
const {LoginManagerParent} = ChromeUtils.import("resource://gre/modules/LoginManagerParent.jsm");
Services.telemetry.clearEvents();
if (LoginManagerParent._generatedPasswordsByPrincipalOrigin) {
LoginManagerParent._generatedPasswordsByPrincipalOrigin.clear();
if (LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin()) {
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
}
Services.logins.addLogin(login1);
}

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

@ -156,7 +156,7 @@ add_task(async function test() {
info("Calling _onFormSubmit with FormLike");
let processedPromise = getSubmitMessage();
LoginManagerContent._onFormSubmit(formLike);
LoginManagerContent.forWindow(frameDoc.defaultView)._onFormSubmit(formLike);
let submittedResult = await processedPromise;

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

@ -5,7 +5,7 @@
"use strict";
const { sinon } = ChromeUtils.import("resource://testing-common/Sinon.jsm");
const { LoginManagerParent: LMP } = ChromeUtils.import(
const { LoginManagerParent } = ChromeUtils.import(
"resource://gre/modules/LoginManagerParent.jsm"
);
@ -13,6 +13,8 @@ add_task(async function test_doAutocompleteSearch_generated_noLogins() {
Services.prefs.setBoolPref("signon.generation.available", true); // TODO: test both with false
Services.prefs.setBoolPref("signon.generation.enabled", true);
let LMP = new LoginManagerParent();
ok(LMP.doAutocompleteSearch, "doAutocompleteSearch exists");
// Default to the happy path
@ -50,7 +52,7 @@ add_task(async function test_doAutocompleteSearch_generated_noLogins() {
};
sinon
.stub(LMP._browsingContextGlobal, "get")
.stub(LoginManagerParent._browsingContextGlobal, "get")
.withArgs(123)
.callsFake(() => {
return {

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

@ -5,7 +5,7 @@
"use strict";
const { sinon } = ChromeUtils.import("resource://testing-common/Sinon.jsm");
const { LoginManagerParent: LMP } = ChromeUtils.import(
const { LoginManagerParent } = ChromeUtils.import(
"resource://gre/modules/LoginManagerParent.jsm"
);
@ -14,23 +14,28 @@ add_task(async function test_getGeneratedPassword() {
Services.prefs.setBoolPref("signon.generation.available", true);
Services.prefs.setBoolPref("signon.generation.enabled", true);
let LMP = new LoginManagerParent();
ok(LMP.getGeneratedPassword, "LMP.getGeneratedPassword exists");
equal(
LMP._generatedPasswordsByPrincipalOrigin.size,
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().size,
0,
"Empty cache to start"
);
equal(LMP.getGeneratedPassword(99), null, "Null with no BrowsingContext");
ok(LMP._browsingContextGlobal, "Check _browsingContextGlobal exists");
ok(
!LMP._browsingContextGlobal.get(99),
LoginManagerParent._browsingContextGlobal,
"Check _browsingContextGlobal exists"
);
ok(
!LoginManagerParent._browsingContextGlobal.get(99),
"BrowsingContext 99 shouldn't exist yet"
);
info("Stubbing BrowsingContext.get(99)");
sinon
.stub(LMP._browsingContextGlobal, "get")
.stub(LoginManagerParent._browsingContextGlobal, "get")
.withArgs(99)
.callsFake(() => {
return {
@ -42,7 +47,7 @@ add_task(async function test_getGeneratedPassword() {
};
});
ok(
LMP._browsingContextGlobal.get(99),
LoginManagerParent._browsingContextGlobal.get(99),
"Checking BrowsingContext.get(99) stub"
);
@ -53,9 +58,13 @@ add_task(async function test_getGeneratedPassword() {
LoginTestUtils.generation.LENGTH,
"Check password length"
);
equal(LMP._generatedPasswordsByPrincipalOrigin.size, 1, "1 added to cache");
equal(
LMP._generatedPasswordsByPrincipalOrigin.get(
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().size,
1,
"1 added to cache"
);
equal(
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://www.example.com^userContextId=6"
).value,
password1,
@ -69,9 +78,9 @@ add_task(async function test_getGeneratedPassword() {
);
info("Changing the documentPrincipal to simulate a navigation in the frame");
LMP._browsingContextGlobal.get.restore();
LoginManagerParent._browsingContextGlobal.get.restore();
sinon
.stub(LMP._browsingContextGlobal, "get")
.stub(LoginManagerParent._browsingContextGlobal, "get")
.withArgs(99)
.callsFake(() => {
return {

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

@ -5,7 +5,7 @@
"use strict";
const { sinon } = ChromeUtils.import("resource://testing-common/Sinon.jsm");
const { LoginManagerParent: LMP } = ChromeUtils.import(
const { LoginManagerParent } = ChromeUtils.import(
"resource://gre/modules/LoginManagerParent.jsm"
);
const { LoginManagerPrompter } = ChromeUtils.import(
@ -19,6 +19,8 @@ const loginTemplate = Object.freeze({
formActionOrigin: "https://www.mozilla.org",
});
let LMP = new LoginManagerParent();
function stubPrompter() {
let fakePromptToSavePassword = sinon.stub();
let fakePromptToChangePassword = sinon.stub();
@ -57,14 +59,17 @@ function stubPrompter() {
}
function stubGeneratedPasswordForBrowsingContextId(id) {
ok(LMP._browsingContextGlobal, "Check _browsingContextGlobal exists");
ok(
!LMP._browsingContextGlobal.get(id),
LoginManagerParent._browsingContextGlobal,
"Check _browsingContextGlobal exists"
);
ok(
!LoginManagerParent._browsingContextGlobal.get(id),
`BrowsingContext ${id} shouldn't exist yet`
);
info(`Stubbing BrowsingContext.get(${id})`);
let stub = sinon
.stub(LMP._browsingContextGlobal, "get")
.stub(LoginManagerParent._browsingContextGlobal, "get")
.withArgs(id)
.callsFake(() => {
return {
@ -79,7 +84,7 @@ function stubGeneratedPasswordForBrowsingContextId(id) {
};
});
ok(
LMP._browsingContextGlobal.get(id),
LoginManagerParent._browsingContextGlobal.get(id),
`Checking BrowsingContext.get(${id}) stub`
);
@ -90,15 +95,19 @@ function stubGeneratedPasswordForBrowsingContextId(id) {
LoginTestUtils.generation.LENGTH,
"Check password length"
);
equal(LMP._generatedPasswordsByPrincipalOrigin.size, 1, "1 added to cache");
equal(
LMP._generatedPasswordsByPrincipalOrigin.get(
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().size,
1,
"1 added to cache"
);
equal(
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://www.example.com^userContextId=6"
).value,
generatedPassword,
"Cache key and value"
);
LMP._browsingContextGlobal.get.resetHistory();
LoginManagerParent._browsingContextGlobal.get.resetHistory();
return {
stub,
@ -148,7 +157,7 @@ function startTestConditions(contextId) {
"Null with no BrowsingContext"
);
equal(
LMP._generatedPasswordsByPrincipalOrigin.size,
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().size,
0,
"Empty cache to start"
);
@ -242,7 +251,7 @@ add_task(async function test_onGeneratedPasswordFilledOrEdited() {
username: "someusername",
password: newPassword,
});
let generatedPW = LMP._generatedPasswordsByPrincipalOrigin.get(
let generatedPW = LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://www.example.com^userContextId=6"
);
ok(generatedPW.edited, "Cached edited boolean should be true");
@ -271,7 +280,7 @@ add_task(async function test_onGeneratedPasswordFilledOrEdited() {
username: "someusername",
password: newerPassword,
});
generatedPW = LMP._generatedPasswordsByPrincipalOrigin.get(
generatedPW = LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://www.example.com^userContextId=6"
);
ok(generatedPW.edited, "Cached edited state should remain true");
@ -288,9 +297,9 @@ add_task(async function test_onGeneratedPasswordFilledOrEdited() {
checkEditTelemetryRecorded(1, "with auto-save");
LMP._browsingContextGlobal.get.restore();
LoginManagerParent._browsingContextGlobal.get.restore();
restorePrompter();
LMP._generatedPasswordsByPrincipalOrigin.clear();
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
Services.logins.removeAllLogins();
Services.telemetry.clearEvents();
});
@ -350,7 +359,7 @@ add_task(async function test_onGeneratedPasswordFilledOrEdited_editToEmpty() {
username: "someusername",
password: newPassword,
});
let generatedPW = LMP._generatedPasswordsByPrincipalOrigin.get(
let generatedPW = LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://www.example.com^userContextId=6"
);
ok(!generatedPW.edited, "Cached edited boolean should be false");
@ -362,9 +371,9 @@ add_task(async function test_onGeneratedPasswordFilledOrEdited_editToEmpty() {
checkEditTelemetryRecorded(0, "Blanking doesn't count as an edit");
LMP._browsingContextGlobal.get.restore();
LoginManagerParent._browsingContextGlobal.get.restore();
restorePrompter();
LMP._generatedPasswordsByPrincipalOrigin.clear();
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
Services.logins.removeAllLogins();
Services.telemetry.clearEvents();
});
@ -433,7 +442,7 @@ add_task(async function test_addUsernameBeforeAutoSaveEdit() {
username: "someusername",
password: newPassword,
});
let generatedPW = LMP._generatedPasswordsByPrincipalOrigin.get(
let generatedPW = LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://www.example.com^userContextId=6"
);
ok(generatedPW.edited, "Cached edited boolean should be true");
@ -463,7 +472,7 @@ add_task(async function test_addUsernameBeforeAutoSaveEdit() {
username: "someusername",
password: newerPassword,
});
generatedPW = LMP._generatedPasswordsByPrincipalOrigin.get(
generatedPW = LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://www.example.com^userContextId=6"
);
ok(generatedPW.edited, "Cached edited state should remain true");
@ -481,9 +490,9 @@ add_task(async function test_addUsernameBeforeAutoSaveEdit() {
checkEditTelemetryRecorded(1, "with auto-save");
LMP._browsingContextGlobal.get.restore();
LoginManagerParent._browsingContextGlobal.get.restore();
restorePrompter();
LMP._generatedPasswordsByPrincipalOrigin.clear();
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
Services.logins.removeAllLogins();
Services.telemetry.clearEvents();
});
@ -509,9 +518,9 @@ add_task(
ok(LMP._getPrompter.notCalled, "Checking _getPrompter wasn't called");
// Clean up
LMP._browsingContextGlobal.get.restore();
LoginManagerParent._browsingContextGlobal.get.restore();
restorePrompter();
LMP._generatedPasswordsByPrincipalOrigin.clear();
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
Services.logins.setLoginSavingEnabled("https://www.example.com", true);
Services.logins.removeAllLogins();
}
@ -571,7 +580,7 @@ add_task(
username: "someusername",
password: newPassword,
});
let generatedPW = LMP._generatedPasswordsByPrincipalOrigin.get(
let generatedPW = LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://www.example.com^userContextId=6"
);
ok(generatedPW.edited, "Cached edited boolean should be true");
@ -587,9 +596,9 @@ add_task(
checkEditTelemetryRecorded(1, "Updating cache, not storage (no auto-save)");
LMP._browsingContextGlobal.get.restore();
LoginManagerParent._browsingContextGlobal.get.restore();
restorePrompter();
LMP._generatedPasswordsByPrincipalOrigin.clear();
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
Services.logins.removeAllLogins();
Services.telemetry.clearEvents();
}
@ -598,7 +607,7 @@ add_task(
add_task(
async function test_onGeneratedPasswordFilledOrEdited_withSavedEmptyUsernameAndUsernameValue() {
// Save as the above task but with a non-empty username field value.
startTestConditions();
startTestConditions(99);
let login0Props = Object.assign({}, loginTemplate, {
username: "",
password: "qweqweq",
@ -676,7 +685,7 @@ add_task(
"promptToSavePassword had a falsey 'notifySaved' argument"
);
let generatedPW = LMP._generatedPasswordsByPrincipalOrigin.get(
let generatedPW = LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().get(
"https://www.example.com^userContextId=6"
);
ok(generatedPW.edited, "Cached edited boolean should be true");
@ -695,9 +704,9 @@ add_task(
"Updating cache, not storage (no auto-save) with username in field"
);
LMP._browsingContextGlobal.get.restore();
LoginManagerParent._browsingContextGlobal.get.restore();
restorePrompter();
LMP._generatedPasswordsByPrincipalOrigin.clear();
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
Services.logins.removeAllLogins();
Services.telemetry.clearEvents();
}
@ -754,9 +763,9 @@ add_task(
"promptToChangePassword had a truthy 'notifySaved' argument"
);
LMP._browsingContextGlobal.get.restore();
LoginManagerParent._browsingContextGlobal.get.restore();
restorePrompter();
LMP._generatedPasswordsByPrincipalOrigin.clear();
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
Services.logins.removeAllLogins();
}
);
@ -810,9 +819,9 @@ add_task(
"promptToChangePassword had a truthy 'notifySaved' argument"
);
LMP._browsingContextGlobal.get.restore();
LoginManagerParent._browsingContextGlobal.get.restore();
restorePrompter();
LMP._generatedPasswordsByPrincipalOrigin.clear();
LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear();
Services.logins.removeAllLogins();
}
);

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

@ -167,7 +167,7 @@ add_task(async function test_searchAndDedupeLogins_acceptDifferentSubdomains() {
"Check length of added logins"
);
let actual = LMP._searchAndDedupeLogins(tc.formActionOrigin, {
let actual = new LMP()._searchAndDedupeLogins(tc.formActionOrigin, {
formActionOrigin: tc.formActionOrigin,
looseActionOriginMatch: true,
acceptDifferentSubdomains: true,

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

@ -161,7 +161,7 @@ for (let tc of TESTCASES) {
await testcase.beforeGetFunction(document, formLike);
}
let actual = LoginManagerContent._getFormFields(
let actual = new LoginManagerContent()._getFormFields(
formLike,
testcase.skipEmptyFields,
new Set()

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

@ -197,7 +197,7 @@ for (let tc of TESTCASES) {
let formLikeIndex = -1;
for (let formLikeFromInput of mapRootElementToFormLike.values()) {
formLikeIndex++;
let pwFields = LoginManagerContent._getPasswordFields(
let pwFields = new LoginManagerContent()._getPasswordFields(
formLikeFromInput,
{
fieldOverrideRecipe: testcase.fieldOverrideRecipe,
@ -287,7 +287,7 @@ for (let tc of EMOJI_TESTCASES) {
let input = document.querySelector("input[type='password']");
Assert.ok(input, "Found the password field");
let formLike = LoginFormFactory.createFromField(input);
let pwFields = LoginManagerContent._getPasswordFields(formLike, {
let pwFields = new LoginManagerContent()._getPasswordFields(formLike, {
minPasswordLength: testcase.minPasswordLength,
});
info("Got password fields: " + pwFields.length);

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

@ -111,7 +111,9 @@ for (let tc of TESTCASES) {
let formOrigin = LoginHelper.getLoginOrigin(document.documentURI);
LoginRecipesContent.cacheRecipes(formOrigin, win, new Set());
let actual = LoginManagerContent.getUserNameAndPasswordFields(input);
let actual = new LoginManagerContent().getUserNameAndPasswordFields(
input
);
Assert.strictEqual(
testcase.returnedFieldIDs.length,