Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 /** | 5 /** |
| 6 * @constructor | 6 * @constructor |
| 7 * @param {DirectoryEntry} root Root directory entry. | 7 * @param {DirectoryEntry} root Root directory entry. |
| 8 */ | 8 */ |
| 9 function FileCopyManager(root) { | 9 function FileCopyManager(root) { |
| 10 this.copyTasks_ = []; | 10 this.copyTasks_ = []; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 this.pendingDirectories = []; | 54 this.pendingDirectories = []; |
| 55 this.pendingFiles = []; | 55 this.pendingFiles = []; |
| 56 this.pendingBytes = 0; | 56 this.pendingBytes = 0; |
| 57 | 57 |
| 58 this.completedDirectories = []; | 58 this.completedDirectories = []; |
| 59 this.completedFiles = []; | 59 this.completedFiles = []; |
| 60 this.completedBytes = 0; | 60 this.completedBytes = 0; |
| 61 | 61 |
| 62 this.deleteAfterCopy = false; | 62 this.deleteAfterCopy = false; |
| 63 this.move = false; | 63 this.move = false; |
| 64 this.zip = false; | |
| 64 this.sourceOnGData = false; | 65 this.sourceOnGData = false; |
| 65 this.targetOnGData = false; | 66 this.targetOnGData = false; |
| 66 | 67 |
| 67 // If directory already exists, we try to make a copy named 'dir (X)', | 68 // If directory already exists, we try to make a copy named 'dir (X)', |
| 68 // where X is a number. When we do this, all subsequent copies from | 69 // where X is a number. When we do this, all subsequent copies from |
| 69 // inside the subtree should be mapped to the new directory name. | 70 // inside the subtree should be mapped to the new directory name. |
| 70 // For example, if 'dir' was copied as 'dir (1)', then 'dir\file.txt' should | 71 // For example, if 'dir' was copied as 'dir (1)', then 'dir\file.txt' should |
| 71 // become 'dir (1)\file.txt'. | 72 // become 'dir (1)\file.txt'. |
| 72 this.renamedDirectories_ = []; | 73 this.renamedDirectories_ = []; |
| 73 }; | 74 }; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 223 pendingBytes: 0, | 224 pendingBytes: 0, |
| 224 | 225 |
| 225 completedItems: 0, // Files + Directories | 226 completedItems: 0, // Files + Directories |
| 226 completedFiles: 0, | 227 completedFiles: 0, |
| 227 completedDirectories: 0, | 228 completedDirectories: 0, |
| 228 completedBytes: 0, | 229 completedBytes: 0, |
| 229 | 230 |
| 230 percentage: NaN, | 231 percentage: NaN, |
| 231 pendingCopies: 0, | 232 pendingCopies: 0, |
| 232 pendingMoves: 0, | 233 pendingMoves: 0, |
| 234 pendingZips: 0, | |
| 233 filename: '' // In case pendingItems == 1 | 235 filename: '' // In case pendingItems == 1 |
| 234 }; | 236 }; |
| 235 | 237 |
| 236 var pendingFile = null; | 238 var pendingFile = null; |
| 237 | 239 |
| 238 for (var i = 0; i < this.copyTasks_.length; i++) { | 240 for (var i = 0; i < this.copyTasks_.length; i++) { |
| 239 var task = this.copyTasks_[i]; | 241 var task = this.copyTasks_[i]; |
| 240 var pendingFiles = task.pendingFiles.length; | 242 var pendingFiles = task.pendingFiles.length; |
| 241 var pendingDirectories = task.pendingDirectories.length; | 243 var pendingDirectories = task.pendingDirectories.length; |
| 242 rv.pendingFiles += pendingFiles; | 244 rv.pendingFiles += pendingFiles; |
| 243 rv.pendingDirectories += pendingDirectories; | 245 rv.pendingDirectories += pendingDirectories; |
| 244 rv.pendingBytes += task.pendingBytes; | 246 rv.pendingBytes += task.pendingBytes; |
| 245 | 247 |
| 246 rv.completedFiles += task.completedFiles.length; | 248 rv.completedFiles += task.completedFiles.length; |
| 247 rv.completedDirectories += task.completedDirectories.length; | 249 rv.completedDirectories += task.completedDirectories.length; |
| 248 rv.completedBytes += task.completedBytes; | 250 rv.completedBytes += task.completedBytes; |
| 249 | 251 |
| 250 if (task.move || task.deleteAfterCopy) { | 252 if (task.zip) { |
| 253 rv.pendingZips += pendingFiles + pendingDirectories; | |
| 254 } else if (task.move || task.deleteAfterCopy) { | |
| 251 rv.pendingMoves += pendingFiles + pendingDirectories; | 255 rv.pendingMoves += pendingFiles + pendingDirectories; |
| 252 } else { | 256 } else { |
| 253 rv.pendingCopies += pendingFiles + pendingDirectories; | 257 rv.pendingCopies += pendingFiles + pendingDirectories; |
| 254 } | 258 } |
| 255 | 259 |
| 256 if (task.pendingFiles.length === 1) | 260 if (task.pendingFiles.length === 1) |
| 257 pendingFile = task.pendingFiles[0]; | 261 pendingFile = task.pendingFiles[0]; |
| 258 | 262 |
| 259 if (task.pendingDirectories.length === 1) | 263 if (task.pendingDirectories.length === 1) |
| 260 pendingFile = task.pendingDirectories[0]; | 264 pendingFile = task.pendingDirectories[0]; |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 628 | 632 |
| 629 self.sendProgressEvent_('PROGRESS'); | 633 self.sendProgressEvent_('PROGRESS'); |
| 630 | 634 |
| 631 // We yield a few ms between copies to give the browser a chance to service | 635 // We yield a few ms between copies to give the browser a chance to service |
| 632 // events (like perhaps the user clicking to cancel the copy, for example). | 636 // events (like perhaps the user clicking to cancel the copy, for example). |
| 633 setTimeout(function() { | 637 setTimeout(function() { |
| 634 self.serviceNextTaskEntry_(task, onEntryServiced, errorCallback); | 638 self.serviceNextTaskEntry_(task, onEntryServiced, errorCallback); |
| 635 }, 10); | 639 }, 10); |
| 636 } | 640 } |
| 637 | 641 |
| 638 this.serviceNextTaskEntry_(task, onEntryServiced, errorCallback); | 642 if (!task.zip) |
| 643 this.serviceNextTaskEntry_(task, onEntryServiced, errorCallback); | |
| 644 else | |
| 645 this.serviceZipTask_(task, onTaskComplete, errorCallback); | |
| 639 }; | 646 }; |
| 640 | 647 |
| 641 /** | 648 /** |
| 642 * Service the next entry in a given task. | 649 * Service the next entry in a given task. |
| 643 * TODO(olege): Refactor this method into a separate class. | 650 * TODO(olege): Refactor this method into a separate class. |
| 644 * | 651 * |
| 645 * @private | 652 * @private |
| 646 * @param {FileManager.Task} task A task. | 653 * @param {FileManager.Task} task A task. |
| 647 * @param {Function} successCallback On success. | 654 * @param {Function} successCallback On success. |
| 648 * @param {Function} errorCallback On error. | 655 * @param {Function} errorCallback On error. |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 929 // Check to see if the target exists. This kicks off the rest of the copy | 936 // Check to see if the target exists. This kicks off the rest of the copy |
| 930 // if the target is not found, or raises an error if it does. | 937 // if the target is not found, or raises an error if it does. |
| 931 util.resolvePath(targetDirEntry, targetRelativePath, onTargetExists, | 938 util.resolvePath(targetDirEntry, targetRelativePath, onTargetExists, |
| 932 onTargetNotResolved); | 939 onTargetNotResolved); |
| 933 } | 940 } |
| 934 | 941 |
| 935 tryNextCopy(); | 942 tryNextCopy(); |
| 936 }; | 943 }; |
| 937 | 944 |
| 938 /** | 945 /** |
| 946 * Service a zip file creation task. | |
| 947 * | |
| 948 * @private | |
| 949 * @param {FileManager.Task} task A task. | |
| 950 * @param {Function} completeCallback On complete. | |
| 951 * @param {Function} errorCallback On error. | |
| 952 */ | |
| 953 FileCopyManager.prototype.serviceZipTask_ = function(task, completeCallback, | |
| 954 errorCallback) { | |
|
Oleg Eterevsky
2012/11/06 10:07:42
Indentation.
hshi1
2012/11/06 18:01:02
Done.
| |
| 955 var self = this; | |
| 956 var dirURL = task.sourceDirEntry.toURL(); | |
| 957 var selectionURLs = []; | |
| 958 for (var i = 0; i < task.pendingDirectories.length; i++) | |
| 959 selectionURLs.push(task.pendingDirectories[i].toURL()); | |
| 960 for (var i = 0; i < task.pendingFiles.length; i++) | |
| 961 selectionURLs.push(task.pendingFiles[i].toURL()); | |
| 962 | |
| 963 var destName = 'Archive'; | |
| 964 if (task.originalEntries.length == 1) { | |
| 965 var entryPath = task.originalEntries[0].fullPath; | |
| 966 var i = entryPath.lastIndexOf('/'); | |
| 967 var basename = (i < 0) ? entryPath : entryPath.substr(i + 1); | |
| 968 i = basename.lastIndexOf('.'); | |
| 969 destName = ((i < 0) ? basename : basename.substr(0, i)); | |
| 970 } | |
| 971 | |
| 972 var copyNumber = 0; | |
| 973 var firstExistingEntry = null; | |
| 974 var destPath = destName + '.zip'; | |
| 975 | |
| 976 function onError(reason, data) { | |
| 977 self.log_('serviceZipTask error: ' + reason + ':', data); | |
| 978 errorCallback(new FileCopyManager.Error(reason, data)); | |
| 979 } | |
| 980 | |
| 981 function onTargetExists(existingEntry) { | |
| 982 if (copyNumber < 10) { | |
| 983 if (!firstExistingEntry) | |
| 984 firstExistingEntry = existingEntry; | |
| 985 copyNumber++; | |
| 986 tryZipSelection(); | |
| 987 } else { | |
| 988 onError('TARGET_EXISTS', firstExistingEntry); | |
| 989 } | |
| 990 } | |
| 991 | |
| 992 function onTargetNotResolved() { | |
| 993 function onZipSelectionComplete() { | |
| 994 self.sendProgressEvent_('SUCCESS'); | |
| 995 completeCallback(task); | |
| 996 } | |
| 997 | |
| 998 self.sendProgressEvent_('PROGRESS'); | |
| 999 chrome.fileBrowserPrivate.zipSelection(dirURL, selectionURLs, destPath, | |
| 1000 onZipSelectionComplete); | |
| 1001 } | |
| 1002 | |
| 1003 function tryZipSelection() { | |
| 1004 if (copyNumber > 0) | |
| 1005 destPath = destName + ' (' + copyNumber + ').zip'; | |
| 1006 | |
| 1007 // Check if the target exists. This kicks off the rest of the zip file | |
| 1008 // creation if the target is not found, or raises an error if it does. | |
| 1009 util.resolvePath(task.targetDirEntry, destPath, onTargetExists, | |
| 1010 onTargetNotResolved); | |
| 1011 } | |
| 1012 | |
| 1013 tryZipSelection(); | |
| 1014 }; | |
| 1015 | |
| 1016 /** | |
| 939 * Copy the contents of sourceEntry into targetEntry. | 1017 * Copy the contents of sourceEntry into targetEntry. |
| 940 * | 1018 * |
| 941 * @private | 1019 * @private |
| 942 * @param {Entry} sourceEntry entry that will be copied. | 1020 * @param {Entry} sourceEntry entry that will be copied. |
| 943 * @param {Entry} targetEntry entry to which sourceEntry will be copied. | 1021 * @param {Entry} targetEntry entry to which sourceEntry will be copied. |
| 944 * @param {function(Entry, number)} progressCallback function that will be | 1022 * @param {function(Entry, number)} progressCallback function that will be |
| 945 * called when a part of the source entry is copied. It takes |targetEntry| | 1023 * called when a part of the source entry is copied. It takes |targetEntry| |
| 946 * and size of the last copied chunk as parameters. | 1024 * and size of the last copied chunk as parameters. |
| 947 * @param {function(Entry, number)} successCallback function that will be called | 1025 * @param {function(Entry, number)} successCallback function that will be called |
| 948 * the copy operation finishes. It takes |targetEntry| and size of the last | 1026 * the copy operation finishes. It takes |targetEntry| and size of the last |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1015 id: id, | 1093 id: id, |
| 1016 timeout: setTimeout(this.forceDeleteTask.bind(this, id), | 1094 timeout: setTimeout(this.forceDeleteTask.bind(this, id), |
| 1017 FileCopyManager.DELETE_TIMEOUT) | 1095 FileCopyManager.DELETE_TIMEOUT) |
| 1018 }; | 1096 }; |
| 1019 this.deleteTasks_.push(task); | 1097 this.deleteTasks_.push(task); |
| 1020 callback(id); | 1098 callback(id); |
| 1021 this.sendDeleteEvent_(task, 'SCHEDULED'); | 1099 this.sendDeleteEvent_(task, 'SCHEDULED'); |
| 1022 }; | 1100 }; |
| 1023 | 1101 |
| 1024 /** | 1102 /** |
| 1103 * Creates a zip file for the selection of files. | |
| 1104 * @param {Entry} dirEntry the directory containing the selection. | |
| 1105 * @param {boolean} isOnGData If directory is on GDrive. | |
| 1106 * @param {Array.<Entry>} selectionEntries the selected entries. | |
| 1107 */ | |
| 1108 FileCopyManager.prototype.zipSelection = function(dirEntry, isOnGData, | |
| 1109 selectionEntries) { | |
| 1110 var self = this; | |
| 1111 var zipTask = new FileCopyManager.Task(dirEntry, dirEntry); | |
| 1112 zipTask.zip = true; | |
| 1113 zipTask.sourceOnGData = isOnGData; | |
| 1114 zipTask.targetOnGData = isOnGData; | |
| 1115 zipTask.setEntries(selectionEntries, function() { | |
| 1116 // TODO: per-entry zip progress update with accurate byte count. | |
| 1117 // For now just set pendingBytes to zero so that the progress bar is full. | |
| 1118 zipTask.pendingBytes = 0; | |
| 1119 self.copyTasks_.push(zipTask); | |
| 1120 if (self.copyTasks_.length == 1) { | |
| 1121 // Assume self.cancelRequested_ == false. | |
| 1122 // This moved us from 0 to 1 active tasks, let the servicing begin! | |
| 1123 self.serviceAllTasks_(); | |
| 1124 } else { | |
| 1125 // Force to update the progress of butter bar when there are new tasks | |
| 1126 // coming while servicing current task. | |
| 1127 self.sendProgressEvent_('PROGRESS'); | |
| 1128 } | |
| 1129 }); | |
| 1130 }; | |
| 1131 | |
| 1132 /** | |
| 1025 * Force deletion before timeout runs out. | 1133 * Force deletion before timeout runs out. |
| 1026 * @param {number} id The delete task id (as returned by deleteEntries). | 1134 * @param {number} id The delete task id (as returned by deleteEntries). |
| 1027 */ | 1135 */ |
| 1028 FileCopyManager.prototype.forceDeleteTask = function(id) { | 1136 FileCopyManager.prototype.forceDeleteTask = function(id) { |
| 1029 var task = this.findDeleteTaskAndCancelTimeout_(id); | 1137 var task = this.findDeleteTaskAndCancelTimeout_(id); |
| 1030 if (task) this.serviceDeleteTask_(task); | 1138 if (task) this.serviceDeleteTask_(task); |
| 1031 }; | 1139 }; |
| 1032 | 1140 |
| 1033 /** | 1141 /** |
| 1034 * Cancels the scheduled deletion. | 1142 * Cancels the scheduled deletion. |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1091 */ | 1199 */ |
| 1092 FileCopyManager.prototype.sendDeleteEvent_ = function(task, reason) { | 1200 FileCopyManager.prototype.sendDeleteEvent_ = function(task, reason) { |
| 1093 this.sendEvent_('delete', { | 1201 this.sendEvent_('delete', { |
| 1094 reason: reason, | 1202 reason: reason, |
| 1095 id: task.id, | 1203 id: task.id, |
| 1096 urls: task.entries.map(function(e) { | 1204 urls: task.entries.map(function(e) { |
| 1097 return util.makeFilesystemUrl(e.fullPath); | 1205 return util.makeFilesystemUrl(e.fullPath); |
| 1098 }) | 1206 }) |
| 1099 }); | 1207 }); |
| 1100 }; | 1208 }; |
| OLD | NEW |