Index: chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/background.js |
diff --git a/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/background.js b/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/background.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..333172bbc2d810b756ab3bc468dc5fc932896f20 |
--- /dev/null |
+++ b/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/background.js |
@@ -0,0 +1,245 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+'use strict'; |
+ |
+// Metadata is stored in files as serialized to JSON maps. See contents of |
+// example1.fake and example2.fake. |
+ |
+// Multiple volumes can be opened at the same time. The key is the |
+// fileSystemId, which is the same as the file's entry.name. |
+// The value is a Volume object. |
+var volumes = {}; |
+ |
+// Defines a volume object that contains information about mounted devices. |
mtomasz
2014/07/01 00:40:33
nit: about mounted devices -> about a mounted file
cmihail
2014/07/01 01:27:20
Done.
|
+function Volume(entry, metadata, opt_openedFiles) { |
+ // Used for restoring the opened file entry after resuming the event page. |
+ this.entry = entry; |
+ |
+ // The volume metadata. Date object is serialized in JSON as string. |
mtomasz
2014/07/01 00:40:33
nit: I think the second comment is confusing in th
cmihail
2014/07/01 01:27:21
Done.
|
+ this.metadata = []; |
+ for (var path in metadata) { |
+ this.metadata[path] = metadata[path]; |
+ this.metadata[path].modificationTime = |
+ new Date(metadata[path].modificationTime); |
+ } |
+ |
+ // A map with currently opened files. As key it has requestId of |
mtomasz
2014/07/01 00:40:32
nit: As key it has requestId... -> The key is a re
cmihail
2014/07/01 01:27:21
Done.
|
+ // openFileRequested and as a value the file path. |
+ this.openedFiles = opt_openedFiles ? opt_openedFiles : {}; |
+}; |
+ |
+function onUnmountRequested(options, onSuccess, onError) { |
+ if (Object.keys(volumes[options.fileSystemId].openedFiles).length != 0) { |
+ onError('IN_USE'); |
+ return; |
+ } |
+ |
+ chrome.fileSystemProvider.unmount( |
+ {fileSystemId: options.fileSystemId}, |
+ function() { |
+ delete volumes[options.fileSystemId]; |
+ saveState(); // Remove volume from local storage state. |
+ onSuccess(); |
+ }, |
+ function() { |
+ onError('FAILED'); |
+ }); |
+}; |
+ |
+function onGetMetadataRequested(options, onSuccess, onError) { |
+ restoreState(options.fileSystemId, function () { |
+ var entryMetadata = |
+ volumes[options.fileSystemId].metadata[options.entryPath]; |
+ if (!entryMetadata) |
+ error('NOT_FOUND'); |
+ else |
+ onSuccess(entryMetadata); |
+ }, onError); |
+}; |
+ |
+function onReadDirectoryRequested(options, onSuccess, onError) { |
+ restoreState(options.fileSystemId, function () { |
+ var directoryMetadata = |
+ volumes[options.fileSystemId].metadata[options.directoryPath]; |
+ if (!directoryMetadata) { |
+ onError('NOT_FOUND'); |
+ return; |
+ } |
+ if (!directoryMetadata.isDirectory) { |
+ onError('NOT_A_DIRECTORY'); |
+ return; |
+ } |
+ |
+ // Retrieve directory contents from metadata. |
+ var entries = []; |
+ for (var entry in volumes[options.fileSystemId].metadata) { |
+ // Do not add itself on the list. |
+ if (entry == options.directoryPath) |
+ continue; |
+ // Check if the entry is a child of the requested directory. |
+ if (entry.indexOf(options.directoryPath) != 0) |
+ continue; |
+ // Restrict to direct children only. |
+ if (entry.substring(options.directoryPath.length + 1).indexOf('/') != -1) |
+ continue; |
+ |
+ entries.push(volumes[options.fileSystemId].metadata[entry]); |
+ } |
+ onSuccess(entries, false /* Last call. */); |
+ }, onError); |
+}; |
+ |
+function onOpenFileRequested(options, onSuccess, onError) { |
+ restoreState(options.fileSystemId, function () { |
+ if (options.mode != 'READ' || options.create) { |
+ onError('INVALID_OPERATION'); |
+ } else { |
+ volumes[options.fileSystemId].openedFiles[options.requestId] = |
+ options.filePath; |
+ onSuccess(); |
+ } |
+ }, onError); |
+}; |
+ |
+function onCloseFileRequested(options, onSuccess, onError) { |
+ restoreState(options.fileSystemId, function () { |
+ if (!volumes[options.fileSystemId].openedFiles[options.openRequestId]) { |
+ onError('INVALID_OPERATION'); |
+ } else { |
+ delete volumes[options.fileSystemId].openedFiles[options.openRequestId]; |
+ onSuccess(); |
+ } |
+ }, onError); |
+}; |
+ |
+function onReadFileRequested(options, onSuccess, onError) { |
+ restoreState(options.fileSystemId, function () { |
+ var filePath = |
+ volumes[options.fileSystemId].openedFiles[options.openRequestId]; |
+ if (!filePath) { |
+ onError('INVALID_OPERATION'); |
+ return; |
+ } |
+ |
+ var contents = volumes[options.fileSystemId].metadata[filePath].contents; |
+ |
+ // Write the contents as ASCII text. |
+ var buffer = new ArrayBuffer(options.length); |
+ var bufferView = new Uint8Array(buffer); |
+ for (var i = 0; i < options.length; i++) { |
+ bufferView[i] = contents.charCodeAt(i); |
+ } |
+ |
+ onSuccess(buffer, false /* Last call. */); |
+ }, onError); |
+}; |
+ |
+// Save state in case of restarts, event page suspend, crashes, etc. |
mtomasz
2014/07/01 00:40:32
nit: Save -> Saves
cmihail
2014/07/01 01:27:21
Done.
|
+function saveState() { |
+ var state = {}; |
+ for (var volumeId in volumes) { |
+ var entryId = chrome.fileSystem.retainEntry(volumes[volumeId].entry); |
+ state[volumeId] = { |
+ entryId: entryId, |
+ openedFiles: volumes[volumeId].openedFiles |
+ }; |
+ } |
+ chrome.storage.local.set({state: state}); |
+} |
+ |
+// Restore state. In this case the file system is already mounted and |
mtomasz
2014/07/01 00:40:32
nit: Restore -> Restores. Comments for methods sho
cmihail
2014/07/01 01:27:22
Done.
|
+// we only need to obtain the metadata, which is done lazily. |
mtomasz
2014/07/01 00:40:33
The comment about remounting is confusing. How abo
cmihail
2014/07/01 01:27:21
Done.
|
+function restoreState(fileSystemId, onSuccess, onError) { |
+ chrome.storage.local.get(['state'], function(result) { |
+ // Check if metadata for the given file system is alread in memory. |
+ if (volumes[fileSystemId]) { |
+ onSuccess(); |
+ return; |
+ } |
+ |
+ chrome.fileSystem.restoreEntry( |
+ result.state[fileSystemId].entryId, |
+ function(entry) { |
+ readMetadataFromFile(entry, |
+ function(metadata) { |
+ volumes[fileSystemId] = new Volume(entry, metadata, |
+ result.state[fileSystemId].openedFiles); |
+ onSuccess(); |
+ }, onError); |
+ }); |
+ }); |
+} |
+ |
+// onSuccess has as parameter the metadata read in JSON format. |
mtomasz
2014/07/01 00:40:33
The returned metadata is already deserialized, so
cmihail
2014/07/01 01:27:21
Yes. I wasn't clear. I was referring to the fact t
|
+function readMetadataFromFile(entry, onSuccess, onError) { |
+ entry.file(function(file) { |
+ var fileReader = new FileReader(); |
+ fileReader.onload = function(event) { |
+ onSuccess(JSON.parse(event.target.result)); |
+ }; |
+ |
+ fileReader.onerror = function(event) { |
+ onError('FAILED'); |
+ }; |
+ |
+ fileReader.readAsText(file); |
+ }); |
+} |
+ |
+// Event called on clicking the file with the extension or mime type |
+// mentioned in the manifest file. |
mtomasz
2014/07/01 00:40:32
nit: clicking on the file -> opening the file
nit:
cmihail
2014/07/01 01:27:21
Done.
|
+chrome.app.runtime.onLaunched.addListener(function(event) { |
+ event.items.forEach(function(item) { |
+ readMetadataFromFile(item.entry, |
+ function(metadata) { |
+ // Mount the volume and save its information in local storage |
+ // in order to be able to recover the metadata in case of |
+ // restarts, system crashes, etc. |
+ volumes[item.entry.name] = new Volume(item.entry, metadata); |
+ chrome.fileSystemProvider.mount( |
+ {fileSystemId: item.entry.name, displayName: item.entry.name}, |
mtomasz
2014/07/01 00:40:33
This may fail when two files with the same name ar
cmihail
2014/07/01 01:27:20
Done. For displayName I have kept item.entry.name
|
+ function() { saveState(); }, |
+ function() { console.error('Failed to mount.'); }); |
+ }, |
+ function(error) { |
+ console.error(error); |
+ }); |
+ }); |
+}); |
+ |
+// Event called on a profile startup. |
+chrome.runtime.onStartup.addListener(function () { |
+ chrome.storage.local.get(['state'], function(result) { |
+ // Nothing to change. |
+ if (!result.state) |
+ return; |
+ |
+ // Remove files opened before the profile shutdown from the local |
+ // storage state. |
mtomasz
2014/07/01 00:40:32
nit: local storage state -> local storage.
cmihail
2014/07/01 01:27:21
Done.
|
+ for (var volumeId in result.state) { |
+ result.state[volumeId].openedFiles = {}; |
+ } |
+ chrome.storage.local.set({state: result.state}); |
+ }); |
+}); |
+ |
+// Save the state before suspending the event page, so we can resume it |
+// once new events arrive. |
+chrome.runtime.onSuspend.addListener(function() { |
+ saveState(); |
+}); |
+ |
+chrome.fileSystemProvider.onUnmountRequested.addListener( |
+ onUnmountRequested); |
+chrome.fileSystemProvider.onGetMetadataRequested.addListener( |
+ onGetMetadataRequested); |
+chrome.fileSystemProvider.onReadDirectoryRequested.addListener( |
+ onReadDirectoryRequested); |
+chrome.fileSystemProvider.onOpenFileRequested.addListener( |
+ onOpenFileRequested); |
+chrome.fileSystemProvider.onCloseFileRequested.addListener( |
+ onCloseFileRequested); |
+chrome.fileSystemProvider.onReadFileRequested.addListener( |
+ onReadFileRequested); |