Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(847)

Unified Diff: ui/file_manager/file_manager/foreground/js/import_controller.js

Issue 886093003: Add support for size checking selection based scans. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update DefaultScanResult to use importerResolver instead of hand rolled support...was investigating… Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 67c96358332cb522efcf7e40bf1e281b003ad61a..439fc43ec381633f6fcbf7b2142c184702e19910 100644
--- a/ui/file_manager/file_manager/foreground/js/import_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/import_controller.js
@@ -55,12 +55,8 @@ importer.ImportController =
/** @private {!importer.CommandWidget} */
this.commandWidget_ = commandWidget;
- /**
- * A cache of scans by volumeId, directory URL.
- * Currently only scans of directories are cached.
- * @private {!Object.<string, !Object.<string, !importer.ScanResult>>}
- */
- this.cachedScans_ = {};
+ /** @type {!importer.ScanManager} */
+ this.scanManager_ = new importer.ScanManager(scanner);
/**
* The active import task, if any.
@@ -83,6 +79,9 @@ importer.ImportController =
this.environment_.addDirectoryChangedListener(
this.onDirectoryChanged_.bind(this));
+ this.environment_.addSelectionChangedListener(
+ this.onSelectionChanged_.bind(this));
+
this.commandWidget_.addExecuteListener(
this.execute.bind(this));
};
@@ -95,7 +94,7 @@ importer.ImportController =
*/
importer.ImportController.prototype.onScanEvent_ = function(event, result) {
if (event === importer.ScanEvent.INVALIDATED) {
- this.resetScanCache_();
+ this.scanManager_.reset();
}
if (event === importer.ScanEvent.FINALIZED ||
event === importer.ScanEvent.INVALIDATED) {
@@ -112,9 +111,10 @@ importer.ImportController.prototype.execute = function() {
console.assert(!this.activeImportTask_,
'Cannot execute while an import task is already active.');
metrics.recordEnum('CloudImport.UserAction', 'IMPORT_INITIATED');
- var result = this.getScanForImport_();
+ var scan = this.getScan_();
+ assert(scan != null);
var importTask = this.importRunner_.importFromScanResult(
- result,
+ scan,
importer.Destination.GOOGLE_DRIVE);
this.activeImportTask_ = importTask;
@@ -129,16 +129,10 @@ importer.ImportController.prototype.execute = function() {
*/
importer.ImportController.prototype.onImportFinished_ = function(task) {
this.activeImportTask_ = null;
- this.resetScanCache_();
+ this.scanManager_.reset();
hirono 2015/02/02 01:07:01 It's better to reset cache when the import is fini
Steve McKay 2015/02/02 15:52:37 Ahh, yeah. Multiple-windows. Good thinking. We pro
this.pushUpdate_();
};
-/** @private */
-importer.ImportController.prototype.resetScanCache_ = function() {
- // TODO(smckay): Actively cancel each scan.
- this.cachedScans_ = {};
-};
-
/**
* Push an update to the command widget.
* @private
@@ -163,48 +157,38 @@ importer.ImportController.prototype.getCommandUpdate = function() {
// If there is no Google Drive mount, Drive may be disabled
// or the machine may be running in guest mode.
- if (this.environment_.isGoogleDriveMounted()) {
- var entries = this.environment_.getSelection();
-
- // Enabled if user has a selection and it consists entirely of files
- // that:
- // 1) are of a recognized media type
- // 2) reside on a removable media device
- // 3) in the DCIM directory
- if (entries.length) {
- if (entries.every(
- importer.isEligibleEntry.bind(null, this.environment_))) {
- return importer.ImportController.createUpdate_(
- importer.ResponseId.EXECUTABLE, entries.length);
- }
- } else if (this.isCurrentDirectoryScannable_()) {
- var scan = this.getCurrentDirectoryScan_();
- if (scan.isFinal()) {
- if (scan.getFileEntries().length === 0) {
- return importer.ImportController.createUpdate_(
- importer.ResponseId.NO_MEDIA);
- } else {
- return this.fitsInAvailableSpace_(scan).then(
- /** @param {boolean} fits */
- function(fits) {
- return fits ?
- importer.ImportController.createUpdate_(
- importer.ResponseId.EXECUTABLE,
- scan.getFileEntries().length) :
- importer.ImportController.createUpdate_(
- importer.ResponseId.INSUFFICIENT_SPACE,
- scan.getTotalBytes());
- });
- }
- } else {
- return importer.ImportController.createUpdate_(
- importer.ResponseId.SCANNING);
- }
- }
+ if (!this.environment_.isGoogleDriveMounted()) {
+ return importer.ImportController.createUpdate_(
+ importer.ResponseId.HIDDEN);
}
- return importer.ImportController.createUpdate_(
- importer.ResponseId.HIDDEN);
+ var scan = this.getScan_();
+ if (!scan) {
+ return importer.ImportController.createUpdate_(
+ importer.ResponseId.HIDDEN);
+ }
+
+ if (!scan.isFinal()) {
+ return importer.ImportController.createUpdate_(
+ importer.ResponseId.SCANNING);
+ }
+
+ if (scan.getFileEntries().length === 0) {
+ return importer.ImportController.createUpdate_(
+ importer.ResponseId.NO_MEDIA);
+ }
+
+ return this.fitsInAvailableSpace_(scan).then(
+ /** @param {boolean} fits */
+ function(fits) {
+ return fits ?
+ importer.ImportController.createUpdate_(
+ importer.ResponseId.EXECUTABLE,
+ scan.getFileEntries().length) :
+ importer.ImportController.createUpdate_(
+ importer.ResponseId.INSUFFICIENT_SPACE,
+ scan.getTotalBytes());
+ });
}.bind(this));
};
@@ -304,48 +288,27 @@ importer.ImportController.prototype.fitsInAvailableSpace_ =
/**
* Get or create scan for the current directory or file selection.
*
- * @return {!importer.ScanResult} A scan result object that may be
- * actively scanning.
+ * @return {importer.ScanResult} A scan result object that may be
+ * actively scanning. Null if scan is not possible in current
+ * context.
* @private
*/
-importer.ImportController.prototype.getScanForImport_ = function() {
+importer.ImportController.prototype.getScan_ = function() {
var entries = this.environment_.getSelection();
if (entries.length) {
if (entries.every(
importer.isEligibleEntry.bind(null, this.environment_))) {
- return this.scanner_.scan(entries);
+ return this.scanManager_.getSelectionScan(entries);
}
- } else {
- return this.getCurrentDirectoryScan_();
- }
-};
-
-/**
- * Get or create scan for the current directory.
- *
- * @return {!importer.ScanResult} A scan result object that may be
- * actively scanning.
- * @private
- */
-importer.ImportController.prototype.getCurrentDirectoryScan_ = function() {
- console.assert(this.isCurrentDirectoryScannable_());
- var directory = this.environment_.getCurrentDirectory();
- var volumeId = this.environment_.getVolumeInfo(directory).volumeId;
+ } else if (this.isCurrentDirectoryScannable_()) {
+ var directory = this.environment_.getCurrentDirectory();
+ var volumeId = this.environment_.getVolumeInfo(directory).volumeId;
- // Lazily initialize the cache for volumeId.
- if (!this.cachedScans_.hasOwnProperty(volumeId)) {
- this.cachedScans_[volumeId] = {};
+ return this.scanManager_.getDirectoryScan(volumeId, directory);
}
- var url = directory.toURL();
- var scan = this.cachedScans_[volumeId][url];
- if (!scan) {
- scan = this.scanner_.scan([directory]);
- this.cachedScans_[volumeId][url] = scan;
- }
- assert(!scan.isInvalidated());
- return scan;
+ return null;
};
/**
@@ -353,7 +316,7 @@ importer.ImportController.prototype.getCurrentDirectoryScan_ = function() {
* @private
*/
importer.ImportController.prototype.onVolumeUnmounted_ = function(volumeId) {
- this.resetScanCache_();
+ this.scanManager_.reset();
hirono 2015/02/02 01:07:01 nit: We can check volume-unmounted event in the ba
Steve McKay 2015/02/02 15:52:37 Yep. Basically the same TODO (moving scan cache an
this.pushUpdate_();
};
@@ -362,6 +325,12 @@ importer.ImportController.prototype.onDirectoryChanged_ = function() {
this.pushUpdate_();
};
+/** @private */
+importer.ImportController.prototype.onSelectionChanged_ = function() {
+ this.scanManager_.clearSelectionScan();
+ this.pushUpdate_();
+};
+
/**
* Interface abstracting away the concrete file manager available
* to commands. By hiding file manager we make it easy to test
@@ -416,6 +385,13 @@ importer.ControllerEnvironment.prototype.addVolumeUnmountListener;
importer.ControllerEnvironment.prototype.addDirectoryChangedListener;
/**
+ * Installs an 'selection-changed' listener. Listener is called when
+ * user selected files is changed.
+ * @param {function()} listener
+ */
+importer.ControllerEnvironment.prototype.addSelectionChangedListener;
+
+/**
* Class providing access to various pieces of information in the
* FileManager environment, like the current directory, volumeinfo lookup
* By hiding file manager we make it easy to test importer.ImportController.
@@ -425,9 +401,13 @@ importer.ControllerEnvironment.prototype.addDirectoryChangedListener;
*
* @param {!FileManager} fileManager
*/
-importer.RuntimeControllerEnvironment = function(fileManager) {
+importer.RuntimeControllerEnvironment =
+ function(fileManager, selectionHandler) {
/** @private {!FileManager} */
this.fileManager_ = fileManager;
+
+ /** @private {!FileSelectionHandler} */
+ this.selectionHandler_ = selectionHandler;
};
/** @override */
@@ -512,6 +492,14 @@ importer.RuntimeControllerEnvironment.prototype.addDirectoryChangedListener =
listener);
};
+/** @override */
+importer.RuntimeControllerEnvironment.prototype.addSelectionChangedListener =
+ function(listener) {
+ this.selectionHandler_.addEventListener(
+ FileSelectionHandler.EventType.CHANGE,
+ listener);
+};
+
/**
* Class that adapts from the new non-command button to the old
* command style interface.
@@ -573,3 +561,91 @@ importer.RuntimeCommandWidget.prototype.update = function(update) {
this.buttonElement_.style.display = update.visible ? 'block' : 'none';
this.iconElement_.setAttribute('icon', update.coreIcon);
};
+
+
+/**
+ * A cache for ScanResults.
+ *
+ * @constructor
+ * @struct
+ *
+ * @param {!importer.MediaScanner} scanner
+ */
+importer.ScanManager = function(scanner) {
+ /** @private {!importer.MediaScanner} */
+ this.scanner_ = scanner;
+
+ /**
+ * The most recent scan based on user selected files (instead of directories).
+ * @private {importer.ScanResult}
+ */
+ this.lastSelectionScan_ = null;
+
+ /**
+ * A cache of scans by volumeId, directory URL.
+ * Currently only scans of directories are cached.
+ * @private {!Object.<string, !Object.<string, !importer.ScanResult>>}
+ */
+ this.cachedScans_ = {};
hirono 2015/02/02 01:07:01 Do we need to have multiple scan caches? If we had
Steve McKay 2015/02/02 15:52:37 TODO will address this...and make the need for mul
+};
+
+/**
+ * Forgets all scans.
+ */
+importer.ScanManager.prototype.reset = function() {
+ this.clearSelectionScan();
+ this.clearDirectoryScans();
+};
+
+/**
+ * Forgets the selection scans.
+ */
+importer.ScanManager.prototype.clearSelectionScan = function() {
+ this.lastSelectionScan_ = null;
+};
+
+/**
+ * Forgets directory scans.
+ */
+importer.ScanManager.prototype.clearDirectoryScans = function() {
+ this.cachedScans_ = {};
hirono 2015/02/02 01:07:01 Please check whether the scans are invalidated or
Steve McKay 2015/02/02 15:52:37 That would be unnecessary coupling with the callin
+};
+
+/**
+ * Returns a scan for the directory.
+ *
+ * @param {!Array.<!FileEntry>} entries
+ *
+ * @return {!importer.ScanResult}
+ */
+importer.ScanManager.prototype.getSelectionScan =
+ function(entries) {
+ if (!this.lastSelectionScan_) {
+ this.lastSelectionScan_ = this.scanner_.scan(entries);
+ }
+ return this.lastSelectionScan_;
+};
+
+/**
+ * Returns a scan for the directory.
+ *
+ * @param {string} volumeId
+ * @param {!DirectoryEntry} directory
+ *
+ * @return {!importer.ScanResult}
+ */
+importer.ScanManager.prototype.getDirectoryScan =
+ function(volumeId, directory) {
+ // Lazily initialize the cache for volumeId.
+ if (!(volumeId in this.cachedScans_)) {
+ this.cachedScans_[volumeId] = {};
+ }
+
+ var url = directory.toURL();
+ var scan = this.cachedScans_[volumeId][url];
+ if (!scan) {
+ scan = this.scanner_.scan([directory]);
+ this.cachedScans_[volumeId][url] = scan;
+ }
+ return scan;
+};

Powered by Google App Engine
This is Rietveld 408576698