Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions public/popup-interceptor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* Popup Interceptor Script
* This script is injected into proxied pages to intercept window.open calls
* and redirect them to the parent iframe instead of opening new tabs/windows.
*
* The script only runs in iframe contexts and intercepts popups that would
* normally open in new tabs/windows (target="_blank", "_new", or empty).
*/

(function () {
"use strict";

// Only run if we're in an iframe
if (window.self === window.top) {
return;
}

// Store the original window.open function
const originalWindowOpen = window.open;

// Override window.open to intercept popup attempts
window.open = function (url, target, features) {
console.log("[Radius] Intercepting window.open:", url, target);

// If target is _blank, _new, or not specified, intercept it
if (!target || target === "_blank" || target === "_new" || target === "") {
// Send message to parent window to open the URL in the main iframe
try {
window.top.postMessage(
{
type: "radius-popup-intercept",
url: url ? url.toString() : ""
},
"*"
);

console.log("[Radius] Popup intercepted and sent to parent");

// Return null since we're not actually opening a new window
return null;
} catch (e) {
console.error("[Radius] Failed to send popup intercept message:", e);
// Fallback to original behavior if messaging fails
return originalWindowOpen.call(this, url, target, features);
}
}

// For other targets (like named frames), use the original function
return originalWindowOpen.call(this, url, target, features);
};

console.log("[Radius] Popup interceptor initialized");
})();
41 changes: 38 additions & 3 deletions public/sw.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,48 @@ 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);
} else if (sj.route(event)) {
return await sj.fetch(event);
response = await sj.fetch(event);
} else {
return await fetch(request);
response = await fetch(request);
}

// Inject popup interceptor script into HTML pages
if (response && response.headers.get("content-type")?.includes("text/html")) {
// Only inject into proxied content
if (url.startsWith(location.origin + __uv$config.prefix) || sj.route(event)) {
try {
const text = await response.text();
// Inject the popup interceptor script at the beginning of the body or head
const injectedScript = '<script src="/popup-interceptor.js"></script>';
let modifiedText = text;

// Try to inject into <head> first, then <body>, then at start of html
if (text.includes("<head>")) {
modifiedText = text.replace("<head>", "<head>" + injectedScript);
} else if (text.includes("<body>")) {
modifiedText = text.replace("<body>", "<body>" + injectedScript);
} else if (text.includes("<html>")) {
modifiedText = text.replace("<html>", "<html>" + injectedScript);
}

// Create new response with modified content
response = new Response(modifiedText, {
status: response.status,
statusText: response.statusText,
headers: response.headers
});
} catch (e) {
console.error("[Radius SW] Failed to inject popup interceptor:", e);
// Return original response if injection fails
}
}
}

return response;
})()
);
});
52 changes: 51 additions & 1 deletion src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const link = Astro.url.searchParams.get("redir");
</div>
</div> */}
</div>
<iframe id="iframe" class="fixed h-[calc(100%-3.5rem)] mt-14 w-full hidden bg-(--background)" />
<iframe id="iframe" sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-downloads allow-orientation-lock allow-pointer-lock allow-presentation" class="fixed h-[calc(100%-3.5rem)] mt-14 w-full hidden bg-(--background)" />
<link-element data-link={link} />
</div>
</Layout>
Expand Down Expand Up @@ -102,6 +102,50 @@ const link = Astro.url.searchParams.get("redir");
}); */
}

// Intercept popup attempts from within the iframe by injecting a script
const interceptPopups = () => {
try {
if (!iframeWin || !iframeWin.document) return;

// Check if we can access the iframe document (same-origin or via proxy)
const iframeDoc = iframeWin.document;

// Create a script element to inject into the iframe
const script = iframeDoc.createElement('script');
script.src = '/popup-interceptor.js';
script.async = true;

// Append the script to the iframe's document
if (iframeDoc.head) {
iframeDoc.head.appendChild(script);
console.log('[Radius] Popup interceptor script injected');
} else if (iframeDoc.body) {
iframeDoc.body.appendChild(script);
console.log('[Radius] Popup interceptor script injected to body');
}
} catch (e) {
// This will fail due to cross-origin restrictions
// In this case, rely on the sandbox attribute to prevent popups from escaping
console.debug('[Radius] Could not inject popup interceptor (cross-origin):', e);
console.log('[Radius] Relying on sandbox attribute to prevent popup escaping');
}
};

// Listen for popup interception messages from iframe
window.addEventListener('message', (event) => {
// Only accept messages from our iframe
if (event.source !== iframeWin) return;

if (event.data?.type === 'radius-popup-intercept' && event.data?.url) {
console.log('[Radius] Received popup intercept message, loading in iframe:', event.data.url);
// Load the URL in the main iframe instead of opening a new window
const url = event.data.url;
if (url) {
iframe.src = sw.encodeURL(url);
}
}
});

iframe.addEventListener("load", async () => {
phlTitle.innerHTML = iframeWin!.document.title;
const pageURL = await getURL();
Expand All @@ -111,6 +155,12 @@ const link = Astro.url.searchParams.get("redir");
phlImage.src = object;
bhl.classList.add("hidden");
phl.classList.remove("hidden");

// Try to inject popup interceptor after the iframe loads
// Use a small delay to ensure the iframe document is ready
setTimeout(() => {
interceptPopups();
}, 100);
});
}

Expand Down