Bug 1374048 - Show the sidebar extension icon in the header. r=Gijs, ui-r=shorlander. draft
authorBlake Winton <bwinton@latte.ca>
Tue, 08 Aug 2017 14:31:40 -0400
changeset 646061 34e979c2670c162778ad8c31db7791c0c705bcdd
parent 645833 df9beb781895fcd0493c21e95ad313e0044515ec
child 726120 c895753a6945474916ae0c52264fbe3801abd98a
push id73985
push userbmo:bwinton@mozilla.com
push dateMon, 14 Aug 2017 19:41:43 +0000
reviewersGijs, shorlander
bugs1374048
milestone57.0a1
Bug 1374048 - Show the sidebar extension icon in the header. r=Gijs, ui-r=shorlander. MozReview-Commit-ID: 3FLYauvCs8E
browser/base/content/browser-sidebar.js
browser/base/content/browser.css
browser/components/extensions/ext-sidebarAction.js
--- a/browser/base/content/browser-sidebar.js
+++ b/browser/base/content/browser-sidebar.js
@@ -225,16 +225,25 @@ var SidebarUI = {
       // Remove the |sidebarcommand| attribute, because the element it
       // refers to no longer exists, so we should assume this sidebar
       // panel has been uninstalled. (249883)
       this._box.removeAttribute("sidebarcommand");
     }
   },
 
   /**
+   * Fire a "SidebarShown" event on the sidebar to give any interested parties
+   * a chance to update the button or whatever.
+   */
+  _fireShowEvent() {
+    let event = new CustomEvent("SidebarShown", {bubbles: true});
+    this._switcherTarget.dispatchEvent(event);
+  },
+
+  /**
    * Fire a "SidebarFocused" event on the sidebar's |window| to give the sidebar
    * a chance to adjust focus as needed. An additional event is needed, because
    * we don't want to focus the sidebar when it's opened on startup or in a new
    * window, only when the user opens the sidebar.
    */
   _fireFocusedEvent() {
     let event = new CustomEvent("SidebarFocused", {bubbles: true});
     this.browser.contentWindow.dispatchEvent(event);
@@ -367,21 +376,27 @@ var SidebarUI = {
           // (non-capturing) event handlers. Let it bubble up before firing the
           // SidebarFocused event.
           setTimeout(() => this._fireFocusedEvent(), 0);
 
           // Run the original function for backwards compatibility.
           sidebarOnLoad(event);
 
           resolve();
+
+          // Now that the currentId is updated, fire a show event.
+          this._fireShowEvent();
         }, {capture: true, once: true});
       } else {
         // Older code handled this case, so we do it too.
         this._fireFocusedEvent();
         resolve();
+
+        // Now that the currentId is updated, fire a show event.
+        this._fireShowEvent();
       }
 
       let selBrowser = gBrowser.selectedBrowser;
       selBrowser.messageManager.sendAsyncMessage("Sidebar:VisibilityChange",
         {commandID, isOpen: true}
       );
     });
   },
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -1382,9 +1382,24 @@ toolbarpaletteitem[place="palette"][hidd
 }
 
 /* Page action panel */
 #pageAction-panel-sendToDevice-subview-body:not([state="notready"]) > #pageAction-panel-sendToDevice-notReady,
 #pageAction-urlbar-sendToDevice-subview-body:not([state="notready"]) > #pageAction-urlbar-sendToDevice-notReady {
   display: none;
 }
 
+/* WebExtension Sidebars */
+#sidebar-box[sidebarcommand$="-sidebar-action"] > #sidebar-header > #sidebar-switcher-target > #sidebar-icon {
+  list-style-image: var(--webextension-menuitem-image, inherit);
+  -moz-context-properties: fill;
+  fill: currentColor;
+  width: 16px;
+  height: 16px;
+}
+
+@media (min-resolution: 1.1dppx) {
+  #sidebar-box[sidebarcommand$="-sidebar-action"] > #sidebar-header > #sidebar-switcher-target > #sidebar-icon {
+    list-style-image: var(--webextension-menuitem-image-2x, inherit);
+  }
+}
+
 %include theme-vars.inc.css
--- a/browser/components/extensions/ext-sidebarAction.js
+++ b/browser/components/extensions/ext-sidebarAction.js
@@ -65,16 +65,33 @@ this.sidebarAction = class extends Exten
                                      extension);
 
     // We need to ensure our elements are available before session restore.
     this.windowOpenListener = (window) => {
       this.createMenuItem(window, this.defaults);
     };
     windowTracker.addOpenListener(this.windowOpenListener);
 
+    this.updateHeader = (event) => {
+      let window = event.target.ownerGlobal;
+      let details = this.tabContext.get(window.gBrowser.selectedTab);
+      let header = window.document.getElementById("sidebar-switcher-target");
+      if (window.SidebarUI.currentID === this.id) {
+        this.setMenuIcon(header, details);
+      }
+    };
+
+    this.windowCloseListener = (window) => {
+      let header = window.document.getElementById("sidebar-switcher-target");
+      if (header) {
+        header.removeEventListener("SidebarShown", this.updateHeader);
+      }
+    };
+    windowTracker.addCloseListener(this.windowCloseListener);
+
     sidebarActionMap.set(extension, this);
   }
 
   onReady() {
     this.build();
   }
 
   onShutdown(reason) {
@@ -100,18 +117,21 @@ this.sidebarAction = class extends Exten
       let button = document.getElementById(this.buttonId);
       if (button) {
         button.remove();
       }
       let broadcaster = document.getElementById(this.id);
       if (broadcaster) {
         broadcaster.remove();
       }
+      let header = document.getElementById("sidebar-switcher-target");
+      header.removeEventListener("SidebarShown", this.updateHeader);
     }
     windowTracker.removeOpenListener(this.windowOpenListener);
+    windowTracker.removeCloseListener(this.windowCloseListener);
   }
 
   build() {
     this.tabContext.on("tab-select", // eslint-disable-line mozilla/balanced-listeners
                        (evt, tab) => { this.updateWindow(tab.ownerGlobal); });
 
     let install = this.extension.startupReason === "ADDON_INSTALL";
     let upgrade = ["ADDON_UPGRADE", "ADDON_DOWNGRADE"].includes(this.extension.startupReason);
@@ -160,16 +180,19 @@ this.sidebarAction = class extends Exten
     broadcaster.setAttribute("group", "sidebar");
     broadcaster.setAttribute("label", details.title);
     broadcaster.setAttribute("sidebarurl", this.sidebarUrl(details.panel));
 
     // oncommand gets attached to menuitem, so we use the observes attribute to
     // get the command id we pass to SidebarUI.
     broadcaster.setAttribute("oncommand", "SidebarUI.show(this.getAttribute('observes'))");
 
+    let header = document.getElementById("sidebar-switcher-target");
+    header.addEventListener("SidebarShown", this.updateHeader);
+
     // Insert a menuitem for View->Show Sidebars.
     let menuitem = document.createElementNS(XUL_NS, "menuitem");
     menuitem.setAttribute("id", this.menuId);
     menuitem.setAttribute("observes", this.id);
     menuitem.setAttribute("class", "menuitem-iconic webextension-menuitem");
     this.setMenuIcon(menuitem, details);
 
     // Insert a toolbarbutton for the sidebar dropdown selector.
@@ -227,16 +250,18 @@ this.sidebarAction = class extends Exten
     this.setMenuIcon(menu, tabData);
 
     let button = document.getElementById(this.buttonId);
     this.setMenuIcon(button, tabData);
 
     // Update the sidebar if this extension is the current sidebar.
     if (SidebarUI.currentID === this.id) {
       SidebarUI.title = title;
+      let header = document.getElementById("sidebar-switcher-target");
+      this.setMenuIcon(header, tabData);
       if (SidebarUI.isOpen && urlChanged) {
         SidebarUI.show(this.id);
       }
     }
   }
 
   /**
    * Update the broadcaster and menuitem for a given window.