[go: nahoru, domu]

blob: 3e58a77bda9f876dff898a00b10076dd3e8040ff [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Custom binding for the fileBrowserHandler API.
const fileBrowserNatives = requireNative('file_browser_handler');
const fileSystemHelpers = requireNative('file_system_natives');
const entryIdManager = require('entryIdManager');
const GetExternalFileEntry = fileBrowserNatives.GetExternalFileEntry;
const GetIsolatedFileSystem = fileSystemHelpers.GetIsolatedFileSystem;
/**
* Adapter to get a FileEntry or DirectoryEntry from |item| passed from API
* callback, via calls to GetExternalFileEntry() or get{Directory,File}().
* Ideally we'd use Promise.allSettled() to process multiple files, but since
* $Promise.allSettled() does not exist, so callbacks are used instead.
* @param {function(!Entry): void} resolve Receiver for resulting Entry.
* @param {function(string): void} reject Receiver for error message.
* @param {boolean} canCreate For getFile() flow only: Whether to grant
* permission to create file if it's missing. Side effect: The file gets
* created if missing.
* @param {!Object} item Key-value pair passed from API callback, containing
* data for GetExternalFileEntry() or get{Directory,File}() flows.
*/
function GetFileEntry(resolve, reject, canCreate, item) {
if (item.hasOwnProperty('fileSystemName')) {
// Legacy flow for Ash. Errors (such as nonexistent file) are not detected
// here. These only arise downstream when the resulting Entry gets used.
resolve(GetExternalFileEntry(item));
} else if (item.hasOwnProperty('fileSystemId')) {
// New flow for Lacros. Some errors (such as nonexistent file) are detected
// here, and require handling.
const fs = GetIsolatedFileSystem(item.fileSystemId);
if (item.isDirectory) {
fs.root.getDirectory(item.baseName, {}, (dirEntry) => {
entryIdManager.registerEntry(item.entryId, dirEntry);
resolve(dirEntry);
}, (err) => {
reject(err.message);
});
} else {
fs.root.getFile(
item.baseName, canCreate ? {create: true} : {},
(fileEntry) => {
entryIdManager.registerEntry(item.entryId, fileEntry);
resolve(fileEntry);
},
(err) => {
reject(err.message);
});
}
} else {
reject('Unknown file entry object.');
}
}
bindingUtil.registerEventArgumentMassager('fileBrowserHandler.onExecute',
function(args, dispatch) {
if (args.length < 2) {
dispatch(args);
return;
}
// The second param for this event's payload is file definition dictionary.
const fileList = args[1].entries;
if (!fileList) {
dispatch(args);
return;
}
// Construct File API's Entry instances. $Promise.allSettled() is unavailable,
// so use a |barrier| counter and explicitly sort results.
const results = [];
let barrier = fileList.length;
const onFinish = () => {
results.sort((a, b) => a.key - b.key);
args[1].entries = $Array.map(results, item => item.entry);
dispatch(args);
};
const onResolve = (index, entry) => {
results.push({key: index, entry});
if (--barrier === 0) onFinish();
};
const onReject = (message) => {
console.error(message);
if (--barrier === 0) onFinish();
};
for (let i = 0; i < fileList.length; ++i) {
GetFileEntry(
onResolve.bind(null, i), onReject,
/*canCreate*/ false, /*item*/ fileList[i]);
}
});