Files
KoalaSync/extension
Timo 68f2d9f27c fix(extension): find the player when the all-frames sweep comes back empty
Diagnosed against a fixture rebuilt from the live yummyanime.tv page, with the
ad churn the real site produces. Under that churn the resolver reported
frame=0, hasVideo=false while the video demonstrably existed two frame levels
down: one ad slot tearing down mid-call makes Chromium reject the whole
allFrames sweep, and the resolver then silently fell back to the top frame and
never looked again.

v3.1.2 did not have this failure because webNavigation.getAllFrames() gave it
an explicit frame list. That list is now rebuilt without the permission: every
content script that messages the background carries sender.frameId, so the
background keeps a per-tab registry of frames it has seen and the resolver asks
any frame the sweep missed directly. One rejected probe now costs one frame
instead of the whole page.

Two supporting fixes fell out of the same investigation. Frames reported hidden
by an ancestor that could inspect them directly — the 0x0 same-origin wrapper an
anime host parks unwatched mirrors in — are now excluded without waiting for the
postMessage visibility handshake, which was the tie the resolver kept failing to
break. And leaf frames with no video and no nested frames are left out of that
handshake entirely, so a churning ad slot can no longer make every phase wait on
a frame that is already gone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:56:17 +02:00
..
2026-06-04 15:33:06 +02:00

KoalaSync Browser Extension

This directory contains the Manifest V3 browser extension for Chrome and Firefox. It owns the popup UI, background service worker, content-script video control, invitation bridge, audio processing, and all browser-local settings.

Where You Are

  • manifest.base.json is the source manifest. The build script creates browser-specific manifest.json files in dist/chrome/ and dist/firefox/.
  • background.js is the long-lived coordinator: WebSocket client, room state, host-control authority, heartbeat, reconnects, tab selection, and content-script injection.
  • content.js runs in the selected video tab. It detects video state, applies remote play/pause/seek, handles episode transitions, and applies local audio processing.
  • popup.html and popup.js implement the visible extension UI.
  • extension/shared/ is generated by npm run build:extension from the root shared/ directory. Do not edit it directly.

Key Features

  • Manifest V3: Service-worker architecture with session persistence and explicit keep-alive handling.
  • Pure Vanilla JS: No extension runtime dependencies and no bundler inside extension/.
  • On-Demand Connection: The service worker connects only while the user intends to be in a room.
  • Host Control & Co-Hosts: Hosts can switch a room into host-only mode and grant controller rights to trusted peers.
  • Episode Auto-Sync: Title/episode changes can open a lobby so peers resume together once everyone is ready.
  • Smart Matching & Title Privacy: Matching video tabs are highlighted, while tab/media title sharing can be reduced or disabled.
  • Audio Processing: Optional local compressor settings live in the dedicated audio options page.
  • Status Diagnostics: The Status tab exposes connection state, ping, video debug data, action history, and copyable logs.
  • Dynamic i18n: 15 languages are supported: en, de, fr, es, it, nl, pl, pt, pt-BR, tr, ru, ja, ko, zh, and uk.

Tab Overview

  1. Room: Select official/custom server, create or join rooms, view peers, share invite links, and manage Host Control when supported by the relay.
  2. Sync: Select the video tab, send play/pause/seek/force-sync actions, and view episode lobby state.
  3. Settings: Configure username, title sharing, noise filtering, auto episode sync, notifications, language, and audio options.
  4. Status: Inspect connection state, latency, video debug info, history, and logs for bug reports.
  5. Dev: Hidden developer-only controls shown for the KoalaDev username.

Privacy & Permissions

KoalaSync requires <all_urls> host permission so it can detect and control <video> elements on arbitrary sites.

  • No browsing history is collected or uploaded.
  • Room credentials and user settings are stored locally with chrome.storage.
  • No analytics, external scripts, external fonts, or tracking libraries are used by the extension.
  • Audio processing is local to the selected tab.
  • Title privacy controls decide whether tab/media titles are shared with room peers.

Installation

From the repository root:

npm install
npm run build:extension

Then load the generated bundle:

  • Chrome/Chromium: open chrome://extensions/, enable Developer Mode, and load dist/chrome.
  • Firefox: open about:debugging, choose This Firefox, and load dist/firefox/manifest.json.

Development

Run the build whenever shared protocol files or extension packaging inputs change:

npm run build:extension

The build copies shared/constants.js, shared/blacklist.js, shared/names.js, and shared/README.md into extension/shared/, injects synchronous constants into content.js, generates browser manifests, and creates zip artifacts in dist/.

Useful focused checks from the repository root:

node -c extension/background.js
node -c extension/content.js
node -c extension/popup.js
node scripts/test-episode-utils.mjs
node scripts/test-title-privacy.mjs
node scripts/test-audio-settings.mjs
node scripts/test-locales.cjs

For the full suite, run:

npm run verify

Do Not Break

  • Keep content.js synchronous and IIFE-based; it cannot import ES modules directly.
  • Keep the injection markers used by scripts/build-extension.cjs.
  • Keep protocol names in shared/constants.js as the source of truth.
  • Keep extension runtime dependencies at zero unless the project explicitly decides to introduce a bundler.
  • Keep all extension assets self-hosted.

Module Structure

File Purpose
background.js Service worker: WebSocket protocol, room state, host control, tab/content routing, reconnects
content.js Video detection/control, audio processing, episode transition, host-only guest behavior
popup.js Popup UI: room join/create, tabs, settings, peer list, status, diagnostics
popup.html Popup markup, tabs, onboarding, status/debug surfaces
bridge.js Invitation bridge injected into sync.koalastuff.net
episode-utils.js Shared episode-title parser imported by background and injected into content at build time
title-privacy.js Tab/media title privacy modes and sanitization helpers
audio-options.html / audio-options.js / audio-options.css Dedicated local audio-processing settings page
page-api-seek-overrides.js Page-level seek bridge for site-specific player APIs
modules/tab-manager.js Tab lifecycle helper used by the background service worker
i18n.js Dynamic locale loader and DOM translation helper
locales/ Runtime popup translations
_locales/ Browser-store manifest translations
shared/ Generated mirror of root shared constants, blacklist, names, and README