Commit inicial
This commit is contained in:
306
background.js
Normal file
306
background.js
Normal file
@@ -0,0 +1,306 @@
|
||||
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*`;
|
||||
|
||||
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 target = await getComcipTab();
|
||||
|
||||
try {
|
||||
await waitForComcipTabReady(target.tab.id);
|
||||
await waitForComcipSessionReady(target.tab.id, headers);
|
||||
|
||||
let response = await executeComcipFetch(target.tab.id, url, method, payload, headers);
|
||||
|
||||
if (isAuthorizationFailure(response)) {
|
||||
await delay(1500);
|
||||
await waitForComcipSessionReady(target.tab.id, headers);
|
||||
response = await executeComcipFetch(target.tab.id, url, method, payload, headers);
|
||||
}
|
||||
|
||||
return response;
|
||||
} finally {
|
||||
if (target.created && target.tab.id) {
|
||||
await chrome.tabs.remove(target.tab.id).catch(() => {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getComcipTab() {
|
||||
const tabs = await chrome.tabs.query({ url: COMCIP_TAB_URL_PATTERN });
|
||||
const existing = tabs.find((tab) => tab.id && !tab.discarded);
|
||||
|
||||
if (existing) {
|
||||
return {
|
||||
tab: existing,
|
||||
created: false,
|
||||
};
|
||||
}
|
||||
|
||||
const created = await chrome.tabs.create({
|
||||
url: COMCIP_APP_URL,
|
||||
active: false,
|
||||
});
|
||||
|
||||
return {
|
||||
tab: created,
|
||||
created: true,
|
||||
};
|
||||
}
|
||||
|
||||
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 = {}) {
|
||||
const startedAt = Date.now();
|
||||
let lastStatus = "";
|
||||
|
||||
while (Date.now() - startedAt < 60000) {
|
||||
const probe = await executeComcipProbe(tabId, headers).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 = {}) {
|
||||
const [injectionResult] = await chrome.scripting.executeScript({
|
||||
target: { tabId },
|
||||
world: "MAIN",
|
||||
args: [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) {
|
||||
const [injectionResult] = await chrome.scripting.executeScript({
|
||||
target: { tabId },
|
||||
world: "MAIN",
|
||||
args: [requestUrl, method || "POST", payload || null, headers || {}],
|
||||
func: async (requestUrl, requestMethod, requestPayload, sourceHeaders) => {
|
||||
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) {
|
||||
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(CLIENT_ID_PROBE_URL, {
|
||||
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);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user