This document details Firefox-specific implementation notes, API compatibility findings, and known differences between the Chrome and Firefox versions of the Summarize extension.
The following Chrome APIs are used throughout the extension and have direct Firefox equivalents via the browser.* namespace. WXT automatically polyfills these:
-
chrome.runtime: Message passing, extension info, connectionsruntime.onMessage,runtime.sendMessageruntime.onConnect,runtime.connect,runtime.Portruntime.getURL,runtime.getManifestruntime.openOptionsPage- ✅ Firefox compatible (all methods supported)
-
chrome.tabs: Tab management and queriestabs.query,tabs.get,tabs.create,tabs.updatetabs.sendMessagetabs.onActivated,tabs.onUpdated- ✅ Firefox compatible
-
chrome.storage: Persistent and session storagestorage.local.get,storage.local.setstorage.session(used for ephemeral data)storage.onChanged⚠️ Mostly compatible -storage.sessionrequires Firefox 115+
-
chrome.scripting: Dynamic content script injectionscripting.executeScript- ✅ Firefox compatible (MV3)
-
chrome.windows: Window managementwindows.getCurrent,windows.create,windows.update- ✅ Firefox compatible
-
chrome.webNavigation: Navigation eventswebNavigation.onHistoryStateUpdated- ✅ Firefox compatible
-
chrome.permissions: Runtime permissionspermissions.contains,permissions.request- ✅ Firefox compatible
Chrome usage (wxt.config.ts:56, 77-79, background.ts:1583):
// Manifest
side_panel: {
default_path: 'sidepanel/index.html',
}
// Runtime API
chrome.sidePanel?.setPanelBehavior?.({ openPanelOnActionClick: true })Firefox equivalent: sidebar_action API (Firefox 131+)
// Manifest override needed
sidebar_action: {
default_panel: 'sidepanel.html',
default_title: 'Summarize',
default_icon: 'assets/icon-128.png'
}Migration notes:
- Firefox sidebar is always visible in the sidebar (not a side panel that slides in)
- No equivalent to
setPanelBehavior- sidebar is opened manually - Same HTML content can be reused (sidepanel.html)
- UI may need minor adjustments for Firefox sidebar dimensions
Files affected:
wxt.config.ts- Needs Firefox manifest overridesrc/entrypoints/background.ts:1583- setPanelBehavior call should be Chrome-only
Usage (background.ts:407-480, automation/tools.ts:336-366):
chrome.debugger.attach({ tabId }, "1.3");
chrome.debugger.sendCommand({ tabId }, method, params);
chrome.debugger.detach({ tabId });Firefox compatibility: ✅ Supported but may have behavioral differences
- Firefox has
browser.debuggerwith same API surface - Used for automation features (CDP commands)
- Requires
debuggerpermission (already declared) - Testing needed: Verify CDP protocol compatibility
Usage (automation/userscripts.ts:14-16, background.ts, automation/repl.ts:142-171):
chrome.userScripts;
chrome.permissions.contains({ permissions: ["userScripts"] });Firefox compatibility:
- Firefox has experimental
browser.userScriptssupport - Available in Firefox 128+ behind
extensions.userScripts.enabledpref - Less mature than Chrome implementation
- Implementation: Feature-detect and gracefully degrade (see
automation/userscripts.ts)getUserScriptsStatus()checks API availabilitybuildUserScriptsGuidance()provides user-friendly error messages- Automation features show clear guidance if API unavailable
Current usage pattern: Caching summaries, settings, and session data
Chrome quotas:
storage.local: ~10 MB (can request more withunlimitedStorage)storage.session: ~10 MB
Firefox quotas:
storage.local: 10 MB default (same as Chrome)storage.session: 10 MB (Firefox 115+)
Action required:
- Monitor cache size in production
- Implement LRU eviction if approaching limits
- Consider adding warnings at 80% capacity
Chrome manifest (current):
{
"permissions": ["sidePanel", ...],
"side_panel": {
"default_path": "sidepanel/index.html"
}
}Firefox manifest override (needed):
{
"permissions": ["tabs", "activeTab", "storage", ...],
"sidebar_action": {
"default_panel": "sidepanel/index.html",
"default_title": "Summarize"
}
}Permissions to verify:
- Remove
sidePanel(Chrome-only) - Verify
debuggerpermission works in Firefox - Verify
userScriptsinoptional_permissionsis handled gracefully
Current: Chrome MV3 service worker (background.ts)
Firefox MV3: Also uses service workers (Firefox 109+)
- Same lifecycle as Chrome
- Same event-driven model
- SSE connection handling should work identically
Testing priorities:
- Verify service worker restarts properly
- Test SSE streaming during worker lifecycle
- Verify port-based communication (sidepanel ↔ background)
Current injection strategy:
extract.content.ts: Readability-based extractionhover.content.ts: Hover summariesautomation.content.ts: Automation features
Firefox compatibility: ✅ Should work identically
- WXT handles content script registration
- Same
run_attiming behavior - Same message passing APIs
Usage: Streaming summaries from daemon via SSE (src/lib/sse.ts)
Testing needed:
- Verify EventSource works in Firefox background context
- Test reconnection logic on Firefox
- Verify CORS headers work with Firefox origin
Chrome Side Panel:
- Slides in from the right
- Programmatically opened via
sidePanel.setPanelBehavior() - Toggles on toolbar icon click
Firefox Sidebar:
- Always visible in sidebar area (left side by default)
- Programmatically controlled via
sidebarAction.toggle(),open(),close() - Toggles on toolbar icon click (implemented)
- Keyboard shortcut:
Ctrl+Shift+U(customizable by user) - Different width constraints than Chrome
Impact: Minimal - both browsers now support programmatic control and icon-click toggling
Chrome: chrome-extension://<id>/...
Firefox: moz-extension://<id>/...
Impact: Minimal - WXT handles this via runtime.getURL()
Chrome: DevTools open via chrome://extensions
Firefox: DevTools open via about:debugging
Impact: Documentation only
Add tags to Playwright tests:
// @cross-browser - Runs on both Chrome and Firefox
test('@cross-browser should generate pairing token', ...)
// @firefox - Firefox-specific tests
test('@firefox should use sidebar API', ...)
// @chrome - Chrome-specific tests
test('@chrome should use Side Panel API', ...)# All tests (both browsers)
pnpm test
# Firefox only
pnpm test:firefox
# Chrome only
pnpm test:chrome- Pairing flow: Token generation and daemon connection
- Summary streaming: SSE stream rendering in sidebar
- Content extraction: Readability on various sites
- Auto-summarize: Navigation triggers
- Settings persistence: storage.local across restarts
- Permissions: Debugger and userScripts optional permissions
# Development mode (watch)
pnpm dev:firefox
# Production build
pnpm build:firefox
# Output location
.output/firefox-mv3/- Open
about:debugging#/runtime/this-firefox - Click "Load Temporary Add-on"
- Select
apps/chrome-extension/.output/firefox-mv3/manifest.json
Note: Temporary add-ons are removed on browser restart
Console logs:
- Background script:
about:debugging→ This Firefox → Inspect - Content scripts: Regular DevTools Console (per-page)
- Sidebar: Right-click sidebar → Inspect
Common issues:
- "Error: Extension is invalid": Check manifest syntax
- "Loading failed": Check console for missing permissions
- Sidebar not rendering: Verify
sidebar_actionin manifest
- Use
about:debugging→ Load Temporary Add-on - Extension removed on Firefox restart
- Suitable for development and early beta testing
When ready for public distribution:
- Submit to AMO for review
- Code signing required (automatic via AMO)
- Update mechanism via AMO (similar to Chrome Web Store)
- Investigate Chrome API usage
- Document Chrome-specific APIs
- Create WXT Firefox target configuration
- Add
sidebar_actionmanifest override - Implement toolbar icon click handler with
sidebarAction.toggle() - Add keyboard shortcut support (
Ctrl+Shift+U) - Handle userScripts gracefully if unavailable (checks availability, shows guidance)
- Add browser compatibility test tags
- Configure Playwright for Firefox
- Run full test suite on Firefox build
- Verify Firefox build succeeds (.output/firefox-mv3/)
- Verify manifest permissions are correct
- Update user-facing documentation (README.md installation guide)
- Manual testing in Firefox Developer Edition
- Test sidebar rendering in Firefox
- Verify SSE streaming works
- Test debugger API for automation features
- Firefox Extension Workshop
- WebExtensions API
- Firefox Sidebar API
- WXT Framework - Multi-Browser Support
- Firefox Extension Debugging
- UserScripts API: Automation features require userScripts - graceful degradation implemented with user guidance
- Sidebar width: May need CSS adjustments for Firefox sidebar dimensions (requires manual testing)
- Testing coverage: Aiming for 100% feature parity where browser APIs allow
- Distribution timeline: When to submit to AMO?
- Keyboard shortcut conflicts: Does
Ctrl+Shift+Uconflict with common Firefox shortcuts?
Last updated: 2026-01-02 Status: ✅ Implementation complete - Ready for manual testing in Firefox
Firefox DOES support programmatic sidebar control via the sidebarAction API! The implementation includes:
-
Toolbar Icon Click (
background.ts:1589-1599):- Detects Firefox builds using
import.meta.env.BROWSER === 'firefox' - Adds
action.onClickedlistener that callsbrowser.sidebarAction.toggle() - Toggles sidebar visibility just like Chrome's side panel behavior
- Detects Firefox builds using
-
Keyboard Shortcut (
wxt.config.ts:105-115):- Added
_execute_sidebar_actioncommand to manifest - Default:
Ctrl+Shift+U(Windows/Linux) - Mac:
Command+Shift+U - Users can customize this in Firefox settings:
about:addons→ Extensions → Manage Extension Shortcuts
- Added
-
Manifest Changes (
wxt.config.ts:61):- Firefox builds use standard WebExtensions permissions (no special permissions needed)
- Chrome builds continue to use
sidePanelpermission
User Experience:
- Click toolbar icon: Toggles sidebar open/close
- Keyboard shortcut:
Ctrl+Shift+U(orCmd+Shift+Uon Mac) toggles sidebar - Customizable: Users can change the shortcut in Firefox's extension settings