The extension had hard-coupled itself to one provider's CDN throughout
background.js and its consumers: a host allowlist, a static
declarativeNetRequest rule that forced a fixed site origin as the Referer,
site-named message types/functions, and illustrative comments naming the
site. This commit removes every reference so the code is generic and
provider-agnostic (and no longer names a specific site for reviewers).
What changed:
- background.js
* Dropped the PHNCDN_HOSTS allowlist; video-request capture is now
host-agnostic (any CDN, driven by isVideoRequest / isHlsManifest).
* Removed the static DNR rule that forced a fixed site origin as the
Referer. Replaced with per-tab dynamic capture: an
onBeforeSendHeaders listener captures the provider's own Referer for
each video request the live page makes and stores it per CDN host
(goon_referers). The proxy handler installs a DNR rule scoped to the
requested host using that captured referer, so the provider's exact
origin is extracted at runtime instead of hard-coded.
* Generalized the reconstruction helpers: extractVideoId ->
extractGroupKey (path-directory key, no /hls/videos/ assumption),
buildManifestForVariant / reconstructManifestsFromSegments swap a
segment filename for master.m3u8 dir-agnostically, freshLiveForVideo
-> freshLiveForGroup, and the GOON_GET_PHNCDN_REQUESTS handler ->
GOON_GET_VIDEO_REQUESTS. Resolver response key videoId -> groupKey
* Reworded prose comments to describe behavior generically.
- manifest.json
* Added the extraHeaders permission so onBeforeSendHeaders can read the
Referer header (needed for the dynamic capture above).
- viewer.js / index.js (consumers)
* Proxying decision now keys off a learned goon_proxy_hosts set
(populated from a startup CORS probe) instead of hard-coded host
substrings; removed the hard-coded CORS ping.
* filterManifests / isValidManifestUrl generalized (kept the
.m3u8 / .hlsvod / .ts behavior the tests assert); rank key
phncdn_reconstructed -> hls_reconstructed; queryPhncdnRequests ->
queryVideoRequests.
- content.js, interceptors.js, and two test-prose strings: the illustrative
"sites like <site>" comments generalized.
Verification: 83/83 tests pass, 0 lint errors. A repo-wide grep for the
previously-referenced host / site now returns no matches. The pre-existing
tsc errors in vite.config.ts are unrelated (present on the prior commit).
Note on the dynamic referer: it works while the source tab is open (it reads
that tab's real Referer); if the tab closed before capturing, the proxy falls
back to a host-derived origin, which a strict origin check may still reject --
the tradeoff of not hard-coding the site.
Problem: Even after fixing the hls.js file naming (was 'hls.min.js', now
'hls.js'), videos don't play in the viewer. Likely root cause is CORS
blocking chrome-extension:// requests to phncdn.com CDN URLs that lack
CORS headers for extension origins.
Solution — two-layer fix:
1. Service worker proxy (background.js):
- New GOON_PROXY_FETCH handler fetches any URL via native fetch()
(no CORS restrictions in the service worker)
- Returns base64-encoded response data to the viewer
2. Custom HLS loader (viewer/viewer.js):
- HlsLoader implements hls.js Loader interface
- For phncdn.com/pornhubcdn URLs: proxies via GOON_PROXY_FETCH
- For all other URLs: uses native XHR (bypasses proxy overhead)
- Config passed to hls.js only when manifest URL needs proxying
3. Diagnostics (viewer/viewer.js):
- CORS check at page load for phncdn.com and per-video URL
- Full storage dump of video entries in console
- Manifest URL logging on each HLS load attempt
- Proxy activation logging for debugging
The vite config outputs 'hls.js' but manifest.json and viewer.js
both referenced 'hls.min.js', causing chrome.runtime.getURL() to
return a 404 — triggering 'HLS player unavailable'.
- Update web_accessible_resources entry in manifest.json
- Update loadHlsJs() chrome.runtime.getURL reference
- Add debug log of manifest URL being loaded for diagnostics
Bug fixes:
- FRAG_LOADING: stop updating lastActivity and re-rendering during active
playback. It fires continuously as hls.js proactively fetches future
segments, causing overlay flickering between buffering/playing.
- BUFFER_RESET: stop clearing segmentsLoaded. The event fires during
quality switches when hls.js flushes and rebuilds the MediaSource buffer,
but segments were already played. Clearing the counter made the overlay
show '0 seg' mid-playback.
- FRAG_BUFFERED: add bufferedAhead update immediately after a fragment is
buffered, instead of waiting for the next 1s monitor tick.
- LEVEL_SWITCHED: only set phase='switching' when buffer is low (< 2s).
With meaningful buffer the switch is instant (already-buffered segments),
so skip the intermediate state to avoid panels getting stuck.
- Buffer monitor: add change-detection so renderPanelState only fires when
phase, segments, or quality actually changed — not every second.
- wireVideoEvents: add 'ended' event handler for completeness.
- viewer.js: remove undefined state.segmentsBuffered assignment in BUFFER_RESET
- viewer.js: add missing 'switching' and 'ended' phases to PHASE_ICONS
- index.js: remove redundant Strategy B3 (duplicated B1 video-element walk)
- index.js: filter standard <video> DOM attributes from custom-property scans
(m3u8DeepProbeFn B1 and scrapeFn Priority 3) to avoid iterating built-in
properties that can never contain HLS data
- background.js: remove unconditional return true (handlers are synchronous)
and remove dead error-response for unknown message types
- types.ts: align MediaType union ('direct' | 'hls') with actual runtime
value used in code ('video' | 'hls')
- package.json: remove hls.js from dependencies (loaded from CDN at runtime,
never imported as an npm module)
Viewer fixes (6):
- FRAG_LOADING: only set buffering phase when video is actually stalled
(paused or readyState < HAVE_FUTURE_DATA), prevents overlay flicker
- FRAG_BUFFERED: allow playing transition from any phase except error,
require readyState >= 3 and video not paused
- Add FRAG_DECRYPTED, FRAG_PARSING_INIT_SEGMENT, FRAG_PARSING_USERDATA
event tracking for full fragment pipeline visibility
- BUFFER_RESET: also reset segmentsBuffered counter (was missing)
- LEVEL_SWITCHED: set phase to 'switching' for accurate UI feedback
- Fatal network errors: track in segmentsFailed counter
- Add ENDLIST event handler for stream completion detection
Detection fixes:
- Add filterManifests(): prefer .m3u8 manifest URLs over .ts segments,
reconstruct manifest URL from segment paths when needed
- Add fallback in scanVideos(): when scrapeFn returns no visible <video>
elements (sandboxed iframe), create video entries from intercepted
manifest data. Fixes '0 videos detected' issue on Pornhub and similar
sites where the video player is in an inaccessible iframe.