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

Side by Side Diff: chrome/browser/resources/file_manager/js/file_copy_manager.js

Issue 11309014: File manager: support for zipping selected files. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Toni's comments for Patch Sets #13, #17 and #22. Created 8 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 643
640 self.sendProgressEvent_('PROGRESS'); 644 self.sendProgressEvent_('PROGRESS');
641 645
642 // We yield a few ms between copies to give the browser a chance to service 646 // We yield a few ms between copies to give the browser a chance to service
643 // events (like perhaps the user clicking to cancel the copy, for example). 647 // events (like perhaps the user clicking to cancel the copy, for example).
644 setTimeout(function() { 648 setTimeout(function() {
645 self.serviceNextTaskEntry_(task, onEntryServiced, errorCallback); 649 self.serviceNextTaskEntry_(task, onEntryServiced, errorCallback);
646 }, 10); 650 }, 10);
647 } 651 }
648 652
649 this.serviceNextTaskEntry_(task, onEntryServiced, errorCallback); 653 if (!task.zip)
654 this.serviceNextTaskEntry_(task, onEntryServiced, errorCallback);
655 else
656 this.serviceZipTask_(task, onTaskComplete, errorCallback);
650 }; 657 };
651 658
652 /** 659 /**
653 * Service the next entry in a given task. 660 * Service the next entry in a given task.
654 * TODO(olege): Refactor this method into a separate class. 661 * TODO(olege): Refactor this method into a separate class.
655 * 662 *
656 * @private 663 * @private
657 * @param {FileManager.Task} task A task. 664 * @param {FileManager.Task} task A task.
658 * @param {Function} successCallback On success. 665 * @param {Function} successCallback On success.
659 * @param {Function} errorCallback On error. 666 * @param {Function} errorCallback On error.
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
969 // Check to see if the target exists. This kicks off the rest of the copy 976 // Check to see if the target exists. This kicks off the rest of the copy
970 // if the target is not found, or raises an error if it does. 977 // if the target is not found, or raises an error if it does.
971 util.resolvePath(targetDirEntry, targetRelativePath, onTargetExists, 978 util.resolvePath(targetDirEntry, targetRelativePath, onTargetExists,
972 onTargetNotResolved); 979 onTargetNotResolved);
973 } 980 }
974 981
975 tryNextCopy(); 982 tryNextCopy();
976 }; 983 };
977 984
978 /** 985 /**
986 * Service a zip file creation task.
987 *
988 * @private
989 * @param {FileManager.Task} task A task.
990 * @param {Function} completeCallback On complete.
991 * @param {Function} errorCallback On error.
992 */
993 FileCopyManager.prototype.serviceZipTask_ = function(task, completeCallback,
994 errorCallback) {
995 var self = this;
996 var dirURL = task.sourceDirEntry.toURL();
997 var selectionURLs = [];
998 for (var i = 0; i < task.pendingDirectories.length; i++)
999 selectionURLs.push(task.pendingDirectories[i].toURL());
1000 for (var i = 0; i < task.pendingFiles.length; i++)
1001 selectionURLs.push(task.pendingFiles[i].toURL());
1002
1003 var destName = 'Archive';
1004 if (task.originalEntries.length == 1) {
1005 var entryPath = task.originalEntries[0].fullPath;
1006 var i = entryPath.lastIndexOf('/');
1007 var basename = (i < 0) ? entryPath : entryPath.substr(i + 1);
1008 i = basename.lastIndexOf('.');
1009 destName = ((i < 0) ? basename : basename.substr(0, i));
1010 }
1011
1012 var copyNumber = 0;
1013 var firstExistingEntry = null;
1014 var destPath = destName + '.zip';
1015
1016 function onError(reason, data) {
1017 self.log_('serviceZipTask error: ' + reason + ':', data);
1018 errorCallback(new FileCopyManager.Error(reason, data));
1019 }
1020
1021 function onTargetExists(existingEntry) {
1022 if (copyNumber < 10) {
1023 if (!firstExistingEntry)
1024 firstExistingEntry = existingEntry;
1025 copyNumber++;
1026 tryZipSelection();
1027 } else {
1028 onError('TARGET_EXISTS', firstExistingEntry);
1029 }
1030 }
1031
1032 function onTargetNotResolved() {
1033 function onZipSelectionComplete(success) {
1034 if (success) {
1035 self.sendProgressEvent_('SUCCESS');
1036 } else {
1037 self.sendProgressEvent_('ERROR',
1038 new FileCopyManager.Error('FILESYSTEM_ERROR', ''));
1039 }
1040 completeCallback(task);
1041 }
1042
1043 self.sendProgressEvent_('PROGRESS');
1044 chrome.fileBrowserPrivate.zipSelection(dirURL, selectionURLs, destPath,
1045 onZipSelectionComplete);
1046 }
1047
1048 function tryZipSelection() {
1049 if (copyNumber > 0)
1050 destPath = destName + ' (' + copyNumber + ').zip';
1051
1052 // Check if the target exists. This kicks off the rest of the zip file
1053 // creation if the target is not found, or raises an error if it does.
1054 util.resolvePath(task.targetDirEntry, destPath, onTargetExists,
1055 onTargetNotResolved);
1056 }
1057
1058 tryZipSelection();
1059 };
1060
1061 /**
979 * Copy the contents of sourceEntry into targetEntry. 1062 * Copy the contents of sourceEntry into targetEntry.
980 * 1063 *
981 * @private 1064 * @private
982 * @param {Entry} sourceEntry entry that will be copied. 1065 * @param {Entry} sourceEntry entry that will be copied.
983 * @param {Entry} targetEntry entry to which sourceEntry will be copied. 1066 * @param {Entry} targetEntry entry to which sourceEntry will be copied.
984 * @param {function(Entry, number)} progressCallback function that will be 1067 * @param {function(Entry, number)} progressCallback function that will be
985 * called when a part of the source entry is copied. It takes |targetEntry| 1068 * called when a part of the source entry is copied. It takes |targetEntry|
986 * and size of the last copied chunk as parameters. 1069 * and size of the last copied chunk as parameters.
987 * @param {function(Entry, number)} successCallback function that will be called 1070 * @param {function(Entry, number)} successCallback function that will be called
988 * the copy operation finishes. It takes |targetEntry| and size of the last 1071 * the copy operation finishes. It takes |targetEntry| and size of the last
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1056 timeout: setTimeout(this.forceDeleteTask.bind(this, id), 1139 timeout: setTimeout(this.forceDeleteTask.bind(this, id),
1057 FileCopyManager.DELETE_TIMEOUT) 1140 FileCopyManager.DELETE_TIMEOUT)
1058 }; 1141 };
1059 this.deleteTasks_.push(task); 1142 this.deleteTasks_.push(task);
1060 this.maybeScheduleCloseBackgroundPage_(); 1143 this.maybeScheduleCloseBackgroundPage_();
1061 callback(id); 1144 callback(id);
1062 this.sendDeleteEvent_(task, 'SCHEDULED'); 1145 this.sendDeleteEvent_(task, 'SCHEDULED');
1063 }; 1146 };
1064 1147
1065 /** 1148 /**
1149 * Creates a zip file for the selection of files.
1150 * @param {Entry} dirEntry the directory containing the selection.
1151 * @param {boolean} isOnGData If directory is on GDrive.
1152 * @param {Array.<Entry>} selectionEntries the selected entries.
1153 */
1154 FileCopyManager.prototype.zipSelection = function(dirEntry, isOnGData,
1155 selectionEntries) {
1156 var self = this;
1157 var zipTask = new FileCopyManager.Task(dirEntry, dirEntry);
1158 zipTask.zip = true;
1159 zipTask.sourceOnGData = isOnGData;
1160 zipTask.targetOnGData = isOnGData;
1161 zipTask.setEntries(selectionEntries, function() {
1162 // TODO: per-entry zip progress update with accurate byte count.
1163 // For now just set pendingBytes to zero so that the progress bar is full.
1164 zipTask.pendingBytes = 0;
1165 self.copyTasks_.push(zipTask);
1166 if (self.copyTasks_.length == 1) {
1167 // Assume self.cancelRequested_ == false.
1168 // This moved us from 0 to 1 active tasks, let the servicing begin!
1169 self.serviceAllTasks_();
1170 } else {
1171 // Force to update the progress of butter bar when there are new tasks
1172 // coming while servicing current task.
1173 self.sendProgressEvent_('PROGRESS');
1174 }
1175 });
1176 };
1177
1178 /**
1066 * Force deletion before timeout runs out. 1179 * Force deletion before timeout runs out.
1067 * @param {number} id The delete task id (as returned by deleteEntries). 1180 * @param {number} id The delete task id (as returned by deleteEntries).
1068 */ 1181 */
1069 FileCopyManager.prototype.forceDeleteTask = function(id) { 1182 FileCopyManager.prototype.forceDeleteTask = function(id) {
1070 var task = this.findDeleteTaskAndCancelTimeout_(id); 1183 var task = this.findDeleteTaskAndCancelTimeout_(id);
1071 if (task) this.serviceDeleteTask_(task); 1184 if (task) this.serviceDeleteTask_(task);
1072 }; 1185 };
1073 1186
1074 /** 1187 /**
1075 * Cancels the scheduled deletion. 1188 * Cancels the scheduled deletion.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 */ 1246 */
1134 FileCopyManager.prototype.sendDeleteEvent_ = function(task, reason) { 1247 FileCopyManager.prototype.sendDeleteEvent_ = function(task, reason) {
1135 this.sendEvent_('delete', { 1248 this.sendEvent_('delete', {
1136 reason: reason, 1249 reason: reason,
1137 id: task.id, 1250 id: task.id,
1138 urls: task.entries.map(function(e) { 1251 urls: task.entries.map(function(e) {
1139 return util.makeFilesystemUrl(e.fullPath); 1252 return util.makeFilesystemUrl(e.fullPath);
1140 }) 1253 })
1141 }); 1254 });
1142 }; 1255 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698