| 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 if (chrome.extension) { | 5 if (chrome.extension) { |
| 6 function getContentWindows() { | 6 function getContentWindows() { |
| 7 return chrome.extension.getViews(); | 7 return chrome.extension.getViews(); |
| 8 } | 8 } |
| 9 } | 9 } |
| 10 | 10 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 this.pendingDirectories = []; | 60 this.pendingDirectories = []; |
| 61 this.pendingFiles = []; | 61 this.pendingFiles = []; |
| 62 this.pendingBytes = 0; | 62 this.pendingBytes = 0; |
| 63 | 63 |
| 64 this.completedDirectories = []; | 64 this.completedDirectories = []; |
| 65 this.completedFiles = []; | 65 this.completedFiles = []; |
| 66 this.completedBytes = 0; | 66 this.completedBytes = 0; |
| 67 | 67 |
| 68 this.deleteAfterCopy = false; | 68 this.deleteAfterCopy = false; |
| 69 this.move = false; | 69 this.move = false; |
| 70 this.zip = false; |
| 70 this.sourceOnGData = false; | 71 this.sourceOnGData = false; |
| 71 this.targetOnGData = false; | 72 this.targetOnGData = false; |
| 72 | 73 |
| 73 // If directory already exists, we try to make a copy named 'dir (X)', | 74 // If directory already exists, we try to make a copy named 'dir (X)', |
| 74 // where X is a number. When we do this, all subsequent copies from | 75 // where X is a number. When we do this, all subsequent copies from |
| 75 // inside the subtree should be mapped to the new directory name. | 76 // inside the subtree should be mapped to the new directory name. |
| 76 // For example, if 'dir' was copied as 'dir (1)', then 'dir\file.txt' should | 77 // For example, if 'dir' was copied as 'dir (1)', then 'dir\file.txt' should |
| 77 // become 'dir (1)\file.txt'. | 78 // become 'dir (1)\file.txt'. |
| 78 this.renamedDirectories_ = []; | 79 this.renamedDirectories_ = []; |
| 79 }; | 80 }; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 pendingBytes: 0, | 230 pendingBytes: 0, |
| 230 | 231 |
| 231 completedItems: 0, // Files + Directories | 232 completedItems: 0, // Files + Directories |
| 232 completedFiles: 0, | 233 completedFiles: 0, |
| 233 completedDirectories: 0, | 234 completedDirectories: 0, |
| 234 completedBytes: 0, | 235 completedBytes: 0, |
| 235 | 236 |
| 236 percentage: NaN, | 237 percentage: NaN, |
| 237 pendingCopies: 0, | 238 pendingCopies: 0, |
| 238 pendingMoves: 0, | 239 pendingMoves: 0, |
| 240 pendingZips: 0, |
| 239 filename: '' // In case pendingItems == 1 | 241 filename: '' // In case pendingItems == 1 |
| 240 }; | 242 }; |
| 241 | 243 |
| 242 var pendingFile = null; | 244 var pendingFile = null; |
| 243 | 245 |
| 244 for (var i = 0; i < this.copyTasks_.length; i++) { | 246 for (var i = 0; i < this.copyTasks_.length; i++) { |
| 245 var task = this.copyTasks_[i]; | 247 var task = this.copyTasks_[i]; |
| 246 var pendingFiles = task.pendingFiles.length; | 248 var pendingFiles = task.pendingFiles.length; |
| 247 var pendingDirectories = task.pendingDirectories.length; | 249 var pendingDirectories = task.pendingDirectories.length; |
| 248 rv.pendingFiles += pendingFiles; | 250 rv.pendingFiles += pendingFiles; |
| 249 rv.pendingDirectories += pendingDirectories; | 251 rv.pendingDirectories += pendingDirectories; |
| 250 rv.pendingBytes += task.pendingBytes; | 252 rv.pendingBytes += task.pendingBytes; |
| 251 | 253 |
| 252 rv.completedFiles += task.completedFiles.length; | 254 rv.completedFiles += task.completedFiles.length; |
| 253 rv.completedDirectories += task.completedDirectories.length; | 255 rv.completedDirectories += task.completedDirectories.length; |
| 254 rv.completedBytes += task.completedBytes; | 256 rv.completedBytes += task.completedBytes; |
| 255 | 257 |
| 256 if (task.move || task.deleteAfterCopy) { | 258 if (task.zip) { |
| 259 rv.pendingZips += pendingFiles + pendingDirectories; |
| 260 } else if (task.move || task.deleteAfterCopy) { |
| 257 rv.pendingMoves += pendingFiles + pendingDirectories; | 261 rv.pendingMoves += pendingFiles + pendingDirectories; |
| 258 } else { | 262 } else { |
| 259 rv.pendingCopies += pendingFiles + pendingDirectories; | 263 rv.pendingCopies += pendingFiles + pendingDirectories; |
| 260 } | 264 } |
| 261 | 265 |
| 262 if (task.pendingFiles.length === 1) | 266 if (task.pendingFiles.length === 1) |
| 263 pendingFile = task.pendingFiles[0]; | 267 pendingFile = task.pendingFiles[0]; |
| 264 | 268 |
| 265 if (task.pendingDirectories.length === 1) | 269 if (task.pendingDirectories.length === 1) |
| 266 pendingFile = task.pendingDirectories[0]; | 270 pendingFile = task.pendingDirectories[0]; |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 | 651 |
| 648 self.sendProgressEvent_('PROGRESS'); | 652 self.sendProgressEvent_('PROGRESS'); |
| 649 | 653 |
| 650 // We yield a few ms between copies to give the browser a chance to service | 654 // We yield a few ms between copies to give the browser a chance to service |
| 651 // events (like perhaps the user clicking to cancel the copy, for example). | 655 // events (like perhaps the user clicking to cancel the copy, for example). |
| 652 setTimeout(function() { | 656 setTimeout(function() { |
| 653 self.serviceNextTaskEntry_(task, onEntryServiced, errorCallback); | 657 self.serviceNextTaskEntry_(task, onEntryServiced, errorCallback); |
| 654 }, 10); | 658 }, 10); |
| 655 } | 659 } |
| 656 | 660 |
| 657 this.serviceNextTaskEntry_(task, onEntryServiced, errorCallback); | 661 if (!task.zip) |
| 662 this.serviceNextTaskEntry_(task, onEntryServiced, errorCallback); |
| 663 else |
| 664 this.serviceZipTask_(task, onTaskComplete, errorCallback); |
| 658 }; | 665 }; |
| 659 | 666 |
| 660 /** | 667 /** |
| 661 * Service the next entry in a given task. | 668 * Service the next entry in a given task. |
| 662 * TODO(olege): Refactor this method into a separate class. | 669 * TODO(olege): Refactor this method into a separate class. |
| 663 * | 670 * |
| 664 * @private | 671 * @private |
| 665 * @param {FileManager.Task} task A task. | 672 * @param {FileManager.Task} task A task. |
| 666 * @param {Function} successCallback On success. | 673 * @param {Function} successCallback On success. |
| 667 * @param {Function} errorCallback On error. | 674 * @param {Function} errorCallback On error. |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 // Check to see if the target exists. This kicks off the rest of the copy | 984 // Check to see if the target exists. This kicks off the rest of the copy |
| 978 // if the target is not found, or raises an error if it does. | 985 // if the target is not found, or raises an error if it does. |
| 979 util.resolvePath(targetDirEntry, targetRelativePath, onTargetExists, | 986 util.resolvePath(targetDirEntry, targetRelativePath, onTargetExists, |
| 980 onTargetNotResolved); | 987 onTargetNotResolved); |
| 981 } | 988 } |
| 982 | 989 |
| 983 tryNextCopy(); | 990 tryNextCopy(); |
| 984 }; | 991 }; |
| 985 | 992 |
| 986 /** | 993 /** |
| 994 * Service a zip file creation task. |
| 995 * |
| 996 * @private |
| 997 * @param {FileManager.Task} task A task. |
| 998 * @param {Function} completeCallback On complete. |
| 999 * @param {Function} errorCallback On error. |
| 1000 */ |
| 1001 FileCopyManager.prototype.serviceZipTask_ = function(task, completeCallback, |
| 1002 errorCallback) { |
| 1003 var self = this; |
| 1004 var dirURL = task.sourceDirEntry.toURL(); |
| 1005 var selectionURLs = []; |
| 1006 for (var i = 0; i < task.pendingDirectories.length; i++) |
| 1007 selectionURLs.push(task.pendingDirectories[i].toURL()); |
| 1008 for (var i = 0; i < task.pendingFiles.length; i++) |
| 1009 selectionURLs.push(task.pendingFiles[i].toURL()); |
| 1010 |
| 1011 var destName = 'Archive'; |
| 1012 if (task.originalEntries.length == 1) { |
| 1013 var entryPath = task.originalEntries[0].fullPath; |
| 1014 var i = entryPath.lastIndexOf('/'); |
| 1015 var basename = (i < 0) ? entryPath : entryPath.substr(i + 1); |
| 1016 i = basename.lastIndexOf('.'); |
| 1017 destName = ((i < 0) ? basename : basename.substr(0, i)); |
| 1018 } |
| 1019 |
| 1020 var copyNumber = 0; |
| 1021 var firstExistingEntry = null; |
| 1022 var destPath = destName + '.zip'; |
| 1023 |
| 1024 function onError(reason, data) { |
| 1025 self.log_('serviceZipTask error: ' + reason + ':', data); |
| 1026 errorCallback(new FileCopyManager.Error(reason, data)); |
| 1027 } |
| 1028 |
| 1029 function onTargetExists(existingEntry) { |
| 1030 if (copyNumber < 10) { |
| 1031 if (!firstExistingEntry) |
| 1032 firstExistingEntry = existingEntry; |
| 1033 copyNumber++; |
| 1034 tryZipSelection(); |
| 1035 } else { |
| 1036 onError('TARGET_EXISTS', firstExistingEntry); |
| 1037 } |
| 1038 } |
| 1039 |
| 1040 function onTargetNotResolved() { |
| 1041 function onZipSelectionComplete(success) { |
| 1042 if (success) { |
| 1043 self.sendProgressEvent_('SUCCESS'); |
| 1044 } else { |
| 1045 self.sendProgressEvent_('ERROR', |
| 1046 new FileCopyManager.Error('FILESYSTEM_ERROR', '')); |
| 1047 } |
| 1048 completeCallback(task); |
| 1049 } |
| 1050 |
| 1051 self.sendProgressEvent_('PROGRESS'); |
| 1052 chrome.fileBrowserPrivate.zipSelection(dirURL, selectionURLs, destPath, |
| 1053 onZipSelectionComplete); |
| 1054 } |
| 1055 |
| 1056 function tryZipSelection() { |
| 1057 if (copyNumber > 0) |
| 1058 destPath = destName + ' (' + copyNumber + ').zip'; |
| 1059 |
| 1060 // Check if the target exists. This kicks off the rest of the zip file |
| 1061 // creation if the target is not found, or raises an error if it does. |
| 1062 util.resolvePath(task.targetDirEntry, destPath, onTargetExists, |
| 1063 onTargetNotResolved); |
| 1064 } |
| 1065 |
| 1066 tryZipSelection(); |
| 1067 }; |
| 1068 |
| 1069 /** |
| 987 * Copy the contents of sourceEntry into targetEntry. | 1070 * Copy the contents of sourceEntry into targetEntry. |
| 988 * | 1071 * |
| 989 * @private | 1072 * @private |
| 990 * @param {Entry} sourceEntry entry that will be copied. | 1073 * @param {Entry} sourceEntry entry that will be copied. |
| 991 * @param {Entry} targetEntry entry to which sourceEntry will be copied. | 1074 * @param {Entry} targetEntry entry to which sourceEntry will be copied. |
| 992 * @param {function(Entry, number)} progressCallback function that will be | 1075 * @param {function(Entry, number)} progressCallback function that will be |
| 993 * called when a part of the source entry is copied. It takes |targetEntry| | 1076 * called when a part of the source entry is copied. It takes |targetEntry| |
| 994 * and size of the last copied chunk as parameters. | 1077 * and size of the last copied chunk as parameters. |
| 995 * @param {function(Entry, number)} successCallback function that will be called | 1078 * @param {function(Entry, number)} successCallback function that will be called |
| 996 * the copy operation finishes. It takes |targetEntry| and size of the last | 1079 * the copy operation finishes. It takes |targetEntry| and size of the last |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1064 timeout: setTimeout(this.forceDeleteTask.bind(this, id), | 1147 timeout: setTimeout(this.forceDeleteTask.bind(this, id), |
| 1065 FileCopyManager.DELETE_TIMEOUT) | 1148 FileCopyManager.DELETE_TIMEOUT) |
| 1066 }; | 1149 }; |
| 1067 this.deleteTasks_.push(task); | 1150 this.deleteTasks_.push(task); |
| 1068 this.maybeScheduleCloseBackgroundPage_(); | 1151 this.maybeScheduleCloseBackgroundPage_(); |
| 1069 callback(id); | 1152 callback(id); |
| 1070 this.sendDeleteEvent_(task, 'SCHEDULED'); | 1153 this.sendDeleteEvent_(task, 'SCHEDULED'); |
| 1071 }; | 1154 }; |
| 1072 | 1155 |
| 1073 /** | 1156 /** |
| 1157 * Creates a zip file for the selection of files. |
| 1158 * @param {Entry} dirEntry the directory containing the selection. |
| 1159 * @param {boolean} isOnGData If directory is on GDrive. |
| 1160 * @param {Array.<Entry>} selectionEntries the selected entries. |
| 1161 */ |
| 1162 FileCopyManager.prototype.zipSelection = function(dirEntry, isOnGData, |
| 1163 selectionEntries) { |
| 1164 var self = this; |
| 1165 var zipTask = new FileCopyManager.Task(dirEntry, dirEntry); |
| 1166 zipTask.zip = true; |
| 1167 zipTask.sourceOnGData = isOnGData; |
| 1168 zipTask.targetOnGData = isOnGData; |
| 1169 zipTask.setEntries(selectionEntries, function() { |
| 1170 // TODO: per-entry zip progress update with accurate byte count. |
| 1171 // For now just set pendingBytes to zero so that the progress bar is full. |
| 1172 zipTask.pendingBytes = 0; |
| 1173 self.copyTasks_.push(zipTask); |
| 1174 if (self.copyTasks_.length == 1) { |
| 1175 // Assume self.cancelRequested_ == false. |
| 1176 // This moved us from 0 to 1 active tasks, let the servicing begin! |
| 1177 self.serviceAllTasks_(); |
| 1178 } else { |
| 1179 // Force to update the progress of butter bar when there are new tasks |
| 1180 // coming while servicing current task. |
| 1181 self.sendProgressEvent_('PROGRESS'); |
| 1182 } |
| 1183 }); |
| 1184 }; |
| 1185 |
| 1186 /** |
| 1074 * Force deletion before timeout runs out. | 1187 * Force deletion before timeout runs out. |
| 1075 * @param {number} id The delete task id (as returned by deleteEntries). | 1188 * @param {number} id The delete task id (as returned by deleteEntries). |
| 1076 */ | 1189 */ |
| 1077 FileCopyManager.prototype.forceDeleteTask = function(id) { | 1190 FileCopyManager.prototype.forceDeleteTask = function(id) { |
| 1078 var task = this.findDeleteTaskAndCancelTimeout_(id); | 1191 var task = this.findDeleteTaskAndCancelTimeout_(id); |
| 1079 if (task) this.serviceDeleteTask_(task); | 1192 if (task) this.serviceDeleteTask_(task); |
| 1080 }; | 1193 }; |
| 1081 | 1194 |
| 1082 /** | 1195 /** |
| 1083 * Cancels the scheduled deletion. | 1196 * Cancels the scheduled deletion. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 */ | 1254 */ |
| 1142 FileCopyManager.prototype.sendDeleteEvent_ = function(task, reason) { | 1255 FileCopyManager.prototype.sendDeleteEvent_ = function(task, reason) { |
| 1143 this.sendEvent_('delete', { | 1256 this.sendEvent_('delete', { |
| 1144 reason: reason, | 1257 reason: reason, |
| 1145 id: task.id, | 1258 id: task.id, |
| 1146 urls: task.entries.map(function(e) { | 1259 urls: task.entries.map(function(e) { |
| 1147 return util.makeFilesystemUrl(e.fullPath); | 1260 return util.makeFilesystemUrl(e.fullPath); |
| 1148 }) | 1261 }) |
| 1149 }); | 1262 }); |
| 1150 }; | 1263 }; |
| OLD | NEW |