Simple API proposal for writing file in local file system

Hello!

As a Web developer, I recently dig into the proposed FileSystem API [1]
which cover many use cases except one: How a user can actually allows a web
application to really write something in the user local file system (even
if it's slow). On the other hand, the File API: Writer [2] cover that need
but with a very overwelming interface which make very hard to use for
simple open/save operation.

There are well known workaround but we could make the life of web developer
easier by providing a simple convenient and secure interface to do this.


*# Accessing a file.*

Currently, as per the File API [3], the only way to access a file in the
user file system is by using the <input type="file"> element. For some
reason, web developer don't want to expose such input to the user
(basically, because it's impossible to change its look and feel
consistently across browsers). To work around this, they hide it and
perform a fake click on it to prompt the user to pick some files.

We could provide a method that allow to do the same. In terms of security,
it would also make easier to track malicious attempt to acces the file
system as we will be able to monitor all access through that single method.

partial interface Navigator {
  Promise openFile();
}

In case of success, the Promise will get a FileList object as the user can
pick more than one file.


*# Writing a file*

Currently, the only way to write a file on the user file system is to turn
a File object into a data URI with the MIME type application/octet-stream
in order to force a download of the file. This allows the user to save the
file wherever he wants on his device.

This is very rough and have two drawbacks:

   1. if the user has setup his browser to always put downloaded file in a
   given repository, it could require some extra action from the user to move
   the file in his file system. This lead to a bad user experience that many
   web developers wish to avoid.
   2. if the user has previously open the file that need to be put back in
   his file system, it's impossible to perform a silent writing. The user is
   always prompt to perform the overriding itself. Once again, it's a bad user
   experience that web developers wish to avoid.

To solve those two issues, we could provide a save method that will allow
to bypass any download setup and to provide a secure way of making silent
writing.

Note: It is worth noticing that Microsoft did something similare for IE11
with the msSaveBlob [4] and msSaveOrOpenBlob [5] methods

partial interface Navigator {
  Promise saveFile(File file, optional boolean silent);
}

Note: it would be possible to add some events to keep track of the writing
operation, but Promise are good enough as we just want to save files in the
local file system rather than making some intensive IO operation. If a web
developer want to do that it would be better for him to relay on the
FileSystem API.

Making secured silent writing require two things:

1. Only file picked by the user and explicitely chose as writable by him
can be silently writen. The LockedFile object in the FileSystem API draft
is close to that but looks unnecessary complicated. I suggest to make
something simple by extending the File interface.

partial interface File {
  readonly attribute DOMString? mode; // It can be 'readonly' or 'writable'
  readonly attribute boolean? lock; // If true, only that tab can modify
the file
}

In order to sustain this, the 'mode' and 'lock' must be set when calling
the openFile method:

partial interface Navigator {
  Promise openFile(optional DOMString mode, optional boolean lock);
}

   - The 'mode' indicate if the File is 'readonly' or 'writable'. The
   browser must retain the information of the location in the file system for
   all writable files object, but this information will never be exposed to
   web content.
   - The 'lock' indicate if the browser must put a lock on the file,
   allowing only the tab which access it first to write back into the file
   (It's an internal lock maintain by the browser, it is never put at the file
   system level, I'm not sure but I think there are to many side effects to
   allow such a hard lock). If another tab has already put a lock on the file,
   the Promise will fail with an appropriate error message. The lock is
   released when the File object is destroyed (it is garbage collected, the
   tab using it is shutdown, etc.). Note: it could be convenient to have a
   setLock method to change the lock state.

If a File object is created without using the openFile method, the mode and
lock will be null;

The saving steps should be the following:

   1. If a File object is saved using the saveFile method:
      1. If the object has its mode set to 'readonly' or null
         1. The user is prompt to choose where to save the file
      2. If the object has its mode set to 'writable'
      1. If the silent parameter is set to true
            1. if the file is no longer available in the file system
               1. If the object has its lock set to true
                  1. The file is recreated using the data available in the
                  File object
               2. If the object has its lock set to false
                  1. The user is prompt to choose where to save the file
               2. otherwise
               1. The file on the file system is silently overridden by the
               content of the File object
            2. If the silent parameter is set to false
            1. if the file is no longer available in the file system
               1. The user is prompt to choose where to save the file
            2. Otherwise
               1. The user is prompt to allow the override

2. The first time a silent saving is performed, the user must be prompt to
allow this (possible answer are never, this time only, for the rest of the
session, or forever); If the user chose 'never', any call to the saveFile
method will be done as if the silent parameter were set to false (whatever
its true value).

In order to avoid nasty security issues, the calls to the saveFile method
from script hosted on third party domain should never be allowed to be
silent and each saving prompt should display which domain is trying to
write on the file system.

[1] http://w3c.github.io/filesystem-api/Overview.html
[2] http://dev.w3.org/2009/dap/file-system/file-writer.html
[3] http://dev.w3.org/2006/webapi/FileAPI/
[4] http://msdn.microsoft.com/en-us/library/hh772331%28v=vs.85%29.aspx
[5] http://msdn.microsoft.com/en-us/library/hh772332%28v=vs.85%29.aspx

Best,
-- 
Jeremie
.............................
Web : http://jeremie.patonnier.net
Twitter : @JeremiePat <http://twitter.com/JeremiePat>

Received on Friday, 18 October 2013 12:08:21 UTC