Bug 1404172: Remove MatchPattern.jsm. r=aswan
authorKris Maglione <maglione.k@gmail.com>
Thu, 28 Sep 2017 18:27:44 -0700
changeset 384544 c0a3da43b7cb28f87538c479040800e59b519e57
parent 384543 cca8c45c7a34e6d0363e998d4f6c73302016231f
child 384545 08cf5146eff130adffce563d2c96d2178a42bb65
push id95804
push usermaglione.k@gmail.com
push dateThu, 05 Oct 2017 02:09:37 +0000
treeherdermozilla-inbound@c0a3da43b7cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1404172
milestone58.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 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"],