Home
Projects
Blog
Toggle Cursor trail
LinkedIn
GitHub
Printables
Email Me
Switch to dark theme

Documenting Firefox Extension OPFS APIs

First Published: 2025-07-10

Last Updated: 2025-07-16

This wasn't supposed to work...

Background

For the Bolt.new hackathon, I worked on Inkproof, a epub editor which stores all project info in the Origin Private File System (OPFS).
I was unable to debug it easily in Zen, so I decided I wanted to port over or make my own extension to debug OPFS.

That is where my things diverge from my original draft of this article.
I was originally stuck and unable to get anything to work, and was frustrated enough to write an article, but I decided to try one more extension API, and... it worked.
So this article is an attempt to salvage the content from my original article and to document what in the OPFS works or doesn't on Firefox Addons.

Extensions 101

Optional context on how Extensions work

Existing Solutions

If you are in an Chromium browser, the best solution to view the contents of a OPFS is an extension:

Extension Structures

OPFS-Viewer is designed quite simply, it just has a Devtools Panel and Script and it uses the chrome.scripting.executeScript api to be able to execute OPFS commands from the Content-Script context without needing a Content-script.

On the other hand OPFS Explorer is a bit more complex: it has three components in three different contexts
  1. A Devtools script to render the interface for the user in the Devtools
  2. A Content script which runs the OPFS commands on the current tab
  3. A Background script which acts a communication bridge between the Content Script and the Devtools Panel

Why these don't work on Firefox

Note: Firefox uses "browser" and not "chrome" as their api keyword, the rest of the article will reflect this

In Firefox, Content-Scripts are locked down to DOM apis and a subset of the full extension apis.
Similarly Devtools are also locked down, although they get access to some devtools apis.

This immediately breaks OPFS-Viewer as its Devtools script loses access to all browser.scripting apis.

You would think that OPFS-Explorer would then be fine, as it does its OPFS calls from the correct context through a bridge.
But it breaks in an entirely different way.

When run from a content-script, most of the OPFS apis work perfectly and without issue, but crucially the exception is the FileSystemDirectoryHandle.values() api which is needed to get the directory structure is broken.
On Firefox, this fetches an empty iterable which triggers an error.

directoryHandle.values() is not iterable (TypeError)

Through this, Firefox appears to have no way for most extensions to access the OPFS directory listings as the other FileSystemDirectoryHandle APIS appear work fine (read, write, delete) and you can even check if a particular file exists through getFileHandle()

My Approach

So if the most important OPFS apis are locked down from being called in extensions, how did I get it to work.

devtools.inspectedWindow.eval() // Referred to as eval() from now on eval()

eval() acts very similarly to tabs.executeScript(), but most importantly it reads the current state of the page, unlike Content-Scripts which are isolated from changes made to the page by page scripts.
This is most likely the reason why eval() is uniquely able to access the OPFS correctly.

However, an issue is that any script run by eval() must return a JSON representable value.
This caused all sorts of headache, as the OPFS api is asynchronous and would return a JSON promise and not JSON, which I could not get eval() to resolve at all.
Ultimately, I was unable to get it to work and my solution was to instead give up on a clean Devtools only script and to architect the extension so that

  1. Devpanel executes OPFS commands via eval()
  2. OPFS Results are written to an element in the DOM
  3. A Content-Script picks up the results and sends it to the background script
  4. The background script forwards the results to the Devpanel

Conclusions

Although I wish I could have gotten the devpanels only architecture working, ultimately the extension does work.
Overall, the native Devtools should really get some native OPFS capabilities, but I don't think that is coming anytime soon.
Here's hoping that day will come sooner than later, but until then, 3rd-party extensions work fine enough.

Edit: My extension can now be downloaded here
This work is licensed under

CC BY 4.0

Creative Commons IconCreative Commons BY Icon
Profile Picture
linkedIn Profile LinkGitHub
JCHU634 Portfolio