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

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: Set the pending bytes for zip task to zero. TODO: need to implement per-entry progress update to tr… 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 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698