tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 3b71b187df97540f5fce156888f7c97a23835870
parent 75ac156647d6a4c1a9c93ce80941b48dba2aa13a
Author: Henry Wilkes <henry@torproject.org>
Date:   Wed, 19 Apr 2023 14:22:18 +0100

BB 41736: Customize toolbar for base-browser.

Diffstat:
Mbrowser/components/customizableui/CustomizableUI.sys.mjs | 185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 182 insertions(+), 3 deletions(-)

diff --git a/browser/components/customizableui/CustomizableUI.sys.mjs b/browser/components/customizableui/CustomizableUI.sys.mjs @@ -71,6 +71,12 @@ const kSubviewEvents = ["ViewShowing", "ViewHiding"]; var kVersion = 23; /** + * 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 * version the button is removed in as the value. e.g. "pocket-button": 5 @@ -310,6 +316,7 @@ var CustomizableUIInternal = { this.updateForNewVersion(); this.updateForNewProtonVersion(); this.markObsoleteBuiltinButtonsSeen(); + this.updateForBaseBrowser(); this.registerArea( CustomizableUI.AREA_FIXED_OVERFLOW_PANEL, @@ -339,10 +346,14 @@ var CustomizableUIInternal = { Services.policies.isAllowed("removeHomeButtonByDefault") ? null : "home-button", - "spring", "vertical-spacer", "urlbar-container", - "spring", + // Don't want springs either side of the urlbar. tor-browser#41736 + // 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", @@ -363,6 +374,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( @@ -917,6 +932,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 @@ -3464,6 +3628,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; @@ -3760,6 +3928,7 @@ var CustomizableUIInternal = { seen: gSeenWidgets, dirtyAreaCache: gDirtyAreaCache, currentVersion: kVersion, + currentVersionBaseBrowser: kVersionBaseBrowser, newElementCount: gNewElementCount, }; @@ -4522,7 +4691,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 + ); } } },