Skip to content

Architecture

Toxc edited this page May 9, 2026 · 1 revision

Architecture

ReelScroller follows the standard Firefox WebExtension two-process model. A non-persistent background script manages global state and messaging; a content script injected into Instagram pages handles DOM observation and scrolling.


Overview

Toolbar Button click
        │
        ▼
  background.js
  ─────────────────────────────────────────
  • Reads reelScrollerEnabled from storage
  • Flips the value and writes it back
  • Updates toolbar badge (ON / empty)
  • Sends ENABLE or DISABLE message
    to all open Instagram tabs
        │
        ▼ browser.tabs.sendMessage
  content_script_clean.js  (runs in Instagram page)
  ─────────────────────────────────────────
  • On ENABLE: checks if URL is /reel/ or /reels/
    → attaches MutationObserver + video 'ended' listeners
  • On DISABLE: removes all listeners, observers, intervals
        │
        ▼
  DOM interaction
  ─────────────────────────────────────────
  • Waits for video 'ended' event
  • Checks nearby visible text for ad labels
  • Scrolls to next Reel (or skips if sponsored)

Background script (background.js)

The background script is declared as non-persistent ("persistent": false), meaning Firefox can unload it when idle to save resources.

Responsibilities:

  • Storage: Reads and writes the single boolean key reelScrollerEnabled via browser.storage.local.
  • Toolbar button: Listens for browserAction.onClicked. On each click, it toggles the stored value and updates the badge text.
  • Tab messaging: After toggling, iterates over all tabs matching *://*.instagram.com/* and sends an ENABLE or DISABLE message.
  • Tab load: Listens for tabs.onUpdated (status = complete) to send the current state to any newly loaded Instagram tab, so the content script always starts with the correct setting.

Content script (content_script_clean.js)

Injected at document_idle into every page on instagram.com. It does nothing until it receives a message from the background script.

Responsibilities:

  • Route check: On receiving ENABLE, checks window.location.pathname. If the path is not /reel/ or /reels/, the script exits early and attaches no listeners.
  • Video observation: Uses a MutationObserver to detect when video elements appear in the DOM (Instagram loads Reels dynamically).
  • Scroll trigger: Attaches an ended event listener to the focused video. When the video ends, calls scrollToNext().
  • Ad check: Before scrolling, inspects visible text nodes near the current Reel container for sponsorship labels. If a match is found, the Reel is skipped without waiting for the ended event.
  • Cleanup: On receiving DISABLE, disconnects the MutationObserver, removes all ended listeners, and clears any active intervals. The script is safe to enable and disable repeatedly — no duplicate listeners are stacked.

Message protocol

Message Direction Meaning
ENABLE background → content Attach observers and start scrolling
DISABLE background → content Detach all observers and stop scrolling

Storage

Only one key is ever written:

Key Type Default
reelScrollerEnabled boolean true

Clone this wiki locally