diff --git a/src/utils/matcher.js b/src/utils/matcher.js index c5394ebcc..8c3da4091 100644 --- a/src/utils/matcher.js +++ b/src/utils/matcher.js @@ -13,14 +13,14 @@ import bugDb from '../classes/BugDb'; import conf from '../classes/Conf'; -import { processUrl, processFpeUrl } from './utils'; +import { processUrl, processTrackerUrl } from './utils'; import { log } from './common'; // ALL APIS IN THIS FILE ARE PERFORMANCE-CRITICAL /** - * Determine if a url matches an entry in an array urls. - * The matching is permissive. + * Determine if a url matches an entry in an array urls. The matching is + * permissive. Used for matching FirstPartyException and CompatibilityDB urls. * @memberOf BackgroundUtils * * @param {string} url url to match @@ -39,10 +39,10 @@ export function fuzzyUrlMatcher(url, urls) { } for (let i = 0; i < urls.length; i++) { - const { host, path } = processFpeUrl(urls[i]); + const { host, path } = processTrackerUrl(urls[i]); if (host === tab_host) { if (!path) { - log(`[fuzzyUrlMatcher] host (${host}) match`); + log(`[fuzzyUrlMatcher] host (${host}) strict match`); return true; } @@ -52,9 +52,26 @@ export function fuzzyUrlMatcher(url, urls) { return true; } } else if (path === tab_path) { - log(`[fuzzyUrlMatcher] host (${host}) and path (${path}) match`); + log(`[fuzzyUrlMatcher] host (${host}) and path (${path}) strict match`); return true; } + } else if (host.substr(0, 2) === '*.') { + if (tab_host.endsWith(host.slice(2))) { + if (!path) { + log(`[fuzzyUrlMatcher] host (${host}) fuzzy match`); + return true; + } + + if (path.slice(-1) === '*') { + if (tab_path.startsWith(path.slice(0, -1))) { + log(`[fuzzyUrlMatcher] host (${host}) and path (${path}) both fuzzy match`); + return true; + } + } else if (path === tab_path) { + log(`[fuzzyUrlMatcher] host (${host}) fuzzy match and path (${path}) strict match`); + return true; + } + } } } return false; diff --git a/src/utils/utils.js b/src/utils/utils.js index 6bde5a64c..0b90f81f2 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -144,13 +144,14 @@ export function defineLazyProperty(obj, prop, callback) { } /** - * Process First Party Exception URLs to return host and path. + * Quickly process tracker URLs to return host and path. Used with fuzzyUrlMatcher() + * to parse FirstPartyException and CompatibilityDB URLs * @memberOf BackgroundUtils * - * @param {string} src the first party exception url + * @param {string} src the tracker url * @return {Object} contains host, path as properties */ -export function processFpeUrl(src) { +export function processTrackerUrl(src) { const index = src.indexOf('/'); const host = (index === -1) ? src : src.substring(0, index); const path = (index === -1) ? '' : src.substring(index + 1); diff --git a/test/utils/matcher.test.js b/test/utils/matcher.test.js index 6c2ea466e..fcca33e90 100644 --- a/test/utils/matcher.test.js +++ b/test/utils/matcher.test.js @@ -155,21 +155,54 @@ describe('src/utils/matcher.js', () => { }); describe('testing fuzzyUrlMatcher()', () => { - const urls = ['google.com', 'ghostery.com/products', 'example.com/page*']; - - test('host match', () => { + const urls = [ + 'google.com', + 'ghostery.com/products', + 'example.com/page*', + '*.atlassian.net', + '*.twitter.com/ghostery', + '*.jira.net/board*', + '*facebook.com', + ]; + + test('host strict match', () => { expect(fuzzyUrlMatcher('https://google.com/analytics', urls)).toBeTruthy(); expect(fuzzyUrlMatcher('https://analytics.google.com/something', urls)).toBeFalsy(); + expect(fuzzyUrlMatcher('https://example.com/', urls)).toBeFalsy(); }); - test('host and path fuzzy match', () => { + test('host and path strict match', () => { + expect(fuzzyUrlMatcher('https://ghostery.com/products', urls)).toBeTruthy(); + expect(fuzzyUrlMatcher('https://ghostery.com/products1', urls)).toBeFalsy(); + }); + + test('host fuzzy match', () => { + expect(fuzzyUrlMatcher('https://ghostery.atlassian.net', urls)).toBeTruthy(); + expect(fuzzyUrlMatcher('https://ghostery.atlassian.net/board', urls)).toBeTruthy(); + expect(fuzzyUrlMatcher('https://ghostery.atlassian.com', urls)).toBeFalsy(); + }); + + test('host fuzzy match rules require \'.\' ', () => { + expect(fuzzyUrlMatcher('https://something.facebook.com', urls)).toBeFalsy(); + expect(fuzzyUrlMatcher('https://facebook.com', urls)).toBeFalsy(); + }); + + test('host fuzzy match and path strict match', () => { + expect(fuzzyUrlMatcher('https://page.twitter.com/ghostery', urls)).toBeTruthy(); + expect(fuzzyUrlMatcher('https://page.twitter.com/ghostery2', urls)).toBeFalsy(); + expect(fuzzyUrlMatcher('https://page.twitter.com/geistery', urls)).toBeFalsy(); + }); + + test('host strict match and path fuzzy match', () => { expect(fuzzyUrlMatcher('https://example.com/page_anything', urls)).toBeTruthy(); expect(fuzzyUrlMatcher('https://example.com/p', urls)).toBeFalsy(); + expect(fuzzyUrlMatcher('https://page.example.com/page', urls)).toBeFalsy(); }); - test('host and path match', () => { - expect(fuzzyUrlMatcher('https://ghostery.com/products', urls)).toBeTruthy(); - expect(fuzzyUrlMatcher('https://ghostery.com/products1', urls)).toBeFalsy(); + test('host and path fuzzy match', () => { + expect(fuzzyUrlMatcher('https://ghostery.jira.net/board', urls)).toBeTruthy(); + expect(fuzzyUrlMatcher('https://ghostery.jira.net/b', urls)).toBeFalsy(); + expect(fuzzyUrlMatcher('https://ghostery.jira.net/board100', urls)).toBeTruthy(); }); }); }); diff --git a/test/utils/utils.test.js b/test/utils/utils.test.js index a622547b3..e49af1d8c 100644 --- a/test/utils/utils.test.js +++ b/test/utils/utils.test.js @@ -11,7 +11,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0 */ -import { getJson, defineLazyProperty, processFpeUrl, semverCompare } from '../../src/utils/utils'; +import { getJson, defineLazyProperty, processTrackerUrl, semverCompare } from '../../src/utils/utils'; describe('tests for getJson()', () => { // Tests for getJson() @@ -62,12 +62,12 @@ describe('tests for defineLazyProperty()', () => { test('property function is still lazy', () => expect(neverCalledSpy).not.toHaveBeenCalled()); }); -describe('test for processFpeUrl()', () => { +describe('test for processTrackerUrl()', () => { test('host only', () => { - expect(processFpeUrl('ghostery.com')).toMatchObject({host: 'ghostery.com', path: ''}); + expect(processTrackerUrl('ghostery.com')).toMatchObject({host: 'ghostery.com', path: ''}); }); test('host and path', () => { - expect(processFpeUrl('ghostery.com/products')).toMatchObject({host: 'ghostery.com', path: 'products'}); + expect(processTrackerUrl('ghostery.com/products')).toMatchObject({host: 'ghostery.com', path: 'products'}); }); });