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
+33 -12
View File
@@ -160,24 +160,41 @@ async function fetchAndRelayRefs() {
// ─── Inspector ──────────────────────────────────────────────────
// Track inspector mode per tab — 'full' (inspector.js injected) or 'basic' (content.js fallback)
let inspectorMode = 'full';
async function injectInspector(tabId) {
// Try full inspector injection first
try {
await chrome.scripting.executeScript({
target: { tabId, allFrames: true },
files: ['inspector.js'],
});
await chrome.scripting.insertCSS({
target: { tabId, allFrames: true },
files: ['inspector.css'],
});
} catch (err) {
return { error: 'Cannot inspect this page (CSP restriction)' };
// CSS injection failure alone doesn't need fallback
try {
await chrome.scripting.insertCSS({
target: { tabId, allFrames: true },
files: ['inspector.css'],
});
} 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) {
@@ -236,7 +253,11 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
const ALLOWED_TYPES = new Set([
'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)) {
console.warn('[gstack] Rejected unknown message type:', msg.type);