mirror of
https://github.com/anticensority/runet-censorship-bypass.git
synced 2024-11-24 02:13:43 +03:00
title bugs fixed, browserAction, badges
This commit is contained in:
parent
9dd4724167
commit
046dfdbdec
|
@ -1,153 +1,116 @@
|
|||
'use strict';
|
||||
|
||||
// Shows user PageAction icon if any part of the current site is being blocked and proxied.
|
||||
// Shows user browserAction icon if any part of the current site is being blocked and proxied.
|
||||
|
||||
function getHostname(url) {
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
return a.hostname;
|
||||
/*
|
||||
In what moment the title of the previous icon is cleared?
|
||||
By my observations it usually takes place near tabs.onUpdate of tab status to "loading".
|
||||
So if you set a title earlier it may be cleared by browser.
|
||||
It pertains not only to page refesh but to newly opened pages too.
|
||||
Also on loosing title see:
|
||||
https://github.com/ilyaigpetrov/repository-for-chrome-bugs/blob/master/browserAction-title-lost-after-setting/background.js
|
||||
Crazy concurrent Chrome.
|
||||
**/
|
||||
window.onTabUpdated = {};
|
||||
|
||||
chrome.tabs.onRemoved.addListener( tabId => delete window.onTabUpdated[tabId] );
|
||||
|
||||
function afterTabUpdated(tabId, cb) {
|
||||
if (window.onTabUpdated[tabId])
|
||||
window.onTabUpdated[tabId].push(cb);
|
||||
else window.onTabUpdated[tabId] = [cb];
|
||||
}
|
||||
|
||||
function updateTitle(requestDetails, cb) {
|
||||
|
||||
chrome.pageAction.getTitle(
|
||||
{ tabId: requestDetails.tabId },
|
||||
title => {
|
||||
|
||||
var ifTitleSetAlready = /\n/.test(title);
|
||||
var proxyHost = window.antiCensorRu.pacProvider.proxyIps[ requestDetails.ip ];
|
||||
var hostname = getHostname(requestDetails.url);
|
||||
var ifShouldUpdateTitle = false;
|
||||
var indent = ' ';
|
||||
var proxyTitle = 'Прокси:';
|
||||
|
||||
// Initially title equals extension name.
|
||||
if (!ifTitleSetAlready) {
|
||||
title = 'Разблокированы:\n'+ indent + hostname +'\n'+ proxyTitle +'\n'+ indent + proxyHost;
|
||||
ifShouldUpdateTitle = true;
|
||||
|
||||
function setIcon(iconOpts) {
|
||||
iconOpts.tabId = requestDetails.tabId;
|
||||
chrome.pageAction.setIcon(iconOpts);
|
||||
chrome.pageAction.show(requestDetails.tabId);
|
||||
}
|
||||
var iconPath = '/icons/ribbon32.png';
|
||||
|
||||
if (requestDetails.type === 'main_frame')
|
||||
setIcon({path: iconPath});
|
||||
else {
|
||||
var canvas = document.createElement('canvas');
|
||||
var iconSize = 19;
|
||||
canvas.width = canvas.height = iconSize;
|
||||
var img = document.createElement('img');
|
||||
img.onload = () => {
|
||||
var context = canvas.getContext('2d');
|
||||
context.drawImage(img, 0, 0, iconSize, iconSize);
|
||||
var badgeText = '%';
|
||||
|
||||
context.fillStyle = 'red';
|
||||
context.fillRect(0, 9, context.measureText(badgeText).width + 1, iconSize);
|
||||
|
||||
context.fillStyle = 'white';
|
||||
context.font = '11px Arial';
|
||||
context.fillText('%', 0, iconSize - 1);
|
||||
|
||||
setIcon({imageData: context.getImageData(0, 0, iconSize, iconSize)})
|
||||
};
|
||||
img.src = iconPath;
|
||||
}
|
||||
} else {
|
||||
var hostsProxiesPair = title.split(proxyTitle);
|
||||
|
||||
if (hostsProxiesPair[1].indexOf(proxyHost) === -1) {
|
||||
title = title.replace(hostsProxiesPair[1], hostsProxiesPair[1] +'\n'+ indent + proxyHost);
|
||||
ifShouldUpdateTitle = true;
|
||||
}
|
||||
|
||||
if (hostsProxiesPair[0].indexOf(hostname) === -1) {
|
||||
title = title.replace(proxyTitle, indent + hostname +'\n'+ proxyTitle);
|
||||
ifShouldUpdateTitle = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ifShouldUpdateTitle)
|
||||
chrome.pageAction.setTitle({
|
||||
title: title,
|
||||
tabId: requestDetails.tabId
|
||||
});
|
||||
|
||||
return cb();
|
||||
}
|
||||
)
|
||||
}
|
||||
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
|
||||
if (window.onTabUpdated[tabId]) {
|
||||
window.onTabUpdated[tabId].map( f => f() );
|
||||
delete window.onTabUpdated[tabId];
|
||||
}
|
||||
});
|
||||
|
||||
var previousUpdateTitleFinished = Promise.resolve();
|
||||
/*
|
||||
previousUpdateTitleFinished works like a semaphor for updateTitle().
|
||||
What? Semaphor? In JavaScript? Are you kidding?
|
||||
|
||||
Look at this:
|
||||
|
||||
function getTitle(cb) {
|
||||
chrome.pageAction.getTitle(
|
||||
{ tabId: details.tabId },
|
||||
cb
|
||||
);
|
||||
}
|
||||
|
||||
function setTitle(title) {
|
||||
console.log(title);
|
||||
chrome.pageAction.setTitle({
|
||||
title: title +' new!',
|
||||
tabId: details.tabId
|
||||
});
|
||||
chrome.pageAction.show(details.tabId);
|
||||
}
|
||||
|
||||
var updateTitle = (details, cb) => {
|
||||
//var ID = parseInt(Math.random()*100);
|
||||
//console.log(ID, 'START');
|
||||
getTitle( title => {
|
||||
setTitle(title);
|
||||
cb && cb(title);
|
||||
//console.log(ID, 'FINISH');
|
||||
});
|
||||
}
|
||||
updateTitle(details);
|
||||
|
||||
Load some massive page.
|
||||
The logs will be:
|
||||
|
||||
FooBar Extension
|
||||
(6) FooBar Extension new!
|
||||
(2) FooBar Extension new! new!
|
||||
FooBar Extension new! new! new!
|
||||
FooBar Extension new! new! new! new!
|
||||
|
||||
Notice the (6) and (2) denoting the number of repeated log messages.
|
||||
Uncommenting logs reveals that START->FINISH pairs are messed.
|
||||
However, if getTitle is called strictly after setTitle, we are ok:
|
||||
|
||||
previousUpdateTitleFinished = previousUpdateTitleFinished.then(
|
||||
() => new Promise( resolve => updateTitle( details, resolve ) )
|
||||
);
|
||||
|
||||
Well, I hope it works, because once I caught a bug.
|
||||
**/
|
||||
|
||||
function blockInform(details) {
|
||||
|
||||
if (details.tabId !== -1 && window.antiCensorRu.pacProvider && window.antiCensorRu.pacProvider.proxyIps && window.antiCensorRu.pacProvider.proxyIps[ details.ip ]) {
|
||||
function blockInform(requestDetails) {
|
||||
if (requestDetails.tabId !== -1 && window.antiCensorRu.pacProvider && window.antiCensorRu.pacProvider.proxyIps && window.antiCensorRu.pacProvider.proxyIps[ requestDetails.ip ]) {
|
||||
|
||||
previousUpdateTitleFinished = previousUpdateTitleFinished.then(
|
||||
() => new Promise( resolve => updateTitle( details, resolve ) )
|
||||
() => new Promise(
|
||||
resolve => {
|
||||
var cb = () => updateTitle( requestDetails, resolve );
|
||||
return requestDetails.type === 'main_frame' ? afterTabUpdated(requestDetails.tabId, cb) : cb();
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
function updateTitle(requestDetails, cb) {
|
||||
|
||||
chrome.browserAction.getTitle(
|
||||
{ tabId: requestDetails.tabId },
|
||||
title => {
|
||||
var ifTitleSetAlready = /\n/.test(title);
|
||||
var proxyHost = window.antiCensorRu.pacProvider.proxyIps[ requestDetails.ip ];
|
||||
|
||||
var a = document.createElement('a');
|
||||
a.href = requestDetails.url;
|
||||
var hostname = a.hostname;
|
||||
|
||||
var ifShouldUpdateTitle = false;
|
||||
var indent = ' ';
|
||||
var proxyTitle = 'Прокси:';
|
||||
|
||||
if (!ifTitleSetAlready) {
|
||||
title = 'Разблокированы:\n'+ indent + hostname +'\n'+ proxyTitle +'\n'+ indent + proxyHost;
|
||||
ifShouldUpdateTitle = true;
|
||||
|
||||
chrome.browserAction.setBadgeText({
|
||||
tabId: requestDetails.tabId,
|
||||
text: requestDetails.type === 'main_frame' ? '1' : '%1'
|
||||
});
|
||||
|
||||
} else {
|
||||
var hostsProxiesPair = title.split(proxyTitle);
|
||||
|
||||
if (hostsProxiesPair[1].indexOf(proxyHost) === -1) {
|
||||
title = title.replace(hostsProxiesPair[1], hostsProxiesPair[1] +'\n'+ indent + proxyHost);
|
||||
ifShouldUpdateTitle = true;
|
||||
}
|
||||
|
||||
if (hostsProxiesPair[0].indexOf(hostname) === -1) {
|
||||
title = title.replace(proxyTitle, indent + hostname +'\n'+ proxyTitle);
|
||||
ifShouldUpdateTitle = true;
|
||||
|
||||
var _cb = cb;
|
||||
cb = () => chrome.browserAction.getBadgeText(
|
||||
{tabId: requestDetails.tabId},
|
||||
result => {
|
||||
chrome.browserAction.setBadgeText(
|
||||
{
|
||||
tabId: requestDetails.tabId,
|
||||
text: ( isNaN( result.charAt(0) ) && result.charAt(0) || '' ) + (hostsProxiesPair[0].split('\n').length - 1)
|
||||
}
|
||||
);
|
||||
return _cb();
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (ifShouldUpdateTitle)
|
||||
chrome.browserAction.setTitle({
|
||||
title: title,
|
||||
tabId: requestDetails.tabId
|
||||
});
|
||||
|
||||
return cb();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
chrome.webRequest.onCompleted.addListener(
|
||||
chrome.webRequest.onResponseStarted.addListener(
|
||||
blockInform,
|
||||
{ urls: ['<all_urls>'] }
|
||||
);
|
||||
|
@ -155,4 +118,4 @@ chrome.webRequest.onCompleted.addListener(
|
|||
chrome.webRequest.onErrorOccurred.addListener(
|
||||
blockInform,
|
||||
{ urls: ['<all_urls>'] }
|
||||
);
|
||||
);
|
|
@ -15,12 +15,13 @@
|
|||
"webRequest",
|
||||
"alarms",
|
||||
"storage",
|
||||
"<all_urls>"
|
||||
"<all_urls>",
|
||||
"tabs"
|
||||
],
|
||||
"background": {
|
||||
"scripts": ["sync-pac-script-with-pac-provider.js", "block-informer.js"]
|
||||
},
|
||||
"page_action": {
|
||||
"browser_action": {
|
||||
"default_popup": "/pages/choose-pac-provider/index.html"
|
||||
},
|
||||
"options_ui": {
|
||||
|
|
|
@ -18,8 +18,10 @@ function renderPage() {
|
|||
status.classList.add('off');
|
||||
}
|
||||
|
||||
console.log('ABC');
|
||||
chrome.runtime.getBackgroundPage( backgroundPage => {
|
||||
|
||||
backgroundPage.console.log('Options page opened.');
|
||||
var antiCensorRu = backgroundPage.antiCensorRu;
|
||||
|
||||
// SET DATE
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
/*
|
||||
In background scripts use window.antiCensorRu public variables.
|
||||
Thay are synced with chrome.storage so they persist restarts.
|
||||
In pages window.antiCensorRu are not accessible,
|
||||
use chrome.runtime.getBackgroundPage(..),
|
||||
avoid old extension.getBackgroundPage.
|
||||
|
@ -96,45 +95,6 @@ window.antiCensorRu = {
|
|||
cb(chrome.runtime.lastError, storage);
|
||||
});
|
||||
},
|
||||
|
||||
migrateStorage(cb) {
|
||||
chrome.storage.local.get(null, oldStorage => {
|
||||
|
||||
var getPubCounter = version => parseInt( version.match(/\d+$/)[0] );
|
||||
var version = oldStorage.version || '0.0.0.0';
|
||||
var oldPubCounter = getPubCounter( version );
|
||||
|
||||
if (oldPubCounter > 9) {
|
||||
console.log('No migration required, storage pub', oldPubCounter, 'is up to date.');
|
||||
return cb && cb(chrome.runtime.lastError, oldStorage);
|
||||
}
|
||||
|
||||
console.log('Starting storage migration from publication', oldPubCounter, 'to', getPubCounter( this.version ));
|
||||
|
||||
this._currentPacProviderKey = oldStorage._currentPacProviderKey;
|
||||
this.lastPacUpdateStamp = oldStorage.lastPacUpdateStamp;
|
||||
// There is no need to persist other properties in the storage.
|
||||
|
||||
return this.pushToStorage(cb);
|
||||
|
||||
/*
|
||||
|
||||
History of Changes to Storage
|
||||
-----------------------------
|
||||
|
||||
Version 0.0.0.10
|
||||
|
||||
* Added this.version
|
||||
* PacProvider.proxyIps changed from {ip -> Boolean} to {ip -> hostname}
|
||||
|
||||
Version 0.0.0.8-9
|
||||
|
||||
* Changed storage.ifNotInstalled to storage.ifFirstInstall
|
||||
* Added storage.lastPacUpdateStamp
|
||||
|
||||
**/
|
||||
});
|
||||
},
|
||||
|
||||
syncWithPacProvider(cb) {
|
||||
var cb = cb || (() => {});
|
||||
|
@ -179,15 +139,13 @@ window.antiCensorRu = {
|
|||
|
||||
var cb = asyncLogGroup('Installing PAC...', cb);
|
||||
|
||||
chrome.alarms.clear(
|
||||
chrome.alarms.create(
|
||||
this._periodicUpdateAlarmReason,
|
||||
() => chrome.alarms.create(
|
||||
this._periodicUpdateAlarmReason,
|
||||
{ periodInMinutes: 4*60 }
|
||||
)
|
||||
{ periodInMinutes: 4*60 }
|
||||
);
|
||||
|
||||
this.syncWithPacProvider(cb);
|
||||
return this.syncWithPacProvider(cb);
|
||||
|
||||
},
|
||||
|
||||
clearPac(cb) {
|
||||
|
@ -205,64 +163,86 @@ window.antiCensorRu = {
|
|||
|
||||
};
|
||||
|
||||
// ON EACH LAUNCH OF EXTENSION
|
||||
// Not only on Chrome's startUp, but aslo on Enable/Disable
|
||||
// ON EACH LAUNCH, STARTUP, RELOAD, UPDATE, ENABLE
|
||||
chrome.storage.local.get(null, oldStorage => {
|
||||
|
||||
window.storageSyncedPromise = new Promise(
|
||||
(resolve, reject) => {
|
||||
/* We have to migrate on each launch, because:
|
||||
1. There is no way to check that chrome.runtime.onInstalled wasn't fired except timeout.
|
||||
2. There is no way to schedule onInstalled before pullFromStorage without timeouts.
|
||||
3. So inside onInstalled storage may only be already pulled.
|
||||
*/
|
||||
window.antiCensorRu.migrateStorage(
|
||||
(err, migratedStorage) =>
|
||||
err ? reject(err) : window.antiCensorRu.pullFromStorage(
|
||||
(err, res) => err ? reject(err) : resolve(res)
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
window.storageSyncedPromise.then(
|
||||
storage => {
|
||||
console.log('Init on storage:', oldStorage);
|
||||
|
||||
// Finish each init with this callback setting alarm listeners.
|
||||
function cb(err) {
|
||||
chrome.alarms.onAlarm.addListener(
|
||||
alarm => {
|
||||
if (alarm.name === window.antiCensorRu._periodicUpdateAlarmReason) {
|
||||
if (alarm.name === antiCensorRu._periodicUpdateAlarmReason) {
|
||||
console.log('Periodic update triggered:', new Date());
|
||||
window.antiCensorRu.syncWithPacProvider();
|
||||
antiCensorRu.syncWithPacProvider();
|
||||
}
|
||||
}
|
||||
);
|
||||
console.log('Alarm listener installed. We won\'t miss any PAC update.');
|
||||
|
||||
chrome.alarms.get(
|
||||
window.antiCensorRu._periodicUpdateAlarmReason,
|
||||
alarm => alarm && console.log(
|
||||
'Next update is scheduled on', new Date(alarm.scheduledTime).toLocaleString('ru-RU')
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
chrome.runtime.onInstalled.addListener( installDetails => {
|
||||
console.log('Extension just installed, reason:', installDetails.reason);
|
||||
window.storageSyncedPromise.then(
|
||||
storage => {
|
||||
|
||||
switch(installDetails.reason) {
|
||||
case 'update':
|
||||
console.log('Update or reload. Do nothing.');
|
||||
break;
|
||||
case 'install':
|
||||
window.antiCensorRu.ifFirstInstall = true;
|
||||
chrome.runtime.openOptionsPage();
|
||||
antiCensorRu._periodicUpdateAlarmReason,
|
||||
alarm => {
|
||||
if (!alarm)
|
||||
return console.error('ALARM NOT SET');
|
||||
console.log(
|
||||
'Next update is scheduled on', new Date(alarm.scheduledTime).toLocaleString('ru-RU')
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// INSTALL
|
||||
antiCensorRu.ifFirstInstall = Object.keys(oldStorage).length === 0;
|
||||
if (antiCensorRu.ifFirstInstall) {
|
||||
console.log('Installing...');
|
||||
return chrome.runtime.openOptionsPage(cb);
|
||||
}
|
||||
|
||||
/*
|
||||
1. There is no way to check that chrome.runtime.onInstalled wasn't fired except timeout.
|
||||
Otherwise we could put storage migration code only there.
|
||||
2. We have to check storage for migration before using it.
|
||||
Better on each launch then on each pull.
|
||||
*/
|
||||
|
||||
// LAUNCH, RELOAD, UPDATE
|
||||
|
||||
antiCensorRu._currentPacProviderKey = oldStorage._currentPacProviderKey || antiCensorRu._currentPacProviderKey;
|
||||
antiCensorRu.lastPacUpdateStamp = oldStorage.lastPacUpdateStamp || antiCensorRu.lastPacUpdateStamp;
|
||||
|
||||
if (antiCensorRu.version === oldStorage.version) {
|
||||
// LAUNCH, RELOAD
|
||||
console.log('Launch or reload. Do nothing.');
|
||||
return cb();
|
||||
}
|
||||
|
||||
// UPDATE & MIGRATION
|
||||
console.log('Updating...');
|
||||
return updatePacProxyIps(
|
||||
antiCensorRu.pacProvider,
|
||||
ipsError => {
|
||||
if (ipsError) ipsError.ifNotCritical = true;
|
||||
antiCensorRu.pushToStorage( pushError => cb( pushError || ipsError ) );
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
/*
|
||||
|
||||
History of Changes to Storage (Migration Guide)
|
||||
-----------------------------------------------
|
||||
|
||||
Version 0.0.0.10
|
||||
|
||||
* Added this.version
|
||||
* PacProvider.proxyIps changed from {ip -> Boolean} to {ip -> hostname}
|
||||
|
||||
Version 0.0.0.8-9
|
||||
|
||||
* Changed storage.ifNotInstalled to storage.ifFirstInstall
|
||||
* Added storage.lastPacUpdateStamp
|
||||
|
||||
**/
|
||||
});
|
||||
|
||||
// PRIVATE
|
||||
|
@ -317,7 +297,7 @@ function updatePacProxyIps(provider, cb) {
|
|||
(err, res) => {
|
||||
if (!err) {
|
||||
provider.proxyIps = provider.proxyIps || {};
|
||||
provider.proxyIps[ JSON.parse(res).answer[0].rdata ] = proxyHost;
|
||||
provider.proxyIps[ JSON.parse(res).answer[0].rdata ] = proxyHost;
|
||||
} else
|
||||
failure.errors[proxyHost] = err;
|
||||
|
||||
|
@ -355,7 +335,6 @@ function setPacScriptFromProvider(provider, cb) {
|
|||
console.log('Setting chrome proxy settings...');
|
||||
chrome.proxy.settings.set( {value: config}, cb );
|
||||
});
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user