function createSpaPage() { function start() { if (location.origin !== "https://spa.oracle.com" || window.top !== window) return; const runtime = (globalThis.browser || globalThis.chrome)?.runtime; if (!runtime) return; const documentId = `${performance.timeOrigin}:${location.pathname}`; let identityRequest = null; function inspect() { const text = `${document.title}\n${document.body?.innerText || ""}`.trim(); let status = "loading"; if (/\b(?:401\s+(?:authorization required|unauthorized)|403\s+forbidden|access denied|authorization required|authentication failed|internal server error|service unavailable|bad gateway)\b/i.test(text)) status = "error"; else if (/^\/(?:cloudgate|login|signin|sso|oauth)(?:\/|$)/i.test(location.pathname) || /\b(?:sign(?:ing)? in|log in|single sign.on|oracle access manager)\b/i.test(document.title) || document.querySelector('input[name="SAMLResponse"], input[name="SAMLRequest"], input[type="password"], form[action*="/sso"], form[action*="/login"], meta[http-equiv="refresh" i]')) status = "login"; else if ((document.readyState === "interactive" || document.readyState === "complete") && text && document.querySelector('a[href], button, input, [role="main"], main, nav')) status = "ready"; return { status, documentId }; } runtime.onMessage.addListener((message, sender, reply) => { if (sender.id !== runtime.id) return false; if (message?.type === "opportunitiesExtension.inspectSpaPage") { reply(inspect()); return false; } if (message?.type !== "opportunitiesExtension.readSpaIdentity") return false; const page = inspect(); if (page.status !== "ready" || page.documentId !== message.documentId) { reply({ error: "SPA page is not ready or has navigated." }); return false; } // A document is probed at most once; failed identity reads require a fresh navigation. if (!identityRequest) identityRequest = (async () => { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), 15000); try { const response = await fetch("https://spa.oracle.com/oalcrm/web/api/identity-management/users/current", { method: "GET", credentials: "include", cache: "no-store", headers: { Accept: "application/json" }, signal: controller.signal }); return { status: response.status, statusText: response.statusText, headers: Object.fromEntries(response.headers), contentType: response.headers.get("content-type") || "", body: await response.text() }; } catch (error) { return { error: error.message || "Unable to read SPA identity." }; } finally { clearTimeout(timer); } })(); identityRequest.then(reply); return true; }); } return { start }; }