Settings & Persistent State
Inspector Lab stores user preferences in Chrome's local storage, enabling consistent behavior across sessions and synchronization between the popup and the injected inspector. All settings are validated on read to ensure type safety, and storage access gracefully handles both modern promise-based and legacy callback-based Chrome APIs.
Storage Architecture
Settings are persisted in chrome.storage.local, which is extension-private and inaccessible to web content. This ensures user preferences remain secure and isolated from the inspected page.
The system uses a validation-on-read model:
- Write layer: The popup writes settings directly to storage.
- Read layer: The injected inspector validates values on retrieval, treating malformed or missing keys with strict defaults (e.g.,
!== falsechecks ensure no accidental feature activation).
This approach keeps the inspector resilient—a corrupted or missing setting never crashes the UI; it simply falls back to a sensible default.
Theme Settings
Inspector Lab supports two independent theme configurations:
Custom Theme Toggle
Controls whether Inspector Lab uses its own branding or adopts the Chrome DevTools appearance.
The storage key: "customInspectorTheme". Defaults to true (branded theme enabled).
Reading the setting:
const enabled = await readCustomThemeSetting(); // Promise<boolean>When no value is stored, the function returns true, activating the branded theme by default. Only an explicit false written by the popup will switch to the DevTools look.
Saving the setting:
const success = await saveCustomThemeSetting(true); // Promise<boolean>Resolves to false if storage rejects the write, allowing the caller to roll back the UI. Best-effort persistence—failure is non-fatal.
Watching for changes:
const cleanup = watchCustomThemeSetting((enabled) => {
console.log("Theme toggled:", enabled);
});
// Later:
cleanup();This is called from a React effect in the injected inspector. The watcher gracefully tolerates browsers that don't implement chrome.storage.onChanged; a missing namespace returns a no-op cleanup function rather than throwing, preventing the entire inspector from unmounting.
Color Scheme Setting
Controls the light/dark mode preference, mirrored from the popup's toggle to the injected inspector. The popup's own UI state lives in its localStorage, which content scripts cannot access.
The storage key: "inspectorColorScheme". Allowed values: "light" | "dark" | null.
Reading the setting:
type InspectorColorScheme = "light" | "dark";
const scheme = await readColorSchemeSetting(); // Promise<InspectorColorScheme | null>When no choice has been made, the function returns null, and the inspector falls back to the operating system preference.
Saving the setting:
await saveColorSchemeSetting("dark"); // Promise<void>Best-effort: if storage rejects, the inspector continues to use the OS preference. Invalid values are rejected on read, so corrupted storage never activates an unintended mode.
Watching for changes:
const cleanup = watchColorSchemeSetting((scheme) => {
console.log("Color scheme changed:", scheme); // "light" | "dark" | null
});
// Later:
cleanup();Storage API Resilience
Inspector Lab implements a dual-callback/promise layer for Chrome storage access, ensuring compatibility with both modern (promise-based) and legacy (callback-only) Chrome extension runtimes. The resilient storage plumbing is shared with the diagnostics log.
storageGet(key)
Reads a value from chrome.storage.local, resolving whichever of callback or returned promise settles first:
function storageGet(key: string): Promise<Record<string, unknown>>- Never rejects; always resolves to an object (empty
{}on failure). - Automatically marks
chrome.runtime.lastErroras handled to suppress warnings. - Falls back gracefully if the API throws or is unavailable.
storageSet(items)
Writes values to chrome.storage.local, resolving to a boolean indicating success:
function storageSet(items: Record<string, unknown>): Promise<boolean>- Resolves to
falseif storage rejects, allowing callers to react to failure. - Resolves to
trueonly if the write succeeds. - Never rejects.
watchStorage(listener)
Subscribes to storage changes and returns a cleanup function:
function watchStorage(
listener: (
changes: Record<string, chrome.storage.StorageChange>,
area: string,
) => void,
): () => void- Gracefully tolerates browsers without
chrome.storage.onChanged. - Always returns a cleanup function (a no-op if registration failed).
- Prevents errors from propagating into React's effect cleanup, avoiding accidental unmounts.
Validation & Defaults
All settings are validated on read using strict comparison. This ensures type safety even if storage is manually corrupted or migrated:
- Custom theme: Strict
!== falsecheck; any non-false value (includingundefined,null,1, or a string) activates the branded theme. - Color scheme: Exact match to
"light"or"dark"; any other value returnsnull, falling back to OS preference.
Storage is extension-private and cannot be accessed by web content, so these settings remain secure even when inspecting untrusted pages.
Related Pages
- Theming & Styling — Details on the branded theme and color scheme design.
- Installation & Setup — How Inspector Lab initializes and persists state on first load.
- Architecture Overview — How the popup, content script, and injected inspector communicate.