|
No, it is possible with extensions. Extensions can inject headers, such as Access-Control-Allow-Origin: *, to unblock cross-origin requests. In the Manifest V3 context, however, that might require patching window.fetch and window.XMLHttpRequest. For example, // content.js
window.fetch = async (...args) => {
const request = args[0] instanceof Request ? args[0].url : args[0]
const config = args[1] || {}
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage({ action: "proxyFetch", request, config }, response => {
if (response.error) {
const err = new Error(response.error.message)
err.name = response.error.name
err.stack = response.error.stack
if (response.error.cause) err.cause = response.error.cause
reject(err)
} else {
const base64Data = response.dataUrl.split(",")[1]
const bytes = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0))
const contentType = response.headers["content-type"] || "application/octet-stream"
const blob = new Blob([bytes], { type: contentType })
const status = response.status
const statusText = response.statusText
const headers = new Headers(response.headers)
const body = status === 204 || status === 205 || status === 304 ? null : blob
resolve(new Response(body, { status, statusText, headers }))
}
})
})
}
// Background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "proxyFetch") {
fetch(message.request, message.config)
.then(async res => {
const headers = Object.fromEntries(res.headers.entries())
const blob = await res.blob()
const reader = new FileReader()
reader.onloadend = () =>
sendResponse({ status: res.status, statusText: res.statusText, headers, dataUrl: reader.result })
reader.readAsDataURL(blob)
})
.catch(err => {
const { name, message, code, stack } = err
sendResponse({ error: { name, message, code, stack } })
})
// Keeps the message channel open for the async fetch
return true
}
})
|