diff options
Diffstat (limited to 'browser/extensions/webcompat/lib/injections.js')
-rw-r--r-- | browser/extensions/webcompat/lib/injections.js | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/browser/extensions/webcompat/lib/injections.js b/browser/extensions/webcompat/lib/injections.js new file mode 100644 index 0000000000..8760f551c7 --- /dev/null +++ b/browser/extensions/webcompat/lib/injections.js @@ -0,0 +1,165 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* globals browser, module */ + +class Injections { + constructor(availableInjections, customFunctions) { + this.INJECTION_PREF = "perform_injections"; + + this._injectionsEnabled = true; + + this._availableInjections = availableInjections; + this._activeInjections = new Map(); + this._customFunctions = customFunctions; + } + + bindAboutCompatBroker(broker) { + this._aboutCompatBroker = broker; + } + + bootup() { + browser.aboutConfigPrefs.onPrefChange.addListener(() => { + this.checkInjectionPref(); + }, this.INJECTION_PREF); + this.checkInjectionPref(); + } + + checkInjectionPref() { + browser.aboutConfigPrefs.getPref(this.INJECTION_PREF).then(value => { + if (value === undefined) { + browser.aboutConfigPrefs.setPref(this.INJECTION_PREF, true); + } else if (value === false) { + this.unregisterContentScripts(); + } else { + this.registerContentScripts(); + } + }); + } + + getAvailableInjections() { + return this._availableInjections; + } + + isEnabled() { + return this._injectionsEnabled; + } + + async registerContentScripts() { + const platformInfo = await browser.runtime.getPlatformInfo(); + const platformMatches = [ + "all", + platformInfo.os, + platformInfo.os == "android" ? "android" : "desktop", + ]; + for (const injection of this._availableInjections) { + if (platformMatches.includes(injection.platform)) { + injection.availableOnPlatform = true; + await this.enableInjection(injection); + } + } + + this._injectionsEnabled = true; + this._aboutCompatBroker.portsToAboutCompatTabs.broadcast({ + interventionsChanged: this._aboutCompatBroker.filterOverrides( + this._availableInjections + ), + }); + } + + assignContentScriptDefaults(contentScripts) { + let finalConfig = Object.assign({}, contentScripts); + + if (!finalConfig.runAt) { + finalConfig.runAt = "document_start"; + } + + return finalConfig; + } + + async enableInjection(injection) { + if (injection.active) { + return undefined; + } + + if (injection.customFunc) { + return this.enableCustomInjection(injection); + } + + return this.enableContentScripts(injection); + } + + enableCustomInjection(injection) { + if (injection.customFunc in this._customFunctions) { + this._customFunctions[injection.customFunc](injection); + injection.active = true; + } else { + console.error( + `Provided function ${injection.customFunc} wasn't found in functions list` + ); + } + } + + async enableContentScripts(injection) { + try { + const handle = await browser.contentScripts.register( + this.assignContentScriptDefaults(injection.contentScripts) + ); + this._activeInjections.set(injection, handle); + injection.active = true; + } catch (ex) { + console.error( + "Registering WebCompat GoFaster content scripts failed: ", + ex + ); + } + } + + unregisterContentScripts() { + for (const injection of this._availableInjections) { + this.disableInjection(injection); + } + + this._injectionsEnabled = false; + this._aboutCompatBroker.portsToAboutCompatTabs.broadcast({ + interventionsChanged: false, + }); + } + + async disableInjection(injection) { + if (!injection.active) { + return undefined; + } + + if (injection.customFunc) { + return this.disableCustomInjections(injection); + } + + return this.disableContentScripts(injection); + } + + disableCustomInjections(injection) { + const disableFunc = injection.customFunc + "Disable"; + + if (disableFunc in this._customFunctions) { + this._customFunctions[disableFunc](injection); + injection.active = false; + } else { + console.error( + `Provided function ${disableFunc} for disabling injection wasn't found in functions list` + ); + } + } + + async disableContentScripts(injection) { + const contentScript = this._activeInjections.get(injection); + await contentScript.unregister(); + this._activeInjections.delete(injection); + injection.active = false; + } +} + +module.exports = Injections; |