Skip to content
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

Proposal: improve tabs.query API when unexpected property is used #769

Open
Juraj-Masiar opened this issue Feb 23, 2025 · 2 comments
Open
Labels
needs-triage: chrome Chrome needs to assess this issue for the first time needs-triage: firefox Firefox needs to assess this issue for the first time needs-triage: safari Safari needs to assess this issue for the first time

Comments

@Juraj-Masiar
Copy link

Motivation

Querying tabs is useful and resource friendly, but most of the time I end up querying everything, and then filtering the result manually:

const notHiddenTabs = (await browser.tabs.query({}))
  .filter(t => !t.hidden);

Why?

Uncaught TypeError: Error in invocation of tabs.query(object queryInfo, function callback): Error at parameter 'queryInfo': Unexpected property: 'hidden'.

The issue is that many fields are browser/platform/version specific. And they will throw when used!

For example:

  • hidden fails in Chromium
  • autoDiscardable fails in Firefox for Android
  • frozen fails in Firefox or in Chrome 131 and lower

This makes cross-browser development quite challenging and tabs.query looses it's usefulness.

Solutions

This is a bit harder than I thought, so let's brainstorm some ideas.

Solution 1 - ignore unexpected properties

Instead of an exception, it would only log a warning to the console.

Problem:
If the query is asking for the "special" fields only, it would wrongly return all tabs:

// get all frozen tabs
const frozenTabs = await browser.tabs.query({frozen: true});

Solution 2 - define unexpected behavior

Similarly to ORDER BY ... NULLS LAST in SQL, we could add an extra parameter to the query call, which would define what to do when unexpected field is found:

const notHiddenTabs  = await browser.tabs.query({hidden: false}, {unknown: 'ignore'});  // return all tabs when "hidden" doesn't exist
const frozenTabs     = await browser.tabs.query({frozen: true }, {unknown: 'empty' });  // return `[]` when "frozen" doesn't exist
const defaultExample = await browser.tabs.query({hidden: false}, {unknown: 'throw' });  // default value for compatibility

Problem:
This would be sufficient only in simple cases, but combining problematic fields would cause issues:

const notHiddenFrozenTabs = await browser.tabs.query({frozen: true, hidden: false}, {unknown: 'empty' });

What we really want in this case is "empty" for frozen and "ignore" for hidden.

Solution 3 - define unexpected behavior for each property

We could use the fact that none of the existing properties values is an object yet (we have boolean, string, string[], integer).
Example:

const notHiddenTabs  = await browser.tabs.query({hidden: {value: false, unknown: 'ignore'}});
const frozenTabs     = await browser.tabs.query({frozen: {value: true,  unknown: 'empty' }});
const defaultExample = await browser.tabs.query({hidden: {value: false, unknown: 'throw' }});  // default value for compatibility
// complex case:
const notHiddenFrozenTabs = await browser.tabs.query({
  frozen: {value: true,  unknown: 'empty'}, 
  hidden: {value: false, unknown: 'ignore'},
});

Problem:
Verbose?

@github-actions github-actions bot added needs-triage: chrome Chrome needs to assess this issue for the first time needs-triage: firefox Firefox needs to assess this issue for the first time needs-triage: safari Safari needs to assess this issue for the first time labels Feb 23, 2025
@fregante
Copy link

Ignoring some properties means your query will silently get something you don't expect. Using console logs means you can never catch this. I definitely prefer the current situation over solution 1.

As for the other two, I think that's too much complexity, particularly because every other API would likely have to follow.

If your supported browsers don't support a particular key, you should probably catch and define what you want to do in each case. Alternatively, do not query hidden but instead query all tabs and then filter later depending on what's available.

@carlosjeurissen
Copy link
Contributor

carlosjeurissen commented Feb 24, 2025

Thanks for bringing this up @Juraj-Masiar! This is very much an issue indeed. Agree with @fregante on ignoring specific keys being troublesome (solution 1). And the unknown concept being too specific for the tabs.query method. This issue is broader than just the tabs.query method and can be an issue in almost any webExtension API.

This was briefly discussed in the San Diego meeting last year (https://github.com/w3c/webextensions/blob/main/_minutes/2024-03-20-san-diego-meetup.md) under Feature support detection.

Ideally we would have some way of detecting support of specific method options. Which we would need some API proposal for.

Currently the most basic way to detect if a browser supports a specific API is to check it's existence in the browser/chrome namespace. However this comes with issues like specific APIs disappear when the extension did not (yet) receive permissions. As a starter for this, it would be good to separate behavioural patterns which could cause an API to fail or be unavailable. And how the exceptions should look like (async/sync/something else)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-triage: chrome Chrome needs to assess this issue for the first time needs-triage: firefox Firefox needs to assess this issue for the first time needs-triage: safari Safari needs to assess this issue for the first time
Projects
None yet
Development

No branches or pull requests

3 participants