diff --git a/esbuild/plugins.ts b/esbuild/plugins.ts index b996be81..d65d2fc1 100644 --- a/esbuild/plugins.ts +++ b/esbuild/plugins.ts @@ -147,11 +147,6 @@ function processManifestPlugin({ json.background = { scripts: [json.background.service_worker], }; - json.content_scripts?.forEach((contentScript) => { - // TODO: Remove this when Firefox supports `world` - at least last 10 - // versions - contentScript.world = undefined; - }); delete json.minimum_chrome_version; } else { delete json['browser_specific_settings']; diff --git a/src/background/services/background.ts b/src/background/services/background.ts index d4e1ec03..885a6e20 100644 --- a/src/background/services/background.ts +++ b/src/background/services/background.ts @@ -51,6 +51,7 @@ export class Background { async start() { this.bindOnInstalled(); + await this.injectPolyfill(); await this.onStart(); this.heartbeat.start(); this.bindMessageHandler(); @@ -61,6 +62,35 @@ export class Background { this.sendToPopup.start(); } + // TODO: When Firefox 128 is old enough, inject directly via manifest. + // Also see: injectPolyfill in contentScript + // See: https://github.com/interledger/web-monetization-extension/issues/607 + async injectPolyfill() { + try { + await this.browser.scripting.registerContentScripts([ + { + world: 'MAIN', + id: 'polyfill', + allFrames: true, + js: ['polyfill/polyfill.js'], + matches: PERMISSION_HOSTS.origins, + runAt: 'document_start', + }, + ]); + } catch (error) { + // Firefox <128 will throw saying world: MAIN isn't supported. So, we'll + // inject via contentScript later. Injection via contentScript is slow, + // but apart from WM detection on page-load, everything else works fine. + if (!error.message.includes(`world`)) { + this.logger.error( + `Content script execution world \`MAIN\` not supported by your browser.\n` + + `Check https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/ExecutionWorld#browser_compatibility for browser compatibility.`, + error, + ); + } + } + } + async onStart() { await this.storage.populate(); await this.checkPermissions(); diff --git a/src/content/polyfill.ts b/src/content/polyfill.ts index 062dae0d..ec12fd5c 100644 --- a/src/content/polyfill.ts +++ b/src/content/polyfill.ts @@ -1,5 +1,10 @@ import type { MonetizationEventPayload } from '@/shared/messages'; (function () { + if (document.createElement('link').relList.supports('monetization')) { + // already patched + return; + } + const handlers = new WeakMap(); const attributes: PropertyDescriptor & ThisType = { enumerable: true, diff --git a/src/content/services/contentScript.ts b/src/content/services/contentScript.ts index 85466344..b5df9572 100644 --- a/src/content/services/contentScript.ts +++ b/src/content/services/contentScript.ts @@ -66,7 +66,9 @@ export class ContentScript { } // TODO: When Firefox has good support for `world: MAIN`, inject this directly - // via manifest.json https://bugzilla.mozilla.org/show_bug.cgi?id=1736575 + // via manifest.json https://bugzilla.mozilla.org/show_bug.cgi?id=1736575 and + // remove this, along with injectPolyfill from background + // See: https://github.com/interledger/web-monetization-extension/issues/607 async injectPolyfill() { const document = this.window.document; const script = document.createElement('script'); diff --git a/src/manifest.json b/src/manifest.json index d8b29928..6680fd44 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -22,14 +22,14 @@ "background": { "service_worker": "background/background.js" }, - "permissions": ["tabs", "storage", "alarms"], + "permissions": ["tabs", "storage", "alarms", "scripting"], "action": { "default_title": "Web Monetization", "default_popup": "popup/index.html" }, "web_accessible_resources": [ { - "resources": ["assets/*", "polyfill/*"], + "resources": ["polyfill/*"], "matches": [""] } ],