w3c / webextensions

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

Proposal: Allow globs for the contextMenus API instead of just URL patterns. #583

Open polywock opened 3 months ago

polywock commented 3 months ago

The contextMenus API allows for restricting a context menu item to pages that match a URL pattern. I propose also allowing for globs instead of only URL patterns. I wanted to allow users to customize where the context menu is shown, but came to realize that URL patterns makes it difficult to support a contains-like pattern.

browser.contextMenus.create({
    ...,
    documentUrlGlobs: [`*${contains}*`]
})
Rob--W commented 2 months ago

The example you've shown is the same as a match pattern. Match patterns are already sufficiently expressive to enable "contains" match, in the path or query component of a URL. Do you have a use case where a glob would work but a MatchPattern would not?

Even without any new APIs, it is already possible for extensions to toggle the visibility of context menus, by calling browser.contextMenus.update(menuId, { visible: false }) to hide it, and visible: true to show it again.

Firefox has the contextMenus.onShown event from where you can try to update the context menu based on the contextual information.

Chrome does not support the contextMenus.onShown event; as an alternative you could consider updating the menu based on the focused window and tab (tabs.onUpdated + windows.onFocusChanged). These events are more chatty than contextMenus.onShown though. There is no event to determine the focused iframe (unless you are willing to run a content script everywhere to intercept mouse/contextmenu events, which I would not recommend).

If you are interested in exploring onShown, refresh and visible, here are relevant links:

polywock commented 2 months ago

I would like to provide a field where the user can provide a URL ~fragment~ substring.

Here's a more accurate example of how I plan to use it. This would be an invalid URL pattern, but a valid glob.

browser.contextMenus.create({
    ...,
    documentUrlGlobs: [`*${containsKeyword}*`]
})
Rob--W commented 2 months ago

Your provided use case is already possible with match patterns: *://*/*#*keywordhere*

polywock commented 2 months ago

My bad. By URL fragment, I meant a substring within any part of the URL

xeenon commented 2 months ago

Even without any new APIs, it is already possible for extensions to toggle the visibility of context menus, by calling browser.contextMenus.update(menuId, { visible: false }) to hide it, and visible: true to show it again.

@Rob--W That assumes the extension has access to the URL, which is not always the case (especially in Safari). documentUrlPatterns is a declarative way to allow activeTab extensions to have context menus respond to the current URL in a privacy preserving way.

While Safari does not currently support globs for anything in Web Extensions, I would be supportive of this if we do add support for globs.

xeenon commented 2 months ago

Side note: I loathe the fact that the documentUrlPatterns property is not documentURLPatterns (with all caps URL). So I'm not super thrilled about adding a second property with similar case.

tophf commented 2 months ago

documentUrlPatterns property is not documentURLPatterns

FWIW, enforcing camelCase when combining is a widely used convention, nothing criminal.

tophf commented 2 months ago

What about documentUrlFilter with URL filters used in webNavigation and declarativeContent API? Meaningfully flexible allowing both complex conditions and a simple urlContains to accommodate for the OP's case. It would make sense to add urlGlob anyway to allow things like *foo*bar* without resorting to a slower RegExp via urlMatches.

Rob--W commented 2 months ago

I'd like to see use cases before expanding the API surface.

The original use cases provided thus far can be covered with match patterns.

It may be tempting to "relax" the syntax, by allowing a ln arbitrary glob instead of a "stricter" match pattern as documentUrlPatterns (and targetUrlPatterns), but that is not backwards-compatible. In a match pattern, ? matches a question mark, while in a glob it matches exactly one character.

Conceptually I am not opposed to expanding globs, but only if there are compelling use cases that need it.

polywock commented 2 months ago

The original use cases provided thus far can be covered with match patterns.

A contains-like pattern can be covered by match patterns, but it's more cumbersome and requires parsing the user's submitted keyword to generate an equivalent match pattern.

Edit: On further thought, a contains-like pattern can't be fully covered because match patterns don't support partial hosts. The host has to be fully defined except for the subdomain.

hanguokai commented 2 months ago

The previous discussions are all technical and developer-oriented. The real problem is that the author wants users to customize the rules. This means several questions:

If the target users understand technology (e.g. users are developers), you can use the existing documentUrlPatterns and give users a link to the reference manual. If the target users don't understand technology, you need to design a simple rule for users, for example, only let users custom the domains part of URL.

polywock commented 2 months ago

@hanguokai Great points! For my case, the latter is the only option. If documentUrlGlobs was supported, I could just throw an input field with a label that says URL contains: and be done with it. The current approach with match patterns requires more thoughtful thinking and effort.