-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: working version with deny list
* chore: tune jest to work with ESM * feat(request-matcher): basic matching and unit tests * feat: requests blocking (wip - missing unit tests) * chore: add html test pages * feat(List): new List data structure Closes #40 * refactor(request_matcher): use the new List instead * refactor: extract requestListener to its own file * test: add playwright and intial e2e test * refactor: move url fixtures to shared folder * refactor:fix * docs: add draft testing doc * tests: pause work on automated functional tests for now * feat: add model folder and DenyList model * feat: add ListPopulator to prepoluate lists * tests: use itty.bitty.site for https * feat: add error listener to webRequest * tests: silence window.alert's :) * refactor: url fixtures export style * refactor: share url fixtures with src/shared * refactor: make bin script executable * refactor: require a type when constructing a List * refactor: list_populator * refactor: update test pages html
- Loading branch information
Showing
21 changed files
with
403 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
//TODO work in this file is paused/block. | ||
// More details and follow up on: https://github.com/lfilho/sample-webextension/issues/38 | ||
|
||
/* | ||
import browserWrapper from 'playwright-firefox'; | ||
import child_process from 'child_process'; | ||
import webExt from 'web-ext'; | ||
import pptr from 'puppeteer-core'; | ||
import { LOCAL_TEST_PAGE_URL } from '../shared/__url_fixtures.js'; | ||
*/ | ||
let page; | ||
/* | ||
let browser; | ||
beforeAll(async () => { | ||
webExt.default.util.logger.consoleStream.makeVerbose(); | ||
const runningInfo = await webExt.default.cmd | ||
.run( | ||
{ | ||
sourceDir: `${process.cwd()}/src`, | ||
firefox: 'nightly' | ||
}, | ||
{ shouldExitProgram: false } | ||
) | ||
.then((runner) => runner.extensionRunners[0].runningInfo); | ||
// Needed because `webExt.cmd.run` returns before the DevTools agent starts running. | ||
// Alternative would be to wrap the call to pptr.connect() with some custom retry logic | ||
child_process.execSync('sleep 5'); | ||
const browserURL = `ws://127.0.0.1:${runningInfo.debuggerPort}`; | ||
browser = await browserWrapper.firefox.connect({ | ||
wsEndpoint: browserURL, | ||
logger: { | ||
isEnabled: () => true, | ||
log: (name, severity, message, args) => { | ||
console.log(`[${severity}] ${name} ${message}. Args: ${args}`); | ||
}, | ||
}, | ||
}); | ||
const context = await browser.newContext(); | ||
page = await context.newPage(); | ||
await page.goto(LOCAL_TEST_PAGE_URL); | ||
}); | ||
afterAll(async () => { | ||
await browser.close(); | ||
}); | ||
*/ | ||
|
||
describe('request to known tracker urls should be blocked', () => { | ||
it.skip('loads the test page', async () => { | ||
const text = await page.evaluate(() => { | ||
return document.querySelector('[data-testid="test-page-header"]'); | ||
}); | ||
expect(text).toBeTruthy(); | ||
}); | ||
|
||
it.skip('blocks a known bad url by not loading its iframe', async () => { | ||
//TODO waiting on resolution for: https://github.com/mozilla/web-ext/issues/1927 | ||
// More details and follow up on: https://github.com/lfilho/sample-webextension/issues/38 | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
|
||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width" /> | ||
<title>Test page</title> | ||
<style type="text/css"> | ||
body { | ||
padding: 2rem; | ||
} | ||
|
||
#bad-page-iframe, | ||
#good-page-iframe { | ||
display: block; | ||
width: 100%; | ||
height: 13rem; | ||
border: 0.2rem solid transparent; | ||
} | ||
|
||
#bad-page-iframe { | ||
border-color: red; | ||
} | ||
|
||
#good-page-iframe { | ||
border-color: green; | ||
} | ||
</style> | ||
</head> | ||
|
||
<body> | ||
<h1 data-testid="test-page-header">✅ Test page</h1> | ||
|
||
<h2>Bad page iframe (should be blank):</h2> | ||
<iframe id="bad-page-iframe" | ||
src="https://itty.bitty.site/#bad_page/data:text/html;charset=utf-8;bxze64,XQAAAAI1AgAAAAAAAAAeGInmWR9D5qtrM4PFJv4W1okR98bzFbE2QlIWuIKxrmOKcpOUCz+bgN13tm1YwI65ckLaaMk97I0eK4ZJmz5rEyi5AYIrCihWPyWsU8imdwCjsAu9mVY4Uz3NDJSwS2tBy4fpBWIzlJM+PEIF1Dz7uHdB5dd0JkIYoHoNI51/xPcOHjaLtkdq929hapYOYARvUkxhKCAYZqoeWl/azB+/iRrItZhXoN2Xhb7cEouQ4ySG85i7cH0nZAJxZezxYYPzjYOKj1QECrYU2ufsndUGql9zsUXyBzVv3UCYzraVIpXLzEWabESPgYK1HY3biPhAiXzCU1i3msUdqKm0jl/HwqnVgJjhKaCsQvuv8pyy+VVkaz/XPVibLpmrbELCVUdG/jgKW2ig1pqjIAIoFb7YROo5+5026HlBBKlBJSJtJPiB5wAAbZMivZGwt72qmdA5R4jjQVr+djo2" | ||
frameborder="0"></iframe> | ||
|
||
<h2>Good page iframe (should not be blank):</h2> | ||
<iframe id="good-page-iframe" | ||
src="https://itty.bitty.site/#good_page/data:text/html;charset=utf-8;bxze64,XQAAAALrAQAAAAAAAAAeGInmWR9D5qtrM4PFJv4W1okR98bzFbE2QlIiIqEKRNhWozLGaVxy2UBVi6vb5PjLiS+KmhnoBI2zbVEi38FFqGt0V2dZ/n48NtEOjSTkOFXBuNLAKC6rlcwmvnHnUnMAWA2l/QImsEbNvvf1bv40vbtBzNp9F3TGp/HpcdlmwUSp59tjbjdUlRkOVnMxBaTPI6tnqjg9UBREwBH6Y4c6xLg53hJodPJyK8AysLdOEqC5OPFdGrHq7n6ViwKq90juHDM+UhFD8ug4iSu0Yo74yBMAo7Rtj+Jd5h9AkkjDCs/m4RMIP7KQKT4AldOuVvxaNDd4LcfbH/7lFxzMpv2FPyYxeR5ZmDMwE6422v7jh2OnV4nTcu42kWkhVBP7U06PxG1bBjmd5+5p11z/jK399tAktg==" | ||
frameborder="0"></iframe> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { A_URL } from '../../../src/shared/__url_fixtures.js'; | ||
|
||
export const RANDOM_REQUEST_DETAILS = { url: A_URL }; | ||
export const BLOCKING_RESPONSE = { | ||
CANCELLED: { cancel: true }, | ||
NOT_CANCELLED: { cancel: false }, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import List from '../../../src/lib/model/list.js'; | ||
import { | ||
A_URL, | ||
ANOTHER_URL, | ||
SOME_URLS, | ||
} from '../../../src/shared/__url_fixtures.js'; | ||
|
||
let list; | ||
|
||
beforeEach(() => { | ||
const RANDOM_TYPE = List.types.DENY_LIST; | ||
list = new List(RANDOM_TYPE); | ||
}); | ||
|
||
describe('List', () => { | ||
it('should add an url to the list', () => { | ||
const originalListSize = list.size; | ||
list.add(A_URL); | ||
expect(list.size).toBe(originalListSize + 1); | ||
}); | ||
|
||
it('should not add duplicate urls to the list', () => { | ||
const originalListSize = list.size; | ||
list.add(A_URL); | ||
list.add(A_URL); | ||
expect(list.size).toBe(originalListSize + 1); | ||
}); | ||
|
||
it('should remove an url from the list', () => { | ||
const originalListSize = list.size; | ||
list.add(A_URL); | ||
list.remove(A_URL); | ||
expect(list.size).toBe(originalListSize); | ||
}); | ||
|
||
it('should tell if an url is on the list', () => { | ||
list.add(A_URL); | ||
expect(list.has(A_URL)).toBe(true); | ||
expect(list.has(ANOTHER_URL)).toBe(false); | ||
}); | ||
|
||
it('should clear the list', () => { | ||
list.add(A_URL); | ||
list.add(ANOTHER_URL); | ||
list.clear(); | ||
expect(list.size).toBe(0); | ||
}); | ||
|
||
it('should return the size of the list', () => { | ||
expect(list.size).toBe(0); | ||
list.add(A_URL); | ||
expect(list.size).toBe(1); | ||
list.add(ANOTHER_URL); | ||
expect(list.size).toBe(2); | ||
}); | ||
|
||
it('should add several urls at once', () => { | ||
expect(list.size).toBe(0); | ||
list.bulkAdd(SOME_URLS); | ||
expect(list.size).toBe(SOME_URLS.length); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { jest } from '@jest/globals'; | ||
|
||
import requestListener from '../../../src/lib/request_listener.js'; | ||
import RequestMatcher from '../../../src/lib/request_matcher.js'; | ||
|
||
import { | ||
RANDOM_REQUEST_DETAILS, | ||
BLOCKING_RESPONSE, | ||
} from './__request_fixtures.js'; | ||
|
||
jest.mock('../../../src/lib/request_matcher.js'); | ||
|
||
describe('Request Listener', () => { | ||
it('should return a BlockingResponse with cancel: true for a tracker url', () => { | ||
RequestMatcher.isDenied = jest.fn().mockReturnValue(true); | ||
const result = requestListener(RANDOM_REQUEST_DETAILS); | ||
expect(result).toEqual(BLOCKING_RESPONSE.CANCELLED); | ||
}); | ||
|
||
it('should return a BlockingResponse with cancel: false for a non-tracker url', () => { | ||
RequestMatcher.isDenied = jest.fn().mockReturnValue(false); | ||
const result = requestListener(RANDOM_REQUEST_DETAILS); | ||
expect(result).toEqual(BLOCKING_RESPONSE.NOT_CANCELLED); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import RequestMatcher from '../../../src/lib/request_matcher.js'; | ||
import { BAD_URL, GOOD_URL } from '../../../src/shared/__url_fixtures.js'; | ||
|
||
beforeAll(() => RequestMatcher.denyList.add(BAD_URL)); | ||
afterAll(() => RequestMatcher.denyList.clear()); | ||
|
||
describe('Request Matcher', () => { | ||
it('should deny urls in the deny list', () => { | ||
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(GOOD_URL); | ||
expect(result).toBe(false); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
#!/usr/bin/env node | ||
|
||
import fs from 'fs'; | ||
|
||
const MANITFEST_FILE = 'src/manifest.json'; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width" /> | ||
</head> | ||
<body> | ||
<script type="module" src="./background_script.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
console.log('This is coming from background script!'); | ||
import RequestBlocker from './lib/request_blocker.js'; | ||
|
||
console.log('Extension is ready to start blocking!'); | ||
RequestBlocker.startMonitoring(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
window.alert('This is coming from the extension button!'); | ||
console.info('This is coming from the extension button!'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
window.alert('This is comming from content script!'); | ||
console.info('This is comming from content script!'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import List from './model/list.js'; | ||
import { BAD_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... | ||
// https://github.com/lfilho/sample-webextension/issues/24 | ||
// https://github.com/lfilho/sample-webextension/issues/18 | ||
// https://github.com/lfilho/sample-webextension/issues/17 | ||
|
||
export default class ListPopulator { | ||
static async populateList(list) { | ||
const listTypeToUrlMapper = { | ||
[List.types.DENY_LIST]: BAD_URLS, | ||
}; | ||
const urls = listTypeToUrlMapper[list.type]; | ||
list.bulkAdd(urls); | ||
|
||
//TODO https://github.com/lfilho/sample-webextension/issues/8 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import List from './list.js'; | ||
|
||
export default class DenyList extends List { | ||
constructor() { | ||
super(List.types.DENY_LIST); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
export default class List { | ||
/* | ||
* Using a Set and mainly proxying the methods to their native ones. | ||
* So if we change the underlaying data structure in the future, | ||
* the API stays the same and the impact on the codebase is minimal. | ||
*/ | ||
|
||
constructor(type) { | ||
if (!type) { | ||
throw new Error('List constructor needs a type'); | ||
//TODO Refactor Error strategy later on to contain an unique error code and both technical and user friendly messages | ||
} | ||
this.list = new Set(); | ||
this.type = type; | ||
} | ||
|
||
static get types() { | ||
return Object.freeze({ | ||
DENY_LIST: 'DENY', | ||
ALLOW_LIST: 'ALLOW', | ||
}); | ||
} | ||
|
||
has(url) { | ||
// Look kid, one day there will be a complex algorithm here. | ||
// For now, full matches only. In future iterations, | ||
// we should support some sort of pattern instead: *evil-tracker.com/* | ||
return this.list.has(url); | ||
} | ||
|
||
add(url) { | ||
this.list.add(url); | ||
} | ||
|
||
remove(url) { | ||
this.list.delete(url); | ||
} | ||
|
||
clear() { | ||
this.list.clear(); | ||
} | ||
|
||
get size() { | ||
return this.list.size; | ||
} | ||
|
||
bulkAdd(values) { | ||
values.forEach(this.list.add.bind(this.list)); | ||
} | ||
} |
Oops, something went wrong.