Bug 1404172: Remove MatchPattern.jsm. r?aswan draft
authorKris Maglione <maglione.k@gmail.com>
Thu, 28 Sep 2017 18:27:44 -0700
changeset 672312 e313e4cd0094d2c7f6da925bec9762b53a7b8cf4
parent 672311 772f1641588ac2fc20ff6ec5fc14df98314f4660
child 733769 c93f7320be239dc30787cbe75391427a5b4be05d
push id82212
push usermaglione.k@gmail.com
push dateFri, 29 Sep 2017 01:28:01 +0000
reviewersaswan
bugs1404172
milestone58.0a1
Bug 1404172: Remove MatchPattern.jsm. r?aswan MozReview-Commit-ID: ItGMuChHS3z
netwerk/cookie/nsCookieService.cpp
toolkit/components/extensions/ext-webNavigation.js
toolkit/modules/addons/MatchPattern.jsm
toolkit/modules/addons/MatchURLFilters.jsm
toolkit/modules/addons/WebRequestContent.js
toolkit/modules/moz.build
toolkit/modules/tests/xpcshell/test_MatchGlobs.js
toolkit/modules/tests/xpcshell/test_MatchPattern.js
toolkit/modules/tests/xpcshell/test_MatchURLFilters.js
toolkit/modules/tests/xpcshell/xpcshell.ini
tools/lint/eslint/modules.json
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -3315,17 +3315,17 @@ nsCookieService::GetCookiesForURI(nsIURI
   case STATUS_REJECTED:
   case STATUS_REJECTED_WITH_ERROR:
     return;
   default:
     break;
   }
 
   // Note: The following permissions logic is mirrored in
-  // toolkit/modules/addons/MatchPattern.jsm:MatchPattern.matchesCookie().
+  // extensions::MatchPattern::MatchesCookie.
   // If it changes, please update that function, or file a bug for someone
   // else to do so.
 
   // check if aHostURI is using an https secure protocol.
   // if it isn't, then we can't send a secure cookie over the connection.
   // if SchemeIs fails, assume an insecure connection, to be on the safe side
   bool isSecure;
   if (NS_FAILED(aHostURI->SchemeIs("https", &isSecure))) {
--- a/toolkit/components/extensions/ext-webNavigation.js
+++ b/toolkit/components/extensions/ext-webNavigation.js
@@ -3,17 +3,17 @@
 // The ext-* files are imported into the same scopes.
 /* import-globals-from ext-toolkit.js */
 
 // This file expectes tabTracker to be defined in the global scope (e.g.
 // by ext-utils.js).
 /* global tabTracker */
 
 XPCOMUtils.defineLazyModuleGetter(this, "MatchURLFilters",
-                                  "resource://gre/modules/MatchPattern.jsm");
+                                  "resource://gre/modules/MatchURLFilters.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "WebNavigation",
                                   "resource://gre/modules/WebNavigation.jsm");
 
 const defaultTransitionTypes = {
   topFrame: "link",
   subFrame: "auto_subframe",
 };
 
rename from toolkit/modules/addons/MatchPattern.jsm
rename to toolkit/modules/addons/MatchURLFilters.jsm
--- a/toolkit/modules/addons/MatchPattern.jsm
+++ b/toolkit/modules/addons/MatchURLFilters.jsm
@@ -4,283 +4,39 @@
 
 "use strict";
 
 const Cu = Components.utils;
 const Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
-                                  "resource://gre/modules/NetUtil.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 
-this.EXPORTED_SYMBOLS = ["MatchPattern", "MatchGlobs", "MatchURLFilters"];
-
-/* globals MatchPattern, MatchGlobs */
-
-const PERMITTED_SCHEMES = ["http", "https", "ws", "wss", "file", "ftp", "data"];
-const PERMITTED_SCHEMES_REGEXP = [...PERMITTED_SCHEMES, "moz-extension"].join("|");
+/* exported MatchURLFilters */
 
-// The basic RE for matching patterns
-const PATTERN_REGEXP = new RegExp(`^(${PERMITTED_SCHEMES_REGEXP}|\\*)://(\\*|\\*\\.[^*/]+|[^*/]+|)(/.*)$`);
-
-// The schemes/protocols implied by a pattern that starts with *://
-const WILDCARD_SCHEMES = ["http", "https"];
-
-// This function converts a glob pattern (containing * and possibly ?
-// as wildcards) to a regular expression.
-function globToRegexp(pat, allowQuestion) {
-  // Escape everything except ? and *.
-  pat = pat.replace(/[.+^${}()|[\]\\]/g, "\\$&");
+this.EXPORTED_SYMBOLS = ["MatchURLFilters"];
 
-  if (allowQuestion) {
-    pat = pat.replace(/\?/g, ".");
-  } else {
-    pat = pat.replace(/\?/g, "\\?");
-  }
-  pat = pat.replace(/\*/g, ".*");
-  return new RegExp("^" + pat + "$");
-}
-
-// These patterns follow the syntax in
-// https://developer.chrome.com/extensions/match_patterns
-function SingleMatchPattern(pat) {
-  this.pat = pat;
-  if (pat == "<all_urls>") {
-    this.schemes = PERMITTED_SCHEMES;
-    this.hostMatch = () => true;
-    this.pathMatch = () => true;
-  } else if (!pat) {
-    this.schemes = [];
-  } else {
-    let match = PATTERN_REGEXP.exec(pat);
-    if (!match) {
-      Cu.reportError(`Invalid match pattern: '${pat}'`);
-      this.schemes = [];
-      return;
-    }
-
-    if (match[1] == "*") {
-      this.schemes = WILDCARD_SCHEMES;
-    } else {
-      this.schemes = [match[1]];
+// Match WebNavigation URL Filters.
+class MatchURLFilters {
+  constructor(filters) {
+    if (!Array.isArray(filters)) {
+      throw new TypeError("filters should be an array");
     }
 
-    // We allow the host to be empty for file URLs.
-    if (match[2] == "" && this.schemes[0] != "file") {
-      Cu.reportError(`Invalid match pattern: '${pat}'`);
-      this.schemes = [];
-      return;
-    }
-
-    // We disallow the host to be * for moz-extension URLs.
-    if (match[2] == "*" && this.schemes[0] == "moz-extension") {
-      Cu.reportError(`Invalid match pattern: '${pat}'`);
-      this.schemes = [];
-      return;
+    if (filters.length == 0) {
+      throw new Error("filters array should not be empty");
     }
 
-    this.host = match[2];
-    this.hostMatch = this.getHostMatcher(match[2]);
-
-    let pathMatch = globToRegexp(match[3], false);
-    this.pathMatch = pathMatch.test.bind(pathMatch);
-  }
-}
-
-SingleMatchPattern.prototype = {
-  getHostMatcher(host) {
-    // This code ignores the port, as Chrome does.
-    if (host == "*") {
-      return () => true;
-    }
-    if (host.startsWith("*.")) {
-      let suffix = host.substr(2);
-      let dotSuffix = "." + suffix;
-
-      return ({host}) => host === suffix || host.endsWith(dotSuffix);
-    }
-    return uri => uri.host === host;
-  },
-
-  matches(uri, ignorePath = false) {
-    return (
-      this.schemes.includes(uri.scheme) &&
-      this.hostMatch(uri) &&
-      (ignorePath || (
-        this.pathMatch(uri.cloneIgnoringRef().pathQueryRef)
-      ))
-    );
-  },
-
-  // Tests if this can possibly overlap with the |other| SingleMatchPattern.
-  overlapsIgnoringPath(other) {
-    return this.schemes.some(scheme => other.schemes.includes(scheme)) &&
-           (this.hostMatch(other) || other.hostMatch(this));
-  },
-
-  get pattern() { return this.pat; },
-};
-
-this.MatchPattern = function(pat) {
-  this.pat = pat;
-  if (!pat) {
-    this.matchers = [];
-  } else if (pat instanceof String || typeof(pat) == "string") {
-    this.matchers = [new SingleMatchPattern(pat)];
-  } else {
-    this.matchers = pat.map(p => new SingleMatchPattern(p));
+    this.filters = filters;
   }
 
-  XPCOMUtils.defineLazyGetter(this, "explicitMatchers", () => {
-    return this.matchers.filter(matcher => matcher.pat != "<all_urls>" &&
-                                           matcher.host &&
-                                           !matcher.host.startsWith("*"));
-  });
-};
-
-MatchPattern.prototype = {
-  // |uri| should be an nsIURI.
-  matches(uri) {
-    return this.matchers.some(matcher => matcher.matches(uri));
-  },
-
-  get patterns() { return this.matchers; },
-
-  matchesIgnoringPath(uri, explicit = false) {
-    if (explicit) {
-      return this.explicitMatchers.some(matcher => matcher.matches(uri, true));
-    }
-    return this.matchers.some(matcher => matcher.matches(uri, true));
-  },
-
-  // Checks that this match pattern grants access to read the given
-  // cookie. |cookie| should be an |nsICookie2| instance.
-  matchesCookie(cookie) {
-    // First check for simple matches.
-    let secureURI = NetUtil.newURI(`https://${cookie.rawHost}/`);
-    if (this.matchesIgnoringPath(secureURI)) {
-      return true;
-    }
-
-    let plainURI = NetUtil.newURI(`http://${cookie.rawHost}/`);
-    if (!cookie.isSecure && this.matchesIgnoringPath(plainURI)) {
-      return true;
-    }
-
-    if (!cookie.isDomain) {
-      return false;
-    }
-
-    // Things get tricker for domain cookies. The extension needs to be able
-    // to read any cookies that could be read any host it has permissions
-    // for. This means that our normal host matching checks won't work,
-    // since the pattern "*://*.foo.example.com/" doesn't match ".example.com",
-    // but it does match "bar.foo.example.com", which can read cookies
-    // with the domain ".example.com".
-    //
-    // So, instead, we need to manually check our filters, and accept any
-    // with hosts that end with our cookie's host.
-
-    let {host, isSecure} = cookie;
-
-    for (let matcher of this.matchers) {
-      let schemes = matcher.schemes;
-      if (schemes.includes("https") || (!isSecure && schemes.includes("http"))) {
-        if (matcher.host.endsWith(host)) {
-          return true;
-        }
-      }
-    }
-
-    return false;
-  },
-
-  // Checks if every part of this filter overlaps with
-  // some of the |hosts| or |optional| permissions MatchPatterns.
-  overlapsPermissions(hosts, optional) {
-    const perms = hosts.matchers.concat(optional.matchers);
-    return this.matchers.length &&
-           this.matchers.every(m => perms.some(p => p.overlapsIgnoringPath(m)));
-  },
-
-  // Test if this MatchPattern subsumes the given pattern (i.e., whether
-  // this pattern matches everything the given pattern does).
-  // Note, this method considers only to protocols and hosts/domains,
-  // paths are ignored.
-  subsumes(pattern) {
-    let match = PATTERN_REGEXP.exec(pattern);
-    if (!match) {
-      throw new Error("Invalid match pattern");
-    }
-
-    if (match[1] == "*") {
-      return WILDCARD_SCHEMES.every(scheme => this.matchesIgnoringPath({scheme, host: match[2]}));
-    }
-
-    return this.matchesIgnoringPath({scheme: match[1], host: match[2]});
-  },
-
-  serialize() {
-    return this.pat;
-  },
-
-  removeOne(pattern) {
-    if (!Array.isArray(this.pat)) {
-      return;
-    }
-
-    let index = this.pat.indexOf(pattern);
-    if (index >= 0) {
-      if (this.matchers[index].pat != pattern) {
-        throw new Error("pat/matcher mismatch in removeOne()");
-      }
-      this.pat.splice(index, 1);
-      this.matchers.splice(index, 1);
-    }
-  },
-};
-
-// Globs can match everything. Be careful, this DOES NOT filter by allowed schemes!
-this.MatchGlobs = function(globs) {
-  this.original = globs;
-  if (globs) {
-    this.regexps = Array.from(globs, (glob) => globToRegexp(glob, true));
-  } else {
-    this.regexps = [];
-  }
-};
-
-MatchGlobs.prototype = {
-  matches(str) {
-    return this.regexps.some(regexp => regexp.test(str));
-  },
-  serialize() {
-    return this.original;
-  },
-};
-
-// Match WebNavigation URL Filters.
-this.MatchURLFilters = function(filters) {
-  if (!Array.isArray(filters)) {
-    throw new TypeError("filters should be an array");
-  }
-
-  if (filters.length == 0) {
-    throw new Error("filters array should not be empty");
-  }
-
-  this.filters = filters;
-};
-
-MatchURLFilters.prototype = {
   matches(url) {
-    let uri = NetUtil.newURI(url);
+    let uri = Services.io.newURI(url);
     // Set uriURL to an empty object (needed because some schemes, e.g. about doesn't support nsIURL).
     let uriURL = {};
     if (uri instanceof Ci.nsIURL) {
       uriURL = uri;
     }
 
     // Set host to a empty string by default (needed so that schemes without an host,
     // e.g. about, can pass an empty string for host based event filtering as expected).
@@ -308,17 +64,17 @@ MatchURLFilters.prototype = {
       query: uriURL.query,
       host,
       port,
       url,
     };
 
     // If any of the filters matches, matches returns true.
     return this.filters.some(filter => this.matchURLFilter({filter, data, uri, uriURL}));
-  },
+  }
 
   matchURLFilter({filter, data, uri, uriURL}) {
     // Test for scheme based filtering.
     if (filter.schemes) {
       // Return false if none of the schemes matches.
       if (!filter.schemes.some((scheme) => uri.schemeIs(scheme))) {
         return false;
       }
@@ -377,17 +133,17 @@ MatchURLFilters.prototype = {
       // of null)
       if (!urlWithoutQueryAndRef ||
           !urlWithoutQueryAndRef.match(filter.originAndPathMatches)) {
         return false;
       }
     }
 
     return true;
-  },
+  }
 
   testMatchOnURLComponent({urlComponent: key, data, filter}) {
     // Test for equals.
     // NOTE: an empty string should not be considered a filter to skip.
     if (filter[`${key}Equals`] != null) {
       if (data[key] !== filter[`${key}Equals`]) {
         return false;
       }
@@ -411,14 +167,14 @@ MatchURLFilters.prototype = {
     // Test for suffix.
     if (filter[`${key}Suffix`]) {
       if (!data[key] || !data[key].endsWith(filter[`${key}Suffix`])) {
         return false;
       }
     }
 
     return true;
-  },
+  }
 
   serialize() {
     return this.filters;
-  },
-};
+  }
+}
--- a/toolkit/modules/addons/WebRequestContent.js
+++ b/toolkit/modules/addons/WebRequestContent.js
@@ -1,27 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Managed via the message managers.
-/* global initialProcessData */
+/* globals MatchPatternSet, initialProcessData */
 
 "use strict";
 
 var Ci = Components.interfaces;
 var Cc = Components.classes;
 var Cu = Components.utils;
 var Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "MatchPattern",
-                                  "resource://gre/modules/MatchPattern.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "WebRequestCommon",
                                   "resource://gre/modules/WebRequestCommon.jsm");
 
 // Websockets will get handled via httpchannel notifications same as http
 // requests, treat them the same as http in ContentPolicy.
 const IS_HTTP = /^https?:|wss?:/;
 
 var ContentPolicy = {
@@ -48,17 +46,17 @@ var ContentPolicy = {
     }
   },
 
   addContentPolicy({id, blocking, filter}) {
     if (this.contentPolicies.size == 0) {
       this.register();
     }
     if (filter.urls) {
-      filter.urls = new MatchPattern(filter.urls);
+      filter.urls = new MatchPatternSet(filter.urls);
     }
     this.contentPolicies.set(id, {blocking, filter});
   },
 
   receiveMessage(msg) {
     switch (msg.name) {
       case "WebRequest:AddContentPolicy":
         this.addContentPolicy(msg.data);
--- a/toolkit/modules/moz.build
+++ b/toolkit/modules/moz.build
@@ -158,17 +158,17 @@ TESTING_JS_MODULES += [
     'tests/modules/MockDocument.jsm',
     'tests/modules/PromiseTestUtils.jsm',
     'tests/xpcshell/TestIntegration.jsm',
 ]
 
 SPHINX_TREES['toolkit_modules'] = 'docs'
 
 EXTRA_JS_MODULES += [
-    'addons/MatchPattern.jsm',
+    'addons/MatchURLFilters.jsm',
     'addons/WebNavigation.jsm',
     'addons/WebNavigationContent.js',
     'addons/WebNavigationFrames.jsm',
     'addons/WebRequest.jsm',
     'addons/WebRequestCommon.jsm',
     'addons/WebRequestContent.js',
     'addons/WebRequestUpload.jsm',
     'AppMenuNotifications.jsm',
deleted file mode 100644
--- a/toolkit/modules/tests/xpcshell/test_MatchGlobs.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-Components.utils.import("resource://gre/modules/MatchPattern.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-function test(url, pattern) {
-  let uri = Services.io.newURI(url);
-  let m = new MatchGlobs(pattern);
-  return m.matches(uri.spec);
-}
-
-function pass({url, pattern}) {
-  ok(test(url, pattern), `Expected match: ${JSON.stringify(pattern)}, ${url}`);
-}
-
-function fail({url, pattern}) {
-  ok(!test(url, pattern), `Expected no match: ${JSON.stringify(pattern)}, ${url}`);
-}
-
-function run_test() {
-  let moz = "http://mozilla.org";
-
-  pass({url: moz, pattern: ["*"]});
-  pass({url: moz, pattern: ["http://*"]}),
-  pass({url: moz, pattern: ["*mozilla*"]});
-  pass({url: moz, pattern: ["*example*", "*mozilla*"]});
-
-  pass({url: moz, pattern: ["*://*"]});
-  pass({url: "https://mozilla.org", pattern: ["*://*"]});
-
-  // Documentation example
-  pass({url: "http://www.example.com/foo/bar", pattern: ["http://???.example.com/foo/*"]});
-  pass({url: "http://the.example.com/foo/", pattern: ["http://???.example.com/foo/*"]});
-  fail({url: "http://my.example.com/foo/bar", pattern: ["http://???.example.com/foo/*"]});
-  fail({url: "http://example.com/foo/", pattern: ["http://???.example.com/foo/*"]});
-  fail({url: "http://www.example.com/foo", pattern: ["http://???.example.com/foo/*"]});
-
-  // Matches path
-  let path = moz + "/abc/def";
-  pass({url: path, pattern: ["*def"]});
-  pass({url: path, pattern: ["*c/d*"]});
-  pass({url: path, pattern: ["*org/abc*"]});
-  fail({url: path + "/", pattern: ["*def"]});
-
-  // Trailing slash
-  pass({url: moz, pattern: ["*.org/"]});
-  fail({url: moz, pattern: ["*.org"]});
-
-  // Wrong TLD
-  fail({url: moz, pattern: ["www*.m*.com/"]});
-  // Case sensitive
-  fail({url: moz, pattern: ["*.ORG/"]});
-
-  fail({url: moz, pattern: []});
-}
deleted file mode 100644
--- a/toolkit/modules/tests/xpcshell/test_MatchPattern.js
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-Components.utils.import("resource://gre/modules/MatchPattern.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-
-function test_matches() {
-  function test(url, pattern) {
-    let uri = Services.io.newURI(url);
-    let m = new MatchPattern(pattern);
-    return m.matches(uri);
-  }
-
-  function pass({url, pattern}) {
-    do_check_true(test(url, pattern), `Expected match: ${JSON.stringify(pattern)}, ${url}`);
-  }
-
-  function fail({url, pattern}) {
-    do_check_false(test(url, pattern), `Expected no match: ${JSON.stringify(pattern)}, ${url}`);
-  }
-
-  // Invalid pattern.
-  fail({url: "http://mozilla.org", pattern: ""});
-
-  // Pattern must include trailing slash.
-  fail({url: "http://mozilla.org", pattern: "http://mozilla.org"});
-
-  // Protocol not allowed.
-  fail({url: "http://mozilla.org", pattern: "gopher://wuarchive.wustl.edu/"});
-
-  pass({url: "http://mozilla.org", pattern: "http://mozilla.org/"});
-  pass({url: "http://mozilla.org/", pattern: "http://mozilla.org/"});
-
-  pass({url: "http://mozilla.org/", pattern: "*://mozilla.org/"});
-  pass({url: "https://mozilla.org/", pattern: "*://mozilla.org/"});
-  fail({url: "file://mozilla.org/", pattern: "*://mozilla.org/"});
-  fail({url: "ftp://mozilla.org/", pattern: "*://mozilla.org/"});
-
-  fail({url: "http://mozilla.com", pattern: "http://*mozilla.com*/"});
-  fail({url: "http://mozilla.com", pattern: "http://mozilla.*/"});
-  fail({url: "http://mozilla.com", pattern: "http:/mozilla.com/"});
-
-  pass({url: "http://google.com", pattern: "http://*.google.com/"});
-  pass({url: "http://docs.google.com", pattern: "http://*.google.com/"});
-
-  pass({url: "http://mozilla.org:8080", pattern: "http://mozilla.org/"});
-  pass({url: "http://mozilla.org:8080", pattern: "*://mozilla.org/"});
-  fail({url: "http://mozilla.org:8080", pattern: "http://mozilla.org:8080/"});
-
-  // Now try with * in the path.
-  pass({url: "http://mozilla.org", pattern: "http://mozilla.org/*"});
-  pass({url: "http://mozilla.org/", pattern: "http://mozilla.org/*"});
-
-  pass({url: "http://mozilla.org/", pattern: "*://mozilla.org/*"});
-  pass({url: "https://mozilla.org/", pattern: "*://mozilla.org/*"});
-  fail({url: "file://mozilla.org/", pattern: "*://mozilla.org/*"});
-  fail({url: "http://mozilla.com", pattern: "http://mozilla.*/*"});
-
-  pass({url: "http://google.com", pattern: "http://*.google.com/*"});
-  pass({url: "http://docs.google.com", pattern: "http://*.google.com/*"});
-
-  // Check path stuff.
-  fail({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/"});
-  pass({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/*"});
-  pass({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/a*f"});
-  pass({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/a*"});
-  pass({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/*f"});
-  fail({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/*e"});
-  fail({url: "http://mozilla.com/abc/def", pattern: "http://mozilla.com/*c"});
-
-  fail({url: "http:///a.html", pattern: "http:///a.html"});
-  pass({url: "file:///foo", pattern: "file:///foo*"});
-  pass({url: "file:///foo/bar.html", pattern: "file:///foo*"});
-
-  pass({url: "http://mozilla.org/a", pattern: "<all_urls>"});
-  pass({url: "https://mozilla.org/a", pattern: "<all_urls>"});
-  pass({url: "ftp://mozilla.org/a", pattern: "<all_urls>"});
-  pass({url: "file:///a", pattern: "<all_urls>"});
-  fail({url: "gopher://wuarchive.wustl.edu/a", pattern: "<all_urls>"});
-
-  // Multiple patterns.
-  pass({url: "http://mozilla.org", pattern: ["http://mozilla.org/"]});
-  pass({url: "http://mozilla.org", pattern: ["http://mozilla.org/", "http://mozilla.com/"]});
-  pass({url: "http://mozilla.com", pattern: ["http://mozilla.org/", "http://mozilla.com/"]});
-  fail({url: "http://mozilla.biz", pattern: ["http://mozilla.org/", "http://mozilla.com/"]});
-
-  // Match url with fragments.
-  pass({url: "http://mozilla.org/base#some-fragment", pattern: "http://mozilla.org/base"});
-}
-
-function test_overlaps() {
-  function test(filter, hosts, optional) {
-    const f = new MatchPattern(filter);
-    return f.overlapsPermissions(new MatchPattern(hosts), new MatchPattern(optional));
-  }
-
-  function pass({filter = [], hosts = [], optional = []}) {
-    ok(test(filter, hosts, optional), `Expected overlap: ${filter}, ${hosts} (${optional})`);
-  }
-
-  function fail({filter = [], hosts = [], optional = []}) {
-    ok(!test(filter, hosts, optional), `Expected no overlap: ${filter}, ${hosts} (${optional})`);
-  }
-
-  // Direct comparison.
-  pass({hosts: "http://ab.cd/", filter: "http://ab.cd/"});
-  fail({hosts: "http://ab.cd/", filter: "ftp://ab.cd/"});
-
-  // Wildcard protocol.
-  pass({hosts: "*://ab.cd/", filter: "https://ab.cd/"});
-  fail({hosts: "*://ab.cd/", filter: "ftp://ab.cd/"});
-
-  // Wildcard subdomain.
-  pass({hosts: "http://*.ab.cd/", filter: "http://ab.cd/"});
-  pass({hosts: "http://*.ab.cd/", filter: "http://www.ab.cd/"});
-  fail({hosts: "http://*.ab.cd/", filter: "http://ab.cd.ef/"});
-  fail({hosts: "http://*.ab.cd/", filter: "http://www.cd/"});
-
-  // Wildcard subsumed.
-  pass({hosts: "http://*.ab.cd/", filter: "http://*.cd/"});
-  fail({hosts: "http://*.cd/", filter: "http://*.xy/"});
-
-  // Subdomain vs substring.
-  fail({hosts: "http://*.ab.cd/", filter: "http://fake-ab.cd/"});
-  fail({hosts: "http://*.ab.cd/", filter: "http://*.fake-ab.cd/"});
-
-  // Wildcard domain.
-  pass({hosts: "http://*/", filter: "http://ab.cd/"});
-  fail({hosts: "http://*/", filter: "https://ab.cd/"});
-
-  // Wildcard wildcards.
-  pass({hosts: "<all_urls>", filter: "ftp://ab.cd/"});
-  fail({hosts: "<all_urls>", filter: ""});
-  fail({hosts: "<all_urls>"});
-
-  // Multiple hosts.
-  pass({hosts: ["http://ab.cd/"], filter: ["http://ab.cd/"]});
-  pass({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: "http://ab.cd/"});
-  pass({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: "http://ab.xy/"});
-  fail({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: "http://ab.zz/"});
-
-  // Multiple Multiples.
-  pass({hosts: ["http://*.ab.cd/"], filter: ["http://ab.cd/", "http://www.ab.cd/"]});
-  pass({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: ["http://ab.cd/", "http://ab.xy/"]});
-  fail({hosts: ["http://ab.cd/", "http://ab.xy/"], filter: ["http://ab.cd/", "http://ab.zz/"]});
-
-  // Optional.
-  pass({hosts: [], optional: "http://ab.cd/", filter: "http://ab.cd/"});
-  pass({hosts: "http://ab.cd/", optional: "http://ab.xy/", filter: ["http://ab.cd/", "http://ab.xy/"]});
-  fail({hosts: "http://ab.cd/", optional: "https://ab.xy/", filter: "http://ab.xy/"});
-}
-
-function run_test() {
-  test_matches();
-  test_overlaps();
-}
--- a/toolkit/modules/tests/xpcshell/test_MatchURLFilters.js
+++ b/toolkit/modules/tests/xpcshell/test_MatchURLFilters.js
@@ -1,14 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-Components.utils.import("resource://gre/modules/MatchPattern.jsm");
+Components.utils.import("resource://gre/modules/MatchURLFilters.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 function createTestFilter({url, filters}) {
   let m = new MatchURLFilters(filters);
   return m.matches(url);
 }
 
 function expectPass({url, filters}) {
--- a/toolkit/modules/tests/xpcshell/xpcshell.ini
+++ b/toolkit/modules/tests/xpcshell/xpcshell.ini
@@ -23,20 +23,16 @@ skip-if = toolkit == 'android'
 skip-if = toolkit == 'android'
 [test_Integration.js]
 [test_jsesc.js]
 skip-if = toolkit == 'android'
 [test_JSONFile.js]
 skip-if = toolkit == 'android'
 [test_Log.js]
 skip-if = toolkit == 'android'
-[test_MatchPattern.js]
-skip-if = toolkit == 'android'
-[test_MatchGlobs.js]
-skip-if = toolkit == 'android'
 [test_MatchURLFilters.js]
 skip-if = toolkit == 'android'
 [test_NewTabUtils.js]
 skip-if = toolkit == 'android'
 [test_ObjectUtils.js]
 skip-if = toolkit == 'android'
 [test_ObjectUtils_strict.js]
 skip-if = toolkit == 'android'
--- a/tools/lint/eslint/modules.json
+++ b/tools/lint/eslint/modules.json
@@ -126,17 +126,17 @@
   "logger.jsm": ["Logger"],
   "logging.js": ["getTestLogger", "initTestLogging"],
   "LoginManagerContent.jsm": ["LoginManagerContent", "LoginFormFactory", "UserAutoCompleteResult"],
   "LoginRecipes.jsm": ["LoginRecipesContent", "LoginRecipesParent"],
   "logmanager.js": ["LogManager"],
   "lz4.js": ["Lz4"],
   "lz4_internal.js": ["Primitives"],
   "main.js": ["Weave"],
-  "MatchPattern.jsm": ["MatchPattern", "MatchGlobs", "MatchURLFilters"],
+  "MatchURLFilters.jsm": ["MatchURLFilters"],
   "mcc_iso3166_table.jsm": ["MCC_ISO3166_TABLE"],
   "message.js": ["Command", "Message", "MessageOrigin", "Response"],
   "MessageContext.jsm": ["MessageContext"],
   "Messaging.jsm": ["sendMessageToJava", "Messaging", "EventDispatcher"],
   "microformat-shiv.js": ["Microformats"],
   "MigrationUtils.jsm": ["MigrationUtils", "MigratorPrototype"],
   "mozelement.js": ["Elem", "Selector", "ID", "Link", "XPath", "Name", "Lookup", "MozMillElement", "MozMillCheckBox", "MozMillRadio", "MozMillDropList", "MozMillTextBox", "subclasses"],
   "mozmill.js": ["controller", "utils", "elementslib", "os", "getBrowserController", "newBrowserController", "getAddonsController", "getPreferencesController", "newMail3PaneController", "getMail3PaneController", "wm", "platform", "getAddrbkController", "getMsgComposeController", "getDownloadsController", "Application", "findElement", "getPlacesController", "isMac", "isLinux", "isWindows", "firePythonCallback", "getAddons"],