Loading browser/components/customizableui/CustomizableUI.sys.mjs +184 −4 Original line number Diff line number Diff line Loading @@ -68,6 +68,12 @@ const kSubviewEvents = ["ViewShowing", "ViewHiding"]; */ var kVersion = 22; /** * The current version for base browser. */ var kVersionBaseBrowser = 2; const NoScriptId = "_73a6fe31-595d-460b-a920-fcc0f8843232_-browser-action"; /** * Buttons removed from built-ins by version they were removed. kVersion must be * bumped any time a new id is added to this. Use the button id as key, and Loading Loading @@ -305,6 +311,7 @@ var CustomizableUIInternal = { this.updateForNewVersion(); this.updateForNewProtonVersion(); this.markObsoleteBuiltinButtonsSeen(); this.updateForBaseBrowser(); this.registerArea( CustomizableUI.AREA_FIXED_OVERFLOW_PANEL, Loading Loading @@ -334,11 +341,16 @@ var CustomizableUIInternal = { Services.policies.isAllowed("removeHomeButtonByDefault") ? null : "home-button", "spring", // Don't want springs either side of the urlbar. tor-browser#41736 "vertical-spacer", "urlbar-container", "spring", "save-to-pocket-button", // save-to-pocket-button is entirely disabled. See tor-browser#18886 and // tor-browser#31602. // Base-browser additions tor-browser#41736. If you want to add to, remove // from, or rearrange this list, then bump the kVersionBaseBrowser and // update existing saved states in _updateForBaseBrowser. "security-level-button", "new-identity-button", "downloads-button", AppConstants.MOZ_DEV_EDITION ? "developer-button" : null, "fxa-toolbar-menu-button", Loading @@ -359,6 +371,10 @@ var CustomizableUIInternal = { }, true ); // navbarPlacements does not match the initial default XHTML layout. // Therefore we always need to rebuild the navbar area when // registerToolbarNode is called. tor-browser#41736 gDirtyAreaCache.add(CustomizableUI.AREA_NAVBAR); if (!Services.appinfo.nativeMenubar) { this.registerArea( Loading Loading @@ -937,6 +953,155 @@ var CustomizableUIInternal = { } }, updateForBaseBrowser() { if (!gSavedState) { // Use the defaults. return; } const currentVersion = gSavedState.currentVersionBaseBrowser; if (currentVersion < 1) { // NOTE: In base-browser/tor-browser version 12.5a5, and earlier, the // toolbar was configured by setting the full JSON string for the default // "browser.uiCustomization.state" preference value. The disadvantage is // that we could not update this value in a way that existing users (who // would have non-default preference values) would also get the desired // change (e.g. for adding or removing a button). // // With tor-browser#41736 we want to switch to changing the toolbar // dynamically like firefox. Therefore, this first version transfer simply // gets the toolbar into the same state we wanted before, away from the // default firefox state. // // If an existing user state aligned with the previous default // "browser.uiCustomization.state" then this shouldn't visibly change // anything. // If a user explicitly customized the toolbar to go back to the firefox // default, then this may undo those changes. const navbarPlacements = gSavedState.placements[CustomizableUI.AREA_NAVBAR]; if (navbarPlacements) { const getBeforeAfterUrlbar = () => { // NOTE: The urlbar is non-removable from the navbar, so should have // an index. const index = navbarPlacements.indexOf("urlbar-container"); let after = index + 1; if ( after < navbarPlacements.length && navbarPlacements[after] === "search-container" ) { // Skip past the search-container. after++; } return { before: index - 1, after }; }; // Remove the urlbar springs either side of the urlbar. const { before, after } = getBeforeAfterUrlbar(); if ( after < navbarPlacements.length && this.matchingSpecials(navbarPlacements[after], "spring") ) { // Remove the spring after. navbarPlacements.splice(after, 1); // NOTE: The `before` index does not change. } if ( before >= 0 && this.matchingSpecials(navbarPlacements[before], "spring") ) { // Remove the spring before. navbarPlacements.splice(before, 1); } // Make sure the security-level-button and new-identity-button appears // in the toolbar. for (const id of ["new-identity-button", "security-level-button"]) { let alreadyAdded = false; for (const placements of Object.values(gSavedState.placements)) { if (placements.includes(id)) { alreadyAdded = true; break; } } if (alreadyAdded) { continue; } // Add to the nav-bar, after the urlbar-container. // NOTE: We have already removed the spring after the urlbar. navbarPlacements.splice(getBeforeAfterUrlbar().after, 0, id); } } // Remove save-to-pocket-button. See tor-browser#18886 and // tor-browser#31602. for (const placements of Object.values(gSavedState.placements)) { let buttonIndex = placements.indexOf("save-to-pocket-button"); if (buttonIndex != -1) { placements.splice(buttonIndex, 1); } } // Remove unused fields that used to be part of // "browser.uiCustomization.state". delete gSavedState.placements["PanelUI-contents"]; delete gSavedState.placements["addon-bar"]; } if (currentVersion < 2) { // Matches against kVersion 19, i.e. when the unified-extensions-button // was introduced and extensions were moved from the palette to // AREA_ADDONS. // For base browser, we want the NoScript addon to be moved from the // default palette to AREA_NAVBAR, so that if it becomes shown through the // preference extensions.hideNoScript it will appear in the toolbar. // If the NoScript addon is already in AREA_NAVBAR, we instead flip the // extensions.hideNoScript preference so that it remains visible. // See tor-browser#41581. const navbarPlacements = gSavedState.placements[CustomizableUI.AREA_NAVBAR]; if (navbarPlacements) { let noScriptVisible = false; for (const [area, placements] of Object.entries( gSavedState.placements )) { const index = placements.indexOf(NoScriptId); if (index === -1) { continue; } if (area === CustomizableUI.AREA_ADDONS) { // Has been placed in the ADDONS area. // Most likely, this is an alpha or nightly user who received the // firefox update in a run before this one. In this case, we want to // match the same behaviour as a stable user: hide the button and // move it to the NAVBAR instead. placements.splice(index, 1); } else { // It is in an area other than the ADDON (and not in the palette). noScriptVisible = true; } } if (noScriptVisible) { // Keep the button where it is and make sure it is visible. Services.prefs.setBoolPref("extensions.hideNoScript", false); } else { // Should appear just before unified-extensions-button, which is // currently not part of the default placements. const placeIndex = navbarPlacements.indexOf( "unified-extensions-button" ); if (placeIndex === -1) { navbarPlacements.push(NoScriptId); } else { navbarPlacements.splice(placeIndex, 0, NoScriptId); } } } } }, /** * If a new area was defined, or new default widgets for an area are defined, * this reconciles the placements of those new default widgets with the Loading Loading @@ -3489,6 +3654,10 @@ var CustomizableUIInternal = { gSavedState.currentVersion = 0; } if (!("currentVersionBaseBrowser" in gSavedState)) { gSavedState.currentVersionBaseBrowser = 0; } gSeenWidgets = new Set(gSavedState.seen || []); gDirtyAreaCache = new Set(gSavedState.dirtyAreaCache || []); gNewElementCount = gSavedState.newElementCount || 0; Loading Loading @@ -3785,6 +3954,7 @@ var CustomizableUIInternal = { seen: gSeenWidgets, dirtyAreaCache: gDirtyAreaCache, currentVersion: kVersion, currentVersionBaseBrowser: kVersionBaseBrowser, newElementCount: gNewElementCount, }; Loading Loading @@ -4547,7 +4717,17 @@ var CustomizableUIInternal = { CustomizableUI.isWebExtensionWidget(widgetId) && !oldAddonPlacements.includes(widgetId) ) { this.addWidgetToArea(widgetId, CustomizableUI.AREA_ADDONS); // When resetting, NoScript goes to the toolbar instead. This matches // its initial placement anyway. And since the button may be hidden by // default by extensions.hideNoScript, we want to make sure that if it // becomes unhidden it is shown rather than in the unified extensions // panel. See tor-browser#41581. this.addWidgetToArea( widgetId, widgetId === NoScriptId ? CustomizableUI.AREA_NAVBAR : CustomizableUI.AREA_ADDONS ); } } }, Loading Loading
browser/components/customizableui/CustomizableUI.sys.mjs +184 −4 Original line number Diff line number Diff line Loading @@ -68,6 +68,12 @@ const kSubviewEvents = ["ViewShowing", "ViewHiding"]; */ var kVersion = 22; /** * The current version for base browser. */ var kVersionBaseBrowser = 2; const NoScriptId = "_73a6fe31-595d-460b-a920-fcc0f8843232_-browser-action"; /** * Buttons removed from built-ins by version they were removed. kVersion must be * bumped any time a new id is added to this. Use the button id as key, and Loading Loading @@ -305,6 +311,7 @@ var CustomizableUIInternal = { this.updateForNewVersion(); this.updateForNewProtonVersion(); this.markObsoleteBuiltinButtonsSeen(); this.updateForBaseBrowser(); this.registerArea( CustomizableUI.AREA_FIXED_OVERFLOW_PANEL, Loading Loading @@ -334,11 +341,16 @@ var CustomizableUIInternal = { Services.policies.isAllowed("removeHomeButtonByDefault") ? null : "home-button", "spring", // Don't want springs either side of the urlbar. tor-browser#41736 "vertical-spacer", "urlbar-container", "spring", "save-to-pocket-button", // save-to-pocket-button is entirely disabled. See tor-browser#18886 and // tor-browser#31602. // Base-browser additions tor-browser#41736. If you want to add to, remove // from, or rearrange this list, then bump the kVersionBaseBrowser and // update existing saved states in _updateForBaseBrowser. "security-level-button", "new-identity-button", "downloads-button", AppConstants.MOZ_DEV_EDITION ? "developer-button" : null, "fxa-toolbar-menu-button", Loading @@ -359,6 +371,10 @@ var CustomizableUIInternal = { }, true ); // navbarPlacements does not match the initial default XHTML layout. // Therefore we always need to rebuild the navbar area when // registerToolbarNode is called. tor-browser#41736 gDirtyAreaCache.add(CustomizableUI.AREA_NAVBAR); if (!Services.appinfo.nativeMenubar) { this.registerArea( Loading Loading @@ -937,6 +953,155 @@ var CustomizableUIInternal = { } }, updateForBaseBrowser() { if (!gSavedState) { // Use the defaults. return; } const currentVersion = gSavedState.currentVersionBaseBrowser; if (currentVersion < 1) { // NOTE: In base-browser/tor-browser version 12.5a5, and earlier, the // toolbar was configured by setting the full JSON string for the default // "browser.uiCustomization.state" preference value. The disadvantage is // that we could not update this value in a way that existing users (who // would have non-default preference values) would also get the desired // change (e.g. for adding or removing a button). // // With tor-browser#41736 we want to switch to changing the toolbar // dynamically like firefox. Therefore, this first version transfer simply // gets the toolbar into the same state we wanted before, away from the // default firefox state. // // If an existing user state aligned with the previous default // "browser.uiCustomization.state" then this shouldn't visibly change // anything. // If a user explicitly customized the toolbar to go back to the firefox // default, then this may undo those changes. const navbarPlacements = gSavedState.placements[CustomizableUI.AREA_NAVBAR]; if (navbarPlacements) { const getBeforeAfterUrlbar = () => { // NOTE: The urlbar is non-removable from the navbar, so should have // an index. const index = navbarPlacements.indexOf("urlbar-container"); let after = index + 1; if ( after < navbarPlacements.length && navbarPlacements[after] === "search-container" ) { // Skip past the search-container. after++; } return { before: index - 1, after }; }; // Remove the urlbar springs either side of the urlbar. const { before, after } = getBeforeAfterUrlbar(); if ( after < navbarPlacements.length && this.matchingSpecials(navbarPlacements[after], "spring") ) { // Remove the spring after. navbarPlacements.splice(after, 1); // NOTE: The `before` index does not change. } if ( before >= 0 && this.matchingSpecials(navbarPlacements[before], "spring") ) { // Remove the spring before. navbarPlacements.splice(before, 1); } // Make sure the security-level-button and new-identity-button appears // in the toolbar. for (const id of ["new-identity-button", "security-level-button"]) { let alreadyAdded = false; for (const placements of Object.values(gSavedState.placements)) { if (placements.includes(id)) { alreadyAdded = true; break; } } if (alreadyAdded) { continue; } // Add to the nav-bar, after the urlbar-container. // NOTE: We have already removed the spring after the urlbar. navbarPlacements.splice(getBeforeAfterUrlbar().after, 0, id); } } // Remove save-to-pocket-button. See tor-browser#18886 and // tor-browser#31602. for (const placements of Object.values(gSavedState.placements)) { let buttonIndex = placements.indexOf("save-to-pocket-button"); if (buttonIndex != -1) { placements.splice(buttonIndex, 1); } } // Remove unused fields that used to be part of // "browser.uiCustomization.state". delete gSavedState.placements["PanelUI-contents"]; delete gSavedState.placements["addon-bar"]; } if (currentVersion < 2) { // Matches against kVersion 19, i.e. when the unified-extensions-button // was introduced and extensions were moved from the palette to // AREA_ADDONS. // For base browser, we want the NoScript addon to be moved from the // default palette to AREA_NAVBAR, so that if it becomes shown through the // preference extensions.hideNoScript it will appear in the toolbar. // If the NoScript addon is already in AREA_NAVBAR, we instead flip the // extensions.hideNoScript preference so that it remains visible. // See tor-browser#41581. const navbarPlacements = gSavedState.placements[CustomizableUI.AREA_NAVBAR]; if (navbarPlacements) { let noScriptVisible = false; for (const [area, placements] of Object.entries( gSavedState.placements )) { const index = placements.indexOf(NoScriptId); if (index === -1) { continue; } if (area === CustomizableUI.AREA_ADDONS) { // Has been placed in the ADDONS area. // Most likely, this is an alpha or nightly user who received the // firefox update in a run before this one. In this case, we want to // match the same behaviour as a stable user: hide the button and // move it to the NAVBAR instead. placements.splice(index, 1); } else { // It is in an area other than the ADDON (and not in the palette). noScriptVisible = true; } } if (noScriptVisible) { // Keep the button where it is and make sure it is visible. Services.prefs.setBoolPref("extensions.hideNoScript", false); } else { // Should appear just before unified-extensions-button, which is // currently not part of the default placements. const placeIndex = navbarPlacements.indexOf( "unified-extensions-button" ); if (placeIndex === -1) { navbarPlacements.push(NoScriptId); } else { navbarPlacements.splice(placeIndex, 0, NoScriptId); } } } } }, /** * If a new area was defined, or new default widgets for an area are defined, * this reconciles the placements of those new default widgets with the Loading Loading @@ -3489,6 +3654,10 @@ var CustomizableUIInternal = { gSavedState.currentVersion = 0; } if (!("currentVersionBaseBrowser" in gSavedState)) { gSavedState.currentVersionBaseBrowser = 0; } gSeenWidgets = new Set(gSavedState.seen || []); gDirtyAreaCache = new Set(gSavedState.dirtyAreaCache || []); gNewElementCount = gSavedState.newElementCount || 0; Loading Loading @@ -3785,6 +3954,7 @@ var CustomizableUIInternal = { seen: gSeenWidgets, dirtyAreaCache: gDirtyAreaCache, currentVersion: kVersion, currentVersionBaseBrowser: kVersionBaseBrowser, newElementCount: gNewElementCount, }; Loading Loading @@ -4547,7 +4717,17 @@ var CustomizableUIInternal = { CustomizableUI.isWebExtensionWidget(widgetId) && !oldAddonPlacements.includes(widgetId) ) { this.addWidgetToArea(widgetId, CustomizableUI.AREA_ADDONS); // When resetting, NoScript goes to the toolbar instead. This matches // its initial placement anyway. And since the button may be hidden by // default by extensions.hideNoScript, we want to make sure that if it // becomes unhidden it is shown rather than in the unified extensions // panel. See tor-browser#41581. this.addWidgetToArea( widgetId, widgetId === NoScriptId ? CustomizableUI.AREA_NAVBAR : CustomizableUI.AREA_ADDONS ); } } }, Loading