const COMCIP_ORIGIN = "https://comcipapic-oalprod.integration.ocp.oraclecloud.com"; const COMCIP_APP_URL = `${COMCIP_ORIGIN}/ic/builder/rt/oalset_semc/live/webApps/Dashboard/?page=shell&shell=main&main=service-requests-detailed-view`; const COMCIP_QUERY_URL = `${COMCIP_ORIGIN}/ic/builder/rt/oalset_semc/live;profile=PROD/services/auth/1.1/proxy/oalsetCRMRestAPIElastic/uri/https/eeho.fa.us2.oraclecloud.com/crmRestApi/searchResources/latest/custom-actions/queries`; const COMCIP_CLIENT_ID_PROBE_URL = `${COMCIP_ORIGIN}/ic/builder/rt/oalset_semc/live;profile=PROD/services/auth/1.1/proxy/oalsetSeaaSOKECustomRestAPI/uri/https/gxpap.oracle.com/oalcrm/service/set/seaas/crm/countries`; const COMCIP_TAB_URL_PATTERN = `${COMCIP_ORIGIN}/ic/builder/rt/oalset_semc/live*`; const COMCIP_TIME_ENTRY_TAB_URL_PATTERN = `${COMCIP_ORIGIN}/ic/builder/rt/oalset_timeentrymobile/live*`; chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => { if ( !message || (message.type !== "ARCH_PANEL_COMCIP_POST" && message.type !== "ARCH_PANEL_COMCIP_REQUEST") ) { return false; } requestComcipFromPage({ url: message.url || COMCIP_QUERY_URL, method: message.method || "POST", payload: message.payload, headers: message.headers, }) .then(sendResponse) .catch((error) => { sendResponse({ ok: false, status: 0, error: error instanceof Error ? error.message : String(error), }); }); return true; }); async function requestComcipFromPage({ url, method = "POST", payload, headers = {} }) { const route = getComcipRoute(url); const activeTab = await captureActiveTab(); const target = await getComcipTab(route, activeTab); try { await restoreActiveTab(activeTab); await waitForComcipTabReady(target.tab.id); await waitForComcipSessionReady(target.tab.id, headers, route); let response = await executeComcipFetch( target.tab.id, url, method, payload, headers, route ); if (isAuthorizationFailure(response)) { await delay(1500); await waitForComcipSessionReady(target.tab.id, headers, route); response = await executeComcipFetch( target.tab.id, url, method, payload, headers, route ); } return response; } finally { if (target.created && target.tab.id) { await chrome.tabs.remove(target.tab.id).catch(() => {}); } await restoreActiveTab(activeTab); } } function getComcipRoute(requestUrl) { const normalizedUrl = String(requestUrl || ""); if (normalizedUrl.includes("/ic/builder/rt/oalset_timeentrymobile/live")) { return { appUrl: normalizedUrl, clientIdProbeUrl: normalizedUrl, tabPattern: COMCIP_TIME_ENTRY_TAB_URL_PATTERN, }; } return { appUrl: COMCIP_APP_URL, clientIdProbeUrl: COMCIP_CLIENT_ID_PROBE_URL, tabPattern: COMCIP_TAB_URL_PATTERN, }; } async function getComcipTab(route, activeTab) { const tabs = await chrome.tabs.query({ url: route.tabPattern }); const existing = tabs.find((tab) => tab.id && !tab.discarded); if (existing) { return { tab: existing, created: false, }; } const created = await chrome.tabs.create({ url: route.appUrl, active: false, windowId: activeTab?.windowId, }); await restoreActiveTab(activeTab); return { tab: created, created: true, }; } async function captureActiveTab() { const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true, }); if (!activeTab?.id) { return null; } return { id: activeTab.id, windowId: activeTab.windowId, }; } async function restoreActiveTab(activeTab) { if (!activeTab?.id) { return; } await chrome.windows.update(activeTab.windowId, { focused: true }).catch(() => {}); await chrome.tabs.update(activeTab.id, { active: true }).catch(() => {}); } async function waitForComcipTabReady(tabId) { const startedAt = Date.now(); while (Date.now() - startedAt < 45000) { const tab = await chrome.tabs.get(tabId); const url = String(tab.url || ""); if (tab.status === "complete" && url.startsWith(COMCIP_ORIGIN)) { await delay(1000); return; } await delay(500); } throw new Error("Timed out while loading the COMCIP origin page."); } async function waitForComcipSessionReady(tabId, headers = {}, route) { const startedAt = Date.now(); let lastStatus = ""; while (Date.now() - startedAt < 60000) { const probe = await executeComcipProbe(tabId, headers, route).catch((error) => ({ ok: false, status: 0, error: error instanceof Error ? error.message : String(error), })); if (probe?.ok && probe?.appBuilderClientId) { return probe; } lastStatus = probe?.status ? `${probe.status} ${probe.statusText || ""}`.trim() : probe?.error || "not ready"; await delay(1000); } throw new Error(`Timed out while waiting for COMCIP authenticated session (${lastStatus}).`); } async function executeComcipProbe(tabId, headers = {}, route) { const [injectionResult] = await chrome.scripting.executeScript({ target: { tabId }, world: "MAIN", args: [route?.clientIdProbeUrl || COMCIP_CLIENT_ID_PROBE_URL, headers || {}], func: async (probeUrl, sourceHeaders) => { const APP_VERSION = "version_1754044416761"; const response = await fetch(probeUrl, { method: "GET", credentials: "include", cache: "no-store", headers: { accept: "*/*", authorization: "Session", "accept-language": sourceHeaders["accept-language"] || navigator.language || "pt-BR", "x-vb-application-version": sourceHeaders["x-vb-application-version"] || APP_VERSION, }, }); return { ok: response.ok, status: response.status, statusText: response.statusText, appBuilderClientId: response.headers.get("x-appbuilder-client-id") || "", href: window.location.href, }; }, }); if (!injectionResult) { throw new Error("COMCIP probe did not return a result."); } return injectionResult.result; } async function executeComcipFetch(tabId, requestUrl, method, payload, headers, route) { const [injectionResult] = await chrome.scripting.executeScript({ target: { tabId }, world: "MAIN", args: [ requestUrl, method || "POST", payload || null, headers || {}, route?.clientIdProbeUrl || COMCIP_CLIENT_ID_PROBE_URL, ], func: async ( requestUrl, requestMethod, requestPayload, sourceHeaders, clientIdProbeUrl ) => { const APP_VERSION = "version_1754044416761"; function parseResponseText(text) { if (!text) { return null; } try { return JSON.parse(text); } catch { return text; } } function pickResponseHeaders(headers) { const safeHeaders = {}; const exposedHeaders = [ "content-type", "x-appbuilder-client-id", "x-invalid-appbuilder-client-id", "x-appbuilder-repeat-request", "vb-proxy-status-actual", "vb-proxy-version", ]; for (const key of exposedHeaders) { const value = headers.get(key); if (value) { safeHeaders[key] = value; } } return safeHeaders; } async function resolveAppBuilderClientId() { try { const response = await fetch(clientIdProbeUrl, { method: "GET", credentials: "include", cache: "no-store", headers: { accept: "*/*", authorization: "Session", "accept-language": sourceHeaders["accept-language"] || navigator.language || "pt-BR", "x-vb-application-version": sourceHeaders["x-vb-application-version"] || APP_VERSION, }, }); return response.headers.get("x-appbuilder-client-id") || ""; } catch { return ""; } } const appBuilderClientId = sourceHeaders["x-appbuilder-client-id"] || (await resolveAppBuilderClientId()); const requestHeaders = { accept: "*/*", authorization: "Session", "vb-proxy-header-preference": "transient", "x-vb-application-version": sourceHeaders["x-vb-application-version"] || APP_VERSION, "accept-language": sourceHeaders["accept-language"] || navigator.language || "pt-BR", }; if (appBuilderClientId) { requestHeaders["x-appbuilder-client-id"] = appBuilderClientId; } const normalizedMethod = String(requestMethod || "POST").toUpperCase(); const fetchOptions = { method: normalizedMethod, credentials: "include", cache: "no-store", headers: requestHeaders, }; if (normalizedMethod !== "GET" && normalizedMethod !== "HEAD") { requestHeaders["content-type"] = "application/json"; fetchOptions.body = JSON.stringify(requestPayload || {}); } const response = await fetch(requestUrl, { ...fetchOptions, }); const text = await response.text(); return { ok: response.ok, status: response.status, statusText: response.statusText, headers: pickResponseHeaders(response.headers), payload: parseResponseText(text), debug: { href: window.location.href, origin: window.location.origin, headerKeys: Object.keys(requestHeaders), }, }; }, }); if (!injectionResult) { throw new Error("COMCIP page script did not return a result."); } return injectionResult.result; } function isAuthorizationFailure(response) { if (!response) { return false; } const payloadText = typeof response.payload === "string" ? response.payload : JSON.stringify(response.payload || ""); return ( response.status === 401 || /401 Authorization Required/i.test(payloadText) || /Authorization Required/i.test(payloadText) ); } function delay(milliseconds) { return new Promise((resolve) => { setTimeout(resolve, milliseconds); }); }