OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 'use strict'; | 5 'use strict'; |
6 | 6 |
7 /** | 7 /** |
8 * Utilities for FileOperationManager. | 8 * Utilities for FileOperationManager. |
9 */ | 9 */ |
10 var fileOperationUtil = {}; | 10 var fileOperationUtil = {}; |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 }); | 291 }); |
292 }; | 292 }; |
293 | 293 |
294 /** | 294 /** |
295 * @constructor | 295 * @constructor |
296 */ | 296 */ |
297 function FileOperationManager() { | 297 function FileOperationManager() { |
298 this.copyTasks_ = []; | 298 this.copyTasks_ = []; |
299 this.deleteTasks_ = []; | 299 this.deleteTasks_ = []; |
300 this.taskIdCounter_ = 0; | 300 this.taskIdCounter_ = 0; |
301 | |
302 this.eventRouter_ = new FileOperationManager.EventRouter(); | 301 this.eventRouter_ = new FileOperationManager.EventRouter(); |
303 | 302 |
304 Object.seal(this); | 303 Object.seal(this); |
305 } | 304 } |
306 | 305 |
307 /** | 306 /** |
308 * Get FileOperationManager instance. In case is hasn't been initialized, a new | 307 * Get FileOperationManager instance. In case is hasn't been initialized, a new |
309 * instance is created. | 308 * instance is created. |
310 * | 309 * |
311 * @return {FileOperationManager} A FileOperationManager instance. | 310 * @return {FileOperationManager} A FileOperationManager instance. |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 entry.processedBytes = 0; | 573 entry.processedBytes = 0; |
575 resolvedEntryMap[entry.toURL()] = entry; | 574 resolvedEntryMap[entry.toURL()] = entry; |
576 } | 575 } |
577 this.processingEntries[index] = resolvedEntryMap; | 576 this.processingEntries[index] = resolvedEntryMap; |
578 callback(); | 577 callback(); |
579 }.bind(this), | 578 }.bind(this), |
580 function(error) { | 579 function(error) { |
581 console.error( | 580 console.error( |
582 'Failed to resolve for copy: %s', | 581 'Failed to resolve for copy: %s', |
583 util.getFileErrorMnemonic(error.code)); | 582 util.getFileErrorMnemonic(error.code)); |
| 583 callback(); |
584 }); | 584 }); |
585 }.bind(this, i)); | 585 }.bind(this, i)); |
586 } | 586 } |
587 | 587 |
588 group.run(function() { | 588 group.run(function() { |
589 // Fill totalBytes. | 589 // Fill totalBytes. |
590 this.totalBytes = 0; | 590 this.totalBytes = 0; |
591 for (var i = 0; i < this.processingEntries.length; i++) { | 591 for (var i = 0; i < this.processingEntries.length; i++) { |
592 for (var entryURL in this.processingEntries[i]) | 592 for (var entryURL in this.processingEntries[i]) |
593 this.totalBytes += this.processingEntries[i][entryURL].size; | 593 this.totalBytes += this.processingEntries[i][entryURL].size; |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
901 var group = new AsyncUtil.Group(); | 901 var group = new AsyncUtil.Group(); |
902 for (var i = 0; i < this.sourceEntries.length; i++) { | 902 for (var i = 0; i < this.sourceEntries.length; i++) { |
903 group.add(function(index, callback) { | 903 group.add(function(index, callback) { |
904 fileOperationUtil.resolveRecursively( | 904 fileOperationUtil.resolveRecursively( |
905 this.sourceEntries[index], | 905 this.sourceEntries[index], |
906 function(entries) { | 906 function(entries) { |
907 for (var j = 0; j < entries.length; j++) | 907 for (var j = 0; j < entries.length; j++) |
908 resolvedEntryMap[entries[j].toURL()] = entries[j]; | 908 resolvedEntryMap[entries[j].toURL()] = entries[j]; |
909 callback(); | 909 callback(); |
910 }, | 910 }, |
911 function(error) {}); | 911 callback); |
912 }.bind(this, i)); | 912 }.bind(this, i)); |
913 } | 913 } |
914 | 914 |
915 group.run(function() { | 915 group.run(function() { |
916 // For zip archiving, all the entries are processed at once. | 916 // For zip archiving, all the entries are processed at once. |
917 this.processingEntries = [resolvedEntryMap]; | 917 this.processingEntries = [resolvedEntryMap]; |
918 | 918 |
919 this.totalBytes = 0; | 919 this.totalBytes = 0; |
920 for (var url in resolvedEntryMap) | 920 for (var url in resolvedEntryMap) |
921 this.totalBytes += resolvedEntryMap[url].size; | 921 this.totalBytes += resolvedEntryMap[url].size; |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 // Do nothing, if we have no entries to be pasted. | 1158 // Do nothing, if we have no entries to be pasted. |
1159 if (filteredEntries.length === 0) | 1159 if (filteredEntries.length === 0) |
1160 return; | 1160 return; |
1161 | 1161 |
1162 this.queueCopy_(targetEntry, filteredEntries, isMove); | 1162 this.queueCopy_(targetEntry, filteredEntries, isMove); |
1163 }.bind(this)); | 1163 }.bind(this)); |
1164 }; | 1164 }; |
1165 | 1165 |
1166 /** | 1166 /** |
1167 * Checks if the move operation is available between the given two locations. | 1167 * Checks if the move operation is available between the given two locations. |
| 1168 * This method uses the volume manager, which is lazily created, therefore the |
| 1169 * result is returned asynchronously. |
1168 * | 1170 * |
1169 * @param {DirectoryEntry} sourceEntry An entry from the source. | 1171 * @param {DirectoryEntry} sourceEntry An entry from the source. |
1170 * @param {DirectoryEntry} targetDirEntry Directory entry for the target. | 1172 * @param {DirectoryEntry} targetDirEntry Directory entry for the target. |
1171 * @return {boolean} Whether we can move from the source to the target. | 1173 * @param {function(boolean)} callback Callback with result whether the entries |
| 1174 * can be directly moved. |
| 1175 * @private |
1172 */ | 1176 */ |
1173 FileOperationManager.prototype.isMovable = function( | 1177 FileOperationManager.prototype.isMovable_ = function( |
1174 sourceEntry, targetDirEntry) { | 1178 sourceEntry, targetDirEntry, callback) { |
1175 var sourceLocationInfo = this.volumeManager_.getLocationInfo(sourceEntry); | 1179 VolumeManager.getInstance(function(volumeManager) { |
1176 var targetDirLocationInfo = this.volumeManager_.getLocationInfo( | 1180 var sourceLocationInfo = volumeManager.getLocationInfo(sourceEntry); |
1177 targetDirEntry); | 1181 var targetDirLocationInfo = volumeManager.getLocationInfo(targetDirEntry); |
1178 | 1182 callback( |
1179 return sourceLocationInfo && targetDirLocationInfo && | 1183 sourceLocationInfo && targetDirLocationInfo && |
1180 sourceLocationInfo.volumeInfo === targetDirLocationInfo.volumeInfo; | 1184 sourceLocationInfo.volumeInfo === targetDirLocationInfo.volumeInfo); |
| 1185 }); |
1181 }; | 1186 }; |
1182 | 1187 |
1183 /** | 1188 /** |
1184 * Initiate a file copy. | 1189 * Initiate a file copy. When copying files, null can be specified as source |
| 1190 * directory. |
1185 * | 1191 * |
1186 * @param {DirectoryEntry} targetDirEntry Target directory. | 1192 * @param {DirectoryEntry} targetDirEntry Target directory. |
1187 * @param {Array.<Entry>} entries Entries to copy. | 1193 * @param {Array.<Entry>} entries Entries to copy. |
1188 * @param {boolean} isMove In case of move. | 1194 * @param {boolean} isMove In case of move. |
1189 * @return {FileOperationManager.Task} Copy task. | |
1190 * @private | 1195 * @private |
1191 */ | 1196 */ |
1192 FileOperationManager.prototype.queueCopy_ = function( | 1197 FileOperationManager.prototype.queueCopy_ = function( |
1193 targetDirEntry, entries, isMove) { | 1198 targetDirEntry, entries, isMove) { |
1194 // When copying files, null can be specified as source directory. | 1199 var createTask = function(task) { |
| 1200 task.taskId = this.generateTaskId_(); |
| 1201 task.initialize(function() { |
| 1202 this.copyTasks_.push(task); |
| 1203 this.eventRouter_.sendProgressEvent( |
| 1204 'BEGIN', task.getStatus(), task.taskId); |
| 1205 if (this.copyTasks_.length === 1) |
| 1206 this.serviceAllTasks_(); |
| 1207 }.bind(this)); |
| 1208 }.bind(this); |
| 1209 |
1195 var task; | 1210 var task; |
1196 if (isMove) { | 1211 if (isMove) { |
1197 if (this.isMovable(entries[0], targetDirEntry)) { | 1212 // When moving between different volumes, moving is implemented as a copy |
1198 task = new FileOperationManager.MoveTask(entries, targetDirEntry); | 1213 // and delete. This is because moving between volumes is slow, and moveTo() |
1199 } else { | 1214 // is not cancellable nor provides progress feedback. |
1200 task = new FileOperationManager.CopyTask(entries, targetDirEntry); | 1215 this.isMovable_(entries[0], targetDirEntry, function(isMovable) { |
1201 task.deleteAfterCopy = true; | 1216 if (isMovable) { |
1202 } | 1217 createTask(new FileOperationManager.MoveTask(entries, targetDirEntry)); |
| 1218 } else { |
| 1219 var task = new FileOperationManager.CopyTask(entries, targetDirEntry); |
| 1220 task.deleteAfterCopy = true; |
| 1221 createTask(task); |
| 1222 } |
| 1223 }); |
1203 } else { | 1224 } else { |
1204 task = new FileOperationManager.CopyTask(entries, targetDirEntry); | 1225 createTask(new FileOperationManager.CopyTask(entries, targetDirEntry)); |
1205 } | 1226 } |
1206 | |
1207 task.taskId = this.generateTaskId_(); | |
1208 task.initialize(function() { | |
1209 this.copyTasks_.push(task); | |
1210 this.eventRouter_.sendProgressEvent('BEGIN', task.getStatus(), task.taskId); | |
1211 if (this.copyTasks_.length == 1) | |
1212 this.serviceAllTasks_(); | |
1213 }.bind(this)); | |
1214 | |
1215 return task; | |
1216 }; | 1227 }; |
1217 | 1228 |
1218 /** | 1229 /** |
1219 * Service all pending tasks, as well as any that might appear during the | 1230 * Service all pending tasks, as well as any that might appear during the |
1220 * copy. | 1231 * copy. |
1221 * | 1232 * |
1222 * @private | 1233 * @private |
1223 */ | 1234 */ |
1224 FileOperationManager.prototype.serviceAllTasks_ = function() { | 1235 FileOperationManager.prototype.serviceAllTasks_ = function() { |
1225 if (!this.copyTasks_.length) { | 1236 if (!this.copyTasks_.length) { |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1407 | 1418 |
1408 /** | 1419 /** |
1409 * Generates new task ID. | 1420 * Generates new task ID. |
1410 * | 1421 * |
1411 * @return {string} New task ID. | 1422 * @return {string} New task ID. |
1412 * @private | 1423 * @private |
1413 */ | 1424 */ |
1414 FileOperationManager.prototype.generateTaskId_ = function() { | 1425 FileOperationManager.prototype.generateTaskId_ = function() { |
1415 return 'file-operation-' + this.taskIdCounter_++; | 1426 return 'file-operation-' + this.taskIdCounter_++; |
1416 }; | 1427 }; |
OLD | NEW |