interledger / web-monetization-extension

An open-source browser extension that enables Web Monetization.
Apache License 2.0
77 stars 6 forks source link

[BUG] `HTMLLinkElement.relList.supports('monetization')` is false on page load #590

Closed sidvishnoi closed 2 months ago

sidvishnoi commented 2 months ago

Steps to reproduce

  1. Go to any website with extension enabled and following code:
    console.log(
      'support?',
      document.createElement('link').relList.supports('monetization'),
    );

Expected result

Logs support? true

Actual result

Logs support? false

Screenshots or videos

No response

Additional context

This works fine if we add the check inside a timeout. So the polyfill script is injected a bit late than actual document_start as we want it to be.

Operating system

Linux

Operating system version

No response

Browsers

Chrome, Firefox

Browser version

No response

Extension version

main branch as of today

sidvishnoi commented 2 months ago

Tried various ways to load content script before scripts on page, but to no avail. Requiring webpages to load script with network (instead of inline) doesn't work consistently either.

What works is injecting the polyfill via manifest, and not via content script's injectPolyfill. But we require execution world: "MAIN" there, which is not well supported in Firefox. Firefox 128 (Released 2024-07-09) adds support for this, but then we lose significant browser support.

So, until Firefox support for world is baseline, we can't use that approach. Until then, we've two options:

So, make websites do this to be safest:

let supportsMonetization = document.createElement('link').relList.supports('monetization');
if (!supportsMonetization) {
  // extension polyfill might not have loaded, so try again after a little wait
  supportsMonetization = await new Promise(resolve => {
    setTimeout(() => {
      resolve(document.createElement('link').relList.supports('monetization'))
    }, 300);
  });
}

This is a timing issue sadly

sidvishnoi commented 2 months ago

As you can see in this video, sometimes it times right and we know the support status on page load. But most of the times, we need a wait to know.

Screencast from 12-09-24 03:50:54 PM IST.webm

sidvishnoi commented 2 months ago

And if we can use world: "MAIN" as describe above (Chrome good support, Firefox very recent support), it works consistently:

Screencast from 12-09-24 03:53:24 PM IST.webm

sidvishnoi commented 2 months ago

cc @raducristianpopa

raducristianpopa commented 2 months ago

Can you please include this in the agenda for this week's call? I am okay with sacrificing some Firefox browser support in exchange of a consistent way, that works the same in every browser, to check if Web Monetization is supported.

sidvishnoi commented 2 months ago

This is what happens in Firefox 127 when we inject polyfill via unsupport world: MAIN only:

  1. load, monetization events get fired.
  2. But we can't access any useful property (amountSent, incomingPayment, currentTarget etc.) of those events.
  3. Detection: relList.supports('monetization') is always false.

So, monetization works, but JS part won't (apart from knowing the event got fired).

So, we need to either:

sidvishnoi commented 2 months ago

Follow-up when we can drop Firefox <128 support: https://github.com/interledger/web-monetization-extension/issues/607