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

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

Issue 22291004: Introduce fileOperationUtil. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 'use strict'; 5 'use strict';
6 6
7 /** 7 /**
8 * Utilities for FileCopyManager.
9 */
10 var fileOperationUtil = {};
11
12 /**
13 * Simple wrapper for util.deduplicatePath. On error, this method translates
14 * the FileError to FileCopyManager.Error object.
15 *
16 * @param {DirectoryEntry} dirEntry The target directory entry.
17 * @param {string} relativePath The path to be deduplicated.
18 * @param {function(string)} successCallback Callback run with the deduplicated
19 * path on success.
20 * @param {function(FileCopyManager.Error)} errorCallback Callback run on error.
21 */
22 fileOperationUtil.deduplicatePath = function(
23 dirEntry, relativePath, successCallback, errorCallback) {
24 util.deduplicatePath(
25 dirEntry, relativePath, successCallback,
26 function(err) {
27 var onFileSystemError = function(error) {
28 errorCallback(new FileCopyManager.Error(
29 util.FileOperationErrorType.FILESYSTEM_ERROR, error));
30 };
31
32 if (err.code == FileError.PATH_EXISTS_ERR) {
33 // Failed to uniquify the file path. There should be an existing
34 // entry, so return the error with it.
35 util.resolvePath(
36 dirEntry, relativePath,
37 function(entry) {
38 errorCallback(new FileCopyManager.Error(
39 util.FileOperationErrorType.TARGET_EXISTS, entry));
40 },
41 onFileSystemError);
42 return;
43 }
44 onFileSystemError(err);
45 });
46 };
47
48 /**
49 * Sets last modified date to the entry.
50 * @param {Entry} entry The entry to which the last modified is set.
51 * @param {Date} modificationTime The last modified time.
52 */
53 fileOperationUtil.setLastModified = function(entry, modificationTime) {
54 chrome.fileBrowserPrivate.setLastModified(
55 entry.toURL(), '' + Math.round(modificationTime.getTime() / 1000));
56 };
57
58 /**
59 * Thin wrapper of chrome.fileBrowserPrivate.zipSelection to adapt its
60 * interface similar to copyTo().
61 *
62 * @param {Array.<Entry>} sources The array of entries to be archived.
63 * @param {DirectoryEntry} parent The entry of the destination directory.
64 * @param {string} newName The name of the archive to be created.
65 * @param {function(FileEntry)} successCallback Callback invoked when the
66 * operation is successfully done with the entry of the created archive.
67 * @param {function(FileError)} errorCallback Callback invoked when an error
68 * is found.
69 */
70 fileOperationUtil.zipSelection = function(
71 sources, parent, newName, successCallback, errorCallback) {
72 chrome.fileBrowserPrivate.zipSelection(
73 parent.toURL(),
74 sources.map(function(e) { return e.toURL(); }),
75 newName, function(success) {
76 if (!success) {
77 // Failed to create a zip archive.
78 errorCallback(
79 util.createFileError(FileError.INVALID_MODIFICATION_ERR));
80 return;
81 }
82
83 // Returns the created entry via callback.
84 parent.getFile(
85 newName, {create: false}, successCallback, errorCallback);
86 });
87 };
88
89 /**
8 * @constructor 90 * @constructor
9 */ 91 */
10 function FileCopyManager() { 92 function FileCopyManager() {
11 this.copyTasks_ = []; 93 this.copyTasks_ = [];
12 this.deleteTasks_ = []; 94 this.deleteTasks_ = [];
13 this.cancelObservers_ = []; 95 this.cancelObservers_ = [];
14 this.cancelRequested_ = false; 96 this.cancelRequested_ = false;
15 this.cancelCallback_ = null; 97 this.cancelCallback_ = null;
16 this.unloadTimeout_ = null; 98 this.unloadTimeout_ = null;
17 99
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 this.zip = false; 211 this.zip = false;
130 212
131 // If directory already exists, we try to make a copy named 'dir (X)', 213 // If directory already exists, we try to make a copy named 'dir (X)',
132 // where X is a number. When we do this, all subsequent copies from 214 // where X is a number. When we do this, all subsequent copies from
133 // inside the subtree should be mapped to the new directory name. 215 // inside the subtree should be mapped to the new directory name.
134 // For example, if 'dir' was copied as 'dir (1)', then 'dir\file.txt' should 216 // For example, if 'dir' was copied as 'dir (1)', then 'dir\file.txt' should
135 // become 'dir (1)\file.txt'. 217 // become 'dir (1)\file.txt'.
136 this.renamedDirectories_ = []; 218 this.renamedDirectories_ = [];
137 }; 219 };
138 220
139 /**
140 * Simple wrapper for util.deduplicatePath. On error, this method translates
141 * the FileError to FileCopyManager.Error object.
142 *
143 * @param {DirectoryEntry} dirEntry The target directory entry.
144 * @param {string} relativePath The path to be deduplicated.
145 * @param {function(string)} successCallback Callback run with the deduplicated
146 * path on success.
147 * @param {function(FileCopyManager.Error)} errorCallback Callback run on error.
148 */
149 FileCopyManager.Task.deduplicatePath = function(
150 dirEntry, relativePath, successCallback, errorCallback) {
151 util.deduplicatePath(
152 dirEntry, relativePath, successCallback,
153 function(err) {
154 var onFileSystemError = function(error) {
155 errorCallback(new FileCopyManager.Error(
156 util.FileOperationErrorType.FILESYSTEM_ERROR, error));
157 };
158
159 if (err.code == FileError.PATH_EXISTS_ERR) {
160 // Failed to uniquify the file path. There should be an existing
161 // entry, so return the error with it.
162 util.resolvePath(
163 dirEntry, relativePath,
164 function(entry) {
165 errorCallback(new FileCopyManager.Error(
166 util.FileOperationErrorType.TARGET_EXISTS, entry));
167 },
168 onFileSystemError);
169 return;
170 }
171 onFileSystemError(err);
172 });
173 };
174 221
175 /** 222 /**
176 * @param {Array.<Entry>} entries Entries. 223 * @param {Array.<Entry>} entries Entries.
177 * @param {function()} callback When entries resolved. 224 * @param {function()} callback When entries resolved.
178 */ 225 */
179 FileCopyManager.Task.prototype.setEntries = function(entries, callback) { 226 FileCopyManager.Task.prototype.setEntries = function(entries, callback) {
180 var self = this; 227 var self = this;
181 this.originalEntries = entries; 228 this.originalEntries = entries;
182 // When moving directories, FileEntry.moveTo() is used if both source 229 // When moving directories, FileEntry.moveTo() is used if both source
183 // and target are on Drive. There is no need to recurse into directories. 230 // and target are on Drive. There is no need to recurse into directories.
(...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 function(error) { 946 function(error) {
900 self.cancelCallback_ = null; 947 self.cancelCallback_ = null;
901 onFilesystemError(error); 948 onFilesystemError(error);
902 }); 949 });
903 }, 950 },
904 util.flog('Error getting file: ' + targetRelativePath, 951 util.flog('Error getting file: ' + targetRelativePath,
905 onFilesystemError)); 952 onFilesystemError));
906 return; 953 return;
907 } 954 }
908 955
956 // TODO(hidehiko): Move following code to fileOperationUtil.
957
909 // Sending a file from a) Drive to Drive, b) Drive to local or c) local to 958 // Sending a file from a) Drive to Drive, b) Drive to local or c) local to
910 // Drive. 959 // Drive.
911 var sourceFileUrl = sourceEntry.toURL(); 960 var sourceFileUrl = sourceEntry.toURL();
912 var sourceFilePath = util.extractFilePath(sourceFileUrl); 961 var sourceFilePath = util.extractFilePath(sourceFileUrl);
913 962
914 // Progress callback. 963 // Progress callback.
915 // Because the uploading the file from local cache to Drive server will be 964 // Because the uploading the file from local cache to Drive server will be
916 // done as a part of background Drive file system sync, so for this copy 965 // done as a part of background Drive file system sync, so for this copy
917 // operation, what we need to take care about is only file downloading. 966 // operation, what we need to take care about is only file downloading.
918 var numTransferredBytes = 0; 967 var numTransferredBytes = 0;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 function(error) { 1022 function(error) {
974 self.cancelCallback_ = null; 1023 self.cancelCallback_ = null;
975 chrome.fileBrowserPrivate.onFileTransfersUpdated.removeListener( 1024 chrome.fileBrowserPrivate.onFileTransfersUpdated.removeListener(
976 onFileTransfersUpdated); 1025 onFileTransfersUpdated);
977 onFilesystemError(error); 1026 onFilesystemError(error);
978 }); 1027 });
979 }, 1028 },
980 onFilesystemError); 1029 onFilesystemError);
981 }; 1030 };
982 1031
983 FileCopyManager.Task.deduplicatePath( 1032 fileOperationUtil.deduplicatePath(
984 targetDirEntry, originalPath, onDeduplicated, errorCallback); 1033 targetDirEntry, originalPath, onDeduplicated, errorCallback);
985 }; 1034 };
986 1035
987 /** 1036 /**
988 * Copies the contents of sourceEntry into targetEntry. 1037 * Copies the contents of sourceEntry into targetEntry.
1038 * TODO(hidehiko): Move this method into fileOperationUtil.
989 * 1039 *
990 * @param {FileEntry} sourceEntry The file entry that will be copied. 1040 * @param {FileEntry} sourceEntry The file entry that will be copied.
991 * @param {FileEntry} targetEntry The file entry to which sourceEntry will be 1041 * @param {FileEntry} targetEntry The file entry to which sourceEntry will be
992 * copied. 1042 * copied.
993 * @param {function(FileEntry, number)} progressCallback Function that will be 1043 * @param {function(FileEntry, number)} progressCallback Function that will be
994 * called when a part of the source entry is copied. It takes |targetEntry| 1044 * called when a part of the source entry is copied. It takes |targetEntry|
995 * and size of the last copied chunk as parameters. 1045 * and size of the last copied chunk as parameters.
996 * @param {function(FileEntry, number)} successCallback Function that will be 1046 * @param {function(FileEntry, number)} successCallback Function that will be
997 * called the copy operation finishes. It takes |targetEntry| and size of 1047 * called the copy operation finishes. It takes |targetEntry| and size of
998 * the last (not previously reported) copied chunk as parameters. 1048 * the last (not previously reported) copied chunk as parameters.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1052 errorCallback(util.createFileError(FileError.ABORT_ERR)); 1102 errorCallback(util.createFileError(FileError.ABORT_ERR));
1053 return; 1103 return;
1054 } 1104 }
1055 1105
1056 sourceEntry.getMetadata(function(metadata) { 1106 sourceEntry.getMetadata(function(metadata) {
1057 if (cancelRequested) { 1107 if (cancelRequested) {
1058 errorCallback(util.createFileError(FileError.ABORT_ERR)); 1108 errorCallback(util.createFileError(FileError.ABORT_ERR));
1059 return; 1109 return;
1060 } 1110 }
1061 1111
1062 chrome.fileBrowserPrivate.setLastModified( 1112 fileOperationUtil.setLastModified(
1063 targetEntry.toURL(), 1113 targetEntry, metadata.modificationTime);
1064 '' + Math.round(metadata.modificationTime.getTime() / 1000));
1065 successCallback(targetEntry, file.size - reportedProgress); 1114 successCallback(targetEntry, file.size - reportedProgress);
1066 }); 1115 });
1067 }; 1116 };
1068 1117
1069 writer.write(file); 1118 writer.write(file);
1070 }, errorCallback); 1119 }, errorCallback);
1071 }, errorCallback); 1120 }, errorCallback);
1072 1121
1073 return function() { 1122 return function() {
1074 cancelRequested = true; 1123 cancelRequested = true;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1144 var sourcePath = sourceEntry.originalSourcePath; 1193 var sourcePath = sourceEntry.originalSourcePath;
1145 if (sourceEntry.fullPath.substr(0, sourcePath.length) != sourcePath) { 1194 if (sourceEntry.fullPath.substr(0, sourcePath.length) != sourcePath) {
1146 // We found an entry in the list that is not relative to the base source 1195 // We found an entry in the list that is not relative to the base source
1147 // path, something is wrong. 1196 // path, something is wrong.
1148 errorCallback(new FileCopyManager.Error( 1197 errorCallback(new FileCopyManager.Error(
1149 util.FileOperationErrorType.UNEXPECTED_SOURCE_FILE, 1198 util.FileOperationErrorType.UNEXPECTED_SOURCE_FILE,
1150 sourceEntry.fullPath)); 1199 sourceEntry.fullPath));
1151 return; 1200 return;
1152 } 1201 }
1153 1202
1154 FileCopyManager.Task.deduplicatePath( 1203 fileOperationUtil.deduplicatePath(
1155 task.targetDirEntry, 1204 task.targetDirEntry,
1156 task.applyRenames(sourceEntry.fullPath.substr(sourcePath.length + 1)), 1205 task.applyRenames(sourceEntry.fullPath.substr(sourcePath.length + 1)),
1157 function(targetRelativePath) { 1206 function(targetRelativePath) {
1158 var onFilesystemError = function(err) { 1207 var onFilesystemError = function(err) {
1159 errorCallback(new FileCopyManager.Error( 1208 errorCallback(new FileCopyManager.Error(
1160 util.FileOperationErrorType.FILESYSTEM_ERROR, 1209 util.FileOperationErrorType.FILESYSTEM_ERROR,
1161 err)); 1210 err));
1162 }; 1211 };
1163 1212
1164 task.targetDirEntry.getDirectory( 1213 task.targetDirEntry.getDirectory(
(...skipping 24 matching lines...) Expand all
1189 * invoked when an entry is changed. 1238 * invoked when an entry is changed.
1190 * @param {function()} progressCallback Callback invoked periodically during 1239 * @param {function()} progressCallback Callback invoked periodically during
1191 * the moving. 1240 * the moving.
1192 * @param {function()} successCallback On complete. 1241 * @param {function()} successCallback On complete.
1193 * @param {function(FileCopyManager.Error)} errorCallback On error. 1242 * @param {function(FileCopyManager.Error)} errorCallback On error.
1194 * @private 1243 * @private
1195 */ 1244 */
1196 FileCopyManager.prototype.serviceZipTask_ = function( 1245 FileCopyManager.prototype.serviceZipTask_ = function(
1197 task, entryChangedCallback, progressCallback, successCallback, 1246 task, entryChangedCallback, progressCallback, successCallback,
1198 errorCallback) { 1247 errorCallback) {
1199 var dirURL = task.zipBaseDirEntry.toURL();
1200 var selectionURLs = [];
1201 for (var i = 0; i < task.pendingDirectories.length; i++)
1202 selectionURLs.push(task.pendingDirectories[i].toURL());
1203 for (var i = 0; i < task.pendingFiles.length; i++)
1204 selectionURLs.push(task.pendingFiles[i].toURL());
1205
1206 // TODO(hidehiko): we should localize the name. 1248 // TODO(hidehiko): we should localize the name.
1207 var destName = 'Archive'; 1249 var destName = 'Archive';
1208 if (task.originalEntries.length == 1) { 1250 if (task.originalEntries.length == 1) {
1209 var entryPath = task.originalEntries[0].fullPath; 1251 var entryPath = task.originalEntries[0].fullPath;
1210 var i = entryPath.lastIndexOf('/'); 1252 var i = entryPath.lastIndexOf('/');
1211 var basename = (i < 0) ? entryPath : entryPath.substr(i + 1); 1253 var basename = (i < 0) ? entryPath : entryPath.substr(i + 1);
1212 i = basename.lastIndexOf('.'); 1254 i = basename.lastIndexOf('.');
1213 destName = ((i < 0) ? basename : basename.substr(0, i)); 1255 destName = ((i < 0) ? basename : basename.substr(0, i));
1214 } 1256 }
1215 1257
1216 var onDeduplicated = function(destPath) { 1258 fileOperationUtil.deduplicatePath(
1217 var onZipSelectionComplete = function(success) { 1259 task.targetDirEntry, destName + '.zip',
1218 var onFilesystemError = function(err) { 1260 function(destPath) {
1219 errorCallback(new FileCopyManager.Error( 1261 progressCallback();
1220 util.FileOperationErrorType.FILESYSTEM_ERROR,
1221 err));
1222 };
1223 1262
1224 if (success) { 1263 fileOperationUtil.zipSelection(
1225 task.targetDirEntry.getFile( 1264 task.pendingDirectories.concat(task.pendingFiles),
1226 destPath, {create: false}, 1265 task.zipBaseDirEntry,
1266 destPath,
1227 function(entry) { 1267 function(entry) {
1228 entryChangedCallback(util.EntryChangedType.CREATE, entry); 1268 entryChangedCallback(util.EntryChangedType.CREATE, entry);
1229 successCallback(); 1269 successCallback();
1230 }, 1270 },
1231 onFilesystemError); 1271 function(error) {
1232 } else { 1272 errorCallback(new FileCopyManager.Error(
1233 onFilesystemError( 1273 util.FileOperationErrorType.FILESYSTEM_ERROR, error));
1234 util.createFileError(FileError.INVALID_MODIFICATION_ERR)); 1274 });
1235 } 1275 },
1236 }; 1276 errorCallback);
1237
1238 progressCallback();
1239 chrome.fileBrowserPrivate.zipSelection(dirURL, selectionURLs, destPath,
1240 onZipSelectionComplete);
1241 };
1242
1243 FileCopyManager.Task.deduplicatePath(
1244 task.targetDirEntry, destName + '.zip', onDeduplicated, errorCallback);
1245 }; 1277 };
1246 1278
1247 /** 1279 /**
1248 * Timeout before files are really deleted (to allow undo). 1280 * Timeout before files are really deleted (to allow undo).
1249 */ 1281 */
1250 FileCopyManager.DELETE_TIMEOUT = 30 * 1000; 1282 FileCopyManager.DELETE_TIMEOUT = 30 * 1000;
1251 1283
1252 /** 1284 /**
1253 * Schedules the files deletion. 1285 * Schedules the files deletion.
1254 * 1286 *
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1371 * @param {Array.<Entry>} selectionEntries The selected entries. 1403 * @param {Array.<Entry>} selectionEntries The selected entries.
1372 */ 1404 */
1373 FileCopyManager.prototype.zipSelection = function(dirEntry, selectionEntries) { 1405 FileCopyManager.prototype.zipSelection = function(dirEntry, selectionEntries) {
1374 var self = this; 1406 var self = this;
1375 var zipTask = new FileCopyManager.Task(dirEntry, dirEntry); 1407 var zipTask = new FileCopyManager.Task(dirEntry, dirEntry);
1376 zipTask.zip = true; 1408 zipTask.zip = true;
1377 zipTask.setEntries(selectionEntries, function() { 1409 zipTask.setEntries(selectionEntries, function() {
1378 // TODO: per-entry zip progress update with accurate byte count. 1410 // TODO: per-entry zip progress update with accurate byte count.
1379 // For now just set completedBytes to same value as totalBytes so that the 1411 // For now just set completedBytes to same value as totalBytes so that the
1380 // progress bar is full. 1412 // progress bar is full.
1381 zipTask.completedBytes = zip.Task.totalBytes; 1413 zipTask.completedBytes = zipTask.totalBytes;
1382 self.copyTasks_.push(zipTask); 1414 self.copyTasks_.push(zipTask);
1383 if (self.copyTasks_.length == 1) { 1415 if (self.copyTasks_.length == 1) {
1384 // Assume self.cancelRequested_ == false. 1416 // Assume self.cancelRequested_ == false.
1385 // This moved us from 0 to 1 active tasks, let the servicing begin! 1417 // This moved us from 0 to 1 active tasks, let the servicing begin!
1386 self.serviceAllTasks_(); 1418 self.serviceAllTasks_();
1387 } else { 1419 } else {
1388 // Force to update the progress of butter bar when there are new tasks 1420 // Force to update the progress of butter bar when there are new tasks
1389 // coming while servicing current task. 1421 // coming while servicing current task.
1390 self.eventRouter_.sendProgressEvent('PROGRESS', self.getStatus()); 1422 self.eventRouter_.sendProgressEvent('PROGRESS', self.getStatus());
1391 } 1423 }
1392 }); 1424 });
1393 }; 1425 };
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698