Bug 1348122 - Share code between the customizable zoom control and the location bar's zoom indicator. r=Gijs
authorDão Gottwald <dao@mozilla.com>
Tue, 21 Mar 2017 09:23:24 +0100
changeset 399070 c8f8b6cb5b7bce0f3c038a8d454488f3b5661796
parent 399069 896b3e4c15e779bd4cdcd4c837b7c36bab491b6b
child 399071 63cbef012e2a58f56fc46c3b4802ae25f414a99c
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1348122
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1348122 - Share code between the customizable zoom control and the location bar's zoom indicator. r=Gijs MozReview-Commit-ID: 7iRRr1gF9R5
browser/base/content/browser.js
browser/components/customizableui/CustomizableWidgets.jsm
browser/components/customizableui/test/browser_934951_zoom_in_toolbar.js
browser/locales/en-US/chrome/browser/browser.properties
browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties
browser/modules/FullZoomUI.jsm
browser/modules/URLBarZoom.jsm
browser/modules/moz.build
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -23,17 +23,17 @@ Cu.import("resource://gre/modules/Notifi
           LoginManagerParent:false, NewTabUtils:false, PageThumbs:false,
           PluralForm:false, Preferences:false, PrivateBrowsingUtils:false,
           ProcessHangMonitor:false, PromiseUtils:false, ReaderMode:false,
           ReaderParent:false, RecentWindow:false, SessionStore:false,
           ShortcutUtils:false, SimpleServiceDiscovery:false, SitePermissions:false,
           Social:false, TabCrashHandler:false, Task:false, TelemetryStopwatch:false,
           Translation:false, UITour:false, UpdateUtils:false, Weave:false,
           fxAccounts:false, gDevTools:false, gDevToolsBrowser:false, webrtcUI:false,
-          URLBarZoom:false
+          FullZoomUI:false
  */
 
 /**
  * IF YOU ADD OR REMOVE FROM THIS LIST, PLEASE UPDATE THE LIST ABOVE AS WELL.
  * XXX Bug 1325373 is for making eslint detect these automatically.
  */
 [
   ["AboutHome", "resource:///modules/AboutHome.jsm"],
@@ -44,16 +44,17 @@ Cu.import("resource://gre/modules/Notifi
   ["CastingApps", "resource:///modules/CastingApps.jsm"],
   ["CharsetMenu", "resource://gre/modules/CharsetMenu.jsm"],
   ["Color", "resource://gre/modules/Color.jsm"],
   ["ContentSearch", "resource:///modules/ContentSearch.jsm"],
   ["Deprecated", "resource://gre/modules/Deprecated.jsm"],
   ["E10SUtils", "resource:///modules/E10SUtils.jsm"],
   ["ExtensionsUI", "resource:///modules/ExtensionsUI.jsm"],
   ["FormValidationHandler", "resource:///modules/FormValidationHandler.jsm"],
+  ["FullZoomUI", "resource:///modules/FullZoomUI.jsm"],
   ["GMPInstallManager", "resource://gre/modules/GMPInstallManager.jsm"],
   ["LightweightThemeManager", "resource://gre/modules/LightweightThemeManager.jsm"],
   ["Log", "resource://gre/modules/Log.jsm"],
   ["LoginManagerParent", "resource://gre/modules/LoginManagerParent.jsm"],
   ["NewTabUtils", "resource://gre/modules/NewTabUtils.jsm"],
   ["PageThumbs", "resource://gre/modules/PageThumbs.jsm"],
   ["PluralForm", "resource://gre/modules/PluralForm.jsm"],
   ["Preferences", "resource://gre/modules/Preferences.jsm"],
@@ -69,17 +70,16 @@ Cu.import("resource://gre/modules/Notifi
   ["SitePermissions", "resource:///modules/SitePermissions.jsm"],
   ["Social", "resource:///modules/Social.jsm"],
   ["TabCrashHandler", "resource:///modules/ContentCrashHandlers.jsm"],
   ["Task", "resource://gre/modules/Task.jsm"],
   ["TelemetryStopwatch", "resource://gre/modules/TelemetryStopwatch.jsm"],
   ["Translation", "resource:///modules/translation/Translation.jsm"],
   ["UITour", "resource:///modules/UITour.jsm"],
   ["UpdateUtils", "resource://gre/modules/UpdateUtils.jsm"],
-  ["URLBarZoom", "resource:///modules/URLBarZoom.jsm"],
   ["Weave", "resource://services-sync/main.js"],
   ["fxAccounts", "resource://gre/modules/FxAccounts.jsm"],
   ["gDevTools", "resource://devtools/client/framework/gDevTools.jsm"],
   ["gDevToolsBrowser", "resource://devtools/client/framework/gDevTools.jsm"],
   ["webrtcUI", "resource:///modules/webrtcUI.jsm"],
 ].forEach(([name, resource]) => XPCOMUtils.defineLazyModuleGetter(this, name, resource));
 
 XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
@@ -1135,17 +1135,17 @@ var gBrowserInit = {
     LanguageDetectionListener.init();
     BrowserOnClick.init();
     FeedHandler.init();
     CompactTheme.init();
     AboutPrivateBrowsingListener.init();
     TrackingProtection.init();
     RefreshBlocker.init();
     CaptivePortalWatcher.init();
-    URLBarZoom.init(window);
+    FullZoomUI.init(window);
 
     let mm = window.getGroupMessageManager("browsers");
     mm.loadFrameScript("chrome://browser/content/tab-content.js", true);
     mm.loadFrameScript("chrome://browser/content/content.js", true);
     mm.loadFrameScript("chrome://browser/content/content-UITour.js", true);
     mm.loadFrameScript("chrome://global/content/manifestMessages.js", true);
 
     // initialize observers and listeners
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -658,21 +658,16 @@ const CustomizableWidgets = [
       win.BrowserOpenAddonsMgr();
     }
   }, {
     id: "zoom-controls",
     type: "custom",
     tooltiptext: "zoom-controls.tooltiptext2",
     defaultArea: CustomizableUI.AREA_PANEL,
     onBuild(aDocument) {
-      const kPanelId = "PanelUI-popup";
-      let areaType = CustomizableUI.getAreaType(this.currentArea);
-      let inPanel = areaType == CustomizableUI.TYPE_MENU_PANEL;
-      let inToolbar = areaType == CustomizableUI.TYPE_TOOLBAR;
-
       let buttons = [{
         id: "zoom-out-button",
         command: "cmd_fullZoomReduce",
         label: true,
         tooltiptext: "tooltiptext2",
         shortcutId: "key_fullZoomReduce",
       }, {
         id: "zoom-reset-button",
@@ -700,135 +695,60 @@ const CustomizableWidgets = [
       buttons.forEach(function(aButton, aIndex) {
         if (aIndex != 0)
           node.appendChild(aDocument.createElementNS(kNSXUL, "separator"));
         let btnNode = aDocument.createElementNS(kNSXUL, "toolbarbutton");
         setAttributes(btnNode, aButton);
         node.appendChild(btnNode);
       });
 
-      // The middle node is the 'Reset Zoom' button.
-      let zoomResetButton = node.childNodes[2];
-      let window = aDocument.defaultView;
-      function updateZoomResetButton() {
-        let updateDisplay = true;
-        // Label should always show 100% in customize mode, so don't update:
-        if (aDocument.documentElement.hasAttribute("customizing")) {
-          updateDisplay = false;
-        }
-        // XXXgijs in some tests we get called very early, and there's no docShell on the
-        // tabbrowser. This breaks the zoom toolkit code (see bug 897410). Don't let that happen:
-        let zoomFactor = 100;
-        try {
-          zoomFactor = Math.round(window.ZoomManager.zoom * 100);
-        } catch (e) {}
-        zoomResetButton.setAttribute("label", CustomizableUI.getLocalizedProperty(
-          buttons[1], "label", [updateDisplay ? zoomFactor : 100]
-        ));
-      }
-
-      // Register ourselves with the service so we know when the zoom prefs change.
-      Services.obs.addObserver(updateZoomResetButton, "browser-fullZoom:location-change", false);
-      window.addEventListener("FullZoomChange", updateZoomResetButton);
-
-      if (inPanel) {
-        let panel = aDocument.getElementById(kPanelId);
-        panel.addEventListener("popupshowing", updateZoomResetButton);
-      } else {
-        if (inToolbar) {
-          let container = window.gBrowser.tabContainer;
-          container.addEventListener("TabSelect", updateZoomResetButton);
-        }
-        updateZoomResetButton();
-      }
       updateCombinedWidgetStyle(node, this.currentArea, true);
 
       let listener = {
         onWidgetAdded: function(aWidgetId, aArea, aPosition) {
           if (aWidgetId != this.id)
             return;
 
           updateCombinedWidgetStyle(node, aArea, true);
-          updateZoomResetButton();
-
-          let newAreaType = CustomizableUI.getAreaType(aArea);
-          if (newAreaType == CustomizableUI.TYPE_MENU_PANEL) {
-            let panel = aDocument.getElementById(kPanelId);
-            panel.addEventListener("popupshowing", updateZoomResetButton);
-          } else if (newAreaType == CustomizableUI.TYPE_TOOLBAR) {
-            let container = window.gBrowser.tabContainer;
-            container.addEventListener("TabSelect", updateZoomResetButton);
-          }
         }.bind(this),
 
         onWidgetRemoved: function(aWidgetId, aPrevArea) {
           if (aWidgetId != this.id)
             return;
 
-          let formerAreaType = CustomizableUI.getAreaType(aPrevArea);
-          if (formerAreaType == CustomizableUI.TYPE_MENU_PANEL) {
-            let panel = aDocument.getElementById(kPanelId);
-            panel.removeEventListener("popupshowing", updateZoomResetButton);
-          } else if (formerAreaType == CustomizableUI.TYPE_TOOLBAR) {
-            let container = window.gBrowser.tabContainer;
-            container.removeEventListener("TabSelect", updateZoomResetButton);
-          }
-
           // When a widget is demoted to the palette ('removed'), it's visual
           // style should change.
           updateCombinedWidgetStyle(node, null, true);
-          updateZoomResetButton();
         }.bind(this),
 
         onWidgetReset: function(aWidgetNode) {
           if (aWidgetNode != node)
             return;
           updateCombinedWidgetStyle(node, this.currentArea, true);
-          updateZoomResetButton();
         }.bind(this),
 
         onWidgetUndoMove: function(aWidgetNode) {
           if (aWidgetNode != node)
             return;
           updateCombinedWidgetStyle(node, this.currentArea, true);
-          updateZoomResetButton();
         }.bind(this),
 
         onWidgetMoved: function(aWidgetId, aArea) {
           if (aWidgetId != this.id)
             return;
           updateCombinedWidgetStyle(node, aArea, true);
-          updateZoomResetButton();
         }.bind(this),
 
         onWidgetInstanceRemoved: function(aWidgetId, aDoc) {
           if (aWidgetId != this.id || aDoc != aDocument)
             return;
 
           CustomizableUI.removeListener(listener);
-          Services.obs.removeObserver(updateZoomResetButton, "browser-fullZoom:location-change");
-          window.removeEventListener("FullZoomChange", updateZoomResetButton);
-          let panel = aDoc.getElementById(kPanelId);
-          panel.removeEventListener("popupshowing", updateZoomResetButton);
-          let container = aDoc.defaultView.gBrowser.tabContainer;
-          container.removeEventListener("TabSelect", updateZoomResetButton);
         }.bind(this),
 
-        onCustomizeStart(aWindow) {
-          if (aWindow.document == aDocument) {
-            updateZoomResetButton();
-          }
-        },
-
-        onCustomizeEnd(aWindow) {
-          if (aWindow.document == aDocument) {
-            updateZoomResetButton();
-          }
-        },
-
         onWidgetDrag: function(aWidgetId, aArea) {
           if (aWidgetId != this.id)
             return;
           aArea = aArea || this.currentArea;
           updateCombinedWidgetStyle(node, aArea, true);
         }.bind(this)
       };
       CustomizableUI.addListener(listener);
--- a/browser/components/customizableui/test/browser_934951_zoom_in_toolbar.js
+++ b/browser/components/customizableui/test/browser_934951_zoom_in_toolbar.js
@@ -24,19 +24,20 @@ add_task(function*() {
   });
 
   is(parseInt(zoomResetButton.label, 10), 100, "Default zoom is 100% for about:mozilla");
   let zoomChangePromise = promiseObserverNotification("browser-fullZoom:zoomChange");
   FullZoom.enlarge();
   yield zoomChangePromise;
   is(parseInt(zoomResetButton.label, 10), 110, "Zoom is changed to 110% for about:mozilla");
 
-  let tabSelectPromise = promiseTabSelect();
+  let tabSelectPromise = promiseObserverNotification("browser-fullZoom:location-change");
   gBrowser.selectedTab = tab2;
   yield tabSelectPromise;
+  yield new Promise(resolve => executeSoon(resolve));
   is(parseInt(zoomResetButton.label, 10), 100, "Default zoom is 100% for about:robots");
 
   gBrowser.selectedTab = tab1;
   let zoomResetPromise = promiseObserverNotification("browser-fullZoom:zoomReset");
   FullZoom.reset();
   yield zoomResetPromise;
   is(parseInt(zoomResetButton.label, 10), 100, "Default zoom is 100% for about:mozilla");
 
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -381,20 +381,21 @@ menuUndoCloseWindowSingleTabLabel=#1
 
 # Unified Back-/Forward Popup
 tabHistory.current=Stay on this page
 tabHistory.goBack=Go back to this page
 tabHistory.goForward=Go forward to this page
 
 # URL Bar
 pasteAndGo.label=Paste & Go
-# LOCALIZATION NOTE(urlbar-zoom-button.label): %S is the current zoom level,
+
+# LOCALIZATION NOTE(zoom-button.label): %S is the current page zoom level,
 # %% will be displayed as a single % character (% is commonly used to define
 # format specifiers, so it needs to be escaped).
-urlbar-zoom-button.label = %S%%
+zoom-button.label = %S%%
 
 # Block autorefresh
 refreshBlocked.goButton=Allow
 refreshBlocked.goButton.accesskey=A
 refreshBlocked.refreshLabel=%S prevented this page from automatically reloading.
 refreshBlocked.redirectLabel=%S prevented this page from automatically redirecting to another page.
 
 # General bookmarks button
--- a/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties
+++ b/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties
@@ -46,20 +46,16 @@ preferences-button.tooltipWin2 = Open op
 
 zoom-controls.label = Zoom Controls
 zoom-controls.tooltiptext2 = Zoom controls
 
 zoom-out-button.label = Zoom out
 # LOCALIZATION NOTE(zoom-out-button.tooltiptext2): %S is the keyboard shortcut.
 zoom-out-button.tooltiptext2 = Zoom out (%S)
 
-# LOCALIZATION NOTE(zoom-reset-button.label): %S is the current zoom level,
-# %% will be displayed as a single % character (% is commonly used to define
-# format specifiers, so it needs to be escaped).
-zoom-reset-button.label = %S%%
 # LOCALIZATION NOTE(zoom-reset-button.tooltiptext2): %S is the keyboard shortcut.
 zoom-reset-button.tooltiptext2 = Reset zoom level (%S)
 
 zoom-in-button.label = Zoom in
 # LOCALIZATION NOTE(zoom-in-button.tooltiptext2): %S is the keyboard shortcut.
 zoom-in-button.tooltiptext2 = Zoom in (%S)
 
 edit-controls.label = Edit Controls
rename from browser/modules/URLBarZoom.jsm
rename to browser/modules/FullZoomUI.jsm
--- a/browser/modules/URLBarZoom.jsm
+++ b/browser/modules/FullZoomUI.jsm
@@ -1,20 +1,20 @@
 // -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-this.EXPORTED_SYMBOLS = [ "URLBarZoom" ];
+this.EXPORTED_SYMBOLS = [ "FullZoomUI" ];
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 
-var URLBarZoom = {
+var FullZoomUI = {
   init(aWindow) {
     aWindow.addEventListener("EndSwapDocShells", onEndSwapDocShells, true);
     aWindow.addEventListener("FullZoomChange", onFullZoomChange);
     aWindow.addEventListener("unload", () => {
       aWindow.removeEventListener("EndSwapDocShells", onEndSwapDocShells, true);
       aWindow.removeEventListener("FullZoomChange", onFullZoomChange);
     }, {once: true});
   },
@@ -22,70 +22,95 @@ var URLBarZoom = {
 
 function fullZoomLocationChangeObserver(aSubject, aTopic) {
   // If the tab was the last one in its window and has been dragged to another
   // window, the original browser's window will be unavailable here. Since that
   // window is closing, we can just ignore this notification.
   if (!aSubject.ownerGlobal) {
     return;
   }
-
-  updateZoomButton(aSubject, false);
+  updateZoomUI(aSubject, false);
 }
+Services.obs.addObserver(fullZoomLocationChangeObserver, "browser-fullZoom:location-change", false);
 
 function onEndSwapDocShells(event) {
-  updateZoomButton(event.originalTarget);
+  updateZoomUI(event.originalTarget);
 }
 
 function onFullZoomChange(event) {
   let browser;
   if (event.target.nodeType == event.target.DOCUMENT_NODE) {
     // In non-e10s, the event is dispatched on the contentDocument
     // so we need to jump through some hoops to get to the <xul:browser>.
     let gBrowser = event.currentTarget.gBrowser;
     let topDoc = event.target.defaultView.top.document;
     browser = gBrowser.getBrowserForDocument(topDoc);
   } else {
     browser = event.originalTarget;
   }
-  updateZoomButton(browser, true);
+  updateZoomUI(browser, true);
 }
 
-  /**
-   * Updates the zoom button in the location bar.
-   *
-   * @param {object} aBrowser The browser that the zoomed content resides in.
-   * @param {boolean} aAnimate Should be True for all cases unless the zoom
-   *   change is related to tab switching. Optional
-   */
-function updateZoomButton(aBrowser, aAnimate = false) {
+/**
+ * Updates zoom controls.
+ *
+ * @param {object} aBrowser The browser that the zoomed content resides in.
+ * @param {boolean} aAnimate Should be True for all cases unless the zoom
+ *   change is related to tab switching. Optional
+ */
+function updateZoomUI(aBrowser, aAnimate = false) {
   let win = aBrowser.ownerGlobal;
   if (aBrowser != win.gBrowser.selectedBrowser) {
     return;
   }
 
   let customizableZoomControls = win.document.getElementById("zoom-controls");
-  let zoomResetButton = win.document.getElementById("urlbar-zoom-button");
-
-  // Ensure that zoom controls haven't already been added to browser in Customize Mode
-  if (customizableZoomControls &&
-      customizableZoomControls.getAttribute("cui-areatype") == "toolbar") {
-    zoomResetButton.hidden = true;
-    return;
-  }
-
+  let customizableZoomReset = win.document.getElementById("zoom-reset-button");
+  let urlbarZoomButton = win.document.getElementById("urlbar-zoom-button");
   let zoomFactor = Math.round(win.ZoomManager.zoom * 100);
-  if (zoomFactor != 100) {
-    zoomResetButton.hidden = false;
+
+  // Hide urlbar zoom button if zoom is at 100% or the customizable control is
+  // in the toolbar.
+  urlbarZoomButton.hidden =
+    (zoomFactor == 100 ||
+     (customizableZoomControls &&
+      customizableZoomControls.getAttribute("cui-areatype") == "toolbar"));
+
+  let label = win.gNavigatorBundle.getFormattedString("zoom-button.label", [zoomFactor]);
+  if (customizableZoomReset) {
+    customizableZoomReset.setAttribute("label", label);
+  }
+  if (!urlbarZoomButton.hidden) {
     if (aAnimate) {
-      zoomResetButton.setAttribute("animate", "true");
+      urlbarZoomButton.setAttribute("animate", "true");
     } else {
-      zoomResetButton.removeAttribute("animate");
+      urlbarZoomButton.removeAttribute("animate");
     }
-    zoomResetButton.setAttribute("label",
-        win.gNavigatorBundle.getFormattedString("urlbar-zoom-button.label", [zoomFactor]));
-  } else {
-    // Hide button if zoom is at 100%
-    zoomResetButton.hidden = true;
+    urlbarZoomButton.setAttribute("label", label);
   }
 }
 
-Services.obs.addObserver(fullZoomLocationChangeObserver, "browser-fullZoom:location-change", false);
+Components.utils.import("resource:///modules/CustomizableUI.jsm");
+let customizationListener = {
+  onAreaNodeRegistered(aAreaType, aAreaNode) {
+    if (aAreaType == CustomizableUI.AREA_PANEL) {
+      updateZoomUI(aAreaNode.ownerGlobal.gBrowser.selectedBrowser);
+    }
+  }
+};
+customizationListener.onWidgetAdded =
+customizationListener.onWidgetRemoved =
+customizationListener.onWidgetMoved =
+customizationListener.onWidgetInstanceRemoved = function(aWidgetId) {
+  if (aWidgetId == "zoom-controls") {
+    for (let window of CustomizableUI.windows) {
+      updateZoomUI(window.gBrowser.selectedBrowser);
+    }
+  }
+};
+customizationListener.onWidgetReset =
+customizationListener.onWidgetUndoMove = function(aWidgetNode) {
+  if (aWidgetNode.id == "zoom-controls") {
+    updateZoomUI(aWidgetNode.ownerGlobal.gBrowser.selectedBrowser);
+  }
+};
+CustomizableUI.addListener(customizationListener);
+
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -24,33 +24,33 @@ EXTRA_JS_MODULES += [
     'ContentSearch.jsm',
     'ContentWebRTC.jsm',
     'DirectoryLinksProvider.jsm',
     'E10SUtils.jsm',
     'ExtensionsUI.jsm',
     'Feeds.jsm',
     'FormSubmitObserver.jsm',
     'FormValidationHandler.jsm',
+    'FullZoomUI.jsm',
     'HiddenFrame.jsm',
     'LaterRun.jsm',
     'NetworkPrioritizer.jsm',
     'offlineAppCache.jsm',
     'PermissionUI.jsm',
     'PluginContent.jsm',
     'ProcessHangMonitor.jsm',
     'ReaderParent.jsm',
     'RecentWindow.jsm',
     'RemotePrompt.jsm',
     'Sanitizer.jsm',
     'SelfSupportBackend.jsm',
     'SitePermissions.jsm',
     'Social.jsm',
     'SocialService.jsm',
     'TransientPrefs.jsm',
-    'URLBarZoom.jsm',
     'webrtcUI.jsm',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     EXTRA_JS_MODULES += [
         'Windows8WindowFrameColor.jsm',
         'WindowsJumpLists.jsm',
         'WindowsPreviewPerTab.jsm',