WebExtensions/Filesystem: Difference between revisions

no edit summary
No edit summary
No edit summary
Line 3: Line 3:
== Overview ==
== 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  
The ability for extensions to interact directly with the filesystem has been one of the more controversial topics with WebExtensions. In the past this ability has been available to legacy extensions through APIs like [https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/OSFile.jsm OS.File and OS.File.DirectoryIterator] and this has allowed those extensions to read and write from the filesystem with no limits.
... 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.
Firefox is adopting a sandboxed, multi-process model to provide a safer and more secure environment for our users. As this model is implemented over the next several months, the access Firefox has - including the content it processes - to a host operating environment will continue to be reduced.  


The main driver of trying to explain this is bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1246236  
Extensions are executed within Firefox, and will have similar access restrictions that are enforced by the sandbox model. Providing extensions with the ability to access the filesystem arbitrarily provides a direct challenge to the integrity of the sandbox, and any potential access outside the content sandbox provided via the WebExtension API needs to be carefully considered.
 
This document was created to clarify [https://bugzilla.mozilla.org/show_bug.cgi?id=1246236 this bug].
 
In current browser products, filesystem access is provided as follows:


=== Chrome ===
=== Chrome ===


Chrome provides the File System Storage API as documented at: https://developer.chrome.com/apps/app_storage  
While Chrome currently provides the Filesystem Storage API as documented at the [https://developer.chrome.com/apps/app_storage Chrome developer site], its use was required explicit user permission and was targeted at Chrome apps primarily. Chrome apps are being being phased out of Chrome proper in favor of [https://developers.google.com/web/progressive-web-apps/ progressive web apps], and the Filesystem Storage API is being removed as part of that process, and no replacement is planned.


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.  
However this API is targeted at Chrome OS and will be removed in Chrome. Currently 1,424 apps out of 37,652 ask for filesystem access. No word has been given of a replacement at this time.  


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.  
Firefox has not been implementing app APIs for extensions, but only implementing extension APIs.


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.
File access is provided through the [https://developer.chrome.com/extensions/extension#method-isAllowedFileSchemeAccess isAllowedFileSchemeAccess API], and allows extensions to read the contents of any file:// locations, as they can other protocols (e.g. http:// and https://), but write access is not provided. Additionally, a user must explicitly permit this behaviour for a given extension through the Chrome preferences pane in chrome://extensions. This API has very low use, with 55 out of approximately 58,000 extensions on the Chrome store using it (as of 03/2017).


=== Firefox ===
=== 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 the [https://developer.mozilla.org/en-US/docs/Web/API/File_and_Directory_Entries_API File and Directory Entries API], which is a non-standard API based off of Chrome’s implementation. Outside creation and modification of a virtual filesystem for a given app, it permits read access to a file when using an <input> element or drag and drop.


==== WebAPI ====
==== Legacy Extensions ====
 
Per above, there are several existing extensions that use OS.File and other APIs to provide direct access to the filesystem. Features that rely on these APIs will no longer function with the shift to WebExtensions exclusively.


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.
==== Opera ====


==== In the past ====
Similar to Chrome, Opera supports the isAllowedFileSchemeAccess API, although its support has not been validated. Minimal testing with an extension that made use of this API caused Opera to crash.


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.
==== Edge ====


==== Just a big button ====
Per [https://docs.microsoft.com/en-us/microsoft-edge/extensions/api-support/supported-apis Microsoft documentation], isAllowedFileSchemeAccess is not supported.


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.
== What to Do? ==


==== Just copy chrome ====
Per above, providing arbitrary filesystem access in WebExtensions is not currently planned. Implementing Filesystem Storage API is also not planned, given the sandboxing concerns outlined and other platforms removing this API in the near future. Any file access should maintain the integrity of Firefox’s sandboxing initiative, and focus on user security and control.


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.
There have been a number of suggestions on how best to approach filesystem access from a general case.


==== Explicit user interaction ====
=== Just add a big button ===


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.
The most popular suggestion for permitting filesystem access is to “just add a big button” that permits users to grant an extension arbitrary filesystem access. This presents a number of challenges, as it is important for users to understand the risk of the permissions they are granting to the extension. An extension with a general permission could read from or write to any content that user has privileges to access, including profile and account information for Firefox and the Operating System. Given the goals of sandboxing, the potential for misuse, and the need to ensure users can make informed decisions and maintain control over what Firefox and its components - including extensions - have access to, this approach is not something that will be considered at this time.


=== Opera ===
=== Just copy Chrome ===


Opera supports isAllowedFileSchemeAccess, although I haven’t confirmed this. I tried this with an extension and Opera crashed.
Effectively, this would entail providing isAllowedFileSchemeAccess only, as the Filesystem API will be removed in early 2018. The isAllowedFileSchemeAccess gives read-only access to any file in the operating environment that a user has permission to access, including system files. Neither the isAllowedFileSchemeAccess nor the Filesystem API being  considered for implemention at this time as a WebExtension API given the security concerns and planned obsolescence, respectively.


=== Edge ===


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


== Use Cases ==
If an extension is going to interact with a specific file and/or directory, that interaction should be performed in a way that is clear and understandable to the user. The focus would be on explicit user actions, like dragging and dropping files, or using a file picker that the user controls exclusively. These are workflows that the user is already familiar with, provides for most of the use cases that have been articulated by developers, and meet the goals of sandboxing and user control. This is the area that WebExtensions API development will focus on.


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.
== Use Cases ==


=== The downloads API ===
=== 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  
It should be noted that Firefox currently implements the [https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/downloads downloads API]. This allows add-ons to write files and data to the filesystem in a consistent manner with an understandable user interface. Files are only written into the users downloads directory. Further on some operating systems files downloaded in this manner trigger OS level notifications.
 
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.
The downloads API is not accessible from the content process, preserving the file system sandboxing requirements.
Line 66: Line 70:
=== Streaming downloads into the downloads directory ===
=== 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:
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 [https://bugzilla.mozilla.org/show_bug.cgi?id=1323414 efficient processing of large downloads] in Firefox.
 
https://bugzilla.mozilla.org/show_bug.cgi?id=1323414  


=== Choosing location in the downloads directory ===
=== 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:
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 [https://bugzilla.mozilla.org/show_bug.cgi?id=1245652 onDeterminingFilename API] that Chrome supports.
 
https://bugzilla.mozilla.org/show_bug.cgi?id=1245652


=== Writing outside the downloads directory ===
=== Writing outside the downloads directory ===
Line 80: Line 80:
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 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.
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. Currently this is not something we plan to implement.
 
https://bugzilla.mozilla.org/show_bug.cgi?id=1331618


=== Blob storage ===
=== 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.
Some extensions just want somewhere to store data in a profile and have it persist between restarts of Firefox. Example extensions are photo editors. For this we have an indexedDB store. That can store a large amount of data with user permission, [https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Browser_storage_limits_and_eviction_criteria although there are limits].


The extension is then able to store, load and manipulate those files efficiently and remain securely inside the WebExtensions and Firefox sandbox.
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.
We’d like to ensure that a large storage is available, with [https://bugzilla.mozilla.org/show_bug.cgi?id=1331618 appropriate prompting] for the user. We’d like to [https://github.com/mdn/webextensions-examples/pull/171 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 ===
=== 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.
Drag and drop and file picker support currently exists for providing read access to files and directories. One known limitation is that drag and drop only works on a content element that can receive a file drop event. It would be nice to enable it across the entire browser. This would require modification of content handlers.
 
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 ==
== Engineering Plan ==
Confirmed users
1,158

edits