Bug 1348122 - Share code between the customizable zoom control and the location bar's zoom indicator. r=gijs draft
authorDão Gottwald <dao@mozilla.com>
Tue, 21 Mar 2017 09:23:24 +0100
changeset 502105 9d1a215e14757272a6145d1338181a26e710a288
parent 501879 5fe5dcf1c10a4523ba3f0a20295551462c2dae11
child 550060 34c5e93033e670e4c5763e4644263e762eef9a9a
push id50177
push userdgottwald@mozilla.com
push dateTue, 21 Mar 2017 08:24:06 +0000
reviewersgijs
bugs1348122
milestone55.0a1
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',