From cb04fd5b19d7be3c1f9e7c55d3079e11d10bc2f9 Mon Sep 17 00:00:00 2001 From: Sameh Khamis Date: Fri, 2 Oct 2026 09:40:12 -0700 Subject: [PATCH] feat: say in the panel what a host's security policy blocked When a host's content security policy refuses part of the panel, such as its frame, the panel now names the blocked directive and address instead of waiting until its load timeout. --- src/tools/globePanel.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/tools/globePanel.js b/src/tools/globePanel.js index 982914e3d..dbe886902 100644 --- a/src/tools/globePanel.js +++ b/src/tools/globePanel.js @@ -40,6 +40,14 @@ function panelHtml(appOrigin) { const APP_ORIGIN = ${JSON.stringify(appOrigin)}; const LOAD_TIMEOUT_MS = 20000; const status = document.getElementById('status'); + // When the host's security policy blocks part of the panel, say what was + // blocked; otherwise a refused frame only shows as a load that never ends. + let blocked = null; + document.addEventListener('securitypolicyviolation', (event) => { + blocked = event.effectiveDirective + ' blocked ' + (event.blockedURI || 'a resource'); + if (status.isConnected) + status.textContent = "God's Eye View could not load here: " + blocked + '.'; + }); const open = document.getElementById('open'); let nextId = 1; const pending = new Map(); @@ -88,7 +96,9 @@ function panelHtml(appOrigin) { setTimeout(() => { if (!frameReady) status.textContent = - "God's Eye View did not load here. Use Open in God's Eye View above."; + "God's Eye View did not load here" + + (blocked ? ' (' + blocked + ')' : '') + + ". Use Open in God's Eye View above."; }, LOAD_TIMEOUT_MS); return; }