The browser extension is built with a multi-context architecture that separates concerns between the background service worker, popup UI, content scripts, and web pages.
Execution Contexts
The extension runs in multiple isolated contexts that communicate via message passing:
Background Service Worker
Entry Point: src/platform/background.ts
Lifecycle: In Manifest V3, the background context runs as a service worker that can be terminated at any time by the browser.
Responsibilities:
- Core business logic and service initialization
- Vault encryption/decryption
- API communication
- Storage management
- Background sync operations
Key Constraints:
- Can be terminated at any time (Manifest V3)
- Cannot directly access DOM
- Must use message passing to communicate with popup and content scripts
Entry Point: src/popup/main.ts
Framework: Angular application
Lifecycle: Created when user clicks extension icon, destroyed when closed
Responsibilities:
- User interface for vault access
- Password generation
- Settings management
- Quick actions (autofill, copy credentials)
Key Constraints:
- Must clean up event listeners to prevent memory leaks (especially Safari)
- Should use
ZonedMessageListenerService for Angular change detection
- Limited lifetime - can be closed at any time
Content Scripts
Location: src/autofill/
Injection: Defined in manifest, injected into web pages
Responsibilities:
- Form field detection
- Autofill triggering
- Page script communication
- FIDO2/WebAuthn interception
Offscreen Documents
Purpose: Manifest V3 workaround for clipboard operations and DOM APIs
Location: src/platform/offscreen-document/
Offscreen documents provide a hidden HTML context for operations that require DOM access:
BrowserApi Abstraction
Location: src/platform/browser/browser-api.ts
The BrowserApi class is a critical abstraction layer that provides cross-browser compatibility.
Critical Rules
NEVER use chrome.* or browser.* APIs directly in business logic. Always use the BrowserApi abstraction for cross-browser compatibility (Chrome/Firefox/Safari/Opera).
Core Methods
Tab Management
Safari Tab Query Bug: Safari can return tabs from multiple windows even when currentWindow: true is specified. Always use BrowserApi.tabsQueryFirstCurrentWindowForSafari() when querying the current window in Safari to avoid incorrect results.
Message Passing
Event Listeners
Safari Memory Leaks: Safari requires manual cleanup of event listeners in popup contexts. Always use BrowserApi.addListener() instead of native chrome.*.addListener() or browser.*.addListener() to ensure proper cleanup.
The BrowserApi.addListener() method automatically tracks and removes listeners on Safari popup unload:
Browser-Specific Implementations
The BrowserApi class detects the browser environment:
Message Passing Architecture
Since Manifest V3 uses service workers, all communication between contexts uses message passing.
From Popup to Background:
From Background to Popup:
In Popup (receiving messages):
Background ↔ Content Script Communication
From Background to Content Script:
From Content Script to Background:
Message Listener Service
For Popup Components:
Use ZonedMessageListenerService to ensure Angular change detection:
For Background Services:
Use BrowserApi.messageListener() directly:
Storage Architecture
The extension uses multiple storage layers:
Storage Types
- Local Storage -
chrome.storage.local for persistent data
- Session Storage -
chrome.storage.session for temporary data (MV3)
- Memory Storage - In-memory state with message passing synchronization
- Local Backed Session Storage - Session storage with local storage fallback
Storage Services
Manifest V3 Constraints
Service Worker Lifecycle
Service Workers can be terminated at any time. The background context is not persistent in Manifest V3. Do not assume it will stay alive indefinitely.
Background Page Access
From browser-api.ts:434:
Next Steps