WebExtensions/Filesystem

From MozillaWiki
Jump to navigation Jump to search

Status: THIS IS A DRAFT, more to come.

Overview

The ability to read and write from the file system has been one of the more controversial topics with WebExtensions. In the past this has been available to legacy extensions through APIs like OS.File and OS.File.DirectoryIterator: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/OSFile.jsm ... and this has allowed extensions to read and write from the file system with no limits.

The goal behind WebExtensions is to provide a safe, secure, sandboxed environment for our users and as such file system access provides a direct challenge to the sandbox. As such we should examine any APIs around file system access carefully.

The main driver of trying to explain this is bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1246236

Chrome

Chrome provides the File System Storage API as documented at: https://developer.chrome.com/apps/app_storage

However this API is targeted at Chrome OS and will be removed in Chrome. Currently 1,424 apps out of 37,652 ask for file system access. No word has been given of a replacement at this time. Firefox has not been implementing app APIs for extensions, but only implementing extension APIs.

There is the isAllowedFileSchemeAccess which is documented at: https://developer.chrome.com/extensions/extension#method-isAllowedFileSchemeAccess this allows you to access the contents of file:// locations, as you can other protocols (http and https). It’s effectively read access to the file system.

To enable it a user has to go to chrome://extensions and give the add-on that permission. Currently 55 out of approx. 58,000 extensions on the chrome store use that API.

Firefox

Just copying Chrome or providing the same access in the past to extensions is a general cause of concern to most the add-ons engineering team.

WebAPI

Currently there is https://developer.mozilla.org/en-US/docs/Web/API/File_and_Directory_Entries_API which is a non-standard API. It only allows read access to a file when using an <input> element or drag and drop.

In the past

There are many extensions that use OS.File and other APIs. This doesn’t mean they automatically should continue to do so in the future. Along with the file system sandboxing initiative being carried out by Firefox, we’d like to focus on user security and privacy first.

Just a big button

The main suggestion seems to be “just add a big button” to let users choose that they can give file system access. The problem is that we have to ensure users understand the risk of what they are giving to the extension. An extension that can read from your file system can at the read through your profile and access all data such as cookies, passwords and history you've been able to break out the sandbox. And that's just what you can gleam from Firefox files.

Just copy chrome

We’ve done pretty well on Chrome parity but refuse to do something just because Chrome has, especially if we feel that feature has a major security or privacy risk. This is one of those.

Explicit user interaction

We believe that if an extension is going to interact with a file then it should be done in a clear and understandable way for the user. For that we focus on explicit user actions, like drag and drop or file picker. UX flows that the user is already familiar with.

Opera

Opera supports isAllowedFileSchemeAccess, although I haven’t confirmed this. I tried this with an extension and Opera crashed.

Edge

Not supported according to the docs: https://docs.microsoft.com/en-us/microsoft-edge/extensions/api-support/supported-apis

Use Cases

We’ve tried to focus on some use cases that extension authors have presented to us. Sadly they don’t meet every need, but should solve some common use cases.

The downloads API

It should be noted that Firefox currently implements the downloads API: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/downloads

This allows add-ons to write files and data to the file system in a consistent manner with an understandable user interface. Files are only written into the users downloads directory.

The downloads API is not accessible from the content process, preserving the file system sandboxing requirements.

Streaming downloads into the downloads directory

If you have an extension which assists in downloading large files, using the download API can be cumbersome as you might have to read the file into memory before processing it further. By implementing a streaming API for Firefox, we hope to allow efficient processing of large downloads in Firefox:

https://bugzilla.mozilla.org/show_bug.cgi?id=1323414

Choosing location in the downloads directory

Currently an extension cannot choose to download a file into a particular location for file name based on rules from the extension. For this, Firefox will need to implement the onDeterminingFilename API that Chrome supports:

https://bugzilla.mozilla.org/show_bug.cgi?id=1245652

Writing outside the downloads directory

The downloads API is limited to just the downloads directory. If the downloads could write outside the directory, then you’ve effectively got write access anywhere that the process can write too.

The problem here is giving a prompt that is understandable to the user. There is quite a difference from the user picking a directory and the extension presenting a directory to the user.

https://bugzilla.mozilla.org/show_bug.cgi?id=1331618

Blob storage

Some extensions just want somewhere to store data in a profile and have persist between restarts of Firefox. Example extensions are photo editors. For this we have an indexedDB store than take files of up to 20 gb, with user permission.

The extension is then able to store, load and manipulate those files efficiently and remain securely inside the WebExtensions and Firefox sandbox.

We’d like to ensure that a large storage is available, with appropriate prompting for the user. We’d like to provide a library that makes using this storage easy from an extension.

https://bugzilla.mozilla.org/show_bug.cgi?id=1331618 https://github.com/mdn/webextensions-examples/pull/171

Drag and drop, file picker support

These should be critical parts of our WebExtension infrastructure as they ensure the easiest way to provide read access to files. Currently we are prototyping and check this to see if there’s anything else we should do.

The use case here is similar to dropping a PDF on Firefox, which opens a pdf tab using the builtin reader. Similar use cases would be doing the same with ePub files. Proper support for this use case would require some modification of content handlers, or the hack work around used by pdfjs (a fake plugin).

One could also drop a directory into a sidebar as a way to gain access to a list of files (ie. project directory) for something like a local wiki page editor, though write access would be an issue for that use case.

From a file picker and drag and drop you can get access to files and their contents. You can get access to directories if you set a pref dom.input.filePicker and using webkitdirectory=true as per https://bugzilla.mozilla.org/show_bug.cgi?id=1164310

Engineering Plan

Firefox 57

These are the things we plan on doing by Firefox 57:

  • Streaming downloads
  • A library based on indexedDB for blob storage and the appropriate support.
  • Providing documentation on:
    • What choices are available and why
    • How to handle drag and drop in an extension
    • How to use file picker support
    • How to use the indexedDB blob storage library
    • How to use nativeMessaging with downloads API to do processing

Not planned

These might be possible, but are too large to reasonably commit too and have too many unanswered security and usability questions:

  • Writing outside the downloads directory
  • Access to file:// URLs or reading files without any explicit user input