diff --git a/README.md b/README.md index 9c3cfd8..832f28a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Built atop the excellent project [xiMatrix](https://github.com/xi/xiMatrix) by T ## Why use xiMatrix as a basis instead of uMatrix? -xiMatrix is simpler with a smaller codebase and is therefore more suitable to hack upon. It is already built in the spririt of 'do one thing and do it well' and implements some of the features I would have liked to see added to uMatrix. uMatrix covers things which may be considered outside the scope of a web request firewall such as spoofing values and managing local storage. +xiMatrix is simpler with a smaller codebase and is therefore more suitable to hack upon. It is already built in the spirit of 'do one thing and do it well' and implements some of the features I would have liked to see added to uMatrix. uMatrix covers things which may be considered outside the scope of a web request firewall such as spoofing values and managing local storage. ## Why not just contribute to xi's xiMatrix? @@ -34,7 +34,6 @@ He has clearly stated in his project that it is a personal tool and will not lik ## TO DO -- Add column for blocking cookies. Cookie blocking is not as simple as other requests, as it necessitates accepting site cookies (but *not returning* them) when they are blocked. - Display enumerated requests blocked in icon. - Placeholder element for blocked images/video. - Update in-place while keeping paraMatrix popup open. diff --git a/screenshot.png b/screenshot.png index b49b420..649491c 100644 Binary files a/screenshot.png and b/screenshot.png differ diff --git a/src/bg.js b/src/bg.js index 2a18bca..76e00cc 100644 --- a/src/bg.js +++ b/src/bg.js @@ -148,6 +148,11 @@ browser.runtime.onMessage.addListener((msg, sender) => { } return savedRules; })); + } else if (msg.type === 'reset') { + return storageChange('rules', rules => { + delete rules[msg.data]; + return rules; + }); } else if (msg.type === 'securitypolicyviolation') { return pushRequest(sender.tab.id, 'inline', msg.data); } else if (msg.type === 'toggleRecording') { @@ -162,12 +167,8 @@ browser.webNavigation.onBeforeNavigate.addListener(details => { } }); -browser.webRequest.onBeforeRequest.addListener(details => { - if (details.type === 'main_frame') { - return; - } - - var context = getHostname(details.documentUrl); +browser.webRequest.onBeforeSendHeaders.addListener(details => { + var context = getHostname(details.documentUrl || details.url); if (details.frameAncestors.length) { var last = details.frameAncestors.length - 1; context = getHostname(details.frameAncestors[last].url); @@ -175,11 +176,21 @@ browser.webRequest.onBeforeRequest.addListener(details => { var hostname = getHostname(details.url); var type = shared.TYPE_MAP[details.type] || 'other'; + let isCookie = h => h.name.toLowerCase() === 'cookie'; + var cookiePromise = Promise.resolve(); + if (details.requestHeaders.some(isCookie)) { + cookiePromise = pushRequest(details.tabId, hostname, 'cookie'); + } + return Promise.all([ pushRequest(details.tabId, hostname, type), + cookiePromise, getRules(context), - ]).then(([_, rules]) => { - if (!shared.shouldAllow(rules, context, hostname, type)) { + ]).then(([_, _2, rules]) => { + if ( + details.type !== 'main_frame' + && !shared.shouldAllow(rules, context, hostname, type) + ) { if (details.type === 'sub_frame') { // this can in turn be blocked by a local CSP return {redirectUrl: 'data:,' + encodeURIComponent(details.url)}; @@ -187,10 +198,17 @@ browser.webRequest.onBeforeRequest.addListener(details => { return {cancel: true}; } } - }); -}, {urls: ['']}, ['blocking']); -browser.webRequest.onHeadersReceived.addListener(function(details) { + if (shared.shouldAllow(rules, context, hostname, 'cookie')) { + return {requestHeaders: details.requestHeaders}; + } else { + var filtered = details.requestHeaders.filter(h => !isCookie(h)); + return {requestHeaders: filtered}; + } + }); +}, {urls: ['']}, ['blocking', 'requestHeaders']); + +browser.webRequest.onHeadersReceived.addListener(details => { var context = getHostname(details.url); return Promise.all([ getRules(context), @@ -215,9 +233,7 @@ browser.webRequest.onHeadersReceived.addListener(function(details) { csp('script', "script-src 'self' *"); csp('media', "img-src 'self' *"); - return { - responseHeaders: details.responseHeaders, - }; + return {responseHeaders: details.responseHeaders}; }); }, { urls: [''], diff --git a/src/popup.css b/src/popup.css index b25549f..a52ff8d 100644 --- a/src/popup.css +++ b/src/popup.css @@ -18,12 +18,12 @@ table { background: var(--orange-light); border-spacing: 0; - margin-bottom: 0.2em; + margin-block-end: 0.2em; } th, td { position: relative; border: 1px solid #1f2042; - min-width: 3.4em; + min-inline-size: 3.4em; line-height: 1.8; text-align: center; font-weight: normal; diff --git a/src/popup.html b/src/popup.html index 117ad50..91f2c61 100644 --- a/src/popup.html +++ b/src/popup.html @@ -1,5 +1,5 @@ - + @@ -12,6 +12,7 @@ recording + diff --git a/src/popup.js b/src/popup.js index 96bba3d..85cb78f 100644 --- a/src/popup.js +++ b/src/popup.js @@ -7,6 +7,7 @@ var rules; var table = document.querySelector('table'); var recording = document.querySelector('[name="recording"]') var commitButton = document.querySelector('[name="commit"]'); +var resetButton = document.querySelector('[name="reset"]'); var reloadButton = document.querySelector('[name="reload"]'); var sendMessage = function(type, data) { @@ -84,6 +85,7 @@ var createCheckbox = function(hostname, type) { }).then(newRules => { rules = newRules; commitButton.disabled = !rules.dirty; + resetButton.disabled = !rules.dirty; reloadButton.disabled = !rules.dirty; updateInherit(type); }); @@ -134,12 +136,13 @@ var createRow = function(hostname) { }; var loadContext = function() { - sendMessage('get').then(data => { + return sendMessage('get').then(data => { context = data.context; requests = data.requests; rules = data.rules; recording.checked = data.recording; commitButton.disabled = !rules.dirty; + resetButton.disabled = !rules.dirty; table.innerHTML = ''; table.append(createHeader()); @@ -175,5 +178,11 @@ reloadButton.addEventListener('click', event => { commitButton.addEventListener('click', event => { sendMessage('commit', context).then(() => { commitButton.disabled = true; + resetButton.disabled = true; + reloadButton.disabled= true; }); }); + +resetButton.addEventListener('click', event => { + sendMessage('reset', context).then(loadContext); +}); diff --git a/src/settings.css b/src/settings.css index e24c787..f243bc7 100644 --- a/src/settings.css +++ b/src/settings.css @@ -9,7 +9,7 @@ body { } form { - height: 100vh; + block-size: 100vb; display: grid; grid-template-rows: 1fr min-content; grid-template-columns: 1fr 1fr; @@ -17,13 +17,19 @@ form { padding: 0.5em; } +label { + display: flex; + flex-direction: column; +} + textarea { - width: 100%; + block-size: 100%; resize: none; } button { - padding: 0.5em 2em; + padding-block: 0.5em; + padding-inline: 2em; justify-self: end; grid-column: 1 / 3; } diff --git a/src/settings.html b/src/settings.html index fe1a854..d41a1af 100644 --- a/src/settings.html +++ b/src/settings.html @@ -1,5 +1,5 @@ - + @@ -7,8 +7,14 @@
- - + +
diff --git a/src/shared.js b/src/shared.js index 5bc8012..55249e4 100644 --- a/src/shared.js +++ b/src/shared.js @@ -1,6 +1,6 @@ var shared = {}; -shared.TYPES = ['font', 'css', 'image', 'media', 'script', 'xhr', 'frame', 'other']; +shared.TYPES = ['cookie', 'font', 'css', 'image', 'media', 'script', 'xhr', 'frame', 'other']; shared.TYPE_MAP = { 'stylesheet': 'css', 'font': 'font',