├── .pr-preview.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── PRIVACY_AND_SECURITY.md ├── README.md ├── explainer.md └── w3c.json /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.html", 3 | "type": "respec", 4 | "params": { 5 | "force": 1 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # File Handling 2 | 3 | Contributions to this repository are intended to become part of Recommendation-track documents 4 | governed by the [W3C Patent Policy](http://www.w3.org/Consortium/Patent-Policy-20040205/) and 5 | [Document License](http://www.w3.org/Consortium/Legal/copyright-documents). To contribute, you must 6 | either participate in the relevant W3C Working Group or make a non-member patent licensing 7 | commitment. 8 | 9 | If you are not the sole contributor to a contribution (pull request), please identify all 10 | contributors in the pull request's body or in subsequent comments. 11 | 12 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 13 | 14 | ``` 15 | +@github_username 16 | ``` 17 | 18 | If you added a contributor by mistake, you can remove them in a comment with: 19 | 20 | ``` 21 | -@github_username 22 | ``` 23 | 24 | If you are making a pull request on behalf of someone else but you had no part in designing the 25 | feature, you can remove yourself with the above syntax. 26 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors under the [W3C Document 2 | License](http://www.w3.org/Consortium/Legal/copyright-documents). 3 | -------------------------------------------------------------------------------- /PRIVACY_AND_SECURITY.md: -------------------------------------------------------------------------------- 1 | # Answers to [Security and Privacy Questionnaire](https://www.w3.org/TR/security-privacy-questionnaire/) 2 | 3 | ### 3.1 Does this specification deal with personally-identifiable information? 4 | 5 | Indirectly: it is conceivable that a user could open sensitive information in a web app, perhaps editing their tax return in a web app made for that purpose. 6 | 7 | 8 | ### 3.2 Does this specification deal with high-value data? 9 | 10 | Yes. It will grant read and write access to some of a user's files (if they choose to open them with a PWA). 11 | 12 | 13 | ### 3.3 Does this specification introduce new state for an origin that persists across browsing sessions? 14 | 15 | No. 16 | 17 | 18 | ### 3.4 Does this specification expose persistent, cross-origin state to the web? 19 | 20 | Yes, in the form of the contents of the native file system. Note, however, that the user must have both origins installed as PWAs and must **explicitly** open the same file with both web apps. 21 | 22 | ### 3.5 Does this specification expose any other data to an origin that it doesn’t currently have access to? 23 | 24 | Yes. The origin may be granted access to files on a user's machine. However, this will be building on top of the [native-file-system](https://github.com/WICG/native-file-system/blob/master/EXPLAINER.md) proposal and is more another avenue for getting access, than completely new data. 25 | 26 | Specifically, this will allow native file system access to be granted by choosing to open a file with a web application from the operating system. Previously, native file system access could only be granted by showing a file picker from a web application. 27 | 28 | ### 3.6 Does this specification enable new script execution/loading mechanisms? 29 | 30 | No. 31 | 32 | 33 | ### 3.7 Does this specification allow an origin access to a user’s location? 34 | 35 | No. 36 | 37 | 38 | ### 3.8 Does this specification allow an origin access to sensors on a user’s device? 39 | 40 | No. 41 | 42 | 43 | ### 3.9 Does this specification allow an origin access to aspects of a user’s local computing environment? 44 | 45 | Yes. This is another avenue of being granted access to certain files in the user's local computing environment. The user explicitly grants permission by a) installing the website and b) choosing to open a file with the installed website. 46 | 47 | 48 | ### 3.10 Does this specification allow an origin access to other devices? 49 | 50 | No. 51 | 52 | 53 | ### 3.11 Does this specification allow an origin some measure of control over a user agent’s native UI? 54 | 55 | No, however it does allow an installed app some measure of control over operating system native UI. 56 | 57 | 58 | ### 3.12 Does this specification expose temporary identifiers to the web? 59 | 60 | No. 61 | 62 | 63 | ### 3.13 Does this specification distinguish between behavior in first-party and third-party contexts? 64 | 65 | Third party contexts will not be able to see files that the first party was launched with. 66 | 67 | 68 | ### 3.14 How should this specification work in the context of a user agent’s "incognito" mode? 69 | 70 | Sites may not be registered as a file handler unless they are installed, which is not possible in incognito mode. Thus, they will never receive access to any files via this API and cannot expect to (as they are not installed). 71 | 72 | 73 | ### 3.15 Does this specification persist data to a user’s local device? 74 | 75 | Not directly, but once a site has been granted write access to a file it may persist data. The duration of access to files is controlled by the [File System Access API](https://github.com/WICG/native-file-system/blob/master/EXPLAINER.md). 76 | 77 | 78 | ### 3.16 Does this specification have a "Security Considerations" and "Privacy Considerations" section? 79 | 80 | Yes. See the [explainer](explainer.md#security-and-privacy-considerations). 81 | 82 | 83 | ### 3.17 Does this specification allow downgrading default security characteristics? 84 | 85 | Yes, in that it provides another way for user's to expose files on their native file system to the web. 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # File Handling 2 | 3 | **Date**: 2018-09-25 4 | 5 | This is the repository for a proposed capability for web applications to support File Handling. 6 | 7 | Please see the [Explainer document](explainer.md), a high-level overview of the proposal. 8 | 9 | You're welcome to [contribute](CONTRIBUTING.md)! 10 | -------------------------------------------------------------------------------- /explainer.md: -------------------------------------------------------------------------------- 1 | # Explainer 2 | 3 | Authors: 4 | * Current: 5 | * Evan Stade <> 6 | * Former: 7 | * Darwin Huang <> 8 | * Eric Willigers <>
9 | * Jay Harris <>
10 | * Raymes Khoury <> 11 | 12 | ## Motivation 13 | 14 | This proposal gives installed web applications a way to register their ability to handle (read, stream, edit) files with given MIME types and/or file extensions. This then allows an operating system's file manager or other operating system flows to use a PWA to handle opening the file, similar to how it would open the file using a native app. 15 | 16 | This has many use cases. For example: 17 | * A document editor could display and edit a number of document formats, like `.txt`, `.md`, `.csv`, and `.docx`. 18 | * A movie player could play a video format. 19 | * A Javascript development environment could interactively step through Javascript programs. 20 | * A data visualizer could generate graphs from `.csv` files. 21 | * A creative tool could generate files in a proprietary format and become the default handler for such files (opening when a user double clicks on `.foo` in the system file browser). 22 | 23 | There has historically been no standards-track API for MIME type handling. For some years, [Chrome packaged apps](https://developer.chrome.com/docs/extensions/apps/) have been able to register one or more file handlers using a [Chrome-specific API](https://developer.chrome.com/apps/manifest/file_handlers) where each handler may handle specific MIME types and/or file extensions. As of August 2018, 619 file handlers handled MIME types, while 509 file handlers handled file extensions. Some packaged apps had more than one file handler. Overall, 580 packaged apps handled MIME types and 337 packaged apps handled file extensions. This usage, and the use cases above, demonstrates the value of being able to associate web applications with MIME types and/or file extensions. 24 | 25 | This will be implemented by a new `"file_handlers"` manifest entry, which specifies file handlers to register onto the target system, as well as a new `window.launchQueue` method, that enables the opened page to handle files queued by the underlying operating system. 26 | 27 | ## Example Manifest 28 | 29 | The following web application declares in its manifest that it can handle CSV and SVG files, as well as a hypothetical file format that this application uses called GRAF. 30 | 31 | ```json 32 | { 33 | "name": "Grafr", 34 | "file_handlers": [ 35 | { 36 | "action": "/open-csv", 37 | "name": "Comma-separated Value", 38 | "accept": { 39 | "text/csv": [ ".csv" ] 40 | }, 41 | "icons": [ 42 | { 43 | "src": "/csv-file.png", 44 | "sizes": "144x144" 45 | } 46 | ] 47 | }, 48 | { 49 | "action": "/open-svg", 50 | "name": "Image", 51 | "accept": { 52 | "image/svg+xml": ".svg" 53 | }, 54 | "icons": [ 55 | { 56 | "src": "/svg-file.png", 57 | "sizes": "144x144" 58 | } 59 | ] 60 | }, 61 | { 62 | "action": "/open-graf", 63 | "name": "Grafr", 64 | "accept": { 65 | "application/vnd.grafr.graph": [ 66 | ".grafr", ".graf" 67 | ], 68 | "application/vnd.alternative-graph-app.graph": ".graph" 69 | }, 70 | "launch_type": "multiple-clients" 71 | } 72 | ] 73 | } 74 | ``` 75 | ## Manifest 76 | 77 | The new manifest API surface is contained in the `file_handlers` list, where each entry in this list is a dictionary describing the file handler, with fields like `action`, `name`, `accept`, and `icons`. 78 | 79 | `action` must be inside the app scope, and specifies the URL after the origin that is the navigation destination for file handling launches (analogous to `start_url` for typical app launches). `launch_type` defines whether multiple files should be opened in a single client or multiple. If omitted, this defaults to `single-client`. See also `launchParams.files`. 80 | 81 | Each `accept` entry is a dictionary mapping MIME types to extensions. Depending on context, both MIME type and file extension may be important. For example, `xdg-utils` on Linux [associates files to apps via MIME types](https://stackoverflow.com/a/31836/3260044), and thus (a) will match files to apps based on MIME type, and (b) requires all file extensions to map to a known MIME type (custom file formats like the `.grafr` example need a MIME type). Other systems map directly from file extension to app. For consistency across platforms, the user agent will enforce that the app can only open files with specified extensions. App authors should expect that both the MIME type *and* file extension must match for a file to be openable by an app. 82 | 83 | `name` and `icons` are a string and [`ImageResource`](https://www.w3.org/TR/image-resource/) array, respectively, which describe the file type. These *may* be used to describe the files in file browsers and other contexts, depending on the operating system and other factors such as whether the PWA is the default handler for the file type. 84 | 85 | ## Launch 86 | 87 | Choosing to open the file would create a new top level browsing context, navigating to the `action` URL (resolved against the manifest URL). Assuming the user opened `graph.csv` in Grafr the URL would be `https://grafr.com/open-csv/`. 88 | 89 | To access launched files, a site should specify a consumer for a `launchQueue` object attached to `window`. See: [`launch_handler`](https://github.com/WICG/sw-launch/blob/main/launch_handler.md). The application will have read/write access through the [File System Access](https://github.com/WICG/file-system-access/blob/master/EXPLAINER.md) API. 90 | 91 | Below is a basic example of using `launchQueue` and `launchParams` to receive the file handles. 92 | ```js 93 | // In grafr.com/open-csv 94 | if ('launchQueue' in window) { 95 | launchQueue.setConsumer(launchParams => { 96 | if (!launchParams.files.length) 97 | return; 98 | 99 | const fileHandle = launchParams.files[0]; 100 | // Handle the file: 101 | // https://github.com/WICG/file-system-access/blob/master/EXPLAINER.md#example-code 102 | }); 103 | } 104 | ``` 105 | 106 | Note that if the user opens multiple files, and the file handler has been notated with `multiple-clients` as its `launch_type`, more than one app launch will occur, and for each launch, the files array will have just one element. This can be useful, for example, if an editing app wishes to make use of the browser's tabbing via `"display_mode": "browser"` rather than building its own way of simultaneously displaying or opening multiple documents. On the other hand, a zip archiving app would likely prefer the files all be passed to a single client, so would not set `launch_type`. It is not possible to coalesce multiple files that match different `file_handler` entries into a single launch. 107 | 108 | # Security and Privacy Considerations 109 | 110 | There is a large category of attack vectors that are opened up by allowing websites access to files. These are dealt with in the [file-system-access](https://github.com/WICG/file-system-access/blob/main/EXPLAINER.md#proposed-security-models) explainer. 111 | 112 | The additional security-pertinent capability that this specification provides over the file-system-access API is the ability to grant access to certain files through the operating system UI, as opposed to through a file picker shown by a web application. Any restrictions as to the files and folders that can be opened via the picker may also be applied to the files and folders opened via the operating system. 113 | 114 | As with native apps, an app's ability to handle a specified file type will be registered with the OS at install time. However, as an additional protection to safeguard against accidental sharing of sensitive information contained in local files, the user agent may initially verify that the action is intentional. As a run-time confirmation, this step follows a flow similar to most web Permissions. The verification prompt should appear before the PWA is launched and the launch should be aborted if the user denies the action. User agents may retain control over default settings and how (or if) they are exposed to the user. 115 | 116 | See the [File Handling Security Model](https://docs.google.com/document/d/1pTTO5MTSlxuqxpWL3pFblKB8y8SR0jPao8uAjJSUTp4) for more discussion of the threat model. Additional details are also available in the [Security and Privacy Questionnaire](https://github.com/WICG/file-handling/blob/main/PRIVACY_AND_SECURITY.md). 117 | 118 | # Addendum 119 | 120 | ## Differences to Similar APIs on the Web 121 | 122 | The proposed method of getting launched files differs from some similar web APIs: 123 | 124 | * Web Share Target: All relevant data is contained in the POST request to the page. 125 | * registerProtocolHandler: Relevant data is contained in the query string the page navigates to. 126 | 127 | In contrast, when we perform a navigation to the file-handling URL, the files are not available as part of a request. Since many apps that make use of the File Handling API will also make use of the [File System Access API](https://github.com/WICG/file-system-access/blob/main/EXPLAINER.md), reusing the `FileSystemFileHandle` part of that API should enable greater code reuse. 128 | 129 | We briefly considered encoding the `FileSystemFileHandles` in the query string in a blob-like format (e.g. `file-handle://`). However, this presents some problems: 130 | * The page would have to parse file handles from the URL itself, adding boilerplate. 131 | * Lifetimes for blob-like URLs are complicated, as we can't predict when/where the handle will be used. 132 | 133 | In addition, were we designing the existing APIs again today, there is a good chance we might take this approach for them too. 134 | 135 | ## Previous Solutions 136 | There are a few similar, non-standard APIs, which it may be useful to compare this with. 137 | 138 | ### [registerContentHandler](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/registerContentHandler) 139 | 140 | Register content handler was [deprecated](https://blog.chromium.org/2016/08/from-chrome-apps-to-web.html) due to the lack of two interoperable implementations and the implementation that was available [did not conform to that standard](https://github.com/whatwg/html/commit/b143dbc2d16f3473fcadee377d838070718549d3). This API was only available in Firefox. 141 | 142 | Example usage, as per MDN 143 | ```js 144 | navigator.registerContentHandler( 145 | "application/vnd.mozilla.maybe.feed", 146 | "http://www.example.tld/?foo=%s", 147 | "My Feed Reader" 148 | ); 149 | ``` 150 | 151 | Presumably this API provided readonly access to the file. 152 | 153 | #### Why not resurrect this now more vendors are interested? 154 | `registerContentHandler` was not designed to handle files being opened, rather it was designed to handle link clicks that resolve to certain mime types (see [Example 17](https://www.w3.org/TR/html52/webappapis.html#custom-scheme-and-content-handlers-the-registerprotocolhandler-and-registercontenthandler-methods) from the spec). 155 | 156 | For Example: 157 | 1. It requires file handles to be encodable as a string (this will not be possible with the [file-system-access](https://github.com/WICG/file-system-access/blob/main/EXPLAINER.md) API, which is required to write to files). 158 | 2. It can only register handlers for content types. This is a problem because some operating systems only support file extensions and we don't want to spec and maintain a mapping. See this [issue](https://github.com/WICG/web-share-target/issues/74) for more context. 159 | 160 | ### [Chrome Apps File Handlers](https://developer.chrome.com/apps/manifest/file_handlers) 161 | 162 | Chrome Apps are in the process of being [deprecated](https://arstechnica.com/gadgets/2017/12/google-shuts-down-the-apps-section-of-the-chrome-web-store/) in favour of PWAs. The API was never intended to be a web standard. This API is only available in Chrom(e|ium), and is only available to apps published in the Chrome App Store. 163 | 164 | Example manifest.json 165 | ```json 166 | { 167 | ... 168 | "file_handlers": { 169 | "graph": { 170 | "extensions": [ "svg" ], 171 | "include_directories": false, 172 | "types": [ "image/svg+xml" ], 173 | "verb": "open_with" 174 | }, 175 | "raw": { 176 | "extensions": [ "csv" ], 177 | "include_directories": false, 178 | "types": [ "text/csv" ], 179 | "verb": "open_with" 180 | } 181 | } 182 | } 183 | ``` 184 | 185 | This would cause a `chrome.app.runtime.onLaunched` event to be fired. This event could be handled in the background process or in a client. 186 | 187 | Example Handler 188 | ```js 189 | function(launchData) { 190 | if (launchData.source !== 'file_handler') return; 191 | 192 | // File handling integration here. 193 | // launchData.items[0] is the first file. 194 | } 195 | ``` 196 | 197 | ### [WinJS File Handlers](https://msdn.microsoft.com/en-us/windows/desktop/hh452684) 198 | 199 | The WinJS API is similar to that of Chrome Apps, except that the registration was done in XAML and the name of the event is different. The API is intended to provide file handling integration to UWP Web Apps, available through the Microsoft store. This API is only available in Edge, isn't accessible from the general web. 200 | 201 | Example Registration 202 | ```xml 203 | 204 | 205 | 206 | 207 | 208 | 209 | SDK Sample File Type 210 | images\logo.png 211 | SDK Sample tip 212 | 213 | 214 | .alsdk 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | ``` 223 | 224 | Example Handler 225 | ```js 226 | function onActivatedHandler(eventArgs) { 227 | if (eventArgs.detail.kind !== Windows.ApplicationModel.Activation.ActivationKind.file) 228 | return; 229 | // Handle file activation here. 230 | 231 | // The number of files received is eventArgs.detail.files.size 232 | // The first file is eventArgs.detail.files[0] 233 | } 234 | ``` 235 | 236 | ## References: 237 | * [Ballista (earlier, related proposal) explainer](https://github.com/chromium/ballista/blob/master/docs/explainer.md). 238 | * Chrome Design Documents: 239 | * [File Handling design document](https://docs.google.com/document/d/1SpLwK0sQ3CUuuG-T9pFBqlm1Ae-OGwi4MsP5X2bCBow/) 240 | * [File Handling Icons design document](https://docs.google.com/document/d/1OAkCvMwTVAf5KuHHDgAeCA3YwcTg_XmujZ7ENYq01ws). 241 | * [File Handling Security Model](https://docs.google.com/document/d/1pTTO5MTSlxuqxpWL3pFblKB8y8SR0jPao8uAjJSUTp4). 242 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": [80485] 3 | , "contacts": ["marcoscaceres"] 4 | , "repo-type": "cg-report" 5 | } 6 | --------------------------------------------------------------------------------