A cross-browser (Chrome + Firefox) Manifest V3 extension that injects local files into the p2r3 online converter without ever switching tabs or closing the popup.
- Navigate to
chrome://extensions - Enable Developer mode (top-right toggle)
- Click Load unpacked → select the
p2r3-converter-companion-extensionfolder
- Navigate to
about:debugging#/runtime/this-firefox - Click Load Temporary Add-on → select
manifest.jsonfrom the folder (Note: temporary add-ons are removed on browser restart; permanent install requires signing via AMO or an enterprise policy)
User action
│
▼
popup.html / popup.js ← Visible extension popup
│ chrome.runtime.sendMessage
▼
background.js (service worker) ← Message broker; owns offscreen lifecycle
│ ┌──────────────────────────────────────────┐
│ │ Offscreen path (Chrome 109+) │
│ │ background → offscreen.html/offscreen.js │
│ │ offscreen reads File → ArrayBuffer │
│ │ offscreen → background (FILE_SELECTED) │
│ └──────────────────────────────────────────┘
│
│ chrome.scripting.executeScript (on-demand)
▼
content_script.js ← Injected into p2r3.github.io/convert/
│ Uint8Array → File → DataTransfer → input.files
│ dispatchEvent("change", { bubbles: true })
▼
p2r3 converter site ← Conversion get our file automatically
| Method | Popup stays open? | Availability |
|---|---|---|
Offscreen API (chrome.offscreen) |
✅ Always | Chrome 109+, Firefox 128+ |
| Drag & Drop onto popup drop zone | ✅ Always | All browsers |
Hidden <input> click via DnD label |
All browsers |
- Firefox added
chrome.offscreensupport in Firefox 128 (July 2024). - The extension uses
chrome.offscreen !== undefinedto detect support. - Older Firefox versions fall back to Drag & Drop automatically.
- Firefox does not require an
offscreenentry inmanifest.jsonpermissions — the permission is silently ignored on Firefox, which is safe.
- MV3 service workers are supported in Firefox 121+.
- For Firefox < 121, you can add a
"scripts"array under"background"in addition to"service_worker"— Firefox ignoresservice_workerand usesscriptsinstead:"background": { "service_worker": "background.js", "scripts": ["background.js"] }
- All modern versions of Firefox support the
chrome.*alias forbrowser.*in MV3 extensions (the WebExtensions Polyfill is not required). - If you need to support very old Firefox builds, install webextension-polyfill.
- Fully supported in Firefox 101+ with MV3.
- Requires
"scripting"in permissions and the host inhost_permissions.
- The
DataTransfer+input.filesassignment technique works in both Chrome and Firefox. Both browsers respect the programmatic assignment when theFileis added viaDataTransfer.items.add().
| Permission | Why |
|---|---|
activeTab |
Allows sending messages to the currently active tab once the user clicks the extension icon |
scripting |
Required to call chrome.scripting.executeScript to inject content_script.js on demand |
offscreen |
Required in Chrome to create the off-screen document that hosts the file picker |
host_permissions: https://p2r3.github.io/convert/* |
Allows executeScript and tabs.sendMessage to operate on the converter page |
content_script.js sets window.__p2r3ExtInjected = true to prevent
duplicate execution if executeScript is called multiple times.
Files are serialised as Array<number> (plain JSON-serialisable array) for
chrome.runtime.sendMessage. Chrome's structured-clone limit is 64 MB per
message. For larger files, consider chunking or switching to IndexedDB as
a shared data store between the service worker and content script.
All scripts are loaded from external .js files; no eval or inline
<script> blocks are used, satisfying MV3's strict CSP.
Tested on brave, edge, zen browser and opera air.