Connect+Documentation
ExtensionsAPI reference

connect.capabilities

Introspect and request the extension's own permissions — list, contains, request.

Introspect and request the extension's own permissions. No capability — an extension can always see what it has and ask for more (within what its manifest declares). This is how you feature-detect before using a gated API, and how you request a declared capability at runtime without a reload.

  • Capability: none
  • Namespace: connect.capabilities

See Capabilities & consent for the permission model.

Walkthrough

Use a gated API only if it's allowed, and ask if it isn't.

  1. Feature-detect with contains before calling a gated API.
  2. Request a declared-but-ungranted capability when the user opts into a feature.
  3. Re-arm any gated event subscriptions from runtime.onGrantsChanged after a grant.
// 1 — branch on what's granted (no error on the "not granted" path)
if (await connect.capabilities.contains('history.read')) render(await connect.history.list());

// 2 — ask for more when the user turns a feature on
const { granted } = await connect.capabilities.request(['history.read']);
if (granted.includes('history.read')) render(await connect.history.list());

Methods

capabilities.list()

What this extension has and asked for, in the current profile.

How to use it

  1. Call it to read { requested, granted, profileId } — useful for a settings screen.

Signatureconnect.capabilities.list() · ReturnsPromise<{ requested, granted, profileId }>.

capabilities.contains(cap)

Is a capability currently granted? The right check to run before code that needs a permission the user may not have allowed.

How to use it

  1. Pass a token ('history.read'), a { host: url } check, or an array (all-of).
  2. Branch on the boolean; skip the gated path if it's false.

Signatureconnect.capabilities.contains(cap)

Parameters

ParameterTypeRequiredDescription
capstringone formA coarse token, e.g. 'history.read'.
cap{ host: url }one formTrue if a granted host pattern covers url.
caparrayone formTrue only if all listed capabilities are granted.

ReturnsPromise<boolean>.

if (await connect.capabilities.contains('history.read')) {
  render(await connect.history.list());          // allowed
} // else: run without history — no error thrown

if (await connect.capabilities.contains({ host: tab.url })) { /* inject */ }
if (await connect.capabilities.contains(['cookies', { host: url }])) { /* … */ }

capabilities.request(capabilities)

Prompt the user for manifest-declared capabilities not yet granted — no reload needed.

How to use it

  1. Call it in response to a user action (opening a feature), not on load.
  2. Read { granted } and proceed only if what you need is in it.

Signatureconnect.capabilities.request(capabilities)

Parameters

ParameterTypeRequiredDescription
capabilitiesstring[] | object[]yesThe declared capabilities to request.

ReturnsPromise<{ granted }>.

Errors & edge cases

  • Already-granted → resolves immediately.
  • Undeclared capabilities → denied (no escalation — you can only request what your manifest declares).
  • A 120s timeout → not granted.
const { granted } = await connect.capabilities.request(['history.read']);
if (granted.includes('history.read')) render(await connect.history.list());

Notes

  • Prefer contains (branch and skip) over calling a gated API and catching CAPABILITY_DENIED — it avoids a thrown error on the expected "not granted" path.
  • Re-arm gated event subscriptions from runtime.onGrantsChanged after a grant lands.

On this page