From 6eb2fbb9ca49b83713392e7314dc26b9e485e777 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Nov 2025 22:36:59 +0000 Subject: [PATCH 1/4] Initial plan From 8caf5e15a3ea012c620a49a5defc422b67213d2a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Nov 2025 22:46:17 +0000 Subject: [PATCH 2/4] Add window.open and link interception to force URLs to open in main iframe Co-authored-by: sriail <225764385+sriail@users.noreply.github.com> --- public/iframe-intercept.js | 53 +++++++++++++++++ src/pages/index.astro | 117 +++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 public/iframe-intercept.js diff --git a/public/iframe-intercept.js b/public/iframe-intercept.js new file mode 100644 index 0000000..e98b48c --- /dev/null +++ b/public/iframe-intercept.js @@ -0,0 +1,53 @@ +// This script intercepts window.open calls and link clicks to force them to open in the parent iframe +// It must be injected into the iframe context after UV/Scramjet initialization + +(function() { + 'use strict'; + + // Store reference to original window.open + const originalWindowOpen = window.open; + + // Override window.open to redirect to parent iframe + window.open = function(url, target, features) { + if (url && window.parent !== window) { + // We're in an iframe, communicate with parent to navigate the iframe + try { + window.parent.postMessage({ + type: 'navigate-iframe', + url: url.toString() + }, '*'); + // Return null since we're not actually opening a window + return null; + } catch (e) { + console.error('Failed to communicate with parent:', e); + } + } + // Fallback to original behavior if not in iframe or message failed + return originalWindowOpen.call(this, url, target, features); + }; + + // Intercept clicks on links with target="_blank" or similar + document.addEventListener('click', function(e) { + const anchor = e.target.closest('a'); + if (anchor && anchor.href) { + const target = anchor.getAttribute('target'); + // Intercept _blank, _new, and other new window targets + if (target === '_blank' || target === '_new' || target === '_parent' || target === '_top') { + e.preventDefault(); + e.stopPropagation(); + // Use window.open override which will message parent + window.open(anchor.href); + } + } + }, true); // Use capture phase to intercept early + + // Also set base target to prevent default new window behavior + const baseTag = document.querySelector('base'); + if (!baseTag) { + const newBase = document.createElement('base'); + newBase.target = '_self'; + document.head.insertBefore(newBase, document.head.firstChild); + } else if (!baseTag.hasAttribute('target')) { + baseTag.target = '_self'; + } +})(); diff --git a/src/pages/index.astro b/src/pages/index.astro index 737b9d0..1797393 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -36,6 +36,46 @@ const link = Astro.url.searchParams.get("redir"); + + + + `; + +// Helper to inject script into HTML responses +async function injectInterceptScript(response) { + const contentType = response.headers.get('content-type') || ''; + console.log('[SW] Response content-type:', contentType); + if (!contentType.includes('text/html')) { + console.log('[SW] Not HTML, skipping injection'); + return response; + } + + try { + let text = await response.text(); + console.log('[SW] Got response text, length:', text.length); + + // Inject the script right after the opening tag or at the start + if (text.includes(']*)>/, `${INTERCEPT_SCRIPT}`); + console.log('[SW] Injected after tag'); + } else if (text.includes(']*)>/, `${INTERCEPT_SCRIPT}`); + console.log('[SW] Injected after tag'); + } else { + text = INTERCEPT_SCRIPT + text; + console.log('[SW] Injected at start'); + } + + return new Response(text, { + status: response.status, + statusText: response.statusText, + headers: response.headers + }); + } catch (e) { + console.error('[SW] Failed to inject script:', e); + return response; + } +} + self.addEventListener("fetch", function (event) { event.respondWith( (async () => { @@ -59,13 +145,24 @@ self.addEventListener("fetch", function (event) { request = enhanceCaptchaRequest(event.request); } + let response; if (url.startsWith(location.origin + __uv$config.prefix)) { - return await uv.fetch(event); + response = await uv.fetch(event); + // Inject our script into proxied HTML content + if (event.request.destination === 'document' || event.request.destination === 'iframe') { + response = await injectInterceptScript(response); + } } else if (sj.route(event)) { - return await sj.fetch(event); + response = await sj.fetch(event); + // Inject our script into proxied HTML content + if (event.request.destination === 'document' || event.request.destination === 'iframe') { + response = await injectInterceptScript(response); + } } else { - return await fetch(request); + response = await fetch(request); } + + return response; })() ); }); diff --git a/src/pages/index.astro b/src/pages/index.astro index 1797393..1cc77de 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -105,13 +105,16 @@ const link = Astro.url.searchParams.get("redir"); // Listen for messages from iframe to navigate it window.addEventListener('message', (event) => { + console.log('Received message:', event.data); if (event.data && event.data.type === 'navigate-iframe' && event.data.url) { // Navigate the iframe to the requested URL + console.log('Navigating iframe to:', event.data.url); iframe.src = sw.encodeURL(event.data.url); } // Handle internal navigation requests (from our global window.open override) if (event.data && event.data.type === 'navigate-iframe-internal' && event.data.url) { // Navigate the iframe to the requested URL + console.log('Navigating iframe (internal) to:', event.data.url); iframe.classList.remove("hidden"); iframe.src = sw.encodeURL(event.data.url); } @@ -169,21 +172,25 @@ const link = Astro.url.searchParams.get("redir"); // Inject the interception script into the iframe try { if (iframeWin && iframeWin.document) { + console.log("Injecting interception script into iframe"); const script = iframeWin.document.createElement('script'); script.textContent = ` (function() { 'use strict'; + console.log('[Iframe Intercept] Script loaded'); const originalWindowOpen = window.open; window.open = function(url, target, features) { + console.log('[Iframe Intercept] window.open called with:', url, target); if (url && window.parent !== window) { try { + console.log('[Iframe Intercept] Sending navigate message to parent'); window.parent.postMessage({ type: 'navigate-iframe', url: url.toString() }, '*'); return null; } catch (e) { - console.error('Failed to communicate with parent:', e); + console.error('[Iframe Intercept] Failed to communicate with parent:', e); } } return originalWindowOpen.call(this, url, target, features); @@ -193,9 +200,11 @@ const link = Astro.url.searchParams.get("redir"); const anchor = e.target.closest('a'); if (anchor && anchor.href) { const target = anchor.getAttribute('target'); + console.log('[Iframe Intercept] Link clicked:', anchor.href, 'target:', target); if (target === '_blank' || target === '_new' || target === '_parent' || target === '_top') { e.preventDefault(); e.stopPropagation(); + console.log('[Iframe Intercept] Intercepting link, calling window.open'); window.open(anchor.href); } } @@ -210,8 +219,10 @@ const link = Astro.url.searchParams.get("redir"); if (document.head) { document.head.insertBefore(newBase, document.head.firstChild); } + console.log('[Iframe Intercept] Created base tag with target="_self"'); } else if (!baseTag.hasAttribute('target')) { baseTag.target = '_self'; + console.log('[Iframe Intercept] Set existing base tag target to "_self"'); } }; if (document.readyState === 'loading') { @@ -222,6 +233,7 @@ const link = Astro.url.searchParams.get("redir"); })(); `; iframeWin.document.head.appendChild(script); + console.log("Interception script injected successfully"); } } catch (e) { // Cross-origin restrictions may prevent this during initial load diff --git a/test-page.html b/test-page.html new file mode 100644 index 0000000..a926afc --- /dev/null +++ b/test-page.html @@ -0,0 +1,25 @@ + + + + Test Page for Window Open + + +

Test Page

+

This page tests window.open and target="_blank" links.

+ +

Test Links:

+ + +

Test Buttons:

+ + + + + + From dadba8a7d49862101614696c7d3b4d59b3dcab7f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Nov 2025 22:58:17 +0000 Subject: [PATCH 4/4] Remove test file --- test-page.html | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 test-page.html diff --git a/test-page.html b/test-page.html deleted file mode 100644 index a926afc..0000000 --- a/test-page.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - Test Page for Window Open - - -

Test Page

-

This page tests window.open and target="_blank" links.

- -

Test Links:

- - -

Test Buttons:

- - - - - -