diff --git a/browser/components/migration/content/migration-wizard.mjs b/browser/components/migration/content/migration-wizard.mjs index 89872a155875..9d58fbe95f1d 100644 --- a/browser/components/migration/content/migration-wizard.mjs +++ b/browser/components/migration/content/migration-wizard.mjs @@ -333,6 +333,7 @@ export class MigrationWizard extends HTMLElement { this.#getPermissionsButton.addEventListener("click", this); this.#browserProfileSelector.addEventListener("click", this); + this.#browserProfileSelector.addEventListener("mousedown", this); this.#resourceTypeList = shadow.querySelector("#resource-type-list"); this.#resourceTypeList.addEventListener("change", this); @@ -1396,107 +1397,122 @@ export class MigrationWizard extends HTMLElement { } } + #handleClickEvent(event) { + if ( + event.target == this.#importButton || + event.target == this.#importFromFileButton + ) { + this.#doImport(); + } else if ( + event.target.classList.contains("cancel-close") || + event.target.classList.contains("finish-button") + ) { + this.dispatchEvent( + new CustomEvent("MigrationWizard:Close", { bubbles: true }) + ); + } else if ( + event.currentTarget == this.#browserProfileSelectorList && + event.target != this.#browserProfileSelectorList + ) { + this.#onBrowserProfileSelectionChanged(event.target); + // If the user selected a file migration type from the selector, we'll + // help the user out by immediately starting the file migration flow, + // rather than waiting for them to click the "Select File". + if ( + event.target.getAttribute("type") == + MigrationWizardConstants.MIGRATOR_TYPES.FILE + ) { + this.#doImport(); + } + } else if (event.target == this.#safariPermissionButton) { + this.#requestSafariPermissions(); + } else if (event.currentTarget == this.#resourceSummary) { + this.#expandedDetails = true; + } else if (event.target == this.#chooseImportFromFile) { + this.dispatchEvent( + new CustomEvent("MigrationWizard:RequestState", { + bubbles: true, + detail: { + allowOnlyFileMigrators: true, + }, + }) + ); + } else if (event.target == this.#safariPasswordImportSkipButton) { + // If the user chose to skip importing passwords from Safari, we + // programmatically uncheck the PASSWORDS resource type and re-request + // import. + let checkbox = this.#shadowRoot.querySelector( + `label[data-resource-type="${MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.PASSWORDS}"]` + ).control; + checkbox.checked = false; + + // If there are no other checked checkboxes, go back to the selection + // screen. + let checked = this.#shadowRoot.querySelectorAll( + `label[data-resource-type] > input:checked` + ).length; + + if (!checked) { + this.requestState(); + } else { + this.#doImport(); + } + } else if (event.target == this.#safariPasswordImportSelectButton) { + this.#selectSafariPasswordFile(); + } else if (event.target == this.#extensionsSuccessLink) { + this.dispatchEvent( + new CustomEvent("MigrationWizard:OpenAboutAddons", { + bubbles: true, + }) + ); + event.preventDefault(); + } else if (event.target == this.#getPermissionsButton) { + this.#getPermissions(); + } + } + + #handleChangeEvent(event) { + if (event.target == this.#browserProfileSelector) { + this.#onBrowserProfileSelectionChanged(); + } else if (event.target == this.#selectAllCheckbox) { + let checkboxes = this.#shadowRoot.querySelectorAll( + 'label[data-resource-type]:not([hidden]) > input[type="checkbox"]' + ); + for (let checkbox of checkboxes) { + checkbox.checked = this.#selectAllCheckbox.checked; + } + this.#displaySelectedResources(); + } else { + let checkboxes = this.#shadowRoot.querySelectorAll( + 'label[data-resource-type]:not([hidden]) > input[type="checkbox"]' + ); + + let allVisibleChecked = Array.from(checkboxes).every(checkbox => { + return checkbox.checked; + }); + + this.#selectAllCheckbox.checked = allVisibleChecked; + this.#displaySelectedResources(); + } + } + handleEvent(event) { + if ( + event.target == this.#browserProfileSelector && + (event.type == "mousedown" || + (event.type == "click" && + event.mozInputSource == MouseEvent.MOZ_SOURCE_KEYBOARD)) + ) { + this.#browserProfileSelectorList.toggle(event); + return; + } switch (event.type) { case "click": { - if ( - event.target == this.#importButton || - event.target == this.#importFromFileButton - ) { - this.#doImport(); - } else if ( - event.target.classList.contains("cancel-close") || - event.target.classList.contains("finish-button") - ) { - this.dispatchEvent( - new CustomEvent("MigrationWizard:Close", { bubbles: true }) - ); - } else if (event.target == this.#browserProfileSelector) { - this.#browserProfileSelectorList.show(event); - } else if ( - event.currentTarget == this.#browserProfileSelectorList && - event.target != this.#browserProfileSelectorList - ) { - this.#onBrowserProfileSelectionChanged(event.target); - // If the user selected a file migration type from the selector, we'll - // help the user out by immediately starting the file migration flow, - // rather than waiting for them to click the "Select File". - if ( - event.target.getAttribute("type") == - MigrationWizardConstants.MIGRATOR_TYPES.FILE - ) { - this.#doImport(); - } - } else if (event.target == this.#safariPermissionButton) { - this.#requestSafariPermissions(); - } else if (event.currentTarget == this.#resourceSummary) { - this.#expandedDetails = true; - } else if (event.target == this.#chooseImportFromFile) { - this.dispatchEvent( - new CustomEvent("MigrationWizard:RequestState", { - bubbles: true, - detail: { - allowOnlyFileMigrators: true, - }, - }) - ); - } else if (event.target == this.#safariPasswordImportSkipButton) { - // If the user chose to skip importing passwords from Safari, we - // programmatically uncheck the PASSWORDS resource type and re-request - // import. - let checkbox = this.#shadowRoot.querySelector( - `label[data-resource-type="${MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.PASSWORDS}"]` - ).control; - checkbox.checked = false; - - // If there are no other checked checkboxes, go back to the selection - // screen. - let checked = this.#shadowRoot.querySelectorAll( - `label[data-resource-type] > input:checked` - ).length; - - if (!checked) { - this.requestState(); - } else { - this.#doImport(); - } - } else if (event.target == this.#safariPasswordImportSelectButton) { - this.#selectSafariPasswordFile(); - } else if (event.target == this.#extensionsSuccessLink) { - this.dispatchEvent( - new CustomEvent("MigrationWizard:OpenAboutAddons", { - bubbles: true, - }) - ); - event.preventDefault(); - } else if (event.target == this.#getPermissionsButton) { - this.#getPermissions(); - } + this.#handleClickEvent(event); break; } case "change": { - if (event.target == this.#browserProfileSelector) { - this.#onBrowserProfileSelectionChanged(); - } else if (event.target == this.#selectAllCheckbox) { - let checkboxes = this.#shadowRoot.querySelectorAll( - 'label[data-resource-type]:not([hidden]) > input[type="checkbox"]' - ); - for (let checkbox of checkboxes) { - checkbox.checked = this.#selectAllCheckbox.checked; - } - this.#displaySelectedResources(); - } else { - let checkboxes = this.#shadowRoot.querySelectorAll( - 'label[data-resource-type]:not([hidden]) > input[type="checkbox"]' - ); - - let allVisibleChecked = Array.from(checkboxes).every(checkbox => { - return checkbox.checked; - }); - - this.#selectAllCheckbox.checked = allVisibleChecked; - this.#displaySelectedResources(); - } + this.#handleChangeEvent(event); break; } } diff --git a/browser/components/migration/tests/browser/browser_disabled_migrator.js b/browser/components/migration/tests/browser/browser_disabled_migrator.js index 782666f6a6a7..a9a6b3083c59 100644 --- a/browser/components/migration/tests/browser/browser_disabled_migrator.js +++ b/browser/components/migration/tests/browser/browser_disabled_migrator.js @@ -17,7 +17,7 @@ add_task(async function test_enabled_migrator() { let wizard = dialog.querySelector("migration-wizard"); let shadow = wizard.openOrClosedShadowRoot; let selector = shadow.querySelector("#browser-profile-selector"); - selector.click(); + EventUtils.synthesizeMouseAtCenter(selector, {}, prefsWin); await new Promise(resolve => { shadow @@ -78,7 +78,7 @@ add_task(async function test_disabling_migrator() { let wizard = dialog.querySelector("migration-wizard"); let shadow = wizard.openOrClosedShadowRoot; let selector = shadow.querySelector("#browser-profile-selector"); - selector.click(); + EventUtils.synthesizeMouseAtCenter(selector, {}, prefsWin); await new Promise(resolve => { shadow diff --git a/browser/components/migration/tests/browser/browser_do_migration.js b/browser/components/migration/tests/browser/browser_do_migration.js index fab9641960a7..74454c0ab1b2 100644 --- a/browser/components/migration/tests/browser/browser_do_migration.js +++ b/browser/components/migration/tests/browser/browser_do_migration.js @@ -106,7 +106,7 @@ add_task(async function test_successful_migrations() { ); let dialogClosed = BrowserTestUtils.waitForEvent(dialog, "close"); - doneButton.click(); + EventUtils.synthesizeMouseAtCenter(doneButton, {}, prefsWin); await dialogClosed; assertQuantitiesShown(wizard, [ MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES.PASSWORDS, diff --git a/browser/components/migration/tests/browser/browser_file_migration.js b/browser/components/migration/tests/browser/browser_file_migration.js index c73dfc445608..94f4ff2908f8 100644 --- a/browser/components/migration/tests/browser/browser_file_migration.js +++ b/browser/components/migration/tests/browser/browser_file_migration.js @@ -132,7 +132,7 @@ add_task(async function test_file_migration() { // Now select our DummyFileMigrator from the list. let selector = shadow.querySelector("#browser-profile-selector"); - selector.click(); + EventUtils.synthesizeMouseAtCenter(selector, {}, prefsWin); info("Waiting for panel-list shown"); await new Promise(resolve => { @@ -246,7 +246,7 @@ add_task(async function test_file_migration_error() { // Now select our DummyFileMigrator from the list. let selector = shadow.querySelector("#browser-profile-selector"); - selector.click(); + EventUtils.synthesizeMouseAtCenter(selector, {}, prefsWin); info("Waiting for panel-list shown"); await new Promise(resolve => { diff --git a/browser/components/migration/tests/browser/head.js b/browser/components/migration/tests/browser/head.js index d3d188a7e1f6..8824a50ee98f 100644 --- a/browser/components/migration/tests/browser/head.js +++ b/browser/components/migration/tests/browser/head.js @@ -332,7 +332,7 @@ async function selectResourceTypesAndStartMigration( // First, select the InternalTestingProfileMigrator browser. let selector = shadow.querySelector("#browser-profile-selector"); - selector.click(); + EventUtils.synthesizeMouseAtCenter(selector, {}, wizard.ownerGlobal); await new Promise(resolve => { shadow diff --git a/browser/components/migration/tests/chrome/test_migration_wizard.html b/browser/components/migration/tests/chrome/test_migration_wizard.html index cc2d8a036347..43fd3ab9312e 100644 --- a/browser/components/migration/tests/chrome/test_migration_wizard.html +++ b/browser/components/migration/tests/chrome/test_migration_wizard.html @@ -147,7 +147,7 @@ // Test that the resource type checkboxes are shown or hidden depending on // which resourceTypes are included with the MigratorProfileInstance. for (let migratorInstance of MIGRATOR_PROFILE_INSTANCES) { - selector.click(); + synthesizeMouseAtCenter(selector, {}, gWiz.ownerGlobal); await new Promise(resolve => { gShadowRoot .querySelector("panel-list") @@ -248,7 +248,7 @@ ok(isHidden(preamble), "preamble should be hidden."); let selector = gShadowRoot.querySelector("#browser-profile-selector"); - selector.click(); + synthesizeMouseAtCenter(selector, {}, gWiz.ownerGlobal); await new Promise(resolve => { let panelList = gShadowRoot.querySelector("panel-list"); if (panelList) { diff --git a/toolkit/content/widgets/panel-list/panel-list.js b/toolkit/content/widgets/panel-list/panel-list.js index 2e93b4ddc3e4..a2b6cb1a009e 100644 --- a/toolkit/content/widgets/panel-list/panel-list.js +++ b/toolkit/content/widgets/panel-list/panel-list.js @@ -439,10 +439,6 @@ // using the mouse. Ignore the first focusin event if it's on the // triggering target. this.focusHasChanged = true; - } else if (!target || !inPanelList) { - // If the target isn't in the panel, hide. This will close when focus - // moves out of the panel. - this.hide(); } else { // Just record that there was a focusin event. this.focusHasChanged = true;