<!doctype html>
<html>
  <head>
    <meta charset="utf-8"/>
    <meta name="referrer" content="no-referrer"/>
    <meta name="color-scheme" content="light dark"/>
    <!--
      The Content Security Policy is dynamically created by Rust at request time based on the domains declared in the MCP App's resource metadata.
    -->
    <meta 
      http-equiv="Content-Security-Policy" 
      content="{{OUTER_CSP}}"/>
    <title>MCP App Sandbox</title>
    <style>
      body,
      html {
        margin: 0;
        padding: 0;
        height: 100%;
        width: 100%;
        overflow: hidden;
      }
      iframe {
        width: 100%;
        height: 100%;
        border: none;
      }
    </style>
  </head>
  <body>
    <script>
      (function () {
        'use strict';

        let guestIframe = null;

        /**
         * Extract the secret and base URL from the current page URL.
         */
        function getProxyParams() {
          var params = new URLSearchParams(window.location.search);
          return {
            secret: params.get('secret') || '',
            baseUrl: window.location.origin
          };
        }

        /**
         * Store guest HTML on the server and get a nonce for retrieval.
         * This allows the guest iframe to load from a real HTTPS URL
         * instead of srcdoc (which has about: protocol).
         */
        async function storeGuestHtml(html) {
          var proxyParams = getProxyParams();
          var response = await fetch(proxyParams.baseUrl + '/mcp-app-guest', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
              secret: proxyParams.secret,
              html: html
            })
          });

          if (!response.ok) {
            throw new Error('Failed to store guest HTML: ' + response.status);
          }

          var data = await response.json();
          return data.nonce;
        }

        async function createGuestIframe(html, permissions) {
          if (guestIframe) {
            guestIframe.remove();
          }

          guestIframe = document.createElement('iframe');

          // Sandbox permissions for the Guest UI
          // allow-scripts: needed for the app to run
          // allow-same-origin: needed for localStorage, cookies, and real URL context
          // allow-forms: needed if the app has forms
          guestIframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms');

          // Build Permission Policy allow attribute from requested permissions
          // These control access to sensitive browser APIs like camera, microphone, etc.
          var allowList = [];
          if (permissions && permissions.camera) allowList.push('camera');
          if (permissions && permissions.microphone) allowList.push('microphone');
          if (permissions && permissions.geolocation) allowList.push('geolocation');
          if (permissions && permissions.clipboardWrite) allowList.push('clipboard-write');
          if (allowList.length > 0) {
            guestIframe.setAttribute('allow', allowList.join('; '));
          }

          guestIframe.style.cssText = 'width:100%; height:100%; border:none;';

          // Store the HTML server-side and load via real URL.
          // This gives the guest iframe a real https:// URL instead of about:srcdoc,
          // which is required by SDKs (like Square Web Payments) that check
          // window.location.protocol for secure context verification.
          try {
            var nonce = await storeGuestHtml(html);
            var proxyParams = getProxyParams();
            guestIframe.src = proxyParams.baseUrl + '/mcp-app-guest?secret=' + encodeURIComponent(proxyParams.secret) + '&nonce=' + encodeURIComponent(nonce);
          } catch (e) {
            // Fallback to srcdoc if the store endpoint is not available
            console.warn('Failed to use /mcp-app-guest endpoint, falling back to srcdoc:', e);
            guestIframe.srcdoc = html;
          }

          document
            .body
            .appendChild(guestIframe);
        }

        /**
         * Handle messages from the Host (parent window).
         */
        function handleHostMessage(event) {
          if (event.source !== window.parent) {
            return;
          }

          var data = event.data;
          if (!data || typeof data !== 'object') {
            return;
          }

          var method = data.method;

          // Handle sandbox-specific notifications from Host
          if (method === 'ui/notifications/sandbox-resource-ready') {
            var params = data.params || {};
            var html = params.html || '';
            var permissions = params.permissions || null;

            createGuestIframe(html, permissions);
            return;
          }

          // Forward all other messages to Guest UI (if it exists)
          // This includes lifecycle messages like responses to ui/initialize
          if (guestIframe && guestIframe.contentWindow) {
            guestIframe
              .contentWindow
              .postMessage(data, '*');
          }
        }

        /**
         * Handle messages from the Guest UI (inner iframe).
         */
        function handleGuestMessage(event) {
          if (!guestIframe || event.source !== guestIframe.contentWindow) {
            return;
          }

          var data = event.data;
          if (!data || typeof data !== 'object') {
            return;
          }

          // Forward all messages from Guest UI to Host
          // The Sandbox does NOT create its own requests - just relays
          window
            .parent
            .postMessage(data, '*');
        }

        /**
         * Main message handler - routes to appropriate handler.
         */
        function handleMessage(event) {
          if (event.source === window.parent) {
            handleHostMessage(event);
          } else if (guestIframe && event.source === guestIframe.contentWindow) {
            handleGuestMessage(event);
          }
        }

        // Set up message listener
        window.addEventListener('message', handleMessage);

        // Notify Host that Sandbox is ready
        window
          .parent
          .postMessage({
            jsonrpc: '2.0',
            method: 'ui/notifications/sandbox-proxy-ready',
            params: {}
          }, '*');
      })();
    </script>
  </body>
</html>
