What Content Scripts Do
The content script (src/content/content-script.js) performs these tasks:
- Monitors link hover events on the page
- Detects active debug parameters in the current URL
- Modifies same-domain links to include those parameters
- Syncs with extension state from storage and messages
- Guards against multiple injections when reloading
Injection Mechanism
Content scripts are injected in two ways:1. Declarative Injection (Manifest)
Defined in the manifest for automatic injection:- matches: Injects into all URLs
- js: Loads three scripts in order (dependencies first)
- run_at:
document_idlewaits until page is fully loaded
2. Dynamic Injection (Programmatic)
The background script can also inject dynamically:- Extension state changes (toggles are enabled)
- User navigates to an allowed domain
- Content script needs to be refreshed
How Link Modification Works
The content script uses event delegation to efficiently monitor all links:Step-by-Step Process
1. User hovers over a link ThehandleMouseEnter function is triggered:
- Auto-apply to links is enabled in settings
- Current domain is in the allowed list
- Current page URL has debug parameters
/home/daytona/workspace/source/src/content/content-script.js:177 for the enable state logic.
3. Validate the link should be modified
- Only HTTP/HTTPS links are modified
- Only same-domain links (including www vs non-www)
- Skips anchors, JavaScript, mailto, and tel links
hsDebug=truehsCacheBuster={timestamp}developerMode=true
link.dataset.hsOriginalHref for reference.
Domain Checking
The content script includes sophisticated domain matching to handle common variations:example.comandwww.example.comare treated as the same domain- Case-insensitive comparison
- Consistent behavior across different link formats
Allowed Domains Check
Before modifying any links, the script verifies the current domain is allowed:- Exact domain matches
- Subdomain matches (e.g.,
blog.example.commatchesexample.com)
State Synchronization
The content script stays synchronized with the extension through multiple mechanisms:1. Initial State Load
2. Message Listener
3. Storage Change Listener
- User toggles settings in the popup
- User modifies allowed domains
- Extension state changes in any tab
Multiple Injection Protection
Content scripts can be injected multiple times during development or extension updates. Protection is added:- Check if script already exists on the page
- If yes, re-run the initialization instead of registering new listeners
- If no, run the full script and register the flag
- Duplicate event listeners
- Memory leaks
- Conflicting behavior
Content Script Context
Content scripts run in an isolated context with: Access to:- Full DOM of the web page
windowanddocumentobjects- Extension APIs (
chrome.runtime,chrome.storage)
- JavaScript variables from the page
- Functions defined by the website
- Page’s JavaScript context (isolated)
- Messages to background script via
chrome.runtime.sendMessage() - Storage via
chrome.storage.sync - Cannot directly call popup or options page functions
Performance Considerations
Event Delegation
Uses a single event listener ondocument instead of individual listeners per link:
- Works with dynamically added links
- Lower memory footprint
- Better performance on pages with many links
Capture Phase
Thetrue parameter uses the capture phase, ensuring the event is caught before it reaches child elements.
Lazy Modification
Links are only modified on hover, not on page load:- Doesn’t slow down initial page rendering
- Only processes links the user interacts with
- Minimal performance impact
Debugging Content Scripts
To debug the content script:- Open DevTools on the web page (not the extension popup)
- Check Console for any error messages
- Inspect Link Elements to see
data-hs-original-hrefattribute - Set Breakpoints in
content-script.jsvia Sources panel - Monitor Network Tab to verify modified URLs are requested