// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-'use strict';
-
// If directory files changes too often, don't rescan directory more than once
// per specified interval
var SIMULTANEOUS_RESCAN_INTERVAL = 500;
* @param {MetadataCache} metadataCache The metadata cache service.
* @param {VolumeManagerWrapper} volumeManager The volume manager.
* @constructor
+ * @extends {cr.EventTarget}
*/
function DirectoryModel(singleSelection, fileFilter, fileWatcher,
metadataCache, volumeManager) {
DirectoryModel.prototype.onWatcherDirectoryChanged_ = function(event) {
var directoryEntry = this.getCurrentDirEntry();
+ // If the change is deletion of currentDir, move up to its parent directory.
+ directoryEntry.getDirectory(directoryEntry.fullPath, {create: false},
+ function() {},
+ function() {
+ var volumeInfo = this.volumeManager_.getVolumeInfo(directoryEntry);
+ if (volumeInfo) {
+ volumeInfo.resolveDisplayRoot().then(function(displayRoot) {
+ this.changeDirectoryEntry(displayRoot);
+ }.bind(this));
+ }
+ }.bind(this));
+
if (event.changedFiles) {
var addedOrUpdatedFileUrls = [];
var deletedFileUrls = [];
*/
DirectoryModel.prototype.getLeadEntry_ = function() {
var index = this.fileListSelection_.leadIndex;
- return index >= 0 && this.getFileList().item(index);
+ return index >= 0 ?
+ /** @type {Entry} */ (this.getFileList().item(index)) : null;
};
/**
DirectoryModel.prototype.setLeadEntry_ = function(value) {
var fileList = this.getFileList();
for (var i = 0; i < fileList.length; i++) {
- if (util.isSameEntry(fileList.item(i), value)) {
+ if (util.isSameEntry(/** @type {Entry} */ (fileList.item(i)), value)) {
this.fileListSelection_.leadIndex = i;
return;
}
*
* This should be used when changing directory or initiating a new search.
*
- * @param {DirectoryContentes} newDirContents New DirectoryContents instance to
+ * @param {DirectoryContents} newDirContents New DirectoryContents instance to
* replace currentDirContents_.
* @param {function(boolean)} callback Callback with result. True if the scan
* is completed successfully, false if the scan is failed.
DirectoryModel.prototype.findIndexByEntry_ = function(entry) {
var fileList = this.getFileList();
for (var i = 0; i < fileList.length; i++) {
- if (util.isSameEntry(fileList.item(i), entry))
+ if (util.isSameEntry(/** @type {Entry} */ (fileList.item(i)), entry))
return i;
}
return -1;
if (util.isSameEntry(oldEntry, this.getCurrentDirEntry()))
this.changeDirectoryEntry(newEntry);
- // Replace the old item with the new item.
- // If the entry doesn't exist in the list, it has been updated from
- // outside (probably by directory rescan) and is just ignored.
- this.getFileList().replaceItem(oldEntry, newEntry);
+ // Replace the old item with the new item. oldEntry instance itself may
+ // have been removed/replaced from the list during the async process, we
+ // find an entry which should be replaced by checking toURL().
+ var list = this.getFileList();
+ var oldEntryExist = false;
+ var newEntryExist = false;
+ var oldEntryUrl = oldEntry.toURL();
+ var newEntryUrl = newEntry.toURL();
+
+ for (var i = 0; i < list.length; i++) {
+ var item = list.item(i);
+ var url = item.toURL();
+ if (url === oldEntryUrl) {
+ list.replaceItem(item, newEntry);
+ oldEntryExist = true;
+ break;
+ }
+
+ if (url === newEntryUrl) {
+ newEntryExist = true;
+ }
+ }
+
+ // When both old and new entries don't exist, it may be in the middle of
+ // update process. In DirectoryContent.update deletion is executed at first
+ // and insertion is executed as a async call. There is a chance that this
+ // method is called in the middle of update process.
+ if (!oldEntryExist && !newEntryExist)
+ list.push(newEntry);
// Run callback, finally.
if (opt_callback)
*
* @param {string} name Directory name.
* @param {function(DirectoryEntry)} successCallback Callback on success.
- * @param {function(FileError)} errorCallback Callback on failure.
+ * @param {function(DOMError)} errorCallback Callback on failure.
* @param {function()} abortCallback Callback on abort (cancelled by user).
*/
DirectoryModel.prototype.createDirectory = function(name,
successCallback(newEntry);
}
}.bind(this), function(reason) {
- errorCallback(reason);
+ errorCallback(/** @type {DOMError} */ (reason));
});
};
// Notify that the current task of this.directoryChangeQueue_
// is completed.
- setTimeout(queueTaskCallback);
+ setTimeout(queueTaskCallback, 0);
});
// For tests that open the dialog to empty directories, everything
};
/**
- * @param {Array.<string>} entries Array of entries.
+ * @param {Array.<Entry>} entries Array of entries.
*/
DirectoryModel.prototype.selectEntries = function(entries) {
// URLs are needed here, since we are comparing Entries by URLs.
this.changeDirectoryEntry(displayRoot);
}.bind(this));
}
+
+ // If a new provided volume is mounted, then redirect to it in the focused
+ // window. Note, that this is a temporary solution for crbug.com/427776.
+ if (window.isFocused() &&
+ event.added.length === 1 &&
+ event.added[0].volumeType === VolumeManagerCommon.VolumeType.PROVIDED) {
+ event.added[0].resolveDisplayRoot().then(function(displayRoot) {
+ // Resolving a display root on FSP volumes is instant, despite the
+ // asynchronous call.
+ this.changeDirectoryEntry(event.added[0].displayRoot);
+ }.bind(this));
+ }
};
/**