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

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: Fix compiler warning: declare base::FileDescriptor a struct, not a class. The struct is put after t… 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 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
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
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
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
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
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
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 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698