fix(extension): add "tabs" permission for live tab awareness off-localhost

Without the `tabs` permission, chrome.tabs.query() returns tab objects with
undefined url/title for any site outside host_permissions (i.e. everything
except 127.0.0.1). snapshotTabs then wrote empty strings into tabs.json and
active-tab.json silently skipped writes, and the sidebar agent lost track
of what page the user was actually on. activeTab is too narrow — it only
applies after a user gesture on the extension action, not for background
polling.

Manifest test asserts permissions includes 'tabs' so future drift is caught.

Note: this widens the extension's permission surface; users will see the
broader scope on next install. Called out in the CHANGELOG.

Contributed by @fredchu (#1257).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-05-10 11:06:58 -07:00
parent 6896f8b429
commit 2eb946b09b
2 changed files with 13 additions and 1 deletions
+12
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');
});
});
+1 -1
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": {