/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; gReduceMotionOverride = true; function enterCustomizationMode(win = window) { let customizationReadyPromise = BrowserTestUtils.waitForEvent( win.gNavToolbox, "customizationready" ); win.gCustomizeMode.enter(); return customizationReadyPromise; } function leaveCustomizationMode(win = window) { let customizationDonePromise = BrowserTestUtils.waitForEvent( win.gNavToolbox, "aftercustomization" ); win.gCustomizeMode.exit(); return customizationDonePromise; } Services.prefs.setBoolPref("browser.uiCustomization.skipSourceNodeCheck", true); registerCleanupFunction(() => { CustomizableUI.reset(); Services.prefs.clearUserPref("browser.uiCustomization.skipSourceNodeCheck"); }); // Stolen from browser/components/customizableui/tests/browser/head.js function simulateItemDrag(aToDrag, aTarget, aEvent = {}, aOffset = 2) { let ev = aEvent; if (ev == "end" || ev == "start") { let win = aTarget.ownerGlobal; const dwu = win.windowUtils; let bounds = dwu.getBoundsWithoutFlushing(aTarget); if (ev == "end") { ev = { clientX: bounds.right - aOffset, clientY: bounds.bottom - aOffset, }; } else { ev = { clientX: bounds.left + aOffset, clientY: bounds.top + aOffset }; } } ev._domDispatchOnly = true; EventUtils.synthesizeDrop( aToDrag.parentNode, aTarget, null, null, aToDrag.ownerGlobal, aTarget.ownerGlobal, ev ); // Ensure dnd suppression is cleared. EventUtils.synthesizeMouseAtCenter( aTarget, { type: "mouseup" }, aTarget.ownerGlobal ); } function organizeToolbars(state = {}) { // Set up the defaults for the state. let targetState = Object.assign( { // Areas where widgets can be placed, set to an array of widget IDs. "toolbar-menubar": undefined, PersonalToolbar: undefined, TabsToolbar: ["tabbrowser-tabs", "alltabs-button"], "widget-overflow-fixed-list": undefined, "nav-bar": ["back-button", "forward-button", "urlbar-container"], // The page action's that should be in the URL bar. pageActionsInUrlBar: [], // Areas to show or hide. titlebarVisible: false, menubarVisible: false, personalToolbarVisible: false, }, state ); for (let area of CustomizableUI.areas) { // Clear out anything there already. for (let widgetId of CustomizableUI.getWidgetIdsInArea(area)) { CustomizableUI.removeWidgetFromArea(widgetId); } if (targetState[area]) { // We specify the position explicitly to support the toolbars that have // fixed widgets. let position = 0; for (let widgetId of targetState[area]) { CustomizableUI.addWidgetToArea(widgetId, area, position++); } } } CustomizableUI.setToolbarVisibility( "toolbar-menubar", targetState.menubarVisible ); CustomizableUI.setToolbarVisibility( "PersonalToolbar", targetState.personalToolbarVisible ); Services.prefs.setIntPref( "browser.tabs.inTitlebar", !targetState.titlebarVisible ); for (let action of PageActions.actions) { action.pinnedToUrlbar = targetState.pageActionsInUrlBar.includes(action.id); } // Clear out the existing telemetry. Services.telemetry.getSnapshotForKeyedScalars("main", true); } function assertVisibilityScalars(expected) { let scalars = Services.telemetry.getSnapshotForKeyedScalars("main", true)?.parent?.[ "browser.ui.toolbar_widgets" ] ?? {}; // Only some platforms have the menubar items. if (AppConstants.MENUBAR_CAN_AUTOHIDE) { expected.push("menubar-items_pinned_menu-bar"); } let keys = new Set(expected.concat(Object.keys(scalars))); for (let key of keys) { Assert.ok(expected.includes(key), `Scalar key ${key} was unexpected.`); Assert.ok(scalars[key], `Expected to see see scalar key ${key} be true.`); } } function assertCustomizeScalars(expected) { let scalars = Services.telemetry.getSnapshotForKeyedScalars("main", true)?.parent?.[ "browser.ui.customized_widgets" ] ?? {}; let keys = new Set(Object.keys(expected).concat(Object.keys(scalars))); for (let key of keys) { Assert.equal( scalars[key], expected[key], `Expected to see the correct value for scalar ${key}.` ); } } add_task(async function widgetPositions() { organizeToolbars(); BrowserUsageTelemetry._recordUITelemetry(); assertVisibilityScalars([ "menu-toolbar_pinned_off", "titlebar_pinned_off", "bookmarks-bar_pinned_off", "tabbrowser-tabs_pinned_tabs-bar", "alltabs-button_pinned_tabs-bar", "unified-extensions-button_pinned_nav-bar-end", "forward-button_pinned_nav-bar-start", "back-button_pinned_nav-bar-start", ]); organizeToolbars({ PersonalToolbar: [ "fxa-toolbar-menu-button", "new-tab-button", "developer-button", ], TabsToolbar: [ "stop-reload-button", "tabbrowser-tabs", "personal-bookmarks", ], "nav-bar": [ "home-button", "forward-button", "downloads-button", "urlbar-container", "back-button", "library-button", ], personalToolbarVisible: true, }); BrowserUsageTelemetry._recordUITelemetry(); assertVisibilityScalars([ "menu-toolbar_pinned_off", "titlebar_pinned_off", "bookmarks-bar_pinned_on", "tabbrowser-tabs_pinned_tabs-bar", "stop-reload-button_pinned_tabs-bar", "personal-bookmarks_pinned_tabs-bar", "alltabs-button_pinned_tabs-bar", "home-button_pinned_nav-bar-start", "forward-button_pinned_nav-bar-start", "downloads-button_pinned_nav-bar-start", "back-button_pinned_nav-bar-end", "library-button_pinned_nav-bar-end", "unified-extensions-button_pinned_nav-bar-end", "fxa-toolbar-menu-button_pinned_bookmarks-bar", "new-tab-button_pinned_bookmarks-bar", "developer-button_pinned_bookmarks-bar", ]); CustomizableUI.reset(); }); add_task(async function customizeMode() { // Create a default state. organizeToolbars({ PersonalToolbar: ["personal-bookmarks"], TabsToolbar: ["tabbrowser-tabs", "new-tab-button"], "nav-bar": [ "back-button", "forward-button", "stop-reload-button", "urlbar-container", "home-button", "library-button", ], }); BrowserUsageTelemetry._recordUITelemetry(); assertVisibilityScalars([ "menu-toolbar_pinned_off", "titlebar_pinned_off", "bookmarks-bar_pinned_off", "tabbrowser-tabs_pinned_tabs-bar", "new-tab-button_pinned_tabs-bar", "alltabs-button_pinned_tabs-bar", "back-button_pinned_nav-bar-start", "forward-button_pinned_nav-bar-start", "stop-reload-button_pinned_nav-bar-start", "home-button_pinned_nav-bar-end", "library-button_pinned_nav-bar-end", "unified-extensions-button_pinned_nav-bar-end", "personal-bookmarks_pinned_bookmarks-bar", ]); let win = await BrowserTestUtils.openNewBrowserWindow(); await enterCustomizationMode(win); let toolbarButton = win.document.getElementById( "customization-toolbar-visibility-button" ); let toolbarPopup = win.document.getElementById("customization-toolbar-menu"); let popupShown = BrowserTestUtils.waitForEvent(toolbarPopup, "popupshown"); EventUtils.synthesizeMouseAtCenter(toolbarButton, {}, win); await popupShown; let barMenu = win.document.getElementById("toggle_PersonalToolbar"); let popupHidden = BrowserTestUtils.waitForEvent(toolbarPopup, "popuphidden"); let subMenu = barMenu.querySelector("menupopup"); popupShown = BrowserTestUtils.waitForEvent(subMenu, "popupshown"); EventUtils.synthesizeMouseAtCenter(barMenu, {}, win); await popupShown; let alwaysButton = barMenu.querySelector('*[data-visibility-enum="always"]'); EventUtils.synthesizeMouseAtCenter(alwaysButton, {}, win); await popupHidden; let navbar = CustomizableUI.getCustomizationTarget( win.document.getElementById("nav-bar") ); let bookmarksBar = CustomizableUI.getCustomizationTarget( win.document.getElementById("PersonalToolbar") ); let tabBar = CustomizableUI.getCustomizationTarget( win.document.getElementById("TabsToolbar") ); simulateItemDrag(win.document.getElementById("home-button"), navbar, "start"); simulateItemDrag(win.document.getElementById("library-button"), bookmarksBar); simulateItemDrag(win.document.getElementById("stop-reload-button"), tabBar); simulateItemDrag( win.document.getElementById("stop-reload-button"), navbar, "start" ); simulateItemDrag(win.document.getElementById("stop-reload-button"), tabBar); await leaveCustomizationMode(win); await BrowserTestUtils.closeWindow(win); assertCustomizeScalars({ "home-button_move_nav-bar-end_nav-bar-start_drag": 1, "library-button_move_nav-bar-end_bookmarks-bar_drag": 1, "stop-reload-button_move_nav-bar-start_tabs-bar_drag": 2, "stop-reload-button_move_tabs-bar_nav-bar-start_drag": 1, "bookmarks-bar_move_off_always_customization-toolbar-menu": 1, }); CustomizableUI.reset(); }); add_task(async function contextMenus() { // Create a default state. organizeToolbars({ PersonalToolbar: ["personal-bookmarks"], TabsToolbar: ["tabbrowser-tabs", "new-tab-button"], "nav-bar": [ "back-button", "forward-button", "stop-reload-button", "urlbar-container", "home-button", "library-button", ], }); BrowserUsageTelemetry._recordUITelemetry(); assertVisibilityScalars([ "menu-toolbar_pinned_off", "titlebar_pinned_off", "bookmarks-bar_pinned_off", "tabbrowser-tabs_pinned_tabs-bar", "new-tab-button_pinned_tabs-bar", "alltabs-button_pinned_tabs-bar", "back-button_pinned_nav-bar-start", "forward-button_pinned_nav-bar-start", "stop-reload-button_pinned_nav-bar-start", "home-button_pinned_nav-bar-end", "library-button_pinned_nav-bar-end", "unified-extensions-button_pinned_nav-bar-end", "personal-bookmarks_pinned_bookmarks-bar", ]); let menu = document.getElementById("toolbar-context-menu"); let popupShown = BrowserTestUtils.waitForEvent(menu, "popupshown"); let button = document.getElementById("stop-reload-button"); EventUtils.synthesizeMouseAtCenter( button, { type: "contextmenu", button: 2 }, window ); await popupShown; let barMenu = document.getElementById("toggle_PersonalToolbar"); let popupHidden = BrowserTestUtils.waitForEvent(menu, "popuphidden"); let subMenu = barMenu.querySelector("menupopup"); popupShown = BrowserTestUtils.waitForEvent(subMenu, "popupshown"); barMenu.openMenu(true); await popupShown; let alwaysButton = subMenu.querySelector('*[data-visibility-enum="always"]'); subMenu.activateItem(alwaysButton); await popupHidden; popupShown = BrowserTestUtils.waitForEvent(menu, "popupshown"); EventUtils.synthesizeMouseAtCenter( button, { type: "contextmenu", button: 2 }, window ); await popupShown; popupHidden = BrowserTestUtils.waitForEvent(menu, "popuphidden"); let removeButton = document.querySelector( "#toolbar-context-menu .customize-context-removeFromToolbar" ); menu.activateItem(removeButton); await popupHidden; assertCustomizeScalars({ "bookmarks-bar_move_off_always_toolbar-context-menu": 1, "stop-reload-button_remove_nav-bar-start_na_toolbar-context-menu": 1, }); CustomizableUI.reset(); }); add_task(async function extensions() { // The page action button is only visible when a page is loaded. await BrowserTestUtils.withNewTab("http://example.com", async () => { organizeToolbars(); const extension = ExtensionTestUtils.loadExtension({ useAddonManager: "temporary", manifest: { version: "1", browser_specific_settings: { gecko: { id: "random_addon@example.com" }, }, browser_action: { default_icon: "default.png", default_title: "Hello", default_area: "navbar", }, page_action: { default_icon: "default.png", default_title: "Hello", }, }, }); await extension.startup(); assertCustomizeScalars({ "random-addon-example-com_add_na_nav-bar-end_addon": 1, "random-addon-example-com_add_na_pageaction-urlbar_addon": 1, }); BrowserUsageTelemetry._recordUITelemetry(); assertVisibilityScalars([ "menu-toolbar_pinned_off", "titlebar_pinned_off", "bookmarks-bar_pinned_off", "tabbrowser-tabs_pinned_tabs-bar", "alltabs-button_pinned_tabs-bar", "forward-button_pinned_nav-bar-start", "back-button_pinned_nav-bar-start", "random-addon-example-com_pinned_nav-bar-end", "unified-extensions-button_pinned_nav-bar-end", "random-addon-example-com_pinned_pageaction-urlbar", ]); let addon = await AddonManager.getAddonByID(extension.id); await addon.disable(); assertCustomizeScalars({ "random-addon-example-com_remove_nav-bar-end_na_addon": 1, "random-addon-example-com_remove_pageaction-urlbar_na_addon": 1, }); BrowserUsageTelemetry._recordUITelemetry(); assertVisibilityScalars([ "menu-toolbar_pinned_off", "titlebar_pinned_off", "bookmarks-bar_pinned_off", "tabbrowser-tabs_pinned_tabs-bar", "alltabs-button_pinned_tabs-bar", "forward-button_pinned_nav-bar-start", "back-button_pinned_nav-bar-start", "unified-extensions-button_pinned_nav-bar-end", ]); await addon.enable(); assertCustomizeScalars({ "random-addon-example-com_add_na_nav-bar-end_addon": 1, "random-addon-example-com_add_na_pageaction-urlbar_addon": 1, }); BrowserUsageTelemetry._recordUITelemetry(); assertVisibilityScalars([ "menu-toolbar_pinned_off", "titlebar_pinned_off", "bookmarks-bar_pinned_off", "tabbrowser-tabs_pinned_tabs-bar", "alltabs-button_pinned_tabs-bar", "forward-button_pinned_nav-bar-start", "back-button_pinned_nav-bar-start", "random-addon-example-com_pinned_nav-bar-end", "unified-extensions-button_pinned_nav-bar-end", "random-addon-example-com_pinned_pageaction-urlbar", ]); await addon.reload(); assertCustomizeScalars({}); await enterCustomizationMode(); let navbar = CustomizableUI.getCustomizationTarget( document.getElementById("nav-bar") ); simulateItemDrag( document.getElementById("random_addon_example_com-browser-action"), navbar, "start" ); await leaveCustomizationMode(); assertCustomizeScalars({ "random-addon-example-com_move_nav-bar-end_nav-bar-start_drag": 1, }); await extension.unload(); assertCustomizeScalars({ "random-addon-example-com_remove_nav-bar-start_na_addon": 1, "random-addon-example-com_remove_pageaction-urlbar_na_addon": 1, }); BrowserUsageTelemetry._recordUITelemetry(); assertVisibilityScalars([ "menu-toolbar_pinned_off", "titlebar_pinned_off", "bookmarks-bar_pinned_off", "tabbrowser-tabs_pinned_tabs-bar", "alltabs-button_pinned_tabs-bar", "forward-button_pinned_nav-bar-start", "back-button_pinned_nav-bar-start", "unified-extensions-button_pinned_nav-bar-end", ]); }); });