Bug 1419842 support pattern matching to show/hide pageActions, r=aswan
authorShane Caraveo <scaraveo@mozilla.com>
Tue, 05 Dec 2017 14:41:21 -0800
changeset 446903 ece8a84edfa7c592f6ca3a719ffb2eda31ac65ff
parent 446902 0ff6e7cbed23520e73e533b2adc23b756df1175c
child 446904 dfe90994b1ae223126cde8ceebbd5f97656a3fac
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1419842
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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",
       },
     },