fix: add inspector message types to background.js allowlist

Pre-existing bug found by Codex: ALLOWED_TYPES in background.js was missing
all inspector message types (startInspector, stopInspector, elementPicked,
pickerCancelled, applyStyle, toggleClass, injectCSS, resetAll, inspectResult).
Messages were silently rejected, making the inspector broken on ALL pages.

Also: separate executeScript and insertCSS into individual try blocks in
injectInspector(), store inspectorMode for routing, and add content.js
fallback when script injection fails (CSP, chrome:// pages).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-03-29 23:10:45 -07:00
parent f4ab540f9b
commit 6238edd5d7

View File

@@ -160,24 +160,41 @@ async function fetchAndRelayRefs() {
// ─── Inspector ────────────────────────────────────────────────── // ─── Inspector ──────────────────────────────────────────────────
// Track inspector mode per tab — 'full' (inspector.js injected) or 'basic' (content.js fallback)
let inspectorMode = 'full';
async function injectInspector(tabId) { async function injectInspector(tabId) {
// Try full inspector injection first
try { try {
await chrome.scripting.executeScript({ await chrome.scripting.executeScript({
target: { tabId, allFrames: true }, target: { tabId, allFrames: true },
files: ['inspector.js'], files: ['inspector.js'],
}); });
await chrome.scripting.insertCSS({ // CSS injection failure alone doesn't need fallback
target: { tabId, allFrames: true }, try {
files: ['inspector.css'], await chrome.scripting.insertCSS({
}); target: { tabId, allFrames: true },
} catch (err) { files: ['inspector.css'],
return { error: 'Cannot inspect this page (CSP restriction)' }; });
} catch {}
// Send startPicker to the injected inspector.js
try {
await chrome.tabs.sendMessage(tabId, { type: 'startPicker' });
} catch {}
inspectorMode = 'full';
return { ok: true, mode: 'full' };
} catch {
// Script injection failed (CSP, chrome:// page, etc.)
// Fall back to content.js basic picker (loaded by manifest on most pages)
try {
await chrome.tabs.sendMessage(tabId, { type: 'startBasicPicker' });
inspectorMode = 'basic';
return { ok: true, mode: 'basic' };
} catch {
inspectorMode = 'full';
return { error: 'Cannot inspect this page' };
}
} }
// Send startPicker to all frames
try {
await chrome.tabs.sendMessage(tabId, { type: 'startPicker' });
} catch {}
return { ok: true };
} }
async function stopInspector(tabId) { async function stopInspector(tabId) {
@@ -236,7 +253,11 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
const ALLOWED_TYPES = new Set([ const ALLOWED_TYPES = new Set([
'getPort', 'setPort', 'getServerUrl', 'fetchRefs', 'getPort', 'setPort', 'getServerUrl', 'fetchRefs',
'openSidePanel', 'command', 'sidebar-command' 'openSidePanel', 'command', 'sidebar-command',
// Inspector message types
'startInspector', 'stopInspector', 'elementPicked', 'pickerCancelled',
'applyStyle', 'toggleClass', 'injectCSS', 'resetAll',
'inspectResult'
]); ]);
if (!ALLOWED_TYPES.has(msg.type)) { if (!ALLOWED_TYPES.has(msg.type)) {
console.warn('[gstack] Rejected unknown message type:', msg.type); console.warn('[gstack] Rejected unknown message type:', msg.type);