Chromium Code Reviews| 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..a0aef7151b624b184db1c85df1e52fe62741c044 |
| --- /dev/null |
| +++ b/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/background.js |
| @@ -0,0 +1,241 @@ |
| +// 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'; |
| + |
| +// For file examples with metadata inside, see example1.fake and example2.fake. |
|
mtomasz
2014/06/30 08:30:30
... -> Metadata is stored in files as serialized t
cmihail
2014/07/01 00:07:05
Done.
|
| + |
| +// Multiple volumes can be opened at the same time. The key is the |
| +// fileSystemId, which is the same as the file entry.name. The value |
|
mtomasz
2014/06/30 08:30:31
file -> file's
cmihail
2014/07/01 00:07:05
Done.
|
| +// is a Volume object. |
| +var volumes = {}; |
| + |
| +// Defines a volume object that contains information about mounted devices. |
| +// openedFiles parameter is optional and can be undefined. |
| +function Volume(entry, mount, metadata, openedFiles) { |
|
mtomasz
2014/06/30 08:30:31
openedFiles -> opt_openedFiles
cmihail
2014/07/01 00:07:05
Done.
|
| + // Used for restoring file entry. |
|
mtomasz
2014/06/30 08:30:30
... -> Used for restoring the opened file entry af
cmihail
2014/07/01 00:07:05
Done.
|
| + this.entry_ = entry; |
| + |
| + // The volume metadata. |
|
mtomasz
2014/06/30 08:30:31
Let's add a comment:
Date object is serialized in
cmihail
2014/07/01 00:07:05
Done.
|
| + for (var item in metadata) { |
|
mtomasz
2014/06/30 08:30:31
I think it is better not to modify input arguments
cmihail
2014/07/01 00:07:05
Done.
|
| + metadata[item].modificationTime = |
| + new Date(metadata[item].modificationTime); |
| + } |
| + this.metadata_ = metadata; |
| + |
| + // A map with currently opened files. As key it has requestId of |
| + // openFileRequested and as a value the file path. |
| + this.openedFiles_ = openedFiles ? openedFiles : {}; |
| + |
| + // Mount device and save device information on local storage in order to be |
|
mtomasz
2014/06/30 08:30:31
Mount device -> Mount the volume and save its info
cmihail
2014/07/01 00:07:05
Done.
|
| + // able to recover metadata in case of restarts, system crashes, etc. |
| + if (mount) { |
| + chrome.fileSystemProvider.mount( |
| + {fileSystemId: entry.name, displayName: entry.name}, |
| + function() { saveState(); }, |
| + function() { console.error('Failed to mount.'); }); |
| + |
| + } |
| +}; |
| + |
| +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; |
|
mtomasz
2014/06/30 08:30:31
nit: metadata_ is private here. Let's make it publ
cmihail
2014/07/01 00:07:05
Done. Also modified the other variables.
|
| + |
| + // 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 restart, extension suspend, crashes, etc. |
|
mtomasz
2014/06/30 08:30:30
nit: restart -> restarts
nit: extension suspend ->
cmihail
2014/07/01 00:07:05
Done.
|
| +function saveState() { |
| + var state = {}; |
| + for (var volumeId in volumes) { |
| + var entryId = chrome.fileSystem.retainEntry(volumes[volumeId].entry_); |
|
cmihail
2014/06/30 08:01:44
As a mention: retainEntry executes quite often. I
mtomasz
2014/06/30 13:35:32
That's a good point. I took a look at the C++ code
|
| + 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 |
| +// we only need to obtain the metadata, which is done lazily. |
| +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, false /* File system is mounted. */, |
| + onSuccess, onError, result.state[fileSystemId].openedFiles); |
| + }); |
| + }); |
| +} |
| + |
| +// openedFiles is an optional parameter. |
| +function readMetadataFromFile(entry, mount, onSuccess, onError, openedFiles) { |
|
mtomasz
2014/06/30 08:30:30
readMetadataFromFile shouldn't need |openedFiles|.
cmihail
2014/07/01 00:07:05
Done.
|
| + entry.file(function(file) { |
| + var fileReader = new FileReader(); |
| + fileReader.onload = function(event) { |
| + var metadata = JSON.parse(event.target.result); |
| + volumes[entry.name] = new Volume(entry, mount, metadata, openedFiles); |
| + onSuccess(); |
| + }; |
| + |
| + fileReader.onerror = function(event) { |
| + onError('FAILED'); |
| + }; |
| + |
| + fileReader.readAsText(file); |
| + }); |
| +} |
| + |
| +// Event called on clicking the file with the extension mentioned |
| +// in the manifest file. |
|
mtomasz
2014/06/30 08:30:30
Not only file extension, but also if mime type is
cmihail
2014/07/01 00:07:06
Done.
|
| +chrome.app.runtime.onLaunched.addListener(function(event) { |
| + event.items.forEach(function(item) { |
| + readMetadataFromFile(item.entry, true /* Mount file system. */, |
| + function() {}, |
| + function(error) { console.error(error); } ); |
| + }); |
| +}); |
| + |
| +// Event called on chromeos startup. |
|
mtomasz
2014/06/30 08:30:31
... -> Event called on a profile startup.
cmihail
2014/07/01 00:07:05
Done.
|
| +chrome.runtime.onStartup.addListener(function () { |
| + chrome.storage.local.get(['state'], function(result) { |
| + // Nothing to change. |
| + if (!result.state) |
| + return; |
| + |
| + // Remove opened files from state. The file entry restore |
|
mtomasz
2014/06/30 08:30:31
I think we could clarify it a little bit, eg.:
...
cmihail
2014/07/01 00:07:05
Done. I added local storage state. It seems a bit
|
| + // will be done by the restoreState function. |
| + for (var volumeId in result.state) { |
| + result.state[volumeId].openedFiles = {}; |
| + } |
| + chrome.storage.local.set({state: result.state}); |
| + }); |
| +}); |
| + |
| +// Event called when the extension is idle for about 10+ seconds and it will |
|
mtomasz
2014/06/30 08:30:31
I think we can remove this comment. The idling per
cmihail
2014/07/01 00:07:05
That sounds good to me.
|
| +// get killed to free resources. The extension state should be saved. |
| +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); |