Files
pdfjs_with_vimiumc/background.js
2025-10-03 23:32:36 +08:00

83 lines
2.6 KiB
JavaScript

// background.js
const blobs = new Set();
function isExtensionUrl(url) {
return url.startsWith(browser.runtime.getURL(''));
}
function viewerUrlFor(originalUrl) {
return browser.runtime.getURL('viewer.html') + '?src=' + encodeURIComponent(originalUrl);
}
// Redirect obvious .pdf URLs (but skip extension pages)
browser.webRequest.onBeforeRequest.addListener(
details => {
const url = details.url;
if (isExtensionUrl(url)) return {};
const path = url.split('?')[0].toLowerCase();
if (path.endsWith('.pdf')) {
return { redirectUrl: viewerUrlFor(details.url) };
}
return {};
},
{ urls: ["<all_urls>"], types: ["main_frame"] },
["blocking"]
);
// Redirect when response headers indicate PDF
browser.webRequest.onHeadersReceived.addListener(
details => {
const url = details.url;
if (isExtensionUrl(url)) return {};
const headers = details.responseHeaders || [];
for (let h of headers) {
if (!h.name || !h.value) continue;
const n = h.name.toLowerCase();
const v = h.value.toLowerCase();
if (n === "content-type" && v.includes("application/pdf")) {
return { redirectUrl: viewerUrlFor(details.url) };
}
// some servers force download with content-disposition
if (n === "content-disposition" && v.includes("attachment") && v.includes(".pdf")) {
return { redirectUrl: viewerUrlFor(details.url) };
}
}
return {};
},
{ urls: ["<all_urls>"], types: ["main_frame"] },
["blocking", "responseHeaders"]
);
// Message API: fetch PDF and return a blob: URL (no large binary through messaging)
browser.runtime.onMessage.addListener(async (msg) => {
if (!msg || !msg.type) return;
if (msg.type === "fetch-pdf" && msg.url) {
try {
// Ensure you have host permission for the target (manifest had "<all_urls>")
const res = await fetch(msg.url, { credentials: "include" });
if (!res.ok) {
return { error: `HTTP ${res.status} ${res.statusText}` };
}
const arrayBuffer = await res.arrayBuffer();
const contentType = res.headers.get("content-type") || "application/pdf";
const blob = new Blob([arrayBuffer], { type: contentType });
const blobUrl = URL.createObjectURL(blob);
blobs.add(blobUrl);
return { blobUrl, contentType };
} catch (err) {
return { error: String(err) };
}
}
// allow viewer to tell us to free the blob URL when it's done
if (msg.type === "revoke-blob" && msg.blobUrl) {
if (blobs.has(msg.blobUrl)) {
blobs.delete(msg.blobUrl);
try { URL.revokeObjectURL(msg.blobUrl); } catch(e) {}
return { revoked: true };
}
return { revoked: false };
}
});