my first commit

This commit is contained in:
Ray Lothian 2017-09-13 14:48:12 +04:30
commit 99ee6c0c6b
20 changed files with 531 additions and 0 deletions

64
common.js Normal file
View file

@ -0,0 +1,64 @@
'use strict';
var ua = 'hi';
var onBeforeSendHeaders = ({requestHeaders}) => {
for (let i = 0, name = requestHeaders[0].name; i < requestHeaders.length; i += 1, name = requestHeaders[i].name) {
if (name === 'User-Agent' || name === 'user-agent') {
requestHeaders[i].value = ua;
return {
requestHeaders
};
}
}
};
var onCommitted = ({frameId, url, tabId}) => {
if (frameId === 0 && url && (url.startsWith('http') || url.startsWith('ftp'))) {
chrome.tabs.executeScript(tabId, {
runAt: 'document_start',
allFrames: true,
code: `{
const script = document.createElement('script');
script.textContent = \`{
navigator.__defineGetter__('userAgent', () => '${ua}');
}\`;
document.documentElement.appendChild(script);
}`
}, () => chrome.runtime.lastError);
}
};
function update(str) {
ua = str;
if (ua) {
chrome.webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {
'urls' : ['*://*/*']
}, ['blocking', 'requestHeaders']);
chrome.webNavigation.onCommitted.addListener(onCommitted);
}
else {
chrome.webRequest.onBeforeSendHeaders.removeListener(onBeforeSendHeaders);
chrome.webNavigation.onCommitted.removeListener(onCommitted);
}
chrome.browserAction.setIcon({
path: {
16: 'data/icons/' + (ua ? 'active/' : '') + '16.png',
32: 'data/icons/' + (ua ? 'active/' : '') + '32.png',
48: 'data/icons/' + (ua ? 'active/' : '') + '48.png',
64: 'data/icons/' + (ua ? 'active/' : '') + '64.png'
}
});
chrome.browserAction.setTitle({
title: `UserAgent Switcher (${ua ? 'enabled' : 'disabled'})
User-Agent String: ${ua || navigator.userAgent}`
});
}
chrome.storage.local.get({
ua: ''
}, prefs => update(prefs.ua));
chrome.storage.onChanged.addListener(prefs => {
update(prefs.ua.newValue);
});

BIN
data/icons/128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
data/icons/16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

BIN
data/icons/256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
data/icons/32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 B

BIN
data/icons/48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
data/icons/512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
data/icons/64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

BIN
data/icons/active/16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

BIN
data/icons/active/32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,015 B

BIN
data/icons/active/48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
data/icons/active/64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

6
data/popup/ReadMe.txt Normal file
View file

@ -0,0 +1,6 @@
Generating the list:
Run
JSON.stringify([...document.querySelectorAll('li a')].map(a => a.textContent))
on
http://www.useragentstring.com/pages/useragentstring.php?typ=Browser

105
data/popup/index.css Normal file
View file

@ -0,0 +1,105 @@
[hbox] {
display: flex;
flex-direction: row;
}
[vbox] {
display: flex;
flex-direction: column;
}
[flex="1"] {
flex: 1;
}
[pack=center] {
justify-content: center;
}
[align=center] {
align-items: center;
}
[pack=end] {
justify-content: flex-end;
}
[align=end] {
align-items: flex-end;
}
body {
font-family: "Helvetica Neue",Helvetica,sans-serif;
font-size: 13px;
width: 700px;
}
table {
width: 100%;
border-collapse: collapse;
}
fieldset {
border: solid 1px #ccc;
}
select,
input[type=search],
input[type=text] {
width: 100%;
margin-right: 2px;
text-indent: 5px;
}
select,
input {
outline: none;
background-color: #fff;
color: #000;
border: solid 1px #ccc;
box-sizing: border-box;
height: 24px;
}
input[type=button] {
cursor: pointer;
min-width: 100px;
}
input[type=button]:active {
opacity: 0.5;
}
#list {
margin: 20px 0;
overflow: auto;
height: 300px;
background-color: rgba(0, 0, 0, 0.05);
}
#list[data-loading=true] {
background: url(loading.gif) top 120px center no-repeat;
background-size: 64px;
}
#list tr {
cursor: pointer;
}
#list tr[data-matched=false] {
opacity: 0.5;
}
#list tr:nth-child(even) {
background-color: rgba(0, 0, 0, 0.05);
}
#list td:nth-child(1) {
width: 20px;
text-align: center;
}
#list td:nth-child(2),
#list td:nth-child(3) {
width: 100px;
}
#list tr {
height: 22px;
}
#tools input {
width: 100px;
margin: 3px 0 0 5px;
}
#filter td:first-child {
width: 100px;
}
#agent {
padding: 10px 0;
white-space: nowrap;
}

153
data/popup/index.html Normal file
View file

@ -0,0 +1,153 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div hbox id="filter">
<select id="os">
<optgroup label="Populars">
<option value="windows">Windows</option>
<option value="mac os">Mac OS</option>
<option value="linux">Linux</option>
<option value="chromium os">Chromium OS</option>
<option value="ubuntu">Ubuntu</option>
<option value="debian">Debian</option>
<option value="android">Android</option>
<option value="ios>">iOS</option>
</optgroup>
<optgroup label="Others">
<option value="amigaos">AmigaOS</option>
<option value="openbsd">OpenBSD</option>
<option value="beos">BeOS</option>
<option value="haiku">Haiku</option>
<option value="solaris">Solaris</option>
<option value="netbsd">NetBSD</option>
<option value="freebsd">FreeBSD</option>
<option value="slackware">Slackware</option>
<option value="suse">SUSE</option>
<option value="gentoo">gentoo</option>
<option value="fedora">Fedora</option>
<option value="gentoo">Gentoo</option>
<option value="mageia">Mageia</option>
<option value="centos">CentOS</option>
<option value="mint">Mint</option>
<option value="dragonfly">DragonFly</option>
<option value="kubuntu">Kubuntu</option>
<option value="mandriva">Mandriva</option>
<option value="zenwalk">Zenwalk</option>
<option value="unix">Unix</option>
<option value="gnu">GNU</option>
<option value="os/2">OS/2</option>
<option value="aix">AIX</option>
<option value="qnx">QNX</option>
<option value="beos">BEOS</option>
<option value="risc os">RISC OS</option>
<option value="symbian">Symbian</option>
<option value="nintendo">Nintendo</option>
<option value="opensolaris">OpenSolaris</option>
<option value="kubuntu">kubuntu</option>
</optgroup>
</select>
<select id="browser">
<optgroup label="Populars">
<option value="ie">Internet Explorer</option>
<option value="safari">Safari</option>
<option value="chrome">Chrome</option>
<option value="firefox">Firefox</option>
<option value="opera">Opera</option>
<option value="edge">Edge</option>
</optgroup>
<optgroup label="Others">
<option value="webkit">WebKit</option>
<option value="avant">Avant</option>
<option value="maxthon">Maxthon</option>
<option value="arora">Arora</option>
<option value="mozilla">Mozilla</option>
<option value="epiphany">Epiphany</option>
<option value="camino">Camino</option>
<option value="chimera">Chimera</option>
<option value="chromium">Chromium</option>
<option value="comodo dragon">Dragon</option>
<option value="conkeror">conkeror</option>
<option value="conkeror">Conkeror</option>
<option value="dillo">Dillo</option>
<option value="links">Links</option>
<option value="firebird">Firebird</option>
<option value="swiftfox">Swiftfox</option>
<option value="netscape">Netscape</option>
<option value="flock">Flock</option>
<option value="icab">iCab</option>
<option value="iceape">Iceape</option>
<option value="icecat">icecat</option>
<option value="icecat">IceCat</option>
<option value="iceweasel">IceWeasel</option>
<option value="iron">Iron</option>
<option value="k-meleon">Meleon</option>
<option value="konqueror">Konqueror</option>
<option value="lunascape">Lunascape</option>
<option value="lynx">Lynx</option>
<option value="maxthon">MAXTHON</option>
<option value="midori">midori</option>
<option value="midori">Midori</option>
<option value="khtml">KHTML</option>
<option value="mosaic">Mosaic</option>
<option value="netsurf">NetSurf</option>
<option value="omniweb">OmniWeb</option>
<option value="opera tablet">Tablet</option>
<option value="opera mini">Mini</option>
<option value="phoenix">Phoenix</option>
<option value="rockmelt">RockMelt</option>
<option value="mobile safari">Safari</option>
<option value="android browser">Browser</option>
<option value="seamonkey">SeaMonkey</option>
<option value="slim">Slim</option>
<option value="webkit">Webkit</option>
<option value="w3m">w3m</option>
</optgroup>
</select>
<select id="sort">
<option value="true">Browser version (descending)</option>
<option value="false">Browser version (ascending)</option>
</select>
</div>
<div id="list" data-loading=true>
<table>
<thead>
<tr>
<th></th>
<th>Browser</th>
<th>OS</th>
<th>String</th>
</tr>
</thead>
<template>
<tr>
<td><input type="radio" name="select"></td>
<td></td>
<td></td>
<td></td>
</tr>
</template>
<tbody></tbody>
</table>
</div>
<div hbox>
<input type="search" id="custom" placeholder="Filter">
<input type="button" value="Update">
</div>
<div hbox id="agent" pack="center" align="center">
User-Agent String:&nbsp;
<input id="ua" type="text" name="">
<input type="button" value="Apply" data-cmd="apply">
<input type="button" value="Reset" style="margin-left: 2px;" data-cmd="reset">
</div>
<script src="ua-parser.min.js"></script>
<script src="index.js"></script>
</body>
</html>

154
data/popup/index.js Normal file
View file

@ -0,0 +1,154 @@
/* globals UAParser */
'use strict';
var json = [];
function filter(list) {
return list.filter(o => {
const browser = document.getElementById('browser').value;
if (browser) {
try {
if (o.browser.name.toLowerCase().trim().indexOf(browser.trim()) === -1) {
return false;
}
}
catch (e) {
return false;
}
}
const os = document.getElementById('os').value;
if (os) {
try {
if (o.os.name.toLowerCase().trim().indexOf(os.trim()) === -1) {
return false;
}
}
catch (e) {
return false;
}
}
return true;
});
}
function sort(arr) {
function sort(a = '', b = '') {
const pa = a.split('.');
const pb = b.split('.');
for (let i = 0; i < 3; i++) {
const na = Number(pa[i]);
const nb = Number(pb[i]);
if (na > nb) {
return 1;
}
if (nb > na) {
return -1;
}
if (!isNaN(na) && isNaN(nb)) {
return 1;
}
if (isNaN(na) && !isNaN(nb)) {
return -1;
}
}
return 0;
}
const list = arr.sort((a, b) => sort(a.browser.version, b.browser.version));
if (document.getElementById('sort').value === 'true') {
return list.reverse();
}
return list;
}
function parse(j) {
json = j.map(s => UAParser(s));
}
function update() {
const list = sort(filter(json));
const t = document.querySelector('template');
const parent = document.getElementById('list');
const tbody = parent.querySelector('tbody');
tbody.textContent = '';
parent.dataset.loading = true;
list.forEach(o => {
const clone = document.importNode(t.content, true);
clone.querySelector('td:nth-child(2)').textContent = o.browser.name + ' ' + (o.browser.version || '-');
clone.querySelector('td:nth-child(3)').textContent = o.os.name + ' ' + (o.os.version || '-');
clone.querySelector('td:nth-child(4)').textContent = o.ua;
tbody.appendChild(clone);
});
parent.dataset.loading = false;
}
document.addEventListener('change', ({target}) => {
if (target.closest('#filter')) {
localStorage.setItem(target.id, target.value);
update();
}
if (target.closest('#list')) {
document.getElementById('ua').value = target.closest('tr').querySelector('td:nth-child(4)').textContent;
}
});
document.getElementById('list').addEventListener('click', ({target}) => {
const tr = target.closest('tr');
if (tr) {
const input = tr.querySelector('input');
if (input && input !== target) {
input.checked = !input.checked;
input.dispatchEvent(new Event('change', {
bubbles: true
}));
}
}
});
document.getElementById('custom').addEventListener('keyup', ({target}) => {
const value = target.value;
[...document.querySelectorAll('#list tr')]
.forEach(tr => tr.dataset.matched = tr.textContent.toLowerCase().indexOf(value.toLowerCase()) !== -1);
});
// init
document.getElementById('os').value = localStorage.getItem('os') || 'windows';
document.getElementById('browser').value = localStorage.getItem('browser') || 'chrome';
chrome.storage.local.get({
ua: ''
}, prefs => document.getElementById('ua').value = prefs.ua || navigator.userAgent);
chrome.storage.onChanged.addListener(prefs => {
if (prefs.ua) {
document.getElementById('ua').value = prefs.ua.newValue || navigator.userAgent;
}
});
window.addEventListener('load', () => {
var req = new XMLHttpRequest();
req.onload = () => {
parse(req.response);
update();
};
req.open('GET', 'list.json');
req.responseType = 'json';
req.send();
});
// commands
document.addEventListener('click', ({target}) => {
const cmd = target.dataset.cmd;
if (cmd) {
if (cmd === 'apply') {
chrome.storage.local.set({
ua: document.getElementById('ua').value
});
}
else if (cmd === 'reset') {
const input = document.querySelector('#list :checked');
if (input) {
input.checked = false;
}
chrome.storage.local.set({
ua: ''
});
}
}
});

1
data/popup/list.json Normal file

File diff suppressed because one or more lines are too long

BIN
data/popup/loading.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

9
data/popup/ua-parser.min.js vendored Normal file

File diff suppressed because one or more lines are too long

39
manifest.json Executable file
View file

@ -0,0 +1,39 @@
{
"manifest_version": 2,
"name": "User-Agent Switcher",
"version": "0.1.0",
"description": "Spoofs User-Agent strings of your browser",
"permissions": [
"tabs",
"storage",
"<all_urls>",
"webNavigation",
"webRequest",
"webRequestBlocking"
],
"icons": {
"16": "data/icons/16.png",
"32": "data/icons/32.png",
"48": "data/icons/48.png",
"64": "data/icons/64.png",
"128": "data/icons/128.png",
"256": "data/icons/256.png"
},
"background":{
"scripts":[
"common.js"
]
},
"browser_action":{
"default_icon": {
"16": "data/icons/16.png",
"32": "data/icons/32.png",
"48": "data/icons/48.png",
"64": "data/icons/64.png"
},
"default_popup": "data/popup/index.html"
}
}