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

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

Issue 867233003: Files.app: Show 'no space' message if there is not enough space to import photos. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased. 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 b6f99d4d09ac9c18fe272a07b5e45f4f7f58179c..578ea182588c66022e206eb187a3731a1a6c0c8f 100644
--- a/ui/file_manager/file_manager/foreground/js/import_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/import_controller.js
@@ -10,6 +10,7 @@ importer.ResponseId = {
HIDDEN: 'hidden',
SCANNING: 'scanning',
NO_MEDIA: 'no_media',
+ NO_SPACE: 'no_spcae',
Steve McKay 2015/01/26 18:08:43 INSUFFICIENT_SPACE: 'insufficient_space'
EXECUTABLE: 'executable'
};
@@ -55,9 +56,15 @@ importer.ImportController =
/**
* A cache of scans by volumeId, directory URL.
* Currently only scans of directories are cached.
- * @private {!Object.<string, !Object.<string, !importer.ScanResult>>}
+ * @private {!importer.ScanCache}
+ * @const
*/
- this.cachedScans_ = {};
+ this.scanCache_ = new importer.ScanCache();
+
+ /**
+ * @private {number}
+ */
+ this.localVolumeAvilableSize_ = 0;
var listener = this.onScanEvent_.bind(this);
this.scanner_.addObserver(listener);
@@ -65,8 +72,6 @@ importer.ImportController =
window.addEventListener('pagehide', function() {
this.scanner_.removeObserver(listener);
}.bind(this));
- this.environment_.addVolumeUnmountListener(
- this.onVolumeUnmounted_.bind(this));
};
/**
@@ -77,17 +82,16 @@ importer.ImportController =
*/
importer.ImportController.prototype.onScanEvent_ = function(event, result) {
if (event === importer.ScanEvent.INVALIDATED) {
- for (var key in this.cachedScans_) {
- for (var url in this.cachedScans_[key]) {
- if (this.cachedScans_[key][url].isInvalidated()) {
- delete this.cachedScans_[key][url];
- }
- }
+ if (this.scanCache_.currentCache.isInvalidated()) {
Steve McKay 2015/01/26 18:08:43 Let's keep this super simple for now. When *any* s
+ this.scanCache_.clear();
}
}
if (event === importer.ScanEvent.FINALIZED ||
event === importer.ScanEvent.INVALIDATED) {
- this.updateCommands_();
+ this.environment_.getLocalVolumeAvailableSize().then(function(size) {
Steve McKay 2015/01/26 18:08:43 Please wrap before anonymous functions. NOT wrappi
+ this.localVolumeAvilableSize_ = size;
+ this.updateCommands_();
+ }.bind(this));
}
};
@@ -98,7 +102,7 @@ importer.ImportController.prototype.onScanEvent_ = function(event, result) {
*/
importer.ImportController.prototype.execute = function() {
metrics.recordEnum('CloudImport.UserAction', 'IMPORT_INITIATED');
- var result = this.getScanForImport_();
+ var result = assert(this.getScanForImport_());
var importTask = this.importRunner_.importFromScanResult(result);
importTask.getDestination().then(
@@ -120,25 +124,15 @@ 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_();
+ var scan = this.getScanForImport_();
+ if (scan) {
if (scan.isFinal()) {
if (scan.getFileEntries().length === 0) {
return importer.ImportController.createUpdate_(
importer.ResponseId.NO_MEDIA);
+ } else if (scan.getTotalBytes() > this.localVolumeAvilableSize_) {
+ return importer.ImportController.createUpdate_(
+ importer.ResponseId.NO_SPACE);
} else {
return importer.ImportController.createUpdate_(
importer.ResponseId.EXECUTABLE,
@@ -186,12 +180,19 @@ importer.ImportController.createUpdate_ =
executable: false,
label: str('CLOUD_IMPORT_EMPTY_SCAN_BUTTON_LABEL')
};
+ case importer.ResponseId.NO_SPACE:
+ return {
+ id: responseId,
+ visible: true,
+ executable: false,
+ label: str('CLOUD_IMPORT_INSUFFICIENT_SPACE_BUTTON_LABEL'),
+ };
case importer.ResponseId.EXECUTABLE:
return {
id: responseId,
- label: strf('CLOUD_IMPORT_BUTTON_LABEL', opt_fileCount),
visible: true,
- executable: true
+ executable: true,
+ label: strf('CLOUD_IMPORT_BUTTON_LABEL', opt_fileCount),
};
default:
assertNotReached('Unrecognized response id: ' + responseId);
@@ -199,75 +200,44 @@ importer.ImportController.createUpdate_ =
};
/**
- * @return {boolean} true if the current directory is scan eligible.
- * @private
- */
-importer.ImportController.prototype.isCurrentDirectoryScannable_ =
- function() {
- var directory = this.environment_.getCurrentDirectory();
- return !!directory &&
- importer.isMediaDirectory(directory, this.environment_);
-};
-
-/**
* 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. Can be null.
* @private
*/
importer.ImportController.prototype.getScanForImport_ = function() {
Steve McKay 2015/01/26 18:08:43 Move this logic into ScanCache and rename that cla
var entries = this.environment_.getSelection();
-
+ var targetEntries = null;
if (entries.length) {
if (entries.every(
importer.isEligibleEntry.bind(null, this.environment_))) {
- return this.scanner_.scan(entries);
+ // 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
+ targetEntries = 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;
-
- // Lazily initialize the cache for volumeId.
- if (!this.cachedScans_.hasOwnProperty(volumeId)) {
- this.cachedScans_[volumeId] = {};
+ var directory = this.environment_.getCurrentDirectory();
+ if (!!directory &&
+ importer.isMediaDirectory(directory, this.environment_)) {
+ targetEntries = [directory];
+ }
}
-
- var url = directory.toURL();
- var scan = this.cachedScans_[volumeId][url];
+ if (!targetEntries)
+ return null;
+ var scan = this.scanCache_.getForEntries(targetEntries);
Steve McKay 2015/01/26 18:08:43 We can't throw away directory scans. A recursive s
if (!scan) {
- scan = this.scanner_.scan([directory]);
- this.cachedScans_[volumeId][url] = scan;
+ scan = this.scanner_.scan(targetEntries);
+ this.scanCache_.putForEntries(targetEntries, scan);
}
assert(!scan.isInvalidated());
return scan;
};
/**
- * @param {string} volumeId
- * @private
- */
-importer.ImportController.prototype.onVolumeUnmounted_ = function(volumeId) {
- // Forget all scans related to the unmounted volume volume.
- if (this.cachedScans_.hasOwnProperty(volumeId)) {
- delete this.cachedScans_[volumeId];
- }
-};
-
-/**
* Interface abstracting away the concrete file manager available
* to commands. By hiding file manager we make it easy to test
* ImportController.
@@ -301,11 +271,9 @@ importer.ControllerEnvironment.prototype.setCurrentDirectory;
importer.ControllerEnvironment.prototype.isGoogleDriveMounted;
/**
- * Installs an 'unmount' listener. Listener is called with
- * the corresponding volume id when a volume is unmounted.
- * @param {function(string)} listener
+ * @return {!Promise<number>}
*/
-importer.ControllerEnvironment.prototype.addVolumeUnmountListener;
Steve McKay 2015/01/26 18:08:44 We still need to invalidate scans when a volume is
+importer.ControllerEnvironment.prototype.getLocalVolumeAvailableSize;
/**
* Class providing access to various pieces of information in the
@@ -356,16 +324,74 @@ importer.RuntimeControllerEnvironment.prototype.isGoogleDriveMounted =
};
/** @override */
-importer.RuntimeControllerEnvironment.prototype.addVolumeUnmountListener =
- function(listener) {
- chrome.fileManagerPrivate.onMountCompleted.addListener(
- /**
- * @param {!MountCompletedEvent} event
- * @this {importer.RuntimeControllerEnvironment}
- */
- function(event) {
- if (event.eventType === 'unmount') {
- listener(event.volumeMetadata.volumeId);
- }
- });
+importer.RuntimeControllerEnvironment.prototype.getLocalVolumeAvailableSize =
+ function() {
+ var localVolumeInfo =
+ this.fileManager_.volumeManager.getCurrentProfileVolumeInfo(
+ VolumeManagerCommon.VolumeType.DOWNLOADS);
+ return new Promise(function(fulfill, reject) {
+ chrome.fileManagerPrivate.getSizeStats(
+ localVolumeInfo.volumeId,
+ function(stats) {
+ if (stats && !chrome.runtime.lastError) {
+ fulfill(stats.remainingSize);
+ } else {
+ reject('Failed to obtain remaining size.');
+ }
+ });
+ });
+};
+
+/**
+ * Cache for scan.
+ * @constructor
+ */
+importer.ScanCache = function() {
+ /**
+ * Cache key
+ * @private {string}
+ */
+ this.cacheKey_ = '';
+
+ /**
+ * Cached scan.
+ * @public {importer.ScanResult}
+ */
+ this.currentCache = null;
+};
+
+/**
+ * Creates cache key for the entries.
+ * @param {!Array<!Entry>} entries
+ * @return {string}
+ * @private
+ */
+importer.ScanCache.createKey_ = function(entries) {
+ return util.entriesToURLs(entries).sort().join('\n');
+};
+
+/**
+ * Puts scan result for the entries into the cache.
+ * @param {!Array<!Entry>} entries
+ * @param {importer.ScanResult} scan
+ */
+importer.ScanCache.prototype.putForEntries = function(entries, scan) {
+ this.cacheKey_ = importer.ScanCache.createKey_(entries);
+ this.currentCache = scan;
+};
+
+/**
+ * Gets cached scan result for the entries.
+ */
+importer.ScanCache.prototype.getForEntries = function(entries) {
+ var key = importer.ScanCache.createKey_(entries);
+ return this.cacheKey_ === key ? this.currentCache : null;
+};
+
+/**
+ * Clears the cached scan result.
+ */
+importer.ScanCache.prototype.clear = function() {
+ this.cacheKey_ = '';
+ this.currentCache = null;
};

Powered by Google App Engine
This is Rietveld 408576698