Overview
Content scripts act as a bridge between web pages and the SubWallet Extension background service. They enable dApps to interact with the wallet through the injected provider API while maintaining security boundaries.Architecture
Content Script Entry Point
Location:packages/extension-koni/src/content.ts
packages/extension-koni/src/content.ts:26-130
Key Components
1. Port Management
The content script maintains a persistent connection to the background service.packages/extension-koni/src/content.ts:32-47
Port Lifecycle:
- Connect: Establish connection when first needed
- Listen: Attach message and disconnect handlers
- Communicate: Send/receive messages via port
- Disconnect: Clean up on disconnect or error
- Reconnect: Automatically handled on next message
2. Message Handling from Background
Messages from the background are forwarded to the page.packages/extension-koni/src/content.ts:50-58
3. Message Handling from Page
Messages from the injected provider are forwarded to the background.packages/extension-koni/src/content.ts:75-97
Security Checks:
- Only processes messages from the same window
- Verifies message origin matches
MESSAGE_ORIGIN_PAGE - Prevents message injection from other sources
4. Port Disconnection Handling
packages/extension-koni/src/content.ts:61-72,15-24
Message Origins
The content script uses specific origin identifiers for security:packages/extension-base/src/defaults.ts:20-21
Message Flow:
Phishing Protection
The content script implements phishing detection on page load.packages/extension-koni/src/content.ts:100-120
Phishing Flow:
- Content script loads on every page
- Immediately sends phishing check request to background
- Background checks URL against phishing database
- If malicious, background redirects to warning page
- If safe, page loads normally
Error Handling
Connection Errors
packages/extension-koni/src/content.ts:81-96
Error Scenarios:
- Extension disabled or uninstalled
- Background service crashed
- Port disconnected unexpectedly
- Message posting failed
Notification Throttling
The content script prevents notification spam with a flag:Injected Provider Integration
The content script works with the injected provider API: Injected at: Page load by extension manifest Available APIs:window.injectedWeb3['subwallet-js']- Polkadot/Substrate APIwindow.injectedWeb3['subwallet']- Legacy API- EVM provider APIs
- Injected provider → window.postMessage
- Content script → chrome.runtime.Port
- Background service → process request
- Background → chrome.runtime.Port
- Content script → window.postMessage
- Injected provider → resolve promise
Security Considerations
Message Validation
- Validates message source is the current window
- Checks origin matches expected value
- Prevents cross-origin message injection
- Blocks iframe message spoofing
Isolated Execution Context
Content scripts run in an isolated world:- Cannot directly access page JavaScript variables
- Cannot be accessed by page JavaScript
- Can only communicate via window.postMessage
- Has access to Chrome extension APIs
- Has access to page DOM
Best Practices
- Origin Validation: Always validate message origin
- Error Handling: Gracefully handle port disconnections
- Notification Management: Prevent notification spam
- Port Lifecycle: Clean up listeners on disconnect
- Security: Never expose extension APIs to page context
Common Patterns
Handling Port Reconnection
getPort() method automatically creates a new connection if needed.
Message Filtering
Debugging
Console Messages
Chrome DevTools
- Open DevTools on the web page
- Go to Sources → Content Scripts
- Find SubWallet content script
- Set breakpoints in message handlers
- Inspect messages in console
Related Documentation
- Message Passing - Communication protocols
- Background Services - Background architecture
- Extension UI - UI component architecture