From 40fa9cc9b592decf8a33c6ec4ff69692921d2171 Mon Sep 17 00:00:00 2001 From: Adrian Bonpin Date: Wed, 19 Aug 2026 02:57:20 +0800 Subject: [PATCH] fix(chrome): replace URL.createObjectURL with base64 data URL for downloads (Chrome MV3 service worker has no createObjectURL) --- background.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/background.js b/background.js index 33e2db5..826af83 100644 --- a/background.js +++ b/background.js @@ -10,6 +10,19 @@ function errMsg(err) { return String((err && err.message) || err); } +// Build a download URL from PDF bytes. Chrome MV3 runs the background as a +// service worker, where URL.createObjectURL is NOT available, so we use a +// base64 data URL (works in both Firefox and Chrome). PDFs here are small +// (~150KB), well within data-URL length limits. +function pdfDataUrl(bytes) { + let binary = ''; + const chunk = 0x8000; + for (let i = 0; i < bytes.length; i += chunk) { + binary += String.fromCharCode.apply(null, bytes.subarray(i, i + chunk)); + } + return 'data:application/pdf;base64,' + btoa(binary); +} + browser.runtime.onMessage.addListener((msg, sender, sendResponse) => { if (msg && msg.type === 'generate-pdf') { generatePdf(msg.data) @@ -32,8 +45,9 @@ function formatPeriod(period) { async function generatePdf(data) { const bytes = await ISMIStools.buildStudyLoadPdf(data); - const blob = new Blob([bytes], { type: 'application/pdf' }); - const url = URL.createObjectURL(blob); + // Chrome MV3 background is a service worker (no URL.createObjectURL), so we + // use a base64 data URL that works in both browsers. + const url = pdfDataUrl(bytes); const header = data.header || {}; const year = parseInt(data.year, 10); const period = formatPeriod(data.period || header.semester || ''); @@ -55,12 +69,10 @@ async function generatePdf(data) { const onChanged = (delta) => { if (delta.id === id && delta.state && (delta.state.current === 'complete' || delta.state.current === 'interrupted')) { browser.downloads.onChanged.removeListener(onChanged); - URL.revokeObjectURL(url); } }; browser.downloads.onChanged.addListener(onChanged); } catch (err) { - URL.revokeObjectURL(url); throw err; } }