diff --git a/background/background.js b/background/background.js index c01c063b..17fdbf13 100644 --- a/background/background.js +++ b/background/background.js @@ -1,6 +1,6 @@ /* global download prefs openURL FIREFOX CHROME VIVALDI - openEditor debounce URLS ignoreChromeError queryTabs getTab - styleManager msg navigatorUtil iconUtil workerUtil */ + openEditor debounce URLS ignoreChromeError getTab + styleManager msg navigatorUtil iconUtil workerUtil contentScripts */ 'use strict'; // eslint-disable-next-line no-var @@ -145,7 +145,9 @@ navigatorUtil.onUrlChange(({tabId, frameId, transitionQualifiers}, type) => { chrome.runtime.onInstalled.addListener(({reason}) => { // save install type: "admin", "development", "normal", "sideload" or "other" // "normal" = addon installed from webstore - chrome.management.getSelf(info => localStorage.installType = info.installType); + chrome.management.getSelf(info => { + localStorage.installType = info.installType; + }); if (reason !== 'update') return; // translations may change @@ -238,7 +240,7 @@ if (chrome.contextMenus) { // reinject content scripts when the extension is reloaded/updated. Firefox // would handle this automatically. if (!FIREFOX) { - reinjectContentScripts(); + setTimeout(contentScripts.injectToAllTabs, 0); } // register hotkeys @@ -258,54 +260,6 @@ if (FIREFOX && browser.commands && browser.commands.update) { msg.broadcastTab({method: 'backgroundReady'}); -function reinjectContentScripts() { - const NTP = 'chrome://newtab/'; - const ALL_URLS = ''; - const contentScripts = chrome.runtime.getManifest().content_scripts; - // expand * as .*? - const wildcardAsRegExp = (s, flags) => new RegExp( - s.replace(/[{}()[\]/\\.+?^$:=!|]/g, '\\$&') - .replace(/\*/g, '.*?'), flags); - for (const cs of contentScripts) { - cs.matches = cs.matches.map(m => ( - m === ALL_URLS ? m : wildcardAsRegExp(m) - )); - } - - const injectCS = (cs, tabId) => { - ignoreChromeError(); - for (const file of cs.js) { - chrome.tabs.executeScript(tabId, { - file, - runAt: cs.run_at, - allFrames: cs.all_frames, - matchAboutBlank: cs.match_about_blank, - }, ignoreChromeError); - } - }; - - const pingCS = (cs, {id, url}) => { - cs.matches.some(match => { - if ((match === ALL_URLS || url.match(match)) && - (!url.startsWith('chrome') || url === NTP)) { - msg.sendTab(id, {method: 'ping'}) - .catch(() => false) - .then(pong => !pong && injectCS(cs, id)); - return true; - } - }); - }; - - queryTabs().then(tabs => - tabs.forEach(tab => { - // skip lazy-loaded aka unloaded tabs that seem to start loading on message in FF - if (tab.width) { - contentScripts.forEach(cs => - setTimeout(pingCS, 0, cs, tab)); - } - })); -} - function webNavUsercssInstallerFF(data) { const {tabId} = data; Promise.all([ diff --git a/background/content-scripts.js b/background/content-scripts.js new file mode 100644 index 00000000..1cfecc19 --- /dev/null +++ b/background/content-scripts.js @@ -0,0 +1,68 @@ +/* global msg queryTabs ignoreChromeError */ +/* exported contentScripts */ +'use strict'; + +const contentScripts = (() => { + const NTP = 'chrome://newtab/'; + const ALL_URLS = ''; + const SCRIPTS = chrome.runtime.getManifest().content_scripts; + // expand * as .*? + const wildcardAsRegExp = (s, flags) => new RegExp( + s.replace(/[{}()[\]/\\.+?^$:=!|]/g, '\\$&') + .replace(/\*/g, '.*?'), flags); + for (const cs of SCRIPTS) { + cs.matches = cs.matches.map(m => ( + m === ALL_URLS ? m : wildcardAsRegExp(m) + )); + } + return {injectToTab, injectToAllTabs}; + + function injectToTab({url, tabId, frameId = null}) { + for (const script of SCRIPTS) { + if ( + script.matches.some(match => + (match === ALL_URLS || url.match(match)) && + (!url.startsWith('chrome') || url === NTP)) + ) { + doInject(tabId, frameId, script); + } + } + } + + function doInject(tabId, frameId, script) { + const options = frameId === null ? {} : {frameId}; + msg.sendTab(tabId, {method: 'ping'}, options) + .catch(() => false) + .then(pong => { + if (pong) { + return; + } + const options = { + runAt: script.run_at, + allFrames: script.all_frames, + matchAboutBlank: script.match_about_blank + }; + if (frameId !== null) { + options.allFrames = false; + options.frameId = frameId; + } + for (const file of script.js) { + chrome.tabs.executeScript(tabId, Object.assign({file}, options), ignoreChromeError); + } + }); + } + + function injectToAllTabs() { + return queryTabs().then(tabs => { + for (const tab of tabs) { + // skip lazy-loaded aka unloaded tabs that seem to start loading on message in FF + if (tab.width) { + injectToTab({ + url: tab.url, + tabId: tab.id + }); + } + } + }); + } +})(); diff --git a/manifest.json b/manifest.json index a50daf43..21374881 100644 --- a/manifest.json +++ b/manifest.json @@ -35,6 +35,7 @@ "js/script-loader.js", "js/usercss.js", "js/cache.js", + "background/content-scripts.js", "background/db.js", "background/style-manager.js", "background/navigator-util.js",