diff options
-rw-r--r-- | background/page_info_server.js | 9 | ||||
-rw-r--r-- | background/policy_injector.js | 65 | ||||
-rwxr-xr-x | build.sh | 6 | ||||
-rw-r--r-- | common/message_server.js (renamed from background/message_server.js) | 0 | ||||
-rw-r--r-- | common/misc.js | 97 | ||||
-rw-r--r-- | content/freezer.js | 2 | ||||
-rw-r--r-- | content/main.js | 31 | ||||
-rw-r--r-- | content/page_actions.js | 1 | ||||
-rw-r--r-- | copyright | 9 | ||||
-rw-r--r-- | html/options_main.js | 25 | ||||
-rw-r--r-- | icons/hachette.svg | 110 | ||||
-rw-r--r-- | icons/hachette128.png | bin | 0 -> 6031 bytes | |||
-rw-r--r-- | icons/hachette16.png | bin | 0 -> 752 bytes | |||
-rw-r--r-- | icons/hachette32.png | bin | 0 -> 1358 bytes | |||
-rw-r--r-- | icons/hachette48.png | bin | 0 -> 2154 bytes | |||
-rw-r--r-- | icons/hachette64.png | bin | 0 -> 2908 bytes | |||
-rw-r--r-- | manifest.json | 12 | ||||
-rwxr-xr-x | re-generate_icons.sh | 8 |
18 files changed, 184 insertions, 191 deletions
diff --git a/background/page_info_server.js b/background/page_info_server.js index 49919fd..6f02750 100644 --- a/background/page_info_server.js +++ b/background/page_info_server.js @@ -40,11 +40,6 @@ async function handle_subscription(connection_data, message) connection_data.port.postMessage(["new_url", query_all(url)]); } -function remove_storage_listener(cb) -{ - storage.remove_change_listener(cb); -} - function new_connection(port) { console.log("new page info connection!"); @@ -59,7 +54,9 @@ function new_connection(port) storage.add_change_listener(_handle_change); port.onMessage.addListener(m => handle_subscription(connection_data, m)); - port.onDisconnect.addListener(() => remove_storage_listener(handle_change)); + port.onDisconnect.addListener( + () => storage.remove_change_listener(_handle_change) + ); } async function start_page_info_server() diff --git a/background/policy_injector.js b/background/policy_injector.js index 8301c3f..01da094 100644 --- a/background/policy_injector.js +++ b/background/policy_injector.js @@ -15,8 +15,9 @@ * IMPORT is_mozilla * IMPORT gen_unique * IMPORT gen_nonce + * IMPORT is_privileged_url * IMPORT url_item - * IMPORT url_extract_policy + * IMPORT url_extract_target * IMPORT sign_policy * IMPORT get_query_best * IMPORT csp_rule @@ -39,27 +40,24 @@ function is_csp_header(header) return !!csp_header_names[header.name.toLowerCase()]; } -function is_our_header(header, rule) -{ - return header.value === rule -} - function url_inject(details) { - const targets = url_extract_policy(details.url); - if (targets.current) { + if (is_privileged_url(details.url)) return; - } else if (targets.policy) { - /* Redirect; update policy */ - targets.target = targets.target2; - delete targets.target2 - } + + const targets = url_extract_target(details.url); + if (targets.current) + return; + + /* Redirect; update policy */ + if (targets.policy) + targets.target = ""; let [pattern, settings] = query_best(targets.base_url); + /* Defaults */ if (!pattern) - /* Defaults */ settings = {}; - + const policy = encodeURIComponent( JSON.stringify({ allow: settings.allow, @@ -67,39 +65,40 @@ function url_inject(details) base_url: targets.base_url }) ); - - let redirect_url = targets.base_url; - redirect_url += '#' + sign_policy(policy, new Date()) + policy; - if (targets.target) - redirect_url += targets.target; - if (targets.target2) - redirect_url += targets.target2; - - return {redirectUrl: redirect_url}; + + return { + redirectUrl: [ + targets.base_url, + '#', sign_policy(policy, new Date()), policy, + targets.target, + targets.target2 + ].join("") + }; } -function inject(details) +function headers_inject(details) { - const targets = url_extract_policy(details.url); + const targets = url_extract_target(details.url); + /* Block mis-/unsigned requests */ if (!targets.current) - /* Block mis-/unsigned requests */ return {cancel: true}; const rule = csp_rule(targets.policy.nonce); var headers = details.responseHeaders; + /* + * Chrome doesn't have the buggy behavior of caching headers + * we injected. Firefox does and we have to remove it there. + */ if (!targets.policy.allow || is_mozilla) - /* - * Chrome doesn't have the buggy behavior of caching headers - * we injected. Firefox does and we have to remove it there. - */ headers = headers.filter(h => !is_csp_header(h)); - if (!targets.policy.allow) + if (!targets.policy.allow) { headers.push({ name : header_name, value : rule }); + } return {responseHeaders: headers}; } @@ -123,7 +122,7 @@ async function start_policy_injector() ); browser.webRequest.onHeadersReceived.addListener( - inject, + headers_inject, { urls: ["<all_urls>"], types: ["main_frame", "sub_frame"] @@ -194,7 +194,7 @@ set_browser() { main() { set_browser "$1" - + # placate importers of these, as they are exported by the yet-to-be-created exports_init.js EXPORTS__browser=exports_init.js EXPORTS__is_chrome=exports_init.js @@ -299,7 +299,9 @@ $(map_get EXPORTCODES $FILEKEY) echo "window.killtheweb={is_mozilla: true, browser: this.browser};" > $BUILDDIR/exports_init.js fi - cp -r icons/ copyright licenses/ $BUILDDIR + cp -r copyright licenses/ $BUILDDIR + mkdir $BUILDDIR/icons + cp icons/*.png $BUILDDIR/icons } main "$@" diff --git a/background/message_server.js b/common/message_server.js index ea40487..ea40487 100644 --- a/background/message_server.js +++ b/common/message_server.js diff --git a/common/misc.js b/common/misc.js index b78dbb9..a59ec14 100644 --- a/common/misc.js +++ b/common/misc.js @@ -27,6 +27,23 @@ function gen_nonce() * generating unique, per-site value that can be computed synchronously * and is impossible to guess for a malicious website */ + +/* Uint8toHex is a separate function not exported as (a) it's useful and (b) it will be used in crypto.subtle-based digests */ +function Uint8toHex(data) +{ + let returnValue = ''; + for (let byte of data) + returnValue += ('00' + byte.toString(16)).slice(-2); + return returnValue; +} + +function gen_nonce(length) // Default 16 +{ + let randomData = new Uint8Array(length || 16); + crypto.getRandomValues(randomData); + return Uint8toHex(randomData); +} + function gen_unique(url) { return sha256(get_secure_salt() + url); @@ -52,24 +69,51 @@ function url_item(url) } /* - * Assume a url like: https://example.com/green?illuminati=confirmed#tinky#winky + * Assume a url like: + * https://example.com/green?illuminati=confirmed#<injected-policy>#winky * This function will make it into an object like: * { - * "base_url" : "https://example.com/green?illuminati=confirmed", - * "target" : "#tinky", - * "target2" : "#winky" + * "base_url": "https://example.com/green?illuminati=confirmed", + * "target": "#<injected-policy>", + * "target2": "#winky", + * "policy": <injected-policy-as-js-object>, + * "current": <boolean-indicating-whether-policy-url-matches> * } * In case url doesn't have 2 #'s, target2 and target can be set to undefined. */ function url_extract_target(url) { - let url_re = /^([^#]*)((#[^#]*)(#.*)?)?$/; - let match = url_re.exec(url); - return { - base_url : match[1], - target : match[3], - target2 : match[4] + const url_re = /^([^#]*)((#[^#]*)(#.*)?)?$/; + const match = url_re.exec(url); + const targets = { + base_url: match[1], + target: match[3] || "", + target2: match[4] || "" }; + if (!targets.target) + return targets; + + /* %7B -> { */ + const index = targets.target.indexOf('%7B'); + if (index === -1) + return targets; + + const now = new Date(); + const sig = targets.target.substring(1, index); + const policy = targets.target.substring(index); + if (sig !== sign_policy(policy, now) && + sig !== sign_policy(policy, now, -1)) + return targets; + + try { + targets.policy = JSON.parse(decodeURIComponent(policy)); + targets.current = targets.policy.base_url === targets.base_url; + } catch (e) { + /* This should not be reached - it's our self-produced valid JSON. */ + console.log("Unexpected internal error - invalid JSON smuggled!", e); + } + + return targets; } /* csp rule that blocks all scripts except for those injected by us */ @@ -110,45 +154,12 @@ function sign_policy(policy, now, hours_offset) { return gen_unique(time + policy); } -/* Extract any policy present in the URL */ -function url_extract_policy(url) -{ - const targets = url_extract_target(url); - if (!targets.target) - return targets; - - /* %7B -> { */ - const index = targets.target.indexOf('%7B'); - if (index === -1) - return targets; - - const now = new Date(); - const sig = targets.target.substring(1, index); - const policy = targets.target.substring(index); - if ( - sig !== sign_policy(policy, now) && - sig !== sign_policy(policy, now, -1) && - sig !== sign_policy(policy, now, 1) - ) - return targets; - - try { - targets.policy = JSON.parse(decodeURIComponent(policy)); - targets.current = targets.policy.base_url === targets.base_url; - } catch (e) { - /* TODO what should happen here? */ - } - - return targets; -} - /* * EXPORTS_START * EXPORT gen_nonce * EXPORT gen_unique * EXPORT url_item * EXPORT url_extract_target - * EXPORT url_extract_policy * EXPORT sign_policy * EXPORT csp_rule * EXPORT nice_name diff --git a/content/freezer.js b/content/freezer.js index 8e543a6..9dbc95e 100644 --- a/content/freezer.js +++ b/content/freezer.js @@ -49,7 +49,7 @@ function mozilla_suppress_scripts(e) { console.log('Script suppressor has detached.'); return; } - else if (e.isTrusted) { // Prevent blocking of injected scripts + if (e.isTrusted && !e.target._hachette_payload) { e.preventDefault(); console.log('Suppressed script', e.target); } diff --git a/content/main.js b/content/main.js index 826019a..8f8375e 100644 --- a/content/main.js +++ b/content/main.js @@ -11,7 +11,6 @@ * IMPORT handle_page_actions * IMPORT url_item * IMPORT url_extract_target - * IMPORT url_extract_policy * IMPORT gen_unique * IMPORT gen_nonce * IMPORT csp_rule @@ -27,14 +26,16 @@ /* * Due to some technical limitations the chosen method of whitelisting sites * is to smuggle whitelist indicator in page's url as a "magical" string - * after '#'. Right now this is not needed in HTTP(s) pages where native - * script blocking happens through CSP header injection but is needed for - * protocols like ftp:// and file://. + * after '#'. Right now this is only supplemental in HTTP(s) pages where + * blocking of native scripts also happens through CSP header injection but is + * necessary for protocols like ftp:// and file://. * * The code that actually injects the magical string into ftp:// and file:// * urls has not yet been added to the extension. */ +var nonce = undefined; + function handle_mutation(mutations, observer) { if (document.readyState === 'complete') { @@ -58,9 +59,8 @@ function block_nodes_recursively(node) function block_node(node) { /* - * Modifying <script> element doesn't always prevent its - * execution in some Mozilla browsers. Additional blocking - * through CSP meta tag injection is required. + * Modifying <script> element doesn't always prevent its execution in some + * Mozilla browsers. This is Chromium-specific code. */ if (node.tagName === "SCRIPT") { block_script(node); @@ -99,21 +99,20 @@ function inject_csp(head) } if (!is_privileged_url(document.URL)) { - const targets = url_extract_policy(document.URL); + const targets = url_extract_target(document.URL); if (targets.policy) { - if (targets.target2 !== undefined) + if (targets.target2) window.location.href = targets.base_url + targets.target2; else history.replaceState(null, "", targets.base_url); } - - targets.policy = targets.current ? targets.policy : {}; - - const nonce = targets.policy.nonce || gen_nonce(); - start_activity_info_server(); + + const policy = targets.current ? targets.policy : {}; + + nonce = policy.nonce || gen_nonce(); handle_page_actions(nonce); - if (!targets.policy.allow) { + if (!policy.allow) { block_nodes_recursively(document.documentElement); if (is_chrome) { @@ -128,4 +127,6 @@ if (!is_privileged_url(document.URL)) { if (is_mozilla) addEventListener('beforescriptexecute', mozilla_suppress_scripts, true); } + + start_activity_info_server(); } diff --git a/content/page_actions.js b/content/page_actions.js index 07fd1bc..aff56b8 100644 --- a/content/page_actions.js +++ b/content/page_actions.js @@ -50,6 +50,7 @@ function add_script(script_text) let script = document.createElement("script"); script.textContent = script_text; script.setAttribute("nonce", nonce); + script._hachette_payload = true; document.body.appendChild(script); report_script(script_text); @@ -6,15 +6,16 @@ Files: * Copyright: 2021 Wojtek Kosior <koszko@koszko.org> License: GPL-3+-javascript or Alicense-1.0 -Files: build.sh +Files: re-generate_icons.sh build.sh Copyright: 2021 Wojtek Kosior <koszko@koszko.org> + 2021 jahoti <jahoti@tilde.team> License: CC0 -Files: icons/hachette.svg +Files: icons/* Copyright: 2017 David Lyons <https://openclipart.org/artist/davidblyons> -License: CC0 +License: CC0 or CC-BY-SA-4.0 -Files: manifest.json background/policy_injector.js common/misc.js content/main.js +Files: background/policy_injector.js common/misc.js content/main.js Copyright: 2021 Wojtek Kosior <koszko@koszko.org> 2021 jahoti <jahoti@tilde.team> License: GPL-3+-javascript or Alicense-1.0 diff --git a/html/options_main.js b/html/options_main.js index cf4c9b1..e1e6cbe 100644 --- a/html/options_main.js +++ b/html/options_main.js @@ -11,7 +11,6 @@ * IMPORT TYPE_PREFIX * IMPORT TYPE_NAME * IMPORT list_prefixes - * IMPORT url_extract_target * IMPORT nice_name * IMPORTS_END */ @@ -633,7 +632,7 @@ function hide_import_window() /* * Reset file <input>. Without this, a second attempt to import the same - * file would result in "change" event on happening on <input> element. + * file would result in "change" event not happening on <input> element. */ file_opener_form.reset(); } @@ -685,26 +684,26 @@ function initialize_import_facility() * * We don't need to worry about the state of the page (e.g. some editing being * in progress) in jump_to_item() - this function is called at the beginning, - * before callbacks are assigned to buttons, so it is safe to assume lists are - * initialized with items and page is in its virgin state with regard to - * everything else. + * together with callbacks being assigned to buttons, so it is safe to assume + * lists are initialized with items and page is in its virgin state with regard + * to everything else. */ function jump_to_item(url_with_item) { - const parsed_url = url_extract_target(url_with_item); - - if (parsed_url.target === undefined) + const [dummy1, base_url, dummy2, target] = + /^([^#]*)(#(.*))?$/i.exec(url_with_item); + if (target === undefined) return; - const prefix = parsed_url.target.substring(1, 2); + const prefix = target.substring(0, 1); if (!list_prefixes.includes(prefix)) { - history.replaceState(null, "", parsed_url.base_url); + history.replaceState(null, "", base_url); return; } by_id(`show_${TYPE_NAME[prefix]}s`).checked = true; - edit_item(prefix, decodeURIComponent(parsed_url.target.substring(2))); + edit_item(prefix, decodeURIComponent(target.substring(1))); } async function main() @@ -718,8 +717,6 @@ async function main() add_radio_li(prefix, item); } - jump_to_item(document.URL); - let name = TYPE_NAME[prefix]; let add_but = by_id(`add_${name}_but`); @@ -746,6 +743,8 @@ async function main() cancel_components_but.addEventListener("click", cancel_components); } + jump_to_item(document.URL); + initialize_import_facility(); storage.add_change_listener(handle_change); diff --git a/icons/hachette.svg b/icons/hachette.svg index c139490..6e8948d 100644 --- a/icons/hachette.svg +++ b/icons/hachette.svg @@ -5,60 +5,36 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - id="svg8" + width="128" + height="128" + viewBox="0 -0.6 33.866668 33.866666" version="1.1" - viewBox="0 -0.6 72.202661 171.30905" - height="647.46729" - width="272.89194" - sodipodi:docname="hatchet.svg" - inkscape:version="0.92.1 r15371"> - <sodipodi:namedview - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1" - objecttolerance="10" - gridtolerance="10" - guidetolerance="10" - inkscape:pageopacity="0" - inkscape:pageshadow="2" - inkscape:window-width="1366" - inkscape:window-height="709" - id="namedview21" - showgrid="false" - inkscape:zoom="0.67493758" - inkscape:cx="136.44597" - inkscape:cy="323.73364" - inkscape:window-x="0" - inkscape:window-y="27" - inkscape:window-maximized="1" - inkscape:current-layer="svg8" /> + id="svg8"> <title id="title1418">Hatchet</title> <defs id="defs2"> <filter - height="1.5078459" - y="-0.25392297" - width="2.5625174" - x="-0.78125864" + style="color-interpolation-filters:sRGB" id="filter994" - style="color-interpolation-filters:sRGB"> + x="-0.78125864" + width="2.5625174" + y="-0.25392297" + height="1.5078459"> <feGaussianBlur - id="feGaussianBlur996" - stdDeviation="1.7304741" /> + stdDeviation="1.7304741" + id="feGaussianBlur996" /> </filter> <filter - height="1.0656563" - y="-0.032828163" - width="1.8736273" - x="-0.43681362" + style="color-interpolation-filters:sRGB" id="filter1401" - style="color-interpolation-filters:sRGB"> + x="-0.43681362" + width="1.8736273" + y="-0.032828163" + height="1.0656563"> <feGaussianBlur - id="feGaussianBlur1403" - stdDeviation="2.2606587" /> + stdDeviation="2.2606587" + id="feGaussianBlur1403" /> </filter> </defs> <metadata @@ -110,52 +86,42 @@ </rdf:RDF> </metadata> <g + transform="matrix(0.18053177,-0.14666587,0.14666587,0.18053177,-0.67884005,5.998568)" id="g4514"> <path - inkscape:connector-curvature="0" - id="rect7" + style="fill:#d38d5f;stroke-width:0.23824416" d="M 7.30405,153.7586 C 20.54927,112.215 15.59359,34.229537 16.31646,33.113187 c 0.87975,-1.35862 11.98736,-0.3859 11.70824,-0.21673 0.17326,45.22237 7.01132,84.510963 -0.71993,131.991763 l -9.29885,-5.88681 z" - style="fill:#d38d5f;stroke-width:0.23824416" /> + id="rect7" /> <path - inkscape:connector-curvature="0" - id="rect9" + style="stroke-width:0.27389684" d="m 63.328435,18.175599 c 0,0 -18.017818,8.640905 -27.631388,12.644707 -3.823279,1.592294 -7.11998,3.047871 -9.996289,4.376476 -11.35319,0.247708 -19.4479991,0.01005 -19.8799245,1.450041 l 0.01602,16.049149 c 0.1225108,1.704999 8.9933655,2.136989 19.9713905,3.333131 6.538886,4.233937 13.307605,8.532834 17.153475,10.714075 9.058079,5.13742 18.504813,7.823295 18.504813,7.823295 0,0 5.056977,-21.237215 4.911847,-31.707625 C 66.23324,32.388436 63.328435,18.175599 63.328435,18.175599 Z" - style="stroke-width:0.27389684" /> + id="rect9" /> <path - sodipodi:nodetypes="cscccsc" - inkscape:connector-curvature="0" - style="opacity:0.45500004;fill:#ffffff;stroke-width:0.26458335" + id="path35" d="m 63.328435,18.175599 c 0,0 2.905055,14.268926 3.050195,24.739336 0.14513,10.47041 -4.912098,31.651538 -4.912098,31.651538 -11.67798,-3.788669 -16.221256,-6.527691 -16.221256,-6.527691 0,0 7.434244,-7.591907 9.174294,-22.366997 1.1592,-16.80443 -4.045711,-21.40711 -4.045711,-21.40711 3.905919,-1.879065 11.01257,-5.216217 12.954576,-6.089076 z" - id="path35" /> + style="opacity:0.45500004;fill:#ffffff;stroke-width:0.26458335" /> <path - sodipodi:nodetypes="cscccscc" - inkscape:connector-curvature="0" - id="path1427" + style="opacity:0.45500004;fill:#ffffff;stroke-width:0.26458335" d="m 63.208938,17.51176 c 0,0 3.024552,14.932765 3.169692,25.403175 0.14513,10.47041 -4.912098,31.621519 -4.912098,31.621519 -1.568463,-0.523507 -1.541936,-0.491688 -1.541936,-0.491688 0,0 5.456154,-26.034461 5.211644,-30.225191 -0.0315,-4.2355 -1.218109,-20.314453 -3.453104,-24.783592 0,0 0.723943,-0.407792 1.645299,-0.860384 z" - style="opacity:0.45500004;fill:#ffffff;stroke-width:0.26458335" /> + id="path1427" /> <path - inkscape:connector-curvature="0" - id="path1407" + style="fill:#784421;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 7.30405,153.7586 10.40103,5.0627 c 0,0 9.14195,5.35641 9.55606,6.02467 0.41411,0.66827 -4.66818,-0.88342 -7.90926,-2.11367 -3.24108,-1.23026 -8.21159,-4.9245 -10.36004,-6.6929 -2.14844,-1.76841 -1.68779,-2.2808 -1.68779,-2.2808 z" - style="fill:#784421;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + id="path1407" /> <path - sodipodi:nodetypes="ccccc" - inkscape:connector-curvature="0" - style="opacity:0.3;fill:#2b1100;stroke-width:0.20724197" + id="path999" d="M 7.30405,153.7586 C 17.372688,112.40594 21.015256,78.343761 17.898744,32.568697 l 3.350934,-0.138515 c 0.131707,45.014525 3.851339,79.911868 -2.025736,127.174438 z" - id="path999" /> + style="opacity:0.3;fill:#2b1100;stroke-width:0.20724197" /> <path - sodipodi:nodetypes="ccccc" - inkscape:connector-curvature="0" - id="rect4493" + style="opacity:1;fill:#1a1a1a;stroke:none;stroke-width:0.1832249" d="m 37.364038,35.560531 9.400174,-5.992052 c 4.831746,9.986754 3.508267,19.973509 -0.303231,29.960263 l -9.096943,-5.992051 z" - style="opacity:1;fill:#1a1a1a;stroke:none;stroke-width:0.1832249" /> + id="rect4493" /> <rect - y="38.224262" - x="23.754957" - height="15.338916" - width="7.4658442" + style="opacity:1;fill:#1a1a1a;stroke:none;stroke-width:0.37082145" id="rect4504" - style="opacity:1;fill:#1a1a1a;stroke:none;stroke-width:0.37082145" /> + width="7.4658442" + height="15.338916" + x="23.754957" + y="38.224262" /> </g> </svg> diff --git a/icons/hachette128.png b/icons/hachette128.png Binary files differnew file mode 100644 index 0000000..18816e9 --- /dev/null +++ b/icons/hachette128.png diff --git a/icons/hachette16.png b/icons/hachette16.png Binary files differnew file mode 100644 index 0000000..182ede5 --- /dev/null +++ b/icons/hachette16.png diff --git a/icons/hachette32.png b/icons/hachette32.png Binary files differnew file mode 100644 index 0000000..ffaa84b --- /dev/null +++ b/icons/hachette32.png diff --git a/icons/hachette48.png b/icons/hachette48.png Binary files differnew file mode 100644 index 0000000..1ffcd38 --- /dev/null +++ b/icons/hachette48.png diff --git a/icons/hachette64.png b/icons/hachette64.png Binary files differnew file mode 100644 index 0000000..a02abb0 --- /dev/null +++ b/icons/hachette64.png diff --git a/manifest.json b/manifest.json index 14b6aa2..328b27f 100644 --- a/manifest.json +++ b/manifest.json @@ -8,7 +8,11 @@ "author": "various", "description": "Kill the web&js",_GECKO_APPLICATIONS_ "icons":{ - "64": "icons/hachette.svg" + "128": "icons/hachette128.png", + "64": "icons/hachette64.png", + "48": "icons/hachette48.png", + "32": "icons/hachette32.png", + "16": "icons/hachette16.png" }, "permissions": [ "contextMenus", @@ -24,7 +28,11 @@ "browser_action": { "browser_style": true, "default_icon": { - "64": "icons/hachette.svg" + "128": "icons/hachette128.png", + "64": "icons/hachette64.png", + "48": "icons/hachette48.png", + "32": "icons/hachette32.png", + "16": "icons/hachette16.png" }, "default_title": "Hachette", "default_popup": "html/display-panel.html" diff --git a/re-generate_icons.sh b/re-generate_icons.sh new file mode 100755 index 0000000..ba0c28a --- /dev/null +++ b/re-generate_icons.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# Copyright (C) 2021 Wojtek Kosior +# Redistribution terms are gathered in the `copyright' file. + +for SIZE in 128 64 48 32 16; do + inkscape -z -e icons/hachette$SIZE.png -w $SIZE -h $SIZE icons/hachette.svg +done |