зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1665802
- Directly migrate importable passwords without wizard for single profile r=sfoster
Share importable handling from LoginManagerParent and support directly migrating. Differential Revision: https://phabricator.services.mozilla.com/D90635
This commit is contained in:
Родитель
d88ac68590
Коммит
9f44cacde2
|
@ -527,7 +527,7 @@ var MigratorPrototype = {
|
|||
},
|
||||
};
|
||||
|
||||
var MigrationUtils = Object.freeze({
|
||||
var MigrationUtils = Object.seal({
|
||||
resourceTypes: {
|
||||
COOKIES: Ci.nsIBrowserProfileMigrator.COOKIES,
|
||||
HISTORY: Ci.nsIBrowserProfileMigrator.HISTORY,
|
||||
|
|
|
@ -796,16 +796,10 @@ let gAutoCompleteListener = {
|
|||
);
|
||||
break;
|
||||
case "importableLogins":
|
||||
loginManager.sendAsyncMessage(
|
||||
"PasswordManager:OpenMigrationWizard",
|
||||
selectedRowComment
|
||||
);
|
||||
Services.telemetry.recordEvent(
|
||||
"exp_import",
|
||||
"event",
|
||||
"enter",
|
||||
selectedRowComment
|
||||
);
|
||||
loginManager.sendAsyncMessage("PasswordManager:HandleImportable", {
|
||||
browserId: selectedRowComment,
|
||||
type: "enter",
|
||||
});
|
||||
break;
|
||||
case "loginsFooter":
|
||||
loginManager.sendAsyncMessage("PasswordManager:OpenPreferences", {
|
||||
|
|
|
@ -599,11 +599,12 @@ this.LoginManagerChild = class LoginManagerChild extends JSWindowActorChild {
|
|||
}
|
||||
|
||||
this._fieldsWithPasswordGenerationForcedOn.add(inputElement);
|
||||
// Clear the cache of previous autocomplete results so that the
|
||||
// generation option appears.
|
||||
gFormFillService.QueryInterface(Ci.nsIAutoCompleteInput);
|
||||
gFormFillService.controller.resetInternalState();
|
||||
gFormFillService.showPopup();
|
||||
this.repopulateAutocompletePopup();
|
||||
break;
|
||||
}
|
||||
|
||||
case "PasswordManager:repopulateAutocompletePopup": {
|
||||
this.repopulateAutocompletePopup();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -620,6 +621,13 @@ this.LoginManagerChild = class LoginManagerChild extends JSWindowActorChild {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
repopulateAutocompletePopup() {
|
||||
// Clear the cache of previous autocomplete results to show new options.
|
||||
gFormFillService.QueryInterface(Ci.nsIAutoCompleteInput);
|
||||
gFormFillService.controller.resetInternalState();
|
||||
gFormFillService.showPopup();
|
||||
}
|
||||
|
||||
shouldIgnoreLoginManagerEvent(event) {
|
||||
let nodePrincipal = event.target.nodePrincipal;
|
||||
// If we have a system or null principal then prevent any more password manager code from running and
|
||||
|
|
|
@ -232,7 +232,7 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
);
|
||||
}
|
||||
|
||||
receiveMessage(msg) {
|
||||
async receiveMessage(msg) {
|
||||
let data = msg.data;
|
||||
if (data.origin || data.formOrigin) {
|
||||
throw new Error(
|
||||
|
@ -313,13 +313,44 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
break;
|
||||
}
|
||||
|
||||
case "PasswordManager:OpenMigrationWizard": {
|
||||
// Open the migration wizard pre-selecting the appropriate browser.
|
||||
let window = this.getRootBrowser().ownerGlobal;
|
||||
MigrationUtils.showMigrationWizard(window, [
|
||||
MigrationUtils.MIGRATION_ENTRYPOINT_PASSWORDS,
|
||||
data,
|
||||
]);
|
||||
case "PasswordManager:HandleImportable": {
|
||||
const { browserId, type } = data;
|
||||
|
||||
// Directly migrate passwords for a single profile.
|
||||
const migrator = await MigrationUtils.getMigrator(browserId);
|
||||
const profiles = await migrator.getSourceProfiles();
|
||||
// TODO: Bug 1666373 Use ExperimentAPI to enable only for treatment.
|
||||
if (profiles.length == 1) {
|
||||
const loginAdded = new Promise(resolve => {
|
||||
const obs = (subject, topic, data) => {
|
||||
if (data == "addLogin") {
|
||||
Services.obs.removeObserver(obs, "passwordmgr-storage-changed");
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(obs, "passwordmgr-storage-changed");
|
||||
});
|
||||
|
||||
await migrator.migrate(
|
||||
MigrationUtils.resourceTypes.PASSWORDS,
|
||||
null,
|
||||
profiles[0]
|
||||
);
|
||||
await loginAdded;
|
||||
|
||||
// Reshow the popup with the imported password.
|
||||
this.sendAsyncMessage("PasswordManager:repopulateAutocompletePopup");
|
||||
} else {
|
||||
// Open the migration wizard pre-selecting the appropriate browser.
|
||||
MigrationUtils.showMigrationWizard(
|
||||
this.getRootBrowser().ownerGlobal,
|
||||
[MigrationUtils.MIGRATION_ENTRYPOINT_PASSWORDS, browserId]
|
||||
);
|
||||
}
|
||||
|
||||
Services.telemetry.recordEvent("exp_import", "event", type, browserId, {
|
||||
profilesCount: profiles.length + "",
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,21 @@ const { MigrationUtils } = ChromeUtils.import(
|
|||
);
|
||||
const { sinon } = ChromeUtils.import("resource://testing-common/Sinon.jsm");
|
||||
|
||||
// Dummy migrator to change and detect importable behavior.
|
||||
const gTestMigrator = {
|
||||
profiles: [],
|
||||
|
||||
getSourceProfiles() {
|
||||
return this.profiles;
|
||||
},
|
||||
|
||||
migrate: sinon
|
||||
.stub()
|
||||
.callsFake(() =>
|
||||
LoginTestUtils.addLogin({ username: "import", password: "pass" })
|
||||
),
|
||||
};
|
||||
|
||||
add_task(async function check_fluent_ids() {
|
||||
await document.l10n.ready;
|
||||
MozXULElement.insertFTLIfNeeded("toolkit/main-window/autocomplete.ftl");
|
||||
|
@ -28,13 +43,17 @@ add_task(async function test_initialize() {
|
|||
const importable = sinon
|
||||
.stub(ChromeMigrationUtils, "getImportableLogins")
|
||||
.resolves(["chrome"]);
|
||||
const migrator = sinon
|
||||
.stub(MigrationUtils, "getMigrator")
|
||||
.resolves(gTestMigrator);
|
||||
|
||||
// This makes the third autocomplete test *not* show import suggestions.
|
||||
Services.prefs.setIntPref("signon.suggestImportCount", 2);
|
||||
// This makes the last autocomplete test *not* show import suggestions.
|
||||
Services.prefs.setIntPref("signon.suggestImportCount", 3);
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
debounce.restore();
|
||||
importable.restore();
|
||||
migrator.restore();
|
||||
Services.prefs.clearUserPref("signon.suggestImportCount");
|
||||
});
|
||||
});
|
||||
|
@ -60,6 +79,9 @@ add_task(async function import_suggestion_wizard() {
|
|||
"Wait for importable suggestion to show"
|
||||
);
|
||||
|
||||
// Pretend there's 2+ profiles to trigger the wizard.
|
||||
gTestMigrator.profiles.length = 2;
|
||||
|
||||
info("Clicking on importable suggestion");
|
||||
const wizardPromise = BrowserTestUtils.waitForCondition(
|
||||
() => Services.wm.getMostRecentWindow("Browser:MigrationWizard"),
|
||||
|
@ -71,6 +93,7 @@ add_task(async function import_suggestion_wizard() {
|
|||
|
||||
const wizard = await wizardPromise;
|
||||
ok(wizard, "Wizard opened");
|
||||
is(gTestMigrator.migrate.callCount, 0, "Direct migrate not used");
|
||||
|
||||
await closePopup(popup);
|
||||
await BrowserTestUtils.closeWindow(wizard);
|
||||
|
@ -113,6 +136,58 @@ add_task(async function import_suggestion_learn_more() {
|
|||
);
|
||||
});
|
||||
|
||||
add_task(async function import_suggestion_migrate() {
|
||||
await BrowserTestUtils.withNewTab(
|
||||
{
|
||||
gBrowser,
|
||||
url: "https://example.com" + DIRECTORY_PATH + "form_basic.html",
|
||||
},
|
||||
async function(browser) {
|
||||
const popup = document.getElementById("PopupAutoComplete");
|
||||
ok(popup, "Got popup");
|
||||
await openACPopup(popup, browser, "#form-basic-username");
|
||||
|
||||
const importableItem = popup.querySelector(
|
||||
`[originaltype="importableLogins"]`
|
||||
);
|
||||
ok(importableItem, "Got importable suggestion richlistitem");
|
||||
|
||||
await BrowserTestUtils.waitForCondition(
|
||||
() => !importableItem.collapsed,
|
||||
"Wait for importable suggestion to show"
|
||||
);
|
||||
|
||||
// Pretend there's 1 profile to trigger migrate.
|
||||
gTestMigrator.profiles.length = 1;
|
||||
|
||||
info("Clicking on importable suggestion");
|
||||
const migratePromise = BrowserTestUtils.waitForCondition(
|
||||
() => gTestMigrator.migrate.callCount,
|
||||
"Wait for direct migration attempt"
|
||||
);
|
||||
EventUtils.synthesizeMouseAtCenter(importableItem, {});
|
||||
|
||||
const callCount = await migratePromise;
|
||||
is(callCount, 1, "Direct migrate used once");
|
||||
|
||||
const importedItem = await BrowserTestUtils.waitForCondition(
|
||||
() => popup.querySelector(`[originaltype="loginWithOrigin"]`),
|
||||
"Wait for imported login to show"
|
||||
);
|
||||
EventUtils.synthesizeMouseAtCenter(importedItem, {});
|
||||
|
||||
const username = await SpecialPowers.spawn(
|
||||
browser,
|
||||
[],
|
||||
() => content.document.getElementById("form-basic-username").value
|
||||
);
|
||||
is(username, "import", "username from import filled in");
|
||||
|
||||
LoginTestUtils.clearData();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function import_suggestion_not_shown() {
|
||||
await BrowserTestUtils.withNewTab(
|
||||
{
|
||||
|
|
|
@ -298,6 +298,8 @@ exp_import:
|
|||
description: >
|
||||
Experimental import logins interface user interactions. Value is the browser suggested.
|
||||
expiry_version: "87"
|
||||
extra_keys:
|
||||
profilesCount: Count of profiles found for the selected browser
|
||||
notification_emails: ["edilee@mozilla.com"]
|
||||
products: ["firefox"]
|
||||
record_in_processes: ["main", "content"]
|
||||
|
|
|
@ -781,29 +781,21 @@
|
|||
super();
|
||||
MozXULElement.insertFTLIfNeeded("toolkit/main-window/autocomplete.ftl");
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"MigrationUtils",
|
||||
"resource:///modules/MigrationUtils.jsm"
|
||||
);
|
||||
|
||||
this.addEventListener("click", event => {
|
||||
const browserId = this.getAttribute("ac-value");
|
||||
if (event.button != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Open the migration wizard pre-selecting the appropriate browser.
|
||||
this.MigrationUtils.showMigrationWizard(window, [
|
||||
this.MigrationUtils.MIGRATION_ENTRYPOINT_PASSWORDS,
|
||||
browserId,
|
||||
]);
|
||||
Services.telemetry.recordEvent(
|
||||
"exp_import",
|
||||
"event",
|
||||
"click",
|
||||
browserId
|
||||
);
|
||||
// Let the login manager parent handle this importable browser click.
|
||||
gBrowser.selectedBrowser.browsingContext.currentWindowGlobal
|
||||
.getActor("LoginManager")
|
||||
.receiveMessage({
|
||||
name: "PasswordManager:HandleImportable",
|
||||
data: {
|
||||
browserId: this.getAttribute("ac-value"),
|
||||
type: "click",
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче