Proposal Date Last updated 2013-02-27 (2013-02-11 -> 2013-02-27: Fixed the remote folder name from "Chrome Syncable Storage" to "Chrome Syncable FileSystem") Who is the primary contact for this API? kinuko@chromium.org Overview Sync FileSystem API is a storage API that appears as yet another local offline HTML5 FileSystem storage which gives app-private sandboxed file storage, except that the storage content is automatically synchronized across clients via a cloud backing service like Google Drive. We initially only target Google Drive as its backing service. Use cases This API could be used to store user-generated data (or any other binary data) locally for offline or caching usage when the app also wants to save/synchronize the data on a cloud storage so that the same data can be available across different clients. This API is NOT for accessing arbitrary user docs stored on a cloud service (e.g. not for opening your google docs document) but to provide app-specific syncable storage. Do you know anyone else, internal or external, that is also interested in this API? I heard there could be some but I'm not aware of anyone at this time. Could this API be part of the web platform? Possibly yes, as this API has strong relationship with the existing owp proposal: File API: Directories and System (http://www.w3.org/TR/file-system-api/). Do you expect this API to be fairly stable? How might it be extended or changed in the future? The API proposed in this API is supposed to be stable, while additional functionality to support more detailed manual conflict handling and sync behavior control might be added in the future. If multiple extensions used this API at the same time, could they conflict with each others? If so, how do you propose to mitigate this problem? No. Multiple extensions should be able to get its own private file storage. List every UI surface belonging to or potentially affected by your API: - Advanced Sync Settings (disabling 'Apps' sync will disable apps data synchronization) - Apps settings UI (when http://crbug.com/141584 kicks in) Actions taken with extension APIs should be obviously attributable to an extension. Will users be able to tell when this new API is being used? How? In the current architecture users can tell the usage of this API by: - Looking at the user's sync backend service storage (e.g. Drive). To be specific, current implementation saves the file in a folder named "Chrome Syncable FileSystem" on the signed-in user's Drive storage. - Looking into the local sandboxed directory for the app. - By querying the usage bytes returned by chrome.syncFileSystem.getUsageAndQuota API. Once we have app settings UI for disk space users should also be able to tell when the API stores something locally. How could this API be abused? One could use up the user's local disk and/or sync backend storage but it cannot use more than the quota that is adjusted by the local and remote storage capacity. Imagine you’re Dr. Evil Extension Writer, list the three worst evil deeds you could commit with your API (if you’ve got good ones, feel free to add more): 1) 2) 3) What security UI or other mitigations do you propose to limit evilness made possible by this new API?
Alright Doctor, one last challenge: Could a consumer of your API cause any permanent change to the user’s system using your API that would not be reversed when that consumer is removed from the system? This API would leave the user data synchronized by this API on the remote sync backend storage even after the consumer is uninstalled, but the user should be able to delete the data by directly visiting the sync backend storage service (e.g. Drive Web interface for Drive). How would you implement your desired features if this API didn't exist? Technically I could combine offline storage API (e.g. FileSystem API or IndexedDB) and remote storage service API (e.g. Drive SDK API) and implement every synchronization logic in JS layer, but it usually requires more engineering power. Integrating a custom JS app with server-side push change notifications and/or efficient background polling mechanism has several limitations too (though serious sync apps are doing that by themselves). Also giving an app access permission to a cloud storage usually means allowing the app to access every file on the storage for the authenticated identity (e.g. giving an app access permission to Drive SDK effectively allows the app to access every docs on Drive of the user). This API hides such details from JS layer and gives isolated access only to the app's private storage. Draft Manifest Changes This API adds a new permission: "syncFileSystem" Draft API spec
Draft API IDL ================================================================================= namespace syncFileSystem { enum SyncAction { added, updated, deleted }; enum ServiceStatus { // The sync service is being initialized (e.g. restoring data from the // database, checking connectivity and authenticating to the service etc). initializing, // The sync service is up and running. running, // The sync service is not synchronizing files because the remote service // needs to be authenticated by the user to proceed. authentication_required, // The sync service is not synchronizing files because the remote service // is (temporarily) unavailable due to some recoverable errors, e.g. // network is offline, the remote service is down or not // reachable etc. More details should be given by |description| parameter // in OnServiceInfoUpdated (which could contain service-specific details). temporary_unavailable, // The sync service is disabled and the content will never sync. // (E.g. this could happen when the user has no account on // the remote service or the sync service has had an unrecoverable // error.) disabled }; enum FileStatus { // Not conflicting and has no pending local changes. synced, // Has one or more pending local changes that haven't been synchronized. pending, // File conflicts with remote version and must be resolved manually. conflicting }; enum SyncDirection { local_to_remote, remote_to_local }; dictionary FileInfo { // |fileEntry| will contain name and path information of synchronized file. // On file deletion, fileEntry information will still be available but file // will no longer exist. [instanceOf=FileEntry] object fileEntry; FileStatus status; // Only applies if status is synced. SyncAction? action; // Only applies if status is synced. SyncDirection? direction; }; dictionary StorageInfo { long usageBytes; long quotaBytes; }; dictionary ServiceInfo { ServiceStatus state; DOMString description; }; // [nodoc] A callback type for requestFileSystem. callback GetFileSystemCallback = void ([instanceOf=DOMFileSystem] object fileSystem); // [nodoc] A callback type for getUsageAndQuota. callback QuotaAndUsageCallback = void (StorageInfo info); // Returns true if operation was successful. callback DeleteFileSystemCallback = void (boolean result); // [nodoc] A callback type for getFileStatus. callback GetFileStatusCallback = void (FileStatus status); interface Functions { // Returns a syncable filesystem backed by Google Drive. // The returned DOMFileSystem instance can be operated on in the same way as // the Temporary and Persistant file systems. // (http://www.w3.org/TR/file-system-api/). Calling this multiple times from // the same app will return the same handle to the same file system. static void requestFileSystem(GetFileSystemCallback callback); // Get usage and quota in bytes for sync file system with |serviceName|. static void getUsageAndQuota([instanceOf=DOMFileSystem] object fileSystem, QuotaAndUsageCallback callback); // Deletes everything in the syncable filesystem. static void deleteFileSystem([instanceOf=DOMFileSystem] object fileSystem, DeleteFileSystemCallback callback); // Get the FileStatus for the given |fileEntry|. static void getFileStatus([instanceOf=FileEntry] object fileEntry, GetFileStatusCallback callback); }; interface Events { // Fired when an error or other status change has happened in the // sync backend. (e.g. the sync is temporarily disabled due to // network or authentication error etc). static void onServiceStatusChanged(ServiceInfo detail); // Fired when a file has been updated by the background sync service. static void onFileStatusChanged(FileInfo detail); }; }; |
