feat: deep probe strategies G (non-enumerable/Symbol) and H (full window scan)
Strategy G — Independent non-enumerable + Symbol property detection on video elements. Uses Object.getOwnPropertyNames/Symbols to catch properties hidden by enumerable:false or Symbol keys. Walks nested objects for URL/levels/config signatures matching HLS instance heuristics. Strategy H — Full window global enumeration with player-like key filtering. Catches previously-unknown globals the player wrapper exposes internally. Content script bridge — merge content-level intercepted manifests into window.__goon_plugin_data so both interceptors and executeScript share findings. Add phncdn_reconstructed to dedup priority ranking.
This commit is contained in:
1 parent
877feec731
commit
509948def1
2 files changed
+188
-5
No files matched your search
+46
-4
@@ -31,15 +31,24 @@
|
||||
* extension-originated <script src="..."> as content scripts — not as
|
||||
* page inline code — so the page's CSP does not apply.
|
||||
*
|
||||
* IMPORTANT: Remove the script element ONLY after the load event fires.
|
||||
* Removing it synchronously can prevent the browser from starting the fetch,
|
||||
* especially in Edge/Chrome with strict timing.
|
||||
*
|
||||
* Runs BEFORE any page JS (document_start), so we catch all HLS activity.
|
||||
*/
|
||||
function injectInterceptors() {
|
||||
const script = document.createElement('script');
|
||||
script.src = chrome.runtime.getURL('interceptors.js');
|
||||
script.setAttribute('type', 'text/javascript');
|
||||
script.onload = function () {
|
||||
// Script loaded and executed — safe to remove the element now
|
||||
if (script.parentNode) {
|
||||
script.parentNode.removeChild(script);
|
||||
}
|
||||
};
|
||||
(document.head || document.documentElement).appendChild(script);
|
||||
// Remove the script element after execution but keep interceptors active
|
||||
script.parentNode.removeChild(script);
|
||||
// Keep the element in the DOM — onload will remove it after execution
|
||||
}
|
||||
|
||||
// Inject immediately at document_start
|
||||
@@ -59,6 +68,7 @@
|
||||
timestamp: event.data.timestamp
|
||||
});
|
||||
console.log('[goon-plugin] Intercepted HLS manifest via', source, ':', url);
|
||||
console.log('[goon-plugin] Total intercepted manifests so far:', interceptedManifests.length);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -96,14 +106,28 @@
|
||||
*/
|
||||
function getVideoData() {
|
||||
const poster = extractPoster();
|
||||
console.log('[goon-content] getVideoData called. Poster:', poster);
|
||||
console.log('[goon-content] Intercepted manifests count:', interceptedManifests.length);
|
||||
if (interceptedManifests.length > 0) {
|
||||
console.log('[goon-content] Manifest details:', JSON.stringify(interceptedManifests.map(m => ({ url: m.url, source: m.source }))));
|
||||
}
|
||||
|
||||
// DOM video scan (isolated world — can access DOM but not page JS)
|
||||
const videoElements = [];
|
||||
try {
|
||||
const videos = document.querySelectorAll('video');
|
||||
console.log('[goon-content] Found', videos.length, '<video> elements in DOM');
|
||||
for (const video of videos) {
|
||||
const style = window.getComputedStyle(video);
|
||||
if (style.display !== 'none' && video.clientWidth > 0 && video.clientHeight > 0) {
|
||||
const isVisible = style.display !== 'none' && video.clientWidth > 0 && video.clientHeight > 0;
|
||||
console.log('[goon-content] Video:', {
|
||||
src: (video.currentSrc || video.src || '').substring(0, 120),
|
||||
visible: isVisible,
|
||||
dimensions: video.clientWidth + 'x' + video.clientHeight,
|
||||
networkState: video.networkState,
|
||||
readyState: video.readyState,
|
||||
});
|
||||
if (isVisible) {
|
||||
// Extract buffered ranges as serializable arrays
|
||||
const bufferedRanges = [];
|
||||
if (video.buffered && video.buffered.length > 0) {
|
||||
@@ -122,7 +146,25 @@
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch { /* ignore DOM access errors */ }
|
||||
} catch(e) { /* ignore DOM access errors */
|
||||
console.warn('[goon-content] DOM scan error:', e && e.message ? e.message : e);
|
||||
}
|
||||
|
||||
console.log('[goon-content] Visible video elements:', videoElements.length);
|
||||
// Expose interceptor data globally so the popup's deep probe can read it.
|
||||
window.__goon_plugin_data = window.__goon_plugin_data || {
|
||||
manifests: [],
|
||||
sources: [],
|
||||
_contentType: 'content-script',
|
||||
};
|
||||
// Merge our intercepted manifests into the shared data store (the interceptors
|
||||
// write their own URLs here; we add content-script-level XHR intercepts).
|
||||
for (const m of interceptedManifests) {
|
||||
if (!window.__goon_plugin_data.manifests.includes(m.url)) {
|
||||
window.__goon_plugin_data.manifests.push(m.url);
|
||||
window.__goon_plugin_data.sources.push(m.source);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
posterUrl: poster,
|
||||
|
||||
Reference in new issue
Block a user