w3c / webextensions

Charter and administrivia for the WebExtensions Community Group (WECG)
Other
578 stars 50 forks source link

API limitation: content scripts URL matches and History API, Navigation API, BFCache #523

Open bershanskiy opened 5 months ago

bershanskiy commented 5 months ago

Summary

Content Script declarations can contain match patterns with non-empty paths (e.g., https://example.com/subpage with path /subpage). The match is evaluated only on the initial document navigation and not on URL replacement in response to History API invocation. (BFCache discards a document if there was an extension-related event affecting it between document entering BFCache and getting restored.) To sum up, currently CS match patterns with non-/* or /*/*paths may not be reliable when pages use History or Navigation API.

Example

Example extension

manifest.json

{
  "name": "Demo",
  "manifest_version": 2,
  "version":"1",
  "content_scripts": [{
    "js": ["content-script.js"],
    "matches": ["https://example.com/sub"]
  }]
}

content-script.js

console.error('ran');

Steps

  1. Go to https://example.com/
  2. Open console and observe no error logged ran
  3. Replace URL via History API by running this in console: history.replaceState(undefined,undefined,"/sub")
  4. Observe that the URL changed to https://example.com/sub but the ran did not appear
  5. Reload the page via reload button and observe ran error message logged in the console
tophf commented 5 months ago

This would help avoid injecting unnecessarily in the entire site with a listener for navigation.onnavigate (Chrome only as of now) or using the background script with chrome.tabs.onUpdated (wakes up the background script for unrelated URLs) or chrome.webNavigation.onHistoryStateUpdated (adds a scary installation warning).

Since it would be a breaking change, a new key in the declaration is necessary e.g. "match_soft_navigation": true

oliverdunk commented 5 months ago

This seems worth discussion, but I expect this may be behaviour we want to keep and just ensure we have adequately documented. When the URL changes to one that matches a content script, this isn't too tricky - we can just inject the script. This gets a lot harder if we try to be consistent with when you navigate away though - there's no way to "uninject" a content script that is already running and may have made changes to the page.

fregante commented 5 months ago

there's no way to "uninject" a content script that is already running and may have made changes to the page.

That applies to the reverse situation though: first load matches, successive AJAX loads and URL changes no longer match.

oliverdunk commented 5 months ago

That applies to the reverse situation though: first load matches, successive AJAX loads and URL changes no longer match.

For sure. I think the thing we need to decide is whether having some soft navigation controls increases the confusion because now it seems like we have handling for that.

xeenon commented 5 months ago

This is pretty much the same request as #446.

bershanskiy commented 4 months ago

Meeting on 15 Feb 2024: agreed to keep implementation as is and add notes to MDN.