-
-
Notifications
You must be signed in to change notification settings - Fork 499
feat: add content script registration optional
#2288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
3459b5b
cfff8d1
b72dfe6
884f596
8360042
8115eac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -145,6 +145,7 @@ export async function generateManifest( | |
| convertActionToMv2(manifest); | ||
| convertCspToMv2(manifest); | ||
| moveHostPermissionsToPermissions(manifest); | ||
| moveOptionalHostPermissionsToOptionalPermissions(manifest); | ||
| } | ||
|
|
||
| if (wxt.config.manifestVersion === 3) { | ||
|
|
@@ -395,13 +396,21 @@ function addEntrypoints( | |
| if (wxt.config.command === 'serve' && wxt.config.manifestVersion === 3) { | ||
| contentScripts.forEach((script) => { | ||
| script.options.matches?.forEach((matchPattern) => { | ||
| addHostPermission(manifest, matchPattern); | ||
| if (script.options.registration === 'optional') { | ||
| addOptionalHostPermission(manifest, matchPattern); | ||
| } else { | ||
| addHostPermission(manifest, matchPattern); | ||
| } | ||
|
Comment on lines
+399
to
+403
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if i want to use both in the same time?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that’s a totally fair point, and I hadn’t considered that case. export default defineContentScript({
matches: ['https://my-app.com/*'],
registration: 'optional',
// ...
});The original issue’s proposed API treats registration as a single option for the whole content script, so it doesn’t currently allow choosing required vs optional behavior per match. If we want to support both without introducing breaking changes, maybe we could extend the API, for example by adding a new optional field to separate optional matches from required ones. That way the current API keeps working, while still leaving room for mixed-permission content scripts. Maybe something like this.. export default defineContentScript({
matches: ['https://required.com/*'],
optionalMatches: ['https://optional.com/*'],
})
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yeah i was thinking about that, because we can't close our users to THIS or THIS approach, especially if on native approach, you can have both.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @marcellino-ornelas @aklinker1 Any feedback on this approach?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm... I like
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice catch on this @PatrykKuniczak
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the optionalMatches here as well 🙌🏽 This is actually something were supporting right now in our custom module wasnt sure how to express this at the time of my issue tho soo left this out. Being able to support both like this is amazing and solves all of our usecases ❤️
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. although how would the registration option work here now? you need Unless were saying here all |
||
| }); | ||
| }); | ||
| } else { | ||
| // Manifest scripts | ||
| const hashToEntrypointsMap = contentScripts | ||
| .filter((cs) => cs.options.registration !== 'runtime') | ||
| .filter( | ||
| (cs) => | ||
| cs.options.registration !== 'runtime' && | ||
| cs.options.registration !== 'optional', | ||
| ) | ||
| .reduce((map, script) => { | ||
| const hash = hashContentScriptOptions(script.options); | ||
| if (map.has(hash)) map.get(hash)?.push(script); | ||
|
|
@@ -433,6 +442,16 @@ function addEntrypoints( | |
| addHostPermission(manifest, matchPattern); | ||
| }); | ||
| }); | ||
|
|
||
| // Optional runtime content scripts | ||
| const optionalContentScripts = contentScripts.filter( | ||
| (cs) => cs.options.registration === 'optional', | ||
| ); | ||
| optionalContentScripts.forEach((script) => { | ||
| script.options.matches?.forEach((matchPattern) => { | ||
| addOptionalHostPermission(manifest, matchPattern); | ||
| }); | ||
| }); | ||
| } | ||
|
|
||
| const contentScriptCssResources = getContentScriptCssWebAccessibleResources( | ||
|
|
@@ -616,6 +635,17 @@ function addPermission( | |
| manifest.permissions.push(permission); | ||
| } | ||
|
|
||
| function addOptionalPermission( | ||
| manifest: Browser.runtime.Manifest, | ||
| permission: string, | ||
| ): void { | ||
| manifest.optional_permissions ??= []; | ||
| // @ts-expect-error: Allow using strings for permissions for MV2 support | ||
| if (manifest.optional_permissions.includes(permission)) return; | ||
| // @ts-expect-error: Allow using strings for permissions for MV2 support | ||
| manifest.optional_permissions.push(permission); | ||
| } | ||
|
|
||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I’m not sure
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah i mean refactor I think you can omit entire Let's use I should add this comment above, but as i mentioned here, i want to do it in other way previously 😆
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you suggest the change please? I can't think of how using // Runtime content scripts
const runtimeContentScripts = contentScripts.filter(
(cs) => cs.options.registration === 'runtime',
);
runtimeContentScripts.forEach((script) => {
script.options.matches?.forEach((matchPattern) => {
addHostPermission(manifest, matchPattern);
});
});
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I'm not sure what you're requesting here either @PatrykKuniczak
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok guys, my bad contentScripts
.filter((cs) => cs.options.registration === 'optional')
.flatMap(script => script.options.matches || [])
.forEach((matchPattern) => {
addOptionalHostPermission(manifest, matchPattern);
});But if you think it isn't let's leave what it is. |
||
| function addHostPermission( | ||
| manifest: Browser.runtime.Manifest, | ||
| hostPermission: string, | ||
|
|
@@ -625,6 +655,15 @@ function addHostPermission( | |
| manifest.host_permissions.push(hostPermission); | ||
| } | ||
|
|
||
| function addOptionalHostPermission( | ||
| manifest: Browser.runtime.Manifest, | ||
| hostPermission: string, | ||
| ): void { | ||
| manifest.optional_host_permissions ??= []; | ||
| if (manifest.optional_host_permissions.includes(hostPermission)) return; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Left this comment separately but you might want to consider using see this comment for more details:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Love the deduping idea, and thanks for the implementation tips! I am considering using |
||
| manifest.optional_host_permissions.push(hostPermission); | ||
| } | ||
|
|
||
| /** | ||
| * - "<all_urls>" → "<all_urls>" | ||
| * - "_://play.google.com/books/_" → "_://play.google.com/_" | ||
|
|
@@ -669,6 +708,17 @@ function moveHostPermissionsToPermissions( | |
| delete manifest.host_permissions; | ||
| } | ||
|
|
||
| function moveOptionalHostPermissionsToOptionalPermissions( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same like for |
||
| manifest: Browser.runtime.Manifest, | ||
| ): void { | ||
| if (!manifest.optional_host_permissions?.length) return; | ||
|
|
||
| manifest.optional_host_permissions.forEach((permission: string) => | ||
| addOptionalPermission(manifest, permission), | ||
| ); | ||
| delete manifest.optional_host_permissions; | ||
| } | ||
|
|
||
| function convertActionToMv2(manifest: Browser.runtime.Manifest): void { | ||
| if ( | ||
| manifest.action == null || | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't go here. Let's put it here instead: https://wxt.dev/guide/essentials/content-scripts.html
We should add an entire section that covers all three options.
I need to update the example from above to not use
defineContentScript, you should use an unlisted script for that use-case.