From aa5173e0d4d3af702f7f3fb2d170f4dc001d9fe8 Mon Sep 17 00:00:00 2001 From: Timo <6156589+Shik3i@users.noreply.github.com> Date: Tue, 18 Aug 2026 00:36:23 +0200 Subject: [PATCH] fix(extension): report why a target failed instead of a generic comm error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dev panel asked the content script for video state even when activation never completed, so every failure surfaced as "communication with the tab video failed" — the one message that says nothing about the cause. It now shows the activation state and its actual error, and content injection logs the frame it was aimed at. Co-Authored-By: Claude Opus 5 --- extension/background.js | 8 ++++++++ extension/popup.js | 20 +++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/extension/background.js b/extension/background.js index d5ebe07..1b197bb 100644 --- a/extension/background.js +++ b/extension/background.js @@ -2504,6 +2504,14 @@ async function injectContentScript(tabId, { try { error.contentTarget = contentTarget; } catch { /* immutable browser error */ } throw error; } + // Name the frame the injection was aimed at. Without it every failure + // reads the same in the log and there is no way to tell a denied player + // frame from a document that navigated mid-injection. + addLog( + `Content injection failed in frame ${contentTarget.frameId}` + + `${contentTarget.frameUrl ? ` (${contentTarget.frameUrl})` : ''}: ${error?.message}`, + 'warn' + ); if (navigationRetries > 0 && isMediaTargetNavigationError(error)) { return injectContentScript(tabId, { requestHostAccess, diff --git a/extension/popup.js b/extension/popup.js index df1076e..5d81aa0 100644 --- a/extension/popup.js +++ b/extension/popup.js @@ -2797,10 +2797,28 @@ function refreshDebugInfo() { return; } + // A target that never finished activating has no content script to talk + // to. Reporting that as a communication failure hides the actual reason, + // which is the only thing that makes the problem fixable. + if (res.targetReady === false && elements.videoDebug) { + const reason = res.targetActivationError + || (res.targetActivationState === 'access_required' + ? `Website access required${res.pendingTargetHost ? ` for ${res.pendingTargetHost}` : ''}` + : null); + elements.videoDebug.textContent = reason + ? `${res.targetActivationState}: ${reason}` + : `${res.targetActivationState}…`; + return; + } + // Request direct state from the content script via background chrome.runtime.sendMessage({ type: 'GET_VIDEO_STATE', tabId: res.targetTabId }, (state) => { if (!state || (!state.found && state.error)) { - if (elements.videoDebug) elements.videoDebug.textContent = getMessage('DEBUG_COMM_FAIL'); + if (elements.videoDebug) { + elements.videoDebug.textContent = state?.error + ? `${getMessage('DEBUG_COMM_FAIL')} (${state.error})` + : getMessage('DEBUG_COMM_FAIL'); + } return; }