Bug 1419842 support pattern matching to show/hide pageActions, r?aswan draft
authorShane Caraveo <scaraveo@mozilla.com>
Tue, 05 Dec 2017 14:41:21 -0800
changeset 707900 d1ff9905cd44933d84f06d1dab25cbf2ee0e2e39
parent 706692 709f355a7a8c4ae426d1824841a71ffdb5ce0137
child 743054 8f316d01c5eb19e18224a089ec10769d5fb35033
push id92238
push usermixedpuppy@gmail.com
push dateTue, 05 Dec 2017 22:42:13 +0000
reviewersaswan
bugs1419842
milestone59.0a1
Bug 1419842 support pattern matching to show/hide pageActions, r?aswan MozReview-Commit-ID: bYcR08xX8r
browser/components/extensions/ext-pageAction.js
browser/components/extensions/schemas/page_action.json
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_pageAction_show_matches.js
browser/components/extensions/test/browser/browser_ext_pageAction_simple.js
--- a/browser/components/extensions/ext-pageAction.js
+++ b/browser/components/extensions/ext-pageAction.js
@@ -35,18 +35,25 @@ this.pageAction = class extends Extensio
     let {extension} = this;
     let options = extension.manifest.page_action;
 
     let widgetId = makeWidgetId(extension.id);
     this.id = widgetId + "-page-action";
 
     this.tabManager = extension.tabManager;
 
+    // If <all_urls> is present, the default is to show the page action.
+    let show = options.show_matches && options.show_matches.includes("<all_urls>");
+    let showMatches = new MatchPatternSet(options.show_matches || []);
+    let hideMatches = new MatchPatternSet(options.hide_matches || []);
+
     this.defaults = {
-      show: false,
+      show,
+      showMatches,
+      hideMatches,
       title: options.default_title || extension.name,
       popup: options.default_popup || "",
     };
 
     this.browserStyle = options.browser_style || false;
     if (options.browser_style === null) {
       this.extension.logger.warn("Please specify whether you want browser_style " +
                                  "or not in your page_action options.");
@@ -65,17 +72,17 @@ this.pageAction = class extends Extensio
 
     if (!this.browserPageAction) {
       this.browserPageAction = PageActions.addAction(new PageActions.Action({
         id: widgetId,
         extensionID: extension.id,
         title: this.defaults.title,
         iconURL: this.getIconData(this.defaults.icon),
         pinnedToUrlbar: true,
-        disabled: true,
+        disabled: !this.defaults.show,
         onCommand: (event, buttonNode) => {
           this.handleClick(event.target.ownerGlobal);
         },
         onBeforePlacedInWindow: browserWindow => {
           if (this.extension.hasPermission("menus") ||
               this.extension.hasPermission("contextMenus")) {
             browserWindow.document.addEventListener("popupshowing", this);
           }
@@ -221,16 +228,22 @@ this.pageAction = class extends Extensio
       this.emit("click", tab);
     }
   }
 
   handleLocationChange(eventType, tab, fromBrowse) {
     if (fromBrowse) {
       this.tabContext.clear(tab);
     }
+
+    // Set show via pattern matching.
+    let context = this.tabContext.get(tab);
+    let uri = tab.linkedBrowser.currentURI;
+    context.show = (context.show || context.showMatches.matches(uri)) && !context.hideMatches.matches(uri);
+
     this.updateButton(tab.ownerGlobal);
   }
 
   getAPI(context) {
     let {extension} = context;
 
     const {tabManager} = extension;
     const pageAction = this;
--- a/browser/components/extensions/schemas/page_action.json
+++ b/browser/components/extensions/schemas/page_action.json
@@ -26,16 +26,28 @@
                 "type": "string",
                 "format": "relativeUrl",
                 "optional": true,
                 "preprocess": "localize"
               },
               "browser_style": {
                 "type": "boolean",
                 "optional": true
+              },
+              "show_matches": {
+                "type": "array",
+                "optional": true,
+                "minItems": 1,
+                "items": { "$ref": "MatchPattern" }
+              },
+              "hide_matches": {
+                "type": "array",
+                "optional": true,
+                "minItems": 1,
+                "items": { "$ref": "MatchPattern" }
               }
             },
             "optional": true
           }
         }
       }
     ]
   },
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -97,16 +97,17 @@ skip-if = (os == 'win' && !debug) # bug 
 [browser_ext_openPanel.js]
 [browser_ext_optionsPage_browser_style.js]
 [browser_ext_optionsPage_modals.js]
 [browser_ext_optionsPage_privileges.js]
 [browser_ext_pageAction_context.js]
 [browser_ext_pageAction_contextMenu.js]
 [browser_ext_pageAction_popup.js]
 [browser_ext_pageAction_popup_resize.js]
+[browser_ext_pageAction_show_matches.js]
 [browser_ext_pageAction_simple.js]
 [browser_ext_pageAction_telemetry.js]
 [browser_ext_pageAction_title.js]
 [browser_ext_popup_api_injection.js]
 [browser_ext_popup_background.js]
 [browser_ext_popup_corners.js]
 [browser_ext_popup_sendMessage.js]
 [browser_ext_popup_shutdown.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_pageAction_show_matches.js
@@ -0,0 +1,68 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+function getExtension(page_action) {
+  return ExtensionTestUtils.loadExtension({
+    manifest: {
+      page_action,
+    },
+  });
+}
+
+add_task(async function test_pageAction_default_show() {
+  let tests = [
+    {
+      "name": "Test shown for all_urls",
+      "page_action": {
+        "show_matches": ["<all_urls>"],
+      },
+      "shown": [true, true, false],
+    },
+    {
+      "name": "Test hide_matches overrides all_urls.",
+      "page_action": {
+        "show_matches": ["<all_urls>"],
+        "hide_matches": ["*://mochi.test/*"],
+      },
+      "shown": [true, false, false],
+    },
+    {
+      "name": "Test shown only for show_matches.",
+      "page_action": {
+        "show_matches": ["*://mochi.test/*"],
+      },
+      "shown": [false, true, false],
+    },
+  ];
+
+  let tabs = [
+    await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/", true, true),
+    await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/", true, true),
+    await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:rights", true, true),
+  ];
+
+  for (let [i, test] of tests.entries()) {
+    info(`test ${i}: ${test.name}`);
+    let extension = getExtension(test.page_action);
+    await extension.startup();
+
+    let widgetId = makeWidgetId(extension.id);
+    let pageActionId = BrowserPageActions.urlbarButtonNodeIDForActionID(widgetId);
+
+    for (let [t, tab] of tabs.entries()) {
+      await BrowserTestUtils.switchTab(gBrowser, tab);
+      is(gBrowser.selectedTab, tab, `tab ${t} selected`);
+      let button = document.getElementById(pageActionId);
+      // Sometimes we're hidden, sometimes a parent is hidden via css (e.g. about pages)
+      let hidden = button === null || button.hidden ||
+        window.getComputedStyle(button).display == "none";
+      is(!hidden, test.shown[t], `test ${i} tab ${t}: page action is ${test.shown[t] ? "shown" : "hidden"} for ${tab.linkedBrowser.currentURI.spec}`);
+    }
+
+    await extension.unload();
+  }
+  for (let tab of tabs) {
+    await BrowserTestUtils.removeTab(tab);
+  }
+});
--- a/browser/components/extensions/test/browser/browser_ext_pageAction_simple.js
+++ b/browser/components/extensions/test/browser/browser_ext_pageAction_simple.js
@@ -1,13 +1,13 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
-add_task(async function() {
+add_task(async function test_pageAction_basic() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "page_action": {
         "default_popup": "popup.html",
         "unrecognized_property": "with-a-random-value",
       },
     },