2015-12-20 23:28:41 +03:00
'use strict' ;
/ *
Task 1. Gets IP for host proxy . antizapret . prostovpn . org with dns - lg . com .
This IP is used in block - informer to inform user when proxy is ON .
Task 2. Downloads PAC proxy script from Antizapret and sets it in Chromium settings .
Task 3. Schedules tasks 1 & 2 for every 2 hours .
* /
/ *
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 .
* /
window . antiCensorRu = {
// PUBLIC
pacProviders : {
Антизапрет : {
pacUrl : 'http://antizapret.prostovpn.org/proxy.pac' ,
2016-01-17 22:27:54 +03:00
proxyHosts : [ 'proxy.antizapret.prostovpn.org' ] ,
proxyIps : { '195.154.110.37' : true }
2015-12-20 23:28:41 +03:00
} ,
Антиценз : {
pacUrl : 'https://config.anticenz.org/proxy.pac' ,
2016-01-18 00:09:55 +03:00
proxyHosts : [ 'gw2.anticenz.org' ] ,
proxyIps : { '185.120.5.7' : true }
2016-01-17 22:27:54 +03:00
} ,
О б а _и _на _с витча х : {
pacUrl : 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0akpCOURNS2VCTmc' ,
2016-01-18 00:09:55 +03:00
proxyHosts : [ 'gw2.anticenz.org' , 'proxy.antizapret.prostovpn.org' ] ,
proxyIps : { '195.154.110.37' : true , '185.120.5.7' : true }
2015-12-20 23:28:41 +03:00
}
} ,
2016-01-17 22:27:54 +03:00
_currentPacProviderKey : 'О б а _и_на _с витча х ' ,
2015-12-20 23:28:41 +03:00
get currentPacProviderKey ( ) { return this . _currentPacProviderKey } ,
set currentPacProviderKey ( newKey ) {
if ( newKey && ! this . pacProviders [ newKey ] )
throw new IllegalArgumentException ( 'No provider for key:' + newKey ) ;
this . _currentPacProviderKey = newKey ;
} ,
get pacProvider ( ) { return this . pacProviders [ this . currentPacProviderKey ] } ,
2016-01-26 19:47:09 +03:00
/ *
Offer PAC choice if this is the first time extension was installed .
* /
ifFirstInstall : true ,
2015-12-20 23:28:41 +03:00
// PROTECTED
pushToStorage ( cb ) {
// Copy only settable properties.
var onlySettable = { } ;
for ( var key of Object . keys ( this ) )
if ( Object . getOwnPropertyDescriptor ( this , key ) . writable && typeof ( this [ key ] ) !== 'function' )
onlySettable [ key ] = this [ key ]
2016-01-26 19:47:09 +03:00
return chrome . storage . local . set ( onlySettable , ( ) => cb && cb ( chrome . runtime . lastError , onlySettable ) ) ;
2015-12-20 23:28:41 +03:00
} ,
pullFromStorage ( cb ) {
chrome . storage . local . get ( null , storage => {
for ( var key of Object . keys ( storage ) )
this [ key ] = storage [ key ] ;
2016-01-26 19:05:23 +03:00
console . log ( 'Synced with storage, any callback?' , ! ! cb ) ;
2015-12-20 23:28:41 +03:00
if ( cb )
2016-01-26 18:50:25 +03:00
cb ( chrome . runtime . lastError , storage ) ;
2015-12-20 23:28:41 +03:00
} ) ;
} ,
2016-01-26 13:38:40 +03:00
lastPacUpdateStamp : 0 ,
2015-12-20 23:28:41 +03:00
syncWithPacProvider ( cb ) {
2016-01-26 23:05:21 +03:00
var cb = cb || ( ( ) => { } ) ;
var pacSetPromise = new Promise (
( resolve , reject ) => setPacScriptFromProvider (
this . pacProvider ,
( err , res ) => {
if ( err )
return reject ( err ) ;
2016-01-26 13:38:40 +03:00
this . lastPacUpdateStamp = Date . now ( ) ;
2016-01-26 23:05:21 +03:00
this . ifFirstInstall = false ;
return resolve ( res ) ;
}
)
) ;
return updatePacProxyIps (
this . pacProvider ,
ipsError => {
if ( ipsError && ipsError . clarification )
ipsError . clarification . ifNotCritical = true ;
pacSetPromise . then (
res => this . pushToStorage (
pushError => pushError ? cb ( pushError ) : cb ( ipsError , res )
) ,
err => cb ( err )
)
}
) ;
2015-12-20 23:28:41 +03:00
} ,
2016-01-18 00:09:55 +03:00
_periodicUpdateAlarmReason : 'Периодичное обновление PAC-скрипта Антизапрет' ,
2015-12-20 23:28:41 +03:00
installPac ( key , cb ) {
2016-01-17 22:27:54 +03:00
2015-12-20 23:28:41 +03:00
if ( typeof ( key ) === 'function' ) {
cb = key ;
key = undefined ;
}
if ( key )
this . currentPacProviderKey = key ;
var cb = asyncLogGroup ( 'Installing PAC...' , cb ) ;
2016-01-18 00:09:55 +03:00
chrome . alarms . clear ( this . _periodicUpdateAlarmReason ,
( ) => chrome . alarms . create ( this . _periodicUpdateAlarmReason , {
periodInMinutes : 4 * 60
} )
2015-12-20 23:28:41 +03:00
) ;
this . syncWithPacProvider ( cb ) ;
} ,
clearPac ( cb ) {
var cb = asyncLogGroup ( 'Cearing PAC...' , cb ) ;
chrome . alarms . clearAll ( ( ) => chrome . proxy . settings . clear (
{ } ,
( ) => {
this . currentPacProviderKey = undefined ;
return this . pushToStorage ( cb ) ;
} )
) ;
}
} ;
2016-01-26 18:50:25 +03:00
// ON EACH LAUNCH OF EXTENSION
window . storageSyncedPromise = new Promise (
( resolve , reject ) => window . antiCensorRu . pullFromStorage (
( err , res ) => err ? reject ( err ) : resolve ( res )
)
) ;
window . storageSyncedPromise . then (
storage => {
chrome . alarms . onAlarm . addListener (
alarm => {
if ( alarm . name === window . antiCensorRu . _periodicUpdateAlarmReason ) {
console . log ( 'Periodic update triggered:' , new Date ( ) ) ;
window . antiCensorRu . syncWithPacProvider ( ) ;
}
}
) ;
2016-01-26 19:05:23 +03:00
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' )
)
) ;
2016-01-26 18:50:25 +03:00
}
) ;
2015-12-20 23:28:41 +03:00
chrome . runtime . onInstalled . addListener ( details => {
2016-01-26 19:05:23 +03:00
console . log ( 'Extension just installed, reason:' , details . reason ) ;
2016-01-26 18:50:25 +03:00
window . storageSyncedPromise . then (
storage => {
switch ( details . reason ) {
case 'update' :
2016-01-26 19:05:23 +03:00
console . log ( 'Ah, it\'s just an update or reload. Do nothing.' ) ;
//window.antiCensorRu.installPac();
2016-01-26 18:50:25 +03:00
break ;
case 'install' :
2016-01-26 19:47:09 +03:00
window . antiCensorRu . ifFirstInstall = true ;
2016-01-26 18:50:25 +03:00
chrome . runtime . openOptionsPage ( ) ;
2016-01-18 00:09:55 +03:00
}
}
2016-01-26 18:50:25 +03:00
)
2015-12-20 23:28:41 +03:00
} ) ;
// PRIVATE
function asyncLogGroup ( ) {
var args = [ ] . slice . apply ( arguments ) ;
var cb = args . pop ( ) ;
console . group . apply ( console , args ) ;
return function ( ) {
console . log ( 'Finished' ) ;
console . groupEnd ( ) ;
var _cb = cb || ( ( ) => { } ) ;
return _cb . apply ( this , arguments ) ;
}
}
2016-01-26 23:05:21 +03:00
function ifSuccessfulCode ( status ) {
return status >= 200 && status < 300 || status === 304 ;
}
2015-12-20 23:28:41 +03:00
function httpGet ( url , cb ) {
var cb = cb || ( ( ) => { } ) ;
var req = new XMLHttpRequest ( ) ;
var ifAsync = true ;
req . open ( 'GET' , url , ifAsync ) ;
req . onload = event => {
2016-01-26 23:05:21 +03:00
if ( ! ifSuccessfulCode ( req . status ) ) {
req . clarification = { message : 'Получен ответ с неудачным HTTP-кодом ' + req . status + '.' } ;
return cb ( req ) ;
}
2015-12-20 23:28:41 +03:00
console . log ( 'GETed with success.' ) ;
return cb ( null , req . responseText )
} ;
2016-01-26 23:05:21 +03:00
req . onerror = event => { event . clarification = { message : 'Что-то не так с сетью, проверьте соединение.' } ; return cb ( event ) ; } ;
2015-12-20 23:28:41 +03:00
req . send ( ) ;
}
2016-01-17 22:27:54 +03:00
function updatePacProxyIps ( provider , cb ) {
if ( ! provider . proxyHosts ) {
console . log ( provider + ' has no proxies defined.' ) ;
return cb ( null , null ) ;
}
var cb = asyncLogGroup ( 'Getting IP for ' + provider . proxyHosts . join ( ', ' ) + '...' , cb ) ;
2016-01-26 23:05:21 +03:00
var failure = {
clarification : { message : 'Н е удалось получить один или несколько IP адресов для прокси-серверов. Иконка для уведомления о б обходе блокировок может не отображаться.' } ,
errors : { }
} ;
2016-01-17 22:27:54 +03:00
var i = 0 ;
for ( var proxyHost of provider . proxyHosts ) {
httpGet (
'http://www.dns-lg.com/google1/' + proxyHost + '/A' ,
( err , res ) => {
if ( ! err ) {
provider . proxyIps = provider . proxyIps || { } ;
provider . proxyIps [ JSON . parse ( res ) . answer [ 0 ] . rdata ] = true ;
2016-01-26 23:05:21 +03:00
} else
failure . errors [ proxyHost ] = err ;
if ( ++ i == provider . proxyHosts . length ) {
failure = Object . keys ( failure . errors ) . length ? failure : null ;
return cb ( failure , provider . proxyIps ) ;
2016-01-17 22:27:54 +03:00
}
}
) ;
}
2015-12-20 23:28:41 +03:00
}
function setPacScriptFromProvider ( provider , cb ) {
var cb = asyncLogGroup ( 'Getting pac script from provider...' , provider . pacUrl , cb ) ;
2016-01-17 22:27:54 +03:00
2015-12-20 23:28:41 +03:00
httpGet (
provider . pacUrl ,
( err , res ) => {
2016-01-26 23:05:21 +03:00
if ( err ) {
err . clarification = {
message : 'Н е удалось скачать PAC-скрипт с адреса: ' + provider . pacUrl + '.' ,
prev : err . clarification
} ;
2015-12-20 23:28:41 +03:00
return cb ( err ) ;
2016-01-26 23:05:21 +03:00
}
2015-12-20 23:28:41 +03:00
console . log ( 'Clearing chrome proxy settings...' ) ;
return chrome . proxy . settings . clear ( { } , ( ) => {
var config = {
mode : 'pac_script' ,
pacScript : {
mandatory : false ,
data : res
}
} ;
console . log ( 'Setting chrome proxy settings...' ) ;
chrome . proxy . settings . set ( { value : config } , cb ) ;
} ) ;
}
) ;
}