Bug 1275116 - Fix {document|target}UrlPatterns by passing in the correct arguments to SingleMatchPattern.match. r=kmag draft
authorMatthew Wein <mwein@mozilla.com>
Thu, 14 Jul 2016 14:41:03 -0700
changeset 392229 88069411b56c3b9f269c6a474ca3f3117f40d451
parent 392228 b3a0aa75399dbb7da9a246082293cdd36fe05be7
child 526278 c59824e36cafe18de47457acc48491e23212e69b
push id23967
push usermwein@mozilla.com
push dateMon, 25 Jul 2016 04:03:30 +0000
reviewerskmag
bugs1275116
milestone50.0a1
Bug 1275116 - Fix {document|target}UrlPatterns by passing in the correct arguments to SingleMatchPattern.match. r=kmag MozReview-Commit-ID: LLNu7jNfUZq
browser/components/extensions/ext-contextMenus.js
browser/components/extensions/test/browser/browser.ini
browser/components/extensions/test/browser/browser_ext_contextMenus_urlPatterns.js
browser/components/extensions/test/browser/head.js
--- a/browser/components/extensions/ext-contextMenus.js
+++ b/browser/components/extensions/ext-contextMenus.js
@@ -435,25 +435,32 @@ MenuItem.prototype = {
 
   enabledForContext(contextData) {
     let contexts = getContexts(contextData);
     if (!this.contexts.some(n => contexts.has(n))) {
       return false;
     }
 
     let docPattern = this.documentUrlMatchPattern;
-    if (docPattern && !docPattern.matches(contextData.pageUrl)) {
+    let pageURI = Services.io.newURI(contextData.pageUrl, null, null);
+    if (docPattern && !docPattern.matches(pageURI)) {
       return false;
     }
 
-    let isMedia = contextData.onImage || contextData.onAudio || contextData.onVideo;
     let targetPattern = this.targetUrlMatchPattern;
-    if (isMedia && targetPattern && !targetPattern.matches(contextData.srcURL)) {
-      // TODO: double check if mediaURL is always set when we need it
-      return false;
+    if (targetPattern) {
+      let isMedia = contextData.onImage || contextData.onAudio || contextData.onVideo;
+      if (!isMedia) {
+        return false;
+      }
+      let srcURI = Services.io.newURI(contextData.srcUrl, null, null);
+      if (!targetPattern.matches(srcURI)) {
+        // TODO: double check if mediaURL is always set when we need it
+        return false;
+      }
     }
 
     return true;
   },
 };
 
 var gExtensionCount = 0;
 /* eslint-disable mozilla/balanced-listeners */
--- a/browser/components/extensions/test/browser/browser.ini
+++ b/browser/components/extensions/test/browser/browser.ini
@@ -27,16 +27,17 @@ support-files =
 [browser_ext_commands_getAll.js]
 [browser_ext_commands_onCommand.js]
 [browser_ext_contentscript_connect.js]
 [browser_ext_contextMenus.js]
 [browser_ext_contextMenus_checkboxes.js]
 [browser_ext_contextMenus_icons.js]
 [browser_ext_contextMenus_radioGroups.js]
 [browser_ext_contextMenus_uninstall.js]
+[browser_ext_contextMenus_urlPatterns.js]
 [browser_ext_currentWindow.js]
 [browser_ext_getViews.js]
 [browser_ext_history.js]
 [browser_ext_incognito_popup.js]
 [browser_ext_lastError.js]
 [browser_ext_optionsPage_privileges.js]
 [browser_ext_pageAction_context.js]
 [browser_ext_pageAction_popup.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_contextMenus_urlPatterns.js
@@ -0,0 +1,186 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+add_task(function* () {
+  let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser,
+    "http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html");
+
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "permissions": ["contextMenus"],
+    },
+
+    background: function() {
+      // Test menu items using targetUrlPatterns.
+      browser.contextMenus.create({
+        title: "targetUrlPatterns-patternMatches-contextAll",
+        targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
+        contexts: ["all"],
+      });
+
+      browser.contextMenus.create({
+        title: "targetUrlPatterns-patternMatches-contextImage",
+        targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
+        contexts: ["image"],
+      });
+
+      browser.contextMenus.create({
+        title: "targetUrlPatterns-patternDoesNotMatch-contextAll",
+        targetUrlPatterns: ["*://*/does-not-match"],
+        contexts: ["all"],
+      });
+
+      browser.contextMenus.create({
+        title: "targetUrlPatterns-patternDoesNotMatch-contextImage",
+        targetUrlPatterns: ["*://*/does-not-match"],
+        contexts: ["image"],
+      });
+
+      // Test menu items using documentUrlPatterns.
+      browser.contextMenus.create({
+        title: "documentUrlPatterns-patternMatches-contextAll",
+        documentUrlPatterns: ["*://*/*context.html"],
+        contexts: ["all"],
+      });
+
+      browser.contextMenus.create({
+        title: "documentUrlPatterns-patternMatches-contextImage",
+        documentUrlPatterns: ["*://*/*context.html", "http://*/url-that-does-not-match"],
+        contexts: ["image"],
+      });
+
+      browser.contextMenus.create({
+        title: "documentUrlPatterns-patternDoesNotMatch-contextAll",
+        documentUrlPatterns: ["*://*/does-not-match"],
+        contexts: ["all"],
+      });
+
+      browser.contextMenus.create({
+        title: "documentUrlPatterns-patternDoesNotMatch-contextImage",
+        documentUrlPatterns: ["*://*/does-not-match"],
+        contexts: ["image"],
+      });
+
+      // Test menu items using both targetUrlPatterns and documentUrlPatterns.
+      browser.contextMenus.create({
+        title: "documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextAll",
+        documentUrlPatterns: ["*://*/*context.html"],
+        targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
+        contexts: ["all"],
+      });
+
+      browser.contextMenus.create({
+        title: "documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextAll",
+        documentUrlPatterns: ["*://does-not-match"],
+        targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
+        contexts: ["all"],
+      });
+
+      browser.contextMenus.create({
+        title: "documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextAll",
+        documentUrlPatterns: ["*://*/*context.html"],
+        targetUrlPatterns: ["*://does-not-match"],
+        contexts: ["all"],
+      });
+
+      browser.contextMenus.create({
+        title: "documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternDoesNotMatch-contextAll",
+        documentUrlPatterns: ["*://does-not-match"],
+        targetUrlPatterns: ["*://does-not-match"],
+        contexts: ["all"],
+      });
+
+      browser.contextMenus.create({
+        title: "documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextImage",
+        documentUrlPatterns: ["*://*/*context.html"],
+        targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
+        contexts: ["image"],
+      });
+
+      browser.contextMenus.create({
+        title: "documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextImage",
+        documentUrlPatterns: ["*://does-not-match"],
+        targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
+        contexts: ["image"],
+      });
+
+      browser.contextMenus.create({
+        title: "documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextImage",
+        documentUrlPatterns: ["*://*/*context.html"],
+        targetUrlPatterns: ["*://does-not-match"],
+        contexts: ["image"],
+      });
+
+      browser.contextMenus.create({
+        title: "documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternDoesNotMatch-contextImage",
+        documentUrlPatterns: ["*://does-not-match"],
+        targetUrlPatterns: ["*://does-not-match"],
+        contexts: ["image"],
+      });
+
+      browser.test.notifyPass("contextmenus-urlPatterns");
+    },
+  });
+
+  function* confirmContextMenuItems(menu, expected) {
+    for (let [label, shouldShow] of expected) {
+      let items = menu.getElementsByAttribute("label", label);
+      if (shouldShow) {
+        is(items.length, 1, `The menu item for label ${label} was correctly shown`);
+      } else {
+        is(items.length, 0, `The menu item for label ${label} was correctly not shown`);
+      }
+    }
+  }
+
+  yield extension.startup();
+  yield extension.awaitFinish("contextmenus-urlPatterns");
+
+  let extensionContextMenu = yield openExtensionContextMenu("#img1");
+  let expected = [
+    ["targetUrlPatterns-patternMatches-contextAll", true],
+    ["targetUrlPatterns-patternMatches-contextImage", true],
+    ["targetUrlPatterns-patternDoesNotMatch-contextAll", false],
+    ["targetUrlPatterns-patternDoesNotMatch-contextImage", false],
+    ["documentUrlPatterns-patternMatches-contextAll", true],
+    ["documentUrlPatterns-patternMatches-contextImage", true],
+    ["documentUrlPatterns-patternDoesNotMatch-contextAll", false],
+    ["documentUrlPatterns-patternDoesNotMatch-contextImage", false],
+    ["documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextAll", true],
+    ["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextAll", false],
+    ["documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextAll", false],
+    ["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternDoesNotMatch-contextAll", false],
+    ["documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextImage", true],
+    ["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextImage", false],
+    ["documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextImage", false],
+    ["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternDoesNotMatch-contextImage", false],
+  ];
+  yield confirmContextMenuItems(extensionContextMenu, expected);
+  yield closeContextMenu();
+
+  let contextMenu = yield openContextMenu("body");
+  expected = [
+    ["targetUrlPatterns-patternMatches-contextAll", false],
+    ["targetUrlPatterns-patternMatches-contextImage", false],
+    ["targetUrlPatterns-patternDoesNotMatch-contextAll", false],
+    ["targetUrlPatterns-patternDoesNotMatch-contextImage", false],
+    ["documentUrlPatterns-patternMatches-contextAll", true],
+    ["documentUrlPatterns-patternMatches-contextImage", false],
+    ["documentUrlPatterns-patternDoesNotMatch-contextAll", false],
+    ["documentUrlPatterns-patternDoesNotMatch-contextImage", false],
+    ["documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextAll", false],
+    ["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextAll", false],
+    ["documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextAll", false],
+    ["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternDoesNotMatch-contextAll", false],
+    ["documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextImage", false],
+    ["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextImage", false],
+    ["documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextImage", false],
+    ["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternDoesNotMatch-contextImage", false],
+  ];
+  yield confirmContextMenuItems(contextMenu, expected);
+  yield closeContextMenu();
+
+  yield extension.unload();
+  yield BrowserTestUtils.removeTab(tab1);
+});
--- a/browser/components/extensions/test/browser/head.js
+++ b/browser/components/extensions/test/browser/head.js
@@ -119,33 +119,33 @@ function closeBrowserAction(extension, w
   let group = getBrowserActionWidget(extension);
 
   let node = win.document.getElementById(group.viewId);
   CustomizableUI.hidePanelForNode(node);
 
   return Promise.resolve();
 }
 
-function* openContextMenu(id) {
+function* openContextMenu(selector="#img1") {
   let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
   let popupShownPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popupshown");
-  yield BrowserTestUtils.synthesizeMouseAtCenter(id, {type: "contextmenu", button: 2}, gBrowser.selectedBrowser);
+  yield BrowserTestUtils.synthesizeMouseAtCenter(selector, {type: "contextmenu"}, gBrowser.selectedBrowser);
   yield popupShownPromise;
   return contentAreaContextMenu;
 }
 
 function* closeContextMenu() {
   let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
   let popupHiddenPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popuphidden");
   contentAreaContextMenu.hidePopup();
   yield popupHiddenPromise;
 }
 
-function* openExtensionContextMenu() {
-  let contextMenu = yield openContextMenu("#img1");
+function* openExtensionContextMenu(selector="#img1") {
+  let contextMenu = yield openContextMenu(selector);
   let topLevelMenu = contextMenu.getElementsByAttribute("ext-type", "top-level-menu");
 
   // Return null if the extension only has one item and therefore no extension menu.
   if (topLevelMenu.length == 0) {
     return null;
   }
 
   let extensionMenu = topLevelMenu[0].childNodes[0];