From 87d94c5056874d6dd5ee57b7f1bc29689a2a780f Mon Sep 17 00:00:00 2001 From: Luiz Gonzaga dos Santos Filho Date: Sat, 13 Jun 2020 18:23:52 -0700 Subject: [PATCH] feat: add allow lists * refactor: move list tests to correct location * feat: allow lists Resolves #7 Resolves #8 Co-authored-by: FutureDuck --- __tests__/src/lib/{ => model}/list.spec.js | 7 ++++--- __tests__/src/lib/request_matcher.spec.js | 19 ++++++++++++++++--- src/lib/list_populator.js | 5 ++--- src/lib/model/allow_list.js | 7 +++++++ src/lib/request_matcher.js | 19 ++++++++++++++++++- src/shared/__url_fixtures.js | 6 +++--- 6 files changed, 50 insertions(+), 13 deletions(-) rename __tests__/src/lib/{ => model}/list.spec.js (89%) create mode 100644 src/lib/model/allow_list.js diff --git a/__tests__/src/lib/list.spec.js b/__tests__/src/lib/model/list.spec.js similarity index 89% rename from __tests__/src/lib/list.spec.js rename to __tests__/src/lib/model/list.spec.js index 56210a4..6f402be 100644 --- a/__tests__/src/lib/list.spec.js +++ b/__tests__/src/lib/model/list.spec.js @@ -1,11 +1,12 @@ -import List from '../../../src/lib/model/list.js'; +import List from '../../../../src/lib/model/list.js'; import { A_URL, - ANOTHER_URL, + URL_IN_NO_LISTS, SOME_URLS, -} from '../../../src/shared/__url_fixtures.js'; +} from '../../../../src/shared/__url_fixtures.js'; let list; +const ANOTHER_URL = URL_IN_NO_LISTS; beforeEach(() => { const RANDOM_TYPE = List.types.DENY_LIST; diff --git a/__tests__/src/lib/request_matcher.spec.js b/__tests__/src/lib/request_matcher.spec.js index 46bdb82..435fb8c 100644 --- a/__tests__/src/lib/request_matcher.spec.js +++ b/__tests__/src/lib/request_matcher.spec.js @@ -1,16 +1,29 @@ import RequestMatcher from '../../../src/lib/request_matcher.js'; -import { BAD_URL, GOOD_URL } from '../../../src/shared/__url_fixtures.js'; +import { + BAD_URL, + GOOD_URL, + URL_IN_NO_LISTS, +} from '../../../src/shared/__url_fixtures.js'; -beforeAll(() => RequestMatcher.denyList.add(BAD_URL)); -afterAll(() => RequestMatcher.denyList.clear()); +beforeEach(() => { + RequestMatcher.allowList.clear(); + RequestMatcher.denyList.clear(); +}); describe('Request Matcher', () => { it('should deny urls in the deny list', () => { + RequestMatcher.denyList.add(BAD_URL); const result = RequestMatcher.isDenied(BAD_URL); expect(result).toBe(true); }); it('should not deny urls if they are not in the deny list', () => { + const result = RequestMatcher.isDenied(URL_IN_NO_LISTS); + expect(result).toBe(false); + }); + + it('should allow urls if they are in the allow list', () => { + RequestMatcher.allowList.add(GOOD_URL); const result = RequestMatcher.isDenied(GOOD_URL); expect(result).toBe(false); }); diff --git a/src/lib/list_populator.js b/src/lib/list_populator.js index 5dd27c0..7e70c05 100644 --- a/src/lib/list_populator.js +++ b/src/lib/list_populator.js @@ -1,5 +1,5 @@ import List from './model/list.js'; -import { BAD_URLS } from '../shared/__url_fixtures.js'; +import { BAD_URLS, GOOD_URLS } from '../shared/__url_fixtures.js'; // TODO for now, just populating it with the examples from fixtures // TODO real deal: fetch from local files shipped with the extension, augment it with live sources... @@ -11,10 +11,9 @@ export default class ListPopulator { static async populateList(list) { const listTypeToUrlMapper = { [List.types.DENY_LIST]: BAD_URLS, + [List.types.ALLOW_LIST]: GOOD_URLS, }; const urls = listTypeToUrlMapper[list.type]; list.bulkAdd(urls); - - //TODO https://github.com/lfilho/ddg-test-project/issues/8 } } diff --git a/src/lib/model/allow_list.js b/src/lib/model/allow_list.js new file mode 100644 index 0000000..25830b6 --- /dev/null +++ b/src/lib/model/allow_list.js @@ -0,0 +1,7 @@ +import List from './list.js'; + +export default class AllowList extends List { + constructor() { + super(List.types.ALLOW_LIST); + } +} diff --git a/src/lib/request_matcher.js b/src/lib/request_matcher.js index eb47375..98317a7 100644 --- a/src/lib/request_matcher.js +++ b/src/lib/request_matcher.js @@ -1,9 +1,21 @@ +import AllowList from './model/allow_list.js'; import DenyList from './model/deny_list.js'; import ListPopulator from './list_populator.js'; -let denyList; +// Singletons. +// Meaning since the extension will run on background, +// we will only load those lists once, saving memory +let denyList, allowList; export default class RequestMatcher { + static get allowList() { + if (!allowList) { + allowList = new AllowList(); + ListPopulator.populateList(allowList); + } + return allowList; + } + static get denyList() { if (!denyList) { denyList = new DenyList(); @@ -13,6 +25,11 @@ export default class RequestMatcher { } static isDenied(url) { + // Allow list implies a user's deliberate action to allow that url + // Hence the precedence below + if (this.allowList.has(url)) { + return false; + } return this.denyList.has(url); } } diff --git a/src/shared/__url_fixtures.js b/src/shared/__url_fixtures.js index 49073d7..4c71a9f 100644 --- a/src/shared/__url_fixtures.js +++ b/src/shared/__url_fixtures.js @@ -1,8 +1,8 @@ const A_URL = 'https://example.com'; const GOOD_URL = 'https://duckduckgo.com'; const BAD_URL = 'https://evil-tracker.com'; -const ANOTHER_URL = GOOD_URL; -const SOME_URLS = [A_URL, ANOTHER_URL, BAD_URL]; +const URL_IN_NO_LISTS = 'https://duck.co'; +const SOME_URLS = [A_URL, URL_IN_NO_LISTS, BAD_URL]; const TEST_PAGE_GOOD_URL = 'https://itty.bitty.site/#good_page/data:text/html;charset=utf-8;bxze64,XQAAAALrAQAAAAAAAAAeGInmWR9D5qtrM4PFJv4W1okR98bzFbE2QlIiIqEKRNhWozLGaVxy2UBVi6vb5PjLiS+KmhnoBI2zbVEi38FFqGt0V2dZ/n48NtEOjSTkOFXBuNLAKC6rlcwmvnHnUnMAWA2l/QImsEbNvvf1bv40vbtBzNp9F3TGp/HpcdlmwUSp59tjbjdUlRkOVnMxBaTPI6tnqjg9UBREwBH6Y4c6xLg53hJodPJyK8AysLdOEqC5OPFdGrHq7n6ViwKq90juHDM+UhFD8ug4iSu0Yo74yBMAo7Rtj+Jd5h9AkkjDCs/m4RMIP7KQKT4AldOuVvxaNDd4LcfbH/7lFxzMpv2FPyYxeR5ZmDMwE6422v7jh2OnV4nTcu42kWkhVBP7U06PxG1bBjmd5+5p11z/jK399tAktg=='; const TEST_PAGE_BAD_URL = @@ -14,7 +14,7 @@ export { A_URL, GOOD_URL, BAD_URL, - ANOTHER_URL, + URL_IN_NO_LISTS, SOME_URLS, TEST_PAGE_BAD_URL, TEST_PAGE_GOOD_URL,