mirror of
				https://github.com/anticensority/runet-censorship-bypass.git
				synced 2025-10-31 16:07:31 +03:00 
			
		
		
		
	Restyle, scope vars/names out of window
This commit is contained in:
		
							parent
							
								
									05c6deadf8
								
							
						
					
					
						commit
						1ef480acd1
					
				|  | @ -13,518 +13,526 @@ | ||||||
|     use chrome.runtime.getBackgroundPage(..), |     use chrome.runtime.getBackgroundPage(..), | ||||||
|     extension.getBackgroundPage is deprecated |     extension.getBackgroundPage is deprecated | ||||||
| */ | */ | ||||||
|  | { // Private namespace starts.
 | ||||||
| 
 | 
 | ||||||
| window.antiCensorRu = { |   window.antiCensorRu = { | ||||||
| 
 | 
 | ||||||
|   version: chrome.runtime.getManifest().version, |     version: chrome.runtime.getManifest().version, | ||||||
| 
 | 
 | ||||||
|   pacProviders: { |     pacProviders: { | ||||||
|     Антизапрет: { |       Антизапрет: { | ||||||
|       pacUrl: 'https://antizapret.prostovpn.org/proxy.pac', |         pacUrl: 'https://antizapret.prostovpn.org/proxy.pac', | ||||||
|       proxyHosts: ['proxy.antizapret.prostovpn.org'], |         proxyHosts: ['proxy.antizapret.prostovpn.org'], | ||||||
|       proxyIps: { |         proxyIps: { | ||||||
|         '195.123.209.38': 'proxy.antizapret.prostovpn.org', |           '195.123.209.38': 'proxy.antizapret.prostovpn.org', | ||||||
|         '2a02:27ac::10':  'proxy.antizapret.prostovpn.org' |           '2a02:27ac::10':  'proxy.antizapret.prostovpn.org' | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       Антиценз: { | ||||||
|  |         pacUrl: 'https://config.anticenz.org/proxy.pac', | ||||||
|  |         proxyHosts: ['gw2.anticenz.org'], | ||||||
|  |         proxyIps: { | ||||||
|  |           '5.196.220.114': 'gw2.anticenz.org' | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       Оба_и_на_свитчах: { | ||||||
|  |         //pacUrl: 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0akpCOURNS2VCTmc', // 0.14
 | ||||||
|  |         pacUrl: 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0bzNUR2F4RF8wOU0',   // 0.15
 | ||||||
|  |         proxyHosts: ['proxy.antizapret.prostovpn.org', 'gw2.anticenz.org'], | ||||||
|  |         proxyIps: { | ||||||
|  |           '195.123.209.38': 'proxy.antizapret.prostovpn.org', | ||||||
|  |           '2a02:27ac::10':  'proxy.antizapret.prostovpn.org', | ||||||
|  |           '5.196.220.114':  'gw2.anticenz.org' | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     Антиценз: { | 
 | ||||||
|       pacUrl: 'https://config.anticenz.org/proxy.pac', |     _currentPacProviderKey: 'Оба_и_на_свитчах', | ||||||
|       proxyHosts: ['gw2.anticenz.org'], | 
 | ||||||
|       proxyIps: { |     get currentPacProviderKey() { return this._currentPacProviderKey }, | ||||||
|         '5.196.220.114': 'gw2.anticenz.org' |     set currentPacProviderKey(newKey) { | ||||||
|       } | 
 | ||||||
|  |       if (newKey && !this.pacProviders[newKey]) | ||||||
|  |         throw new IllegalArgumentException('No provider for key:' + newKey); | ||||||
|  |       this._currentPacProviderKey = newKey; | ||||||
|     }, |     }, | ||||||
|     Оба_и_на_свитчах: { |  | ||||||
|       //pacUrl: 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0akpCOURNS2VCTmc', // 0.14
 |  | ||||||
|       pacUrl: 'https://drive.google.com/uc?export=download&id=0B-ZCVSvuNWf0bzNUR2F4RF8wOU0',   // 0.15
 |  | ||||||
|       proxyHosts: ['proxy.antizapret.prostovpn.org', 'gw2.anticenz.org'], |  | ||||||
|       proxyIps: { |  | ||||||
|         '195.123.209.38': 'proxy.antizapret.prostovpn.org', |  | ||||||
|         '2a02:27ac::10':  'proxy.antizapret.prostovpn.org', |  | ||||||
|         '5.196.220.114':  'gw2.anticenz.org' |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
| 
 | 
 | ||||||
|   _currentPacProviderKey: 'Оба_и_на_свитчах', |     get pacProvider() { return this.pacProviders[this.currentPacProviderKey] }, | ||||||
| 
 | 
 | ||||||
|   get currentPacProviderKey() { return this._currentPacProviderKey }, |     /* | ||||||
|   set currentPacProviderKey(newKey) { |       Is it the first time extension installed? Do something, e.g. initiate PAC sync. | ||||||
|  |     */ | ||||||
|  |     ifFirstInstall: false, | ||||||
|  |     lastPacUpdateStamp: 0, | ||||||
| 
 | 
 | ||||||
|     if (newKey && !this.pacProviders[newKey]) |     _periodicUpdateAlarmReason: 'Периодичное обновление PAC-скрипта Антизапрет', | ||||||
|       throw new IllegalArgumentException('No provider for key:' + newKey); |  | ||||||
|     this._currentPacProviderKey = newKey; |  | ||||||
|   }, |  | ||||||
| 
 | 
 | ||||||
|   get pacProvider() { return this.pacProviders[this.currentPacProviderKey] }, |     pushToStorage(cb) { | ||||||
| 
 | 
 | ||||||
|   /* |       console.log('Pushing to storage...'); | ||||||
|     Is it the first time extension installed? Do something, e.g. initiate PAC sync. |  | ||||||
|   */ |  | ||||||
|   ifFirstInstall: false, |  | ||||||
|   lastPacUpdateStamp: 0, |  | ||||||
| 
 | 
 | ||||||
|   _periodicUpdateAlarmReason: 'Периодичное обновление PAC-скрипта Антизапрет', |       // Copy only settable properties (except functions).
 | ||||||
| 
 |       const onlySettable = {}; | ||||||
|   pushToStorage(cb) { |       for(const key of Object.keys(this)) { | ||||||
| 
 |         if (Object.getOwnPropertyDescriptor(this, key).writable && typeof(this[key]) !== 'function') { | ||||||
|     console.log('Pushing to storage...'); |           onlySettable[key] = this[key]; | ||||||
| 
 |  | ||||||
|     // 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]; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return chrome.storage.local.clear( |  | ||||||
|       () => chrome.storage.local.set( |  | ||||||
|         onlySettable, |  | ||||||
|         chromified(cb, onlySettable) |  | ||||||
|       ) |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|   }, |  | ||||||
| 
 |  | ||||||
|   pullFromStorage(cb) { |  | ||||||
| 
 |  | ||||||
|     chrome.storage.local.get(null, (storage) => { |  | ||||||
| 
 |  | ||||||
|       const err = checkChromeError(); |  | ||||||
|       if (!err) { |  | ||||||
|         console.log('Pulled from storage:', storage); |  | ||||||
|         for(const key of Object.keys(storage)) { |  | ||||||
|           this[key] = storage[key]; |  | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       console.log('Synced with storage, any callback?', !!cb); |       return chrome.storage.local.clear( | ||||||
|       return cb && cb(err, storage); |         () => chrome.storage.local.set( | ||||||
|  |           onlySettable, | ||||||
|  |           chromified(cb, onlySettable) | ||||||
|  |         ) | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     pullFromStorage(cb) { | ||||||
|  | 
 | ||||||
|  |       chrome.storage.local.get(null, (storage) => { | ||||||
|  | 
 | ||||||
|  |         const err = checkChromeError(); | ||||||
|  |         if (!err) { | ||||||
|  |           console.log('Pulled from storage:', storage); | ||||||
|  |           for(const key of Object.keys(storage)) { | ||||||
|  |             this[key] = storage[key]; | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         console.log('Synced with storage, any callback?', !!cb); | ||||||
|  |         return cb && cb(err, storage); | ||||||
|  | 
 | ||||||
|  |       }); | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     syncWithPacProvider(cb) { | ||||||
|  | 
 | ||||||
|  |       cb = asyncLogGroup('Syncing with PAC provider...', cb); | ||||||
|  |       if (!this.pacProvider) { | ||||||
|  |         return cb({clarification:{message:'Сперва выберите PAC-провайдера.'}}); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       const pacSetPromise = new Promise( | ||||||
|  |         (resolve, reject) => setPacScriptFromProvider( | ||||||
|  |           this.pacProvider, | ||||||
|  |           (err, res) => { | ||||||
|  | 
 | ||||||
|  |             if (!err) { | ||||||
|  |               this.lastPacUpdateStamp = Date.now(); | ||||||
|  |               this.ifFirstInstall = false; | ||||||
|  |               this.setAlarms(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return resolve([err, res]); | ||||||
|  | 
 | ||||||
|  |           } | ||||||
|  |         ) | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       const ipsPromise = new Promise( | ||||||
|  |         (resolve, reject) => updatePacProxyIps( | ||||||
|  |           this.pacProvider, | ||||||
|  |           (ipsError) => { | ||||||
|  | 
 | ||||||
|  |             if (ipsError && ipsError.clarification) { | ||||||
|  |               ipsError.clarification.ifNotCritical = true; | ||||||
|  |             } | ||||||
|  |             return resolve([ipsError]); | ||||||
|  | 
 | ||||||
|  |           } | ||||||
|  |         ) | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       Promise.all([pacSetPromise, ipsPromise]).then( | ||||||
|  |         ([[pacErr, pacRes], [ipsErr]]) => { | ||||||
|  | 
 | ||||||
|  |           if (pacErr && ipsErr) { | ||||||
|  |             return cb(pacErr, pacRes); | ||||||
|  |           } | ||||||
|  |           return cb(pacErr || ipsErr); | ||||||
|  |           this.pushToStorage( | ||||||
|  |             (pushErr) => cb(pacErr || ipsErr || pushErr, pacRes) | ||||||
|  |           ); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     _pacUpdatePeriodInMinutes: 4*60, | ||||||
|  | 
 | ||||||
|  |     setAlarms() { | ||||||
|  | 
 | ||||||
|  |       let nextUpdateMoment = this.lastPacUpdateStamp + this._pacUpdatePeriodInMinutes*60*1000; | ||||||
|  |       const now = Date.now(); | ||||||
|  |       if (nextUpdateMoment < now) { | ||||||
|  |         nextUpdateMoment = now; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       console.log( 'Next PAC update is scheduled on', new Date(nextUpdateMoment).toLocaleString('ru-RU') ); | ||||||
|  | 
 | ||||||
|  |       chrome.alarms.create( | ||||||
|  |         this._periodicUpdateAlarmReason, | ||||||
|  |         { | ||||||
|  |           when: nextUpdateMoment, | ||||||
|  |           periodInMinutes: this._pacUpdatePeriodInMinutes | ||||||
|  |         } | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       return nextUpdateMoment === now; // ifAlarmTriggered. May be changed in the future.
 | ||||||
|  | 
 | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     installPac(key, cb) { | ||||||
|  | 
 | ||||||
|  |       console.log('Installing PAC'); | ||||||
|  |       if(typeof(key) === 'function') { | ||||||
|  |         cb = key; | ||||||
|  |         key = undefined; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if(key) { | ||||||
|  |         this.currentPacProviderKey = key; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return this.syncWithPacProvider(cb); | ||||||
|  | 
 | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     clearPac(cb) { | ||||||
|  | 
 | ||||||
|  |       cb = asyncLogGroup('Cearing alarms and PAC...', cb); | ||||||
|  |       chrome.alarms.clearAll( | ||||||
|  |         () => chrome.proxy.settings.clear( | ||||||
|  |           {}, | ||||||
|  |           () => { | ||||||
|  | 
 | ||||||
|  |             const err = checkChromeError(); | ||||||
|  |             if (err) { | ||||||
|  |               return cb(err); | ||||||
|  |             } | ||||||
|  |             this.currentPacProviderKey = undefined; | ||||||
|  |             return this.pushToStorage(cb); | ||||||
|  | 
 | ||||||
|  |           } | ||||||
|  |         ) | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // ON EACH LAUNCH, STARTUP, RELOAD, UPDATE, ENABLE
 | ||||||
|  |   chrome.storage.local.get(null, (oldStorage) => { | ||||||
|  | 
 | ||||||
|  |     console.log('Init on storage:', oldStorage); | ||||||
|  |     antiCensorRu.ifFirstInstall = Object.keys(oldStorage).length === 0; | ||||||
|  | 
 | ||||||
|  |     if (!antiCensorRu.ifFirstInstall) { | ||||||
|  |       // LAUNCH, RELOAD, UPDATE
 | ||||||
|  |       antiCensorRu._currentPacProviderKey = oldStorage._currentPacProviderKey; | ||||||
|  |       antiCensorRu.lastPacUpdateStamp = oldStorage.lastPacUpdateStamp || antiCensorRu.lastPacUpdateStamp; | ||||||
|  |       console.log( 'Last PAC update was on', new Date(antiCensorRu.lastPacUpdateStamp).toLocaleString('ru-RU') ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     chrome.alarms.onAlarm.addListener( | ||||||
|  |       (alarm) => { | ||||||
|  | 
 | ||||||
|  |         if (alarm.name === antiCensorRu._periodicUpdateAlarmReason) { | ||||||
|  |           console.log('Periodic PAC update triggered:', new Date().toLocaleString('ru-RU')); | ||||||
|  |           antiCensorRu.syncWithPacProvider(/* Swallows errors. */); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |       } | ||||||
|  |     ); | ||||||
|  |     console.log('Alarm listener installed. We won\'t miss any PAC update.'); | ||||||
|  | 
 | ||||||
|  |     window.addEventListener('online',  () => { | ||||||
|  | 
 | ||||||
|  |       console.log('We are online, checking periodic updates...'); | ||||||
|  |       antiCensorRu.setAlarms(); | ||||||
| 
 | 
 | ||||||
|     }); |     }); | ||||||
|   }, |  | ||||||
| 
 | 
 | ||||||
|   syncWithPacProvider(cb) { |     if (antiCensorRu.ifFirstInstall) { | ||||||
| 
 |       // INSTALL
 | ||||||
|     cb = asyncLogGroup('Syncing with PAC provider...', cb); |       console.log('Installing...'); | ||||||
|     if (!this.pacProvider) { |       return chrome.runtime.openOptionsPage(); | ||||||
|       return cb({clarification:{message:'Сперва выберите PAC-провайдера.'}}); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const pacSetPromise = new Promise( |     if (!antiCensorRu.pacProvider) { | ||||||
|       (resolve, reject) => setPacScriptFromProvider( |       return console.log('No PAC provider set. Do nothing.'); | ||||||
|         this.pacProvider, |       /* | ||||||
|         (err, res) => { |         In case of UPDATE: | ||||||
| 
 |           1. new providers will still be shown. | ||||||
|           if (!err) { |           2. new version won't be pushed to storage | ||||||
|             this.lastPacUpdateStamp = Date.now(); |       */ | ||||||
|             this.ifFirstInstall = false; |  | ||||||
|             this.setAlarms(); |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           return resolve([err, res]); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
|       ) |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     const ipsPromise = new Promise( |  | ||||||
|       (resolve, reject) => updatePacProxyIps( |  | ||||||
|         this.pacProvider, |  | ||||||
|         (ipsError) => { |  | ||||||
| 
 |  | ||||||
|           if (ipsError && ipsError.clarification) { |  | ||||||
|             ipsError.clarification.ifNotCritical = true; |  | ||||||
|           } |  | ||||||
|           return resolve([ipsError]); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
|       ) |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     Promise.all([pacSetPromise, ipsPromise]).then( |  | ||||||
|       ([[pacErr, pacRes], [ipsErr]]) => { |  | ||||||
| 
 |  | ||||||
|         if (pacErr && ipsErr) { |  | ||||||
|           return cb(pacErr, pacRes); |  | ||||||
|         } |  | ||||||
|         return cb(pacErr || ipsErr); |  | ||||||
|         this.pushToStorage( |  | ||||||
|           (pushErr) => cb(pacErr || ipsErr || pushErr, pacRes) |  | ||||||
|         ); |  | ||||||
| 
 |  | ||||||
|       } |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|   }, |  | ||||||
| 
 |  | ||||||
|   _pacUpdatePeriodInMinutes: 4*60, |  | ||||||
| 
 |  | ||||||
|   setAlarms() { |  | ||||||
| 
 |  | ||||||
|     let nextUpdateMoment = this.lastPacUpdateStamp + this._pacUpdatePeriodInMinutes*60*1000; |  | ||||||
|     const now = Date.now(); |  | ||||||
|     if (nextUpdateMoment < now) |  | ||||||
|       nextUpdateMoment = now; |  | ||||||
| 
 |  | ||||||
|     console.log( 'Next PAC update is scheduled on', new Date(nextUpdateMoment).toLocaleString('ru-RU') ); |  | ||||||
| 
 |  | ||||||
|     chrome.alarms.create( |  | ||||||
|       this._periodicUpdateAlarmReason, |  | ||||||
|       { |  | ||||||
|         when: nextUpdateMoment, |  | ||||||
|         periodInMinutes: this._pacUpdatePeriodInMinutes |  | ||||||
|       } |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     return nextUpdateMoment === now; // ifAlarmTriggered. May be changed in the future.
 |  | ||||||
|   }, |  | ||||||
| 
 |  | ||||||
|   installPac(key, cb) { |  | ||||||
| 
 |  | ||||||
|     console.log('Installing PAC'); |  | ||||||
|     if(typeof(key) === 'function') { |  | ||||||
|       cb = key; |  | ||||||
|       key = undefined; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(key) { |     /* | ||||||
|       this.currentPacProviderKey = key; |       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. | ||||||
|  |     */ | ||||||
|  | 
 | ||||||
|  |     const ifAlarmTriggered = antiCensorRu.setAlarms(); | ||||||
|  | 
 | ||||||
|  |     if (antiCensorRu.version === oldStorage.version) { | ||||||
|  |       // LAUNCH, RELOAD, ENABLE
 | ||||||
|  |       antiCensorRu.pacProviders = oldStorage.pacProviders; | ||||||
|  |       return console.log('Extension launched, reloaded or enabled.'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return this.syncWithPacProvider(cb); |     // UPDATE & MIGRATION
 | ||||||
| 
 |     console.log('Extension updated.'); | ||||||
|   }, |     if (!ifAlarmTriggered) { | ||||||
| 
 |       antiCensorRu.pushToStorage(/* Swallows errors. */); | ||||||
|   clearPac(cb) { |  | ||||||
| 
 |  | ||||||
|     cb = asyncLogGroup('Cearing alarms and PAC...', cb); |  | ||||||
|     chrome.alarms.clearAll( |  | ||||||
|       () => chrome.proxy.settings.clear( |  | ||||||
|         {}, |  | ||||||
|         () => { |  | ||||||
| 
 |  | ||||||
|           const err = checkChromeError(); |  | ||||||
|           if (err) { |  | ||||||
|             return cb(err); |  | ||||||
|           } |  | ||||||
|           this.currentPacProviderKey = undefined; |  | ||||||
|           return this.pushToStorage(cb); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
|       ) |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // ON EACH LAUNCH, STARTUP, RELOAD, UPDATE, ENABLE
 |  | ||||||
| chrome.storage.local.get(null, (oldStorage) => { |  | ||||||
| 
 |  | ||||||
|   console.log('Init on storage:', oldStorage); |  | ||||||
|   antiCensorRu.ifFirstInstall = Object.keys(oldStorage).length === 0; |  | ||||||
| 
 |  | ||||||
|   if (!antiCensorRu.ifFirstInstall) { |  | ||||||
|     // LAUNCH, RELOAD, UPDATE
 |  | ||||||
|     antiCensorRu._currentPacProviderKey = oldStorage._currentPacProviderKey; |  | ||||||
|     antiCensorRu.lastPacUpdateStamp = oldStorage.lastPacUpdateStamp || antiCensorRu.lastPacUpdateStamp; |  | ||||||
|     console.log( 'Last PAC update was on', new Date(antiCensorRu.lastPacUpdateStamp).toLocaleString('ru-RU') ); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   chrome.alarms.onAlarm.addListener( |  | ||||||
|     (alarm) => { |  | ||||||
| 
 |  | ||||||
|       if (alarm.name === antiCensorRu._periodicUpdateAlarmReason) { |  | ||||||
|         console.log('Periodic PAC update triggered:', new Date().toLocaleString('ru-RU')); |  | ||||||
|         antiCensorRu.syncWithPacProvider(/* Swallows errors. */); |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|   ); |  | ||||||
|   console.log('Alarm listener installed. We won\'t miss any PAC update.'); |  | ||||||
| 
 |  | ||||||
|   window.addEventListener('online',  () => { |  | ||||||
| 
 |  | ||||||
|     console.log('We are online, checking periodic updates...'); |  | ||||||
|     antiCensorRu.setAlarms(); |  | ||||||
| 
 | 
 | ||||||
|  |     /* | ||||||
|  |       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 | ||||||
|  |     **/ | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   if (antiCensorRu.ifFirstInstall) { |   function asyncLogGroup(...args) { | ||||||
|     // INSTALL
 | 
 | ||||||
|     console.log('Installing...'); |     const cb = args.pop() || (() => {}); | ||||||
|     return chrome.runtime.openOptionsPage(); |     console.group.apply(console, args); | ||||||
|  |     return function(...cbArgs) { | ||||||
|  | 
 | ||||||
|  |       console.groupEnd(); | ||||||
|  |       console.log('Group finished.'); | ||||||
|  |       return cb.apply(this, cbArgs); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (!antiCensorRu.pacProvider) { |   function checkChromeError(betterStack) { | ||||||
|     return console.log('No PAC provider set. Do nothing.'); | 
 | ||||||
|  |     // Chrome API calls your cb in a context different from the point of API method invokation.
 | ||||||
|  |     const err = chrome.runtime.lastError || chrome.extension.lastError || null; | ||||||
|  |     if (err) { | ||||||
|  |       const args = ['API returned error:', err]; | ||||||
|  |       if (betterStack) { | ||||||
|  |         args.push('\n' + betterStack); | ||||||
|  |       } | ||||||
|  |       console.warn.apply(console, args); | ||||||
|  |     } | ||||||
|  |     return err; | ||||||
|  | 
 | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* |   function chromified(cb, ...replaceArgs) { | ||||||
|     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. |  | ||||||
|   */ |  | ||||||
| 
 | 
 | ||||||
|   const ifAlarmTriggered = antiCensorRu.setAlarms(); |     const stack = (new Error()).stack; | ||||||
|  |     // Take error first callback and covert it to chrome api callback.
 | ||||||
|  |     return function(...args) { | ||||||
|  | 
 | ||||||
|  |       if (replaceArgs.length) { | ||||||
|  |         args = replaceArgs; | ||||||
|  |       } | ||||||
|  |       const err = checkChromeError(stack); | ||||||
|  |       return cb && cb.call(this, err, ...args); | ||||||
|  | 
 | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|   if (antiCensorRu.version === oldStorage.version) { |  | ||||||
|     // LAUNCH, RELOAD, ENABLE
 |  | ||||||
|     antiCensorRu.pacProviders = oldStorage.pacProviders; |  | ||||||
|     return console.log('Extension launched, reloaded or enabled.'); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // UPDATE & MIGRATION
 |   function httpGet(url, cb) { | ||||||
|   console.log('Extension updated.'); | 
 | ||||||
|   if (!ifAlarmTriggered) { |     const start = Date.now(); | ||||||
|     updatePacProxyIps( |     return fetch(url).then( | ||||||
|       antiCensorRu.pacProvider, |       (res) => { | ||||||
|       (ipsError) => ipsError ? console.error('Error updating IPs:', ipsError) : antiCensorRu.pushToStorage(/* Swallows errors. */) | 
 | ||||||
|  |         const textCb = | ||||||
|  |           (err) => cb && res.text() | ||||||
|  |             .then( (text) => cb(err, text), cb ); | ||||||
|  |         const status = res.status; | ||||||
|  |         if ( !( status >= 200 && status < 300 || status === 304 ) ) { | ||||||
|  |           res.clarification = {message: 'Получен ответ с неудачным HTTP-кодом ' + status + '.'}; | ||||||
|  |           return textCb(res); | ||||||
|  |         } | ||||||
|  |         console.log('GETed with success:', url, Date.now() - start); | ||||||
|  |         return textCb(); | ||||||
|  | 
 | ||||||
|  |       }, | ||||||
|  |       (err) => { | ||||||
|  | 
 | ||||||
|  |         err.clarification = {message: 'Что-то не так с сетью, проверьте соединение.'}; | ||||||
|  |         return cb && cb(err); | ||||||
|  | 
 | ||||||
|  |       } | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* |   function getOneDnsRecord(args, cb) { | ||||||
|     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 |  | ||||||
|   **/ |  | ||||||
| }); |  | ||||||
| 
 | 
 | ||||||
| function asyncLogGroup(...args) { |     // args: { host:..., type: 'AAAA', filter: ['AAAA'] }
 | ||||||
| 
 |     if (!(args.host && args.type && cb)) { | ||||||
|   const cb = args.pop() || (() => {}); |       throw new Error('Wrong args:' + host + ',' + type); | ||||||
|   console.group.apply(console, args); |  | ||||||
|   return function(...cbArgs) { |  | ||||||
| 
 |  | ||||||
|     console.groupEnd(); |  | ||||||
|     console.log('Group finished.'); |  | ||||||
|     return cb.apply(this, cbArgs); |  | ||||||
| 
 |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function checkChromeError(betterStack) { |  | ||||||
| 
 |  | ||||||
|   // Chrome API calls your cb in a context different from the point of API method invokation.
 |  | ||||||
|   const err = chrome.runtime.lastError || chrome.extension.lastError || null; |  | ||||||
|   if (err) { |  | ||||||
|     const args = ['API returned error:', err]; |  | ||||||
|     if (betterStack) { |  | ||||||
|       args.push('\n' + betterStack); |  | ||||||
|     } |     } | ||||||
|     console.warn.apply(console, args); |  | ||||||
|   } |  | ||||||
|   return err; |  | ||||||
| 
 | 
 | ||||||
| } |     const type2str = { | ||||||
|  |       // https://en.wikipedia.org/wiki/List_of_DNS_record_types
 | ||||||
|  |       // A, AAAA may be localized (github, e.g.), but you may use ANY
 | ||||||
|  |       1:  'A',      // IPv4
 | ||||||
|  |       28: 'AAAA',   // IPv6
 | ||||||
|  |       2:  'NS', | ||||||
|  |       5:  'CNAME',  // Synonyms, returned by server together with A/AAAA.
 | ||||||
|  |       255: 'ANY'    // Deprecated on some servers, not recommended
 | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
| function chromified(cb, ...replaceArgs) { |     httpGet( | ||||||
| 
 |       'https://dns.google.com/resolve?type=' + args.type + '&name=' + args.host, | ||||||
|   const stack = (new Error()).stack; |       (err, res) => { | ||||||
|   // Take error first callback and covert it to chrome api callback.
 |         if (res) { | ||||||
|   return function(...args) { |           try { | ||||||
| 
 |             res = JSON.parse(res); | ||||||
|     if (replaceArgs.length) { |             console.log('Json parsed.'); | ||||||
|       args = replaceArgs; |             if (err || res.Status) { | ||||||
|     } |               const msg = ['Answer', 'Comment', 'Status'] | ||||||
|     const err = checkChromeError(stack); |                 .filter( (prop) => res[ prop ] ) | ||||||
|     return cb && cb.call(this, err, ...args); |                 .map( (prop) => prop + ': ' + JSON.stringify( res[ prop ] ) ) | ||||||
| 
 |                 .join(', \n'); | ||||||
|   }; |               err.clarification.message += ' Сервер (json): ' + msg; | ||||||
| 
 |               err.data = err.data || res; | ||||||
| } |             } | ||||||
| 
 |             else { | ||||||
| function httpGet(url, cb) { |               res = res.Answer || []; | ||||||
| 
 |               for (const record of res) { | ||||||
|   const start = Date.now(); |                 record.type = type2str[ record.type ]; | ||||||
|   return fetch(url).then( |               } | ||||||
|     (res) => { |               if ( args.filter ) { | ||||||
| 
 |                 res = res.filter( (record) => args.filter.indexOf( record.type ) > -1 ); | ||||||
|       const textCb = |               } | ||||||
|         (err) => cb && res.text() |             } | ||||||
|           .then( (text) => cb(err, text), cb ); |           } | ||||||
|       const status = res.status; |           catch(e) { | ||||||
|       if ( !( status >= 200 && status < 300 || status === 304 ) ) { |             err = e || err || {clarification:{message:''}}; | ||||||
|         res.clarification = {message: 'Получен ответ с неудачным HTTP-кодом ' + status + '.'}; |             err.clarification = err.clarification || { message: '' }; | ||||||
|         return textCb(res); |             err.clarification.message += ' Сервер (текст): '+ res; | ||||||
|       } |             err.clarification.message.trim(); | ||||||
|       console.log('GETed with success:', url, Date.now() - start); |  | ||||||
|       return textCb(); |  | ||||||
| 
 |  | ||||||
|     }, |  | ||||||
|     (err) => { |  | ||||||
| 
 |  | ||||||
|       err.clarification = {message: 'Что-то не так с сетью, проверьте соединение.'}; |  | ||||||
|       return cb && cb(err); |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
|   ); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function getOneDnsRecord(args, cb) { |  | ||||||
| 
 |  | ||||||
|   // args: { host:..., type: 'AAAA', filter: ['AAAA'] }
 |  | ||||||
|   if (!(args.host && args.type && cb)) { |  | ||||||
|     throw new Error('Wrong args:' + host + ',' + type); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   const type2str = { |  | ||||||
|     // https://en.wikipedia.org/wiki/List_of_DNS_record_types
 |  | ||||||
|     // A, AAAA may be localized (github, e.g.), but you may use ANY
 |  | ||||||
|     1:  'A',      // IPv4
 |  | ||||||
|     28: 'AAAA',   // IPv6
 |  | ||||||
|     2:  'NS', |  | ||||||
|     5:  'CNAME',  // Synonyms, returned by server together with A/AAAA.
 |  | ||||||
|     255: 'ANY'    // Deprecated on some servers, not recommended
 |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   httpGet( |  | ||||||
|     'https://dns.google.com/resolve?type=' + args.type + '&name=' + args.host, |  | ||||||
|     (err, res) => { |  | ||||||
|       if (res) { |  | ||||||
|         try { |  | ||||||
|           res = JSON.parse(res); |  | ||||||
|           console.log('Json parsed.'); |  | ||||||
|           if (err || res.Status) { |  | ||||||
|             const msg = ['Answer', 'Comment', 'Status'] |  | ||||||
|               .filter( (prop) => res[ prop ] ) |  | ||||||
|               .map( (prop) => prop + ': ' + JSON.stringify( res[ prop ] ) ) |  | ||||||
|               .join(', \n'); |  | ||||||
|             err.clarification.message += ' Сервер (json): ' + msg; |  | ||||||
|             err.data = err.data || res; |             err.data = err.data || res; | ||||||
|           } |           } | ||||||
|           else { |  | ||||||
|             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 ); |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|         catch(e) { |  | ||||||
|           err = e || err || {clarification:{message:''}}; |  | ||||||
|           err.clarification = err.clarification || { message: '' }; |  | ||||||
|           err.clarification.message += ' Сервер (текст): '+ res; |  | ||||||
|           err.clarification.message.trim(); |  | ||||||
|           err.data = err.data || res; |  | ||||||
|         } |         } | ||||||
|  |         return cb( err, res ); | ||||||
|       } |       } | ||||||
|       return cb( err, res ); |     ); | ||||||
|     } |  | ||||||
|   ); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| 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 ); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const getIpDnsRecords = (host, cb) => getDnsRecords({ host: host }, cb); |  | ||||||
| 
 |  | ||||||
| function updatePacProxyIps(provider, cb) { |  | ||||||
| 
 |  | ||||||
|   cb = asyncLogGroup('Getting IP for '+ provider.proxyHosts.join(', ') +'...', cb); |  | ||||||
|   let failure = { |  | ||||||
|     clarification: {message:'Не удалось получить один или несколько IP адресов для прокси-серверов. Иконка для уведомления об обходе блокировок может не отображаться.'}, |  | ||||||
|     errors: {} |  | ||||||
|   }; |   }; | ||||||
|   let i = 0; |  | ||||||
|   provider.proxyHosts.map( |  | ||||||
|     (proxyHost) => getIpDnsRecords( |  | ||||||
|       proxyHost, |  | ||||||
|       (err, records) => { |  | ||||||
| 
 | 
 | ||||||
|         if (!err) { |   function getDnsRecords(args, cb) { | ||||||
|           provider.proxyIps = provider.proxyIps || {}; | 
 | ||||||
|           records.forEach( (ans) => provider.proxyIps[ ans.data ] = proxyHost ); |     /* | ||||||
|         } |       Example of input: | ||||||
|         else { |         { | ||||||
|           failure.errors[proxyHost] = err; |           // 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 ( ++i === provider.proxyHosts.length ) { |     if ( !args.host.length ) { | ||||||
|           failure = Object.keys(failure.errors).length ? failure : null; |       throw new Error('args.host is required: ' + args.host); | ||||||
|           return cb(failure, provider.proxyIps); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     ) |  | ||||||
|   ); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function setPacScriptFromProvider(provider, cb) { |  | ||||||
| 
 |  | ||||||
|   cb = asyncLogGroup('Getting pac script from provider...', provider.pacUrl, cb); |  | ||||||
| 
 |  | ||||||
|   httpGet( |  | ||||||
|     provider.pacUrl, |  | ||||||
|     (err, pacData) => { |  | ||||||
| 
 |  | ||||||
|       if (err) { |  | ||||||
|         err.clarification = { |  | ||||||
|           message: 'Не удалось скачать PAC-скрипт с адреса: ' + provider.pacUrl + '.', |  | ||||||
|           prev: err.clarification |  | ||||||
|         }; |  | ||||||
|         return cb(err); |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       const config = { |  | ||||||
|         mode: 'pac_script', |  | ||||||
|         pacScript: { |  | ||||||
|           mandatory: false, |  | ||||||
|           data: pacData |  | ||||||
|         } |  | ||||||
|       }; |  | ||||||
|       console.log('Setting chrome proxy settings...'); |  | ||||||
|       chrome.proxy.settings.set( {value: config}, chromified(cb) ); |  | ||||||
| 
 |  | ||||||
|     } |     } | ||||||
|   ); |     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 ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const getIpDnsRecords = (host, cb) => getDnsRecords({ host: host }, cb); | ||||||
|  | 
 | ||||||
|  |   function updatePacProxyIps(provider, cb) { | ||||||
|  | 
 | ||||||
|  |     cb = asyncLogGroup('Getting IP for '+ provider.proxyHosts.join(', ') +'...', cb); | ||||||
|  |     let failure = { | ||||||
|  |       clarification: {message:'Не удалось получить один или несколько IP адресов для прокси-серверов. Иконка для уведомления об обходе блокировок может не отображаться.'}, | ||||||
|  |       errors: {} | ||||||
|  |     }; | ||||||
|  |     let i = 0; | ||||||
|  |     provider.proxyHosts.map( | ||||||
|  |       (proxyHost) => getIpDnsRecords( | ||||||
|  |         proxyHost, | ||||||
|  |         (err, records) => { | ||||||
|  | 
 | ||||||
|  |           if (!err) { | ||||||
|  |             provider.proxyIps = provider.proxyIps || {}; | ||||||
|  |             records.forEach( (ans) => provider.proxyIps[ ans.data ] = proxyHost ); | ||||||
|  |           } | ||||||
|  |           else { | ||||||
|  |             failure.errors[proxyHost] = err; | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           if ( ++i === provider.proxyHosts.length ) { | ||||||
|  |             failure = Object.keys(failure.errors).length ? failure : null; | ||||||
|  |             return cb(failure, provider.proxyIps); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function setPacScriptFromProvider(provider, cb) { | ||||||
|  | 
 | ||||||
|  |     cb = asyncLogGroup('Getting pac script from provider...', provider.pacUrl, cb); | ||||||
|  | 
 | ||||||
|  |     httpGet( | ||||||
|  |       provider.pacUrl, | ||||||
|  |       (err, pacData) => { | ||||||
|  | 
 | ||||||
|  |         if (err) { | ||||||
|  |           err.clarification = { | ||||||
|  |             message: 'Не удалось скачать PAC-скрипт с адреса: ' + provider.pacUrl + '.', | ||||||
|  |             prev: err.clarification | ||||||
|  |           }; | ||||||
|  |           return cb(err); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const config = { | ||||||
|  |           mode: 'pac_script', | ||||||
|  |           pacScript: { | ||||||
|  |             mandatory: false, | ||||||
|  |             data: pacData | ||||||
|  |           } | ||||||
|  |         }; | ||||||
|  |         console.log('Setting chrome proxy settings...'); | ||||||
|  |         chrome.proxy.settings.set( {value: config}, chromified(cb) ); | ||||||
|  | 
 | ||||||
|  |       } | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| window.addEventListener('error', (err) => { | window.addEventListener('error', (err) => { | ||||||
|  |  | ||||||
|  | @ -18,9 +18,9 @@ window.chrome.browserAction.setBadgeBackgroundColor({ | ||||||
| 
 | 
 | ||||||
| window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
 | window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP!
 | ||||||
| 
 | 
 | ||||||
| +function() { | { | ||||||
| 
 | 
 | ||||||
|   var _tabCallbacks = {}; |   const _tabCallbacks = {}; | ||||||
| 
 | 
 | ||||||
|   function afterTabUpdated(tabId, cb) { |   function afterTabUpdated(tabId, cb) { | ||||||
|     if (_tabCallbacks[tabId]) |     if (_tabCallbacks[tabId]) | ||||||
|  | @ -42,7 +42,7 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP! | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   chrome.webRequest.onErrorOccurred.addListener( |   chrome.webRequest.onErrorOccurred.addListener( | ||||||
|     requestDetails => |     (requestDetails) => | ||||||
|       isInsideTabWithIp(requestDetails) && |       isInsideTabWithIp(requestDetails) && | ||||||
|       ( |       ( | ||||||
|         isProxiedAndInformed(requestDetails) || requestDetails.type === 'main_frame' && ( window.tabWithError2ip[requestDetails.tabId] = requestDetails.ip ) |         isProxiedAndInformed(requestDetails) || requestDetails.type === 'main_frame' && ( window.tabWithError2ip[requestDetails.tabId] = requestDetails.ip ) | ||||||
|  | @ -50,9 +50,9 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP! | ||||||
|     { urls: ['<all_urls>'] } |     { urls: ['<all_urls>'] } | ||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
|   chrome.tabs.onRemoved.addListener( tabId => { onTabUpdate(tabId); delete window.tabWithError2ip[tabId] } ); |   chrome.tabs.onRemoved.addListener( (tabId) => { onTabUpdate(tabId); delete window.tabWithError2ip[tabId] } ); | ||||||
| 
 | 
 | ||||||
|   var previousUpdateTitleFinished = Promise.resolve(); |   let previousUpdateTitleFinished = Promise.resolve(); | ||||||
| 
 | 
 | ||||||
|   function isProxiedAndInformed(requestDetails) { |   function isProxiedAndInformed(requestDetails) { | ||||||
| 
 | 
 | ||||||
|  | @ -62,12 +62,12 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP! | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     var ifMainFrame = requestDetails.type === 'main_frame'; |     const ifMainFrame = requestDetails.type === 'main_frame'; | ||||||
| 
 | 
 | ||||||
|     previousUpdateTitleFinished = previousUpdateTitleFinished.then( |     previousUpdateTitleFinished = previousUpdateTitleFinished.then( | ||||||
|       () => new Promise( |       () => new Promise( | ||||||
|         resolve => { |         (resolve) => { | ||||||
|           var cb = () => updateTitle( requestDetails, resolve ); |           const cb = () => updateTitle( requestDetails, resolve ); | ||||||
|           return ifMainFrame ? afterTabUpdated(requestDetails.tabId, cb) : cb(); |           return ifMainFrame ? afterTabUpdated(requestDetails.tabId, cb) : cb(); | ||||||
|         } |         } | ||||||
|       ) |       ) | ||||||
|  | @ -79,15 +79,16 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP! | ||||||
| 
 | 
 | ||||||
|       chrome.browserAction.getTitle( |       chrome.browserAction.getTitle( | ||||||
|         { tabId: requestDetails.tabId }, |         { tabId: requestDetails.tabId }, | ||||||
|         title => { |         (title) => { | ||||||
|           var ifTitleSetAlready = /\n/.test(title); |  | ||||||
|           var proxyHost = window.antiCensorRu.pacProvider.proxyIps[ requestDetails.ip ]; |  | ||||||
| 
 | 
 | ||||||
|           var hostname = new URL( requestDetails.url ).hostname; |           const ifTitleSetAlready = /\n/.test(title); | ||||||
|  |           const proxyHost = window.antiCensorRu.pacProvider.proxyIps[ requestDetails.ip ]; | ||||||
| 
 | 
 | ||||||
|           var ifShouldUpdateTitle = false; |           const hostname = new URL( requestDetails.url ).hostname; | ||||||
|           var indent = '  '; | 
 | ||||||
|           var proxyTitle = 'Прокси:'; |           let ifShouldUpdateTitle = false; | ||||||
|  |           const indent = '  '; | ||||||
|  |           const proxyTitle = 'Прокси:'; | ||||||
| 
 | 
 | ||||||
|           if (!ifTitleSetAlready) { |           if (!ifTitleSetAlready) { | ||||||
|             title = 'Разблокированы:\n'+ indent + hostname +'\n'+ proxyTitle +'\n'+ indent + proxyHost; |             title = 'Разблокированы:\n'+ indent + hostname +'\n'+ proxyTitle +'\n'+ indent + proxyHost; | ||||||
|  | @ -98,7 +99,8 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP! | ||||||
|               text: ifMainFrame ? '1' : '%1' |               text: ifMainFrame ? '1' : '%1' | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|           } else { |           } | ||||||
|  |           else { | ||||||
|             const hostsProxiesPair = title.split(proxyTitle); |             const hostsProxiesPair = title.split(proxyTitle); | ||||||
| 
 | 
 | ||||||
|             if (hostsProxiesPair[1].indexOf(proxyHost) === -1) { |             if (hostsProxiesPair[1].indexOf(proxyHost) === -1) { | ||||||
|  | @ -110,10 +112,11 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP! | ||||||
|               title = title.replace(proxyTitle, indent + hostname +'\n'+ proxyTitle); |               title = title.replace(proxyTitle, indent + hostname +'\n'+ proxyTitle); | ||||||
|               ifShouldUpdateTitle = true; |               ifShouldUpdateTitle = true; | ||||||
| 
 | 
 | ||||||
|               var _cb = cb; |               const _cb = cb; | ||||||
|               cb = () => chrome.browserAction.getBadgeText( |               cb = () => chrome.browserAction.getBadgeText( | ||||||
|                 {tabId: requestDetails.tabId}, |                 {tabId: requestDetails.tabId}, | ||||||
|                 result => { |                 (result) => { | ||||||
|  | 
 | ||||||
|                   chrome.browserAction.setBadgeText( |                   chrome.browserAction.setBadgeText( | ||||||
|                     { |                     { | ||||||
|                       tabId: requestDetails.tabId, |                       tabId: requestDetails.tabId, | ||||||
|  | @ -121,27 +124,30 @@ window.tabWithError2ip = {}; // For errors only: Error? -> Check this IP! | ||||||
|                     } |                     } | ||||||
|                   ); |                   ); | ||||||
|                   return _cb(); |                   return _cb(); | ||||||
|  | 
 | ||||||
|                 } |                 } | ||||||
|               ); |               ); | ||||||
| 
 | 
 | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
| 
 | 
 | ||||||
|           if (ifShouldUpdateTitle) |           if (ifShouldUpdateTitle) { | ||||||
|             chrome.browserAction.setTitle({ |             chrome.browserAction.setTitle({ | ||||||
|               title: title, |               title: title, | ||||||
|               tabId: requestDetails.tabId |               tabId: requestDetails.tabId | ||||||
|             }); |             }); | ||||||
|  |           } | ||||||
| 
 | 
 | ||||||
|           return cb(); |           return cb(); | ||||||
|  | 
 | ||||||
|         } |         } | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   chrome.webRequest.onResponseStarted.addListener( |   chrome.webRequest.onResponseStarted.addListener( | ||||||
|     requestDetails => isInsideTabWithIp(requestDetails) && isProxiedAndInformed(requestDetails), |     (requestDetails) => isInsideTabWithIp(requestDetails) && isProxiedAndInformed(requestDetails), | ||||||
|     { urls: ['<all_urls>'] } |     { urls: ['<all_urls>'] } | ||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
| }(); | } | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ | ||||||
|   const createMenuLinkEntry = (title, tab2url) => chrome.contextMenus.create({ |   const createMenuLinkEntry = (title, tab2url) => chrome.contextMenus.create({ | ||||||
|     title: title, |     title: title, | ||||||
|     contexts: ['browser_action'], |     contexts: ['browser_action'], | ||||||
|     onclick: (menuInfo, tab) => Promise.resolve( tab2url( tab ) ).then( url => chrome.tabs.create({url: url}) ) |     onclick: (menuInfo, tab) => Promise.resolve( tab2url( tab ) ).then( (url) => chrome.tabs.create({url: url}) ) | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   createMenuLinkEntry( 'Сайт доступен из-за границы? Is up?', (tab) => 'http://isup.me/'+ new URL(tab.url).hostname ); |   createMenuLinkEntry( 'Сайт доступен из-за границы? Is up?', (tab) => 'http://isup.me/'+ new URL(tab.url).hostname ); | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| { | { | ||||||
|   "manifest_version": 2, |   "manifest_version": 2, | ||||||
| 
 | 
 | ||||||
|   "name": "Обход блокировок Рунета", |   "name": "Обход блокировок Рунета 0.15", | ||||||
|   "description": "Аргументы против цензуры: https://git.io/vEkI9", |   "description": "Аргументы против цензуры: https://git.io/vEkI9", | ||||||
|   "version": "0.0.0.15", |   "version": "0.0.0.15", | ||||||
|   "icons": { |   "icons": { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user