Bug 1385418 - Remove disabled pocket code for the toolbar button now that it's been replaced by the item in the page action panel. r?Gijs draft
authorDrew Willcoxon <adw@mozilla.com>
Wed, 16 Aug 2017 10:13:15 -0700
changeset 647604 138c8ebcbb6f99fd5a9e18767a6dd30040dced41
parent 647200 4e93516e92e58d166ad37b8544c3230024afb587
child 647613 d7205874abfb855c1dfe16fb83b1f920f00ff0b9
child 647722 f4f1c3f2b331a41a11440b7791f15a0aba2460ba
child 647729 a206d2fd1c3d7d5fa72a13b89203d98a81492390
push id74474
push userdwillcoxon@mozilla.com
push dateWed, 16 Aug 2017 17:15:27 +0000
reviewersGijs
bugs1385418
milestone57.0a1
Bug 1385418 - Remove disabled pocket code for the toolbar button now that it's been replaced by the item in the page action panel. r?Gijs MozReview-Commit-ID: 1wANxaD3QaV
browser/base/content/browser-pageActions.js
browser/base/content/test/performance/browser_startup_images.js
browser/base/content/theme-vars.inc.css
browser/components/customizableui/CustomizableUI.jsm
browser/components/extensions/test/browser/browser_ext_themes_icons.js
browser/components/uitour/UITour.jsm
browser/components/uitour/test/browser_UITour_pocket.js
browser/extensions/pocket/bootstrap.js
browser/extensions/pocket/content/Pocket.jsm
browser/extensions/pocket/content/main.js
browser/extensions/pocket/jar.mn
browser/extensions/pocket/skin/linux/pocket.css
browser/extensions/pocket/skin/osx/pocket.css
browser/extensions/pocket/skin/shared/pocket.css
browser/extensions/pocket/skin/windows/pocket.css
browser/extensions/pocket/test/head.js
browser/modules/PageActions.jsm
browser/modules/test/browser/browser_PageActions.js
testing/profiles/prefs_general.js
--- a/browser/base/content/browser-pageActions.js
+++ b/browser/base/content/browser-pageActions.js
@@ -130,17 +130,17 @@ var BrowserPageActions = {
     }
     buttonNode.addEventListener("command", event => {
       if (panelViewNode) {
         action.subview.onShowing(panelViewNode);
         this.multiViewNode.showSubView(panelViewNode, buttonNode);
         return;
       }
       if (action.wantsIframe) {
-        this._toggleTempPanelForAction(action);
+        this._toggleActivatedActionPanelForAction(action);
         return;
       }
       this.panelNode.hidePopup();
       action.onCommand(event, buttonNode);
     });
     return [buttonNode, panelViewNode];
   },
 
@@ -167,27 +167,55 @@ var BrowserPageActions = {
       buttonNode.addEventListener("command", event => {
         button.onCommand(event, buttonNode);
       });
       bodyNode.appendChild(buttonNode);
     }
     return panelViewNode;
   },
 
-  _toggleTempPanelForAction(action) {
-    let panelNodeID = this._tempPanelID;
-    let panelNode = document.getElementById(panelNodeID);
+  _toggleActivatedActionPanelForAction(action) {
+    let panelNode = this.activatedActionPanelNode;
     if (panelNode) {
       panelNode.hidePopup();
       return null;
     }
 
+    // Before creating the panel, find the best anchor node for it because we'll
+    // bail if there isn't one.  Try each of the following nodes in order, using
+    // the first that's visible.
+    let anchorNode = null;
+    let potentialAnchorNodeIDs = [
+      action.anchorIDOverride || null,
+      this._urlbarButtonNodeIDForActionID(action.id),
+      this.mainButtonNode.id,
+      "identity-icon",
+    ];
+    let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
+                    .getInterface(Ci.nsIDOMWindowUtils);
+    for (let id of potentialAnchorNodeIDs) {
+      if (id) {
+        let node = document.getElementById(id);
+        if (node && !node.hidden) {
+          let bounds = dwu.getBoundsWithoutFlushing(node);
+          if (bounds.height > 0 && bounds.width > 0) {
+            anchorNode = node;
+            break;
+          }
+        }
+      }
+    }
+    if (!anchorNode) {
+      throw new Error(`PageActions: No anchor node for '${action.id}'`);
+    }
+
     panelNode = document.createElement("panel");
-    panelNode.id = panelNodeID;
+    panelNode.id = this._activatedActionPanelID;
     panelNode.classList.add("cui-widget-panel");
+    panelNode.setAttribute("actionID", action.id);
     panelNode.setAttribute("role", "group");
     panelNode.setAttribute("type", "arrow");
     panelNode.setAttribute("flip", "slide");
     panelNode.setAttribute("noautofocus", "true");
     panelNode.setAttribute("tabspecific", "true");
 
     let panelViewNode = null;
     let iframeNode = null;
@@ -218,39 +246,34 @@ var BrowserPageActions = {
       }
     }, { once: true });
 
     if (panelViewNode) {
       action.subview.onPlaced(panelViewNode);
       action.subview.onShowing(panelViewNode);
     }
 
+    // Hide the main page action panel before showing the activated-action
+    // panel.
     this.panelNode.hidePopup();
-
-    let urlbarNodeID = this._urlbarButtonNodeIDForActionID(action.id);
-    let urlbarNode = document.getElementById(urlbarNodeID);
-    let anchorNode;
-    if (urlbarNode && !urlbarNode.hidden) {
-      anchorNode = action.anchorIDOverride ?
-        document.getElementById(action.anchorIDOverride) :
-        urlbarNode;
-    } else {
-      anchorNode = this.mainButtonNode;
-    }
     panelNode.openPopup(anchorNode, "bottomcenter topright");
 
     if (iframeNode) {
       action.onIframeShown(iframeNode, panelNode);
     }
 
     return panelNode;
   },
 
-  get _tempPanelID() {
-    return "pageActionTempPanel";
+  get activatedActionPanelNode() {
+    return document.getElementById(this._activatedActionPanelID);
+  },
+
+  get _activatedActionPanelID() {
+    return "pageActionActivatedActionPanel";
   },
 
   /**
    * Adds or removes as necessary a DOM node for the given action in the urlbar.
    *
    * @param  action (PageActions.Action, required)
    *         The action to place.
    * @param  insertBeforeID (string, required)
@@ -327,17 +350,17 @@ var BrowserPageActions = {
         buttonNode.setAttribute(name, action.nodeAttributes[name]);
       }
     }
     buttonNode.addEventListener("click", event => {
       if (event.button != 0) {
         return;
       }
       if (action.subview || action.wantsIframe) {
-        this._toggleTempPanelForAction(action);
+        this._toggleActivatedActionPanelForAction(action);
         return;
       }
       action.onCommand(event, buttonNode);
     });
     return buttonNode;
   },
 
   _appendPanelSeparator(action) {
@@ -427,17 +450,17 @@ var BrowserPageActions = {
     let node = document.getElementById(id);
     if (node) {
       node.setAttribute("label", action.title);
     }
   },
 
   doCommandForAction(action) {
     if (action.subview || action.wantsIframe) {
-      this._toggleTempPanelForAction(action);
+      this._toggleActivatedActionPanelForAction(action);
       return;
     }
     action.onCommand();
   },
 
   /**
    * Returns the action for a node.
    *
@@ -523,20 +546,21 @@ var BrowserPageActions = {
   mainButtonClicked(event) {
     event.stopPropagation();
     if ((event.type == "click" && event.button != 0) ||
         (event.type == "keypress" && event.charCode != KeyEvent.DOM_VK_SPACE &&
          event.keyCode != KeyEvent.DOM_VK_RETURN)) {
       return;
     }
 
-    // If the temp panel is open and anchored to the main button, close it.
-    let tempPanel = document.getElementById(this._tempPanelID);
-    if (tempPanel && tempPanel.anchorNode.id == this.mainButtonNode.id) {
-      tempPanel.hidePopup();
+    // If the activated-action panel is open and anchored to the main button,
+    // close it.
+    let panelNode = this.activatedActionPanelNode;
+    if (panelNode && panelNode.anchorNode.id == this.mainButtonNode.id) {
+      panelNode.hidePopup();
       return;
     }
 
     if (this.panelNode.state == "open") {
       this.panelNode.hidePopup();
     } else if (this.panelNode.state == "closed") {
       this.showPanel(event);
     }
--- a/browser/base/content/test/performance/browser_startup_images.js
+++ b/browser/base/content/test/performance/browser_startup_images.js
@@ -32,16 +32,20 @@ const whitelist = [
   {
     file: "chrome://browser/skin/bookmark-hollow.svg",
     platforms: ["linux", "win", "macosx"],
   },
   {
     file: "chrome://browser/skin/page-action.svg",
     platforms: ["linux", "win", "macosx"],
   },
+  {
+    file: "chrome://pocket-shared/skin/pocket.svg",
+    platforms: ["linux", "win", "macosx"],
+  },
 
   // Shared entries
   {
     file: "chrome://browser/skin/arrow-left.svg",
     platforms: ["linux", "win", "macosx"],
   },
   {
     file: "chrome://browser/skin/arrow-dropdown-16.svg",
--- a/browser/base/content/theme-vars.inc.css
+++ b/browser/base/content/theme-vars.inc.css
@@ -121,20 +121,16 @@
 :root[lwthemeicons~="--email_link-icon"] #email-link-button:-moz-lwtheme {
   list-style-image: var(--email_link-icon) !important;
 }
 
 :root[lwthemeicons~="--forget-icon"] #panic-button:-moz-lwtheme {
   list-style-image: var(--forget-icon) !important;
 }
 
-:root[lwthemeicons~="--pocket-icon"] #pocket-button:-moz-lwtheme {
-  list-style-image: var(--pocket-icon) !important;
-}
-
 :root[lwthemeicons~="--bookmark_star-icon"] #star-button:-moz-lwtheme,
 :root[lwthemeicons~="--bookmark_menu-icon"] #bookmarks-menu-button:-moz-lwtheme,
 :root[lwthemeicons~="--back-icon"] #back-button:-moz-lwtheme,
 :root[lwthemeicons~="--forward-icon"] #forward-button:-moz-lwtheme,
 :root[lwthemeicons~="--reload-icon"] #reload-button:-moz-lwtheme,
 :root[lwthemeicons~="--stop-icon"] #stop-button:-moz-lwtheme,
 :root[lwthemeicons~="--bookmark_star-icon"] #bookmarks-menu-button:-moz-lwtheme,
 :root[lwthemeicons~="--bookmark_menu-icon"] #bookmarks-menu-button[cui-areatype='toolbar'] > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon:-moz-lwtheme,
@@ -156,12 +152,11 @@
 :root[lwthemeicons~="--developer-icon"] #developer-button:-moz-lwtheme,
 :root[lwthemeicons~="--synced_tabs-icon"] #sync-button:-moz-lwtheme,
 :root[lwthemeicons~="--open_file-icon"] #open-file-button:-moz-lwtheme,
 :root[lwthemeicons~="--sidebars-icon"] #sidebar-button:-moz-lwtheme,
 :root[lwthemeicons~="--share_page-icon"] #social-share-button:-moz-lwtheme,
 :root[lwthemeicons~="--subscribe-icon"] #feed-button:-moz-lwtheme,
 :root[lwthemeicons~="--text_encoding-icon"] #characterencoding-button:-moz-lwtheme,
 :root[lwthemeicons~="--email_link-icon"] #email-link-button:-moz-lwtheme,
-:root[lwthemeicons~="--forget-icon"] #panic-button:-moz-lwtheme,
-:root[lwthemeicons~="--pocket-icon"] #pocket-button:-moz-lwtheme {
+:root[lwthemeicons~="--forget-icon"] #panic-button:-moz-lwtheme {
   -moz-image-region: rect(0, 16px, 16px, 0) !important;
 }
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -60,17 +60,16 @@ const kSubviewEvents = [
 var kVersion = 10;
 
 /**
  * Buttons removed from built-ins by version they were removed. kVersion must be
  * bumped any time a new id is added to this. Use the button id as key, and
  * version the button is removed in as the value.  e.g. "pocket-button": 5
  */
 var ObsoleteBuiltinButtons = {
-  "pocket-button": 6
 };
 
 /**
  * gPalette is a map of every widget that CustomizableUI.jsm knows about, keyed
  * on their IDs.
  */
 var gPalette = new Map();
 
@@ -200,23 +199,16 @@ var CustomizableUIInternal = {
       "library-button",
       "sidebar-button",
     ];
 
     if (AppConstants.MOZ_DEV_EDITION) {
       navbarPlacements.splice(2, 0, "developer-button");
     }
 
-    // Place this last, when createWidget is called for pocket, it will
-    // append to the toolbar.
-    if (Services.prefs.getBoolPref("extensions.pocket.enabled", false) &&
-        Services.prefs.getBoolPref("extensions.pocket.disablePageAction", false)) {
-      navbarPlacements.push("pocket-button");
-    }
-
     this.registerArea(CustomizableUI.AREA_NAVBAR, {
       legacy: true,
       type: CustomizableUI.TYPE_TOOLBAR,
       overflowable: true,
       defaultPlacements: navbarPlacements,
       defaultCollapsed: false,
     }, true);
 
--- a/browser/components/extensions/test/browser/browser_ext_themes_icons.js
+++ b/browser/components/extensions/test/browser/browser_ext_themes_icons.js
@@ -133,17 +133,16 @@ async function runTestWithIcons(icons) {
     ["synced_tabs", "#sync-button", "sync-button"],
     ["open_file", "#open-file-button", "open-file-button"],
     ["sidebars", "#sidebar-button", "sidebar-button"],
     ["share_page", "#social-share-button", "social-share-button"],
     ["subscribe", "#feed-button", "feed-button"],
     ["text_encoding", "#characterencoding-button", "characterencoding-button"],
     ["email_link", "#email-link-button", "email-link-button"],
     ["forget", "#panic-button", "panic-button"],
-    ["pocket", "#pocket-button", "pocket-button"],
   ];
   // We add these at the beginning because adding them at the end can end up
   // putting them in the overflow panel, where they aren't displayed the same way.
   ICON_INFO.unshift(["bookmark_star", "#star-button"]);
   ICON_INFO.unshift(["bookmark_menu", "#bookmarks-menu-button", "bookmarks-menu-button"]);
 
   window.maximize();
 
@@ -207,17 +206,16 @@ add_task(async function test_all_icons()
     ["synced_tabs", "fox.svg"],
     ["open_file", "fox.svg"],
     ["sidebars", "fox.svg"],
     ["share_page", "fox.svg"],
     ["subscribe", "fox.svg"],
     ["text_encoding", "fox.svg"],
     ["email_link", "fox.svg"],
     ["forget", "fox.svg"],
-    ["pocket", "fox.svg"],
   ];
   await runTestWithIcons(icons);
 });
 
 add_task(async function teardown() {
   CustomizableUI.reset();
   window.restore();
 });
@@ -249,17 +247,16 @@ add_task(async function test_some_icons(
     ["synced_tabs", ""],
     ["open_file", ""],
     ["sidebars", ""],
     ["share_page", ""],
     ["subscribe", ""],
     ["text_encoding", ""],
     ["email_link", ""],
     ["forget", ""],
-    ["pocket", "fox.svg"],
   ];
   await runTestWithIcons(icons);
 });
 
 add_task(async function teardown() {
   CustomizableUI.reset();
   window.restore();
 });
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -27,16 +27,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
   "resource:///modules/BrowserUITelemetry.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ProfileAge",
   "resource://gre/modules/ProfileAge.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ReaderParent",
   "resource:///modules/ReaderParent.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PageActions",
+  "resource:///modules/PageActions.jsm");
 
 // See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
 const PREF_LOG_LEVEL      = "browser.uitour.loglevel";
 const PREF_SEENPAGEIDS    = "browser.uitour.seenPageIDs";
 
 const BACKGROUND_PAGE_ACTIONS_ALLOWED = new Set([
   "forceShowReaderIcon",
   "getConfiguration",
@@ -146,17 +148,16 @@ this.UITour = {
       widgetName: "panic-button",
     }],
     ["help",        {query: "#appMenu-help-button"}],
     ["home",        {query: "#home-button"}],
     ["library",     {query: "#appMenu-library-button"}],
     ["pocket", {
       allowAdd: true,
       query: "#pocket-button",
-      widgetName: "pocket-button",
     }],
     ["privateWindow", {query: "#appMenu-private-window-button"}],
     ["quit",        {query: "#appMenu-quit-button"}],
     ["readerMode-urlBar", {query: "#reader-mode-button"}],
     ["search",      {
       infoPanelOffsetX: 18,
       infoPanelPosition: "after_start",
       query: "#searchbar",
@@ -1411,54 +1412,22 @@ this.UITour = {
       this.recreatePopup(popup);
 
       // Open the control center
       if (aOpenCallback) {
         popup.addEventListener("popupshown", aOpenCallback, { once: true });
       }
       aWindow.document.getElementById("identity-box").click();
     } else if (aMenuName == "pocket") {
-      this.getTarget(aWindow, "pocket").then(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.
-          await 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() {
-              resolve();
-            }, {once: true});
-
-            aWindow.PanelUI.show();
-          });
-        }
-
-        let widgetWrapper = widgetGroupWrapper.forWindow(aWindow);
-        aWindow.PanelUI.showSubView(widgetGroupWrapper.viewId,
-                                    widgetWrapper.anchor,
-                                    placement.area);
-      }).catch(log.error);
+      let pageAction = PageActions.actionForID("pocket");
+      if (!pageAction) {
+        log.error("Can't open the pocket menu without a page action");
+        return;
+      }
+      pageAction.doCommand(aWindow);
     } else if (aMenuName == "urlbar") {
       this.getTarget(aWindow, "urlbar").then(target => {
         let urlbar = target.node;
         if (aOpenCallback) {
           urlbar.popup.addEventListener("popupshown", aOpenCallback, { once: true });
         }
         urlbar.focus();
         // To demonstrate the ability of searching, we type "Firefox" in advance
--- a/browser/components/uitour/test/browser_UITour_pocket.js
+++ b/browser/components/uitour/test/browser_UITour_pocket.js
@@ -1,82 +1,34 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 var gTestTab;
 var gContentAPI;
 var gContentWindow;
-var button;
 
-function test() {
-  UITourTest();
-}
-
-var tests = [
-  taskify(async function test_menu_show_navbar() {
-    is(button.open, false, "Menu should initially be closed");
-    gContentAPI.showMenu("pocket");
+add_task(setup_UITourTest);
 
-    // The panel gets created dynamically.
-    let widgetPanel = null;
-    await 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(async function test_menu_show_appMenu() {
-    CustomizableUI.addWidgetToArea("pocket-button", CustomizableUI.AREA_PANEL);
-
-    is(PanelUI.multiView.hasAttribute("panelopen"), false, "Multiview should initially be closed");
-    gContentAPI.showMenu("pocket");
-
-    await waitForConditionPromise(() => {
-      return PanelUI.panel.state == "open";
-    }, "Menu should be visible after showMenu()");
+add_UITour_task(async function test_menu_show() {
+  let panel = BrowserPageActions.activatedActionPanelNode;
+  Assert.ok(!panel || panel.state == "closed",
+            "Pocket panel should initially be closed");
+  gContentAPI.showMenu("pocket");
 
-    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");
+  // The panel gets created dynamically.
+  panel = null;
+  await waitForConditionPromise(() => {
+    panel = BrowserPageActions.activatedActionPanelNode;
+    return panel && panel.state == "open";
+  }, "Menu should be visible after showMenu()");
 
-    PanelUI.showMainView();
-    PanelUI.panel.hidePopup();
-    checkPanelIsHidden(PanelUI.panel);
-  }),
-];
-
-// End tests
+  Assert.ok(!panel.hasAttribute("noautohide"), "@noautohide shouldn't be on the pocket panel");
 
-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("extensions.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();
+  panel.hidePopup();
+  await new Promise(resolve => {
+    panel = BrowserPageActions.activatedActionPanelNode;
+    if (!panel || panel.state == "closed") {
+      resolve();
+    }
   });
-
-  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 = [];
-}
+});
--- a/browser/extensions/pocket/bootstrap.js
+++ b/browser/extensions/pocket/bootstrap.js
@@ -11,33 +11,31 @@ Cu.import("resource://gre/modules/XPCOMU
 Cu.import("resource://services-common/utils.js");
 Cu.import("resource://gre/modules/AppConstants.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AboutPocket",
                                   "chrome://pocket/content/AboutPocket.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AddonManagerPrivate",
                                   "resource://gre/modules/AddonManager.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
                                   "resource://gre/modules/BrowserUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
-                                  "resource:///modules/CustomizableUI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PageActions",
                                   "resource:///modules/PageActions.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Pocket",
                                   "chrome://pocket/content/Pocket.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode",
                                   "resource://gre/modules/ReaderMode.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
                                   "resource:///modules/RecentWindow.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 XPCOMUtils.defineLazyGetter(this, "gPocketBundle", function() {
   return Services.strings.createBundle("chrome://pocket/locale/pocket.properties");
 });
 XPCOMUtils.defineLazyGetter(this, "gPocketStyleURI", function() {
-  return Services.io.newURI("chrome://pocket/skin/pocket.css");
+  return Services.io.newURI("chrome://pocket-shared/skin/pocket.css");
 });
 
 // Due to bug 1051238 frame scripts are cached forever, so we can't update them
 // as a restartless add-on. The Math.random() is the work around for this.
 const PROCESS_SCRIPT = "chrome://pocket/content/pocket-content-process.js?" + Math.random();
 
 const PREF_BRANCH = "extensions.pocket.";
 const PREFS = {
@@ -71,115 +69,30 @@ function setDefaultPrefs() {
 function createElementWithAttrs(document, type, attrs) {
   let element = document.createElement(type);
   Object.keys(attrs).forEach(function(attr) {
     element.setAttribute(attr, attrs[attr]);
   })
   return element;
 }
 
-function CreatePocketWidget(reason) {
-  let id = "pocket-button"
-  let widget = CustomizableUI.getWidget(id);
-  // The widget is only null if we've created then destroyed the widget.
-  // Once we've actually called createWidget the provider will be set to
-  // PROVIDER_API.
-  if (widget && widget.provider == CustomizableUI.PROVIDER_API)
-    return;
-  // if upgrading from builtin version and the button was placed in ui,
-  // seenWidget will not be null
-  let seenWidget = CustomizableUI.getPlacementOfWidget("pocket-button", false, true);
-  let pocketButton = {
-    id: "pocket-button",
-    defaultArea: CustomizableUI.AREA_NAVBAR,
-    introducedInVersion: "pref",
-    type: "view",
-    tabSpecific: true,
-    viewId: "PanelUI-pocketView",
-    label: gPocketBundle.GetStringFromName("pocket-button.label"),
-    tooltiptext: gPocketBundle.GetStringFromName("pocket-button.tooltiptext"),
-    // Use forwarding functions here to avoid loading Pocket.jsm on startup:
-    onBeforeCommand() {
-      // We need to use onBeforeCommand to calculate the height
-      // of the pocket-button before it is opened since we need
-      // the height of the button to perform the animation that is
-      // triggered off of [open="true"].
-      return Pocket.onBeforeCommand.apply(this, arguments);
-    },
-    onViewShowing() {
-      return Pocket.onPanelViewShowing.apply(this, arguments);
-    },
-    onViewHiding() {
-      return Pocket.onPanelViewHiding.apply(this, arguments);
-    },
-    onBeforeCreated(doc) {
-      // Bug 1223127,CUI should make this easier to do.
-      if (doc.getElementById("PanelUI-pocketView"))
-        return;
-      let view = doc.createElement("panelview");
-      view.id = "PanelUI-pocketView";
-      let panel = doc.createElement("vbox");
-      panel.setAttribute("class", "panel-subview-body");
-      view.appendChild(panel);
-      doc.getElementById("PanelUI-multiView").appendChild(view);
-    },
-    onCreated(node) {
-      if (Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled")) {
-        let doc = node.ownerDocument;
-        let box = doc.createElement("box");
-        box.classList.add("toolbarbutton-animatable-box");
-        let image = doc.createElement("image");
-        image.classList.add("toolbarbutton-animatable-image");
-        box.appendChild(image);
-        node.appendChild(box);
-        node.setAttribute("animationsenabled", "true");
-      }
-    },
-  };
-
-  CustomizableUI.createWidget(pocketButton);
-  CustomizableUI.addListener(pocketButton);
-  // placed is null if location is palette
-  let placed = CustomizableUI.getPlacementOfWidget("pocket-button");
-
-  // a first time install will always have placed the button somewhere, and will
-  // not have a placement prior to creating the widget. Thus, !seenWidget &&
-  // placed.
-  if (reason == ADDON_ENABLE && !seenWidget && placed) {
-    // initially place the button after the bookmarks button if it is in the UI
-    let widgets = CustomizableUI.getWidgetIdsInArea(CustomizableUI.AREA_NAVBAR);
-    let bmbtn = widgets.indexOf("bookmarks-menu-button");
-    if (bmbtn > -1) {
-      CustomizableUI.moveWidgetWithinArea("pocket-button", bmbtn + 1);
-    }
-  }
-}
 
 function isPocketEnabled() {
-  return PocketPageAction.shouldUse ? PocketPageAction.enabled :
-         !!CustomizableUI.getPlacementOfWidget("pocket-button");
+  return PocketPageAction.enabled;
 }
 
 var PocketPageAction = {
   pageAction: null,
   urlbarNode: null,
 
-  get shouldUse() {
-    return !Services.prefs.getBranch(PREF_BRANCH)
-                    .getBoolPref("disablePageAction", false);
-  },
-
   get enabled() {
     return !!this.pageAction;
   },
 
   init() {
-    if (!this.shouldUse) {
-      return;
-    }
     let id = "pocket";
     this.pageAction = PageActions.actionForID(id);
     if (!this.pageAction) {
       this.pageAction = PageActions.addAction(new PageActions.Action({
         id,
         title: gPocketBundle.GetStringFromName("pocket-button.label"),
         shownInUrlbar: true,
         wantsIframe: true,
@@ -210,32 +123,38 @@ var PocketPageAction = {
           pocketButton.classList.add("urlbar-icon");
 
           wrapper.appendChild(pocketButton);
           wrapper.appendChild(animatableBox);
           animatableBox.appendChild(animatableImage);
           let iconBox = doc.getElementById("page-action-buttons");
           iconBox.appendChild(wrapper);
           wrapper.hidden = true;
+
           wrapper.addEventListener("click", event => {
-            PocketPageAction.onUrlbarNodeClicked(event);
+            if (event.type == "click" && event.button != 0) {
+              return;
+            }
+            this.doCommand(event.target.ownerGlobal);
           });
         },
         onPlacedInPanel(panelNode, urlbarNode) {
           PocketOverlay.onWindowOpened(panelNode.ownerGlobal);
         },
         onIframeShown(iframe, panel) {
           Pocket.onShownInPhotonPageActionPanel(panel, iframe);
 
           let doc = panel.ownerDocument;
           let urlbarNode = doc.getElementById("pocket-button-box");
           if (!urlbarNode || urlbarNode.hidden) {
             return;
           }
 
+          BrowserUtils.setToolbarButtonHeightProperty(urlbarNode);
+
           PocketPageAction.urlbarNode = urlbarNode;
           PocketPageAction.urlbarNode.setAttribute("open", "true");
           if (Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled")) {
             PocketPageAction.urlbarNode.setAttribute("animate", "true");
           }
         },
         onIframeHiding(iframe, panel) {
           if (iframe.getAttribute("itemAdded") == "true") {
@@ -247,16 +166,17 @@ var PocketPageAction = {
             return;
           }
           PocketPageAction.urlbarNode.removeAttribute("animate");
           PocketPageAction.urlbarNode.removeAttribute("open");
           PocketPageAction.urlbarNode = null;
         },
       }));
     }
+    Pocket.pageAction = this.pageAction;
   },
 
   shutdown() {
     if (!this.pageAction) {
       return;
     }
 
     for (let win of browserWindows()) {
@@ -266,28 +186,16 @@ var PocketPageAction = {
         pocketButtonBox.remove();
       }
     }
 
     this.pageAction.remove();
     this.pageAction = null;
   },
 
-  onUrlbarNodeClicked(event) {
-    if (event.type == "click" && event.button != 0) {
-      return;
-    }
-
-    BrowserUtils.setToolbarButtonHeightProperty(event.target);
-
-    let win = event.target.ownerGlobal;
-    let browserPageActions = win.BrowserPageActions;
-    browserPageActions.doCommandForAction(PocketPageAction.pageAction);
-  },
-
   startLibraryAnimation(doc) {
     var libraryButton = doc.getElementById("library-button");
     if (!Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled") ||
         !libraryButton ||
         libraryButton.getAttribute("cui-areatype") == "menu-panel" ||
         libraryButton.getAttribute("overflowedItem") == "true" ||
         !libraryButton.closest("#nav-bar")) {
       return;
@@ -426,36 +334,18 @@ var PocketReader = {
           break;
         message.target.messageManager.
           sendAsyncMessage("Reader:AddButton", { id: "pocket-button",
                                                  title: gPocketBundle.GetStringFromName("pocket-button.tooltiptext"),
                                                  image: "chrome://pocket/content/panels/img/pocket.svg#pocket-mark"});
         break;
       }
       case "Reader:Clicked-pocket-button": {
-        let doc = message.target.ownerDocument;
-        if (PocketPageAction.shouldUse) {
-          // TODO: PageActions should make this easier.
-          let event = new doc.defaultView.CustomEvent("command");
-          let panelButton = doc.getElementById("pageAction-panel-pocket");
-          panelButton.dispatchEvent(event);
-        } else {
-          let pocketWidget = doc.getElementById("pocket-button");
-          let placement = CustomizableUI.getPlacementOfWidget("pocket-button");
-          if (placement) {
-            if (placement.area == CustomizableUI.AREA_PANEL) {
-              doc.defaultView.PanelUI.show().then(function() {
-                // The DOM node might not exist yet if the panel wasn't opened before.
-                pocketWidget = doc.getElementById("pocket-button");
-                pocketWidget.doCommand();
-              });
-            } else {
-              pocketWidget.doCommand();
-            }
-          }
+        if (PocketPageAction.pageAction) {
+          PocketPageAction.pageAction.doCommand(message.target.ownerGlobal);
         }
         break;
       }
     }
   }
 }
 
 
@@ -478,43 +368,33 @@ var PocketOverlay = {
   startup(reason) {
     let styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"]
                               .getService(Ci.nsIStyleSheetService);
     this._sheetType = styleSheetService.AUTHOR_SHEET;
     this._cachedSheet = styleSheetService.preloadSheet(gPocketStyleURI,
                                                        this._sheetType);
     Services.ppmm.loadProcessScript(PROCESS_SCRIPT, true);
     PocketReader.startup();
-    if (PocketPageAction.shouldUse) {
-      PocketPageAction.init();
-    } else {
-      CustomizableUI.addListener(this);
-      CreatePocketWidget(reason);
-    }
+    PocketPageAction.init();
     PocketContextMenu.init();
     for (let win of browserWindows()) {
       this.onWindowOpened(win);
     }
   },
   shutdown(reason) {
     let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
                  .getService(Ci.nsIMessageBroadcaster);
     ppmm.broadcastAsyncMessage("PocketShuttingDown");
     // Although the ppmm loads the scripts into the chrome process as well,
     // we need to manually unregister here anyway to ensure these aren't part
     // of the chrome process and avoid errors.
     AboutPocket.aboutSaved.unregister();
     AboutPocket.aboutSignup.unregister();
 
-    if (PocketPageAction.shouldUse) {
-      PocketPageAction.shutdown();
-    } else {
-      CustomizableUI.removeListener(this);
-      CustomizableUI.destroyWidget("pocket-button");
-    }
+    PocketPageAction.shutdown();
 
     for (let window of browserWindows()) {
       for (let id of ["panelMenu_pocket", "menu_pocket", "BMB_pocket",
                       "panelMenu_pocketSeparator", "menu_pocketSeparator",
                       "BMB_pocketSeparator", "appMenu-library-pocket-button"]) {
         let element = window.document.getElementById(id) ||
                       window.gNavToolbox.palette.querySelector("#" + id);
         if (element)
@@ -532,19 +412,16 @@ var PocketOverlay = {
     PocketReader.shutdown();
   },
   onWindowOpened(window) {
     if (window.hasOwnProperty("pktUI"))
       return;
     this.setWindowScripts(window);
     this.addStyles(window);
     this.updateWindow(window);
-    if (PocketPageAction.shouldUse) {
-      this.updateWindowAfterWidgetPlaced(window);
-    }
   },
   setWindowScripts(window) {
     XPCOMUtils.defineLazyModuleGetter(window, "Pocket",
                                       "chrome://pocket/content/Pocket.jsm");
     // Can't use XPCOMUtils for these because the scripts try to define the variables
     // on window, and so the defineProperty inside defineLazyGetter fails.
     Object.defineProperty(window, "pktApi", pktUIGetter("pktApi", window));
     Object.defineProperty(window, "pktUI", pktUIGetter("pktUI", window));
@@ -623,43 +500,17 @@ var PocketOverlay = {
         "id": "appMenu-library-pocket-button",
         "label": gPocketBundle.GetStringFromName("pocketMenuitem.label"),
         "class": "subviewbutton subviewbutton-iconic",
         "oncommand": "openUILink(Pocket.listURL, event);",
         "hidden": hidden
       });
       sib.parentNode.insertBefore(menu, sib);
     }
-  },
-  onWidgetAfterDOMChange(aWidgetNode) {
-    if (aWidgetNode.id != "pocket-button") {
-      return;
-    }
-    this.updateWindowAfterWidgetPlaced(aWidgetNode.ownerGlobal);
-  },
 
-  updateWindowAfterWidgetPlaced(browserWindow) {
-    let doc = browserWindow.document;
-    let hidden = !isPocketEnabled();
-    let elementIds = [
-      "panelMenu_pocket",
-      "menu_pocket",
-      "BMB_pocket",
-      "appMenu-library-pocket-button",
-    ];
-    for (let elementId of elementIds) {
-      let element = doc.getElementById(elementId);
-      if (element) {
-        element.hidden = hidden;
-        let sep = doc.getElementById(elementId + "Separator");
-        if (sep) {
-          sep.hidden = hidden;
-        }
-      }
-    }
     // enable or disable reader button
     PocketReader.hidden = hidden;
   },
 
   addStyles(win) {
     let utils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
     utils.addSheet(this._cachedSheet, this._sheetType);
   },
--- a/browser/extensions/pocket/content/Pocket.jsm
+++ b/browser/extensions/pocket/content/Pocket.jsm
@@ -7,18 +7,16 @@ const {classes: Cc, interfaces: Ci, util
 
 this.EXPORTED_SYMBOLS = ["Pocket"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
   "resource://gre/modules/BrowserUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
-  "resource:///modules/CustomizableUI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode",
   "resource://gre/modules/ReaderMode.jsm");
 
 var Pocket = {
   get site() { return Services.prefs.getCharPref("extensions.pocket.site"); },
   get listURL() { return "https://" + Pocket.site + "/?src=ff_ext"; },
 
   /**
@@ -87,27 +85,23 @@ var Pocket = {
   onPanelViewHiding(event) {
     let window = event.target.ownerGlobal;
     window.pktUI.pocketPanelDidHide(event);
   },
 
   _urlToSave: null,
   _titleToSave: null,
   savePage(browser, url, title) {
-    let document = browser.ownerDocument;
-    let pocketWidget = document.getElementById("pocket-button");
-    let placement = CustomizableUI.getPlacementOfWidget("pocket-button");
-    if (!placement)
-      return;
-
-    this._urlToSave = url;
-    this._titleToSave = title;
-    if (placement.area == CustomizableUI.AREA_PANEL) {
-      let win = document.defaultView;
-      win.PanelUI.show().then(function() {
-        pocketWidget = document.getElementById("pocket-button");
-        pocketWidget.doCommand();
-      });
-    } else {
-      pocketWidget.doCommand();
+    if (this.pageAction) {
+      this._urlToSave = url;
+      this._titleToSave = title;
+      this.pageAction.doCommand(browser.ownerGlobal);
     }
   },
+
+  get pageAction() {
+    return this._pageAction;
+  },
+  set pageAction(pageAction) {
+    return this._pageAction = pageAction;
+  },
+  _pageAction: null,
 };
--- a/browser/extensions/pocket/content/main.js
+++ b/browser/extensions/pocket/content/main.js
@@ -333,27 +333,20 @@ var pktUI = (function() {
      * options = {
      *  width: ,
      *  height: ,
      *  animate [default false]
      * }
      */
     function resizePanel(options) {
         var iframe = getPanelFrame();
-        var subview = getSubview();
 
-        if (subview) {
-          // Use the subview's size
-          iframe.style.width = "100%";
-          iframe.style.height = subview.parentNode.clientHeight + "px";
-        } else {
-          // Set an explicit size, panel will adapt.
-          iframe.style.width  = options.width + "px";
-          iframe.style.height = options.height + "px";
-        }
+        // Set an explicit size, panel will adapt.
+        iframe.style.width  = options.width + "px";
+        iframe.style.height = options.height + "px";
     }
 
     /**
      * Called when the signup and saved panel was hidden
      */
     function panelDidHide() {
         // clear the onShow and onHide values
         _currentPanelDidShow = null;
@@ -572,49 +565,21 @@ var pktUI = (function() {
 
     var photonPageActionPanelFrame;
 
     function setPhotonPageActionPanelFrame(frame) {
         photonPageActionPanelFrame = frame;
     }
 
     function getPanelFrame() {
-        if (photonPageActionPanelFrame) {
-            return photonPageActionPanelFrame;
-        }
-
-        var frame = document.getElementById("pocket-panel-iframe");
-        if (!frame) {
-            var frameParent = document.getElementById("PanelUI-pocketView").firstChild;
-            frame = document.createElement("iframe");
-            frame.id = "pocket-panel-iframe";
-            frame.setAttribute("type", "content");
-            frameParent.appendChild(frame);
-        }
-        return frame;
-    }
-
-    function getSubview() {
-        if (photonPageActionPanelFrame) {
-            return null;
-        }
-
-        var view = document.getElementById("PanelUI-pocketView");
-        if (view && view.getAttribute("current") == "true" && !view.getAttribute("mainview"))
-            return view;
-        return null;
+        return photonPageActionPanelFrame;
     }
 
     function isInOverflowMenu() {
-        if (photonPageActionPanelFrame) {
-            return false;
-        }
-
-        var subview = getSubview();
-        return !!subview;
+        return false;
     }
 
     function getFirefoxAccountSignedInUser(callback) {
         fxAccounts.getSignedInUser().then(userData => {
             callback(userData);
         }).then(null, error => {
             callback();
         });
--- a/browser/extensions/pocket/jar.mn
+++ b/browser/extensions/pocket/jar.mn
@@ -7,23 +7,20 @@
 % skin pocket classic/1.0 %skin/linux/ os=LikeUnix
 % skin pocket classic/1.0 %skin/osx/ os=Darwin
 % skin pocket classic/1.0 %skin/windows/ os=WINNT
 % skin pocket-shared classic/1.0 %skin/shared/
   content/  (content/*)
   skin/shared (skin/shared/*)
 #ifdef XP_WIN
   skin/windows/ (skin/windows/*.png)
-  skin/windows/pocket.css (skin/windows/pocket.css)
 #elifdef XP_MACOSX
   skin/osx/ (skin/osx/*.png)
-  skin/osx/pocket.css (skin/osx/pocket.css)
 #else
   skin/linux/ (skin/linux/*.png)
-  skin/linux/pocket.css (skin/linux/pocket.css)
 #endif
 
 # windows overrides
 % override chrome://pocket/skin/menuPanel.png             chrome://pocket/skin/menuPanel-aero.png            os=WINNT osversion=6
 % override chrome://pocket/skin/menuPanel.png             chrome://pocket/skin/menuPanel-aero.png            os=WINNT osversion=6.1
 % override chrome://pocket/skin/menuPanel@2x.png          chrome://pocket/skin/menuPanel-aero@2x.png         os=WINNT osversion=6
 % override chrome://pocket/skin/menuPanel@2x.png          chrome://pocket/skin/menuPanel-aero@2x.png         os=WINNT osversion=6.1
 % override chrome://pocket/skin/menuPanel.png             chrome://pocket/skin/menuPanel-yosemite.png        os=Darwin osversion>=10.10
deleted file mode 100644
--- a/browser/extensions/pocket/skin/linux/pocket.css
+++ /dev/null
@@ -1,10 +0,0 @@
-@import url("chrome://pocket-shared/skin/pocket.css");
-
-#nav-bar #pocket-button > .toolbarbutton-icon {
-  padding: calc(var(--toolbarbutton-inner-padding) - 1px);
-}
-
-:-moz-any(#TabsToolbar, .widget-overflow-list) #pocket-button > .toolbarbutton-icon {
-    max-width: 18px;
-    padding: 0;
-}
deleted file mode 100644
--- a/browser/extensions/pocket/skin/osx/pocket.css
+++ /dev/null
@@ -1,9 +0,0 @@
-@import url("chrome://pocket-shared/skin/pocket.css");
-
-#nav-bar #pocket-button > .toolbarbutton-icon {
-  padding: calc(var(--toolbarbutton-inner-padding) - 1px);
-}
-
-#PanelUI-pocketView[mainview=true] > .panel-subview-body > #pocket-panel-iframe {
-  border-radius: var(--arrowpanel-border-radius);
-}
--- a/browser/extensions/pocket/skin/shared/pocket.css
+++ b/browser/extensions/pocket/skin/shared/pocket.css
@@ -1,23 +1,13 @@
-/* Bug 1164419 - increase Pocket panel size to accomidate wider Russian text. */
-panelmultiview[mainViewId=PanelUI-pocketView] > .panel-viewcontainer > .panel-viewstack > .panel-mainview:not([panelid="PanelUI-popup"]) {
-  max-width: 33em; /* standaloneSubviewWidth + 3 */
-}
-
-.cui-widget-panel[viewId="PanelUI-pocketView"] > .panel-arrowcontainer > .panel-arrowcontent {
+#pageActionActivatedActionPanel[actionID="pocket"] > .panel-arrowcontainer > .panel-arrowcontent {
   padding-top: 0;
   padding-bottom: 0;
 }
 
-#PanelUI-pocketView > .panel-subview-body,
-#PanelUI-pocketView {
-  overflow: visible;
-}
-
 #pocket-button {
   list-style-image: url("chrome://pocket-shared/skin/pocket.svg");
 }
 
 #pocket-button-box[animate="true"] > #pocket-button,
 #pocket-button[open="true"][animationsenabled] > .toolbarbutton-icon {
   fill: transparent;
 }
deleted file mode 100644
--- a/browser/extensions/pocket/skin/windows/pocket.css
+++ /dev/null
@@ -1,10 +0,0 @@
-@import url("chrome://pocket-shared/skin/pocket.css");
-
-#nav-bar #pocket-button > .toolbarbutton-icon {
-  padding: calc(var(--toolbarbutton-inner-padding) - 1px);
-}
-
-:-moz-any(#TabsToolbar, .widget-overflow-list) #pocket-button > .toolbarbutton-icon {
-    max-width: 18px;
-    padding: 0;
-}
--- a/browser/extensions/pocket/test/head.js
+++ b/browser/extensions/pocket/test/head.js
@@ -7,58 +7,40 @@ let enabledOnStartup = false;
 // Enabled/Disabled, and false if it need to Enable/Disable.
 function promisePocketEnabled() {
   if (Services.prefs.getPrefType("extensions.pocket.enabled") != Services.prefs.PREF_INVALID &&
       Services.prefs.getBoolPref("extensions.pocket.enabled")) {
     info( "pocket was already enabled, assuming enabled by default for tests");
     enabledOnStartup = true;
     return Promise.resolve(true);
   }
-  info( "pocket is not enabled");
-  return new Promise((resolve, reject) => {
-    let listener = {
-      onWidgetAfterCreation(widgetid) {
-        if (widgetid == "pocket-button") {
-          info("pocket-button created");
-          CustomizableUI.removeListener(listener);
-          resolve(false);
-        }
-      }
-    }
-    CustomizableUI.addListener(listener);
-    Services.prefs.setBoolPref("extensions.pocket.enabled", true);
+  info("pocket is not enabled");
+  Services.prefs.setBoolPref("extensions.pocket.enabled", true);
+  return BrowserTestUtils.waitForCondition(() => {
+    return PageActions.actionForID("pocket");
   });
 }
 
 function promisePocketDisabled() {
   if (Services.prefs.getPrefType("extensions.pocket.enabled") == Services.prefs.PREF_INVALID ||
       !Services.prefs.getBoolPref("extensions.pocket.enabled")) {
     info("pocket-button already disabled");
     return Promise.resolve(true);
   }
-  return new Promise((resolve, reject) => {
-    let listener = {
-      onWidgetDestroyed(widgetid) {
-        if (widgetid == "pocket-button") {
-          CustomizableUI.removeListener(listener);
-          info( "pocket-button destroyed");
-          // wait for a full unload of pocket
-          BrowserTestUtils.waitForCondition(() => {
-            return !window.hasOwnProperty("pktUI");
-          }, "pocket properties removed from window").then(() => {
-            resolve(false);
-          })
-        }
-      }
-    }
-    CustomizableUI.addListener(listener);
-    info("reset pocket enabled pref");
-    // testing/profiles/prefs_general.js uses user_pref to disable pocket, set
-    // back to false.
-    Services.prefs.setBoolPref("extensions.pocket.enabled", false);
+  info("reset pocket enabled pref");
+  // testing/profiles/prefs_general.js uses user_pref to disable pocket, set
+  // back to false.
+  Services.prefs.setBoolPref("extensions.pocket.enabled", false);
+  return BrowserTestUtils.waitForCondition(() => {
+    return !PageActions.actionForID("pocket");
+  }).then(() => {
+    // wait for a full unload of pocket
+    return BrowserTestUtils.waitForCondition(() => {
+      return !window.hasOwnProperty("pktUI");
+    });
   });
 }
 
 function promisePocketReset() {
   if (enabledOnStartup) {
     info("reset is enabling pocket addon");
     return promisePocketEnabled();
   }
--- a/browser/modules/PageActions.jsm
+++ b/browser/modules/PageActions.jsm
@@ -387,53 +387,56 @@ this.PageActions = {
  *                The URL of the action's icon.  Usually you want to specify an
  *                icon in CSS, but this option is useful if that would be a pain
  *                for some reason -- like your code is in an embedded
  *                WebExtension.
  *         @param nodeAttributes (object, optional)
  *                An object of name-value pairs.  Each pair will be added as
  *                an attribute to DOM nodes created for this action.
  *         @param onBeforePlacedInWindow (function, optional)
- *                Called before the action is placed in the window. Passed the
- *                following arguments:
+ *                Called before the action is placed in the window:
+ *                onBeforePlacedInWindow(window)
  *                * window: The window that the action will be placed in.
  *         @param onCommand (function, optional)
  *                Called when the action is clicked, but only if it has neither
- *                a subview nor an iframe.  Passed the following arguments:
+ *                a subview nor an iframe:
+ *                onCommand(event, buttonNode)
  *                * event: The triggering event.
  *                * buttonNode: The button node that was clicked.
  *         @param onIframeHiding (function, optional)
- *                Called when the action's iframe is hiding. Passed the
- *                following arguments:
+ *                Called when the action's iframe is hiding:
+ *                onIframeHiding(iframeNode, parentPanelNode)
  *                * iframeNode: The iframe.
  *                * parentPanelNode: The panel node in which the iframe is
  *                  shown.
  *         @param onIframeHidden (function, optional)
- *                Called when the action's iframe is hidden. Passed the
- *                following arguments:
+ *                Called when the action's iframe is hidden:
+ *                onIframeHidden(iframeNode, parentPanelNode)
  *                * iframeNode: The iframe.
  *                * parentPanelNode: The panel node in which the iframe is
  *                  shown.
  *         @param onIframeShown (function, optional)
- *                Called when the action's iframe is shown to the user.  Passed
- *                the following arguments:
+ *                Called when the action's iframe is shown to the user:
+ *                onIframeShown(iframeNode, parentPanelNode)
  *                * iframeNode: The iframe.
  *                * parentPanelNode: The panel node in which the iframe is
  *                  shown.
  *         @param onPlacedInPanel (function, optional)
  *                Called when the action is added to the page action panel in
- *                a browser window.  Passed the following arguments:
+ *                a browser window:
+ *                onPlacedInPanel(buttonNode)
  *                * buttonNode: The action's node in the page action panel.
  *         @param onPlacedInUrlbar (function, optional)
  *                Called when the action is added to the urlbar in a browser
- *                window.  Passed the following arguments:
+ *                window:
+ *                onPlacedInUrlbar(buttonNode)
  *                * buttonNode: The action's node in the urlbar.
  *         @param onShowingInPanel (function, optional)
- *                Called when a browser window's page action panel is showing.
- *                Passed the following arguments:
+ *                Called when a browser window's page action panel is showing:
+ *                onShowingInPanel(buttonNode)
  *                * buttonNode: The action's node in the page action panel.
  *         @param shownInUrlbar (bool, optional)
  *                Pass true to show the action in the urlbar, false otherwise.
  *                False by default.
  *         @param subview (object, optional)
  *                An options object suitable for passing to the Subview
  *                constructor, if you'd like the action to have a subview.  See
  *                the subview constructor for info on this object's properties.
@@ -578,24 +581,36 @@ Action.prototype = {
   /**
    * A Subview object if the action wants a subview (Subview, nullable)
    */
   get subview() {
     return this._subview;
   },
 
   /**
+   * Performs the command for an action.  If the action has an onCommand
+   * handler, then it's called.  If the action has a subview or iframe, then a
+   * panel is opened, displaying the subview or iframe.
+   *
+   * @param  browserWindow (DOM window, required)
+   *         The browser window in which to perform the action.
+   */
+  doCommand(browserWindow) {
+    browserPageActions(browserWindow).doCommandForAction(this);
+  },
+
+  /**
    * Call this when before placing the action in the window.
    *
-   * @param  window (DOM window, required)
-   *         The window the action will be placed in.
+   * @param  browserWindow (DOM window, required)
+   *         The browser window the action will be placed in.
    */
-  onBeforePlacedInWindow(window) {
+  onBeforePlacedInWindow(browserWindow) {
     if (this._onBeforePlacedInWindow) {
-      this._onBeforePlacedInWindow(window);
+      this._onBeforePlacedInWindow(browserWindow);
     }
   },
 
   /**
    * Call this when the user activates the action.
    *
    * @param  event (DOM event, required)
    *         The triggering event.
@@ -709,22 +724,23 @@ this.PageActions.Action = Action;
  *         An object with the following properties:
  *         @param buttons (array, optional)
  *                An array of buttons to show in the subview.  Each item in the
  *                array must be an options object suitable for passing to the
  *                Button constructor.  See the Button constructor for
  *                information on these objects' properties.
  *         @param onPlaced (function, optional)
  *                Called when the subview is added to its parent panel in a
- *                browser window.  Passed the following arguments:
+ *                browser window:
+ *                onPlaced(panelViewNode)
  *                * panelViewNode: The panelview node represented by this
  *                  Subview.
  *         @param onShowing (function, optional)
- *                Called when the subview is showing in a browser window.
- *                Passed the following arguments:
+ *                Called when the subview is showing in a browser window:
+ *                onShowing(panelViewNode)
  *                * panelViewNode: The panelview node represented by this
  *                  Subview.
  */
 function Subview(options) {
   setProperties(this, options, {
     buttons: false,
     onPlaced: false,
     onShowing: false,
@@ -780,18 +796,18 @@ this.PageActions.Subview = Subview;
  *                itself, but it will be used to generate DOM node IDs.  But in
  *                terms of spaces and weird characters and such, do treat this
  *                like a DOM node ID.
  *         @param title (string, required)
  *                The button's title.
  *         @param disabled (bool, required)
  *                Pass true to disable the button.
  *         @param onCommand (function, optional)
- *                Called when the button is clicked.  Passed the following
- *                arguments:
+ *                Called when the button is clicked:
+ *                onCommand(event, buttonNode)
  *                * event: The triggering event.
  *                * buttonNode: The node that was clicked.
  *         @param shortcut (string, optional)
  *                The button's shortcut text.
  */
 function Button(options) {
   setProperties(this, options, {
     id: true,
--- a/browser/modules/test/browser/browser_PageActions.js
+++ b/browser/modules/test/browser/browser_PageActions.js
@@ -340,32 +340,32 @@ add_task(async function withSubview() {
 //   EventUtils.synthesizeMouseAtCenter(panelViewButtonNodePanel, {});
   panelViewButtonNodePanel.click();
   await promisePageActionPanelHidden();
   Assert.equal(onActionCommandCallCount, 0,
                "onActionCommandCallCount should remain 0");
   Assert.equal(onButtonCommandCallCount, 1,
                "onButtonCommandCallCount should be inc'ed");
 
-  // Click the action's urlbar button, which should open the temp panel showing
-  // the subview, and click the subview's first button.
+  // Click the action's urlbar button, which should open the activated-action
+  // panel showing the subview, and click the subview's first button.
   onSubviewPlacedExpectedPanelViewID = panelViewIDUrlbar;
   onSubviewShowingExpectedPanelViewID = panelViewIDUrlbar;
   EventUtils.synthesizeMouseAtCenter(urlbarButtonNode, {});
-  await promisePanelShown(BrowserPageActions._tempPanelID);
+  await promisePanelShown(BrowserPageActions._activatedActionPanelID);
   Assert.equal(onSubviewPlacedCount, 2,
                "onSubviewPlacedCount should be inc'ed");
   Assert.equal(onSubviewShowingCount, 2,
                "onSubviewShowingCount should be inc'ed");
   let panelViewButtonNodeUrlbar =
     document.getElementById(panelViewButtonIDUrlbar);
   Assert.notEqual(panelViewButtonNodeUrlbar, null, "panelViewButtonNodeUrlbar");
   onButtonCommandExpectedButtonID = panelViewButtonIDUrlbar;
   EventUtils.synthesizeMouseAtCenter(panelViewButtonNodeUrlbar, {});
-  await promisePanelHidden(BrowserPageActions._tempPanelID);
+  await promisePanelHidden(BrowserPageActions._activatedActionPanelID);
   Assert.equal(onButtonCommandCallCount, 2,
                "onButtonCommandCallCount should be inc'ed");
 
   // Remove the action.
   action.remove();
   panelButtonNode = document.getElementById(panelButtonID);
   Assert.equal(panelButtonNode, null, "panelButtonNode");
   urlbarButtonNode = document.getElementById(urlbarButtonID);
@@ -398,17 +398,17 @@ add_task(async function withIframe() {
     onCommand(event, buttonNode) {
       onCommandCallCount++;
     },
     onIframeShown(iframeNode, panelNode) {
       onIframeShownCount++;
       Assert.ok(iframeNode, "iframeNode should be non-null: " + iframeNode);
       Assert.equal(iframeNode.localName, "iframe", "iframe localName");
       Assert.ok(panelNode, "panelNode should be non-null: " + panelNode);
-      Assert.equal(panelNode.id, BrowserPageActions._tempPanelID,
+      Assert.equal(panelNode.id, BrowserPageActions._activatedActionPanelID,
                    "panelNode.id");
     },
     onPlacedInPanel(buttonNode) {
       onPlacedInPanelCallCount++;
       Assert.ok(buttonNode, "buttonNode should be non-null: " + buttonNode);
       Assert.equal(buttonNode.id, panelButtonID, "buttonNode.id");
     },
     onPlacedInUrlbar(buttonNode) {
@@ -437,63 +437,63 @@ add_task(async function withIframe() {
   // The action's urlbar button should have been created.
   let urlbarButtonNode = document.getElementById(urlbarButtonID);
   Assert.notEqual(urlbarButtonNode, null, "urlbarButtonNode");
 
   // Open the panel, click the action's button.
   await promisePageActionPanelOpen();
   Assert.equal(onIframeShownCount, 0, "onIframeShownCount should remain 0");
   EventUtils.synthesizeMouseAtCenter(panelButtonNode, {});
-  await promisePanelShown(BrowserPageActions._tempPanelID);
+  await promisePanelShown(BrowserPageActions._activatedActionPanelID);
   Assert.equal(onCommandCallCount, 0, "onCommandCallCount should remain 0");
   Assert.equal(onIframeShownCount, 1, "onIframeShownCount should be inc'ed");
 
-  // The temp panel should have opened, anchored to the action's urlbar button.
-  let tempPanel = document.getElementById(BrowserPageActions._tempPanelID);
-  Assert.notEqual(tempPanel, null, "tempPanel");
-  Assert.equal(tempPanel.anchorNode.id, urlbarButtonID,
-               "tempPanel.anchorNode.id");
+  // The activated-action panel should have opened, anchored to the action's
+  // urlbar button.
+  let aaPanel =
+    document.getElementById(BrowserPageActions._activatedActionPanelID);
+  Assert.notEqual(aaPanel, null, "activated-action panel");
+  Assert.equal(aaPanel.anchorNode.id, urlbarButtonID, "aaPanel.anchorNode.id");
   EventUtils.synthesizeMouseAtCenter(urlbarButtonNode, {});
-  await promisePanelHidden(BrowserPageActions._tempPanelID);
+  await promisePanelHidden(BrowserPageActions._activatedActionPanelID);
 
   // Click the action's urlbar button.
   EventUtils.synthesizeMouseAtCenter(urlbarButtonNode, {});
-  await promisePanelShown(BrowserPageActions._tempPanelID);
+  await promisePanelShown(BrowserPageActions._activatedActionPanelID);
   Assert.equal(onCommandCallCount, 0, "onCommandCallCount should remain 0");
   Assert.equal(onIframeShownCount, 2, "onIframeShownCount should be inc'ed");
 
-  // The temp panel should have opened, again anchored to the action's urlbar
-  // button.
-  tempPanel = document.getElementById(BrowserPageActions._tempPanelID);
-  Assert.notEqual(tempPanel, null, "tempPanel");
-  Assert.equal(tempPanel.anchorNode.id, urlbarButtonID,
-               "tempPanel.anchorNode.id");
+  // The activated-action panel should have opened, again anchored to the
+  // action's urlbar button.
+  aaPanel = document.getElementById(BrowserPageActions._activatedActionPanelID);
+  Assert.notEqual(aaPanel, null, "aaPanel");
+  Assert.equal(aaPanel.anchorNode.id, urlbarButtonID, "aaPanel.anchorNode.id");
   EventUtils.synthesizeMouseAtCenter(urlbarButtonNode, {});
-  await promisePanelHidden(BrowserPageActions._tempPanelID);
+  await promisePanelHidden(BrowserPageActions._activatedActionPanelID);
 
   // Hide the action's button in the urlbar.
   action.shownInUrlbar = false;
   urlbarButtonNode = document.getElementById(urlbarButtonID);
   Assert.equal(urlbarButtonNode, null, "urlbarButtonNode");
 
   // Open the panel, click the action's button.
   await promisePageActionPanelOpen();
   EventUtils.synthesizeMouseAtCenter(panelButtonNode, {});
-  await promisePanelShown(BrowserPageActions._tempPanelID);
+  await promisePanelShown(BrowserPageActions._activatedActionPanelID);
   Assert.equal(onCommandCallCount, 0, "onCommandCallCount should remain 0");
   Assert.equal(onIframeShownCount, 3, "onIframeShownCount should be inc'ed");
 
-  // The temp panel should have opened, this time anchored to the main page
-  // action button in the urlbar.
-  tempPanel = document.getElementById(BrowserPageActions._tempPanelID);
-  Assert.notEqual(tempPanel, null, "tempPanel");
-  Assert.equal(tempPanel.anchorNode.id, BrowserPageActions.mainButtonNode.id,
-               "tempPanel.anchorNode.id");
+  // The activated-action panel should have opened, this time anchored to the
+  // main page action button in the urlbar.
+  aaPanel = document.getElementById(BrowserPageActions._activatedActionPanelID);
+  Assert.notEqual(aaPanel, null, "aaPanel");
+  Assert.equal(aaPanel.anchorNode.id, BrowserPageActions.mainButtonNode.id,
+               "aaPanel.anchorNode.id");
   EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {});
-  await promisePanelHidden(BrowserPageActions._tempPanelID);
+  await promisePanelHidden(BrowserPageActions._activatedActionPanelID);
 
   // Remove the action.
   action.remove();
   panelButtonNode = document.getElementById(panelButtonID);
   Assert.equal(panelButtonNode, null, "panelButtonNode");
   urlbarButtonNode = document.getElementById(urlbarButtonID);
   Assert.equal(urlbarButtonNode, null, "urlbarButtonNode");
 });
--- a/testing/profiles/prefs_general.js
+++ b/testing/profiles/prefs_general.js
@@ -389,12 +389,8 @@ user_pref("marionette.prefs.recommended"
 
 // Disable Screenshots by default for now
 user_pref("extensions.screenshots.system-disabled", true);
 
 // Set places maintenance far in the future to avoid it kicking in during tests.
 // The maintenance can take a relatively long time which may cause unnecessary
 // intermittents and slow down tests.
 user_pref("places.database.lastMaintenance", 7258114800);
-
-// Disable the Pocket page action and enable the CUI widget until bug 1385418 is
-// fixed.
-user_pref("extensions.pocket.disablePageAction", true);