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

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

Issue 39123003: [Files.app] Split the JavaScript files into subdirectories: common, background, and foreground (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed test failure. Created 7 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
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 /**
8 * Progress center at the background page.
9 * @constructor
10 */
11 var ProgressCenter = function() {
12 cr.EventTarget.call(this);
13
14 /**
15 * Default container.
16 * @type {ProgressItemContainer}
17 * @private
18 */
19 this.targetContainer_ = ProgressItemContainer.CLIENT;
20
21 /**
22 * Current items managed by the progress center.
23 * @type {Array.<ProgressItem>}
24 * @private
25 */
26 this.items_ = [];
27
28 /**
29 * Timeout callback to remove items.
30 * @type {TimeoutManager}
31 * @private
32 */
33 this.resetTimeout_ = new ProgressCenter.TimeoutManager(
34 this.reset_.bind(this));
35 };
36
37 /**
38 * The default amount of milliseconds time, before a progress item will reset
39 * after the last complete.
40 * @type {number}
41 * @private
42 * @const
43 */
44 ProgressCenter.RESET_DELAY_TIME_MS_ = 5000;
45
46 /**
47 * Utility for timeout callback.
48 *
49 * @param {function(*):*} callback Callbakc function.
50 * @constructor
51 */
52 ProgressCenter.TimeoutManager = function(callback) {
53 this.callback_ = callback;
54 this.id_ = null;
55 Object.seal(this);
56 };
57
58 /**
59 * Requests timeout. Previous request is canceled.
60 * @param {number} milliseconds Time to invoke the callback function.
61 */
62 ProgressCenter.TimeoutManager.prototype.request = function(milliseconds) {
63 if (this.id_)
64 clearTimeout(this.id_);
65 this.id_ = setTimeout(function() {
66 this.id_ = null;
67 this.callback_();
68 }.bind(this), milliseconds);
69 };
70
71 ProgressCenter.prototype = {
72 __proto__: cr.EventTarget.prototype,
73
74 /**
75 * Obtains the items to be displayed in the application window.
76 * @private
77 */
78 get applicationItems() {
79 return this.items_.filter(function(item) {
80 return item.container == ProgressItemContainer.CLIENT;
81 });
82 }
83 };
84
85 /**
86 * Updates the item in the progress center.
87 * If the item has a new ID, the item is added to the item list.
88 *
89 * @param {ProgressCenterItem} item Updated item.
90 */
91 ProgressCenter.prototype.updateItem = function(item) {
92 var index = this.getItemIndex_(item.id);
93 if (index === -1) {
94 item.container = this.targetContainer_;
95 this.items_.push(item);
96 } else {
97 this.items_[index] = item;
98 }
99
100 if (item.status !== ProgressItemState.PROGRESSING)
101 this.resetTimeout_.request(ProgressCenter.RESET_DELAY_TIME_MS_);
102
103 var event = new Event(ProgressCenterEvent.ITEM_UPDATED);
104 event.item = item;
105 this.dispatchEvent(event);
106 };
107
108 /**
109 * Requests to cancel the progress item.
110 * @param {string} id Progress ID to be requested to cancel.
111 */
112 ProgressCenter.prototype.requestCancel = function(id) {
113 var item = this.getItemById(id);
114 if (item && item.cancelCallback)
115 item.cancelCallback();
116 };
117
118 /**
119 * Switches the default container.
120 * @param {ProgressItemContainer} newContainer New value of the default
121 * container.
122 */
123 ProgressCenter.prototype.switchContainer = function(newContainer) {
124 if (this.targetContainer_ === newContainer)
125 return;
126
127 // Current items to be moved to the notification center.
128 if (newContainer == ProgressItemContainer.NOTIFICATION) {
129 var items = this.applicationItems;
130 for (var i = 0; i < items.length; i++) {
131 items[i].container = ProgressItemContainer.NOTIFICATION;
132 this.postItemToNotification_(items);
133 }
134 }
135
136 // The items in the notification center does not come back to the Files.app
137 // clients.
138
139 // Assign the new value.
140 this.targetContainer_ = newContainer;
141 };
142
143 /**
144 * Obtains the summarized item to be displayed in the closed progress center
145 * panel.
146 * @return {ProgressCenterItem} Summarized item. Returns null if there is no
147 * item.
148 */
149 ProgressCenter.prototype.getSummarizedItem = function() {
150 var applicationItems = this.applicationItems;
151 if (applicationItems.length == 0)
152 return null;
153 if (applicationItems.length == 1)
154 return applicationItems[0];
155 var summarizedItem = new ProgressCenterItem();
156 summarizedItem.summarized = true;
157 var completeCount = 0;
158 var progressingCount = 0;
159 var canceledCount = 0;
160 var errorCount = 0;
161 for (var i = 0; i < applicationItems.length; i++) {
162 switch (applicationItems[i].state) {
163 case ProgressItemState.COMPLETE:
164 completeCount++;
165 break;
166 case ProgressItemState.PROGRESSING:
167 progressingCount++;
168 break;
169 case ProgressItemState.ERROR:
170 errorCount++;
171 continue;
172 case ProgressItemState.CANCELED:
173 canceledCount++;
174 continue;
175 }
176 summarizedItem.progressMax += applicationItems[i].progressMax;
177 summarizedItem.progressValue += applicationItems[i].progressValue;
178 }
179 var messages = [];
180 if (completeCount)
181 messages.push(completeCount + ' complete');
182 if (progressingCount)
183 messages.push(progressingCount + ' active');
184 if (canceledCount)
185 messages.push(canceledCount + ' canceled');
186 if (errorCount)
187 messages.push(errorCount + ' error');
188 summarizedItem.message = messages.join(', ') + '.';
189 summarizedItem.state =
190 completeCount + progressingCount == 0 ? ProgressItemState.CANCELED :
191 progressingCount > 0 ? ProgressItemState.PROGRESSING :
192 ProgressItemState.COMPLETE;
193 return summarizedItem;
194 };
195
196 /**
197 * Obtains item by ID.
198 * @param {string} id ID of progress item.
199 * @return {ProgressCenterItem} Progress center item having the specified
200 * ID. Null if the item is not found.
201 */
202 ProgressCenter.prototype.getItemById = function(id) {
203 return this.items_[this.getItemIndex_(id)];
204 };
205
206 /**
207 * Obtains item index that have the specifying ID.
208 * @param {string} id Item ID.
209 * @return {number} Item index. Returns -1 If the item is not found.
210 * @private
211 */
212 ProgressCenter.prototype.getItemIndex_ = function(id) {
213 for (var i = 0; i < this.items_.length; i++) {
214 if (this.items_[i].id === id)
215 return i;
216 }
217 return -1;
218 };
219
220 /**
221 * Passes the item to the ChromeOS's message center.
222 *
223 * TODO(hirono): Implement the method.
224 *
225 * @private
226 */
227 ProgressCenter.prototype.passItemsToNotification_ = function() {
228
229 };
230
231 /**
232 * Hides the progress center if there is no progressing items.
233 * @private
234 */
235 ProgressCenter.prototype.reset_ = function() {
236 // If we have a progressing item, stop reset.
237 for (var i = 0; i < this.items_.length; i++) {
238 if (this.items_[i].state == ProgressItemState.PROGRESSING)
239 return;
240 }
241
242 // Reset items.
243 this.items_.splice(0, this.items_.length);
244
245 // Dispatch a event.
246 this.dispatchEvent(new Event(ProgressCenterEvent.RESET));
247 };
248
249 /**
250 * An event handler for progress center.
251 * @param {FileOperationManager} fileOperationManager File operation manager.
252 * @param {ProgressCenter} progressCenter Progress center.
253 * @constructor
254 */
255 var ProgressCenterHandler = function(fileOperationManager, progressCenter) {
256 /**
257 * Number of deleted files.
258 * @type {number}
259 * @private
260 */
261 this.totalDeleted_ = 0;
262
263 /**
264 * File operation manager.
265 * @type {FileOperationManager}
266 * @private
267 */
268 this.fileOperationManager_ = fileOperationManager;
269
270 /**
271 * Progress center.
272 * @type {progressCenter}
273 * @private
274 */
275 this.progressCenter_ = progressCenter;
276
277 // Seal the object.
278 Object.seal(this);
279
280 // Register event.
281 fileOperationManager.addEventListener('copy-progress',
282 this.onCopyProgress_.bind(this));
283 fileOperationManager.addEventListener('delete',
284 this.onDeleteProgress_.bind(this));
285 };
286
287 /**
288 * Generate a progress message from the event.
289 * @param {Event} event Progress event.
290 * @return {string} message.
291 * @private
292 */
293 ProgressCenterHandler.getMessage_ = function(event) {
294 if (event.reason === 'ERROR') {
295 switch (event.error.code) {
296 case util.FileOperationErrorType.TARGET_EXISTS:
297 var name = event.error.data.name;
298 if (event.error.data.isDirectory)
299 name += '/';
300 switch (event.status.operationType) {
301 case 'COPY': return strf('COPY_TARGET_EXISTS_ERROR', name);
302 case 'MOVE': return strf('MOVE_TARGET_EXISTS_ERROR', name);
303 case 'ZIP': return strf('ZIP_TARGET_EXISTS_ERROR', name);
304 default: return strf('TRANSFER_TARGET_EXISTS_ERROR', name);
305 }
306
307 case util.FileOperationErrorType.FILESYSTEM_ERROR:
308 var detail = util.getFileErrorString(event.error.data.code);
309 switch (event.status.operationType) {
310 case 'COPY': return strf('COPY_FILESYSTEM_ERROR', detail);
311 case 'MOVE': return strf('MOVE_FILESYSTEM_ERROR', detail);
312 case 'ZIP': return strf('ZIP_FILESYSTEM_ERROR', detail);
313 default: return strf('TRANSFER_FILESYSTEM_ERROR', detail);
314 }
315
316 default:
317 switch (event.status.operationType) {
318 case 'COPY': return strf('COPY_UNEXPECTED_ERROR', event.error);
319 case 'MOVE': return strf('MOVE_UNEXPECTED_ERROR', event.error);
320 case 'ZIP': return strf('ZIP_UNEXPECTED_ERROR', event.error);
321 default: return strf('TRANSFER_UNEXPECTED_ERROR', event.error);
322 }
323 }
324 } else if (event.status.numRemainingItems === 1) {
325 var name = event.status.processingEntry.name;
326 switch (event.status.operationType) {
327 case 'COPY': return strf('COPY_FILE_NAME', name);
328 case 'MOVE': return strf('MOVE_FILE_NAME', name);
329 case 'ZIP': return strf('ZIP_FILE_NAME', name);
330 default: return strf('TRANSFER_FILE_NAME', name);
331 }
332 } else {
333 var remainNumber = event.status.numRemainingItems;
334 switch (event.status.operationType) {
335 case 'COPY': return strf('COPY_ITEMS_REMAINING', remainNumber);
336 case 'MOVE': return strf('MOVE_ITEMS_REMAINING', remainNumber);
337 case 'ZIP': return strf('ZIP_ITEMS_REMAINING', remainNumber);
338 default: return strf('TRANSFER_ITEMS_REMAINING', remainNumber);
339 }
340 }
341 };
342
343 /**
344 * Generate a delete message from the event.
345 * @param {Event} event Progress event.
346 * @param {number} totalDeleted Total number of deleted files.
347 * @return {string} message.
348 * @private
349 */
350 ProgressCenterHandler.getDeleteMessage_ = function(event, totalDeleted) {
351 if (totalDeleted === 1) {
352 var fullPath = util.extractFilePath(event.urls[0]);
353 var fileName = PathUtil.split(fullPath).pop();
354 return strf('DELETED_MESSAGE', fileName);
355 } else {
356 return strf('DELETED_MESSAGE_PLURAL', totalDeleted);
357 }
358 };
359
360 /**
361 * Handles the copy-progress event.
362 * @param {Event} event The copy-progress event.
363 * @private
364 */
365 ProgressCenterHandler.prototype.onCopyProgress_ = function(event) {
366 var progressCenter = this.progressCenter_;
367 var item;
368 switch (event.reason) {
369 case 'BEGIN':
370 item = new ProgressCenterItem();
371 item.id = event.taskId;
372 item.message = ProgressCenterHandler.getMessage_(event);
373 item.progressMax = event.status.totalBytes;
374 item.progressValue = event.status.processedBytes;
375 item.cancelCallback = this.fileOperationManager_.requestTaskCancel.bind(
376 this.fileOperationManager_,
377 event.taskId);
378 progressCenter.updateItem(item);
379 break;
380
381 case 'PROGRESS':
382 item = progressCenter.getItemById(event.taskId);
383 if (!item) {
384 console.error('Cannot find copying item.');
385 return;
386 }
387 item.message = ProgressCenterHandler.getMessage_(event);
388 item.progressValue = event.status.processedBytes;
389 progressCenter.updateItem(item);
390 break;
391
392 case 'SUCCESS':
393 case 'ERROR':
394 item = progressCenter.getItemById(event.taskId);
395 if (!item) {
396 // ERROR events can be dispatched before BEGIN events.
397 item = new ProgressCenterItem();
398 item.id = event.taskId;
399 item.progressMax = 1;
400 }
401 if (event.reason === 'SUCCESS') {
402 // TODO(hirono): Add a message for complete.
403 item.state = ProgressItemState.COMPLETE;
404 item.progressValue = item.progressMax;
405 } else if (event.error.data.code === FileError.ABORT_ERR) {
406 item.message = strf('COPY_CANCELLED');
407 item.state = ProgressItemState.CANCELED;
408 } else {
409 item.message = ProgressCenterHandler.getMessage_(event);
410 item.state = ProgressItemState.ERROR;
411 }
412 progressCenter.updateItem(item);
413 break;
414 }
415 };
416
417 /**
418 * Handles the delete event.
419 * @param {Event} event The delete event.
420 * @private
421 */
422 ProgressCenterHandler.prototype.onDeleteProgress_ = function(event) {
423 var progressCenter = this.progressCenter_;
424 var item;
425 switch (event.reason) {
426 case 'BEGIN':
427 this.totalDeleted_ = 0;
428 item = new ProgressCenterItem();
429 item.id = event.taskId;
430 // TODO(hirono): Specifying the correct message.
431 item.message =
432 ProgressCenterHandler.getDeleteMessage_(event, this.totalDeleted_);
433 item.progressMax = 100;
434 progressCenter.updateItem(item);
435 break;
436
437 case 'PROGRESS':
438 item = progressCenter.getItemById(event.taskId);
439 if (!item) {
440 console.error('Cannot find deleting item.');
441 return;
442 }
443 this.totalDeleted_ += event.urls.length;
444 item.message =
445 ProgressCenterHandler.getDeleteMessage_(event, this.totalDeleted_);
446 progressCenter.updateItem(item);
447 break;
448
449 case 'SUCCESS':
450 case 'ERROR':
451 item = progressCenter.getItemById(event.taskId);
452 if (!item) {
453 console.error('Cannot find deleting item.');
454 return;
455 }
456 if (event.reason === 'SUCCESS') {
457 this.totalDeleted_ += event.urls.length;
458 item.message =
459 ProgressCenterHandler.getDeleteMessage_(event, this.totalDeleted_);
460 item.state = ProgressItemState.COMPLETE;
461 item.progressValue = item.progressMax;
462 } else {
463 item.message = str('DELETE_ERROR');
464 item.state = ProgressItemState.ERROR;
465 }
466 progressCenter.updateItem(item);
467 break;
468 }
469 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698