Skip to content

Latest commit

 

History

History
403 lines (289 loc) · 15.9 KB

File metadata and controls

403 lines (289 loc) · 15.9 KB

Extension Reviewer Guide

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.


1. Summary

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.


2. Repository Layout (Source vs Built Artifacts)

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.


3. Build & Verification Steps

Perform a clean build from source:

# (Use PowerShell equivalent if on Windows, commands are cross-platform)
npm ci
grunt release

This produces:

  • dist/chromium (MV3 build using eventPage.chrome.js as service worker + background script bundle pieces).
  • dist/firefox (MV2 build with background.scripts).

Mapping Built Code to Source

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.


4. Permissions & Justification

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.

Firefox (MV2)

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.


5. Background & Runtime Architecture

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.


6. Data Handling & Privacy

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.

7. Third‑Party Libraries

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/.


8. How to Functionally Test

8.1 Load the Extension (Chromium)

  1. Build: npm ci && grunt release.

  2. Open chrome://extensions → Enable Developer Mode.

  3. Click “Load unpacked” → select dist/chromium.

  4. Open the popup: verify enable/disable button toggles state (stored in extension storage).

8.2 Load the Extension (Firefox)

Option A (temporary install):

  1. Build: npm ci && grunt release.
  2. Visit about:debugging#/runtime/this-firefox.
  3. “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

8.3 Configure & Test Core Features

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. |

8.4 Storage Inspection

In DevTools (background page or service worker):

await browser.storage.sync.get();

Review structure (only configuration JSON under a single key).


8.5 Backup & Restore

  1. Options → “Backup & restore” tab.

Backup

  • Click “Download backup” → a pretty‑printed JSON file is downloaded using an envelope format:

    • type: "servarr-autosearch-settings"
    • schemaVersion: 1
    • exportedAt: ISO timestamp
    • appVersion: 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 (config object, sites[], integrations[]).
  • If the backup’s schemaVersion is 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.

9. Security Review Checklist

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.

10. Testing (Automated)

Playwright (site integrations)

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 test

These load integration target pages and assert icon injection or URL logic (requires network access to public sites; may be flaky if site layout changes).

Jest (unit tests)

npm ci
npm test

(Currently minimal; used as a development safeguard.)


11. Notable Implementation Details

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.

12. How to Trace Code Paths

Typical icon injection path on an integration page:

  1. Content script runs (sonarr_radarr_lidarr_autosearch.js).
  2. Loads settings via helpers in core.js.
  3. Detects page type via site-specific selectors.
  4. Builds search URLs and injects <a> or <img> element with click handler.
  5. If disabled (settings.config.enabled === false) early returns.

Auto-search path:

  1. User navigates to an add/new URL carrying trailing search text.

  2. Content script checks path & extracts trailing segment.

  3. Waits for search input (configurable selectors) up to a timeout.

  4. Sets value, dispatches input event.


13. Known Limitations / Edge Cases

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).

14. Reviewer Quick Script Audit Pointers

Search for any suspicious patterns:

  • eval( → not present.
  • new Function( → not present.
  • fetch( / XMLHttpRequest → confined to Servarr API probing in core.js (search for callApi).
  • Event listeners for context menu: background script only (eventPage.*).
  • Storage key typically: sonarrRadarrLidarrAutosearchSettings (searchable).

15. Contact

If clarification is required during review, please raise an issue in the repository or include reviewer notes in the store submission feedback.


16. Change Log

For incremental updates: see CHANGELOG.md (kept current each release).


17. Summary Assertion

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.