Changes

Jump to: navigation, search

Firefox OS/Cloud Storage

23,764 bytes added, 03:49, 17 February 2016
update the document
= Overview =
This FirefoxOS cloud storage support is a project aims at to support that supports a framework for web apps to interact with integrate user's cloud storageinto their FirefoxOS device.<br />[[File:= Current Cloud Storage Support OverviewUser Scenario =In android or iOS, viewing a media file on cloud, it has following possible ways.png|550px]]<br />Cloud Storage framework wants to support following features* '''Universal Storage API'''Universal Storage API is a general API for web apps to access all kinds of cloud storage1. * '''Virtual Storage Interface'''Virtual Storage Interface is plugin system for Using one viewing app and one cloud storage framework to extend cloud storage optionapp= Planning Phases =[[File:PlanningPhasesIt needs following steps.png|thumbnail|Planning Phases|500px]]<br/>* '''Phase 1'''** We will implement a read-only storage for # Using the ready-made cloud app to read download the data via Device Storage APImedia file to device. For example, Video # Using the viewing app can play a video in Dropbox even to open the downloaded media file size is larger than internal storage without any app modification.* '''Phase 2'''** Each user might have more than one storage account:In this way, so multi-storage support is an important feature for user to manipulate their storage more flexiblemust download the whole media file first. Download brings following drawbacks.<br/>:** Second, offline Support is for using storages even there is no network available (, and we can leverage Cache mechanism to implement this featureFile duplication.)** From :File occupies the perspective of local storage. If device local storage provideris almost full, Flexible Storage Module is an easy way user might need to install or update cleanup the local storage plugin for 3rd party storage provider like Dropbox, Box.net, etcfirst.<br/> :** Multi Storage support will be handled by Account management. 3rd-party Storage plugin and Virtual Storage Interface are Need to download the key components to implement Flexible Storage Modulewhole file before viewing.* '''Phase 3'''** Read-Write support, just like its literal meaning, :Some files can might be read or written. Read-Write feature is our last mile not suitable to achieve our final destinationbe downloaded, and Sync Mechanism should handle all possible conflict when any file is changed from different clientsfor example 4k video files.<br/>  = Cloud Storage Framework === Overall Architecture ==[[File:OverallArchitecture.png|thumbnail|Overall Architecture|500px]]<br/>Based on 2. Using a viewing app which support the planning phases, this is an overall architecture of Cloud Storage includes Gecko part and Gaia partspecified cloud accessing. It needs following steps.<br/>* Cloud Storage Configuration UI is for # 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 enable/disable support the user preferred cloud storage via storage management API. It could be in Settings Otherwise, user might select another app or any possible wayscloud they don't want.<br/><br/>In this project, we want to support user* Gaia <b>Choose their preferred apps can use Device Storage API and cloud in free.</b>* <b>No need to access save the files whole file in local.</b>= Cloud StorageSupport 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, just like Video appFirefoxOS becomes a proxy for apps to access user's cloud, Music app such that apps needn't know how to access cloud data in special way and Gallery app didmaintain cloud by themselves. EventuallyOn the other hand, we have FirefoxOS can support streaming access to extend Device Storage API for Cloud Storage, like getting avoid downloading the synchronisation status of a whole fileinto local storage.<br/>* 3rd party storage provider Instead of accessing cloud directly in Gecko, we design FileSystemProvider API to provide apps/addons can implement a new plugin for users to manipulate their storage via Virtual Storage Interface. The interface is for storage provider to define how create a virtual file is accessed including getting meta datasystem in Gaia, file content reading and writingaccessing cloud in these apps/addons.According to this design, we can gain following benefits<br/>* Cache mechanism, sync mechanism, and account management are the modules No need to maintain third party cloud APIs in gecko Gecko.:It means FirefoxOS no need to be hidden, so app developers don’t have FOTA to support the third party cloud APIs upgrade. It only needs to worry about update the issues like how corresponding Cloud Storage Addons.<br/>* Easy to resolve reuse the conflict issueframework on other kinds of storage.:Not only cloud storage, data caching for performancebut also NFS, personal NAS can reuse this framework to plug into FirefoxOS Volume System, etcsuch that apps can also interact with these storage directly.<br/>== Universal Storage API FirefoxOS Volume System ==Universal Storage API FirefoxOS Volume System is a general API for web apps 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 access all kinds of storagethe basic volume operations, the Volume System also provides fake volume creation and deletion mechanism.<br />According to different purposesIn this framework, we creates fake volumes for each connected cloud, Universal Storage API therefore these connected cloud can be separated into following two categories* '''Document based recognized, identified and accessed by apps through DeviceStorage API'''Document based and File API is used to help web apps save.<br/operate their application data, such as indexedDB, on the cloud storage.>* '''Filesystem based == DeviceStorage API and File API'''==Filesystem based DeviceStorage API supports web and File API are interface used by apps to access cloud storage with filesystem operations, such as FirefoxOS file systems. Apps can use these APIs to perform file create, delete, open, read, write, closecreation, etcand deletion.<br />Reference for Filesystem based API: Here are more detail about [httphttps://wwwdeveloper.w3mozilla.org/TRen-US/file-system-apidocs/Mozilla/Firefox_OS/API/ W3C FileAPIDevice_Storage_API DeviceStorage API]and [https://githubdeveloper.mozilla.comorg/en-US/filerjsdocs/filer#providers filerWeb/API/File File API][[WebAPI<br/DeviceStorageAPI|DeviceStorageAPI]]>== Virtual Storage Interface ==Virtual Storage Interface is plugin system for cloud storage In this framework , we let apps still use these APIs to cooperate with different access cloud storagedata== Cache Architecture ===== Background ===* '''Improve performance'''** The response time of each file operation should be as short as possible to provide better It means apps can access user experience when users want to view a photo, listen an audio, or watch a video.* '''Offline Support'''** Cache store is a subset of s cloud without any modification which just like they access the device local storage, so Cache system still can provide cached file content from cache store even no network connection available.<br/>=== Architecture =FileSystemProvider API ==[[File:CacheArchitecture.png|thumbnail|Cache Architecture|500px]]* '''Cache Manager'''** Block-based data management** Dispatch low-level file operation from FUSE FileSystemProvider API provides apps/addons capability to Data/Meta Cache first** Get data from Web Storage Manager if there is no data existed in Cache.* '''Meta Cache'''** Metadata for each create virtual file (mdate, cdate, size, etc.) should be cached systems in memory or Indexed DBGaia.It provides<br/>* '''Data Cache'''** Data Cache should store a file content requested by user for each file in order Methods to avoid extra network transaction.* '''Web Storage Manager'''** Provide an interface for each web storage provider (Dropbox, Box.net, etc) request Volume System to communicate with Cache Managercreate/delete a fake volume.** 3rd party plugin could be in the form of add-on for developer to support new web storage easily.* '''Cache Policy'''** Cache store entry can be flexible Events and callbacks 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.** Cache policy is a set of method to prefetch data from virtual file content or meta aggressively, so the response time for each request can be improvedsystems created by apps/addons. === Data Cache Implement Proposal Types === * File-based Cache:<b>OpenFileMode</b><br/>** minimum data chunk - File* Block-based Cache** minimum data chunk - Block (with fixed-size)** File System level operation can be mapped to cloud storage::Mode for open a file.<br/>::{| class="wikitable"style="width:100%"| style="background:#abc2e0" | <b>Enum</b>
|-
! | <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 || Filesize 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.|-based !! Block| colspan="2" style="background:#abc2e0" | <b>Return value</b>|-based| colspan="2" | void
|-
| Cross Platform/Browser rowspan="5" |function | Yes |colspan="2" | TBD..errorCallback || rowspan="5" valign="top" | Error callback for writefilerequested event.
|-
| Response Time for large-size filecolspan="2" style="background:#abc2e0" | <b>Parameter<br /b>(ex: video) || poor || good
|-
| Response Time for small-size file<br />(ex: photo, audio) FileSystemProviderError || good || good<br />(depends on block-size)errorCode
|-
| Implementation Idea || Gaiacolspan="2" style="background: JS Library (Filer) #abc2e0" || Gaia: TBD...<br b>Return value</b>Gecko: FUSE
|-
| Related Web API colspan="2" || Blob, MSE(?), ... || Blob, Device Storage, ...void
|}
 Reference* [https://docs.google.com/presentation/d/1gB41Z6uQQO9C51Ns2aAm2A7vJox0AYt5tz2vyDC0xuo/edit#slide=id.p Cache Architecture study] == Proposed Solution(s) ===== FUSE based solution =Cloud Storage Addons ==Mounting Cloud Storage to device filesystem through Addons are in charge of the communication with the FUSE mechanismtarget cloud.It should provides at least<br />[[File:* User authentication and authorization mechanism* Cloud access operations through the public APIs from cloud providers Moreover, Cloud Storage FUSE solution.png|550px]]Addons might provide more features, such as<br />* Data catch* Data Synchronization* Account management=Usage Flow === Benefits ==Mounting a Cloud on FirefoxOS ==* DeviceStorageAPI provides well defined filesystem based To mount a cloud on FirefoxOS, FileSystemProvider API to access files/directories on internal storage providers methods and SD cardevents for Cloud Storage Addons. Once FUSE based solution supported, Web app can used DeviceStorageAPI directly to access <br/>The picture shows the flow that Cloud Storage Addon mounts a cloud storage without any modification"MyCloud" on FirefoxOS through FileSystemProvider API.<br/>* FUSE interface is a good reference for Virtual # Cloud Storage Interfaceaddon registers the event listener on FileSystemProviderEvents.# Call FileSystemProvider. By propagating FUSE interface mount() method with parameters to FirefoxOS, FirefoxOS can easy connect request Volume System to many kinds of storage, such as cloud storage, NAS, etccreate a fake volume. [http://en.wikipedia.org/wiki/ExpanDrive Here Following is an commercial example].==== Drawbacks ====* DeviceStorageAPI is not code to mount a standard API for all browser.cloud "MyCloud"<br/>* FUSE is not supported // Code in all platforms.Cloud Storage Addons var fileSystemProvider ==== Prototype ====navigator.fileSystemProvider;* [https: //githubEvent handler definition function GetMetadataHandler(event) { var path = event.comoptions.entryPath; //MozCloudStorage MozCloudStorage github repo]get metadata through cloud APIs with entry path* CloudStorageServiceAPI if (this is only for prototypemetadata){CloudStorageServiceAPI is a WebAPI for enabling/disabling cloud storage event. <br />successCallback(metadata);enum CloudStorageType } else { event.errorCallback('NotFound'); } } ... // Register event listener on FileSystemProviderEvents fileSystemProvider.addEventListener("Dummygetmetadatarequested",GetMetadataHandler); fileSystemProvider.addEventListener("Dropboxopenfilerequested",OpenFileHandler);} fileSystemProvider.addEventListener("closefilerequested", CloseFileHandler); <br />Promise<boolean> enable fileSystemProvider.addEventListener(DOMString cloudName"readdirectoryrequested", CloudStorageType cloudType, DOMString accessTokenReadDirectoryHandler)<br />;Promise<void> disable fileSystemProvider.addEventListener(DOMString cloudName"readfilerequested", ReadFileHandler)<br />;=== JS library solution === ...==== Benefits ==== // Call mount method to create fake volume "MyCloud" in FirefoxOS==== Drawbacks ====== Framework Issues == * fileSystemProvider.mount({fileSystemId: 'MyCloud', displayName: 'Cloud Storage Account management and Authentication''MyCloud', writable: true,* '''Security issues''' openedFilesLimit: 256})=== Issue Study === .then(* function() { dump('mount successfully\n');} function(aError) { dump('Video Support with MSEmount failed ['+aError+']\n');}** [https://w3c.github.io/media-source/ Media Source Extensions]** The challenge with HTML5 audio and video is still the fragmented support for audio and video formats.** In Firefox browser, the maximum size of each fragment is 75MB. Getting QuotaExceededError if the fragment size is over 75MB.** Fragmented Video Format - the video MUST be in fragmented format, and this video can be played well.** 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. );= Related Use cases === Play media files saved on cloud Accessing Cloud through the Framework ==John saves his media files on dropbox or any other To access a mounted cloud storage and wants to play these media online on his mobile device.<br />In traditional, John needs to do with following steps<br />#Open the cloud storage app, such as dropbox can reuse DeviceStorage and google driveFile APIs, and download the media files to the mobile devicejust like they access local storage.<br />#Open The picture shows the player app, such as flow how Gallery and Music, and play the media files locally.<br />On FirefoxOS device, the steps can be reduced to<br />#Open the player app and play read the media files on cloud storage directly"test== Create and share files jpg" on cloud ==Bob wants to take a picture and share it with friend on flickr"MyCloud".<br />In traditional, Bob needs to do with following steps<br />#Open the camera Gallery app to take a picture and save the file on the deviceasks "MyCloud/test.<br />#(Optional) Open a third party app to edit jpg" data through the picture on the deviceFile API.<br />#Open Volume System get the flickr app request and send FileSystemProvderReadFileEvent to ask corresponding Cloud Storage Addons to upload get the file and set it as shareddata from cloud.<br />On FirefoxOS device, the steps can be reduced to<br />#Open Cloud Storage Addon receives the camera app FileSystemProviderReadFileEvent and call ReadFileEventListener to take a picture and save and share get "test.jpg" data from cloud through the file on cloud storage directlyaccess API.<br />#(Optional) Open a third party app to edit Once read success or fail, call the picture on cloud storage directlyevent.successCallback with data or event.<br /> == File management between clouds ==Amy wants to copy a finished work document form her personal dropbox space to the company google drive space<br />In traditional, Amy needs to do errorCallback with following steps<br />error code.#Open Volume System receives the dropbox app callback data and download the document file send it back to device.#Open the google drive app and upload through the document fileFile API.<br />On FirefoxOS device, the steps can be reduced Following is an example to<br />#Open a file browser app access cloud 'MyCloud' through DeviceStorage and copy the document from dropbox to google drive directlyFile APIs= Related links =* [[Firefox_Cloud]]<br />* [[Webmaker /MakeDrive|MakeDrive]]<br />Get file through DeviceStorage API* [http://fuse var myStorage = navigator.sourceforge.net/ FUSEgetDeviceStorage(filesystem in userspace'MyCloud')]<br />;= Previous works = if (myStorage) {* https: //githubRequest to send GetMetadataEvent to get the information of "myFile.com/weilonge/unidisktxt"* http://weilonge var request = myStorage.bitbucketget('myFile.org/unidisk/UDtxt'); request.pdfonsuccess = function() { var file = Related Bugzilla this.result; dump(file.name+'\n'); var fileReader =new FileReader();* [https://bugzilla.mozilla.org/show_bug fileRead.cgi?idonloadend =1035053 Bug 1035053 - [Device Storage<nowiki>]</nowiki> To Support Variant Cloud Storage]function() {dump('load finished\n');}* [https: //bugzillaRequest to send OpenFileEvent, ReadFileEvents and CloseFileEvent fileReader.mozilla.org/show_bug.cgi?id=1164750 Bug 1164750 - [Meta<nowiki>]</nowiki> Cloud storage support in FirefoxOS FUSE based prototyping]readAsArrayBuffer(file); } }
33
edits

Navigation menu