Fix undefined uiRaw in popup, add gulp building mini-version, rm micro-version
|  | @ -1 +0,0 @@ | ||||||
| Blue Ribbon Icon: http://www.iconsdb.com/icon-sets/cardboard-blue-icons/ribbon-12-icon.html |  | ||||||
|  | @ -1,313 +0,0 @@ | ||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| console.log('Started.'); |  | ||||||
| 
 |  | ||||||
| window.state = { |  | ||||||
|   lastError: null, |  | ||||||
|   ifNotControllable: false, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| window.whichExtensionHtml = ` |  | ||||||
| 
 |  | ||||||
|   ${chrome.i18n.getMessage('noControl')} |  | ||||||
|   <a href="chrome://settings/search#${chrome.i18n.getMessage('proxy')}"> |  | ||||||
|     ${chrome.i18n.getMessage('which')} |  | ||||||
|   </a>`; |  | ||||||
| 
 |  | ||||||
| const resetBadge = function resetBadge() { |  | ||||||
| 
 |  | ||||||
|   okBadge('M'); |  | ||||||
|   chrome.browserAction.setTitle({title: ''}); |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| window.timeouted = (cb) => (...args) => window.setTimeout(() => cb(...args), 0); |  | ||||||
| 
 |  | ||||||
| const errorJsonReplacer = function errorJsonReplacer(key, value) { |  | ||||||
| 
 |  | ||||||
|   // fooWindow.ErrorEvent !== barWindow.ErrorEvent
 |  | ||||||
|   if (!( value && value.constructor |  | ||||||
|     && ['Error', 'Event'].some( |  | ||||||
|       (suff) => value.constructor.name.endsWith(suff) |  | ||||||
|     ) |  | ||||||
|   )) { |  | ||||||
|     return value; |  | ||||||
|   } |  | ||||||
|   const alt = {}; |  | ||||||
| 
 |  | ||||||
|   Object.getOwnPropertyNames(value).forEach(function(key) { |  | ||||||
| 
 |  | ||||||
|       alt[key] = value[key]; |  | ||||||
| 
 |  | ||||||
|   }, value); |  | ||||||
| 
 |  | ||||||
|   for(const prop in value) { |  | ||||||
|     if (/^[A-Z]/.test(prop)) { |  | ||||||
|       // MOUSEMOVE, CLICK, KEYUP, NONE, etc.
 |  | ||||||
|       continue; |  | ||||||
|     } |  | ||||||
|     alt[prop] = value[prop]; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (value.constructor.name === 'ErrorEvent') { |  | ||||||
|     for(const circularProp of |  | ||||||
|       [  // First line are circular props.
 |  | ||||||
|         'target', 'srcElement', 'path', 'currentTarget', |  | ||||||
|         'bubbles', 'cancelBubble', 'cancelable', 'composed', |  | ||||||
|         'defaultPrevented', 'eventPhase', 'isTrusted', 'returnValue', |  | ||||||
|         'timeStamp']) { |  | ||||||
|       delete alt[circularProp]; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (value.name) { |  | ||||||
|     alt.name = value.name; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return alt; |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const extName = chrome.runtime.getManifest().name; |  | ||||||
| 
 |  | ||||||
| chrome.notifications.onClicked.addListener( timeouted( (notId) => { |  | ||||||
| 
 |  | ||||||
|   chrome.notifications.clear(notId); |  | ||||||
|   const err = window.state.lastError; |  | ||||||
|   err.extName = extName; |  | ||||||
|   const type = 'ext-error'; |  | ||||||
|   const json = JSON.stringify(err, errorJsonReplacer, 0); |  | ||||||
|   const url = 'http://rebrand.ly/ac-error/?json=' + encodeURIComponent(json) |  | ||||||
|     + (type ? '&type=' + encodeURIComponent(type) : '') |  | ||||||
|     + '&version=' + chrome.runtime.getManifest().version; |  | ||||||
|   chrome.tabs.create( |  | ||||||
|     {url: url} |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
| })); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| const mayNotify = function mayNotify( |  | ||||||
|   id, title, errOrMessage, |  | ||||||
|   { |  | ||||||
|     icon = 'default-128.png', |  | ||||||
|     ifSticky = true, |  | ||||||
|   } = {} |  | ||||||
| ) { |  | ||||||
| 
 |  | ||||||
|   const message = errOrMessage.message || errOrMessage.toString(); |  | ||||||
|   chrome.notifications.create( |  | ||||||
|     id, |  | ||||||
|     { |  | ||||||
|       title: title, |  | ||||||
|       message: message, |  | ||||||
|       contextMessage: |  | ||||||
|         extName + ' ' + chrome.runtime.getManifest().version.replace(/\d+\.\d+\./g, ''), |  | ||||||
|       requireInteraction: ifSticky, |  | ||||||
|       type: 'basic', |  | ||||||
|       iconUrl: './icons/' + icon, |  | ||||||
|       isClickable: true, |  | ||||||
|     } |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| window.installListenersOn = function installListenersOn(win, name, cb) { |  | ||||||
| 
 |  | ||||||
|   win.addEventListener('error', (errEvent) => { |  | ||||||
| 
 |  | ||||||
|     window.state.lastError = errEvent; |  | ||||||
|     console.warn(name + ':GLOBAL ERROR', errEvent); |  | ||||||
|     mayNotify('ext-error', 'Ошибка расширения!', errEvent, {icon: 'ext-error-128.png'}); |  | ||||||
| 
 |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   win.addEventListener('unhandledrejection', (event) => { |  | ||||||
| 
 |  | ||||||
|     console.warn(name + ': Unhandled rejection. Throwing error.'); |  | ||||||
|     event.preventDefault(); |  | ||||||
|     console.log('ev', event); |  | ||||||
|     throw event.reason; |  | ||||||
| 
 |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   if (cb) { |  | ||||||
|     // In most cases getBackgroundPage( (bg) => installListenersOn
 |  | ||||||
|     // Without setTimeout errors are swallowed, bug #357568
 |  | ||||||
|     timeouted(cb)(); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| window.installListenersOn(window, 'BG'); |  | ||||||
| 
 |  | ||||||
| const redBadge = function redBadge(msg) { |  | ||||||
| 
 |  | ||||||
|   chrome.browserAction.setBadgeBackgroundColor({ |  | ||||||
|     color: '#db4b2f', |  | ||||||
|   }); |  | ||||||
|   chrome.browserAction.setBadgeText({ |  | ||||||
|     text: msg, |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const defaultColorPromise = new Promise( function (resolve) { |  | ||||||
| 
 |  | ||||||
|   chrome.browserAction.getBadgeBackgroundColor({}, resolve); |  | ||||||
| 
 |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| const okBadge = function okBadge(msg) { |  | ||||||
| 
 |  | ||||||
|   defaultColorPromise.then( function (defaultColor) { |  | ||||||
|     chrome.browserAction.setBadgeBackgroundColor({ |  | ||||||
|       color: defaultColor, |  | ||||||
|     }); |  | ||||||
|     chrome.browserAction.setBadgeText({ |  | ||||||
|       text: msg, |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const mandatory = (err) => { |  | ||||||
| 
 |  | ||||||
|   throw new TypeError('This arg is required!'); |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const throwIfError = (err) => { |  | ||||||
| 
 |  | ||||||
|   if (err) { |  | ||||||
|     throw new Error('Got error in cb!'); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const areSettingsNotControllableFor = function areSettingsNotControllable(details = mandatory()) { |  | ||||||
| 
 |  | ||||||
|   state.ifNotControllable = ['controlled_by_other', 'not_controllable'] |  | ||||||
|     .some( (pref) => details.levelOfControl.startsWith(pref) ); |  | ||||||
| 
 |  | ||||||
|   if (state.ifNotControllable) { |  | ||||||
|     console.warn('Failed, other extension is in control.'); |  | ||||||
|     state.ifNotControlled = true; |  | ||||||
|     redBadge('xCTRL'); |  | ||||||
|     chrome.browserAction.setTitle({title: 'Другое расширение контролирует прокси'}); |  | ||||||
|   } else { |  | ||||||
|     console.log('Settings are under our control.'); |  | ||||||
|     state.ifNotControlled = !details.levelOfControl.startsWith('controlled_by_this'); |  | ||||||
|     resetBadge(); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| chrome.proxy.settings.onChange.addListener( (details) => { |  | ||||||
| 
 |  | ||||||
|   console.log('CHANGED prx'); |  | ||||||
|   areSettingsNotControllableFor(details); |  | ||||||
| 
 |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| const updateControlState = function updateControlState(cb = mandatory()) { |  | ||||||
| 
 |  | ||||||
|   chrome.proxy.settings.get({}, timeouted( (details) => { |  | ||||||
| 
 |  | ||||||
|     areSettingsNotControllableFor(details); |  | ||||||
|     cb(); |  | ||||||
| 
 |  | ||||||
|   })); |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const mayUpdatePac = function mayUpdatePac(cb = mandatory()) { |  | ||||||
| 
 |  | ||||||
|   if (Date.now() < (localStorage.lastPacUpdateStamp || 0) + 12*60*60*1000 ) { |  | ||||||
|     console.log('Too early for an update.' ); |  | ||||||
|     return cb(); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   fetch('https://rebrand.ly/ac-light-pac').then( |  | ||||||
|     (res) => { |  | ||||||
| 
 |  | ||||||
|       const status = res.status; |  | ||||||
|       if ( !( status >= 200 && status < 300 || status === 304 ) ) { |  | ||||||
|         return cb(new Error('Не удалось скачать скрипт, ошибка ' + status)); |  | ||||||
|       } |  | ||||||
|       return res.text(); |  | ||||||
| 
 |  | ||||||
|     }, |  | ||||||
|     cb |  | ||||||
|   ).then( (pacData) => { |  | ||||||
| 
 |  | ||||||
|     console.log('Updating PAC...'); |  | ||||||
|     chrome.proxy.settings.set( |  | ||||||
|       { |  | ||||||
|         value: { |  | ||||||
|           mode: 'pac_script', |  | ||||||
|           pacScript: { |  | ||||||
|             // Use only with extension!
 |  | ||||||
|             data: pacData |  | ||||||
|           }, |  | ||||||
|         }, |  | ||||||
|       }, |  | ||||||
|       timeouted(() => { |  | ||||||
| 
 |  | ||||||
|         const err = chrome.runtime.lastError || chrome.extension.lastError; |  | ||||||
|         if(err) { |  | ||||||
|           console.log('Updated with error:', err); |  | ||||||
|           state.lastError = err; |  | ||||||
|           redBadge('ERR'); |  | ||||||
|           chrome.browserAction.setTitle({title: 'Произошла ошибка'}); |  | ||||||
|           setTimeout(resetBadge, 10000); |  | ||||||
|           return cb(err); |  | ||||||
|         } |  | ||||||
|         console.log('Updated, no errors.'); |  | ||||||
|         localStorage.lastPacUpdateStamp = Date.now(); |  | ||||||
|         updateControlState( () => { |  | ||||||
| 
 |  | ||||||
|           if(state.ifNotControlled) { |  | ||||||
|             cb(new Error(window.whichExtensionHtml)); |  | ||||||
|           } else { |  | ||||||
|             cb(); |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|       }) |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|   }, |  | ||||||
|   cb |  | ||||||
| ); |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| window.switchPac = function switchPac(onOff, cb = mandatory()) { |  | ||||||
| 
 |  | ||||||
|   if(onOff !== 'off') { |  | ||||||
|     localStorage.onOff = 'on'; |  | ||||||
|     chrome.browserAction.setIcon( {path: './icons/default-128.png'} ); |  | ||||||
|     return mayUpdatePac(cb); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   chrome.proxy.settings.clear({}, timeouted(() => { |  | ||||||
| 
 |  | ||||||
|     localStorage.lastPacUpdateStamp = 0; |  | ||||||
|     localStorage.onOff = 'off'; |  | ||||||
|     chrome.browserAction.setIcon({ |  | ||||||
|       path: './icons/default-grayscale-128.png', |  | ||||||
|     }); |  | ||||||
|     cb(); |  | ||||||
| 
 |  | ||||||
|   })); |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| resetBadge(); |  | ||||||
| switchPac( localStorage.onOff, (err) => { |  | ||||||
| 
 |  | ||||||
|   updateControlState(() => throwIfError(err)); |  | ||||||
| 
 |  | ||||||
| }); |  | ||||||
|  | @ -1,17 +0,0 @@ | ||||||
| { |  | ||||||
|   "extName": { |  | ||||||
|     "message": "Облегчённый обход блокировок Рунета" |  | ||||||
|   }, |  | ||||||
|   "extDesc": { |  | ||||||
|     "message": "Обход интернет-цензуры в России: https://rebrand.ly/ac-wiki" |  | ||||||
|   }, |  | ||||||
|   "proxy": { |  | ||||||
|     "message": "прокси" |  | ||||||
|   }, |  | ||||||
|   "noControl": { |  | ||||||
|     "message": "Другое расширение контролирует настройки прокси!" |  | ||||||
|   }, |  | ||||||
|   "which": { |  | ||||||
|     "message": "Какое?" |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  | @ -1,111 +0,0 @@ | ||||||
| <!DOCTYPE html> |  | ||||||
| <html style="display: none; will-change: display"> |  | ||||||
|   <head> |  | ||||||
|     <style> |  | ||||||
|       body { |  | ||||||
|         margin: 0; |  | ||||||
|       } |  | ||||||
|       .hor-padded { |  | ||||||
|         padding-left: 1.4em; |  | ||||||
|         padding-right: 1.4em; |  | ||||||
|       } |  | ||||||
|       header, .control-row { |  | ||||||
|         white-space: nowrap; |  | ||||||
|         word-break: keep-all; |  | ||||||
|       } |  | ||||||
|       input[type="radio"], label { |  | ||||||
|         cursor: pointer; |  | ||||||
|       } |  | ||||||
|       .control-row { |  | ||||||
|         display: flex; |  | ||||||
|         justify-content: space-between; |  | ||||||
|         align-items: center; |  | ||||||
|         margin: 2em 1em 1em; |  | ||||||
|       } |  | ||||||
|       header { |  | ||||||
|         padding-bottom: 0.4em; |  | ||||||
|       } |  | ||||||
|       hr { |  | ||||||
|         border-width: 1px 0 0 0; |  | ||||||
|         margin: 0 0 0.6em 0; |  | ||||||
|         padding: 0; |  | ||||||
|       } |  | ||||||
|       .greeting { |  | ||||||
|         display: none; |  | ||||||
|       } |  | ||||||
|       :root:not(.if-error) .greeting { |  | ||||||
|         display: block; |  | ||||||
|       } |  | ||||||
|       :root:not(.if-not-controlled) .if-not-controlled, |  | ||||||
|       :root:not(.if-error) .if-error |  | ||||||
|       { |  | ||||||
|         display: none; |  | ||||||
|       } |  | ||||||
|       .ver-padded { |  | ||||||
|         padding-top: 1em; |  | ||||||
|         padding-bottom: 1em; |  | ||||||
|       } |  | ||||||
|       .centered { |  | ||||||
|         text-align: center; |  | ||||||
|       } |  | ||||||
|       .warn { |  | ||||||
|         background-color: red; |  | ||||||
|         color: white; |  | ||||||
|         font-weight: bold; |  | ||||||
| 
 |  | ||||||
|         border-bottom: 1px solid #bfbfbf; |  | ||||||
|       } |  | ||||||
|       .warn a { |  | ||||||
|         color: white; |  | ||||||
|       } |  | ||||||
|       header, main { |  | ||||||
|         border-bottom: 1px solid #bfbfbf; |  | ||||||
|       } |  | ||||||
|       ul, ol { |  | ||||||
|         margin: 0; |  | ||||||
|         padding: 0; |  | ||||||
|         list-style-type: none; |  | ||||||
|       }       |  | ||||||
|       li, li > * { |  | ||||||
|         vertical-align: middle; |  | ||||||
|       } |  | ||||||
|       #pac-switch { |  | ||||||
|         display: flex; |  | ||||||
|         justify-content: space-around; |  | ||||||
|         align-items: center; |  | ||||||
|       } |  | ||||||
|       #pac-switch li { |  | ||||||
|         display: inline-block; |  | ||||||
|         padding: 1em; |  | ||||||
|       } |  | ||||||
|     </style> |  | ||||||
|   </head> |  | ||||||
|   <body> |  | ||||||
|     <section class="if-not-controlled warn hor-padded ver-padded centered" id="which-extension"></section> |  | ||||||
|     <header class="hor-padded"> |  | ||||||
|       <h2>Обход блокировок Рунета МИКРО</h2> |  | ||||||
|     </header> |  | ||||||
|     <main class="hor-padded ver-padded"> |  | ||||||
|       <section> |  | ||||||
|         <ol id="pac-switch"> |  | ||||||
|           <li><input type="radio" value="on" id="pac-on" name="pac-switch"/> <label for="pac-on">ON</label></li> |  | ||||||
|           <li><input type="radio" value="off" id="pac-off" name="pac-switch"/> <label for="pac-off">OFF</label></li> |  | ||||||
|         </ol> |  | ||||||
|       </section> |  | ||||||
|     </main> |  | ||||||
|     <footer> |  | ||||||
|       <section id="status" class="greeting hor-padded" style="padding-top: 0.5em; padding-bottom: 0"> |  | ||||||
|         Данная версия предназначена для слабых компьютеров, она не сообщает о разблокировках и не имеет настроек. |  | ||||||
|       </section> |  | ||||||
|       <section class="if-error centered"> |  | ||||||
|         <div>Ошибка!</div> |  | ||||||
|         <span id="last-error"></span> |  | ||||||
|       </section>       |  | ||||||
|       <div class="control-row"> |  | ||||||
|         <input type="button" value="Готово" class="close-button"> <a href="../debug/index.html" style="text-decoration: none; margin-left: 1em;">Полная версия расширения</a> |  | ||||||
|       </div> |  | ||||||
|     </footer> |  | ||||||
|     <script src="./index.js"></script> |  | ||||||
|     <script src="./keep-links-clickable.js"></script> |  | ||||||
|   </body> |  | ||||||
| </html> |  | ||||||
|  | @ -1,61 +0,0 @@ | ||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| chrome.runtime.getBackgroundPage( (backgroundPage) => { |  | ||||||
| 
 |  | ||||||
|   const state = backgroundPage.state; |  | ||||||
| 
 |  | ||||||
|   if( state.ifNotControllable ) { |  | ||||||
|     document.getElementById('which-extension').innerHTML = backgroundPage.whichExtensionHtml; |  | ||||||
|     document.documentElement.classList.add('if-not-controlled'); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if ( state.lastError) { |  | ||||||
| 
 |  | ||||||
|     const err = ['message', 'stack', 'name'].reduce((acc, prop) => { |  | ||||||
| 
 |  | ||||||
|       acc[prop] = state.lastError[prop]; |  | ||||||
|       return acc; |  | ||||||
| 
 |  | ||||||
|     }, {}); |  | ||||||
|     document.getElementById('last-error').innerHTML = JSON.stringify(err); |  | ||||||
|     document.documentElement.classList.add('if-error'); |  | ||||||
| 
 |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   const setStatusTo = (msg) => { |  | ||||||
|     document.getElementById('status').innerHTML = msg; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   if(localStorage.onOff === 'on') { |  | ||||||
|     document.getElementById('pac-on').checked = true; |  | ||||||
|   } else { |  | ||||||
|     document.getElementById('pac-off').checked = true; |  | ||||||
|   } |  | ||||||
|   document.getElementById('pac-switch').onclick = function(event) { |  | ||||||
| 
 |  | ||||||
|     if(event.target.tagName !== 'INPUT') { |  | ||||||
|       return true; |  | ||||||
|     } |  | ||||||
|     setStatusTo('Ждите...'); |  | ||||||
|     const cb = () => { |  | ||||||
| 
 |  | ||||||
|       event.target.checked = true; |  | ||||||
|       setStatusTo('Готово!'); |  | ||||||
| 
 |  | ||||||
|     }; |  | ||||||
|     if (event.target.id === 'pac-on') { |  | ||||||
|       backgroundPage.switchPac('on', cb); |  | ||||||
|     } else { |  | ||||||
|       backgroundPage.switchPac('off', cb); |  | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
| 
 |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   // CLOSE BUTTON
 |  | ||||||
| 
 |  | ||||||
|   document.querySelector('.close-button').onclick = () => window.close(); |  | ||||||
| 
 |  | ||||||
|   document.documentElement.style.display = ''; |  | ||||||
| 
 |  | ||||||
| }); |  | ||||||
							
								
								
									
										4
									
								
								extensions/chromium/runet-censorship-bypass/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,4 @@ | ||||||
|  | node_modules | ||||||
|  | npm-debug.log | ||||||
|  | .swp | ||||||
|  | build/ | ||||||
							
								
								
									
										0
									
								
								extensions/chromium/runet-censorship-bypass/README.md
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						|  | @ -1,49 +0,0 @@ | ||||||
| 'use strict'; |  | ||||||
| 
 |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
|   const createMenuLinkEntry = (title, tab2url) => chrome.contextMenus.create({ |  | ||||||
|     title: title, |  | ||||||
|     contexts: ['browser_action'], |  | ||||||
|     onclick: |  | ||||||
|       (menuInfo, tab) => Promise.resolve( tab2url( tab ) ) |  | ||||||
|         .then( (url) => chrome.tabs.create({url: url}) ), |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   createMenuLinkEntry( |  | ||||||
|     'Сайт доступен из-за границы?', |  | ||||||
|     (tab) => `data:text/html;charset=utf8,<title>Запрашиваю...</title>
 |  | ||||||
|             <form class='tracker-form' method='POST' |  | ||||||
|               action='https://www.host-tracker.com/ru/InstantCheck/Create'> |  | ||||||
|             <input name='InstantCheckUrl' value='${new URL(tab.url).hostname}' |  | ||||||
|               type='hidden'> |  | ||||||
|             </form> |  | ||||||
|             <script>document.querySelector('.tracker-form').submit()<\/script>` |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
|   createMenuLinkEntry( |  | ||||||
|     'Сайт в реестре блокировок?', |  | ||||||
|     (tab) => 'https://antizapret.info/index.php?search=' + new URL(tab.url).hostname |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
|   createMenuLinkEntry( |  | ||||||
|     'Из архива archive.org', |  | ||||||
|     (tab) => 'https://web.archive.org/web/*/' + tab.url |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
|   createMenuLinkEntry( |  | ||||||
|     'Через Google Translate', |  | ||||||
|     (tab) => 'https://translate.google.com/translate?hl=&sl=en&tl=ru&anno=2&sandbox=1&u=' + tab.url |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
|   createMenuLinkEntry( |  | ||||||
|     'Другие варианты разблокировки', |  | ||||||
|     (tab) => 'https://rebrand.ly/ac-unblock#' + tab.url |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
|   createMenuLinkEntry( |  | ||||||
|     'Руководство / Помощь / Ссылки', |  | ||||||
|     (tab) => 'https://rebrand.ly/ac-wiki' |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1,17 +0,0 @@ | ||||||
| { |  | ||||||
|   "extName": { |  | ||||||
|     "message": "Runet Censorship Bypass" |  | ||||||
|   }, |  | ||||||
|   "extDesc": { |  | ||||||
|       "message": "Circumvent Russian Internet Censorship: https://rebrand.ly/ac-wiki" |  | ||||||
|   }, |  | ||||||
|   "proxy": { |  | ||||||
|     "message": "proxy" |  | ||||||
|   }, |  | ||||||
|   "noControl": { |  | ||||||
|     "message": "Other extension controls proxy!" |  | ||||||
|   }, |  | ||||||
|   "which": { |  | ||||||
|     "message": "Which?" |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| Before Width: | Height: | Size: 10 KiB | 
| Before Width: | Height: | Size: 5.2 KiB | 
| Before Width: | Height: | Size: 9.3 KiB | 
|  | @ -1,37 +0,0 @@ | ||||||
| 'use strict'; |  | ||||||
| /* |  | ||||||
| In popup links are not clickable at all, fix it. |  | ||||||
| On other pages "chrome://" links are not clickable, fix it. |  | ||||||
| Use only if really required because of performance penalty. |  | ||||||
| */ |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
|   const target = document.documentElement; |  | ||||||
| 
 |  | ||||||
|   const updateLinks = () => { |  | ||||||
| 
 |  | ||||||
|     const links = document.querySelectorAll('a:not([href=""])'); |  | ||||||
|     for (let i = 0; i < links.length; i++) { |  | ||||||
|       const ln = links[i]; |  | ||||||
|       const location = ln.href; |  | ||||||
|       ln.onclick = function() { |  | ||||||
| 
 |  | ||||||
|         chrome.tabs.create({active: !this.dataset.inBg, url: location}); |  | ||||||
|         return false; |  | ||||||
| 
 |  | ||||||
|       }; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   new MutationObserver( updateLinks ) |  | ||||||
|     .observe(target, { |  | ||||||
|       attributes: true, |  | ||||||
|       subtree: true, |  | ||||||
|       childList: true, |  | ||||||
|       characterData: false, |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|   document.addEventListener('DOMContentLoaded', updateLinks); |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										86
									
								
								extensions/chromium/runet-censorship-bypass/gulpfile.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,86 @@ | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | const gulp = require('gulp'); | ||||||
|  | const del = require('del'); | ||||||
|  | const through = require('through2'); | ||||||
|  | const PluginError = require('gulp-util').PluginError; | ||||||
|  | 
 | ||||||
|  | const PluginName = 'Template literals'; | ||||||
|  | 
 | ||||||
|  | const templatePlugin = (context) => through.obj(function(file, encoding, cb) { | ||||||
|  | 
 | ||||||
|  |   const tjson = '.tmpl.json'; | ||||||
|  |   if (file.path.endsWith(tjson)) { | ||||||
|  | 
 | ||||||
|  |     file.path = file.path.replace(new RegExp(`${tjson}$`), '.json'); | ||||||
|  | 
 | ||||||
|  |     if (file.isStream()) { | ||||||
|  |       return cb(new PluginError(PluginName, 'Streams not supported!')); | ||||||
|  |     } else if (file.isBuffer()) { | ||||||
|  | 
 | ||||||
|  |       const stringsContext = new Proxy(context, { | ||||||
|  |         get: function(target, prop) { | ||||||
|  |           return target[prop] || ''; | ||||||
|  |         }, | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       try { | ||||||
|  |         file.contents = new Buffer( | ||||||
|  |           (new Function('ctx', 'return `' + String(file.contents) + '`;'))(stringsContext) | ||||||
|  |         ); | ||||||
|  |       } catch(e) { | ||||||
|  |         return cb(new PluginError(PluginName, e)); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  |   cb(null, file); | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | gulp.task('default', ['build']); | ||||||
|  | 
 | ||||||
|  | gulp.task('clean', function() { | ||||||
|  | 
 | ||||||
|  |   return del.sync('./build'); | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const commonContext = { | ||||||
|  |   version: '0.19', | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const contextMini = Object.assign({ | ||||||
|  |   nameSuffixEn: ' MINI', | ||||||
|  |   nameSuffixRu: ' МИНИ', | ||||||
|  | }, commonContext); | ||||||
|  | 
 | ||||||
|  | gulp.task('_cp-common', ['clean'], function() { | ||||||
|  | 
 | ||||||
|  |   gulp.src(['./src/extension-common/**/*']) | ||||||
|  |     .pipe(templatePlugin(contextMini)) | ||||||
|  |     .pipe(gulp.dest('./build/extension-mini')) | ||||||
|  | 
 | ||||||
|  |   gulp.src(['./src/extension-common/**/*']) | ||||||
|  |     .pipe(templatePlugin(commonContext)) | ||||||
|  |     .pipe(gulp.dest('./build/extension-full')); | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | gulp.task('_cp-mini', ['_cp-common'], function() { | ||||||
|  | 
 | ||||||
|  |   gulp.src(['./src/extension-mini/**/*']) | ||||||
|  |     .pipe(templatePlugin(contextMini)) | ||||||
|  |     .pipe(gulp.dest('./build/extension-mini')); | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | gulp.task('_cp-full', ['_cp-common'], function() { | ||||||
|  | 
 | ||||||
|  |   gulp.src(['./src/extension-full/**/*']) | ||||||
|  |     .pipe(templatePlugin(commonContext)) | ||||||
|  |     .pipe(gulp.dest('./build/extension-full')); | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | gulp.task('build', ['_cp-mini', '_cp-full']); | ||||||
							
								
								
									
										0
									
								
								extensions/chromium/runet-censorship-bypass/kasparov.ru-title.jpg
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						| Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB | 
							
								
								
									
										0
									
								
								extensions/chromium/runet-censorship-bypass/krrb-kiwiirc-irccloud-slideshare.jpg
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						| Before Width: | Height: | Size: 306 KiB After Width: | Height: | Size: 306 KiB | 
|  | @ -1,10 +1,8 @@ | ||||||
| { | { | ||||||
|   "name": "russian-censorship-bypass", |   "name": "runet-censorship-bypass", | ||||||
|   "version": "0.0.15", |   "version": "0.0.19", | ||||||
|   "description": "Development tools for chromium extension", |   "description": "Development tools for chromium extension", | ||||||
|   "main": "index.js", |  | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "test": "echo \"Error: no test specified\" && exit 1", |  | ||||||
|     "lint": "./node_modules/.bin/eslint ./runet-censorship-bypass/extension/**/*.js --ignore-pattern vendor" |     "lint": "./node_modules/.bin/eslint ./runet-censorship-bypass/extension/**/*.js --ignore-pattern vendor" | ||||||
|   }, |   }, | ||||||
|   "author": "Ilya Ig. Petrov", |   "author": "Ilya Ig. Petrov", | ||||||
|  | @ -12,5 +10,10 @@ | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "eslint": "^3.15.0", |     "eslint": "^3.15.0", | ||||||
|     "eslint-config-google": "^0.7.1" |     "eslint-config-google": "^0.7.1" | ||||||
|  |   }, | ||||||
|  |   "dependencies": { | ||||||
|  |     "del": "^2.2.2", | ||||||
|  |     "gulp": "^3.9.1", | ||||||
|  |     "through2": "^2.0.3" | ||||||
|   } |   } | ||||||
| } | } | ||||||
							
								
								
									
										0
									
								
								extensions/chromium/runet-censorship-bypass/slideshare-menu.jpg
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						| Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB | 
|  | @ -84,6 +84,18 @@ | ||||||
| 
 | 
 | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|  |     addEventHandler(type, handler) { | ||||||
|  | 
 | ||||||
|  |       document.addEventListener(type, (event) => handler(...event.detail)); | ||||||
|  | 
 | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     fireEvent(type, ...args) { | ||||||
|  | 
 | ||||||
|  |       document.dispatchEvent( new CustomEvent(type, { detail: args }) ); | ||||||
|  | 
 | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|     createStorage(prefix) { |     createStorage(prefix) { | ||||||
| 
 | 
 | ||||||
|       return function state(key, value) { |       return function state(key, value) { | ||||||
|  | @ -113,7 +113,6 @@ | ||||||
| 
 | 
 | ||||||
|     isControllable(details) { |     isControllable(details) { | ||||||
| 
 | 
 | ||||||
|       console.log('IS',details); |  | ||||||
|       this.ifControllable = window.utils.areSettingsControllableFor(details); |       this.ifControllable = window.utils.areSettingsControllableFor(details); | ||||||
| 
 | 
 | ||||||
|       if (this.ifControllable) { |       if (this.ifControllable) { | ||||||
|  | @ -321,10 +321,12 @@ | ||||||
|           } |           } | ||||||
| 
 | 
 | ||||||
|           const hosts = par.map( (ps) => ps.split(/\s+/)[1] ); |           const hosts = par.map( (ps) => ps.split(/\s+/)[1] ); | ||||||
|           window.apis.ipToHost.replaceAllAsync( |           window.utils.fireEvent('ip-to-host-replace-all', hosts, throwIfError); | ||||||
|  |           cb(null, null, ...warns); | ||||||
|  |           /*window.apis.ipToHost.replaceAllAsync( | ||||||
|             hosts, |             hosts, | ||||||
|             (...args) => cb(...args, ...warns) |             (...args) => cb(...args, ...warns) | ||||||
|           ); |           );*/ | ||||||
| 
 | 
 | ||||||
|         } |         } | ||||||
|       ); |       ); | ||||||
|  | @ -93,7 +93,9 @@ | ||||||
|       'Getting IPs for PAC hosts...', |       'Getting IPs for PAC hosts...', | ||||||
|       cb |       cb | ||||||
|     ); |     ); | ||||||
|     window.apis.ipToHost.updateAllAsync(cb); |     window.utils.fireEvent('ip-to-host-update-all', throwIfError); | ||||||
|  |     cb(); | ||||||
|  |     //window.apis.ipToHost.updateAllAsync(cb);
 | ||||||
| 
 | 
 | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  | @ -197,7 +199,7 @@ | ||||||
|       }, |       }, | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|     _currentPacProviderKey: 'Антицензорити', |     _currentPacProviderKey: 'Антизапрет', | ||||||
| 
 | 
 | ||||||
|     /* Is it the first time extension installed? |     /* Is it the first time extension installed? | ||||||
|        Do something, e.g. initiate PAC sync. |        Do something, e.g. initiate PAC sync. | ||||||
|  | @ -2,6 +2,8 @@ | ||||||
| 
 | 
 | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|  |   const timeouted = window.utils.timeouted; | ||||||
|  | 
 | ||||||
|   let seqId = 0; |   let seqId = 0; | ||||||
| 
 | 
 | ||||||
|   const createMenuLinkEntry = (title, tab2url) => { |   const createMenuLinkEntry = (title, tab2url) => { | ||||||
|  | @ -17,7 +19,7 @@ | ||||||
| 
 | 
 | ||||||
|         const err = chrome.runtime.lastError; |         const err = chrome.runtime.lastError; | ||||||
|         if(err) { |         if(err) { | ||||||
|           console.warn('CTX MENU ERR', err); |           console.warn('Context menu error:', err); | ||||||
|           throw err; |           throw err; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | Files of this directory must be copied into final build without modifications. | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| { | { | ||||||
|   "extName": { |   "extName": { | ||||||
|     "message": "Runet Censorship Bypass MICRO" |     "message": "Runet Censorship Bypass${ctx.nameSuffixEn}" | ||||||
|   }, |   }, | ||||||
|   "extDesc": { |   "extDesc": { | ||||||
|       "message": "Circumvent Russian Internet Censorship: https://rebrand.ly/ac-wiki" |     "message": "Circumvent Russian Internet Censorship: https://rebrand.ly/ac-wiki" | ||||||
|   }, |   }, | ||||||
|   "proxy": { |   "proxy": { | ||||||
|     "message": "proxy" |     "message": "proxy" | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| { | { | ||||||
|   "extName": { |   "extName": { | ||||||
|     "message": "Обход блокировок Рунета" |     "message": "Обход блокировок Рунета${ctx.nameSuffixRu}" | ||||||
|   }, |   }, | ||||||
|   "extDesc": { |   "extDesc": { | ||||||
|     "message": "Обход интернет-цензуры в России: https://rebrand.ly/ac-wiki" |     "message": "Обход интернет-цензуры в России: https://rebrand.ly/ac-wiki" | ||||||
| Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB | 
| Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB | 
| Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB | 
| Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB | 
| Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB | 
| Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB | 
|  | @ -226,7 +226,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => | ||||||
|         }; |         }; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // IF INSIDE OPTIONS
 |       // IF INSIDE OPTIONS TAB
 | ||||||
| 
 | 
 | ||||||
|       const currentTab = await new Promise( |       const currentTab = await new Promise( | ||||||
|         (resolve) => chrome.tabs.query( |         (resolve) => chrome.tabs.query( | ||||||
|  | @ -503,6 +503,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => | ||||||
|         const _firstChild = modPanel.firstChild; |         const _firstChild = modPanel.firstChild; | ||||||
|         const keyToLi = {}; |         const keyToLi = {}; | ||||||
|         const customProxyStringKey = 'customProxyStringRaw'; |         const customProxyStringKey = 'customProxyStringRaw'; | ||||||
|  |         const uiRaw = 'ui-proxy-string-raw'; | ||||||
| 
 | 
 | ||||||
|         for(const conf of pacKitchen.getOrderedConfigs()) { |         for(const conf of pacKitchen.getOrderedConfigs()) { | ||||||
| 
 | 
 | ||||||
|  | @ -518,7 +519,6 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => | ||||||
|           if (key !== customProxyStringKey) { |           if (key !== customProxyStringKey) { | ||||||
|             li.innerHTML += infoSign(conf.desc); |             li.innerHTML += infoSign(conf.desc); | ||||||
|           } else { |           } else { | ||||||
|             const uiRaw = 'ui-proxy-string-raw'; |  | ||||||
|             li.innerHTML += `<a href="${conf.url}" class="info-sign info-url">🛈</a><br/>
 |             li.innerHTML += `<a href="${conf.url}" class="info-sign info-url">🛈</a><br/>
 | ||||||
| <textarea | <textarea | ||||||
|   spellcheck="false" |   spellcheck="false" | ||||||
|  | @ -186,7 +186,7 @@ | ||||||
| 
 | 
 | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   window.apis.ipToHost = { |   const self = window.apis.ipToHost = { | ||||||
| 
 | 
 | ||||||
|     persist() { |     persist() { | ||||||
| 
 | 
 | ||||||
|  | @ -276,20 +276,6 @@ | ||||||
| 
 | 
 | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     updateAllAsync(cb = mandatory()) { |  | ||||||
| 
 |  | ||||||
|       this._updateAllAsync((err, ...args) => { |  | ||||||
| 
 |  | ||||||
|         if (!err) { |  | ||||||
|           this.persist(); |  | ||||||
|         } |  | ||||||
|         cb(err, ...args); |  | ||||||
| 
 |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     _replaceAllAsync(hostArr = mandatory(), cb) { |     _replaceAllAsync(hostArr = mandatory(), cb) { | ||||||
| 
 | 
 | ||||||
|       if (typeof(hostArr) === 'function') { |       if (typeof(hostArr) === 'function') { | ||||||
|  | @ -306,6 +292,21 @@ | ||||||
| 
 | 
 | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|  |     // PUBLIC
 | ||||||
|  | 
 | ||||||
|  |     updateAllAsync(cb = mandatory()) { | ||||||
|  | 
 | ||||||
|  |       this._updateAllAsync((err, ...args) => { | ||||||
|  | 
 | ||||||
|  |         if (!err) { | ||||||
|  |           this.persist(); | ||||||
|  |         } | ||||||
|  |         cb(err, ...args); | ||||||
|  | 
 | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|     replaceAllAsync(addrArr, cb = mandatory()) { |     replaceAllAsync(addrArr, cb = mandatory()) { | ||||||
| 
 | 
 | ||||||
|       console.log('Replacing...'); |       console.log('Replacing...'); | ||||||
|  | @ -336,4 +337,7 @@ | ||||||
| 
 | 
 | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  |   window.utils.addEventHandler('ip-to-host-update-all', (...args) => self.updateAllAsync(...args) ); | ||||||
|  |   window.utils.addEventHandler('ip-to-host-replace-all', (...args) => self.replaceAllAsync(...args) ); | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| { | { | ||||||
|   "manifest_version": 2, |   "manifest_version": 2, | ||||||
| 
 | 
 | ||||||
|   "name": "__MSG_extName__ 0.19", |   "name": "__MSG_extName__", | ||||||
|   "default_locale": "ru", |   "default_locale": "ru", | ||||||
|   "description": "__MSG_extDesc__", |   "description": "__MSG_extDesc__", | ||||||
|   "version": "0.0.0.19", |   "version": "0.0.${ctx.version}", | ||||||
|   "icons": { |   "icons": { | ||||||
|     "128": "/icons/default-128.png" |     "128": "/icons/default-128.png" | ||||||
| 	}, | 	}, | ||||||
|  | @ -36,7 +36,7 @@ | ||||||
|     ] |     ] | ||||||
|   }, |   }, | ||||||
|   "browser_action": { |   "browser_action": { | ||||||
|     "default_title": "Этот сайт благословлён 0.19", |     "default_title": "Этот сайт благословлён ${ctx.version}", | ||||||
|     "default_popup": "/pages/choose-pac-provider/index.html" |     "default_popup": "/pages/choose-pac-provider/index.html" | ||||||
|   }, |   }, | ||||||
|   "options_ui": { |   "options_ui": { | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | 'use strict'; | ||||||
|  | 
 | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |   chrome.browserAction.setBadgeText({text: 'M'}); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -1,18 +1,20 @@ | ||||||
| { | { | ||||||
|   "manifest_version": 2, |   "manifest_version": 2, | ||||||
| 
 | 
 | ||||||
|   "name": "__MSG_extName__ 0.17", |   "name": "__MSG_extName__", | ||||||
|   "default_locale": "ru", |   "default_locale": "ru", | ||||||
|   "description": "__MSG_extDesc__", |   "description": "__MSG_extDesc__", | ||||||
|   "version": "0.0.0.17", |   "version": "0.0.${ctx.version}", | ||||||
|   "icons": { |   "icons": { | ||||||
|     "128": "/icons/default-128.png" |     "128": "/icons/default-128.png" | ||||||
| 	}, |   }, | ||||||
|   "author": "ilyaigpetrov@gmail.com", |   "author": "ilyaigpetrov@gmail.com", | ||||||
|   "homepage_url": "https://github.com/anticensorship-russia/chromium-extension", |   "homepage_url": "https://github.com/anticensorship-russia/chromium-extension", | ||||||
| 
 | 
 | ||||||
|   "permissions": [ |   "permissions": [ | ||||||
|     "proxy", |     "proxy", | ||||||
|  |     "alarms", | ||||||
|  |     "storage", | ||||||
|     "<all_urls>", |     "<all_urls>", | ||||||
|     "tabs", |     "tabs", | ||||||
|     "contextMenus", |     "contextMenus", | ||||||
|  | @ -22,16 +24,22 @@ | ||||||
|   "background": { |   "background": { | ||||||
|     "persistent": false, |     "persistent": false, | ||||||
|     "scripts": [ |     "scripts": [ | ||||||
|       "00-set-pac.js", |       "00-init-apis.js", | ||||||
|       "40-context-menus.js" |       "11-error-handlers-api.js", | ||||||
|  |       "12-errors-lib.js", | ||||||
|  |       "13-http-lib.js", | ||||||
|  |       "15-pac-kitchen-api.js", | ||||||
|  |       "17-sync-pac-script-with-pac-provider-api.js", | ||||||
|  |       "40-context-menus.js", | ||||||
|  |       "50-for-mini-only.js" | ||||||
|     ] |     ] | ||||||
|   }, |   }, | ||||||
|   "browser_action": { |   "browser_action": { | ||||||
|     "default_title": "Этот сайт благословлён 0.17", |     "default_title": "Этот сайт благословлён ${ctx.version}-mini", | ||||||
|     "default_popup": "pages/show-state/index.html" |     "default_popup": "/pages/choose-pac-provider/index.html" | ||||||
|   }, |   }, | ||||||
|   "options_ui": { |   "options_ui": { | ||||||
|      "page": "pages/show-state/index.html", |      "page": "/pages/choose-pac-provider/index.html", | ||||||
|      "chrome_style": true |      "chrome_style": true | ||||||
|    } |    } | ||||||
| } | } | ||||||