Firefox OS/Cloud Storage: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
(Add reference for Cache Architecture)
(Add mozlando demo link and team member introduction)
 
(15 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= Overview =
= Overview =
This project aims at to support a framework for web apps to interact with cloud storage.<br />
FirefoxOS cloud storage support is a project that supports a framework to integrate user's cloud storage into their FirefoxOS device.<br/>
[[File:Cloud Storage Support Overview.png|550px]]<br />
[[File:Cloud Storage Support Overview.png|400px]]<br/>
Cloud Storage framework wants to support following features
= Current Cloud Storage User Scenario =
* '''Universal Storage API'''
In android or iOS, viewing a media file on cloud, it has following possible ways.<br/>
Universal Storage API is a general API for web apps to access all kinds of cloud storage.
1. Using one viewing app and one cloud app. It needs following steps.<br/>
* '''Virtual Storage Interface'''
# Using the cloud app to download the media file to device.
Virtual Storage Interface is plugin system for cloud storage framework to extend cloud storage option.
# Using the viewing app to open the downloaded media file.
 
:In this way, user must download the whole media file first. Download brings following drawbacks.<br/>
= Cloud Storage Framework =
:* File duplication.
== Universal Storage API ==
:File occupies the local storage. If device local storage is almost full, user might need to cleanup the local storage first.<br/>
Universal Storage API is a general API for web apps to access all kinds of storage.<br />
:* Need to download the whole file before viewing.
According to different purposes, Universal Storage API can be separated into following two categories
:Some files might be not suitable to be downloaded, for example 4k video files.<br/>
* '''Document based API'''
<br/>
Document based API is used to help web apps save/operate their application data, such as indexedDB, on the cloud storage.
2. Using a viewing app which support the specified cloud accessing. It needs following steps.<br/>
* '''Filesystem based API'''
# Using the viewing app to open the media file on cloud.
Filesystem based API supports web apps to access cloud storage with filesystem operations, such as file create, delete, open, read, write, close, etc.<br />
:In this way, user can view the media in stream way. However, the viewing app must to support the user preferred cloud. Otherwise, user might select another app or cloud they don't want.<br/>
Reference for Filesystem based API: [http://www.w3.org/TR/file-system-api/ W3C FileAPI]
<br/>
[https://github.com/filerjs/filer#providers filer]
In this project, we want to support user
[[WebAPI/DeviceStorageAPI|DeviceStorageAPI]]
* <b>Choose their preferred apps and cloud in free.</b>
== Virtual Storage Interface ==
* <b>No need to save the whole file in local.</b>
Virtual Storage Interface is plugin system for cloud storage framework to cooperate with different cloud storage.
= Cloud Storage Support Framework =
 
[[File:Cloud Storage Support Framework.png|thumbnail|Framework|550px]]
== Cache Architecture ==
The basic idea of this framework is mounting cloud storage as a FirefoxOS fake volume in FirefoxOS Volume System. By mounting cloud as a fake volume, FirefoxOS becomes a proxy for apps to access user's cloud, such that apps needn't know how to access cloud data in special way and maintain cloud by themselves. On the other hand, FirefoxOS can support streaming access to avoid downloading the whole file into local storage.<br/>
=== Background ===
Instead of accessing cloud directly in Gecko, we design FileSystemProvider API to provide apps/addons can create a virtual file system in Gaia, and accessing cloud in these apps/addons. According to this design, we can gain following benefits<br/>
* '''Improve performance'''
* No need to maintain third party cloud APIs in Gecko.
** The response time of each file operation should be as short as possible to provide better user experience when users want to view a photo, listen an audio, or watch a video.
:It means FirefoxOS no need to FOTA to support the third party cloud APIs upgrade. It only needs to update the corresponding Cloud Storage Addons.<br/>
* '''Offline Support'''
* Easy to reuse the framework on other kinds of storage.
** Cache store is a subset of cloud storage, so Cache system still can provide cached file content from cache store even no network connection available.
:Not only cloud storage, but also NFS, personal NAS can reuse this framework to plug into FirefoxOS Volume System, such that apps can also interact with these storage directly.<br/>
=== Architecture ===
== FirefoxOS Volume System ==
* '''Cache Manager'''
FirefoxOS Volume System is a middle layer between FirefoxOS and low-level OS kernel. It supports basic volume operations, such as mounting, unmounting, and formatting, to manage volumes in the device. In addition to the basic volume operations, the Volume System also provides fake volume creation and deletion mechanism.<br/>
** Dispatch the request from Cloud Storage Interface to Data/Meta Cache first
In this framework, we creates fake volumes for each connected cloud, therefore these connected cloud can be recognized, identified and accessed by apps through DeviceStorage API and File API.<br/>
** Get data from Web Storage Manager if there is no data existed in Cache.
== DeviceStorage API and File API ==
* '''Cloud Storage Interface'''
DeviceStorage API and File API are interface used by apps to access FirefoxOS file systems. Apps can use these APIs to perform file read, write, creation, and deletion. Here are more detail about [https://developer.mozilla.org/en-US/docs/Mozilla/Firefox_OS/API/Device_Storage_API DeviceStorage API] and [https://developer.mozilla.org/en-US/docs/Web/API/File File API]<br/>
** The interface for using Cloud Storage cache is a general design. This can be used in JS Library or Gecko implementation.
In this framework, we let apps still use these APIs to access cloud data. It means apps can access user's cloud without any modification which just like they access the device local storage.<br/>
* '''Meta Cache'''
== FileSystemProvider API ==
** Each file has its meta data like mdate, cdate, size, etc. These information should be cached.
FileSystemProvider API provides apps/addons capability to create virtual file systems in Gaia. It provides<br/>
* '''Data Cache'''
* Methods to request Volume System to create/delete a fake volume.
** Data Cache should store a file content requested by user for each file in order to avoid extra network transaction.
* Events and callbacks to request data from virtual file systems created by apps/addons.
* '''Web Storage Manager'''
=== Types ===
** Provide an interface for each web storage provider (Dropbox, Box.net, etc) to communicate with Cache Manager.
:<b>OpenFileMode</b><br/>
** 3rd party plugin could be in the form of add-on for developer to support new web storage easily.
::Mode for open a file.<br/>
* '''Cache Policy'''
::{| class="wikitable" style="width:100%"
** Cache store entry can be flexible to adjust for different requirement, i.e. storage size. Any new request can replace one existed entry if the maximum entry is exceeded. ‘existed entry’ has not been well-defined yet, and it depends on user story.
| style="background:#abc2e0" | <b>Enum</b>
** Cache policy is a set of method to prefetch file content or meta aggressively, so the response time for each request can be improved.
 
=== Data Cache Implement Proposal ===  
* File-based Cache
** minimum data chunk - File
* Block-based Cache
** minimum data chunk - Block (with fixed-size)
** File System level operation can be mapped to cloud storage.
{| class="wikitable"
|-
|-
! !! File-based !! Block-based
| <b>"READ"</b> or <b>"WRITE"</b>
|}
:<b>MountOptions</b><br/>
::Options for the mount method.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b>  
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system. It must be unique for each file system.
|-
| DOMString || displayName || The fake volume name.
|-
| boolean || writable || Writable file system.
|-
| unsigned long || openedFilesLimit<br/>(optional) || The maximum number of opened files.
|}
:<b>UnmountOptions</b><br/>
::Options for the unmount method.<br/>
::{| class="wikitable" style="width:100%"
| colspan=3 style="background:#abc2e0" | <b>Properties</b>
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|}
:<b>OpenedFile</b><br/>
::Represents an opened file.<br/>
::{| class="wikitable" style="width:100%"
| colspan=3 style="background:#abc2e0" | <b>Properties</b>
|-
| width=15% | unsigned long || width=15% | openRequestId || width=70% | The open request ID.
|-
| DOMString || filePath || The opened file path.
|-
| OpenFileMode || mode || The mode of open file.
|}
:<b>FileSystemInfo</b><br/>
::Represents a mounted file system.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| DOMString || displayName || The fake volume name.
|-
| boolean || writable || Writable file system.
|-
| unsigned long || openedFilesLimit || The maximum number of opened files.
|-
| sequence<br/><OpenedFile> || openedFiles || The sequence of opened files.
|}
:<b>FileSystemProviderError</b><br/>
::FileSystemProvider error types.<br/>
::{| class="wikitable" style="width:100%"
| style="background:#abc2e0" | <b>Enum</b>
|-
| <b>"Failed"</b>, <b>"InUse"</b>, <b>"Exists"</b>, <b>"NotFound"</b>, <b>"AccessDenied"</b>, <b>"TooManyOpened"</b>, <b>"NoMemory"</b>, <b>"NoSpace"</b>, <b>"NotADirectory"</b>, <b>"InvalidOperation"</b>, <b>"Security"</b>, <b>"Abort"</b>, <b>"NotAFile"</b>, <b>"NotEmpty"</b>, or <b>"InvalidURL"</b>
|}
:<b>EntryMetadata</b><br/>
::Represents metadata of a file or a directory.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | boolean || width=15% | isDirectory || width=70% | True if it is a directory.
|-
| DOMString || name || Name of this entry (not full path name). Must not contain '/'. For root it must be empty.
|-
| unsigned long long || size || File size in bytes.
|-
| DOMTimeStamp || modificationTime || The last modified time of this entry.
|-
| DOMString || mimeType<br/>(Optional) || Mime type for the entry.
|}
:<b>UnmountRequestedOptions</b><br/>
::Options for unmountrequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|}
:<b>AbortRequestedOptions</b><br/>
::Options for abortrequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|-
| unsigned long || operationRequestId || The unsigned integer identifier of the aborting request.
|}
:<b>GetMetadataRequestedOptions</b><br/>
:: Options for getmetadatarequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|-
| DOMString || entryPath || The path of the entry to fetch metadata about.
|}
:<b>ReadDirectoryRequestedOptions</b><br/>
::Options for readdirectoryrequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|-
| DOMString || directoryPath || The path of the directory which contents are requested.
|}
:<b>OpenFileRequestedOptions</b><br/>
::Options for openfilerequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|-
| DOMString || filePath || The path of the file to be opened.
|-
| OpenFileMode || mode || Whether the file will be used for reading or writing.
|}
:<b>CloseFileRequestedOptions</b><br/>
::Options for closefilerequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|-
| unsigned long || openRequestId || The unsigned integer identifier of the corresponding open request.
|}
:<b>ReadFileRequestedOptions</b><br/>
::Options for readfilerequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|-
| unsigned long || openRequestId || The unsigned integer identifier of the corresponding open file request.
|-
| unsigned long long || offset || Position in the file (in bytes) to start reading from.
|-
| unsigned long long || size || Number of bytes to be returned.
|}
:<b>CreateDirectoryRequestedOptions</b><br/>
::Options for createdirectoryrequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|-
| DOMString || directoryPath || The path of the directory to be created.
|-
| boolean || recursive || Whether the operation is recursive (for directories only).
|}
:<b>DeleteEntryRequestedOptions</b><br/>
::Options for deleteentryrequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|-
| DOMString || entryPath || The path of the entry to be deleted.
|-
| boolean || recursive || Whether the operation is recursive (for directories only).
|}
:<b>CopyEntryRequestedOptions</b><br/>
::Options for copyentryrequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|-
| DOMString || sourcePath || The source path of the entry to be copied.
|-
| DOMString || targetPath || The destination path for the copy operation.
|}
:<b>MoveEntryRequestedOptions</b><br/>
::Options for moveentryrequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|-
| DOMString || sourcePath || The source path of the entry to be copied.
|-
| DOMString || targetPath || The destination path for the copy operation.
|}
:<b>CreateFileRequestedOptions</b><br/>
::Options for createfilerequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|-
| DOMString || filePath || The path of the file to be created.
|}
:<b>WriteFileRequestedOptions</b><br/>
::Options for writefilerequested event.<br/>
::{| class="wikitable" style="width:100%"
| colspan="3" style="background:#abc2e0" | <b>Properties</b> 
|-
| width=15% | DOMString || width=15% | fileSystemId || width=70% | The string identifier of the file system.
|-
| unsigned long || requestId || The unsigned integer identifier of this request.
|-
| unsigned long || openRequestId || The unsigned integer identifier of the corresponding open file request.
|-
| unsigned long long || offset || Position in the file (in bytes) to start writing the bytes from.
|-
| ArrayBuffer || data || Buffer of bytes to be written to the file.
|}
=== Methods ===
:<b>mount</b><br/>
::navigator.fileSystemProvider.mount(MountOptions options)<br/>
::Mount a file system with the given MountOptions.<br/>
::{| class="wikitable" style="width:100%"
| colspan="2" style="background:#abc2e0" | <b>Parameters</b>
|-
| width=20% | MountOptions || width=80% | The mount options for mount a file system.
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | Promise<void>
|}
:<b>unmount</b><br/>
::navigator.fileSystemProvider.unmount(UnmountOptions options)<br/>
::Unmount a file system by the given UnmountOptions.<br/>
::{| class="wikitable" style="width:100%"
| colspan="2" style="background:#abc2e0" | <b>Parameters</b>
|-
| width=20% | UnmountOptions || width=80% | The unmount options for unmount a file system.
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | Promise<void>
|}
:<b>get</b><br/>
::navigator.fileSystemProvider.get(DOMString fileSystemId)<br/>
::Returns information about a file system with the passed fileSystemId.<br/>
::{| class="wikitable" style="width:100%"
| colspan="2" style="background:#abc2e0" | <b>Parameters</b>
|-
| width=20% | DOMStrig || width=80% | The file system ID.
|-
| colspan="2" style="background:#abc2e0" | <b>Return</b>
|-
| colspan="2" | FileSystemInfo
|}
:<b>getAll</b><br/>
::navigator.fileSystemProvider.getAll()<br/>
::Returns all file system information mounted by FileSystemProvider API
::{| class="wikitable" style="width:100%"
| style="background:#abc2e0" | <b>Return value</b>
|-
| sequence<FileSystemInfo>
|}
=== Events ===
:<b>unmountrequested</b><br/>
::Raised when unmounting for the file system with the fileSystemId identifier is requested.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("unmountrequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | UnmountRequestedOptions || colspan="2" width=30% | options || width=50% | The requested unmount options.
|-
| rowspan="3" | function || colspan="2" | successCallback || rowspan="3" valign="top" | Success callback for unmountrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for unmountrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| FileSystemProviderError || errorCode
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|}
:<b>abortrequsted</b><br/>
::Raised when aborting an operation with operationRequestId is requested. The operation executed with operationRequestId must be immediately stopped and successCallback of this abort request executed. If aborting fails, then errorCallback must be called. Note, that callbacks of the aborted operation must not be called, as they will be ignored. Despite calling errorCallback, the request may be forcibly aborted.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("abortrequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | AbortRequestedOptions || colspan="2" width=30% | options || width=50% | The requested abort options.
|-
| rowspan="3" | function || colspan="2" | successCallback || rowspan="3" valign="top" | Success callback for abortrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for abortrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| FileSystemProviderError || errorCode
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|}
:<b>getmetadatarequested</b><br/>
::Raised when metadata of a file or a directory at entryPath is requested. The metadata must be returned with the successCallback call. In case of an error, errorCallback must be called.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("getmetadatarequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | GetMetadataRequestedOptions || colspan="2" width=30% | options || width=50% | The requested getmetadata options.
|-
| rowspan="5" | function || colspan="2" | successCallback || rowspan="5" valign="top" | Success callback for getmetadatarequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| EntryMetadata || metadata
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for getmetadatarequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| FileSystemProviderError || errorCode
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|}
:<b>readdirectoryrequested</b><br/>
::Raised when contents of a directory at directoryPath are requested. The results must be returned in chunks by calling the successCallback several times. In case of an error, errorCallback must be called.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("readdirectorytrequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | ReadDirectoryRequestedOptions || colspan="2" width=30% | options || width=50% | The requested readdirectory options.
|-
| rowspan="6" | function || colspan="2" | successCallback || rowspan="6" valign="top" | Success callback for readdirectoryrequested event.<br/>If more entries will be returned, then hasMore must be true, and it has to be called again with additional entries. If no more entries are available, then hasMore must be set to false.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| Sequence<EntryMetadata> || entries
|-
| boolean || hasMore
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for readdirectoryrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| FileSystemProviderError || errorCode
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|}
:<b>openfilerequested</b><br/>
::Raised when opening a file at filePath is requested. If the file does not exist, then the operation must fail.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("openfilerequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | OpenFileRequestedOptions || colspan="2" width=30% | options || width=50% | The requested openfile options.
|-
| rowspan="3" | function || colspan="2" | successCallback || rowspan="3" valign="top" | Success callback for openfilerequested.
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for openfilerequested.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| FileSystemProviderError || errorCode
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|}
:<b>closefilerequested</b><br/>
::Raised when opening a file previously opened with openRequestId is requested to be closed.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("closefilerequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | CloseFileRequestedOptions || colspan="2" width=30% | options || width=50% | The requested closefile options.
|-
| rowspan="3" | function || colspan="2" | successCallback || rowspan="3" valign="top" | Success callback for closefilerequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for closefilerequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| FileSystemProviderError || errorCode
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|}
:<b>readfilerequested</b><br/>
::Raised when reading contents of a file opened previously with openRequestId is requested. The results must be returned in chunks by calling successCallback several times. In case of an error, errorCallback must be called.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("readfilerequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | ReadFileRequestedOptions || colspan="2" width=30% | options || width=50% | The requested readfile options.
|-
| rowspan="6" | function || colspan="2" | successCallback || rowspan="6" valign="top" | Success callback for the readfilerequested event.<br/>If more data will be returned, then hasMore must be true, and it has to be called again with additional entries. If no more data is available, then hasMore must be set to false.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| ArrayBuffer || data
|-
| boolean || hasMore
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for the readfilerequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| FileSystemProviderError || errorCode
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|}
:<b>createdirectoryrequested</b><br/>
::Raised when creating a directory is requested. The operation must fail with the EXISTS error if the target directory already exists. If recursive is true, then all of the missing directories on the directory path must be created.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("createdirectoryrequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | CreateDirectoryRequestedOptions || colspan="2" width=30% | options || width=50% | The requested createdirectory options.
|-
| rowspan="3" | function || colspan="2" | successCallback || rowspan="3" valign="top" | Success callback for createdirectoryrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for createdirectoryrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| FileSystemProviderError || errorCode
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|}
:<b>deleteentryrequested</b><br/>
::Raised when deleting an entry is requested. If recursive is true, and the entry is a directory, then all of the entries inside must be recursively deleted as well.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("deleteentryrequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | DeleteEntryRequestedOptions || colspan="2" width=30% | options || width=50% | The requested deleteentry options.
|-
| rowspan="3" | function || colspan="2" | successCallback || rowspan="3" valign="top" | Success callback for deleteentryrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for deleteentryrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| FileSystemProviderError || errorCode
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|}
:<b>copyentryrequested</b><br/>
::Raised when copying an entry (recursively if a directory) is requested. If an error occurs, then errorCallback must be called.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("copyentryrequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | CopyEntryRequestedOptions || colspan="2" width=30% | options || width=50% | The requested copyentry options.
|-
| rowspan="3" | function || colspan="2" | successCallback || rowspan="3" valign="top" | Success callback for copyentryrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for copyentryrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| FileSystemProviderError || errorCode
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|}
:<b>moveentryrequested</b><br/>
::Raised when moving an entry (recursively if a directory) is requested. If an error occurs, then errorCallback must be called.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("moveentryrequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | MoveEntryRequestedOptions || colspan="2" width=30% | options || width=50% | The requested moveentry options.
|-
| rowspan="3" | function || colspan="2" | successCallback || rowspan="3" valign="top" | Success callback for moveentryrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for moveentryrequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| FileSystemProviderError || errorCode
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|}
:<b>createfilerequested</b><br/>
::Raised when creating a file is requested. If the file already exists, then errorCallback must be called with the "EXISTS" error code.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("createfilerequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | CreateFileRequestedOptions || colspan="2" width=30% | options || width=50% | The requested createfile options.
|-
| rowspan="3" | function || colspan="2" | successCallback || rowspan="3" valign="top" | Success callback for createfilerequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for createfilerequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
| FileSystemProviderError || errorCode
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|}
:<b>writefilerequested</b><br/>
::Raised when writing contents to a file opened previously with openRequestId is requested.<br/>
::<b>addListener</b><br/>
:::navigator.fileSystemProvider.addListener("writefilerequested", function handler)<br/>
::{| class="wikitable" style="width:100%"
| colspan="4" style="background:#abc2e0" | <b>Properties</b>
|-
| width=20% | WriteFileRequestedOptions || colspan="2" width=30% | options || width=50% | The requested writefile options.
|-
| rowspan="3" | function || colspan="2" | successCallback || rowspan="3" valign="top" | Success callback for writefilerequested event.
|-
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
| colspan="2" | void
|-
|-
| Cross Platform/Browser || Yes || TBD...
| rowspan="5" | function || colspan="2" | errorCallback || rowspan="5" valign="top" | Error callback for writefilerequested event.
|-
|-
| Response Time for large-size file<br />(ex: video) || poor || good
| colspan="2" style="background:#abc2e0" | <b>Parameter</b>
|-
|-
| Response Time for small-size file<br />(ex: photo, audio) || good || good<br />(depends on block-size)
| FileSystemProviderError || errorCode
|-
|-
| Implementation Idea || Gaia: JS Library (Filer) || Gaia: TBD...<br />Gecko: FUSE
| colspan="2" style="background:#abc2e0" | <b>Return value</b>
|-
|-
| Related Web API || Blob, MSE(?), ... || Blob, Device Storage, ...
| colspan="2" | void
|}
|}
 
== Cloud Storage Addons ==
Reference
Cloud Storage Addons are in charge of the communication with the target cloud. It should provides at least<br/>
* [https://docs.google.com/presentation/d/1gB41Z6uQQO9C51Ns2aAm2A7vJox0AYt5tz2vyDC0xuo/edit#slide=id.p Cache Architecture study]
* User authentication and authorization mechanism
 
* Cloud access operations through the public APIs from cloud providers
== Proposed Solution(s) ==
Moreover, Cloud Storage Addons might provide more features, such as<br/>
=== FUSE based solution ===
* Data catch
Mounting Cloud Storage to device filesystem through the FUSE mechanism.<br />
* Data Synchronization
[[File:Cloud Storage FUSE solution.png|550px]]<br />
* Account management
==== Benefits ====
= Usage Flow =
* DeviceStorageAPI provides well defined filesystem based API to access files/directories on internal storage and SD card. Once FUSE based solution supported, Web app can used DeviceStorageAPI directly to access cloud storage without any modification.
== Mounting a Cloud on FirefoxOS ==
* FUSE interface is a good reference for Virtual Storage Interface. By propagating FUSE interface to FirefoxOS, FirefoxOS can easy connect to many kinds of storage, such as cloud storage, NAS, etc. [http://en.wikipedia.org/wiki/ExpanDrive Here is an commercial example].
[[File:Cloud Storage Support Mount Flow.png|thumbnail|Mount Flow|550px]]
==== Drawbacks ====
To mount a cloud on FirefoxOS, FileSystemProvider API providers methods and events for Cloud Storage Addons.<br/>
* DeviceStorageAPI is not a standard API for all browser.
The picture shows the flow that Cloud Storage Addon mounts a cloud "MyCloud" on FirefoxOS through FileSystemProvider API.<br/>
* FUSE is not supported in all platforms.
# Cloud Storage addon registers the event listener on FileSystemProviderEvents.
==== Prototype ====
# Call FileSystemProvider.mount() method with parameters to request Volume System to create a fake volume.
* [https://github.com/MozCloudStorage MozCloudStorage github repo]
<br/><br/><br/>
* CloudStorageServiceAPI (this is only for prototype)
Following is an example code to mount a cloud "MyCloud"<br/>
CloudStorageServiceAPI is a WebAPI for enabling/disabling cloud storage. <br />
  // Code in Cloud Storage Addons
enum CloudStorageType {
  var fileSystemProvider = navigator.fileSystemProvider;
   "Dummy",
  // Event handler definition
   "Dropbox",
  function GetMetadataHandler(event) {
}; <br />
    var path = event.options.entryPath;
Promise<boolean> enable(DOMString cloudName, CloudStorageType cloudType, DOMString accessToken)<br />
    // get metadata through cloud APIs with entry path
Promise<void> disable(DOMString cloudName)<br />
    if (metadata) {
=== JS library solution ===
      event.successCallback(metadata);
==== Benefits ====
    } else {
==== Drawbacks ====
      event.errorCallback('NotFound');
== Framework Issues ==
    }
* '''Cloud Storage Account management and Authentication'''
  }
* '''Security issues'''
    ...
=== Issue Study ===
   // Register event listener on FileSystemProviderEvents
* '''Video Support with MSE'''
  fileSystemProvider.addEventListener("getmetadatarequested", GetMetadataHandler);
** [https://w3c.github.io/media-source/ Media Source Extensions]
   fileSystemProvider.addEventListener("openfilerequested", OpenFileHandler);
** The challenge with HTML5 audio and video is still the fragmented support for audio and video formats.
  fileSystemProvider.addEventListener("closefilerequested", CloseFileHandler);
** In Firefox browser, the maximum size of each fragment is 75MB. Getting QuotaExceededError if the fragment size is over 75MB.
  fileSystemProvider.addEventListener("readdirectoryrequested", ReadDirectoryHandler);
** Fragmented Video Format - the video MUST be in fragmented format, and this video can be played well.
  fileSystemProvider.addEventListener("readfilerequested", ReadFileHandler);
** Non-fragmented Video - this more general format can be played in MSE way. Browser treats a non-fragment video as a one big fragment file because the maximum size of a non-fragment video is 75MB.
    ...
 
  // Call mount method to create fake volume "MyCloud" in FirefoxOS
= Related Use cases =
  fileSystemProvider.mount({fileSystemId: 'MyCloud',
== Play media files saved on cloud ==
                            displayName: 'MyCloud',
John saves his media files on dropbox or any other cloud storage and wants to play these media online on his mobile device.<br />
                            writable: true,
In traditional, John needs to do with following steps<br />
                            openedFilesLimit: 256})
#Open the cloud storage app, such as dropbox and google drive, and download the media files to the mobile device.<br />
                            .then(
#Open the player app, such as Gallery and Music, and play the media files locally.<br />
                            function() { dump('mount successfully\n');}
On FirefoxOS device, the steps can be reduced to<br />
                            function(aError) { dump('mount failed ['+aError+']\n');}
#Open the player app and play the media files on cloud storage directly.
                            );
 
== Accessing Cloud through the Framework ==
== Create and share files on cloud ==
[[File:Cloud Storage Support Read File Flow.png|thumbnail|Read File Flow|550px]]
Bob wants to take a picture and share it with friend on flickr.<br />
To access a mounted cloud, app can reuse DeviceStorage and File APIs, just like they access local storage.<br/>
In traditional, Bob needs to do with following steps<br />
The picture shows the flow how Gallery app read the "test.jpg" on cloud "MyCloud".<br/>
#Open the camera app to take a picture and save the file on the device.<br />
# Gallery app asks "MyCloud/test.jpg" data through the File API.
#(Optional) Open a third party app to edit the picture on the device.<br />
# Volume System get the request and send FileSystemProvderReadFileEvent to ask corresponding Cloud Storage Addons to get the data from cloud.
#Open the flickr app to upload the file and set it as shared.<br />
# Cloud Storage Addon receives the FileSystemProviderReadFileEvent and call ReadFileEventListener to get "test.jpg" data from cloud through the cloud access API.
On FirefoxOS device, the steps can be reduced to<br />
# Once read success or fail, call the event.successCallback with data or event.errorCallback with error code.
#Open the camera app to take a picture and save and share the file on cloud storage directly.<br />
# Volume System receives the callback data and send it back to app through the File API.
#(Optional) Open a third party app to edit the picture on cloud storage directly.<br />
Following is an example to access cloud 'MyCloud' through DeviceStorage and File APIs.<br/>
 
  // Get file through DeviceStorage API
== File management between clouds ==
  var myStorage = navigator.getDeviceStorage('MyCloud');
Amy wants to copy a finished work document form her personal dropbox space to the company google drive space<br />
  if (myStorage) {
In traditional, Amy needs to do with following steps<br />
    // Request to send GetMetadataEvent to get the information of "myFile.txt"
#Open the dropbox app and download the document file to device.
    var request = myStorage.get('myFile.txt');
#Open the google drive app and upload the document file.<br />
    request.onsuccess = function() {
On FirefoxOS device, the steps can be reduced to<br />
      var file = this.result;
#Open a file browser app and copy the document from dropbox to google drive directly.
      dump(file.name+'\n');
 
      var fileReader = new FileReader();
= Related links =
      fileRead.onloadend = function() {dump('load finished\n');}
* [[Firefox_Cloud]]<br />
      // Request to send OpenFileEvent, ReadFileEvents and CloseFileEvent
* [[Webmaker/MakeDrive|MakeDrive]]<br />
      fileReader.readAsArrayBuffer(file);
* [http://fuse.sourceforge.net/ FUSE(filesystem in userspace)]<br />
    }
= Previous works =
  }
* https://github.com/weilonge/unidisk
= Mozlando =
* http://weilonge.bitbucket.org/unidisk/UD.pdf
Presentation slide: https://goo.gl/Yd5lqT <br/>
= Related Bugzilla =
= Team =
* [https://bugzilla.mozilla.org/show_bug.cgi?id=1035053 Bug 1035053 - [Device Storage<nowiki>]</nowiki> To Support Variant Cloud Storage]
* Frontend Engineer: [https://phonebook.mozilla.org/#search/Sean%20Lee Sean Lee]
* [https://bugzilla.mozilla.org/show_bug.cgi?id=1164750 Bug 1164750 - [Meta<nowiki>]</nowiki> Cloud storage support in FirefoxOS FUSE based prototyping]
* Backend Engineer: [https://phonebook.mozilla.org/#search/Kershaw%20Chang Kershaw Chang] [https://phonebook.mozilla.org/#search/Eden%20Chuang Eden Chuang]
* EPM: [https://phonebook.mozilla.org/#search/Aaron%20Wu Aaron Wu]

Latest revision as of 02:32, 19 February 2016

Overview

FirefoxOS cloud storage support is a project that supports a framework to integrate user's cloud storage into their FirefoxOS device.
Cloud Storage Support Overview.png

Current Cloud Storage User Scenario

In android or iOS, viewing a media file on cloud, it has following possible ways.
1. Using one viewing app and one cloud app. It needs following steps.

  1. Using the cloud app to download the media file to device.
  2. Using the viewing app to open the downloaded media file.
In this way, user must download the whole media file first. Download brings following drawbacks.
  • File duplication.
File occupies the local storage. If device local storage is almost full, user might need to cleanup the local storage first.
  • Need to download the whole file before viewing.
Some files might be not suitable to be downloaded, for example 4k video files.


2. Using a viewing app which support the specified cloud accessing. It needs following steps.

  1. Using the viewing app to open the media file on cloud.
In this way, user can view the media in stream way. However, the viewing app must to support the user preferred cloud. Otherwise, user might select another app or cloud they don't want.


In this project, we want to support user

  • Choose their preferred apps and cloud in free.
  • No need to save the whole file in local.

Cloud Storage Support Framework

Framework

The basic idea of this framework is mounting cloud storage as a FirefoxOS fake volume in FirefoxOS Volume System. By mounting cloud as a fake volume, FirefoxOS becomes a proxy for apps to access user's cloud, such that apps needn't know how to access cloud data in special way and maintain cloud by themselves. On the other hand, FirefoxOS can support streaming access to avoid downloading the whole file into local storage.
Instead of accessing cloud directly in Gecko, we design FileSystemProvider API to provide apps/addons can create a virtual file system in Gaia, and accessing cloud in these apps/addons. According to this design, we can gain following benefits

  • No need to maintain third party cloud APIs in Gecko.
It means FirefoxOS no need to FOTA to support the third party cloud APIs upgrade. It only needs to update the corresponding Cloud Storage Addons.
  • Easy to reuse the framework on other kinds of storage.
Not only cloud storage, but also NFS, personal NAS can reuse this framework to plug into FirefoxOS Volume System, such that apps can also interact with these storage directly.

FirefoxOS Volume System

FirefoxOS Volume System is a middle layer between FirefoxOS and low-level OS kernel. It supports basic volume operations, such as mounting, unmounting, and formatting, to manage volumes in the device. In addition to the basic volume operations, the Volume System also provides fake volume creation and deletion mechanism.
In this framework, we creates fake volumes for each connected cloud, therefore these connected cloud can be recognized, identified and accessed by apps through DeviceStorage API and File API.

DeviceStorage API and File API

DeviceStorage API and File API are interface used by apps to access FirefoxOS file systems. Apps can use these APIs to perform file read, write, creation, and deletion. Here are more detail about DeviceStorage API and File API
In this framework, we let apps still use these APIs to access cloud data. It means apps can access user's cloud without any modification which just like they access the device local storage.

FileSystemProvider API

FileSystemProvider API provides apps/addons capability to create virtual file systems in Gaia. It provides

  • Methods to request Volume System to create/delete a fake volume.
  • Events and callbacks to request data from virtual file systems created by apps/addons.

Types

OpenFileMode
Mode for open a file.
Enum
"READ" or "WRITE"
MountOptions
Options for the mount method.
Properties
DOMString fileSystemId The string identifier of the file system. It must be unique for each file system.
DOMString displayName The fake volume name.
boolean writable Writable file system.
unsigned long openedFilesLimit
(optional)
The maximum number of opened files.
UnmountOptions
Options for the unmount method.
Properties
DOMString fileSystemId The string identifier of the file system.
OpenedFile
Represents an opened file.
Properties
unsigned long openRequestId The open request ID.
DOMString filePath The opened file path.
OpenFileMode mode The mode of open file.
FileSystemInfo
Represents a mounted file system.
Properties
DOMString fileSystemId The string identifier of the file system.
DOMString displayName The fake volume name.
boolean writable Writable file system.
unsigned long openedFilesLimit The maximum number of opened files.
sequence
<OpenedFile>
openedFiles The sequence of opened files.
FileSystemProviderError
FileSystemProvider error types.
Enum
"Failed", "InUse", "Exists", "NotFound", "AccessDenied", "TooManyOpened", "NoMemory", "NoSpace", "NotADirectory", "InvalidOperation", "Security", "Abort", "NotAFile", "NotEmpty", or "InvalidURL"
EntryMetadata
Represents metadata of a file or a directory.
Properties
boolean isDirectory True if it is a directory.
DOMString name Name of this entry (not full path name). Must not contain '/'. For root it must be empty.
unsigned long long size File size in bytes.
DOMTimeStamp modificationTime The last modified time of this entry.
DOMString mimeType
(Optional)
Mime type for the entry.
UnmountRequestedOptions
Options for unmountrequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
AbortRequestedOptions
Options for abortrequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
unsigned long operationRequestId The unsigned integer identifier of the aborting request.
GetMetadataRequestedOptions
Options for getmetadatarequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
DOMString entryPath The path of the entry to fetch metadata about.
ReadDirectoryRequestedOptions
Options for readdirectoryrequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
DOMString directoryPath The path of the directory which contents are requested.
OpenFileRequestedOptions
Options for openfilerequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
DOMString filePath The path of the file to be opened.
OpenFileMode mode Whether the file will be used for reading or writing.
CloseFileRequestedOptions
Options for closefilerequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
unsigned long openRequestId The unsigned integer identifier of the corresponding open request.
ReadFileRequestedOptions
Options for readfilerequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
unsigned long openRequestId The unsigned integer identifier of the corresponding open file request.
unsigned long long offset Position in the file (in bytes) to start reading from.
unsigned long long size Number of bytes to be returned.
CreateDirectoryRequestedOptions
Options for createdirectoryrequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
DOMString directoryPath The path of the directory to be created.
boolean recursive Whether the operation is recursive (for directories only).
DeleteEntryRequestedOptions
Options for deleteentryrequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
DOMString entryPath The path of the entry to be deleted.
boolean recursive Whether the operation is recursive (for directories only).
CopyEntryRequestedOptions
Options for copyentryrequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
DOMString sourcePath The source path of the entry to be copied.
DOMString targetPath The destination path for the copy operation.
MoveEntryRequestedOptions
Options for moveentryrequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
DOMString sourcePath The source path of the entry to be copied.
DOMString targetPath The destination path for the copy operation.
CreateFileRequestedOptions
Options for createfilerequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
DOMString filePath The path of the file to be created.
WriteFileRequestedOptions
Options for writefilerequested event.
Properties
DOMString fileSystemId The string identifier of the file system.
unsigned long requestId The unsigned integer identifier of this request.
unsigned long openRequestId The unsigned integer identifier of the corresponding open file request.
unsigned long long offset Position in the file (in bytes) to start writing the bytes from.
ArrayBuffer data Buffer of bytes to be written to the file.

Methods

mount
navigator.fileSystemProvider.mount(MountOptions options)
Mount a file system with the given MountOptions.
Parameters
MountOptions The mount options for mount a file system.
Return value
Promise<void>
unmount
navigator.fileSystemProvider.unmount(UnmountOptions options)
Unmount a file system by the given UnmountOptions.
Parameters
UnmountOptions The unmount options for unmount a file system.
Return value
Promise<void>
get
navigator.fileSystemProvider.get(DOMString fileSystemId)
Returns information about a file system with the passed fileSystemId.
Parameters
DOMStrig The file system ID.
Return
FileSystemInfo
getAll
navigator.fileSystemProvider.getAll()
Returns all file system information mounted by FileSystemProvider API
Return value
sequence<FileSystemInfo>

Events

unmountrequested
Raised when unmounting for the file system with the fileSystemId identifier is requested.
addListener
navigator.fileSystemProvider.addListener("unmountrequested", function handler)
Properties
UnmountRequestedOptions options The requested unmount options.
function successCallback Success callback for unmountrequested event.
Return value
void
function errorCallback Error callback for unmountrequested event.
Parameter
FileSystemProviderError errorCode
Return value
void
abortrequsted
Raised when aborting an operation with operationRequestId is requested. The operation executed with operationRequestId must be immediately stopped and successCallback of this abort request executed. If aborting fails, then errorCallback must be called. Note, that callbacks of the aborted operation must not be called, as they will be ignored. Despite calling errorCallback, the request may be forcibly aborted.
addListener
navigator.fileSystemProvider.addListener("abortrequested", function handler)
Properties
AbortRequestedOptions options The requested abort options.
function successCallback Success callback for abortrequested event.
Return value
void
function errorCallback Error callback for abortrequested event.
Parameter
FileSystemProviderError errorCode
Return value
void
getmetadatarequested
Raised when metadata of a file or a directory at entryPath is requested. The metadata must be returned with the successCallback call. In case of an error, errorCallback must be called.
addListener
navigator.fileSystemProvider.addListener("getmetadatarequested", function handler)
Properties
GetMetadataRequestedOptions options The requested getmetadata options.
function successCallback Success callback for getmetadatarequested event.
Parameter
EntryMetadata metadata
Return value
void
function errorCallback Error callback for getmetadatarequested event.
Parameter
FileSystemProviderError errorCode
Return value
void
readdirectoryrequested
Raised when contents of a directory at directoryPath are requested. The results must be returned in chunks by calling the successCallback several times. In case of an error, errorCallback must be called.
addListener
navigator.fileSystemProvider.addListener("readdirectorytrequested", function handler)
Properties
ReadDirectoryRequestedOptions options The requested readdirectory options.
function successCallback Success callback for readdirectoryrequested event.
If more entries will be returned, then hasMore must be true, and it has to be called again with additional entries. If no more entries are available, then hasMore must be set to false.
Parameter
Sequence<EntryMetadata> entries
boolean hasMore
Return value
void
function errorCallback Error callback for readdirectoryrequested event.
Parameter
FileSystemProviderError errorCode
Return value
void
openfilerequested
Raised when opening a file at filePath is requested. If the file does not exist, then the operation must fail.
addListener
navigator.fileSystemProvider.addListener("openfilerequested", function handler)
Properties
OpenFileRequestedOptions options The requested openfile options.
function successCallback Success callback for openfilerequested.
Return value
void
function errorCallback Error callback for openfilerequested.
Parameter
FileSystemProviderError errorCode
Return value
void
closefilerequested
Raised when opening a file previously opened with openRequestId is requested to be closed.
addListener
navigator.fileSystemProvider.addListener("closefilerequested", function handler)
Properties
CloseFileRequestedOptions options The requested closefile options.
function successCallback Success callback for closefilerequested event.
Return value
void
function errorCallback Error callback for closefilerequested event.
Parameter
FileSystemProviderError errorCode
Return value
void
readfilerequested
Raised when reading contents of a file opened previously with openRequestId is requested. The results must be returned in chunks by calling successCallback several times. In case of an error, errorCallback must be called.
addListener
navigator.fileSystemProvider.addListener("readfilerequested", function handler)
Properties
ReadFileRequestedOptions options The requested readfile options.
function successCallback Success callback for the readfilerequested event.
If more data will be returned, then hasMore must be true, and it has to be called again with additional entries. If no more data is available, then hasMore must be set to false.
Parameter
ArrayBuffer data
boolean hasMore
Return value
void
function errorCallback Error callback for the readfilerequested event.
Parameter
FileSystemProviderError errorCode
Return value
void
createdirectoryrequested
Raised when creating a directory is requested. The operation must fail with the EXISTS error if the target directory already exists. If recursive is true, then all of the missing directories on the directory path must be created.
addListener
navigator.fileSystemProvider.addListener("createdirectoryrequested", function handler)
Properties
CreateDirectoryRequestedOptions options The requested createdirectory options.
function successCallback Success callback for createdirectoryrequested event.
Return value
void
function errorCallback Error callback for createdirectoryrequested event.
Parameter
FileSystemProviderError errorCode
Return value
void
deleteentryrequested
Raised when deleting an entry is requested. If recursive is true, and the entry is a directory, then all of the entries inside must be recursively deleted as well.
addListener
navigator.fileSystemProvider.addListener("deleteentryrequested", function handler)
Properties
DeleteEntryRequestedOptions options The requested deleteentry options.
function successCallback Success callback for deleteentryrequested event.
Return value
void
function errorCallback Error callback for deleteentryrequested event.
Parameter
FileSystemProviderError errorCode
Return value
void
copyentryrequested
Raised when copying an entry (recursively if a directory) is requested. If an error occurs, then errorCallback must be called.
addListener
navigator.fileSystemProvider.addListener("copyentryrequested", function handler)
Properties
CopyEntryRequestedOptions options The requested copyentry options.
function successCallback Success callback for copyentryrequested event.
Return value
void
function errorCallback Error callback for copyentryrequested event.
Parameter
FileSystemProviderError errorCode
Return value
void
moveentryrequested
Raised when moving an entry (recursively if a directory) is requested. If an error occurs, then errorCallback must be called.
addListener
navigator.fileSystemProvider.addListener("moveentryrequested", function handler)
Properties
MoveEntryRequestedOptions options The requested moveentry options.
function successCallback Success callback for moveentryrequested event.
Return value
void
function errorCallback Error callback for moveentryrequested event.
Parameter
FileSystemProviderError errorCode
Return value
void
createfilerequested
Raised when creating a file is requested. If the file already exists, then errorCallback must be called with the "EXISTS" error code.
addListener
navigator.fileSystemProvider.addListener("createfilerequested", function handler)
Properties
CreateFileRequestedOptions options The requested createfile options.
function successCallback Success callback for createfilerequested event.
Return value
void
function errorCallback Error callback for createfilerequested event.
Parameter
FileSystemProviderError errorCode
Return value
void
writefilerequested
Raised when writing contents to a file opened previously with openRequestId is requested.
addListener
navigator.fileSystemProvider.addListener("writefilerequested", function handler)
Properties
WriteFileRequestedOptions options The requested writefile options.
function successCallback Success callback for writefilerequested event.
Return value
void
function errorCallback Error callback for writefilerequested event.
Parameter
FileSystemProviderError errorCode
Return value
void

Cloud Storage Addons

Cloud Storage Addons are in charge of the communication with the target cloud. It should provides at least

  • User authentication and authorization mechanism
  • Cloud access operations through the public APIs from cloud providers

Moreover, Cloud Storage Addons might provide more features, such as

  • Data catch
  • Data Synchronization
  • Account management

Usage Flow

Mounting a Cloud on FirefoxOS

Mount Flow

To mount a cloud on FirefoxOS, FileSystemProvider API providers methods and events for Cloud Storage Addons.
The picture shows the flow that Cloud Storage Addon mounts a cloud "MyCloud" on FirefoxOS through FileSystemProvider API.

  1. Cloud Storage addon registers the event listener on FileSystemProviderEvents.
  2. Call FileSystemProvider.mount() method with parameters to request Volume System to create a fake volume.




Following is an example code to mount a cloud "MyCloud"

 // Code in Cloud Storage Addons
 var fileSystemProvider = navigator.fileSystemProvider;
 // Event handler definition
 function GetMetadataHandler(event) {
   var path = event.options.entryPath;
   // get metadata through cloud APIs with entry path
   if (metadata) {
      event.successCallback(metadata);
   } else {
      event.errorCallback('NotFound');
   }
 }
   ...
 // Register event listener on FileSystemProviderEvents
 fileSystemProvider.addEventListener("getmetadatarequested", GetMetadataHandler);
 fileSystemProvider.addEventListener("openfilerequested", OpenFileHandler);
 fileSystemProvider.addEventListener("closefilerequested", CloseFileHandler);
 fileSystemProvider.addEventListener("readdirectoryrequested", ReadDirectoryHandler);
 fileSystemProvider.addEventListener("readfilerequested", ReadFileHandler);
   ...
 // Call mount method to create fake volume "MyCloud" in FirefoxOS
 fileSystemProvider.mount({fileSystemId: 'MyCloud',
                           displayName: 'MyCloud',
                           writable: true,
                           openedFilesLimit: 256})
                           .then(
                           function() { dump('mount successfully\n');}
                           function(aError) { dump('mount failed ['+aError+']\n');}
                           );

Accessing Cloud through the Framework

Read File Flow

To access a mounted cloud, app can reuse DeviceStorage and File APIs, just like they access local storage.
The picture shows the flow how Gallery app read the "test.jpg" on cloud "MyCloud".

  1. Gallery app asks "MyCloud/test.jpg" data through the File API.
  2. Volume System get the request and send FileSystemProvderReadFileEvent to ask corresponding Cloud Storage Addons to get the data from cloud.
  3. Cloud Storage Addon receives the FileSystemProviderReadFileEvent and call ReadFileEventListener to get "test.jpg" data from cloud through the cloud access API.
  4. Once read success or fail, call the event.successCallback with data or event.errorCallback with error code.
  5. Volume System receives the callback data and send it back to app through the File API.

Following is an example to access cloud 'MyCloud' through DeviceStorage and File APIs.

 // Get file through DeviceStorage API
 var myStorage = navigator.getDeviceStorage('MyCloud');
 if (myStorage) {
   // Request to send GetMetadataEvent to get the information of "myFile.txt"
   var request = myStorage.get('myFile.txt');
   request.onsuccess = function() {
     var file = this.result;
     dump(file.name+'\n');
     var fileReader = new FileReader();
     fileRead.onloadend = function() {dump('load finished\n');}
     // Request to send OpenFileEvent, ReadFileEvents and CloseFileEvent
     fileReader.readAsArrayBuffer(file);
   }
 }

Mozlando

Presentation slide: https://goo.gl/Yd5lqT

Team