Bug 1538460 - Only defer handling fields for login autofill when master password is not set. r=MattN

* Use Services.(ppmm|cpmm).sharedData to make isMasterPasswordSet value available to the content process
* We don't handle runtime enable/disable of MP

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Sam Foster 2019-04-15 18:48:03 +00:00
Родитель 0ce6855fe4
Коммит 1b48ee9bf6
4 изменённых файлов: 43 добавлений и 34 удалений

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

@ -87,11 +87,14 @@ LoginManager.prototype = {
Services.obs.addObserver(this._observer, "gather-telemetry");
},
_initStorage() {
this._storage = Cc["@mozilla.org/login-manager/storage/default;1"]
.createInstance(Ci.nsILoginManagerStorage);
this.initializationPromise = this._storage.initialize();
this.initializationPromise.then(() => {
log.debug("initializationPromise is resolved, updating isMasterPasswordSet in sharedData");
Services.ppmm.sharedData.set("isMasterPasswordSet", LoginHelper.isMasterPasswordSet());
});
},

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

@ -445,8 +445,15 @@ var LoginManagerContent = {
if (!event.isTrusted) {
return;
}
let isMasterPasswordSet = Services.cpmm.sharedData.get("isMasterPasswordSet");
let document = event.target.ownerDocument;
if (document.visibilityState == "visible") {
// don't attempt to defer handling when a master password is set
// Showing the MP modal as soon as possible minimizes its interference with tab interactions
// See bug 1539091 and bug 1538460.
log("onDOMFormHasPassword, visibilityState:", document.visibilityState,
"isMasterPasswordSet:", isMasterPasswordSet);
if (document.visibilityState == "visible" || isMasterPasswordSet) {
this._processDOMFormHasPasswordEvent(event);
} else {
// wait until the document becomes visible before handling this event
@ -477,7 +484,14 @@ var LoginManagerContent = {
}
let document = pwField.ownerDocument;
if (document.visibilityState == "visible") {
let isMasterPasswordSet = Services.cpmm.sharedData.get("isMasterPasswordSet");
log("onDOMInputPasswordAdded, visibilityState:", document.visibilityState,
"isMasterPasswordSet:", isMasterPasswordSet);
// don't attempt to defer handling when a master password is set
// Showing the MP modal as soon as possible minimizes its interference with tab interactions
// See bug 1539091 and bug 1538460.
if (document.visibilityState == "visible" || isMasterPasswordSet) {
this._processDOMInputPasswordAddedEvent(event, topWindow);
} else {
// wait until the document becomes visible before handling this event

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

@ -63,6 +63,7 @@ skip-if = verify
[browser_http_autofill.js]
skip-if = verify
[browser_hidden_document_autofill.js]
skip-if = os == "win" && os_version == "10.0" && debug # bug 1530935
[browser_insecurePasswordConsoleWarning.js]
skip-if = verify
[browser_master_password_autocomplete.js]

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

@ -129,55 +129,46 @@ testUrls.forEach(testUrl => {
});
});
add_task(async function test_defer_autofill_with_masterpassword() {
add_task(async function test_immediate_autofill_with_masterpassword() {
// Set master password prompt timeout to 3s.
// If this test goes intermittent, you likely have to increase this value.
await SpecialPowers.pushPrefEnv({set: [["signon.masterPasswordReprompt.timeout_ms", 3000]]});
LoginTestUtils.masterPassword.enable();
registerCleanupFunction(function() {
LoginTestUtils.masterPassword.enable();
await LoginTestUtils.reloadData();
info(`Have enabled masterPassword, now isLoggedIn? ${Services.logins.isLoggedIn}`);
registerCleanupFunction(async function() {
LoginTestUtils.masterPassword.disable();
await LoginTestUtils.reloadData();
});
let result, tab1Visibility, dialogObserved;
let dialogResult, tab1Visibility, dialogObserved;
// open 2 tabs
const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, INITIAL_URL);
const tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, INITIAL_URL);
info("sanity check by first loading a form into the visible tab");
is(await getDocumentVisibilityState(tab2.linkedBrowser),
"visible", "The second tab should be visible");
result = { wasShown: false };
dialogObserved = observeMasterPasswordDialog(tab2.ownerGlobal, result);
await BrowserTestUtils.loadURI(tab2.linkedBrowser, FORM_URL);
await dialogObserved;
ok(result.wasShown, "Dialog should be shown when form is loaded into a visible document");
info("load a background login form tab with a matching saved login " +
"and wait to see if the master password dialog is shown");
// confirm document is hidden
is(await getDocumentVisibilityState(tab2.linkedBrowser),
"visible", "The second tab should be visible");
tab1Visibility = await getDocumentVisibilityState(tab1.linkedBrowser);
is(tab1Visibility, "hidden", "The first tab should be backgrounded");
result = { wasShown: false };
dialogObserved = observeMasterPasswordDialog(tab1.ownerGlobal, result);
dialogResult = { wasShown: false };
dialogObserved = observeMasterPasswordDialog(tab1.ownerGlobal, dialogResult);
// In this case we will try to autofill while hidden, so look for the passwordmgr-processed-form
// to be observed
await addContentObserver(tab1.linkedBrowser, "passwordmgr-processed-form");
await BrowserTestUtils.loadURI(tab1.linkedBrowser, FORM_URL);
await dialogObserved;
ok(!result.wasShown, "Dialog should not be shown when form is loaded into a hidden document");
let wasProcessed = getContentObserverResult(tab1.linkedBrowser, "passwordmgr-processed-form");
await Promise.all([dialogObserved, wasProcessed]);
info("switch to the form tab " +
"and confirm the master password dialog is then shown");
tab1Visibility = await getDocumentVisibilityState(tab1.linkedBrowser);
is(tab1Visibility, "hidden", "The first tab should be backgrounded");
result = { wasShown: false };
dialogObserved = observeMasterPasswordDialog(tab1.ownerGlobal, result);
await BrowserTestUtils.switchTab(gBrowser, tab1);
await dialogObserved;
tab1Visibility = await getDocumentVisibilityState(tab1.linkedBrowser);
is(tab1Visibility, "visible", "The first tab should be foreground");
ok(result.wasShown, "Dialog should be shown when input's document becomes visible");
ok(wasProcessed, "Observer should be notified when form is loaded into a hidden document");
ok(dialogResult && dialogResult.wasShown, "MP Dialog should be shown when form is loaded into a hidden document");
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);