Skip to content

Commit

Permalink
1. Fianlly make the HTTP header modifying work (after fighting with a…
Browse files Browse the repository at this point in the history
…n obscure undocumented API issue)

2. Add Sentry lib to capture potential crash reports (but can only used on options.html and popup.html)
  • Loading branch information
zhuzhuor committed Jul 2, 2022
1 parent d4e778f commit 91eedf8
Show file tree
Hide file tree
Showing 15 changed files with 172 additions and 93 deletions.
4 changes: 2 additions & 2 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Unblock Youku",
"version": "4.0.0",
"manifest_version": 3,
"minimum_chrome_version": "96.0",
"minimum_chrome_version": "103.0",
"default_locale": "en",
"description": "__MSG_description__",
"icons": {
Expand All @@ -20,7 +20,7 @@
"https://*/*"
],
"background": {
"service_worker": "src/background.mjs",
"service_worker": "src/service_worker.mjs",
"type": "module"
},
"action": {
Expand Down
17 changes: 0 additions & 17 deletions src/background.mjs

This file was deleted.

80 changes: 45 additions & 35 deletions src/modules/_header.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,55 +3,65 @@
*/


import {HEADER_URLS} from '../configs/urls.mjs';


function newRandomIp() {
'use strict';
let ipAddr = '220.181.111.';
// ipAddr += Math.floor(Math.random() * 255) + '.';
ipAddr += Math.floor(Math.random() * 254 + 1); // 1 ~ 254
return ipAddr;
}

const RANDOM_IP = newRandomIp();
// TODO: Store in local storage, and change everytime the chrome is restarted.


function headerModifier(details) {
console.log('modify headers of ' + details.url);

details.requestHeaders.push({
name: 'X-Forwarded-For',
value: RANDOM_IP,
}, {
name: 'Client-IP',
value: RANDOM_IP,
});

return {requestHeaders: details.requestHeaders};
}
// The header modifying rules may be applied to the following types of requests
const RESOURCE_TYPES = [
'main_frame', 'sub_frame', 'script', 'object', 'xmlhttprequest', 'media', 'websocket', 'other'];

export async function setHeaderModifier() {
// Alway clear the existing rules (if there are any) before apply new rules again.
// Otherwise the rule IDs may be duplicated and cause exceptions.
await clearHeaderModifier();

export function setHeaderModifier() {
if (!chrome.webRequest.onBeforeSendHeaders.hasListener(headerModifier)) {
// TODO: Fix this
// chrome.webRequest.onBeforeSendHeaders.addListener(
// headerModifier,
// {
// urls: unblock_youku.header_urls,
// },
// ['requestHeaders', 'blocking'],
// );
console.log('header_modifier is successfully set');
} else {
console.error('header modifer is already there! So didn\'t set it again.');
const rules = [];
for (let i = 0; i < HEADER_URLS.length; i++) {
const url = HEADER_URLS[i];
rules.push({
'id': i + 1, // id has to be larger than 0 and unique
'priority': 10,
'condition': {
urlFilter: url,
// Perhaps it is a bug in Chrome's declarativeNetRequest API:
// Although reousrceTypes is an optional parameter, without setting it,
// the rule will not be applied at all.
resourceTypes: RESOURCE_TYPES,
},
'action': {
type: 'modifyHeaders',
requestHeaders: [{
header: 'X-Forwarded-For',
operation: 'set',
value: RANDOM_IP,
}],
},
});
}

await chrome.declarativeNetRequest.updateDynamicRules({
addRules: rules,
});
console.log('Successfully set header modifying rules');
}


export function clearHeaderModifier() {
if (chrome.webRequest.onBeforeSendHeaders.hasListener(headerModifier)) {
chrome.webRequest.onBeforeSendHeaders.removeListener(headerModifier);
console.log('header modifier is removed');
} else {
console.error('header modifier is not there!');
}
export async function clearHeaderModifier() {
const enabledRules = await chrome.declarativeNetRequest.getDynamicRules();
const enabledRuleIds = enabledRules.map((rule) => rule.id);
console.log('Clearing header modifying rules with IDs: ' + enabledRuleIds);
await chrome.declarativeNetRequest.updateDynamicRules({
removeRuleIds: enabledRuleIds,
});
console.log('Successfully cleared header modifying rules');
}
26 changes: 17 additions & 9 deletions src/modules/_proxy.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ import {urls2pac} from './_url_utils.mjs';

async function setPacScript(
defaultProxyProtocol, defaultProxyAddress, backupProxyProtocol, backupProxyAddress) {
console.log('To set up proxy...');
console.log('To generate and set the PAC script');

const pacScript = urls2pac(
PROXY_BYPASS_URLS, PROXY_URLS,
defaultProxyProtocol, defaultProxyAddress,
backupProxyProtocol, backupProxyAddress);

console.groupCollapsed('Printing PAC script content...');
console.log(pacScript);
console.groupEnd();
// console.groupCollapsed('Printing PAC script content...');
// console.log(pacScript);
// console.groupEnd();

await chrome.proxy.settings.set({
value: {
Expand All @@ -33,7 +33,7 @@ async function setPacScript(
scope: 'regular',
});
console.log(
'Successfully set the proxy server: ' + defaultProxyProtocol + ' ' + defaultProxyAddress);
'Successfully set the PAC script with: ' + defaultProxyProtocol + ' ' + defaultProxyAddress);
}


Expand Down Expand Up @@ -63,7 +63,15 @@ export async function clearProxy() {
}


chrome.proxy.onProxyError.addListener(function(details) {
console.error('Received errors from onProxyError:');
console.error(details);
});
function logProxyError(details) {
console.error('Received errors from onProxyError:\n' + JSON.stringify(details, null, 2));
}

console.log('Setting up proxy.onProxyError listener for debugging purposes');
// NOTE: Need to first check if the listener is already set; otherwise
// service_worker.mjs, popup.mjs, and options.mjs may set it multiple times
if (chrome.proxy.onProxyError.hasListener(logProxyError)) {
console.log('The proxy.onProxyError listener is already set, so it won\'t be set again');
} else {
chrome.proxy.onProxyError.addListener(logProxyError);
}
14 changes: 14 additions & 0 deletions src/modules/_storage.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,17 @@ export function setItem(key, value) {
export function removeItem(key) {
return chrome.storage.sync.remove(key);
}


function storageChangeMonitor(changes, area) {
console.log('Storage changed for the area "' + area + '": ' + JSON.stringify(changes));
}

console.log('Setting up storage.onChanged listener for debugging purposes');
// NOTE: Need to first check if the listener is already set; otherwise
// service_worker.mjs, popup.mjs, and options.mjs may set it multiple times
if (chrome.storage.onChanged.hasListener(storageChangeMonitor)) {
console.log('The storage.onChanged listener is already set, so it won\'t be set again');
} else {
chrome.storage.onChanged.addListener(storageChangeMonitor);
}
17 changes: 17 additions & 0 deletions src/modules/crash_report.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// IMPORTANT NOTE:
// To make it work, we need to add the following line first to the HTML file:
// <script type="text/javascript" src="third_party/js/sentry-x.y.z.min.js"></script>
// So it do NOT work for the service_worker.mjs file. Currently it works only for the
// popup.html and options.html pages.

const PRODUCTION_SAMPLE_RATE = 0.01;

function isProductionExtension() {
return chrome.runtime.id === 'pdnfnkhpgegpcingjbfihlkjeighnddk';
}

Sentry.init({
dsn: 'https://[email protected]/6544429',
sampleRate: isProductionExtension() ? PRODUCTION_SAMPLE_RATE : 1.0,
release: chrome.runtime.getManifest().version,
});
50 changes: 24 additions & 26 deletions src/modules/settings.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {Modes} from './modes.mjs';
import * as Storage from './_storage.mjs';
import * as Proxy from './_proxy.mjs';
import * as Header from './_header.mjs';
import * as Icon from './_icon.mjs';


Expand Down Expand Up @@ -28,33 +29,32 @@ export function getCustomProxy() {
}


// Clear all settings regardless of the current mode
// Note: Make sure a Promise is returned so that the caller can wait for it
function clearAllSettings() {
return Promise.all([
Proxy.clearProxy(),
// Header.clearHeaderModifier(),
]);
}

// Apply the settings for the given mode
// Note: Make sure a Promise is returned so that the caller can wait for it
// Clear any previous settings and apply new settings for the given mode.
// Note:
// * The function should be idempotent so it can be called multiple times.
// * Make sure a Promise is returned so that the caller can wait for it.
async function applyModeSettings(mode) {
if (mode === Modes.OFF) {
Icon.setIcon(Modes.OFF);
return; // Do nothing else
}

const customProxy = await getCustomProxy();
if (typeof customProxy === 'undefined' ||
return Promise.all([
Proxy.clearProxy(),
Header.clearHeaderModifier(),
Icon.setIcon(Modes.OFF),
]);
} else {
// 1. Set proxy
const customProxy = await getCustomProxy();
if (typeof customProxy === 'undefined' ||
typeof customProxy.proc === 'undefined' ||
typeof customProxy.addr === 'undefined') {
await Proxy.setDefaultProxy();
} else {
await Proxy.setCustomProxy(customProxy.proc, customProxy.addr);
await Proxy.setDefaultProxy();
} else {
await Proxy.setCustomProxy(customProxy.proc, customProxy.addr);
}
// 2. Set header modifier
await Header.setHeaderModifier();
// 3. Set icon
Icon.setIcon(Modes.NORMAL);
}
// TODO: Set header modifier
Icon.setIcon(Modes.NORMAL);
}


Expand All @@ -74,12 +74,10 @@ export async function loadCurrentSettings() {
// ================================================================
// Function called by popup.js:
// * setNewMode()
// 1. Tear down the settings of the old mode
// 2. Set up the mode settings for the new mode
// 3. Save the new mode into storage
// 1. Set up the mode settings for the new mode
// 2. Save the new mode into storage

export async function setNewMode(mode) {
await clearAllSettings();
await applyModeSettings(mode);
await Storage.setItem(MODE_STORAGE_KEY, mode);

Expand Down
1 change: 1 addition & 0 deletions src/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<link rel="stylesheet" type="text/css" href="third_party/css/bootstrap-3.3.5.min.css" />
<script type="text/javascript" src="third_party/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="third_party/js/bootstrap-3.3.5.min.js"></script>
<script type="text/javascript" src="third_party/js/sentry-7.4.1.min.js"></script>
<script type="module" src="options.mjs"></script>
</head>

Expand Down
5 changes: 2 additions & 3 deletions src/options.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import './modules/crash_report.mjs';

import * as Settings from './modules/settings.mjs';
import {DEFAULT_PROXY_PROTOCOL, DEFAULT_PROXY_ADDRESS} from './configs/servers.mjs';

Expand Down Expand Up @@ -99,8 +101,6 @@ $('#custom_proxy_enable').click(function() {
showProxyMessage(
'warning', 'Set the custom proxy server, and changed mode to use proxy');

console.log('Successfully set the custom proxy server to ' +
customProxyProtocol + ' ' + customProxyAddress);
console.groupEnd();
});
});
Expand All @@ -118,7 +118,6 @@ $('#custom_proxy_reset').click(function() {
$('#custom_proxy_enable').attr('disabled', false);
showProxyMessage('warning', 'Reset custom proxy server, and changed mode to use proxy');

console.log('Successfully reset the custom proxy server');
console.groupEnd();
});
});
Expand Down
1 change: 1 addition & 0 deletions src/popup.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<link rel="stylesheet" type="text/css" href="css/popup.css" />
<script type="text/javascript" src="third_party/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="third_party/js/bootstrap-3.3.5.min.js"></script>
<script type="text/javascript" src="third_party/js/sentry-7.4.1.min.js"></script>
<script type="module" src="popup.mjs"></script>
</head>

Expand Down
3 changes: 2 additions & 1 deletion src/popup.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import './modules/crash_report.mjs';

import {Modes} from './modules/modes.mjs';
import * as Settings from './modules/settings.mjs';
import * as Icon from './modules/_icon.mjs';
Expand Down Expand Up @@ -59,4 +61,3 @@ $('input#input_normal').change(function() {

// Enable tooltip
$('#tooltip').tooltip();

36 changes: 36 additions & 0 deletions src/service_worker.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// IMPORTANT NOTE:
// Any asynchronous operations not wrapped by an event listener here
// are not guaranteed to complete, or may not get executed at all.
// So please make sure all important logic is done via listeners.


import * as Settings from './modules/settings.mjs';


function initializeExtension() {
console.group('To intialize the extension...');
Settings.loadCurrentSettings().then(() => {
console.log('Successfully initialized the chrome extension');
console.groupEnd();
});
}


// Triggered when the extension is first time installed
chrome.runtime.onInstalled.addListener(function(details) {
// Show the donation page when the extension is installed
if (details.reason === 'install') {
chrome.tabs.create({
url: chrome.i18n.getMessage('donation_url'),
});
}

// Initialize the extension
initializeExtension();
});


// Triggered when the Chrome browser itself is just opened
chrome.runtime.onStartup.addListener(function() {
initializeExtension();
});
5 changes: 5 additions & 0 deletions src/third_party/js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Run the following command to validate the integrity of the third-party JavaScript libs:

```
sha256sum --check checksum.sha256
```
3 changes: 3 additions & 0 deletions src/third_party/js/checksum.sha256
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
4a4de7903ea62d330e17410ea4db6c22bcbeb350ac6aa402d6b54b4c0cbed327 bootstrap-3.3.5.min.js
f16ab224bb962910558715c82f58c10c3ed20f153ddfaa199029f141b5b0255c jquery-2.1.4.min.js
ca19d635167de42633b7c4acda11365444ebafe4093f9f241963b48cd57093b6 sentry-7.4.1.min.js
Loading

0 comments on commit 91eedf8

Please sign in to comment.