I wrote previously about some work we're doing on a web file system like node.js' that sits atop modern browser data stores. Yesterday Alan came to my class and we brainstormed a solution for creating safe, shared web file systems. I wanted to write down some of the ideas, for my students, but also for you, dear reader!
The goal is to allow various domains to all access the same file system. Imagine a scenario like this (note: I'm making up all these domains/apps):
git clonesome repo into my web file system, perhaps using a web app at webgit.com
- I want to edit some of the text files in that repo locally using a web app at editor.com
- There's also an image I need to touch up, so I open it with a web app at paint.com and correct the colours.
- When I'm done I want to attach the image in an email I'm writing in a web app at mail.org
So far that's 4 separate domains that need to share the same web file system and set of files. However, our file system, which uses an IndexedDB backend (and soon a WebSQL one for legacy/cross-browser support) is bound by the same origin policy: if you create your file system data store using domain x.com, you can't access it from y.com. If you imagine it like a desktop OS, it's like saying that each app has its own file system, and they can't talk to one another.
There are excellent reasons why this is so. I might be fine with good.webapp.com reading and writing my files, but don't want rouge.webapp.io near them. Just as I don't install random crap from the web, I don't want random web sites interacting with my files.
One way to solve this is to rely on an iframe-based, proxy API using postMessage. Such APIs are becoming more and more popular, for example, the YouTube Player API. Here's how it might work for a shared file system in the browser:
- Register a domain, https://myfiles.io, and use that for our single origin. Users can visit this domain to create a web file system. This is going to be the domain of your shared file system.
- paint.com wants to use this shared file system. It includes the https://myfiles.io/client-api.js script, which does a few things. First, it embeds an iframe in paint.com that hosts https://myfiles.io/embed. This page is setup to receive messages from a parent window with requests to do things on the file system; second, it sets up a proxy API in paint.com that translates file system calls (e.g., readFile, mkdir, ...) into postMessage requests into the embedded iframe. The page at paint.com can now do fs.readFile(...) and it will get proxied into the iframe.
- The page at https://myfiles.io/embed (i.e, the iframe) can make choices about who it listens to, and who it ignores. For example, it might require a user to authenticate before it allows any file system calls to get through, and open some UI from the iframe that the user has to interact with (e.g., Persona). Or it might require an authentication token for the app that's hosting it. There are a host of options. The point is, the page at https://myfiles.io/embed gets to decide what is and isn't allowed to happen on the file system, not a 3rd party web app like paint.com. Such web apps can only request that things happen, or perhaps request permissions/abilities to do certain kinds of things, and the user can be involved in deciding what's allowed by opening a dialog or other UI window from the iframe and giving the user a choice. In a way this lets us create something similar to trusted events in the browser's chrome, but do it all in content.
The nice thing about this is that the degree to which a particular file system gets shared across apps/domains is tied into the file system itself. On Webmaker.org, for example, I might want to enable all sorts of separate apps to use a common file system, but not apps outside those I trust. Someone else might decide they only want a single app to use it. The design allows for multiple file systems, which can optionally be shared by providing an iframe-embed/proxy-api--if you don't want to do this, you don't provide the proxy.
Having a "My Computer" type access point for my file system at https://myfiles.io is also nice because it can serve as a file management UI and allow for things like synchronization, adding files from my local file system, etc. Using WebRTC and data channels, I might connect my phone and laptop, and sync the files in my file system between both devices. I might also provide a drag-and-drop interface to allow users to "upload" files into their web file system. For a user, the idea that I go to a particular web site to manage my files is already well understood. We can provide a solid UI for the file system as well as the proxied api.
Lots to think about, lots more to implement. Over the coming weeks I hope we'll have a demo of what I'm describing above. For now, feel free to get involved or give ideas.