2015-12-20 23:28:41 +03:00
'use strict' ;
/ *
2016-05-08 19:14:08 +03:00
Task 1. Gets IPs for proxies of antizapret / anticenz via dns over https .
2016-02-12 19:00:40 +03:00
These IPs are used in block - informer to inform user when proxy is ON .
Task 2. Downloads PAC proxy script from antizapret / anticenz / my Google Drive and sets it in Chromium settings .
Task 3. Schedules tasks 1 & 2 for every 4 hours .
2015-12-20 23:28:41 +03:00
* /
/ *
In background scripts use window . antiCensorRu public variables .
2016-05-15 16:08:23 +03:00
In pages window . antiCensorRu is not accessible ,
2015-12-20 23:28:41 +03:00
use chrome . runtime . getBackgroundPage ( . . ) ,
2016-05-08 19:14:08 +03:00
extension . getBackgroundPage is deprecated
2015-12-20 23:28:41 +03:00
* /
window . antiCensorRu = {
2016-02-08 12:55:41 +03:00
version : chrome . runtime . getManifest ( ) . version ,
2015-12-20 23:28:41 +03:00
pacProviders : {
Антизапрет : {
2016-04-10 12:39:11 +03:00
pacUrl : 'https://antizapret.prostovpn.org/proxy.pac' ,
2016-01-17 22:27:54 +03:00
proxyHosts : [ 'proxy.antizapret.prostovpn.org' ] ,
2016-02-08 12:55:41 +03:00
proxyIps : {
2016-05-15 16:08:23 +03:00
'195.123.209.38' : 'proxy.antizapret.prostovpn.org' ,
'2a02:27ac::10' : 'proxy.antizapret.prostovpn.org'
2016-02-08 12:55:41 +03:00
}
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' ] ,
2016-02-08 12:55:41 +03:00
proxyIps : {
'5.196.220.114' : 'gw2.anticenz.org'
}
2016-01-17 22:27:54 +03:00
} ,
О б а _и _на _с витча х : {
2016-11-12 17:35:50 +03:00
//pacUrl: 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0akpCOURNS2VCTmc',
pacUrl : 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0WGczNmJzY3gzMWc' , // Beta
2016-02-13 18:53:27 +03:00
proxyHosts : [ 'proxy.antizapret.prostovpn.org' , 'gw2.anticenz.org' ] ,
2016-02-08 12:55:41 +03:00
proxyIps : {
2016-02-13 18:53:27 +03:00
'195.123.209.38' : 'proxy.antizapret.prostovpn.org' ,
2016-05-15 16:08:23 +03:00
'2a02:27ac::10' : 'proxy.antizapret.prostovpn.org' ,
'5.196.220.114' : 'gw2.anticenz.org'
2016-02-08 12:55:41 +03:00
}
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 ) {
2016-05-15 16:08:23 +03:00
2015-12-20 23:28:41 +03:00
if ( newKey && ! this . pacProviders [ newKey ] )
2016-05-08 19:14:08 +03:00
throw new IllegalArgumentException ( 'No provider for key:' + newKey ) ;
2015-12-20 23:28:41 +03:00
this . _currentPacProviderKey = newKey ;
} ,
get pacProvider ( ) { return this . pacProviders [ this . currentPacProviderKey ] } ,
2016-01-26 19:47:09 +03:00
/ *
2016-02-08 12:55:41 +03:00
Is it the first time extension installed ? Do something , e . g . initiate PAC sync .
2016-01-26 19:47:09 +03:00
* /
2016-02-08 12:55:41 +03:00
ifFirstInstall : false ,
lastPacUpdateStamp : 0 ,
2015-12-20 23:28:41 +03:00
2016-02-08 12:55:41 +03:00
_periodicUpdateAlarmReason : 'Периодичное обновление PAC-скрипта Антизапрет' ,
2015-12-20 23:28:41 +03:00
pushToStorage ( cb ) {
2016-05-15 16:08:23 +03:00
console . log ( 'Pushing to storage...' ) ;
// Copy only settable properties (except functions).
const onlySettable = { } ;
for ( const key of Object . keys ( this ) ) {
if ( Object . getOwnPropertyDescriptor ( this , key ) . writable && typeof ( this [ key ] ) !== 'function' ) {
onlySettable [ key ] = this [ key ] ;
}
}
2016-02-05 19:11:19 +03:00
return chrome . storage . local . clear (
2016-02-08 12:55:41 +03:00
( ) => chrome . storage . local . set (
onlySettable ,
( ) => cb && cb ( chrome . runtime . lastError , onlySettable )
)
) ;
2016-02-13 18:53:27 +03:00
2015-12-20 23:28:41 +03:00
} ,
pullFromStorage ( cb ) {
2016-05-15 16:08:23 +03:00
chrome . storage . local . get ( null , ( storage ) => {
console . log ( 'Pulled from storage:' , storage ) ;
for ( const key of Object . keys ( storage ) ) {
2015-12-20 23:28:41 +03:00
this [ key ] = storage [ key ] ;
2016-05-15 16:08:23 +03:00
}
2015-12-20 23:28:41 +03:00
2016-01-26 19:05:23 +03:00
console . log ( 'Synced with storage, any callback?' , ! ! cb ) ;
2016-05-15 16:08:23 +03:00
if ( cb ) {
2016-01-26 18:50:25 +03:00
cb ( chrome . runtime . lastError , storage ) ;
2016-05-15 16:08:23 +03:00
}
2015-12-20 23:28:41 +03:00
} ) ;
} ,
2016-01-26 13:38:40 +03:00
2015-12-20 23:28:41 +03:00
syncWithPacProvider ( cb ) {
2016-05-15 16:08:23 +03:00
cb = asyncLogGroup ( 'Syncing with PAC provider...' , cb ) ;
if ( ! this . pacProvider ) {
2016-03-24 19:11:36 +03:00
return cb ( { clarification : { message : 'Сперва выберите PAC-провайдера.' } } ) ;
2016-05-15 16:08:23 +03:00
}
2016-01-26 23:05:21 +03:00
var pacSetPromise = new Promise (
( resolve , reject ) => setPacScriptFromProvider (
this . pacProvider ,
( err , res ) => {
2016-05-15 16:08:23 +03:00
if ( err ) {
2016-01-26 23:05:21 +03:00
return reject ( err ) ;
2016-05-15 16:08:23 +03:00
}
2016-04-10 12:39:11 +03:00
2016-01-26 13:38:40 +03:00
this . lastPacUpdateStamp = Date . now ( ) ;
2016-01-26 23:05:21 +03:00
this . ifFirstInstall = false ;
2016-02-13 18:53:27 +03:00
this . setAlarms ( ) ;
2016-01-26 23:05:21 +03:00
return resolve ( res ) ;
}
)
) ;
return updatePacProxyIps (
this . pacProvider ,
2016-05-15 16:08:23 +03:00
( ipsError ) => {
if ( ipsError && ipsError . clarification ) {
2016-01-26 23:05:21 +03:00
ipsError . clarification . ifNotCritical = true ;
2016-05-15 16:08:23 +03:00
}
2016-01-26 23:05:21 +03:00
pacSetPromise . then (
2016-05-15 16:08:23 +03:00
( res ) => this . pushToStorage (
( pushError ) => pushError ? cb ( pushError ) : cb ( ipsError , res )
2016-01-26 23:05:21 +03:00
) ,
2016-05-15 16:08:23 +03:00
cb
2016-01-26 23:05:21 +03:00
)
}
) ;
2015-12-20 23:28:41 +03:00
} ,
2016-05-08 19:14:08 +03:00
2016-02-13 18:53:27 +03:00
_pacUpdatePeriodInMinutes : 4 * 60 ,
2016-02-12 19:00:40 +03:00
setAlarms ( ) {
2016-02-13 18:53:27 +03:00
2016-05-15 16:08:23 +03:00
let nextUpdateMoment = this . lastPacUpdateStamp + this . _pacUpdatePeriodInMinutes * 60 * 1000 ;
const now = Date . now ( ) ;
2016-02-13 18:53:27 +03:00
if ( nextUpdateMoment < now )
nextUpdateMoment = now ;
2016-03-24 19:11:36 +03:00
2016-02-13 18:53:27 +03:00
console . log ( 'Next PAC update is scheduled on' , new Date ( nextUpdateMoment ) . toLocaleString ( 'ru-RU' ) ) ;
2016-02-12 19:00:40 +03:00
chrome . alarms . create (
this . _periodicUpdateAlarmReason ,
2016-02-13 18:53:27 +03:00
{
when : nextUpdateMoment ,
periodInMinutes : this . _pacUpdatePeriodInMinutes
}
2016-02-12 19:00:40 +03:00
) ;
2016-02-13 18:53:27 +03:00
2016-05-08 19:14:08 +03:00
return nextUpdateMoment === now ; // ifAlarmTriggered. May be changed in the future.
2016-02-12 19:00:40 +03:00
} ,
2015-12-20 23:28:41 +03:00
installPac ( key , cb ) {
2016-05-15 16:08:23 +03:00
2016-02-08 12:55:41 +03:00
if ( typeof ( key ) === 'function' ) {
cb = key ;
key = undefined ;
}
2015-12-20 23:28:41 +03:00
2016-05-15 16:08:23 +03:00
if ( key ) {
2016-02-08 12:55:41 +03:00
this . currentPacProviderKey = key ;
2016-05-15 16:08:23 +03:00
}
2015-12-20 23:28:41 +03:00
2016-02-11 23:07:39 +03:00
return this . syncWithPacProvider ( cb ) ;
2015-12-20 23:28:41 +03:00
} ,
clearPac ( cb ) {
2016-05-15 16:08:23 +03:00
cb = asyncLogGroup ( 'Cearing alarms and PAC...' , cb ) ;
2016-02-08 12:55:41 +03:00
chrome . alarms . clearAll (
( ) => chrome . proxy . settings . clear (
{ } ,
( ) => {
2016-05-15 16:08:23 +03:00
2016-02-08 12:55:41 +03:00
this . currentPacProviderKey = undefined ;
return this . pushToStorage ( cb ) ;
}
)
) ;
2015-12-20 23:28:41 +03:00
}
} ;
2016-05-08 19:14:08 +03:00
// ON EACH LAUNCH, STARTUP, RELOAD, UPDATE, ENABLE
2016-05-15 16:08:23 +03:00
chrome . storage . local . get ( null , ( oldStorage ) => {
2016-01-26 18:50:25 +03:00
2016-02-11 23:07:39 +03:00
console . log ( 'Init on storage:' , oldStorage ) ;
2016-02-12 19:00:40 +03:00
antiCensorRu . ifFirstInstall = Object . keys ( oldStorage ) . length === 0 ;
2016-02-08 12:55:41 +03:00
2016-02-13 18:53:27 +03:00
if ( ! antiCensorRu . ifFirstInstall ) {
// LAUNCH, RELOAD, UPDATE
antiCensorRu . _currentPacProviderKey = oldStorage . _currentPacProviderKey ;
antiCensorRu . lastPacUpdateStamp = oldStorage . lastPacUpdateStamp || antiCensorRu . lastPacUpdateStamp ;
2016-03-24 19:11:36 +03:00
console . log ( 'Last PAC update was on' , new Date ( antiCensorRu . lastPacUpdateStamp ) . toLocaleString ( 'ru-RU' ) ) ;
2016-02-11 23:07:39 +03:00
}
2016-02-08 12:55:41 +03:00
2016-02-13 18:53:27 +03:00
chrome . alarms . onAlarm . addListener (
2016-05-15 16:08:23 +03:00
( alarm ) => {
2016-02-13 18:53:27 +03:00
if ( alarm . name === antiCensorRu . _periodicUpdateAlarmReason ) {
console . log ( 'Periodic PAC update triggered:' , new Date ( ) . toLocaleString ( 'ru-RU' ) ) ;
2016-05-15 16:08:23 +03:00
antiCensorRu . syncWithPacProvider ( /* Swallows errors. */ ) ;
2016-02-13 18:53:27 +03:00
}
}
) ;
console . log ( 'Alarm listener installed. We won\'t miss any PAC update.' ) ;
2016-05-08 19:14:08 +03:00
2016-02-11 23:07:39 +03:00
if ( antiCensorRu . ifFirstInstall ) {
2016-02-13 18:53:27 +03:00
// INSTALL
2016-02-11 23:07:39 +03:00
console . log ( 'Installing...' ) ;
2016-02-13 18:53:27 +03:00
return chrome . runtime . openOptionsPage ( ) ;
2016-01-26 18:50:25 +03:00
}
2016-02-08 12:55:41 +03:00
2016-05-15 16:08:23 +03:00
if ( ! antiCensorRu . pacProvider ) {
2016-02-13 18:53:27 +03:00
return console . log ( 'No PAC provider set. Do nothing.' ) ;
2016-05-15 16:08:23 +03:00
}
2016-02-13 18:53:27 +03:00
2016-05-08 19:14:08 +03:00
/ *
2016-02-11 23:07:39 +03:00
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 .
* /
2016-05-15 16:08:23 +03:00
const ifAlarmTriggered = antiCensorRu . setAlarms ( ) ;
2016-05-08 19:14:08 +03:00
2016-02-11 23:07:39 +03:00
if ( antiCensorRu . version === oldStorage . version ) {
2016-03-24 19:11:36 +03:00
// LAUNCH, RELOAD, ENABLE
2016-02-13 18:53:27 +03:00
antiCensorRu . pacProviders = oldStorage . pacProviders ;
return console . log ( 'Extension launched, reloaded or enabled.' ) ;
2016-02-11 23:07:39 +03:00
}
2016-02-12 19:00:40 +03:00
2016-02-11 23:07:39 +03:00
// UPDATE & MIGRATION
2016-02-13 18:53:27 +03:00
console . log ( 'Extension updated.' ) ;
2016-05-15 16:08:23 +03:00
if ( ! ifAlarmTriggered ) {
2016-02-12 19:00:40 +03:00
updatePacProxyIps (
antiCensorRu . pacProvider ,
2016-05-15 16:08:23 +03:00
( ipsError ) => ipsError ? console . error ( 'Error updating IPs:' , ipsError ) : antiCensorRu . pushToStorage ( /* Swallows errors. */ )
2016-02-12 19:00:40 +03:00
) ;
2016-05-15 16:08:23 +03:00
}
2016-02-11 23:07:39 +03:00
/ *
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
* * /
2015-12-20 23:28:41 +03:00
} ) ;
function asyncLogGroup ( ) {
2016-05-15 16:08:23 +03:00
const args = [ ] . slice . apply ( arguments ) ;
const cb = args . pop ( ) || ( ( ) => { } ) ;
2015-12-20 23:28:41 +03:00
console . group . apply ( console , args ) ;
return function ( ) {
2016-05-15 16:08:23 +03:00
2015-12-20 23:28:41 +03:00
console . groupEnd ( ) ;
2016-02-13 18:53:27 +03:00
console . log ( 'Group finished.' ) ;
2016-05-15 16:08:23 +03:00
return cb . apply ( this , arguments ) ;
2016-11-12 17:35:50 +03:00
2015-12-20 23:28:41 +03:00
}
}
2016-03-24 19:11:36 +03:00
function httpGet ( url , cb ) {
2016-05-15 16:08:23 +03:00
const start = Date . now ( ) ;
2016-03-24 19:11:36 +03:00
return fetch ( url ) . then (
2016-05-15 16:08:23 +03:00
( res ) => {
const textCb = ( err ) => cb && res . text ( ) . then ( text => cb ( err , text ) , cb ) ;
const status = res . status ;
2016-03-24 19:11:36 +03:00
if ( ! ( status >= 200 && status < 300 || status === 304 ) ) {
2016-05-15 16:08:23 +03:00
res . clarification = { message : 'Получен ответ с неудачным HTTP-кодом ' + status + '.' } ;
2016-03-24 19:11:36 +03:00
return textCb ( res ) ;
}
2016-05-15 16:08:23 +03:00
console . log ( 'GETed with success:' , url , Date . now ( ) - start ) ;
2016-03-24 19:11:36 +03:00
return textCb ( ) ;
} ,
2016-05-15 16:08:23 +03:00
( err ) => {
2016-03-24 19:11:36 +03:00
err . clarification = { message : 'Что-то не так с сетью, проверьте соединение.' } ;
return cb && cb ( err ) ;
}
) ;
2016-01-26 23:05:21 +03:00
}
2016-05-15 16:08:23 +03:00
function getOneDnsRecord ( args , cb ) {
2016-05-08 19:14:08 +03:00
2016-05-15 16:08:23 +03:00
// args: { host:..., type: 'AAAA', filter: ['AAAA'] }
if ( ! ( args . host && args . type && cb ) ) {
throw new Error ( 'Wrong args:' + host + ',' + type ) ;
}
2016-05-08 19:14:08 +03:00
const type2str = {
// https://en.wikipedia.org/wiki/List_of_DNS_record_types
2016-05-15 16:08:23 +03:00
// A, AAAA may be localized (github, e.g.), but you may use ANY
1 : 'A' , // IPv4
28 : 'AAAA' , // IPv6
2016-05-08 19:14:08 +03:00
2 : 'NS' ,
2016-05-15 16:08:23 +03:00
5 : 'CNAME' , // Synonyms, returned by server together with A/AAAA.
255 : 'ANY' // Deprecated on some servers, not recommended
2016-05-08 19:14:08 +03:00
} ;
httpGet (
2016-05-15 16:08:23 +03:00
'https://dns.google.com/resolve?type=' + args . type + '&name=' + args . host ,
2016-05-08 19:14:08 +03:00
( err , res ) => {
if ( res ) {
try {
res = JSON . parse ( res ) ;
2016-05-15 16:08:23 +03:00
console . log ( 'Json parsed.' ) ;
2016-05-08 19:14:08 +03:00
if ( err || res . Status ) {
const msg = [ 'Answer' , 'Comment' , 'Status' ]
. filter ( ( prop ) => res [ prop ] )
2016-05-15 16:08:23 +03:00
. map ( ( prop ) => prop + ': ' + JSON . stringify ( res [ prop ] ) )
2016-05-08 19:14:08 +03:00
. join ( ', \n' ) ;
2016-05-15 16:08:23 +03:00
err . clarification . message += ' Сервер (json): ' + msg ;
2016-05-08 19:14:08 +03:00
err . data = err . data || res ;
}
else {
2016-05-15 16:08:23 +03:00
res = res . Answer || [ ] ;
for ( const record of res ) {
record . type = type2str [ record . type ] ;
}
if ( args . filter ) {
res = res . filter ( ( record ) => args . filter . indexOf ( record . type ) > - 1 ) ;
2016-05-08 19:14:08 +03:00
}
}
}
catch ( e ) {
2016-05-15 16:08:23 +03:00
err = e || err || { clarification : { message : '' } } ;
err . clarification = err . clarification || { message : '' } ;
err . clarification . message += ' Сервер (текст): ' + res ;
2016-05-08 19:14:08 +03:00
err . clarification . message . trim ( ) ;
err . data = err . data || res ;
}
}
return cb ( err , res ) ;
}
) ;
2016-05-15 16:08:23 +03:00
} ;
function getDnsRecords ( args , cb ) {
/ *
Example of input :
{
// Required
host : 'proxy.navalny.cia.gov' ,
// Optional
types : {
string : [ 'A' , 'AAAA' ] , // <- Default. Makes one request per each type.
filter : [ 'A' , 'AAAA' ] , // <- Default. E.g., you want to get rid of CNAME type from response.
}
}
Exmple of answer from google :
"Answer" :
[
{
"name" : "apple.com." , // Always matches name in the Question section
"type" : 1 , // A - Standard DNS RR type
"TTL" : 3599 , // Record's time-to-live in seconds
"data" : "17.178.96.59" // Data for A - IP address as text
} ,
...
Exmple of output :
The same as google , but types _may be _ canonical strings ( 'AAAA' , 'A' )
* * /
if ( ! args . host . length ) {
throw new Error ( 'args.host is required: ' + args . host ) ;
}
args . types = Object . assign ( {
string : [ 'A' , 'AAAA' ] ,
filter : [ 'A' , 'AAAA' ]
} , args . types ) ;
const promises = args . types . string . map (
( type ) => new Promise ( ( resolve , reject ) =>
getOneDnsRecord ( { host : args . host , type : type , filter : args . types . filter } , ( err , res ) => err ? reject ( err ) : resolve ( res ) )
)
) ;
Promise . all ( promises ) . then ( ( answers ) => cb ( null , [ ] . concat . apply ( [ ] , answers ) ) , cb ) ;
2016-05-08 19:14:08 +03:00
}
2016-05-15 16:08:23 +03:00
const getIpDnsRecords = ( host , cb ) => getDnsRecords ( { host : host } , cb ) ;
2016-01-17 22:27:54 +03:00
function updatePacProxyIps ( provider , cb ) {
2016-05-15 16:08:23 +03:00
cb = asyncLogGroup ( 'Getting IP for ' + provider . proxyHosts . join ( ', ' ) + '...' , cb ) ;
let failure = {
2016-01-26 23:05:21 +03:00
clarification : { message : 'Н е удалось получить один или несколько IP адресов для прокси-серверов. Иконка для уведомления о б обходе блокировок может не отображаться.' } ,
errors : { }
2016-05-08 19:14:08 +03:00
} ;
2016-05-15 16:08:23 +03:00
let i = 0 ;
2016-02-13 18:53:27 +03:00
provider . proxyHosts . map (
2016-05-15 16:08:23 +03:00
( proxyHost ) => getIpDnsRecords (
2016-03-24 19:11:36 +03:00
proxyHost ,
2016-05-15 16:08:23 +03:00
( err , records ) => {
2016-01-17 22:27:54 +03:00
if ( ! err ) {
provider . proxyIps = provider . proxyIps || { } ;
2016-05-15 16:08:23 +03:00
records . forEach ( ( ans ) => provider . proxyIps [ ans . data ] = proxyHost ) ;
}
else {
2016-01-26 23:05:21 +03:00
failure . errors [ proxyHost ] = err ;
2016-05-15 16:08:23 +03:00
}
2016-01-26 23:05:21 +03:00
2016-05-15 16:08:23 +03:00
if ( ++ i === provider . proxyHosts . length ) {
2016-01-26 23:05:21 +03:00
failure = Object . keys ( failure . errors ) . length ? failure : null ;
return cb ( failure , provider . proxyIps ) ;
2016-01-17 22:27:54 +03:00
}
}
2016-02-13 18:53:27 +03:00
)
) ;
2015-12-20 23:28:41 +03:00
}
function setPacScriptFromProvider ( provider , cb ) {
2016-05-15 16:08:23 +03:00
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 ,
2016-11-12 17:35:50 +03:00
( err , pacData ) => {
2016-05-15 16:08:23 +03:00
2016-01-26 23:05:21 +03:00
if ( err ) {
err . clarification = {
2016-11-12 17:35:50 +03:00
message : 'Н е удалось скачать PAC-скрипт с адреса: ' + provider . pacUrl + '.' ,
2016-01-26 23:05:21 +03:00
prev : err . clarification
} ;
2015-12-20 23:28:41 +03:00
return cb ( err ) ;
2016-01-26 23:05:21 +03:00
}
2016-11-12 17:35:50 +03:00
2015-12-20 23:28:41 +03:00
console . log ( 'Clearing chrome proxy settings...' ) ;
return chrome . proxy . settings . clear ( { } , ( ) => {
2016-05-15 16:08:23 +03:00
const config = {
2016-02-08 12:55:41 +03:00
mode : 'pac_script' ,
pacScript : {
mandatory : false ,
2016-11-12 17:35:50 +03:00
data : pacData
2016-02-08 12:55:41 +03:00
}
} ;
console . log ( 'Setting chrome proxy settings...' ) ;
chrome . proxy . settings . set ( { value : config } , cb ) ;
} ) ;
2015-12-20 23:28:41 +03:00
}
) ;
2016-11-12 17:35:50 +03:00
}