[tor-commits] [Git][tpo/applications/tor-browser][tor-browser-115.3.1esr-13.0-1] 6 commits: fixup! Bug 41736: Customize toolbar for base-browser.

Pier Angelo Vendrame (@pierov) git at gitlab.torproject.org
Thu Oct 5 20:38:24 UTC 2023



Pier Angelo Vendrame pushed to branch tor-browser-115.3.1esr-13.0-1 at The Tor Project / Applications / Tor Browser


Commits:
197b6fdd by Henry Wilkes at 2023-10-05T20:20:02+01:00
fixup! Bug 41736: Customize toolbar for base-browser.

Bug 41736: Stop placing the NoScript button in the palette, and let it
go to the toolbar by default when shown.

- - - - -
45b58e5a by Henry Wilkes at 2023-10-05T20:20:03+01:00
fixup! Bug 41598: Prevent NoScript from being removed/disabled.

Bug 41736: Add a isNoScript property to Extension class.

- - - - -
ddd31383 by Henry Wilkes at 2023-10-05T20:20:03+01:00
Bug 41736: Hide NoScript extension's toolbar button by default.

This hides it from both the toolbar and the unified extensions panel.

We also hide the unified-extension-button if the panel would be empty:
not including the NoScript button when it is hidden. As a result, this
will be hidden by default until a user installs another extension (or
shows the NoScript button and unpins it).

- - - - -
96e80ac1 by Henry Wilkes at 2023-10-05T20:20:04+01:00
fixup! Firefox preference overrides.

Bug 41736: Hide NoScript extension by default.

We also hide the unified-extension-button if it would be empty.

- - - - -
db17a989 by Henry Wilkes at 2023-10-05T21:20:52+01:00
fixup! Bug 41736: Customize toolbar for base-browser.

Bug 41581: Keep NoScript button in the toolbar (but hidden) by default.

Also includes some migration.

- - - - -
9db5d46d by Henry Wilkes at 2023-10-05T21:20:53+01:00
fixup! Base Browser strings

Bug 41581: Add strings for changing the visibility of the NoScript
toolbar button.

- - - - -


9 changed files:

- browser/app/profile/001-base-profile.js
- browser/base/content/browser-addons.js
- browser/components/customizableui/CustomizableUI.sys.mjs
- browser/components/extensions/parent/ext-browserAction.js
- browser/locales/en-US/browser/base-browser.ftl
- browser/themes/shared/addons/unified-extensions.css
- toolkit/components/extensions/Extension.sys.mjs
- toolkit/mozapps/extensions/content/aboutaddons.html
- toolkit/mozapps/extensions/content/aboutaddons.js


Changes:

=====================================
browser/app/profile/001-base-profile.js
=====================================
@@ -220,6 +220,10 @@ pref("privacy.annotate_channels.strict_list.enabled", false);
 // Disable the Pocket extension (Bug #18886 and #31602)
 pref("extensions.pocket.enabled", false);
 
+// Custom extensions preferences tor-browser#41581
+pref("extensions.hideNoScript", true);
+pref("extensions.hideUnifiedWhenEmpty", true);
+
 // Disable activity stream/"Recommended by Pocket" in about:home (Bug #41029)
 pref("browser.newtabpage.activity-stream.discoverystream.enabled", false);
 pref("browser.newtabpage.activity-stream.feeds.section.topstories", false);


=====================================
browser/base/content/browser-addons.js
=====================================
@@ -26,6 +26,9 @@ XPCOMUtils.defineLazyGetter(lazy, "l10n", function () {
   );
 });
 
+const HIDE_NO_SCRIPT_PREF = "extensions.hideNoScript";
+const HIDE_UNIFIED_WHEN_EMPTY_PREF = "extensions.hideUnifiedWhenEmpty";
+
 /**
  * Mapping of error code -> [error-id, local-error-id]
  *
@@ -1186,6 +1189,18 @@ var gUnifiedExtensions = {
     gNavToolbox.addEventListener("customizationstarting", this);
     CustomizableUI.addListener(this);
 
+    // Listen out for changes in extensions.hideNoScript and
+    // extension.hideUnifiedWhenEmpty, which can effect the visibility of the
+    // unified-extensions-button.
+    // See tor-browser#41581.
+    this._hideNoScriptObserver = () => this._updateVisibility();
+    Services.prefs.addObserver(HIDE_NO_SCRIPT_PREF, this._hideNoScriptObserver);
+    Services.prefs.addObserver(
+      HIDE_UNIFIED_WHEN_EMPTY_PREF,
+      this._hideNoScriptObserver
+    );
+    this._updateVisibility();
+
     this._initialized = true;
   },
 
@@ -1201,6 +1216,15 @@ var gUnifiedExtensions = {
 
     gNavToolbox.removeEventListener("customizationstarting", this);
     CustomizableUI.removeListener(this);
+
+    Services.prefs.removeObserver(
+      HIDE_NO_SCRIPT_PREF,
+      this._hideNoScriptObserver
+    );
+    Services.prefs.removeObserver(
+      HIDE_UNIFIED_WHEN_EMPTY_PREF,
+      this._hideNoScriptObserver
+    );
   },
 
   onLocationChange(browser, webProgress, _request, _uri, flags) {
@@ -1278,6 +1302,15 @@ var gUnifiedExtensions = {
         return false;
       }
 
+      // When an extensions is about to be removed, it may still appear in
+      // getActiveExtensions.
+      // This is needed for hasExtensionsInPanel, when called through
+      // onWidgetDestroy when an extension is being removed.
+      // See tor-browser#41581.
+      if (extension.hasShutdown) {
+        return false;
+      }
+
       // Ignore hidden and extensions that cannot access the current window
       // (because of PB mode when we are in a private window), since users
       // cannot do anything with those extensions anyway.
@@ -1292,6 +1325,20 @@ var gUnifiedExtensions = {
     return policies;
   },
 
+  /**
+   * Potentially hide the unified-extensions-button if it would be empty.
+   */
+  // See tor-browser#41581.
+  // The behaviour overlaps with a proposal in mozilla Bug 1778684, which has
+  // not been implemented, or had much recent activity as of 5th October 2023.
+  _updateVisibility() {
+    this.button.classList.toggle(
+      "hide-empty",
+      Services.prefs.getBoolPref(HIDE_UNIFIED_WHEN_EMPTY_PREF, true) &&
+        !this.hasExtensionsInPanel()
+    );
+  },
+
   /**
    * Returns true when there are active extensions listed/shown in the unified
    * extensions panel, and false otherwise (e.g. when extensions are pinned in
@@ -1300,7 +1347,13 @@ var gUnifiedExtensions = {
    * @returns {boolean} Whether there are extensions listed in the panel.
    */
   hasExtensionsInPanel() {
-    const policies = this.getActivePolicies();
+    let policies = this.getActivePolicies();
+    // If the NoScript button is hidden, we won't count it towards the list of
+    // extensions in the panel.
+    // See tor-browser#41581.
+    if (Services.prefs.getBoolPref(HIDE_NO_SCRIPT_PREF, true)) {
+      policies = policies.filter(policy => !policy.extension?.isNoScript);
+    }
 
     return !!policies
       .map(policy => this.browserActionFor(policy)?.widget)
@@ -1795,7 +1848,17 @@ var gUnifiedExtensions = {
     }
   },
 
+  onWidgetRemoved() {
+    this._updateVisibility();
+  },
+
+  onWidgetDestroyed() {
+    this._updateVisibility();
+  },
+
   onWidgetAdded(aWidgetId, aArea, aPosition) {
+    this._updateVisibility();
+
     // When we pin a widget to the toolbar from a narrow window, the widget
     // will be overflowed directly. In this case, we do not want to change the
     // class name since it is going to be changed by `onWidgetOverflow()`
@@ -1811,6 +1874,8 @@ var gUnifiedExtensions = {
   },
 
   onWidgetOverflow(aNode, aContainer) {
+    this._updateVisibility();
+
     // We register a CUI listener for each window so we make sure that we
     // handle the event for the right window here.
     if (window !== aNode.ownerGlobal) {
@@ -1821,6 +1886,8 @@ var gUnifiedExtensions = {
   },
 
   onWidgetUnderflow(aNode, aContainer) {
+    this._updateVisibility();
+
     // We register a CUI listener for each window so we make sure that we
     // handle the event for the right window here.
     if (window !== aNode.ownerGlobal) {


=====================================
browser/components/customizableui/CustomizableUI.sys.mjs
=====================================
@@ -65,7 +65,8 @@ var kVersion = 19;
 /**
  * The current version for base browser.
  */
-var kVersionBaseBrowser = 1;
+var kVersionBaseBrowser = 2;
+const NoScriptId = "_73a6fe31-595d-460b-a920-fcc0f8843232_-browser-action";
 
 /**
  * The current version for tor browser.
@@ -858,6 +859,57 @@ var CustomizableUIInternal = {
       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);
+          }
+        }
+      }
+    }
   },
 
   _updateForTorBrowser() {
@@ -3441,7 +3493,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
+        );
       }
     }
   },


=====================================
browser/components/extensions/parent/ext-browserAction.js
=====================================
@@ -176,10 +176,6 @@ this.browserAction = class extends ExtensionAPIPersistent {
   }
 
   build() {
-    // The extension ID for NoScript (WebExtension)
-    const isNoScript =
-      this.extension.id === "{73a6fe31-595d-460b-a920-fcc0f8843232}";
-
     let { extension } = this;
     let widgetId = makeWidgetId(extension.id);
     let widget = CustomizableUI.createWidget({
@@ -190,11 +186,7 @@ this.browserAction = class extends ExtensionAPIPersistent {
       removable: true,
       label: this.action.getProperty(null, "title"),
       tooltiptext: this.action.getProperty(null, "title"),
-      // Do not want to add the NoScript extension to the toolbar by default.
-      // tor-browser#41736
-      defaultArea: isNoScript
-        ? null
-        : browserAreas[this.action.getDefaultArea()],
+      defaultArea: browserAreas[this.action.getDefaultArea()],
       showInPrivateBrowsing: extension.privateBrowsingAllowed,
       disallowSubView: true,
 
@@ -282,6 +274,22 @@ this.browserAction = class extends ExtensionAPIPersistent {
         node.append(button, menuButton);
         node.viewButton = button;
 
+        if (extension.isNoScript) {
+          // Hide NoScript by default.
+          // See tor-browser#41581.
+          const HIDE_NO_SCRIPT_PREF = "extensions.hideNoScript";
+          const changeNoScriptVisibility = () => {
+            node.hidden = Services.prefs.getBoolPref(HIDE_NO_SCRIPT_PREF, true);
+          };
+          // Since we expect the NoScript widget to only be destroyed on exit,
+          // we do not set up to remove the observer.
+          Services.prefs.addObserver(
+            HIDE_NO_SCRIPT_PREF,
+            changeNoScriptVisibility
+          );
+          changeNoScriptVisibility();
+        }
+
         return node;
       },
 


=====================================
browser/locales/en-US/browser/base-browser.ftl
=====================================
@@ -24,6 +24,11 @@ basebrowser-rfp-restore-window-size-button-ak = R
 basebrowser-addon-badge-recommended = Mozilla only recommends extensions that meet their standards for security and performance
 basebrowser-addon-badge-verified = Mozilla has reviewed this extension to meet their standards for security and performance
 
+## Option to show or hide the NoScript extension button/item.
+basebrowser-addon-noscript-visibility-label = Toolbar button
+basebrowser-addon-noscript-visibility-show = Show
+basebrowser-addon-noscript-visibility-hide = Hide
+
 ## About dialog
 
 # "Mozilla Firefox" should be treated like a brand and it should be neither translated nor transliterated.


=====================================
browser/themes/shared/addons/unified-extensions.css
=====================================
@@ -238,3 +238,21 @@ unified-extensions-item > .subviewbutton {
     border-color: transparent;
   }
 }
+
+/* Extra rule for tor-browser. See tor-browser#41581.
+ * We want to hide the unified-extensions-button when it is empty.
+ * However, this button is needed as an anchor for addon notifications. E.g.
+ * when installing another addon and permissions pop up.
+ * If we simply marked it as "hidden" then it would not be used as an anchor, so
+ * the popup would fall back to using the identity button as an anchor instead.
+ * So instead, we use "visibility: collapse" whilst it is empty *and* it is not
+ * being used as an anchor (the open attribute is missing). */
+#unified-extensions-button.hide-empty:not([open]) {
+  visibility: collapse;
+  /* Ensure getBoundingClientRect().width returns 0.
+   * Even though this button is collapsed, and therefore should not take up any
+   * layout space, getBoundingClientRect will still measure the padding.
+   * If this was not zero, OverflowableToolbar#getOverflowInfo would
+   * over-measure the children width and would always overflow. */
+  padding-inline: 0;
+}


=====================================
toolkit/components/extensions/Extension.sys.mjs
=====================================
@@ -765,6 +765,15 @@ export class ExtensionData {
     this.eventPagesEnabled = lazy.eventPagesEnabled;
   }
 
+  /**
+   * Whether this is the NoScript extension.
+   *
+   * @type {boolean}
+   */
+  get isNoScript() {
+    return this.id === "{73a6fe31-595d-460b-a920-fcc0f8843232}";
+  }
+
   /**
    * A factory function that allows the construction of ExtensionData, with
    * the isPrivileged flag computed asynchronously.
@@ -3498,7 +3507,7 @@ export class Extension extends ExtensionData {
     }
 
     // Bug 40253: Explicitly allow NoScript in Private Browsing mode.
-    if (this.id === "{73a6fe31-595d-460b-a920-fcc0f8843232}") {
+    if (this.isNoScript) {
       lazy.ExtensionPermissions.add(this.id, {
         permissions: [PRIVATE_ALLOWED_PERMISSION],
         origins: [],


=====================================
toolkit/mozapps/extensions/content/aboutaddons.html
=====================================
@@ -508,6 +508,32 @@
           <div class="addon-detail-sitepermissions">
             <addon-sitepermissions-list></addon-sitepermissions-list>
           </div>
+          <!-- Add an option to show the NoScript toolbar button, if this is the
+             - NoScript addon. See tor-browser#41581. -->
+          <div
+            class="addon-detail-row addon-detail-row-noscript-visibility"
+            role="radiogroup"
+            hidden="hidden"
+          >
+            <span
+              class="addon-noscript-visibility-label"
+              data-l10n-id="basebrowser-addon-noscript-visibility-label"
+            ></span>
+            <div class="addon-detail-actions">
+              <label class="radio-container-with-text">
+                <input type="radio" name="noscript-visibility" value="show" />
+                <span
+                  data-l10n-id="basebrowser-addon-noscript-visibility-show"
+                ></span>
+              </label>
+              <label class="radio-container-with-text">
+                <input type="radio" name="noscript-visibility" value="hide" />
+                <span
+                  data-l10n-id="basebrowser-addon-noscript-visibility-hide"
+                ></span>
+              </label>
+            </div>
+          </div>
           <div class="addon-detail-row addon-detail-row-updates">
             <label data-l10n-id="addon-detail-updates-label"></label>
             <div class="addon-detail-actions">


=====================================
toolkit/mozapps/extensions/content/aboutaddons.js
=====================================
@@ -2063,6 +2063,8 @@ class AddonSitePermissionsList extends HTMLElement {
 }
 customElements.define("addon-sitepermissions-list", AddonSitePermissionsList);
 
+const HIDE_NO_SCRIPT_PREF = "extensions.hideNoScript";
+
 class AddonDetails extends HTMLElement {
   connectedCallback() {
     if (!this.children.length) {
@@ -2070,12 +2072,61 @@ class AddonDetails extends HTMLElement {
     }
     this.deck.addEventListener("view-changed", this);
     this.descriptionShowMoreButton.addEventListener("click", this);
+
+    // If this is for the NoScript extension, we listen for changes in the
+    // visibility of its toolbar button.
+    // See tor-browser#41581.
+    // NOTE: The addon should be set before being connected, so isNoScript will
+    // return a correct value.
+    if (this.isNoScript && !this._noScriptVisibilityObserver) {
+      this._noScriptVisibilityObserver = () => this.updateNoScriptVisibility();
+      Services.prefs.addObserver(
+        HIDE_NO_SCRIPT_PREF,
+        this._noScriptVisibilityObserver
+      );
+    }
   }
 
   disconnectedCallback() {
     this.inlineOptions.destroyBrowser();
     this.deck.removeEventListener("view-changed", this);
     this.descriptionShowMoreButton.removeEventListener("click", this);
+
+    if (this._noScriptVisibilityObserver) {
+      Services.prefs.removeObserver(
+        HIDE_NO_SCRIPT_PREF,
+        this._noScriptVisibilityObserver
+      );
+      // Clear in case this is called again, or if connectedCallback is called.
+      delete this._noScriptVisibilityObserver;
+    }
+  }
+
+  /**
+   * Whether this is a description for the NoScript extension.
+   *
+   * @type {boolean}
+   */
+  get isNoScript() {
+    return this.addon?.id === "{73a6fe31-595d-460b-a920-fcc0f8843232}";
+  }
+
+  /**
+   * Update the shown visibility value for the NoScript extension's toolbar
+   * button.
+   */
+  updateNoScriptVisibility() {
+    if (!this.isNoScript) {
+      return;
+    }
+    const visibility = Services.prefs.getBoolPref(HIDE_NO_SCRIPT_PREF, true)
+      ? "hide"
+      : "show";
+    for (const input of this.querySelectorAll(
+      ".addon-detail-row-noscript-visibility input"
+    )) {
+      input.checked = input.value === visibility;
+    }
   }
 
   handleEvent(e) {
@@ -2271,6 +2322,27 @@ class AddonDetails extends HTMLElement {
       "upgrade"
     );
 
+    // If this is the NoScript extension, we want to show an option to change
+    // the visibility of its toolbar button.
+    // See tor-browser#41581.
+    const visibilityRow = this.querySelector(
+      ".addon-detail-row-noscript-visibility"
+    );
+    visibilityRow.hidden = !this.isNoScript;
+    if (this.isNoScript) {
+      // Set up the aria-label for the role="radiogroup".
+      const visibilityLabel = visibilityRow.querySelector(
+        ".addon-noscript-visibility-label"
+      );
+      visibilityLabel.id = ExtensionCommon.makeWidgetId(
+        `${addon.id}-noscript-visibility-label`
+      );
+      visibilityRow.setAttribute("aria-labelledby", visibilityLabel.id);
+
+      // Set the initial displayed value.
+      this.updateNoScriptVisibility();
+    }
+
     if (addon.type != "extension") {
       // Don't show any private browsing related section for non-extension
       // addon types, because not relevant or they are either always allowed
@@ -2662,6 +2734,11 @@ class AddonCard extends HTMLElement {
           // Update the card if the add-on isn't active.
           this.update();
         }
+      } else if (name == "noscript-visibility") {
+        // Update the NoScript toolbar button visibility.
+        // See tor-browser#41581.
+        const hide = e.target.value !== "show";
+        Services.prefs.setBoolPref(HIDE_NO_SCRIPT_PREF, hide);
       }
     } else if (e.type == "mousedown") {
       // Open panel on mousedown when the mouse is used.



View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/8ec6aad8bff0f58e23d4dd46d36d5196ef736827...9db5d46d8e6d3a0e4cd20572af3cbcf14804ae1d

-- 
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/8ec6aad8bff0f58e23d4dd46d36d5196ef736827...9db5d46d8e6d3a0e4cd20572af3cbcf14804ae1d
You're receiving this email because of your account on gitlab.torproject.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.torproject.org/pipermail/tor-commits/attachments/20231005/b00478bd/attachment-0001.htm>


More information about the tor-commits mailing list