From ad06551440290ae43e86eca7ed78b824431daf1d Mon Sep 17 00:00:00 2001 From: eight Date: Sun, 14 Oct 2018 02:16:48 +0800 Subject: [PATCH] Fix: use dataurl to inject page script --- content/apply.js | 63 +++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/content/apply.js b/content/apply.js index dfad77f1..8c4c7796 100644 --- a/content/apply.js +++ b/content/apply.js @@ -66,27 +66,27 @@ const APPLY = (() => { // Since it's easy to spoof the browser version in pre-Quantum FF we're checking // for getPreventDefault which got removed in FF59 https://bugzil.la/691151 const EVENT_NAME = chrome.runtime.id; - if (CHROME || isOwnPage || Event.prototype.getPreventDefault || !injectPageScript()) { - return (el, content) => { - // FIXME: do we have to keep el.sheet.disabled? - el.textContent = content; - }; - } + const usePageScript = CHROME || isOwnPage || Event.prototype.getPreventDefault ? + Promise.resolve(false) : injectPageScript(); return (el, content) => { - const detail = pageObject({ - method: 'setStyleContent', - id: el.id, - content + usePageScript.then(ok => { + if (!ok) { + // FIXME: do we have to keep el.sheet.disabled? + el.textContent = content; + } else { + const detail = pageObject({ + method: 'setStyleContent', + id: el.id, + content + }); + window.dispatchEvent(new CustomEvent(EVENT_NAME, {detail})); + } }); - window.dispatchEvent(new CustomEvent(EVENT_NAME, {detail})); }; function injectPageScript() { - // FIXME: does it work with XML? const scriptContent = EVENT_NAME => { - window.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: {method: 'pageScriptOK'} - })); + document.currentScript.remove(); window.addEventListener(EVENT_NAME, function handler(e) { const {method, id, content} = e.detail; if (method === 'setStyleContent') { @@ -102,24 +102,27 @@ const APPLY = (() => { } }, true); }; - let ok = false; - const check = e => { - if (e.detail.method === 'pageScriptOK') { - ok = true; - } - }; - window.addEventListener(EVENT_NAME, check, true); - try { - // eslint-disable-next-line no-eval - window.eval(`(${scriptContent})(${JSON.stringify(EVENT_NAME)})`); - } catch (err) { - // csp error - } - window.removeEventListener(EVENT_NAME, check, true); - return ok; + const code = `(${scriptContent})(${JSON.stringify(EVENT_NAME)})`; + const src = `data:application/javascript;base64,${btoa(code)}`; + const script = document.createElement('script'); + const {resolve, promise} = deferred(); + script.src = src; + script.onload = () => resolve(true); + script.onerror = () => resolve(false); + document.documentElement.appendChild(script); + return promise; } } + function deferred() { + const o = {}; + o.promise = new Promise((resolve, reject) => { + o.resolve = resolve; + o.reject = reject; + }); + return o; + } + function getMatchUrl() { var matchUrl = location.href; if (!matchUrl.match(/^(http|file|chrome|ftp)/)) {