diff --git a/background.js b/background.js index 5e35cd7..706f3c3 100644 --- a/background.js +++ b/background.js @@ -7,6 +7,8 @@ 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 ( @@ -36,18 +38,35 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => { }); async function requestComcipFromPage({ url, method = "POST", payload, headers = {} }) { - const target = await getComcipTab(); + 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); + await waitForComcipSessionReady(target.tab.id, headers, route); - let response = await executeComcipFetch(target.tab.id, url, method, payload, headers); + let response = await executeComcipFetch( + target.tab.id, + url, + method, + payload, + headers, + route + ); if (isAuthorizationFailure(response)) { await delay(1500); - await waitForComcipSessionReady(target.tab.id, headers); - response = await executeComcipFetch(target.tab.id, url, method, payload, headers); + await waitForComcipSessionReady(target.tab.id, headers, route); + response = await executeComcipFetch( + target.tab.id, + url, + method, + payload, + headers, + route + ); } return response; @@ -55,11 +74,31 @@ async function requestComcipFromPage({ url, method = "POST", payload, headers = if (target.created && target.tab.id) { await chrome.tabs.remove(target.tab.id).catch(() => {}); } + + await restoreActiveTab(activeTab); } } -async function getComcipTab() { - const tabs = await chrome.tabs.query({ url: COMCIP_TAB_URL_PATTERN }); +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) { @@ -70,9 +109,11 @@ async function getComcipTab() { } const created = await chrome.tabs.create({ - url: COMCIP_APP_URL, + url: route.appUrl, active: false, + windowId: activeTab?.windowId, }); + await restoreActiveTab(activeTab); return { tab: created, @@ -80,6 +121,31 @@ async function getComcipTab() { }; } +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(); @@ -98,12 +164,12 @@ async function waitForComcipTabReady(tabId) { throw new Error("Timed out while loading the COMCIP origin page."); } -async function waitForComcipSessionReady(tabId, headers = {}) { +async function waitForComcipSessionReady(tabId, headers = {}, route) { const startedAt = Date.now(); let lastStatus = ""; while (Date.now() - startedAt < 60000) { - const probe = await executeComcipProbe(tabId, headers).catch((error) => ({ + const probe = await executeComcipProbe(tabId, headers, route).catch((error) => ({ ok: false, status: 0, error: error instanceof Error ? error.message : String(error), @@ -122,11 +188,11 @@ async function waitForComcipSessionReady(tabId, headers = {}) { throw new Error(`Timed out while waiting for COMCIP authenticated session (${lastStatus}).`); } -async function executeComcipProbe(tabId, headers = {}) { +async function executeComcipProbe(tabId, headers = {}, route) { const [injectionResult] = await chrome.scripting.executeScript({ target: { tabId }, world: "MAIN", - args: [COMCIP_CLIENT_ID_PROBE_URL, headers || {}], + args: [route?.clientIdProbeUrl || COMCIP_CLIENT_ID_PROBE_URL, headers || {}], func: async (probeUrl, sourceHeaders) => { const APP_VERSION = "version_1754044416761"; const response = await fetch(probeUrl, { @@ -160,15 +226,25 @@ async function executeComcipProbe(tabId, headers = {}) { return injectionResult.result; } -async function executeComcipFetch(tabId, requestUrl, method, payload, headers) { +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 || {}], - func: async (requestUrl, requestMethod, requestPayload, sourceHeaders) => { + 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"; - const CLIENT_ID_PROBE_URL = - `${window.location.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`; function parseResponseText(text) { if (!text) { @@ -206,7 +282,7 @@ async function executeComcipFetch(tabId, requestUrl, method, payload, headers) { async function resolveAppBuilderClientId() { try { - const response = await fetch(CLIENT_ID_PROBE_URL, { + const response = await fetch(clientIdProbeUrl, { method: "GET", credentials: "include", cache: "no-store", diff --git a/content-script.js b/content-script.js index b29df45..a6e9fdf 100644 --- a/content-script.js +++ b/content-script.js @@ -76,6 +76,8 @@ "https://comcipapic-oalprod.integration.ocp.oraclecloud.com/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", timeEntriesSummaryUrl: "https://comcipapic-oalprod.integration.ocp.oraclecloud.com/ic/builder/rt/oalset_semc/live;profile=PROD/services/auth/1.1/proxy/oalsetSeaaSOKECustomRestAPI/uri/https/gxpap.oracle.com/oalcrm/service/set/seaas/mgmt/timeEntries/summary", + resourceCurrentUserUrl: + "https://comcipapic-oalprod.integration.ocp.oraclecloud.com/ic/builder/rt/oalset_timeentrymobile/live;profile=PROD/services/auth/1.1/proxy/oke_seaas/uri/https/gxpap.oracle.com/oalcrm/service/set/seaas/crm/resourceUsers", appVersion: "version_1754044416761", }; @@ -2097,6 +2099,12 @@ const user = await fetchCurrentUser(); + updateLoadingProgress("Loading current resource user", 8); + + const resourceCurrentUser = await fetchResourceCurrentUser(user.userEmail).catch( + () => null + ); + updateLoadingProgress("Loading customer summary pages", 12); const customers = await fetchAllCustomers(user.userEmail); @@ -2208,13 +2216,16 @@ updateLoadingProgress("Loading pending delivery service requests", 90); - const pendingServiceRequests = await fetchPendingServiceRequests(); + const pendingServiceRequests = await fetchPendingServiceRequests().catch( + () => [] + ); updateLoadingProgress("Preparing dashboard cache", 96); const finalCustomers = Array.from(customersMap.values()); const exportPayload = createExportPayload( user, finalCustomers, - pendingServiceRequests + pendingServiceRequests, + resourceCurrentUser ); const dataset = createDatasetSnapshot(exportPayload); @@ -2686,6 +2697,39 @@ }; } + async function fetchResourceCurrentUser(userEmail) { + const normalizedUserEmail = cleanString(userEmail); + + if (!normalizedUserEmail) { + throw new Error("Unable to request resource current user without userEmail."); + } + + const url = `${COMCIP_REQUEST.resourceCurrentUserUrl}?emailAddress=${encodeURIComponent( + normalizedUserEmail + )}`; + const response = await sendComcipGetMessage(url); + + if (!response?.ok) { + const payloadMessage = + typeof response?.payload === "string" + ? cleanString(response.payload) + : firstNonEmptyString([ + response?.payload?.message, + response?.payload?.error, + response?.payload?.title, + response?.payload?.detail, + ]); + + throw new Error( + payloadMessage || + response?.error || + `COMCIP resource user request failed (${response?.status || 0}).` + ); + } + + return response.payload; + } + async function fetchAllCustomers(userEmail) { const limit = 49; @@ -3142,10 +3186,16 @@ }; } - function createExportPayload(user, customers, pendingServiceRequests = []) { + function createExportPayload( + user, + customers, + pendingServiceRequests = [], + resourceCurrentUser = null + ) { return { generatedAt: new Date().toISOString(), user, + resourceCurrentUser, customers, pendingServiceRequests, }; @@ -3156,6 +3206,7 @@ return { user: normalizedPayload.user, + resourceCurrentUser: normalizedPayload.resourceCurrentUser, customers: normalizedPayload.customers, exportPayload: normalizedPayload, summary: buildSummary(normalizedPayload), @@ -3262,6 +3313,7 @@ ]) || "", administrator: Boolean(exportPayload?.user?.administrator), }; + const resourceCurrentUser = exportPayload?.resourceCurrentUser ?? null; const normalizedCustomers = extractArray(exportPayload?.customers, ["customers"]) .map((customer) => ({ customerId: cleanString(customer?.customerId || customer?.id), @@ -3284,6 +3336,7 @@ generatedAt: firstNonEmptyString([exportPayload?.generatedAt]) || new Date().toISOString(), user: normalizedUser, + resourceCurrentUser, customers: normalizedCustomers, pendingServiceRequests, }; @@ -3916,7 +3969,8 @@ const exportPayload = createExportPayload( appState.dataset.user, updatedCustomers, - appState.dataset.exportPayload?.pendingServiceRequests || [] + appState.dataset.exportPayload?.pendingServiceRequests || [], + appState.dataset.exportPayload?.resourceCurrentUser || null ); const nextDataset = createDatasetSnapshot(exportPayload); const previousDetailModal = appState.detailModal diff --git a/manifest.json b/manifest.json index 26b46fc..443dee8 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Arch Panel Injector", - "version": "1.0.3", + "version": "1.0.7", "description": "Insere o botao Arch panel no header do Oracle Workload Workbench.", "permissions": [ "cookies", @@ -40,3 +40,7 @@ + + + +