import {normalizeUrlIfValid} from 'react-devtools-shared/src/utils';
import {__DEBUG__} from 'react-devtools-shared/src/constants';
let debugIDCounter = 0;
const debugLog = (...args) => {
if (__DEBUG__) {
console.log(...args);
}
};
const fetchFromNetworkCache = (url, resolve, reject) => {
let debugID = null;
if (__DEBUG__) {
debugID = debugIDCounter++;
debugLog(`[main] fetchFromNetworkCache(${debugID})`, url);
}
chrome.devtools.network.getHAR(harLog => {
for (let i = 0; i < harLog.entries.length; i++) {
const entry = harLog.entries[i];
if (url !== entry.request.url) {
continue;
}
debugLog(
`[main] fetchFromNetworkCache(${debugID}) Found matching URL in HAR`,
url,
);
if (entry.getContent != null) {
entry.getContent(content => {
if (content) {
debugLog(
`[main] fetchFromNetworkCache(${debugID}) Content retrieved`,
);
resolve(content);
} else {
debugLog(
`[main] fetchFromNetworkCache(${debugID}) Invalid content returned by getContent()`,
content,
);
fetchFromPage(url, resolve, reject);
}
});
} else {
const content = entry.response.content.text;
if (content != null) {
debugLog(
`[main] fetchFromNetworkCache(${debugID}) Content retrieved`,
);
resolve(content);
} else {
debugLog(
`[main] fetchFromNetworkCache(${debugID}) Invalid content returned from entry.response.content`,
content,
);
fetchFromPage(url, resolve, reject);
}
}
}
debugLog(
`[main] fetchFromNetworkCache(${debugID}) No cached request found in getHAR()`,
);
fetchFromPage(url, resolve, reject);
});
};
const fetchFromPage = async (url, resolve, reject) => {
debugLog('[main] fetchFromPage()', url);
function onPortMessage({payload, source}) {
if (source === 'react-devtools-background') {
switch (payload?.type) {
case 'fetch-file-with-cache-complete':
chrome.runtime.onMessage.removeListener(onPortMessage);
resolve(payload.value);
break;
case 'fetch-file-with-cache-error':
chrome.runtime.onMessage.removeListener(onPortMessage);
reject(payload.value);
break;
}
}
}
chrome.runtime.onMessage.addListener(onPortMessage);
chrome.runtime.sendMessage({
source: 'devtools-page',
payload: {
type: 'fetch-file-with-cache',
tabId: chrome.devtools.inspectedWindow.tabId,
url,
},
});
};
async function fetchFileWithCaching(url: string): Promise<string> {
if (__IS_CHROME__ || __IS_EDGE__) {
const resources = await new Promise(resolve =>
chrome.devtools.inspectedWindow.getResources(r => resolve(r)),
);
const normalizedReferenceURL = normalizeUrlIfValid(url);
const resource = resources.find(r => r.url === normalizedReferenceURL);
if (resource != null) {
const content = await new Promise(resolve =>
resource.getContent(fetchedContent => resolve(fetchedContent)),
);
if (content) {
return content;
}
}
}
return new Promise((resolve, reject) => {
fetchFromNetworkCache(url, resolve, reject);
});
}
export default fetchFileWithCaching;