fix(extension): add "tabs" permission so live tab awareness works on non-localhost sites

Without "tabs", chrome.tabs.query() returns tab objects with undefined
url/title for any site outside host_permissions (everything except
127.0.0.1). snapshotTabs() in background.js then writes empty strings
into tabs.json, and the active-tab.json gate (`if (active && active.url
&& ...)`) silently skips the write. The sidebar agent loses track of
what page the user is actually on.

The "tabs" permission is a no-warning install-time grant in MV3 (not a
host permission). It exposes tab.url / tab.title / tab.favIconUrl across
all tabs, but does not grant content-script injection or cross-origin
fetch — a tight scope match for what snapshotTabs() actually needs.
activeTab is too narrow (only after a user gesture on the extension
action) for background polling.

Reproduces on every gstack version since v1.14.0.0 (ed1e4be), where the
chrome.tabs.onUpdated listener was added but the manifest only gained
`ws://127.0.0.1:*/` for the new PTY channel — tab-related permissions
were never broadened.

Adds a manifest source-level test in sidebar-tabs.test.ts that asserts
`permissions` contains "tabs", to guard against future regressions.

Closes #1256
This commit is contained in:
Fred Chu 2026-04-28 15:15:44 +08:00
parent dde55103fc
commit 9e2c0ad395
2 changed files with 13 additions and 1 deletions

View File

@ -254,3 +254,15 @@ describe('manifest: ws permission + xterm-safe CSP', () => {
}
});
});
describe('manifest: live tab awareness needs "tabs" permission', () => {
// Without "tabs", chrome.tabs.query() returns tab objects with undefined
// url/title for any site outside host_permissions (e.g., everything except
// 127.0.0.1). snapshotTabs() then writes empty strings into tabs.json and
// active-tab.json silently skips the write — the sidebar agent loses track
// of what page the user is on. activeTab is too narrow (only after a user
// gesture on the extension action) for background polling.
test('permissions includes "tabs"', () => {
expect(MANIFEST.permissions).toContain('tabs');
});
});

View File

@ -3,7 +3,7 @@
"name": "gstack browse",
"version": "0.1.0",
"description": "Live activity feed and @ref overlays for gstack browse",
"permissions": ["sidePanel", "storage", "activeTab", "scripting"],
"permissions": ["sidePanel", "storage", "activeTab", "scripting", "tabs"],
"host_permissions": ["http://127.0.0.1:*/", "ws://127.0.0.1:*/"],
"action": {
"default_icon": {