Bug 1883337 - Ensure focus is moved when mute/unmute button is removed in Fx View r=fxview-reviewers,nsharpley,jsudiaman

Differential Revision: https://phabricator.services.mozilla.com/D203484
This commit is contained in:
Kelly Cochrane 2024-03-05 15:49:24 +00:00
parent ce9ffe8103
commit 4356fdde79
11 changed files with 119 additions and 85 deletions

View File

@ -718,7 +718,26 @@ export class FxviewTabRow extends MozLitElement {
}
}
muteOrUnmuteTab() {
muteOrUnmuteTab(e) {
e?.preventDefault();
// If the tab has no sound playing, the mute/unmute button will be removed when toggled.
// We should move the focus to the right in that case. This does not apply to pinned tabs
// on the Open Tabs page.
let shouldMoveFocus =
(!this.pinnedTabsGridView ||
(!this.indicators.includes("pinned") && this.pinnedTabsGridView)) &&
this.mediaButtonEl &&
!this.indicators.includes("soundplaying") &&
this.currentActiveElementId === "fxview-tab-row-media-button";
if (e?.type === "keydown" && shouldMoveFocus) {
let tabList = this.getRootNode().host;
if (document.dir == "rtl") {
tabList.moveFocusLeft(this);
} else {
tabList.moveFocusRight(this);
}
}
this.tabElement.toggleMuteAudio();
}
@ -880,6 +899,7 @@ export class FxviewTabRow extends MozLitElement {
!this.indicators?.includes("muted")
}
@click=${this.muteOrUnmuteTab}
@keydown=${this.muteOrUnmuteTab}
tabindex="${
this.active &&
this.currentActiveElementId === "fxview-tab-row-media-button"

View File

@ -5,9 +5,6 @@ const tabURL1 = "data:,Tab1";
const tabURL2 = "data:,Tab2";
const tabURL3 = "data:,Tab3";
const { NonPrivateTabs } = ChromeUtils.importESModule(
"resource:///modules/OpenTabs.sys.mjs"
);
const TestTabs = {};
function getTopLevelViewElements(document) {

View File

@ -55,12 +55,6 @@ function triggerClickOn(target, options) {
return promise;
}
async function add_new_tab(URL) {
let tab = BrowserTestUtils.addTab(gBrowser, URL);
await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
return tab;
}
add_task(async function aria_attributes() {
let win = await BrowserTestUtils.openNewBrowserWindow();
is(

View File

@ -7,9 +7,6 @@ const ROW_DATE_ID = "fxview-tab-row-date";
let gInitialTab;
let gInitialTabURL;
const { NonPrivateTabs } = ChromeUtils.importESModule(
"resource:///modules/OpenTabs.sys.mjs"
);
add_setup(function () {
// This test opens a lot of windows and tabs and might run long on slower configurations

View File

@ -1,4 +1,4 @@
const { NonPrivateTabs, getTabsTargetForWindow } = ChromeUtils.importESModule(
const { getTabsTargetForWindow } = ChromeUtils.importESModule(
"resource:///modules/OpenTabs.sys.mjs"
);
let privateTabsChanges;

View File

@ -20,27 +20,11 @@ const fxaDevicesWithCommands = [
},
];
const { NonPrivateTabs } = ChromeUtils.importESModule(
"resource:///modules/OpenTabs.sys.mjs"
);
async function getRowsForCard(card) {
await TestUtils.waitForCondition(() => card.tabList.rowEls.length);
return card.tabList.rowEls;
}
async function add_new_tab(URL) {
let tabChangeRaised = BrowserTestUtils.waitForEvent(
NonPrivateTabs,
"TabChange"
);
let tab = BrowserTestUtils.addTab(gBrowser, URL);
// wait so we can reliably compare the tab URL
await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
await tabChangeRaised;
return tab;
}
function getVisibleTabURLs(win = window) {
return win.gBrowser.visibleTabs.map(tab => tab.linkedBrowser.currentURI.spec);
}

View File

@ -1,10 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const { NonPrivateTabs } = ChromeUtils.importESModule(
"resource:///modules/OpenTabs.sys.mjs"
);
let pageWithAlert =
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
"http://example.com/browser/browser/base/content/test/tabPrompts/openPromptOffTimeout.html";
@ -18,22 +14,6 @@ function cleanup() {
}
}
function isActiveElement(expectedLinkEl) {
return expectedLinkEl.getRootNode().activeElement == expectedLinkEl;
}
async function add_new_tab(URL) {
let tabChangeRaised = BrowserTestUtils.waitForEvent(
NonPrivateTabs,
"TabChange"
);
let tab = BrowserTestUtils.addTab(gBrowser, URL);
// wait so we can reliably compare the tab URL
await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
await tabChangeRaised;
return tab;
}
const arrowDown = async tabList => {
info("Arrow down");
EventUtils.synthesizeKey("KEY_ArrowDown", {});
@ -170,9 +150,8 @@ add_task(async function test_pin_unpin_open_tab() {
await tabChangeRaised;
await openTabs.updateComplete;
await telemetryEvent(contextMenuEvent);
cleanup();
});
cleanup();
});
add_task(async function test_indicator_pinned_tabs_with_keyboard() {
@ -320,8 +299,8 @@ add_task(async function test_indicator_pinned_tabs_with_keyboard() {
// Switch back to other tab to close prompt before cleanup
await BrowserTestUtils.switchTab(gBrowser, openedTab);
EventUtils.synthesizeKey("KEY_Enter", {});
cleanup();
});
cleanup();
});
add_task(async function test_mute_unmute_pinned_tab() {
@ -375,9 +354,8 @@ add_task(async function test_mute_unmute_pinned_tab() {
await TestUtils.waitForCondition(
() => !unmutedTab.indicators.includes("muted")
);
cleanup();
});
cleanup();
});
add_task(async function test_mute_unmute_with_context_menu() {
@ -482,7 +460,6 @@ add_task(async function test_mute_unmute_with_context_menu() {
await TestUtils.waitForCondition(
() => !unmutedTab.indicators.includes("muted")
);
cleanup();
});
cleanup();
});

View File

@ -13,9 +13,6 @@ const tabURL4 = "data:,Tab4";
let gInitialTab;
let gInitialTabURL;
const { NonPrivateTabs } = ChromeUtils.importESModule(
"resource:///modules/OpenTabs.sys.mjs"
);
add_setup(function () {
gInitialTab = gBrowser.selectedTab;

View File

@ -3,23 +3,12 @@
requestLongerTimeout(2);
const { NonPrivateTabs } = ChromeUtils.importESModule(
"resource:///modules/OpenTabs.sys.mjs"
);
let pageWithAlert =
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
"http://example.com/browser/browser/base/content/test/tabPrompts/openPromptOffTimeout.html";
let pageWithSound =
"http://mochi.test:8888/browser/dom/base/test/file_audioLoop.html";
function cleanup() {
// Cleanup
while (gBrowser.tabs.length > 1) {
BrowserTestUtils.removeTab(gBrowser.tabs[0]);
}
}
add_task(async function test_notification_dot_indicator() {
clearHistory();
await withFirefoxView({}, async browser => {
@ -62,7 +51,7 @@ add_task(async function test_notification_dot_indicator() {
await BrowserTestUtils.switchTab(gBrowser, openedTab);
EventUtils.synthesizeKey("KEY_Enter", {}, win);
cleanup();
cleanupTabs();
});
});
@ -120,7 +109,7 @@ add_task(async function test_container_indicator() {
info("The newly opened tab is marked as a container tab.");
cleanup();
cleanupTabs();
});
});
@ -222,7 +211,7 @@ add_task(async function test_sound_playing_muted_indicator() {
"The tab has the unmute button showing."
);
cleanup();
cleanupTabs();
});
});
@ -287,6 +276,6 @@ add_task(async function test_bookmark_indicator() {
"The bookmark star is removed."
);
});
await cleanup();
await cleanupTabs();
await PlacesUtils.bookmarks.eraseEverything();
});

View File

@ -1,6 +1,5 @@
const { NonPrivateTabs } = ChromeUtils.importESModule(
"resource:///modules/OpenTabs.sys.mjs"
);
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(async function test_open_tab_row_navigation() {
await withFirefoxView({}, async browser => {
@ -59,9 +58,66 @@ add_task(async function test_open_tab_row_navigation() {
info("The tab row main element has focus.");
});
while (gBrowser.tabs.length > 1) {
BrowserTestUtils.removeTab(gBrowser.tabs[0]);
}
cleanupTabs();
});
add_task(async function test_focus_moves_after_unmute() {
await withFirefoxView({}, async browser => {
const { document } = browser.contentWindow;
let win = browser.ownerGlobal;
await navigateToViewAndWait(document, "opentabs");
let openTabs = document.querySelector("view-opentabs[name=opentabs]");
await openTabs.updateComplete;
await TestUtils.waitForCondition(
() => openTabs.viewCards[0].tabList.rowEls.length,
"The tab list has rendered."
);
await openTabs.openTabsTarget.readyWindowsPromise;
let card = openTabs.viewCards[0];
let openTabEl = card.tabList.rowEls[0];
let tabChangeRaised = BrowserTestUtils.waitForEvent(
NonPrivateTabs,
"TabChange"
);
// Mute tab
openTabEl.muteOrUnmuteTab();
await tabChangeRaised;
await openTabs.updateComplete;
let mutedTab = card.tabList.rowEls[0];
await TestUtils.waitForCondition(
() => mutedTab.indicators.includes("muted"),
"The tab has been muted."
);
// Unmute using keyboard
card.tabList.currentActiveElementId = mutedTab.focusMediaButton();
isActiveElement(mutedTab.mediaButtonEl);
info("The media button has focus.");
tabChangeRaised = BrowserTestUtils.waitForEvent(
NonPrivateTabs,
"TabChange"
);
EventUtils.synthesizeKey("KEY_Enter", {}, win);
await tabChangeRaised;
await openTabs.updateComplete;
let unmutedTab = card.tabList.rowEls[0];
await TestUtils.waitForCondition(
() => !unmutedTab.indicators.includes("muted"),
"The tab is no longer muted."
);
isActiveElement(unmutedTab.secondaryButtonEl);
info(
"Focus should be on the tab's secondary button element after unmuting."
);
});
cleanupTabs();
});
add_task(async function test_open_tab_row_with_sound_navigation() {
@ -89,7 +145,7 @@ add_task(async function test_open_tab_row_with_sound_navigation() {
await TestUtils.waitForCondition(
() => openTabs.viewCards[0].tabList?.rowEls.length === 2,
"The tab list hasn't rendered"
"The tab list has rendered."
);
// Focus tab row with sound playing
@ -163,7 +219,5 @@ add_task(async function test_open_tab_row_with_sound_navigation() {
info("The tab row main element has focus.");
});
while (gBrowser.tabs.length > 1) {
BrowserTestUtils.removeTab(gBrowser.tabs[0]);
}
cleanupTabs();
});

View File

@ -31,6 +31,9 @@ const { FeatureCalloutMessages } = ChromeUtils.importESModule(
const { TelemetryTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/TelemetryTestUtils.sys.mjs"
);
const { NonPrivateTabs } = ChromeUtils.importESModule(
"resource:///modules/OpenTabs.sys.mjs"
);
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
const { SessionStoreTestUtils } = ChromeUtils.importESModule(
@ -694,3 +697,25 @@ async function waitForRecentlyClosedTabsList(doc) {
});
return [cardMainSlotNode, cardMainSlotNode.rowEls];
}
async function add_new_tab(URL) {
let tabChangeRaised = BrowserTestUtils.waitForEvent(
NonPrivateTabs,
"TabChange"
);
let tab = BrowserTestUtils.addTab(gBrowser, URL);
// wait so we can reliably compare the tab URL
await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
await tabChangeRaised;
return tab;
}
function isActiveElement(expectedLinkEl) {
return expectedLinkEl.getRootNode().activeElement == expectedLinkEl;
}
function cleanupTabs() {
while (gBrowser.tabs.length > 1) {
BrowserTestUtils.removeTab(gBrowser.tabs[0]);
}
}