diff --git a/package-lock.json b/package-lock.json index 1e25582..f5226a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "core-js": "^3.8.3", "highlight.js": "^10.7.3", "jszip": "^3.10.1", - "lib-iitc-manager": "^1.8.4", + "lib-iitc-manager": "^1.9.0", "scored-fuzzysearch": "^1.0.5", "vue": "^2.6.14" }, @@ -9460,9 +9460,9 @@ } }, "node_modules/lib-iitc-manager": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/lib-iitc-manager/-/lib-iitc-manager-1.8.4.tgz", - "integrity": "sha512-1Mk58EgTbUDR7DOZAqx8oEWaFvu8kuhyZPyyuAIYYDf91jAdr61Ht3/rtQYOSXPIQGTj+sbgN5musk40puverQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/lib-iitc-manager/-/lib-iitc-manager-1.9.0.tgz", + "integrity": "sha512-8baF0kySzDQIqNv8+eSLNhjHN+jQIG8TLKvENDNVSaE4dWmdyF0IjWaYqxxE06+uwQktQG3XeY49QLYelmBscw==", "dependencies": { "@bundled-es-modules/deepmerge": "^4.3.1", "xhr2": "^0.2.1" diff --git a/package.json b/package.json index aabc2ec..4ae80ed 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "core-js": "^3.8.3", "highlight.js": "^10.7.3", "jszip": "^3.10.1", - "lib-iitc-manager": "^1.8.4", + "lib-iitc-manager": "^1.9.0", "scored-fuzzysearch": "^1.0.5", "vue": "^2.6.14" }, diff --git a/src/background/background.js b/src/background/background.js index e4a87ce..438cb1e 100644 --- a/src/background/background.js +++ b/src/background/background.js @@ -3,7 +3,6 @@ import { Manager } from "lib-iitc-manager"; import browser from "webextension-polyfill"; import { IS_SCRIPTING_API, IS_USERSCRIPTS_API } from "@/userscripts/env"; import { _ } from "@/i18n"; -import { inject_gm_api, inject_plugin } from "@/userscripts/wrapper"; import { onUpdatedListener, onRemovedListener, @@ -13,9 +12,14 @@ import { import "./requests"; import { strToBase64 } from "@/strToBase64"; import { - is_userscripts_api_available, + init_userscripts_api, is_iitc_enabled, + is_userscripts_api_available, } from "@/userscripts/utils"; +import { + inject_plugin_via_content_scripts, + manage_userscripts_api, +} from "@/background/injector"; const manager = new Manager({ storage: browser.storage.local, @@ -42,19 +46,17 @@ const manager = new Manager({ } catch { // If popup is closed, message goes nowhere and an error occurs. Ignore. } - if (IS_USERSCRIPTS_API) { - is_iitc_enabled().then((status) => { - if (status) { - init_userscripts_api(); - manager.inject().then(); - } - }); - } }, inject_plugin: async (plugin) => { - await inject_plugin(plugin); + if (IS_USERSCRIPTS_API) return; + + const iitc_status = await is_iitc_enabled(); + if (iitc_status === false) return; + + await inject_plugin_via_content_scripts(plugin, true); }, - is_daemon: IS_USERSCRIPTS_API, + plugin_event: async (data) => await manage_userscripts_api(data), + is_daemon: true, }); manager.run().then(); @@ -73,19 +75,19 @@ browser.runtime.onMessage.addListener(async (request) => { await onRequestOpenIntel(); break; case "toggleIITC": + await onToggleIITC(request.value); + if (IS_USERSCRIPTS_API && request.value === true) { + await initUserscriptsApi(); + } + break; + case "popupWasOpened": if (IS_USERSCRIPTS_API) { - await manage_user_scripts_status(request.value); + await initUserscriptsApi(); } - await onToggleIITC(request.value); break; case "xmlHttpRequestHandler": await xmlHttpRequestHandler(request.value); break; - } -}); - -browser.runtime.onMessage.addListener(async function (request) { - switch (request.type) { case "managePlugin": await manager.managePlugin(request.uid, request.action); break; @@ -239,24 +241,28 @@ async function xmlHttpRequestHandler(data) { } } -const init_userscripts_api = () => { - if (!is_userscripts_api_available) return; - chrome.userScripts.configureWorld({ - csp: "script-src 'self' 'unsafe-inline'", - messaging: true, - }); - inject_gm_api(); -}; +async function initUserscriptsApi() { + if (IS_SCRIPTING_API) return; -async function manage_user_scripts_status(status) { - if (status === true) { - init_userscripts_api(); - manager.inject().then(); - } else { - try { - await chrome.userScripts.unregister(); - } catch (e) { - console.log(e); - } - } + let scripts = []; + try { + scripts = await chrome.userScripts.getScripts(); + // eslint-disable-next-line no-empty + } catch {} + + const is_gm_api_plugin_exist = scripts.some( + (script) => script.id === "gm_api" + ); + if (is_gm_api_plugin_exist) return; + + init_userscripts_api(); + const plugins_event = { + event: "add", + plugins: await manager.getEnabledPlugins(), + }; + await manage_userscripts_api(plugins_event); } + +self.addEventListener("activate", () => { + initUserscriptsApi().then(); +}); diff --git a/src/background/injector.js b/src/background/injector.js index 383b4a7..bd999b2 100644 --- a/src/background/injector.js +++ b/src/background/injector.js @@ -33,39 +33,48 @@ export async function inject_plugin_via_content_scripts(plugin, use_gm_api) { } } -export async function inject_plugin_via_userscripts_api(plugin, use_gm_api) { +export async function manage_userscripts_api(plugins_event) { if (!is_userscripts_api_available) return; - if (use_gm_api) { - plugin.code = await gm_api_for_plugin(plugin, 0); - } + const event = plugins_event.event; + const plugins = plugins_event.plugins; + const use_gm_api = plugins_event.use_gm_api === true; - let scripts = []; - try { - scripts = await chrome.userScripts.getScripts(); - } catch (e) { - console.log(e); - return; + if (event === "remove") { + const remove_ids = Object.keys(plugins); + try { + await browser.userScripts.unregister({ ids: remove_ids }); + } catch (e) { + console.log("an error occurred while unregistering the plugin", e); + } } - const plugin_obj = [ - { + + let plugins_obj = []; + for (let plugin of Object.values(plugins)) { + if (use_gm_api) { + plugin.code = await gm_api_for_plugin(plugin, 0); + } + plugins_obj.push({ id: plugin.uid, matches: plugin.uid === "gm_api" ? ["https://*/*"] : getPluginMatches(plugin), js: [{ code: plugin.code }], runAt: plugin.uid === "gm_api" ? "document_start" : "document_end", world: "MAIN", - }, - ]; - - const is_exist = scripts.some((script) => script.id === plugin.uid); - if (!is_exist) { - await chrome.userScripts.register(plugin_obj); - return; + }); } - const exist_script = scripts.find((script) => script.id === plugin.uid); - if (exist_script.js[0].code !== plugin_obj[0].js[0].code) { - await chrome.userScripts.update(plugin_obj); + if (event === "add") { + try { + await browser.userScripts.register(plugins_obj); + } catch (e) { + console.log("an error occurred while registering the plugin", e); + } + } else if (event === "update") { + try { + await browser.userScripts.update(plugins_obj); + } catch (e) { + console.log("an error occurred while updating the plugin", e); + } } } diff --git a/src/background/intel.js b/src/background/intel.js index 19bf9a6..57be1d8 100644 --- a/src/background/intel.js +++ b/src/background/intel.js @@ -2,6 +2,7 @@ import browser from "webextension-polyfill"; import { getTabsToInject } from "@/background/utils"; import { is_iitc_enabled } from "@/userscripts/utils"; +import { IS_USERSCRIPTS_API } from "@/userscripts/env"; let lastIITCTab = null; @@ -24,15 +25,24 @@ export async function onRequestOpenIntel() { } } -export async function onToggleIITC(value) { - await browser.storage.local.set({ IITC_is_enabled: value }); +export async function onToggleIITC(status) { + await browser.storage.local.set({ IITC_is_enabled: status }); - // Fetch all completly loaded Ingress Intel tabs - const tabs = await getTabsToInject(); + if (IS_USERSCRIPTS_API) { + if (status === false) { + try { + await browser.userScripts.unregister(); + // eslint-disable-next-line no-empty + } catch {} + } + } else { + // Fetch all completly loaded Ingress Intel tabs + const tabs = await getTabsToInject(); - for (let tab of Object.values(tabs)) { - if (isIngressIntelUrl(tab.url)) { - await browser.tabs.reload(tab.id); + for (let tab of Object.values(tabs)) { + if (isIngressIntelUrl(tab.url)) { + await browser.tabs.reload(tab.id); + } } } } diff --git a/src/popup/App.vue b/src/popup/App.vue index 2801abd..cf490d1 100644 --- a/src/popup/App.vue +++ b/src/popup/App.vue @@ -34,6 +34,7 @@ import Message from "./components/Message"; import Alert from "./components/Alert"; import * as data from "./data.js"; +import browser from "webextension-polyfill"; export default { name: "App", @@ -61,6 +62,7 @@ export default { await data.init(this); await data.onChangedListener(this); await data.onMessageListener(this); + await browser.runtime.sendMessage({ type: "popupWasOpened" }); }, methods: { detect_safari: function () { diff --git a/src/userscripts/utils.js b/src/userscripts/utils.js index ac1743b..3feeb0e 100644 --- a/src/userscripts/utils.js +++ b/src/userscripts/utils.js @@ -1,6 +1,7 @@ //@license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3 import browser from "webextension-polyfill"; +import { inject_gm_api } from "@/userscripts/wrapper"; export async function is_iitc_enabled() { const status = await browser.storage.local @@ -12,10 +13,22 @@ export async function is_iitc_enabled() { export function is_userscripts_api_available() { try { // Property access which throws if developer mode is not enabled. - chrome.userScripts; + browser.userScripts; return true; } catch { // Not available. return false; } } + +export const init_userscripts_api = () => { + if (!is_userscripts_api_available) return; + try { + browser.userScripts.configureWorld({ + csp: "script-src 'self' 'unsafe-inline'", + messaging: true, + }); + inject_gm_api(); + // eslint-disable-next-line no-empty + } catch {} +}; diff --git a/src/userscripts/wrapper.js b/src/userscripts/wrapper.js index 461ffa0..1767abe 100644 --- a/src/userscripts/wrapper.js +++ b/src/userscripts/wrapper.js @@ -2,35 +2,16 @@ import browser from "webextension-polyfill"; import { IS_USERSCRIPTS_API } from "@/userscripts/env"; -import { - inject_plugin_via_content_scripts, - inject_plugin_via_userscripts_api, -} from "@/background/injector"; +import { manage_userscripts_api } from "@/background/injector"; import { strToBase64 } from "@/strToBase64"; import { getUID } from "lib-iitc-manager"; import { inject } from "@/content-scripts/utils"; import { GM } from "@/userscripts/gm-api"; -import { is_iitc_enabled } from "@/userscripts/utils"; function getPluginHash(uid) { return "VMin" + strToBase64(uid); } -export async function inject_plugin(plugin, use_gm_api) { - if (use_gm_api === undefined) use_gm_api = true; - - const iitc_status = await is_iitc_enabled(); - if (iitc_status === false) return; - - if (IS_USERSCRIPTS_API) { - console.log("INJECT LIKE IS CHROME MV3"); - await inject_plugin_via_userscripts_api(plugin, use_gm_api); - } else { - console.log("INJECT LIKE OTHER BROWSER"); - await inject_plugin_via_content_scripts(plugin, use_gm_api); - } -} - export function inject_gm_api() { const plugin = { uid: "gm_api", @@ -40,7 +21,12 @@ export function inject_gm_api() { }; if (IS_USERSCRIPTS_API) { - inject_plugin_via_userscripts_api(plugin, false).then(); + const plugins_event = { + event: "add", + use_gm_api: false, + plugins: [plugin], + }; + manage_userscripts_api(plugins_event).then(); } else { inject(plugin.code); }