refactor: audit fixes — clean up bugs, dead code, and type mismatches
CI / test (pull_request) Successful in 23s
CI / test (pull_request) Successful in 23s
- 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)
This commit is contained in:
1 parent
ae8608148d
commit
8e9f7f96f1
5 files changed
+36
-31
No files matched your search
@@ -13,9 +13,6 @@
|
|||||||
"test:watch": "vitest",
|
"test:watch": "vitest",
|
||||||
"check": "tsc --noEmit"
|
"check": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
|
||||||
"hls.js": "^1.5.17"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ajv": "^8.17.1",
|
"ajv": "^8.17.1",
|
||||||
"ajv-formats": "^3.0.1",
|
"ajv-formats": "^3.0.1",
|
||||||
|
|||||||
@@ -18,13 +18,9 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'PING':
|
case 'PING':
|
||||||
sendResponse({ pong: true, timestamp: Date.now() });
|
sendResponse({ pong: true, timestamp: Date.now() });
|
||||||
break;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.warn('[goon-plugin] Unknown message type:', message.type);
|
console.warn('[goon-plugin] Unknown message type:', message.type);
|
||||||
sendResponse({ error: `Unknown type: ${message.type}` });
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true; // keep sendResponse channel open for async work
|
|
||||||
});
|
});
|
||||||
+2
-2
@@ -14,10 +14,10 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Media delivery format of the video source.
|
* Media delivery format of the video source.
|
||||||
* - 'direct' : plain MP4/WebM blob served via HTTP(S)
|
* - 'video' : plain MP4/WebM blob served via HTTP(S)
|
||||||
* - 'hls' : HTTP Live Streaming manifest (.m3u8)
|
* - 'hls' : HTTP Live Streaming manifest (.m3u8)
|
||||||
*/
|
*/
|
||||||
export type MediaType = 'direct' | 'hls';
|
export type MediaType = 'video' | 'hls';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single video entry discovered by a tab scan.
|
* A single video entry discovered by a tab scan.
|
||||||
|
|||||||
+31
-20
@@ -171,8 +171,23 @@ function m3u8DeepProbeFn() {
|
|||||||
// NOT a reverse-lookup. It returns its input unchanged — Hls.cast(video) just
|
// NOT a reverse-lookup. It returns its input unchanged — Hls.cast(video) just
|
||||||
// returns the <video> element with no .url property. Real players store the
|
// returns the <video> element with no .url property. Real players store the
|
||||||
// HLS instance directly on the video element as a custom property.
|
// HLS instance directly on the video element as a custom property.
|
||||||
|
// Only check non-standard properties (skip built-in <video> attributes).
|
||||||
|
const STANDARD_VIDEO_ATTRS = new Set([
|
||||||
|
'src', 'srcObject', 'crossOrigin', 'preload', 'autoplay', 'muted',
|
||||||
|
'defaultMuted', 'loop', 'controls', 'controlsList', 'disableRemotePlayback',
|
||||||
|
'volume', 'playbackRate', 'defaultPlaybackRate', 'playbackState',
|
||||||
|
'currentTime', 'startTime', 'duration', 'buffered', 'seekable',
|
||||||
|
'played', 'seeking', 'ended', 'readyState', 'networkState',
|
||||||
|
'videoWidth', 'videoHeight', 'error', 'textTracks', 'videoTracks',
|
||||||
|
'audioTracks', 'loadingBeganAt', 'label', 'id', 'className',
|
||||||
|
'classList', 'style', 'attributes', 'dataset', 'innerHTML', 'textContent',
|
||||||
|
'outerHTML', 'outerText', 'slot', 'accessKey', 'draggable', 'hidden',
|
||||||
|
'lang', 'spellcheck', 'tabIndex', 'title', 'translate',
|
||||||
|
'width', 'height', 'poster', 'preload', 'referrerPolicy',
|
||||||
|
]);
|
||||||
for (const v of document.querySelectorAll('video')) {
|
for (const v of document.querySelectorAll('video')) {
|
||||||
for (const key of Object.keys(v)) {
|
for (const key of Object.keys(v)) {
|
||||||
|
if (STANDARD_VIDEO_ATTRS.has(key)) continue;
|
||||||
const obj = v[key];
|
const obj = v[key];
|
||||||
if (!obj || typeof obj !== 'object') continue;
|
if (!obj || typeof obj !== 'object') continue;
|
||||||
// Check for common HLS instance patterns on video elements
|
// Check for common HLS instance patterns on video elements
|
||||||
@@ -193,23 +208,6 @@ function m3u8DeepProbeFn() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// B3: Fallback — walk video element keys looking for HLS-related objects
|
|
||||||
for (const v of document.querySelectorAll('video')) {
|
|
||||||
for (const key of Object.keys(v)) {
|
|
||||||
if (key.toLowerCase().includes('hls') || key === 'player') {
|
|
||||||
const hlsObj = v[key];
|
|
||||||
if (hlsObj && typeof hlsObj === 'object') {
|
|
||||||
for (const subKey of Object.keys(hlsObj)) {
|
|
||||||
if (typeof hlsObj[subKey] === 'string' && hlsObj[subKey].includes('.m3u8')) {
|
|
||||||
if (!seen.has(hlsObj[subKey])) { seen.add(hlsObj[subKey]); manifests.push({ url: hlsObj[subKey], player: `video.${key}.${subKey}` }); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
walk(hlsObj, `video.${key}`, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strategy C: Inline scripts
|
// Strategy C: Inline scripts
|
||||||
for (const script of document.querySelectorAll('script:not([src])')) {
|
for (const script of document.querySelectorAll('script:not([src])')) {
|
||||||
const text = script.textContent || '';
|
const text = script.textContent || '';
|
||||||
@@ -281,11 +279,24 @@ function scrapeFn(hlsManifests) {
|
|||||||
mediaType = 'hls';
|
mediaType = 'hls';
|
||||||
src = hlsManifest;
|
src = hlsManifest;
|
||||||
}
|
}
|
||||||
// Priority 3: Scan video element properties for HLS instance references.
|
// Priority 3: Scan video element custom properties for HLS instance references.
|
||||||
// Hls.cast() is a TypeScript identity cast in hls.js — NOT a reverse-lookup.
|
// Only check non-standard (custom) properties — skip built-in <video> attrs.
|
||||||
// Real players store the HLS instance on the video element as custom properties.
|
|
||||||
if (!hlsManifest) {
|
if (!hlsManifest) {
|
||||||
|
const stdAttrs = new Set([
|
||||||
|
'src', 'srcObject', 'crossOrigin', 'preload', 'autoplay', 'muted',
|
||||||
|
'defaultMuted', 'loop', 'controls', 'controlsList', 'disableRemotePlayback',
|
||||||
|
'volume', 'playbackRate', 'defaultPlaybackRate', 'playbackState',
|
||||||
|
'currentTime', 'startTime', 'duration', 'buffered', 'seekable',
|
||||||
|
'played', 'seeking', 'ended', 'readyState', 'networkState',
|
||||||
|
'videoWidth', 'videoHeight', 'error', 'textTracks', 'videoTracks',
|
||||||
|
'audioTracks', 'loadingBeganAt', 'label', 'id', 'className',
|
||||||
|
'classList', 'style', 'attributes', 'dataset', 'innerHTML', 'textContent',
|
||||||
|
'outerHTML', 'outerText', 'slot', 'accessKey', 'draggable', 'hidden',
|
||||||
|
'lang', 'spellcheck', 'tabIndex', 'title', 'translate',
|
||||||
|
'width', 'height', 'poster', 'referrerPolicy',
|
||||||
|
]);
|
||||||
for (const key of Object.keys(v)) {
|
for (const key of Object.keys(v)) {
|
||||||
|
if (stdAttrs.has(key)) continue;
|
||||||
const obj = v[key];
|
const obj = v[key];
|
||||||
if (obj && typeof obj === 'object' && typeof obj.url === 'string') {
|
if (obj && typeof obj === 'object' && typeof obj.url === 'string') {
|
||||||
const u = obj.url.toLowerCase();
|
const u = obj.url.toLowerCase();
|
||||||
|
|||||||
@@ -170,7 +170,9 @@ const PHASE_ICONS = {
|
|||||||
loading: '\u2B07', // down arrow
|
loading: '\u2B07', // down arrow
|
||||||
buffering: '\u27F7', // spinning
|
buffering: '\u27F7', // spinning
|
||||||
playing: '\u25B6', // play
|
playing: '\u25B6', // play
|
||||||
|
switching: '\u21BB', // right arrow corner
|
||||||
error: '\u2717', // X
|
error: '\u2717', // X
|
||||||
|
ended: '\u23F9', // stop
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -413,7 +415,6 @@ function wireHlsEvents(hls, video, panel) {
|
|||||||
state.lastActivity = Date.now();
|
state.lastActivity = Date.now();
|
||||||
state.bufferedAhead = 0;
|
state.bufferedAhead = 0;
|
||||||
state.segmentsLoaded = 0;
|
state.segmentsLoaded = 0;
|
||||||
state.segmentsBuffered = 0;
|
|
||||||
renderPanelState(video, panel);
|
renderPanelState(video, panel);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user