Let installed web applications be file handlers
Register an app as a file handler with the operating system.
Now that web apps are capable of reading and writing files, the next logical step is to let developers declare these very web apps as file handlers for the files their apps can create and process. The File Handling API allows you to do exactly this. After registering a text editor app as a file handler and after installing it, you can right-click a .txt
file on macOS and select "Get Info" to then instruct the OS that it should always open .txt
files with this app as default.
Suggested use cases for the File Handling API
Examples of sites that may use this API include:
- Office applications such as text editors, spreadsheet apps, and slideshow creators.
- Graphics editors and drawing tools.
- Video game level editor tools.
How to use the File Handling API
Progressive enhancement
The File Handling API per se cannot be polyfilled. The functionality of opening files with a web app, however, can be achieved through two other means:
- The Web Share Target API lets developers specify their app as a share target so files can be opened from the operating system's share sheet.
- The File System Access API can be integrated with file drag and drop, so developers can handle dropped files in the already opened app.
Browser support
- chrome 102, Supported 102
- firefox, Not supported ×
- edge 102, Supported 102
- safari, Not supported ×
Feature detection
To check if the File Handling API is supported, use:
if ('launchQueue' in window && 'files' in LaunchParams.prototype) {
// The File Handling API is supported.
}
File Handling is currently limited to desktop operating systems.
The declarative part of the File Handling API
As a first step, web apps need to declaratively describe in their web app manifest what kind of files they can handle. The File Handling API extends web app manifest with a new property called "file_handlers"
that accepts an array of, well, file handlers. A file handler is an object with these properties:
- An
"action"
property that points to a URL within the scope of the app as its value. - An
"accept"
property with an object of MIME-types as keys and lists of file extensions as their values. - An
"icons"
property with an array ofImageResource
icons. Some operating systems allow a file type association to display an icon that is not just the associated application icon, but rather a special icon related to the use of that file type with the application. - A
"launch_type"
property that defines whether multiple files should be opened in a single client or in multiple clients. The default is"single-client"
. If the user opens multiple files and if the file handler has been annotated with"multiple-clients"
as its"launch_type"
, more than one app launch will occur, and for each launch, theLaunchParams.files
array (see further down) will have just one element.
The example below, showing only the relevant excerpt of the web app manifest, should make it clearer:
{
"file_handlers": [
{
"action": "/open-csv",
"accept": {
"text/csv": [".csv"]
},
"icons": [
{
"src": "csv-icon.png",
"sizes": "256x256",
"type": "image/png"
}
],
"launch_type": "single-client"
},
{
"action": "/open-svg",
"accept": {
"image/svg+xml": ".svg"
},
"icons": [
{
"src": "svg-icon.png",
"sizes": "256x256",
"type": "image/png"
}
],
"launch_type": "single-client"
},
{
"action": "/open-graf",
"accept": {
"application/vnd.grafr.graph": [".grafr", ".graf"],
"application/vnd.alternative-graph-app.graph": ".graph"
},
"icons": [
{
"src": "graf-icon.png",
"sizes": "256x256",
"type": "image/png"
}
],
"launch_type": "multiple-clients"
}
]
}
This is for a hypothetical application that handles comma-separated value (.csv
) files at /open-csv
, scalable vector graphics (.svg
) files at /open-svg
, and a made-up Grafr file format with any of .grafr
, .graf
, or .graph
as the extension at /open-graf
. The first two will open in a single client, the last one in multiple clients if multiple files are being handled.
For this declaration to have any effect, the application must be installed. You can learn more in an article series on this very site on making your app installable.
The imperative part of the File Handling API
Now that the app has declared what files it can handle at which in-scope URL in theory, it needs to imperatively do something with incoming files in practice. This is where the launchQueue
comes into play. To access launched files, a site needs to specify a consumer for the window.launchQueue
object. Launches are queued until they are handled by the specified consumer, which is invoked exactly once for each launch. In this manner, every launch is handled, regardless of when the consumer was specified.
if ('launchQueue' in window && 'files' in LaunchParams.prototype) {
launchQueue.setConsumer((launchParams) => {
// Nothing to do when the queue is empty.
if (!launchParams.files.length) {
return;
}
for (const fileHandle of launchParams.files) {
// Handle the file.
}
});
}
DevTools support
There is no DevTools support at the time of this writing, but I have filed a feature request for support to be added.
Demo
I have added file handling support to Excalidraw, a cartoon-style drawing app. To test it, you first need to install Excalidraw. When you then create a file with it and store it somewhere on your file system, you can open the file via a double click, or a right click and then select "Excalidraw" in the context menu. You can check out the implementation in the source code.
Security
The Chrome team has designed and implemented the File Handling API using the core principles defined in Controlling Access to Powerful Web Platform Features, including user control, transparency, and ergonomics.
Permissions, permissions persistence, and file handler updates
To ensure user trust and the safety of users' files, when the File Handling API opens a file, a permission prompt will be shown before a PWA can view a file. This permission prompt will be shown right after the user selects the PWA to open a file, so that the permission is tightly coupled to the action of opening a file using the PWA, making it more understandable and relevant.
This permission will show every time until the user clicks to Allow or Block file handling for the site, or ignores the prompt three times (after which Chromium will embargo and block this permission). The selected setting will persist across the PWA closing and reopening.
When the manifest updates and changes in the "file_handlers"
section are detected, the permissions will be reset.
File-related challenges
There is a large category of attack vectors that are opened by allowing websites access to files. These are outlined in the article on the File System Access API. The additional security-pertinent capability that the File Handling API provides over the File System Access API is the ability to grant access to certain files through the operating system's built-in UI, as opposed to through a file picker shown by a web application.
There is still a risk that users may unintentionally grant a web application access to a file by opening it. However, it is generally understood that opening a file allows the application it is opened with to read and/or manipulate that file. Therefore, a user's explicit choice to open a file in an installed application, such as via an "Open with…" context menu, can be read as a sufficient signal of trust in the application.
Default handler challenges
The exception to this is when there are no applications on the host system for a given file type. In this case, some host operating systems may automatically promote the newly registered handler to the default handler for that file type silently and without any intervention by the user. This would mean if the user double clicks a file of that type, it would automatically open in the registered web app. On such host operating systems, when the user agent determines that there is no existing default handler for the file type, an explicit permission prompt might be necessary to avoid accidentally sending the contents of a file to a web application without the user's consent.
User control
The spec states that browsers should not register every site that can handle files as a file handler. Instead, file handling registration should be gated behind installation and never happen without explicit user confirmation, especially if a site is to become the default handler. Rather than hijacking existing extensions like .json
that the user probably already has a default handler registered for, sites should consider crafting their own extensions.
Transparency
All operating systems allow users to change the present file associations. This is outside the scope of the browser.
Feedback
The Chrome team wants to hear about your experiences with the File Handling API.
Tell us about the API design
Is there something about the API that doesn't work like you expected? Or are there missing methods or properties that you need to implement your idea? Have a question or comment on the security model?
- File a spec issue on the corresponding GitHub repo, or add your thoughts to an existing issue.
Report a problem with the implementation
Did you find a bug with Chrome's implementation? Or is the implementation different from the spec?
- File a bug at new.crbug.com. Be sure to include as much detail as you can, simple instructions for reproducing, and enter
UI>Browser>WebAppInstalls>FileHandling
in the Components box. Glitch works great for sharing quick and easy repros.
Show support for the API
Are you planning to use the File Handling API? Your public support helps the Chrome team to prioritize features and shows other browser vendors how critical it is to support them.
- Share how you plan to use it on the WICG Discourse thread.
- Send a tweet to @ChromiumDev using the hashtag
#FileHandling
and let us know where and how you are using it.
Helpful links
- Public explainer
- File Handling API demo | File Handling API demo source
- Chromium tracking bug
- ChromeStatus.com entry
- Blink Component:
UI>Browser>WebAppInstalls>FileHandling
- TAG Review
- Mozilla Standards Position
Acknowledgements
The File Handling API was specified by Eric Willigers, Jay Harris, and Raymes Khoury. This article was reviewed by Joe Medley.