Index: ui/file_manager/file_manager/foreground/js/import_controller.js |
diff --git a/ui/file_manager/file_manager/foreground/js/import_controller.js b/ui/file_manager/file_manager/foreground/js/import_controller.js |
index 058e2dd4e14c5a244ff58fd9b81aeb9a708e4e5e..93f18dfb58695ae2ddcd1642f5cb28186e72d75d 100644 |
--- a/ui/file_manager/file_manager/foreground/js/import_controller.js |
+++ b/ui/file_manager/file_manager/foreground/js/import_controller.js |
@@ -80,6 +80,9 @@ importer.ImportController = |
this.scanner_.removeObserver(listener); |
}.bind(this)); |
+ this.environment_.addWindowCloseListener( |
+ this.onWindowClosing_.bind(this)); |
+ |
this.environment_.addVolumeUnmountListener( |
this.onVolumeUnmounted_.bind(this)); |
@@ -128,7 +131,7 @@ importer.ImportController.prototype.onScanEvent_ = function(event, scan) { |
switch (event) { |
case importer.ScanEvent.INVALIDATED: |
- this.scanManager_.reset(); |
+ this.onScanInvalidated_(); |
case importer.ScanEvent.FINALIZED: |
case importer.ScanEvent.UPDATED: |
this.checkState_(scan); |
@@ -136,6 +139,11 @@ importer.ImportController.prototype.onScanEvent_ = function(event, scan) { |
} |
}; |
+/** @private */ |
+importer.ImportController.prototype.onWindowClosing_ = function() { |
+ this.scanManager_.reset(); // Will cancel any active scans. |
+}; |
+ |
/** |
* @param {string} volumeId |
* @private |
@@ -160,10 +168,11 @@ importer.ImportController.prototype.onDirectoryChanged_ = function(event) { |
importer.isMediaDirectory(event.newDirEntry, this.environment_)) { |
this.commandWidget_.setDetailsVisible(true); |
} |
- this.scanManager_.clearSelectionScan(); |
+ |
+ this.scanManager_.reset(); |
if (this.isCurrentDirectoryScannable_()) { |
this.checkState_( |
- this.scanManager_.getCurrentDirectoryScan()); |
+ this.scanManager_.getDirectoryScan()); |
} else { |
this.checkState_(); |
} |
@@ -171,6 +180,15 @@ importer.ImportController.prototype.onDirectoryChanged_ = function(event) { |
/** @private */ |
importer.ImportController.prototype.onSelectionChanged_ = function() { |
+ // NOTE: Empty selection changed events can and will fire for a directory |
+ // before we receive the the corresponding directory changed event |
+ // and when the selection is empty. These are spurios events |
+ // and we ignore them. |
+ if (!this.scanManager_.hasSelectionScan() && |
+ this.environment_.getSelection().length === 0) { |
+ return; |
+ } |
+ |
// NOTE: We clear the scan here, but don't immediately initiate |
// a new scan. checkState will attempt to initialize the scan |
// during normal processing. |
@@ -181,7 +199,7 @@ importer.ImportController.prototype.onSelectionChanged_ = function() { |
if (this.environment_.getSelection().length === 0 && |
this.isCurrentDirectoryScannable_()) { |
this.checkState_( |
- this.scanManager_.getCurrentDirectoryScan()); |
+ this.scanManager_.getDirectoryScan()); |
} else { |
this.checkState_(); |
} |
@@ -199,6 +217,18 @@ importer.ImportController.prototype.onImportFinished_ = function(task) { |
this.checkState_(); |
}; |
+/** @private */ |
+importer.ImportController.prototype.onScanInvalidated_ = function() { |
+ this.scanManager_.reset(); |
+ if (this.environment_.getSelection().length === 0 && |
+ this.isCurrentDirectoryScannable_()) { |
+ this.checkState_( |
+ this.scanManager_.getDirectoryScan()); |
+ } else { |
+ this.checkState_(); |
+ } |
+}; |
+ |
/** |
* Does book keeping necessary to finalize the active task. |
* @private |
@@ -282,9 +312,11 @@ importer.ImportController.prototype.execute_ = function() { |
* @private |
*/ |
importer.ImportController.prototype.cancel_ = function() { |
- this.activeImport_.task.requestCancel(); |
- this.finalizeActiveImport_(); |
- this.tracker_.send(metrics.ImportEvents.IMPORT_CANCELLED); |
+ if (this.activeImport_) { |
+ this.activeImport_.task.requestCancel(); |
+ this.finalizeActiveImport_(); |
+ this.tracker_.send(metrics.ImportEvents.IMPORT_CANCELLED); |
+ } |
this.scanManager_.reset(); |
this.checkState_(); |
@@ -411,14 +443,13 @@ importer.ImportController.prototype.fitsInAvailableSpace_ = |
*/ |
importer.ImportController.prototype.tryScan_ = function() { |
var entries = this.environment_.getSelection(); |
- |
if (entries.length) { |
if (entries.every( |
importer.isEligibleEntry.bind(null, this.environment_))) { |
return this.scanManager_.getSelectionScan(entries); |
} |
} else if (this.isCurrentDirectoryScannable_()) { |
- return this.scanManager_.getCurrentDirectoryScan(); |
+ return this.scanManager_.getDirectoryScan(); |
} |
return null; |
@@ -802,40 +833,53 @@ importer.ScanManager = function(environment, scanner) { |
this.scanner_ = scanner; |
/** |
- * A cache of selection scans by directory (url). |
+ * The active files scan, if any. |
* |
* @private {importer.ScanResult} |
*/ |
this.selectionScan_ = null; |
/** |
- * A cache of scans by directory (url). |
+ * The active directory scan, if any. |
* |
- * @private {!Object.<string, !importer.ScanResult>} |
+ * @private {importer.ScanResult} |
*/ |
- this.directoryScans_ = {}; |
+ this.directoryScan_ = null; |
}; |
/** |
- * Forgets all scans. |
+ * Cancels and forgets all scans. |
*/ |
importer.ScanManager.prototype.reset = function() { |
this.clearSelectionScan(); |
- this.clearDirectoryScans(); |
+ this.clearDirectoryScan(); |
}; |
/** |
- * Forgets the selection scans for the current directory. |
+ * @return {boolean} True if we have an existing selection scan. |
+ */ |
+importer.ScanManager.prototype.hasSelectionScan = function() { |
+ return !!this.selectionScan_; |
+}; |
+ |
+/** |
+ * Cancels and forgets the current selection scan, if any. |
*/ |
importer.ScanManager.prototype.clearSelectionScan = function() { |
+ if (this.selectionScan_) { |
+ this.selectionScan_.cancel(); |
+ } |
this.selectionScan_ = null; |
}; |
/** |
- * Forgets directory scans. |
+ * Cancels and forgets the current directory scan, if any. |
*/ |
-importer.ScanManager.prototype.clearDirectoryScans = function() { |
- this.directoryScans_ = {}; |
+importer.ScanManager.prototype.clearDirectoryScan = function() { |
+ if (this.directoryScan_) { |
+ this.directoryScan_.cancel(); |
+ } |
+ this.directoryScan_ = null; |
}; |
/** |
@@ -843,14 +887,7 @@ importer.ScanManager.prototype.clearDirectoryScans = function() { |
* if none. |
*/ |
importer.ScanManager.prototype.getActiveScan = function() { |
- if (!!this.selectionScan_) { |
- return this.selectionScan_; |
- } |
- var directory = this.environment_.getCurrentDirectory(); |
- if (directory) { |
- return this.directoryScans_[directory.toURL()]; |
- } |
- return null; |
+ return this.selectionScan_ || this.directoryScan_; |
}; |
/** |
@@ -859,13 +896,7 @@ importer.ScanManager.prototype.getActiveScan = function() { |
* selection scan or the scan for the current directory. |
*/ |
importer.ScanManager.prototype.isActiveScan = function(scan) { |
- if (scan === this.selectionScan_) { |
- return true; |
- } |
- |
- var directory = this.environment_.getCurrentDirectory(); |
- return !!directory && |
- scan === this.directoryScans_[directory.toURL()]; |
+ return scan === this.selectionScan_ || scan === this.directoryScan_; |
}; |
/** |
@@ -888,21 +919,15 @@ importer.ScanManager.prototype.getSelectionScan = function(entries) { |
* |
* @return {importer.ScanResult} |
*/ |
-importer.ScanManager.prototype.getCurrentDirectoryScan = function() { |
- var directory = this.environment_.getCurrentDirectory(); |
- if (!directory) { |
- return null; |
- } |
- |
- var url = directory.toURL(); |
- var scan = this.directoryScans_[url]; |
- if (!scan) { |
- scan = this.scanner_.scanDirectory( |
- /** @type {!DirectoryEntry} */ (directory)); |
- this.directoryScans_[url] = scan; |
+importer.ScanManager.prototype.getDirectoryScan = function() { |
+ if (!this.directoryScan_) { |
+ var directory = this.environment_.getCurrentDirectory(); |
+ if (directory) { |
+ this.directoryScan_ = this.scanner_.scanDirectory( |
+ /** @type {!DirectoryEntry} */ (directory)); |
+ } |
} |
- |
- return scan; |
+ return this.directoryScan_; |
}; |
/** |
@@ -945,6 +970,14 @@ importer.ControllerEnvironment.prototype.isGoogleDriveMounted; |
importer.ControllerEnvironment.prototype.getFreeStorageSpace; |
/** |
+ * Installs a 'window closed' listener. Listener is called just |
+ * just before the window is closed. Any business must be |
+ * done synchronously. |
+ * @param {function()} listener |
+ */ |
+importer.ControllerEnvironment.prototype.addWindowCloseListener; |
+ |
+/** |
* Installs an 'unmount' listener. Listener is called with |
* the corresponding volume id when a volume is unmounted. |
* @param {function(string)} listener |
@@ -1049,22 +1082,6 @@ importer.RuntimeControllerEnvironment.prototype.isGoogleDriveMounted = |
}; |
/** @override */ |
-importer.RuntimeControllerEnvironment.prototype.addVolumeUnmountListener = |
- function(listener) { |
- // TODO(smckay): remove listeners when the page is torn down. |
- chrome.fileManagerPrivate.onMountCompleted.addListener( |
- /** |
- * @param {!MountCompletedEvent} event |
- * @this {importer.RuntimeControllerEnvironment} |
- */ |
- function(event) { |
- if (event.eventType === 'unmount') { |
- listener(event.volumeMetadata.volumeId); |
- } |
- }); |
-}; |
- |
-/** @override */ |
importer.RuntimeControllerEnvironment.prototype.getFreeStorageSpace = |
function() { |
// Checking DOWNLOADS returns the amount of available local storage space. |
@@ -1089,6 +1106,28 @@ importer.RuntimeControllerEnvironment.prototype.getFreeStorageSpace = |
}; |
/** @override */ |
+importer.RuntimeControllerEnvironment.prototype.addWindowCloseListener = |
+ function(listener) { |
+ window.addEventListener('pagehide', listener); |
+}; |
+ |
+/** @override */ |
+importer.RuntimeControllerEnvironment.prototype.addVolumeUnmountListener = |
+ function(listener) { |
+ // TODO(smckay): remove listeners when the page is torn down. |
+ chrome.fileManagerPrivate.onMountCompleted.addListener( |
+ /** |
+ * @param {!MountCompletedEvent} event |
+ * @this {importer.RuntimeControllerEnvironment} |
+ */ |
+ function(event) { |
+ if (event.eventType === 'unmount') { |
+ listener(event.volumeMetadata.volumeId); |
+ } |
+ }); |
+}; |
+ |
+/** @override */ |
importer.RuntimeControllerEnvironment.prototype.addDirectoryChangedListener = |
function(listener) { |
// TODO(smckay): remove listeners when the page is torn down. |