mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 10:05:14 +00:00
Intercept iframe navigation and open links externally
- Add navigation interceptor script that prevents all iframe navigation - Intercept link clicks, form submissions, and window.location changes - Send open-external-url messages to parent window - Use chrome.tabs.create() in extension context, window.open() fallback - Fix font-size workaround to use 'initial' instead of hardcoded 16px - Document Chrome extension font-size bug with Stack Overflow reference This prevents HTML artifacts from navigating away when users click links, which would break the sandbox message system. All links now open in new Chrome tabs instead.
This commit is contained in:
parent
2a67556e5d
commit
98ea763d64
1 changed files with 65 additions and 2 deletions
|
|
@ -133,6 +133,21 @@ export class SandboxIframe extends LitElement {
|
|||
// Update router with iframe reference BEFORE appending to DOM
|
||||
RUNTIME_MESSAGE_ROUTER.setSandboxIframe(sandboxId, this.iframe);
|
||||
|
||||
// Listen for open-external-url messages from iframe
|
||||
const externalUrlHandler = (e: MessageEvent) => {
|
||||
if (e.data.type === "open-external-url" && e.source === this.iframe?.contentWindow) {
|
||||
// Use chrome.tabs API to open in new tab
|
||||
const chromeAPI = (globalThis as any).chrome;
|
||||
if (chromeAPI?.tabs) {
|
||||
chromeAPI.tabs.create({ url: e.data.url });
|
||||
} else {
|
||||
// Fallback for non-extension context
|
||||
window.open(e.data.url, "_blank");
|
||||
}
|
||||
}
|
||||
};
|
||||
window.addEventListener("message", externalUrlHandler);
|
||||
|
||||
// Listen for sandbox-ready and sandbox-error messages directly
|
||||
const readyHandler = (e: MessageEvent) => {
|
||||
if (e.data.type === "sandbox-ready" && e.source === this.iframe?.contentWindow) {
|
||||
|
|
@ -189,6 +204,15 @@ export class SandboxIframe extends LitElement {
|
|||
// Update router with iframe reference BEFORE appending to DOM
|
||||
RUNTIME_MESSAGE_ROUTER.setSandboxIframe(sandboxId, this.iframe);
|
||||
|
||||
// Listen for open-external-url messages from iframe
|
||||
const externalUrlHandler = (e: MessageEvent) => {
|
||||
if (e.data.type === "open-external-url" && e.source === this.iframe?.contentWindow) {
|
||||
// Fallback for non-extension context
|
||||
window.open(e.data.url, "_blank");
|
||||
}
|
||||
};
|
||||
window.addEventListener("message", externalUrlHandler);
|
||||
|
||||
this.appendChild(this.iframe);
|
||||
}
|
||||
|
||||
|
|
@ -495,9 +519,13 @@ export class SandboxIframe extends LitElement {
|
|||
})
|
||||
.join("\n");
|
||||
|
||||
// TODO the font-size is needed, as chrome seems to inject a stylesheet into iframes
|
||||
// found in an extension context like sidepanel, settin body { font-size: 75% }. It's
|
||||
// definitely not our code doing that.
|
||||
// See https://stackoverflow.com/questions/71480433/chrome-is-injecting-some-stylesheet-in-popup-ui-which-reduces-the-font-size-to-7
|
||||
return `<style>
|
||||
html {
|
||||
font-size: 16px;
|
||||
html, body {
|
||||
font-size: initial;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
|
|
@ -505,6 +533,41 @@ window.sandboxId = ${JSON.stringify(sandboxId)};
|
|||
${dataInjection}
|
||||
${bridgeCode}
|
||||
${runtimeFunctions.join("\n")}
|
||||
|
||||
// Navigation interceptor: prevent all navigation and open externally
|
||||
(function() {
|
||||
// Intercept link clicks
|
||||
document.addEventListener('click', function(e) {
|
||||
const link = e.target.closest('a');
|
||||
if (link && link.href) {
|
||||
// Check if it's an external link (not javascript: or #hash)
|
||||
if (link.href.startsWith('http://') || link.href.startsWith('https://')) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
window.parent.postMessage({ type: 'open-external-url', url: link.href }, '*');
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Intercept form submissions
|
||||
document.addEventListener('submit', function(e) {
|
||||
const form = e.target;
|
||||
if (form && form.action) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
window.parent.postMessage({ type: 'open-external-url', url: form.action }, '*');
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Prevent window.location changes
|
||||
const originalLocation = window.location;
|
||||
Object.defineProperty(window, 'location', {
|
||||
get: function() { return originalLocation; },
|
||||
set: function(url) {
|
||||
window.parent.postMessage({ type: 'open-external-url', url: url.toString() }, '*');
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>`;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue