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,61 +1,72 @@
|
||||||
'use strict';
|
'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');
|
In what moment the title of the previous icon is cleared?
|
||||||
a.href = url;
|
By my observations it usually takes place near tabs.onUpdate of tab status to "loading".
|
||||||
return a.hostname;
|
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.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
|
||||||
|
if (window.onTabUpdated[tabId]) {
|
||||||
|
window.onTabUpdated[tabId].map( f => f() );
|
||||||
|
delete window.onTabUpdated[tabId];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
chrome.pageAction.getTitle(
|
var previousUpdateTitleFinished = Promise.resolve();
|
||||||
|
|
||||||
|
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 => {
|
||||||
|
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 },
|
{ tabId: requestDetails.tabId },
|
||||||
title => {
|
title => {
|
||||||
|
|
||||||
var ifTitleSetAlready = /\n/.test(title);
|
var ifTitleSetAlready = /\n/.test(title);
|
||||||
var proxyHost = window.antiCensorRu.pacProvider.proxyIps[ requestDetails.ip ];
|
var proxyHost = window.antiCensorRu.pacProvider.proxyIps[ requestDetails.ip ];
|
||||||
var hostname = getHostname(requestDetails.url);
|
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.href = requestDetails.url;
|
||||||
|
var hostname = a.hostname;
|
||||||
|
|
||||||
var ifShouldUpdateTitle = false;
|
var ifShouldUpdateTitle = false;
|
||||||
var indent = ' ';
|
var indent = ' ';
|
||||||
var proxyTitle = 'Прокси:';
|
var proxyTitle = 'Прокси:';
|
||||||
|
|
||||||
// Initially title equals extension name.
|
|
||||||
if (!ifTitleSetAlready) {
|
if (!ifTitleSetAlready) {
|
||||||
title = 'Разблокированы:\n'+ indent + hostname +'\n'+ proxyTitle +'\n'+ indent + proxyHost;
|
title = 'Разблокированы:\n'+ indent + hostname +'\n'+ proxyTitle +'\n'+ indent + proxyHost;
|
||||||
ifShouldUpdateTitle = true;
|
ifShouldUpdateTitle = true;
|
||||||
|
|
||||||
function setIcon(iconOpts) {
|
chrome.browserAction.setBadgeText({
|
||||||
iconOpts.tabId = requestDetails.tabId;
|
tabId: requestDetails.tabId,
|
||||||
chrome.pageAction.setIcon(iconOpts);
|
text: requestDetails.type === 'main_frame' ? '1' : '%1'
|
||||||
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 {
|
} else {
|
||||||
var hostsProxiesPair = title.split(proxyTitle);
|
var hostsProxiesPair = title.split(proxyTitle);
|
||||||
|
|
||||||
|
@ -67,87 +78,39 @@ function updateTitle(requestDetails, cb) {
|
||||||
if (hostsProxiesPair[0].indexOf(hostname) === -1) {
|
if (hostsProxiesPair[0].indexOf(hostname) === -1) {
|
||||||
title = title.replace(proxyTitle, indent + hostname +'\n'+ proxyTitle);
|
title = title.replace(proxyTitle, indent + hostname +'\n'+ proxyTitle);
|
||||||
ifShouldUpdateTitle = true;
|
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)
|
if (ifShouldUpdateTitle)
|
||||||
chrome.pageAction.setTitle({
|
chrome.browserAction.setTitle({
|
||||||
title: title,
|
title: title,
|
||||||
tabId: requestDetails.tabId
|
tabId: requestDetails.tabId
|
||||||
});
|
});
|
||||||
|
|
||||||
return cb();
|
return cb();
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var previousUpdateTitleFinished = Promise.resolve();
|
chrome.webRequest.onResponseStarted.addListener(
|
||||||
/*
|
|
||||||
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 ]) {
|
|
||||||
|
|
||||||
previousUpdateTitleFinished = previousUpdateTitleFinished.then(
|
|
||||||
() => new Promise( resolve => updateTitle( details, resolve ) )
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
chrome.webRequest.onCompleted.addListener(
|
|
||||||
blockInform,
|
blockInform,
|
||||||
{ urls: ['<all_urls>'] }
|
{ urls: ['<all_urls>'] }
|
||||||
);
|
);
|
||||||
|
|
|
@ -15,12 +15,13 @@
|
||||||
"webRequest",
|
"webRequest",
|
||||||
"alarms",
|
"alarms",
|
||||||
"storage",
|
"storage",
|
||||||
"<all_urls>"
|
"<all_urls>",
|
||||||
|
"tabs"
|
||||||
],
|
],
|
||||||
"background": {
|
"background": {
|
||||||
"scripts": ["sync-pac-script-with-pac-provider.js", "block-informer.js"]
|
"scripts": ["sync-pac-script-with-pac-provider.js", "block-informer.js"]
|
||||||
},
|
},
|
||||||
"page_action": {
|
"browser_action": {
|
||||||
"default_popup": "/pages/choose-pac-provider/index.html"
|
"default_popup": "/pages/choose-pac-provider/index.html"
|
||||||
},
|
},
|
||||||
"options_ui": {
|
"options_ui": {
|
||||||
|
|
|
@ -18,8 +18,10 @@ function renderPage() {
|
||||||
status.classList.add('off');
|
status.classList.add('off');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('ABC');
|
||||||
chrome.runtime.getBackgroundPage( backgroundPage => {
|
chrome.runtime.getBackgroundPage( backgroundPage => {
|
||||||
|
|
||||||
|
backgroundPage.console.log('Options page opened.');
|
||||||
var antiCensorRu = backgroundPage.antiCensorRu;
|
var antiCensorRu = backgroundPage.antiCensorRu;
|
||||||
|
|
||||||
// SET DATE
|
// SET DATE
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
In background scripts use window.antiCensorRu public variables.
|
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,
|
In pages window.antiCensorRu are not accessible,
|
||||||
use chrome.runtime.getBackgroundPage(..),
|
use chrome.runtime.getBackgroundPage(..),
|
||||||
avoid old extension.getBackgroundPage.
|
avoid old extension.getBackgroundPage.
|
||||||
|
@ -97,45 +96,6 @@ window.antiCensorRu = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
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) {
|
syncWithPacProvider(cb) {
|
||||||
var cb = cb || (() => {});
|
var cb = cb || (() => {});
|
||||||
|
|
||||||
|
@ -179,15 +139,13 @@ window.antiCensorRu = {
|
||||||
|
|
||||||
var cb = asyncLogGroup('Installing PAC...', cb);
|
var cb = asyncLogGroup('Installing PAC...', cb);
|
||||||
|
|
||||||
chrome.alarms.clear(
|
chrome.alarms.create(
|
||||||
this._periodicUpdateAlarmReason,
|
|
||||||
() => chrome.alarms.create(
|
|
||||||
this._periodicUpdateAlarmReason,
|
this._periodicUpdateAlarmReason,
|
||||||
{ periodInMinutes: 4*60 }
|
{ periodInMinutes: 4*60 }
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this.syncWithPacProvider(cb);
|
return this.syncWithPacProvider(cb);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
clearPac(cb) {
|
clearPac(cb) {
|
||||||
|
@ -205,64 +163,86 @@ window.antiCensorRu = {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ON EACH LAUNCH OF EXTENSION
|
// ON EACH LAUNCH, STARTUP, RELOAD, UPDATE, ENABLE
|
||||||
// Not only on Chrome's startUp, but aslo on Enable/Disable
|
chrome.storage.local.get(null, oldStorage => {
|
||||||
|
|
||||||
window.storageSyncedPromise = new Promise(
|
console.log('Init on storage:', oldStorage);
|
||||||
(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 => {
|
|
||||||
|
|
||||||
|
// Finish each init with this callback setting alarm listeners.
|
||||||
|
function cb(err) {
|
||||||
chrome.alarms.onAlarm.addListener(
|
chrome.alarms.onAlarm.addListener(
|
||||||
alarm => {
|
alarm => {
|
||||||
if (alarm.name === window.antiCensorRu._periodicUpdateAlarmReason) {
|
if (alarm.name === antiCensorRu._periodicUpdateAlarmReason) {
|
||||||
console.log('Periodic update triggered:', new Date());
|
console.log('Periodic update triggered:', new Date());
|
||||||
window.antiCensorRu.syncWithPacProvider();
|
antiCensorRu.syncWithPacProvider();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
console.log('Alarm listener installed. We won\'t miss any PAC update.');
|
console.log('Alarm listener installed. We won\'t miss any PAC update.');
|
||||||
|
|
||||||
chrome.alarms.get(
|
chrome.alarms.get(
|
||||||
window.antiCensorRu._periodicUpdateAlarmReason,
|
antiCensorRu._periodicUpdateAlarmReason,
|
||||||
alarm => alarm && console.log(
|
alarm => {
|
||||||
|
if (!alarm)
|
||||||
|
return console.error('ALARM NOT SET');
|
||||||
|
console.log(
|
||||||
'Next update is scheduled on', new Date(alarm.scheduledTime).toLocaleString('ru-RU')
|
'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 ) );
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
/*
|
||||||
);
|
|
||||||
|
|
||||||
chrome.runtime.onInstalled.addListener( installDetails => {
|
History of Changes to Storage (Migration Guide)
|
||||||
console.log('Extension just installed, reason:', installDetails.reason);
|
-----------------------------------------------
|
||||||
window.storageSyncedPromise.then(
|
|
||||||
storage => {
|
|
||||||
|
|
||||||
switch(installDetails.reason) {
|
Version 0.0.0.10
|
||||||
case 'update':
|
|
||||||
console.log('Update or reload. Do nothing.');
|
|
||||||
break;
|
|
||||||
case 'install':
|
|
||||||
window.antiCensorRu.ifFirstInstall = true;
|
|
||||||
chrome.runtime.openOptionsPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
* 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
|
// PRIVATE
|
||||||
|
@ -355,7 +335,6 @@ function setPacScriptFromProvider(provider, cb) {
|
||||||
console.log('Setting chrome proxy settings...');
|
console.log('Setting chrome proxy settings...');
|
||||||
chrome.proxy.settings.set( {value: config}, cb );
|
chrome.proxy.settings.set( {value: config}, cb );
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user