supports sibling hostnames. fixes #93

This commit is contained in:
Ray Lothian 2020-09-06 09:36:28 +02:00
parent b9721d4580
commit 486629ad0c
4 changed files with 90 additions and 5 deletions

View file

@ -22,6 +22,10 @@ const prefs = {
blacklist: [], blacklist: [],
whitelist: [], whitelist: [],
custom: {}, custom: {},
siblings: {
'www.google.com': 0,
'www.youtube.com': 0
}, // a list of domains that are considered siblings (use same index for all)
mode: 'blacklist', mode: 'blacklist',
color: '#777', color: '#777',
cache: true, cache: true,
@ -34,7 +38,7 @@ window.prefs = prefs; // access from popup
const log = (...args) => prefs.log && console.log(...args); const log = (...args) => prefs.log && console.log(...args);
// exand comma-separated keys of prefs.custom // expand comma-separated keys of prefs.custom and add missing keys
const expand = () => { const expand = () => {
log('expanding custom rules'); log('expanding custom rules');
expand.rules = {}; expand.rules = {};
@ -42,6 +46,25 @@ const expand = () => {
for (const k of key.split(/\s*,\s*/)) { for (const k of key.split(/\s*,\s*/)) {
if (k) { if (k) {
expand.rules[k] = prefs.custom[key]; expand.rules[k] = prefs.custom[key];
// make sure all siblings have the same expanded rule
const i = prefs.siblings[key];
if (i !== undefined) {
for (const [hostname, j] of Object.entries(prefs.siblings)) {
if (i === j) {
expand.rules[hostname] = expand.rules[hostname] || prefs.custom[key];
if (expand.rules._) {
const x = expand.rules._.indexOf(key);
const y = expand.rules._.indexOf(hostname);
if (x !== -1 && y === -1) {
expand.rules._.push(hostname);
}
if (x === -1 && y !== -1) {
expand.rules._.push(key);
}
}
}
}
}
} }
} }
} }
@ -373,7 +396,20 @@ function match({url, tabId, cookieStoreId = DCSI}) {
return s.endsWith('.' + h) || h.endsWith('.' + s) || s.endsWith('.' + hh) || hh.endsWith('.' + s); return s.endsWith('.' + h) || h.endsWith('.' + s) || s.endsWith('.' + hh) || hh.endsWith('.' + s);
} }
}).shift(); }).shift();
let s = expand.rules[key] || expand.rules['*']; let s;
// try to use an already resolved sibling hostname
const i = prefs.siblings[key];
if (i !== undefined) {
for (const [hostname, j] of Object.entries(prefs.siblings)) {
if (j === i && expand.rules[hostname] && typeof expand.rules[hostname] === 'string') {
s = expand.rules[hostname];
}
}
}
s = s || expand.rules[key];
// use '*' when the hostname specific key is not found
s = s || expand.rules['*'];
console.log(s);
// if s is an array select a random string // if s is an array select a random string
if (Array.isArray(s)) { if (Array.isArray(s)) {
s = s[Math.floor(Math.random() * s.length)]; s = s[Math.floor(Math.random() * s.length)];
@ -418,7 +454,7 @@ const onBeforeSendHeaders = d => {
} }
const o = (cache[tabId] || ua.object(tabId, undefined, cookieStoreId)); const o = (cache[tabId] || ua.object(tabId, undefined, cookieStoreId));
const str = o ? o.userAgent : ''; const str = o ? o.userAgent : '';
if (str) { if (str && requestHeaders.length) {
for (let i = 0, name = requestHeaders[0].name; i < requestHeaders.length; i += 1, name = (requestHeaders[i] || {}).name) { for (let i = 0, name = requestHeaders[0].name; i < requestHeaders.length; i += 1, name = (requestHeaders[i] || {}).name) {
if (name === 'User-Agent' || name === 'user-agent') { if (name === 'User-Agent' || name === 'user-agent') {
requestHeaders[i].value = str === 'empty' ? '' : str; requestHeaders[i].value = str === 'empty' ? '' : str;

View file

@ -52,6 +52,7 @@ textarea {
.mode-2 { .mode-2 {
grid-template-columns: min-content min-content; grid-template-columns: min-content min-content;
} }
#toggle-sibling-desc,
#toggle-parser-desc, #toggle-parser-desc,
#toggle-protected-desc, #toggle-protected-desc,
#toggle-custom-desc, #toggle-custom-desc,

View file

@ -29,7 +29,7 @@
<span id="toggle-custom-desc">Description</span> <span id="toggle-custom-desc">Description</span>
</div> </div>
<p for="toggle-custom-desc" class="note hidden">Try to resolve the user-agent string from a JSON object; otherwise either use the default user-agent string or use the one that the user is set from the popup interface. Use "*" as the hostname to match all domains. You can randomly select from multiple user-agent strings by providing an array instead of a fixed string. If there is a "_" key in your JSON object which refers to an array of hostnames, then the extension only randomly selects the user-agent string once for each hostname inside this list. This is useful if you don't want the random user-agent to change until this browser session is over.</label> Press <a href="#" id="sample">here</a> to insert a sample JSON object.</p> <p for="toggle-custom-desc" class="note hidden">Try to resolve the user-agent string from a JSON object; otherwise either use the default user-agent string or use the one that the user is set from the popup interface. Use "*" as the hostname to match all domains. You can randomly select from multiple user-agent strings by providing an array instead of a fixed string. If there is a "_" key in your JSON object which refers to an array of hostnames, then the extension only randomly selects the user-agent string once for each hostname inside this list. This is useful if you don't want the random user-agent to change until this browser session is over.</label> Press <a href="#" id="sample">here</a> to insert a sample JSON object.</p>
<textarea id="custom" rows="5" wrap="off"></textarea> <textarea id="custom" rows="8" wrap="off"></textarea>
<div class="checked"> <div class="checked">
<input type="checkbox" id="cache"> <input type="checkbox" id="cache">
@ -56,6 +56,13 @@
<p for="toggle-parser-desc" class="note hidden">A JSON object to bypass the internal user-agent string parsing method. The keys are the actual user-agent strings and the value of each key is an object of the keys that need to be set for the "navigator" object. You can use the "[delete]" keyword if you want a key in the "navigator" object to get deleted. Press <a href="#" id="sample-2">here</a> to insert a sample JSON object.</p> <p for="toggle-parser-desc" class="note hidden">A JSON object to bypass the internal user-agent string parsing method. The keys are the actual user-agent strings and the value of each key is an object of the keys that need to be set for the "navigator" object. You can use the "[delete]" keyword if you want a key in the "navigator" object to get deleted. Press <a href="#" id="sample-2">here</a> to insert a sample JSON object.</p>
<textarea id="parser" rows="5" wrap="off"></textarea> <textarea id="parser" rows="5" wrap="off"></textarea>
<div class="mode-2">
<h1>Sibling Hostnames</h1>
<span id="toggle-sibling-desc">Description</span>
</div>
<p for="toggle-sibling-desc" class="note hidden">A JSON array that contains one or more groups of hostnames to have a single user-agent string per group for the "Custom Mode". For all hostnames in one group, the user-agent string calculation only occurs once, and all the other members use the same calculated string. This is useful to make sure a group of connected websites only access to the same user-agent string. Press <a href="#" id="sample-3">here</a> to insert a sample JSON array.</p>
<textarea id="siblings" rows="5" wrap="off"></textarea>
<div id="backup"> <div id="backup">
<button id="import">Import Settings</button> <button id="import">Import Settings</button>
<button id="export">Export Settings</button> <button id="export">Export Settings</button>

View file

@ -36,10 +36,28 @@ function save() {
catch (e) { catch (e) {
window.setTimeout(() => { window.setTimeout(() => {
notify('Parser JSON error: ' + e.message, 5000); notify('Parser JSON error: ' + e.message, 5000);
document.getElementById('parser').value = c; document.getElementById('parser').value = p;
}, 1000); }, 1000);
} }
let siblings = {};
const s = document.getElementById('siblings').value;
try {
siblings = JSON.parse(s);
siblings = siblings.reduce((p, c, i) => {
c.forEach(hostname => p[hostname] = i);
return p;
}, {});
}
catch (e) {
window.setTimeout(() => {
notify('Sibling JSON error: ' + e.message, 5000);
document.getElementById('siblings').value = c;
}, 1000);
}
console.log(siblings);
chrome.storage.local.set({ chrome.storage.local.set({
exactMatch: document.getElementById('exactMatch').checked, exactMatch: document.getElementById('exactMatch').checked,
faqs: document.getElementById('faqs').checked, faqs: document.getElementById('faqs').checked,
@ -49,6 +67,7 @@ function save() {
whitelist: prepare(document.getElementById('whitelist').value), whitelist: prepare(document.getElementById('whitelist').value),
custom, custom,
parser, parser,
siblings,
mode: document.querySelector('[name="mode"]:checked').value, mode: document.querySelector('[name="mode"]:checked').value,
protected: document.getElementById('protected').value.split(/\s*,\s*/).filter(s => s.length > 4) protected: document.getElementById('protected').value.split(/\s*,\s*/).filter(s => s.length > 4)
}, () => { }, () => {
@ -71,6 +90,10 @@ function restore() {
blacklist: [], blacklist: [],
custom: {}, custom: {},
parser: {}, parser: {},
siblings: {
'www.google.com': 0,
'www.youtube.com': 0
},
protected: ['google.com/recaptcha', 'gstatic.com/recaptcha'] protected: ['google.com/recaptcha', 'gstatic.com/recaptcha']
}, prefs => { }, prefs => {
document.getElementById('exactMatch').checked = prefs.exactMatch; document.getElementById('exactMatch').checked = prefs.exactMatch;
@ -82,6 +105,11 @@ function restore() {
document.getElementById('whitelist').value = prefs.whitelist.join(', '); document.getElementById('whitelist').value = prefs.whitelist.join(', ');
document.getElementById('custom').value = JSON.stringify(prefs.custom, null, 2); document.getElementById('custom').value = JSON.stringify(prefs.custom, null, 2);
document.getElementById('parser').value = JSON.stringify(prefs.parser, null, 2); document.getElementById('parser').value = JSON.stringify(prefs.parser, null, 2);
document.getElementById('siblings').value = JSON.stringify(Object.entries(prefs.siblings).reduce((p, [hostname, index]) => {
p[index] = p[index] || [];
p[index].push(hostname);
return p;
}, []), null, 2);
document.getElementById('protected').value = prefs.protected.join(', '); document.getElementById('protected').value = prefs.protected.join(', ');
}); });
} }
@ -114,6 +142,16 @@ document.getElementById('sample-2').addEventListener('click', e => {
}, null, 2); }, null, 2);
}); });
document.getElementById('sample-3').addEventListener('click', e => {
e.preventDefault();
document.getElementById('siblings').value = JSON.stringify([[
'www.google.com', 'www.youtube.com', 'www.youtube.be'
], [
'www.gmx.com', 'www.mail.com'
]], null, 2);
});
document.getElementById('donate').addEventListener('click', () => { document.getElementById('donate').addEventListener('click', () => {
chrome.tabs.create({ chrome.tabs.create({
url: chrome.runtime.getManifest().homepage_url + '?rd=donate' url: chrome.runtime.getManifest().homepage_url + '?rd=donate'
@ -205,3 +243,6 @@ document.getElementById('toggle-protected-desc').addEventListener('click', () =>
document.getElementById('toggle-parser-desc').addEventListener('click', () => { document.getElementById('toggle-parser-desc').addEventListener('click', () => {
document.querySelector('[for="toggle-parser-desc"]').classList.toggle('hidden'); document.querySelector('[for="toggle-parser-desc"]').classList.toggle('hidden');
}); });
document.getElementById('toggle-sibling-desc').addEventListener('click', () => {
document.querySelector('[for="toggle-sibling-desc"]').classList.toggle('hidden');
});