This document is intended for Chrome Web Store, Mozilla Add-ons (AMO), and Microsoft Edge Add-ons reviewers to help inspect, validate, and test the Sonarr/Radarr/Lidarr/Readarr Autosearch browser extension.
See latest release changes in CHANGELOG.md.
This extension streamlines searching across user‑hosted Servarr applications (Sonarr, Radarr, Lidarr, Readarr) by:
- Auto-prefilling Servarr search pages when a user navigates to a URL containing
/add/new/<term>(or similar). - Adding context menu items to search selected text directly in any configured Servarr instance.
- Injecting small Servarr search icons/links into supported third‑party media sites (IMDb, TMDb, TVDb, Trakt, TVmaze, MusicBrainz, Letterboxd, TV Calendar, Rotten Tomatoes, Metacritic, Simkl, IPTorrents, Last.fm, Allociné, SensCritique, Betaseries, Prime Video, Rate Your Music, MyAnimeList, etc.).
- Providing an options UI where users configure base URLs + API keys (optional) for automatic advanced selector configuration.
- Backup & restore of user settings via a dedicated Options tab:
- Exports a JSON file using a schema‑versioned envelope.
- Imports either new envelope or legacy plain JSON with validation.
- Supports merge or replace modes and a preview‑changes diff.
The extension does not collect analytics, ship remote code, or exfiltrate user data. All API calls target only the user’s own Servarr instances explicitly configured in settings.
| Path | Purpose |
|---|---|
src/ |
Authoritative source (HTML, JS, Tailwind/Sass inputs, manifests). |
src/manifest-chromium/manifest.json |
Chromium MV3 manifest. |
src/manifest-firefox/manifest.json |
Firefox MV2 manifest (kept until MV3 fully supported on Firefox for parity). |
src/content/js/ |
Core runtime scripts (logic, content script, shared helpers, popup & options). |
src/content/css/ |
Tailwind entry (tailwind.css). |
dist/chromium/ |
Build output for Chromium (produced by grunt release). |
dist/firefox/ |
Build output for Firefox. |
tests/playwright/ |
Playwright integration tests (site integration smoke tests). |
tests/unit-tests/ |
Jest unit tests (minimal). |
Gruntfile.js |
Build pipeline definition. |
tailwind.config.js |
Tailwind configuration (purge/content globs + safelist). |
All minified/processed assets in dist/ are reproducible by following the build steps below.
Perform a clean build from source:
# (Use PowerShell equivalent if on Windows, commands are cross-platform)
npm ci
grunt releaseThis produces:
dist/chromium(MV3 build usingeventPage.chrome.jsas service worker + background script bundle pieces).dist/firefox(MV2 build withbackground.scripts).
| Built file (example) | Source origin |
|---|---|
dist/**/popup.html |
src/popup.html (unchanged except path rewriting if any). |
dist/**/options.html |
src/options.html. |
dist/**/content/js/*.js |
Direct copies from src/content/js/ (no obfuscation). |
dist/**/content/css/tailwind.css |
Generated by Tailwind from utility classes declared across src/**/*.html & src/**/*.js + safelist. |
| Icon images | Copied 1:1 from src/content/assets/images/. |
There is no custom packer, no dynamic code generation beyond Tailwind’s static CSS expansion.
manifest-chromium/manifest.json
"permissions": ["scripting", "storage", "activeTab", "contextMenus"],
"host_permissions": [
"*://*.allocine.fr/*",
"*://*.betaseries.com/*",
"*://*.imdb.com/*",
"*://*.iptorrents/*",
"*://*.last.fm/*",
"*://*.letterboxd.com/*",
"*://*.metacritic.com/*",
"*://*.musicbrainz.org/*",
"*://*.myanimelist.net/*",
"*://*.primevideo.com/*",
"*://*.rateyourmusic.com/*",
"*://*.rottentomatoes.com/*",
"*://*.senscritique.com/*",
"*://*.simkl.com/*",
"*://*.themoviedb.org/*",
"*://*.thetvdb.com/*",
"*://*.trakt.tv/*",
"*://*.pogdesign.co.uk/*",
"*://*.tvmaze.com/*"
],
"optional_host_permissions": [
"<all_urls>"
]| Permission | Rationale |
|---|---|
scripting |
Injection of content script on listed domains (MV3 requirement). |
storage |
Persist user configuration (base URLs, API keys, toggles). |
activeTab |
Allow immediate context menu initiated search to open correct tab / access tab URL when needed. |
contextMenus |
Add right-click Servarr search items. |
| Host list | Integration discovery & user-specified Servarr domains (unknown hostnames at install time). <all_urls> enables: 1) detecting configured Servarr pages for auto-search injection, 2) context menu fallback. The site list is explicit for transparency; <all_urls> covers arbitrary self-hosted internal domains (e.g., http://nas.local:8989). |
<all_urls> (optional) |
User-specified Servarr domains (unknown hostnames at install time). User's grant permissions to their Servarr instances on a per domain basis. |
manifest-firefox/manifest.json uses:
"permissions": [
"*://*.allocine.fr/*",
"*://*.betaseries.com/*",
"*://*.imdb.com/*",
"*://*.iptorrents/*",
"*://*.last.fm/*",
"*://*.letterboxd.com/*",
"*://*.metacritic.com/*",
"*://*.musicbrainz.org/*",
"*://*.myanimelist.net/*",
"*://*.primevideo.com/*",
"*://*.rateyourmusic.com/*",
"*://*.rottentomatoes.com/*",
"*://*.senscritique.com/*",
"*://*.simkl.com/*",
"*://*.themoviedb.org/*",
"*://*.thetvdb.com/*",
"*://*.trakt.tv/*",
"*://*.pogdesign.co.uk/*",
"*://*.tvmaze.com/*",
"storage",
"activeTab",
"tabs",
"contextMenus"
],
"optional_permissions": [
"<all_urls>"
]MV2 does not separate host_permissions. Same justifications apply. The commented host list (retained in source) documents intended integration targets for reviewer clarity.
| Component | Role |
|---|---|
eventPage.chrome.js |
MV3 service worker shim (message routing, context menu handling, storage change propagation). |
eventPage.js |
Shared background script logic (non‑service worker pieces reused). |
core.js |
Shared helpers: settings access (storage), API version probing, URL building, small browser polyfill for non-WebExtension contexts (used in tests). |
options.js |
Options UI assembly (Tailwind utility classes, accessible tabs, toggle wiring, Spectrum colour picker). |
options_*.js |
Options tab‑specific logic (settings load/save, site/integration list management, backup/restore handling). |
popup.js |
Popup enable/disable toggle + quick settings link. |
All logic is synchronous or simple async with fetch only to user‑supplied Servarr endpoints (API base derived from settings). No external analytics endpoints.
| Aspect | Details |
|---|---|
| Storage scope | browser.storage.sync / local (standard WebExtension) for configuration only. |
| Personal data | None collected or transmitted externally. |
| Network calls | Only to user Servarr instances (optional) when API key present—to detect version for auto configuration. |
| Telemetry | None. |
| Tracking / Ads | None. |
| Backup/restore | Export produces a local JSON download only; import reads a local JSON file chosen by the user. No data is transmitted externally. |
| Library | Source | Use |
|---|---|---|
| jQuery | node_modules/jquery |
Simple DOM selection & legacy code compatibility. |
| Font Awesome 7 | @fortawesome/fontawesome-free |
Icons in popup/options/UIs. |
| Tailwind CSS 4 + Forms plugin | tailwindcss, @tailwindcss/forms |
Utility-first styling, accessible form defaults. Built into single CSS file (tailwind.css). |
| Spectrum colour picker | spectrum-colorpicker2 |
Colour picker |
| webextension-polyfill | webextension-polyfill |
Unified browser.* API shim across Chrome/Firefox. |
All libraries are installed via npm ci and bundled transparently (no CDN runtime fetches). Unminified sources remain in node_modules/.
-
Build:
npm ci && grunt release. -
Open
chrome://extensions→ Enable Developer Mode. -
Click “Load unpacked” → select
dist/chromium. -
Open the popup: verify enable/disable button toggles state (stored in extension storage).
Option A (temporary install):
- Build:
npm ci && grunt release. - Visit
about:debugging#/runtime/this-firefox. - “Load Temporary Add-on” → pick any file inside
dist/firefox(e.g.,manifest.json).
Option B (web-ext run):
npm ci
grunt release
npm run firefox| Feature | Steps |
|---|---|
| Auto-search injection | Navigate to a configured Sonarr/Radarr URL, append /add/new/<term> → search field prefilled & results loaded. |
| Context menu search | Select text on any page → right-click → choose a Servarr target → new tab opens to correct add/new path. |
| Integration icons | Visit (e.g.) https://www.imdb.com/title/tt0944947/ → Servarr icon(s) should inject near title region (depends on site layout). |
| Enable/Disable toggle | Popup → toggle → integration icons & auto-search cease when disabled. | | Advanced auto-detect | In options: set base URL + API key for (e.g.) Sonarr → advanced selectors auto-populate; test by removing key and toggling detection off/on. | | Custom icon (if enabled) | In options, navigate to custom icon tab; enable & adjust position/colour; verify preview updates. |
In DevTools (background page or service worker):
await browser.storage.sync.get();Review structure (only configuration JSON under a single key).
- Options → “Backup & restore” tab.
Backup
-
Click “Download backup” → a pretty‑printed JSON file is downloaded using an envelope format:
type:"servarr-autosearch-settings"schemaVersion:1exportedAt: ISO timestampappVersion: Extension version (from manifest)data: sanitized settings payload (internal fields prefixed with_or__are stripped)
Restore
- Choose a previously saved JSON file (envelope or legacy plain JSON). Legacy files are accepted with an informational note.
- Optional: Check “Replace existing settings instead of merging” to overwrite fully; otherwise, defaults to a deep merge (arrays replaced; objects merged).
- Click “Preview changes” to inspect a diff (added/removed/changed paths) before applying.
- Click “Restore” → the file is parsed and minimally validated (
configobject,sites[],integrations[]). - If the backup’s
schemaVersionis newer than the extension supports, a warning appears in the confirmation prompt; older schemas are normalized on import. - On confirmation, settings are applied via the WebExtension storage API. A success/failure message is displayed in the UI.
Reset
- Click “Reset settings” → confirmation prompt → resets to built-in defaults.
Notes
- No network transmission occurs during backup or restore; files are handled locally in the browser context.
- Merge mode is safer for forward compatibility; replace mode is provided for deterministic snapshots.
- Enveloped backups are preferred for forward compatibility; legacy JSON remains supported for reviewers and existing users.
| Check | Notes |
|---|---|
| Remote script injection | None (all scripts packaged locally). |
eval / dynamic function |
Not used. |
| Dangerous DOM APIs | Only standard element creation & attribute manipulation; no unsanitized HTML injection from external sources. |
| External network endpoints | Only user-configured Servarr base URLs when API key present (GET/POST for version test). |
| Permission minimization | Core set only; <all_urls> justified for unknown self-hosted domains & consistent injection model. |
| CSP | Uses default WebExtension CSP; no inline JS reliance beyond standard HTML event-free patterns. |
Tests are not required for functional store acceptance but provided for transparency.
npm ci
grunt release
cd tests/playwright
npm i
npx playwright install --with-deps chromium
npx playwright testThese load integration target pages and assert icon injection or URL logic (requires network access to public sites; may be flaky if site layout changes).
npm ci
npm test(Currently minimal; used as a development safeguard.)
| Concern | Handling |
|---|---|
| Accessible tabs | ARIA roles & keyboard navigation (ArrowLeft/Right, Home/End). |
| Toggle controls | Replaces legacy Bootstrap toggle plugin with small custom button logic + aria-pressed. |
| Range inputs | Native <input type="range"> styled via Tailwind forms plugin (no 3rd party slider). |
| Status badges (options) | Show passive health (attempt) of Servarr API endpoints; timeouts gracefully degrade to "Unknown/Fail". |
| Browser polyfill | webextension-polyfill for consistent Promise-based APIs. |
Typical icon injection path on an integration page:
- Content script runs (
sonarr_radarr_lidarr_autosearch.js). - Loads settings via helpers in
core.js. - Detects page type via site-specific selectors.
- Builds search URLs and injects
<a>or<img>element with click handler. - If disabled (
settings.config.enabled === false) early returns.
Auto-search path:
-
User navigates to an add/new URL carrying trailing search text.
-
Content script checks path & extracts trailing segment.
-
Waits for search input (configurable selectors) up to a timeout.
-
Sets value, dispatches input event.
| Area | Note |
|---|---|
| Layout changes on external sites | May break icon injection; handled by future config updates, not runtime heuristics. |
| Firefox MV3 migration | Pending full parity; MV2 manifest is currently retained for Android support (See: Firefox for Android MV3 compatibility). |
Search for any suspicious patterns:
eval(→ not present.new Function(→ not present.fetch(/XMLHttpRequest→ confined to Servarr API probing incore.js(search forcallApi).- Event listeners for context menu: background script only (
eventPage.*). - Storage key typically:
sonarrRadarrLidarrAutosearchSettings(searchable).
If clarification is required during review, please raise an issue in the repository or include reviewer notes in the store submission feedback.
For incremental updates: see CHANGELOG.md (kept current each release).
All shipped code is:
- Deterministic & build-reproducible with
npm ci && grunt release. - Free of remote executable payloads.
- Limited to user-directed network activity.
- Structured for least complexity in review (no bundler obfuscation).
Thank you for reviewing this extension.