/* 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 createTestFilter({url, filters}) { let m = new MatchURLFilters(filters); return m.matches(url); } function expectPass({url, filters}) { ok(createTestFilter({url, filters}), `Expected match: ${JSON.stringify(filters)}, ${url}`); } function expectFail({url, filters}) { ok(!createTestFilter({url, filters}), `Expected no match: ${JSON.stringify(filters)}, ${url}`); } function expectThrow({url, filters, exceptionMessageContains}) { let logData = {filters, url}; Assert.throws( () => { createTestFilter({url, filters}); }, exceptionMessageContains, `Check received exception for expected message: ${JSON.stringify(logData)}` ); } add_task(function* test_match_url_filters() { const shouldPass = true; const shouldFail = true; const shouldThrow = true; var testCases = [ // Empty, undefined and null filters. {shouldThrow, exceptionMessageContains: "filters array should not be empty", filters: [], url: "http://mozilla.org", }, {shouldThrow, exceptionMessageContains: "filters should be an array", filters: undefined, url: "http://mozilla.org"}, {shouldThrow, exceptionMessageContains: "filters should be an array", filters: null, url: "http://mozilla.org"}, // Wrong formats (in a real webextension this will be blocked by the schema validation). {shouldThrow, exceptionMessageContains: "filters should be an array", filters: {}, url: "http://mozilla.org"}, {shouldThrow, exceptionMessageContains: "filters should be an array", filters: {nonExistentCriteria: true}, url: "http://mozilla.org", }, {shouldPass, filters: [{nonExistentCriteria: true}], url: "http://mozilla.org"}, // Schemes filter over various url schemes. {shouldPass, filters: [{schemes: ["http"]}], url: "http://mozilla.org"}, {shouldPass, filters: [{schemes: ["https"]}], url: "https://mozilla.org"}, {shouldPass, filters: [{schemes: ["ftp"]}], url: "ftp://fake/ftp/url"}, {shouldPass, filters: [{schemes: ["about"]}], url: "about:blank"}, {shouldPass, filters: [{schemes: ["data"]}], url: "data:,testDataURL"}, {shouldFail, filters: [{schemes: ["http"]}], url: "ftp://fake/ftp/url"}, // Multiple schemes: pass when at least one scheme matches. {shouldPass, filters: [{schemes: ["https", "about"]}], url: "https://mozilla.org"}, {shouldPass, filters: [{schemes: ["about", "https"]}], url: "https://mozilla.org"}, {shouldFail, filters: [{schemes: ["about", "http"]}], url: "https://mozilla.org"}, // Port filter: standard (implicit) ports. {shouldPass, filters: [{ports: [443]}], url: "https://mozilla.org"}, {shouldPass, filters: [{ports: [80]}], url: "http://mozilla.org"}, {shouldPass, filters: [{ports: [21]}], url: "ftp://ftp.mozilla.org"}, // Port filter: schemes without a default port. {shouldFail, filters: [{ports: [-1]}], url: "about:blank"}, {shouldFail, filters: [{ports: [-1]}], url: "data:,testDataURL"}, {shouldFail, filters: [{ports: [[1, 65535]]}], url: "about:blank"}, {shouldFail, filters: [{ports: [[1, 65535]]}], url: "data:,testDataURL"}, // Host filters (hostEquals, hostContains, hostPrefix, hostSuffix): schemes with an host. {shouldFail, filters: [{hostEquals: ""}], url: "https://mozilla.org"}, {shouldPass, filters: [{hostEquals: null}], url: "https://mozilla.org"}, {shouldPass, filters: [{hostEquals: "mozilla.org"}], url: "https://mozilla.org"}, {shouldFail, filters: [{hostEquals: "mozilla.com"}], url: "https://mozilla.org"}, // NOTE: trying at least once another valid protocol. {shouldPass, filters: [{hostEquals: "mozilla.org"}], url: "ftp://mozilla.org"}, {shouldFail, filters: [{hostEquals: "mozilla.com"}], url: "ftp://mozilla.org"}, {shouldPass, filters: [{hostEquals: "mozilla.org"}], url: "https://mozilla.org:8888"}, {shouldPass, filters: [{hostContains: "moz"}], url: "https://mozilla.org"}, // NOTE: an implicit '.' char is inserted into the host. {shouldPass, filters: [{hostContains: ".moz"}], url: "https://mozilla.org"}, {shouldFail, filters: [{hostContains: "com"}], url: "https://mozilla.org"}, {shouldPass, filters: [{hostContains: ""}], url: "https://mozilla.org"}, {shouldPass, filters: [{hostContains: null}], url: "https://mozilla.org"}, {shouldPass, filters: [{hostPrefix: "moz"}], url: "https://mozilla.org"}, {shouldFail, filters: [{hostPrefix: "org"}], url: "https://mozilla.org"}, {shouldPass, filters: [{hostPrefix: ""}], url: "https://mozilla.org"}, {shouldPass, filters: [{hostPrefix: null}], url: "https://mozilla.org"}, {shouldPass, filters: [{hostSuffix: ".org"}], url: "https://mozilla.org"}, {shouldFail, filters: [{hostSuffix: "moz"}], url: "https://mozilla.org"}, {shouldPass, filters: [{hostSuffix: ""}], url: "https://mozilla.org"}, {shouldPass, filters: [{hostSuffix: null}], url: "https://mozilla.org"}, {shouldPass, filters: [{hostSuffix: "lla.org"}], url: "https://mozilla.org:8888"}, // hostEquals: urls without an host. // TODO: should we explicitly cover hostContains, hostPrefix, hostSuffix for // these sub-cases? {shouldFail, filters: [{hostEquals: "blank"}], url: "about:blank"}, {shouldFail, filters: [{hostEquals: "blank"}], url: "about://blank"}, {shouldFail, filters: [{hostEquals: "testDataURL"}], url: "data:,testDataURL"}, {shouldPass, filters: [{hostEquals: ""}], url: "about:blank"}, {shouldPass, filters: [{hostEquals: ""}], url: "about://blank"}, {shouldPass, filters: [{hostEquals: ""}], url: "data:,testDataURL"}, // Path filters (pathEquals, pathContains, pathPrefix, pathSuffix). {shouldFail, filters: [{pathEquals: ""}], url: "https://mozilla.org/test/path"}, {shouldPass, filters: [{pathEquals: null}], url: "https://mozilla.org/test/path"}, {shouldPass, filters: [{pathEquals: "/test/path"}], url: "https://mozilla.org/test/path"}, {shouldFail, filters: [{pathEquals: "/wrong/path"}], url: "https://mozilla.org/test/path"}, {shouldPass, filters: [{pathEquals: "/test/path"}], url: "https://mozilla.org:8888/test/path"}, // NOTE: trying at least once another valid protocol {shouldPass, filters: [{pathEquals: "/test/path"}], url: "ftp://mozilla.org/test/path"}, {shouldFail, filters: [{pathEquals: "/wrong/path"}], url: "ftp://mozilla.org/test/path"}, {shouldPass, filters: [{pathContains: "st/"}], url: "https://mozilla.org/test/path"}, {shouldPass, filters: [{pathContains: "/test"}], url: "https://mozilla.org/test/path"}, {shouldFail, filters: [{pathContains: "org"}], url: "https://mozilla.org/test/path"}, {shouldPass, filters: [{pathContains: ""}], url: "https://mozilla.org/test/path"}, {shouldPass, filters: [{pathContains: null}], url: "https://mozilla.org/test/path"}, {shouldFail, filters: [{pathContains: "param"}], url: "https://mozilla.org:8888/test/path?param=1"}, {shouldFail, filters: [{pathContains: "ref"}], url: "https://mozilla.org:8888/test/path#ref"}, {shouldPass, filters: [{pathContains: "st/pa"}], url: "https://mozilla.org:8888/test/path"}, {shouldPass, filters: [{pathPrefix: "/te"}], url: "https://mozilla.org/test/path"}, {shouldFail, filters: [{pathPrefix: "org/"}], url: "https://mozilla.org/test/path"}, {shouldPass, filters: [{pathPrefix: ""}], url: "https://mozilla.org/test/path"}, {shouldPass, filters: [{pathPrefix: null}], url: "https://mozilla.org/test/path"}, {shouldPass, filters: [{pathSuffix: "/path"}], url: "https://mozilla.org/test/path"}, {shouldFail, filters: [{pathSuffix: "th/"}], url: "https://mozilla.org/test/path"}, {shouldPass, filters: [{pathSuffix: ""}], url: "https://mozilla.org/test/path"}, {shouldPass, filters: [{pathSuffix: null}], url: "https://mozilla.org/test/path"}, {shouldFail, filters: [{pathSuffix: "p=1"}], url: "https://mozilla.org:8888/test/path?p=1"}, {shouldFail, filters: [{pathSuffix: "ref"}], url: "https://mozilla.org:8888/test/path#ref"}, // Query filters (queryEquals, queryContains, queryPrefix, querySuffix). {shouldFail, filters: [{queryEquals: ""}], url: "https://mozilla.org/?param=val"}, {shouldPass, filters: [{queryEquals: null}], url: "https://mozilla.org/?param=val"}, {shouldPass, filters: [{queryEquals: "param=val"}], url: "https://mozilla.org/?param=val"}, {shouldFail, filters: [{queryEquals: "?param=val"}], url: "https://mozilla.org/?param=val"}, {shouldFail, filters: [{queryEquals: "/path?param=val"}], url: "https://mozilla.org/path?param=val"}, // NOTE: about scheme urls cannot be matched by query. {shouldFail, filters: [{queryEquals: "param=val"}], url: "about:blank?param=val"}, {shouldFail, filters: [{queryEquals: "param"}], url: "ftp://mozilla.org?param=val"}, {shouldPass, filters: [{queryContains: "ram"}], url: "https://mozilla.org/?param=val"}, {shouldPass, filters: [{queryContains: "=val"}], url: "https://mozilla.org/?param=val"}, {shouldFail, filters: [{queryContains: "?param"}], url: "https://mozilla.org/?param=val"}, {shouldFail, filters: [{queryContains: "path"}], url: "https://mozilla.org/path/?p=v#ref"}, {shouldPass, filters: [{queryContains: ""}], url: "https://mozilla.org/?param=val"}, {shouldPass, filters: [{queryContains: null}], url: "https://mozilla.org/?param=val"}, {shouldPass, filters: [{queryPrefix: "param"}], url: "https://mozilla.org/?param=val"}, {shouldFail, filters: [{queryPrefix: "p="}], url: "https://mozilla.org/?param=val"}, {shouldFail, filters: [{queryPrefix: "path"}], url: "https://mozilla.org/path?param=val"}, {shouldPass, filters: [{queryPrefix: ""}], url: "https://mozilla.org/?param=val"}, {shouldPass, filters: [{queryPrefix: null}], url: "https://mozilla.org/?param=val"}, {shouldPass, filters: [{querySuffix: "=val"}], url: "https://mozilla.org/?param=val"}, {shouldFail, filters: [{querySuffix: "=wrong"}], url: "https://mozilla.org/?param=val"}, {shouldPass, filters: [{querySuffix: ""}], url: "https://mozilla.org/?param=val"}, {shouldPass, filters: [{querySuffix: null}], url: "https://mozilla.org/?param=val"}, // URL filters (urlEquals, urlContains, urlPrefix, urlSuffix). {shouldFail, filters: [{urlEquals: ""}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlEquals: null}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlEquals: "https://mozilla.org/?p=v#ref"}], url: "https://mozilla.org/?p=v#ref"}, {shouldFail, filters: [{urlEquals: "https://mozilla.org/?p=v#ref2"}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlEquals: "about:blank?p=v#ref"}], url: "about:blank?p=v#ref"}, {shouldPass, filters: [{urlEquals: "ftp://mozilla.org?p=v#ref"}], url: "ftp://mozilla.org?p=v#ref"}, {shouldPass, filters: [{urlContains: "org/?p"}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlContains: "=v#ref"}], url: "https://mozilla.org/?p=v#ref"}, {shouldFail, filters: [{urlContains: "ftp"}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlContains: ""}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlContains: null}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlPrefix: "http"}], url: "https://mozilla.org/?p=v#ref"}, {shouldFail, filters: [{urlPrefix: "moz"}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlPrefix: ""}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlPrefix: null}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlSuffix: "#ref"}], url: "https://mozilla.org/?p=v#ref"}, {shouldFail, filters: [{urlSuffix: "=wrong"}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlSuffix: ""}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlSuffix: null}], url: "https://mozilla.org/?p=v#ref"}, // More url filters: urlMatches. {shouldPass, filters: [{urlMatches: ".*://mozilla"}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlMatches: ".*://mozilla"}], url: "ftp://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlMatches: ".*://.*/\?p"}], url: "ftp://mozilla.org/?p=v#ref"}, // NOTE: urlMatches should not match the url without the ref. {shouldFail, filters: [{urlMatches: "v#ref$"}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{urlMatches: "^ftp"}], url: "ftp://mozilla.org/?p=v#ref"}, // More url filters: originAndPathMatches. {shouldPass, filters: [{originAndPathMatches: ".*://mozilla"}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{originAndPathMatches: ".*://mozilla"}], url: "ftp://mozilla.org/?p=v#ref"}, // NOTE: urlMatches should not match the url without the query and the ref. {shouldFail, filters: [{originAndPathMatches: ".*://.*/\?p"}], url: "ftp://mozilla.org/?p=v#ref"}, {shouldFail, filters: [{originAndPathMatches: "v#ref$"}], url: "https://mozilla.org/?p=v#ref"}, {shouldPass, filters: [{originAndPathMatches: "^ftp"}], url: "ftp://mozilla.org/?p=v#ref"}, // Filter with all criteria: all matches, none matches, some matches. // All matches. {shouldPass, filters: [ { schemes: ["https", "http"], ports: [443, 80], hostEquals: "www.mozilla.org", hostContains: ".moz", hostPrefix: "www", hostSuffix: "org", pathEquals: "/sub/path", pathContains: "b/p", pathPrefix: "/sub", pathSuffix: "/path", queryEquals: "p=v", queryContains: "1=", queryPrefix: "p1", querySuffix: "=v", urlEquals: "https://www.mozilla.org/sub/path?p1=v#ref", urlContains: "org/sub", urlPrefix: "https://moz", urlSuffix: "#ref", urlMatches: "v#ref$", originAndPathMatches: ".*://moz.*/" }, ], url: "https://www.mozilla.org/sub/path?p1=v#ref"}, // None matches. {shouldFail, filters: [ { schemes: ["http"], ports: [80], hostEquals: "mozilla.com", hostContains: "www.moz", hostPrefix: "www", hostSuffix: "com", pathEquals: "/wrong/path", pathContains: "g/p", pathPrefix: "/wrong", pathSuffix: "/wrong", queryEquals: "p2=v", queryContains: "2=", queryPrefix: "p2", querySuffix: "=value", urlEquals: "http://mozilla.com/sub/path?p1=v#ref", urlContains: "com/sub", urlPrefix: "http://moz", urlSuffix: "#ref2", urlMatches: "value#ref2$", originAndPathMatches: ".*://moz.*com/" }, ], url: "https://mozilla.org/sub/path?p1=v#ref"}, // Some matches {shouldFail, filters: [ { schemes: ["https"], ports: [80], hostEquals: "mozilla.com", hostContains: "www.moz", hostPrefix: "www", hostSuffix: "com", pathEquals: "/wrong/path", pathContains: "g/p", pathPrefix: "/wrong", pathSuffix: "/wrong", queryEquals: "p2=v", queryContains: "2=", queryPrefix: "p2", querySuffix: "=value", urlEquals: "http://mozilla.com/sub/path?p1=v#ref", urlContains: "com/sub", urlPrefix: "http://moz", urlSuffix: "#ref2", urlMatches: "value#ref2$", originAndPathMatches: ".*://moz.*com/" }, ], url: "https://mozilla.org/sub/path?p1=v#ref"}, // Filter with multiple filters: all matches, some matches, none matches. // All matches. {shouldPass, filters: [ {schemes: ["https", "http"]}, {ports: [443, 80]}, {hostEquals: "www.mozilla.org"}, {hostContains: ".moz"}, {hostPrefix: "www"}, {hostSuffix: "org"}, {pathEquals: "/sub/path"}, {pathContains: "b/p"}, {pathPrefix: "/sub"}, {pathSuffix: "/path"}, {queryEquals: "p=v"}, {queryContains: "1="}, {queryPrefix: "p1"}, {querySuffix: "=v"}, {urlEquals: "https://www.mozilla.org/sub/path?p1=v#ref"}, {urlContains: "org/sub"}, {urlPrefix: "https://moz"}, {urlSuffix: "#ref"}, {urlMatches: "v#ref$"}, {originAndPathMatches: ".*://moz.*/"}, ], url: "https://www.mozilla.org/sub/path?p1=v#ref"}, // None matches. {shouldFail, filters: [ {schemes: ["http"]}, {ports: [80]}, {hostEquals: "mozilla.com"}, {hostContains: "www.moz"}, {hostPrefix: "www"}, {hostSuffix: "com"}, {pathEquals: "/wrong/path"}, {pathContains: "g/p"}, {pathPrefix: "/wrong"}, {pathSuffix: "/wrong"}, {queryEquals: "p2=v"}, {queryContains: "2="}, {queryPrefix: "p2"}, {querySuffix: "=value"}, {urlEquals: "http://mozilla.com/sub/path?p1=v#ref"}, {urlContains: "com/sub"}, {urlPrefix: "http://moz"}, {urlSuffix: "#ref2"}, {urlMatches: "value#ref2$"}, {originAndPathMatches: ".*://moz.*com/"}, ], url: "https://mozilla.org/sub/path?p1=v#ref"}, // Some matches. {shouldPass, filters: [ {schemes: ["https"]}, {ports: [80]}, {hostEquals: "mozilla.com"}, {hostContains: "www.moz"}, {hostPrefix: "www"}, {hostSuffix: "com"}, {pathEquals: "/wrong/path"}, {pathContains: "g/p"}, {pathPrefix: "/wrong"}, {pathSuffix: "/wrong"}, {queryEquals: "p2=v"}, {queryContains: "2="}, {queryPrefix: "p2"}, {querySuffix: "=value"}, {urlEquals: "http://mozilla.com/sub/path?p1=v#ref"}, {urlContains: "com/sub"}, {urlPrefix: "http://moz"}, {urlSuffix: "#ref2"}, {urlMatches: "value#ref2$"}, {originAndPathMatches: ".*://moz.*com/"}, ], url: "https://mozilla.org/sub/path?p1=v#ref"}, ]; // Run all the the testCases defined above. for (let currentTest of testCases) { let { exceptionMessageContains, url, filters, } = currentTest; if (currentTest.shouldThrow) { expectThrow({url, filters, exceptionMessageContains}) } else if (currentTest.shouldFail) { expectFail({url, filters}); } else { expectPass({url, filters}); } } });