version 0.3.3
This commit is contained in:
parent
b99fd158bb
commit
b866177b86
9 changed files with 59 additions and 26 deletions
|
@ -1,2 +1,2 @@
|
|||
ua-parser.min.js:
|
||||
https://github.com/faisalman/ua-parser-js/releases/tag/0.7.19
|
||||
https://github.com/faisalman/ua-parser-js/releases/tag/0.7.20
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
|
||||
const cache = {};
|
||||
const tabs = {};
|
||||
chrome.tabs.onRemoved.addListener(id => delete cache[id]);
|
||||
|
@ -17,10 +18,15 @@ const prefs = {
|
|||
cache: true,
|
||||
exactMatch: false,
|
||||
protected: ['google.com/recaptcha', 'gstatic.com/recaptcha'],
|
||||
parser: {} // maps ua string to a ua object
|
||||
parser: {}, // maps ua string to a ua object,
|
||||
log: false
|
||||
};
|
||||
|
||||
const log = (...args) => prefs.log && console.log(...args);
|
||||
|
||||
// exand comma-separated keys of prefs.custom
|
||||
const expand = () => {
|
||||
log('expanding custom rules');
|
||||
expand.rules = {};
|
||||
for (const key of Object.keys(prefs.custom)) {
|
||||
for (const k of key.split(/\s*,\s*/)) {
|
||||
|
@ -82,14 +88,18 @@ const ua = {
|
|||
'global': {}
|
||||
},
|
||||
diff(tabId) { // returns true if there is per window object
|
||||
log('ua.diff is called', tabId);
|
||||
const windowId = tabs[tabId];
|
||||
return windowId in this._obj;
|
||||
},
|
||||
get windows() {
|
||||
log('ua.windows is called');
|
||||
return Object.keys(this._obj).filter(id => id !== 'global').map(s => Number(s));
|
||||
},
|
||||
parse: s => {
|
||||
log('ua.parse is called', s);
|
||||
if (prefs.parser[s]) {
|
||||
log('ua.parse is resolved using parser');
|
||||
return Object.assign({
|
||||
userAgent: s
|
||||
}, prefs.parser[s]);
|
||||
|
@ -140,10 +150,12 @@ const ua = {
|
|||
return o;
|
||||
},
|
||||
object(tabId, windowId) {
|
||||
log('ua.object is called', tabId, windowId);
|
||||
windowId = windowId || (tabId ? tabs[tabId] : 'global');
|
||||
return this._obj[windowId] || this._obj.global;
|
||||
},
|
||||
string(str, windowId) {
|
||||
log('ua.string is called', str, windowId);
|
||||
if (str) {
|
||||
this._obj[windowId] = this.parse(str);
|
||||
}
|
||||
|
@ -152,12 +164,14 @@ const ua = {
|
|||
}
|
||||
},
|
||||
tooltip(title, tabId) {
|
||||
log('ua.tooltip is called', title, tabId);
|
||||
chrome.browserAction.setTitle({
|
||||
title,
|
||||
tabId
|
||||
});
|
||||
},
|
||||
icon(mode, tabId) {
|
||||
log('ua.icon is called', mode, tabId);
|
||||
chrome.browserAction.setIcon({
|
||||
tabId,
|
||||
path: {
|
||||
|
@ -172,6 +186,7 @@ const ua = {
|
|||
});
|
||||
},
|
||||
toolbar: ({windowId, tabId}) => {
|
||||
log('ua.toolbar is called', windowId, tabId);
|
||||
if (windowId) {
|
||||
chrome.tabs.query({
|
||||
windowId
|
||||
|
@ -191,9 +206,13 @@ const ua = {
|
|||
}
|
||||
},
|
||||
update(str = prefs.ua, windowId = 'global') {
|
||||
log('ua.update is called', str, windowId);
|
||||
// clear caching
|
||||
Object.keys(cache).forEach(key => delete cache[key]);
|
||||
// remove old listeners
|
||||
chrome.webRequest.onBeforeSendHeaders.removeListener(onBeforeSendHeaders);
|
||||
chrome.webNavigation.onCommitted.removeListener(onCommitted);
|
||||
|
||||
// apply new ones
|
||||
if (str || prefs.mode === 'custom' || this.windows.length) {
|
||||
ua.string(str, windowId);
|
||||
chrome.webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {
|
||||
|
@ -224,6 +243,7 @@ if (chrome.windows) { // FF on Android
|
|||
}
|
||||
|
||||
function hostname(url) {
|
||||
log('hostname', url);
|
||||
const s = url.indexOf('//') + 2;
|
||||
if (s > 1) {
|
||||
let o = url.indexOf('/', s);
|
||||
|
@ -246,6 +266,7 @@ function hostname(url) {
|
|||
}
|
||||
// returns true, false or an object; true: ignore, false: use from ua object.
|
||||
function match({url, tabId}) {
|
||||
log('match', url, tabId);
|
||||
const h = hostname(url);
|
||||
|
||||
if (prefs.mode === 'blacklist') {
|
||||
|
@ -364,10 +385,16 @@ const onCommitted = ({frameId, url, tabId}) => {
|
|||
}\`;
|
||||
document.documentElement.appendChild(script);
|
||||
script.remove();
|
||||
navigator.userAgent
|
||||
}`
|
||||
}, () => {
|
||||
if (chrome.runtime.lastError) {
|
||||
}, r => {
|
||||
const lastError = chrome.runtime.lastError;
|
||||
if (lastError &&
|
||||
lastError.message !== 'No matching message handler' && // Firefox on Windows
|
||||
lastError.message !== 'document.documentElement is null' // Firefox on Windows
|
||||
) {
|
||||
if (frameId === 0) {
|
||||
console.log(lastError);
|
||||
ua.tooltip('[Default] ' + navigator.userAgent, tabId);
|
||||
ua.icon('ignored', tabId);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<table width=100%>
|
||||
<tr>
|
||||
<td>
|
||||
<label><input type="radio" name="mode" value="blacklist" id="mode-blacklist"> <span class="h">Black-list mode</span>: Apply the custom user-agent string to all tabs except the tabs with the following top-level hostnames (comma-separated list of hostnames). Note that even if a window-based user-agent string is set from the toolbar popup, your browser's default user-agent string is used.</label>
|
||||
<label><input type="radio" name="mode" value="blacklist" id="mode-blacklist"> <span class="h">Black-List Mode</span>: Apply the custom user-agent string to all tabs except the tabs with the following top-level hostnames (comma-separated list of hostnames). Note that even if a window-based user-agent string is set from the toolbar popup, your browser's default user-agent string is used.</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -32,7 +32,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label><input type="radio" name="mode" value="whitelist" id="mode-whitelist"> <span class="h">White-list mode</span>: Only apply the custom user-agent string to the tabs with following top-level hostnames. Note that if a window-based user-agent string is set from the toolbar popup, this user-agent will overwrite the global one.</label>
|
||||
<label><input type="radio" name="mode" value="whitelist" id="mode-whitelist"> <span class="h">White-List Mode</span>: Only apply the custom user-agent string to the tabs with following top-level hostnames. Note that if a window-based user-agent string is set from the toolbar popup, this user-agent will overwrite the global one.</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -40,20 +40,12 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label><input type="radio" name="mode" value="custom" id="mode-custom"> <span class="h">Custom mode</span>: 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.
|
||||
<label><input type="radio" name="mode" value="custom" id="mode-custom"> <span class="h">Custom Mode</span>: 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.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="spacer"><textarea id="custom" rows="5" wrap="off"></textarea></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label><span class="h">Custom user-agent string parsing</span>: 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.</label> Press <a href="#" id="sample-2">here</a> to insert a sample JSON object.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="spacer"><textarea id="parser" rows="5" wrap="off"></textarea></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="spacer"><label><input type="checkbox" id="cache"> Use caching to improve performance (recommended value is true). Uncheck this option only if you are using the custom mode and also you need the user-agent string to be altered from the provided list on every single request.</label></td>
|
||||
</tr>
|
||||
|
@ -64,11 +56,22 @@
|
|||
<td class="spacer"><label><input type="checkbox" id="faqs"> Open FAQs page on updates</label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>A comma-separated list of keywords that the extension should not spoof the user-agent header. Use this list to protect URLs that contain these protected keywords. Each keyword need to be at least 5 char long.</td>
|
||||
<td class="spacer"><label><input type="checkbox" id="log"> Display debuging info in the browser console</label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="h">Disable Spoofing</span> A comma-separated list of keywords that the extension should not spoof the user-agent header. Use this list to protect URLs that contain these protected keywords. Each keyword need to be at least 5 char long.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><textarea id="protected" rows="3" wrap="off"></textarea></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="h">Custom User-Agent Parsing</span>: 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.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="spacer"><textarea id="parser" rows="5" wrap="off"></textarea></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -43,6 +43,7 @@ function save() {
|
|||
chrome.storage.local.set({
|
||||
exactMatch: document.getElementById('exactMatch').checked,
|
||||
faqs: document.getElementById('faqs').checked,
|
||||
log: document.getElementById('log').checked,
|
||||
cache: document.getElementById('cache').checked,
|
||||
blacklist: prepare(document.getElementById('blacklist').value),
|
||||
whitelist: prepare(document.getElementById('whitelist').value),
|
||||
|
@ -63,6 +64,7 @@ function restore() {
|
|||
chrome.storage.local.get({
|
||||
exactMatch: false,
|
||||
faqs: true,
|
||||
log: false,
|
||||
cache: true,
|
||||
mode: 'blacklist',
|
||||
whitelist: [],
|
||||
|
@ -73,6 +75,7 @@ function restore() {
|
|||
}, prefs => {
|
||||
document.getElementById('exactMatch').checked = prefs.exactMatch;
|
||||
document.getElementById('faqs').checked = prefs.faqs;
|
||||
document.getElementById('log').checked = prefs.log;
|
||||
document.getElementById('cache').checked = prefs.cache;
|
||||
document.querySelector(`[name="mode"][value="${prefs.mode}"`).checked = true;
|
||||
document.getElementById('blacklist').value = prefs.blacklist.join(', ');
|
||||
|
|
|
@ -26,7 +26,7 @@ body {
|
|||
background-color: #fff;
|
||||
font-family: "Helvetica Neue", Helvetica, sans-serif;
|
||||
font-size: 13px;
|
||||
width: 650px;
|
||||
min-width: 650px;
|
||||
margin: 0;
|
||||
}
|
||||
table {
|
||||
|
@ -89,10 +89,10 @@ select {
|
|||
#list {
|
||||
overflow: auto;
|
||||
scroll-behavior: smooth;
|
||||
height: 200px;
|
||||
height: 268px;
|
||||
margin-bottom: 16px;
|
||||
color: #000;
|
||||
background-position: top 88px center;
|
||||
background-position: top 120px center;
|
||||
background-repeat: no-repeat;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
@ -210,6 +210,7 @@ body[data-android="true"] [data-cmd="window"] {
|
|||
}
|
||||
#view {
|
||||
background-color: #f5f5f5;
|
||||
padding: 5px 0;
|
||||
}
|
||||
#view td {
|
||||
text-align: right;
|
||||
|
|
|
@ -85,7 +85,6 @@ function update(ua) {
|
|||
}
|
||||
|
||||
document.addEventListener('change', ({target}) => {
|
||||
console.log(target);
|
||||
if (target.closest('#filter')) {
|
||||
localStorage.setItem(target.id, target.value);
|
||||
chrome.storage.local.get({
|
||||
|
|
BIN
extension/extension.zip
Normal file
BIN
extension/extension.zip
Normal file
Binary file not shown.
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 2,
|
||||
"name": "User-Agent Switcher and Manager",
|
||||
"short_name": "useragent-switcher",
|
||||
"version": "0.3.2",
|
||||
"version": "0.3.3",
|
||||
|
||||
"description": "A highly customizable extension to spoof the User-Agent string of your browser with a new one globally, randomly or per hostname",
|
||||
|
||||
|
|
8
extension/ua-parser.min.js
vendored
Executable file → Normal file
8
extension/ua-parser.min.js
vendored
Executable file → Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue