Bug 1161810 - UITour: Allow opening the Pocket panel via showMenu("pocket"). r=jaws a=dolske
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Mon, 11 May 2015 22:03:45 -0700
changeset 260492 06499c7a81a9
parent 260491 d5ba1bc97911
child 260493 48eaac80d6b5
push id799
push userjdolske@mozilla.com
push date2015-05-14 03:46 +0000
treeherdermozilla-release@11c4678a21bb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws, dolske
bugs1161810
milestone38.0.1
Bug 1161810 - UITour: Allow opening the Pocket panel via showMenu("pocket"). r=jaws a=dolske
browser/components/customizableui/CustomizableUI.jsm
browser/components/uitour/UITour.jsm
browser/components/uitour/test/browser.ini
browser/components/uitour/test/browser_UITour_pocket.js
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -3660,17 +3660,17 @@ Object.freeze(this.CustomizableUI.window
  * widget group - AKA, all instances of a widget across a series of windows.
  * This particular wrapper is only used for widgets created via the provider
  * API.
  */
 function WidgetGroupWrapper(aWidget) {
   this.isGroup = true;
 
   const kBareProps = ["id", "source", "type", "disabled", "label", "tooltiptext",
-                      "showInPrivateBrowsing"];
+                      "showInPrivateBrowsing", "viewId"];
   for (let prop of kBareProps) {
     let propertyName = prop;
     this.__defineGetter__(propertyName, function() aWidget[propertyName]);
   }
 
   this.__defineGetter__("provider", function() CustomizableUI.PROVIDER_API);
 
   this.__defineSetter__("disabled", function(aValue) {
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -183,17 +183,21 @@ this.UITour = {
       query: (aDocument) => {
         let loopBrowser = aDocument.defaultView.LoopUI.browser;
         if (!loopBrowser) {
           return null;
         }
         return loopBrowser.contentDocument.querySelector(".signin-link");
       },
     }],
-    ["pocket", {query: "#pocket-button"}],
+    ["pocket", {
+      allowAdd: true,
+      query: "#pocket-button",
+      widgetName: "pocket-button",
+    }],
     ["privateWindow",  {query: "#privatebrowsing-button"}],
     ["quit",        {query: "#PanelUI-quit"}],
     ["readerMode-urlBar", {query: "#reader-mode-button"}],
     ["search",      {
       infoPanelOffsetX: 18,
       infoPanelPosition: "after_start",
       query: "#searchbar",
       widgetName: "search-container",
@@ -1537,16 +1541,56 @@ this.UITour = {
         }
       });
       panel.addEventListener("popuphidden", this.onPanelHidden);
       panel.addEventListener("popuphiding", this.hideLoopPanelAnnotations);
     } else if (aMenuName == "searchEngines") {
       this.getTarget(aWindow, "searchProvider").then(target => {
         openMenuButton(target.node);
       }).catch(log.error);
+    } else if (aMenuName == "pocket") {
+      this.getTarget(aWindow, "pocket").then(Task.async(function* onPocketTarget(target) {
+        let widgetGroupWrapper = CustomizableUI.getWidget(target.widgetName);
+        if (widgetGroupWrapper.type != "view" || !widgetGroupWrapper.viewId) {
+          log.error("Can't open the pocket menu without a view");
+          return;
+        }
+        let placement = CustomizableUI.getPlacementOfWidget(target.widgetName);
+        if (!placement || !placement.area) {
+          log.error("Can't open the pocket menu without a placement");
+          return;
+        }
+
+        if (placement.area == CustomizableUI.AREA_PANEL) {
+          // Open the appMenu and wait for it if it's not already opened or showing a subview.
+          yield new Promise((resolve, reject) => {
+            if (aWindow.PanelUI.panel.state != "closed") {
+              if (aWindow.PanelUI.multiView.showingSubView) {
+                reject("A subview is already showing");
+                return;
+              }
+
+              resolve();
+              return;
+            }
+
+            aWindow.PanelUI.panel.addEventListener("popupshown", function onShown() {
+              aWindow.PanelUI.panel.removeEventListener("popupshown", onShown);
+              resolve();
+            });
+
+            aWindow.PanelUI.show();
+          });
+        }
+
+        let widgetWrapper = widgetGroupWrapper.forWindow(aWindow);
+        aWindow.PanelUI.showSubView(widgetGroupWrapper.viewId,
+                                    widgetWrapper.anchor,
+                                    placement.area);
+      })).catch(log.error);
     }
   },
 
   hideMenu: function(aWindow, aMenuName) {
     log.debug("hideMenu:", aMenuName);
     function closeMenuButton(aMenuBtn) {
       if (aMenuBtn && aMenuBtn.boxObject)
         aMenuBtn.boxObject.openMenu(false);
--- a/browser/components/uitour/test/browser.ini
+++ b/browser/components/uitour/test/browser.ini
@@ -24,14 +24,16 @@ skip-if = e10s # Bug 1073247 - UITour.js
 skip-if = os == "linux" || e10s # Bug 1073247 - UITour.jsm not e10s friendly.
 [browser_UITour_modalDialog.js]
 run-if = os == "mac" # modal dialog disabling only working on OS X
 skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
 [browser_UITour_observe.js]
 skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly.
 [browser_UITour_panel_close_annotation.js]
 skip-if = true # Disabled due to frequent failures, bugs 1026310 and 1032137
+[browser_UITour_pocket.js]
+skip-if = os == "linux" || e10s || debug # Bug 1073247 - UITour.jsm not e10s friendly.
 [browser_UITour_registerPageID.js]
 skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
 [browser_UITour_sync.js]
 skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
 [browser_UITour_resetProfile.js]
 skip-if = e10s # Bug 1073247 - UITour.jsm not e10s friendly
new file mode 100644
--- /dev/null
+++ b/browser/components/uitour/test/browser_UITour_pocket.js
@@ -0,0 +1,84 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+let gTestTab;
+let gContentAPI;
+let gContentWindow;
+let button;
+
+Components.utils.import("resource:///modules/UITour.jsm");
+
+function test() {
+  UITourTest();
+}
+
+let tests = [
+  taskify(function* test_menu_show_navbar() {
+    ise(button.open, false, "Menu should initially be closed");
+    gContentAPI.showMenu("pocket");
+
+    // The panel gets created dynamically.
+    let widgetPanel = null;
+    yield waitForConditionPromise(() => {
+      widgetPanel = document.getElementById("customizationui-widget-panel");
+      return widgetPanel && widgetPanel.state == "open";
+    }, "Menu should be visible after showMenu()");
+
+    ok(button.open, "Button should know its view is open");
+    ok(!widgetPanel.hasAttribute("noautohide"), "@noautohide shouldn't be on the pocket panel");
+    ok(button.hasAttribute("open"), "Pocket button should know that the menu is open");
+
+    widgetPanel.hidePopup();
+    checkPanelIsHidden(widgetPanel);
+  }),
+  taskify(function* test_menu_show_appMenu() {
+    CustomizableUI.addWidgetToArea("pocket-button", CustomizableUI.AREA_PANEL);
+
+    ise(PanelUI.multiView.hasAttribute("panelopen"), false, "Multiview should initially be closed");
+    gContentAPI.showMenu("pocket");
+
+    yield waitForConditionPromise(() => {
+      return PanelUI.panel.state == "open";
+    }, "Menu should be visible after showMenu()");
+
+    ok(!PanelUI.panel.hasAttribute("noautohide"), "@noautohide shouldn't be on the pocket panel");
+    ok(PanelUI.multiView.showingSubView, "Subview should be open");
+    ok(PanelUI.multiView.hasAttribute("panelopen"), "Multiview should know it's open");
+
+    PanelUI.showMainView();
+    PanelUI.panel.hidePopup();
+    checkPanelIsHidden(PanelUI.panel);
+  }),
+];
+
+// End tests
+
+function checkPanelIsHidden(aPanel) {
+  if (aPanel.parentElement) {
+    is_hidden(aPanel);
+  } else {
+    ok(!aPanel.parentElement, "Widget panel should have been removed");
+  }
+  is(button.hasAttribute("open"), false, "Pocket button should know that the panel is closed");
+}
+
+if (Services.prefs.getBoolPref("browser.pocket.enabled")) {
+  let placement = CustomizableUI.getPlacementOfWidget("pocket-button");
+
+  // Add the button to the nav-bar by default.
+  if (!placement || placement.area != CustomizableUI.AREA_NAVBAR) {
+    CustomizableUI.addWidgetToArea("pocket-button", CustomizableUI.AREA_NAVBAR);
+  }
+  registerCleanupFunction(() => {
+    CustomizableUI.reset();
+  });
+
+  let widgetGroupWrapper = CustomizableUI.getWidget("pocket-button");
+  button = widgetGroupWrapper.forWindow(window).node;
+  ok(button, "Got button node");
+} else {
+  todo(false, "Pocket is disabled so skip its UITour tests");
+  tests = [];
+}