| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 * Utilities for file operations. | 6 * Utilities for file operations. |
| 7 */ | 7 */ |
| 8 var fileOperationUtil = {}; | 8 var fileOperationUtil = {}; |
| 9 | 9 |
| 10 /** | 10 /** |
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 */ | 543 */ |
| 544 this.totalBytes = 1; | 544 this.totalBytes = 1; |
| 545 | 545 |
| 546 /** | 546 /** |
| 547 * Total number of already processed bytes. Updated periodically. | 547 * Total number of already processed bytes. Updated periodically. |
| 548 * @type {number} | 548 * @type {number} |
| 549 */ | 549 */ |
| 550 this.processedBytes = 0; | 550 this.processedBytes = 0; |
| 551 | 551 |
| 552 /** | 552 /** |
| 553 * Total number of remaining items. Updated periodically. |
| 554 * @type {number} |
| 555 */ |
| 556 this.numRemainingItems = this.sourceEntries.length; |
| 557 |
| 558 /** |
| 553 * Index of the progressing entry in sourceEntries. | 559 * Index of the progressing entry in sourceEntries. |
| 554 * @private {number} | 560 * @private {number} |
| 555 */ | 561 */ |
| 556 this.processingSourceIndex_ = 0; | 562 this.processingSourceIndex_ = 0; |
| 557 | 563 |
| 558 /** | 564 /** |
| 559 * Set to true when cancel is requested. | 565 * Set to true when cancel is requested. |
| 560 * @private {boolean} | 566 * @private {boolean} |
| 561 */ | 567 */ |
| 562 this.cancelRequested_ = false; | 568 this.cancelRequested_ = false; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 * @param {function()} successCallback Callback run on success. | 611 * @param {function()} successCallback Callback run on success. |
| 606 * @param {function(fileOperationUtil.Error)} errorCallback Callback run on | 612 * @param {function(fileOperationUtil.Error)} errorCallback Callback run on |
| 607 * error. | 613 * error. |
| 608 */ | 614 */ |
| 609 fileOperationUtil.Task.prototype.run = function( | 615 fileOperationUtil.Task.prototype.run = function( |
| 610 entryChangedCallback, progressCallback, successCallback, errorCallback) { | 616 entryChangedCallback, progressCallback, successCallback, errorCallback) { |
| 611 }; | 617 }; |
| 612 | 618 |
| 613 /** | 619 /** |
| 614 * Get states of the task. | 620 * Get states of the task. |
| 615 * TOOD(hirono): Removes this method and sets a task to progress events. | 621 * TODO(hirono): Removes this method and sets a task to progress events. |
| 616 * @return {Object} Status object. | 622 * @return {Object} Status object. |
| 617 */ | 623 */ |
| 618 fileOperationUtil.Task.prototype.getStatus = function() { | 624 fileOperationUtil.Task.prototype.getStatus = function() { |
| 619 var processingEntry = this.sourceEntries[this.processingSourceIndex_]; | 625 var processingEntry = this.sourceEntries[this.processingSourceIndex_]; |
| 620 return { | 626 return { |
| 621 operationType: this.operationType, | 627 operationType: this.operationType, |
| 622 numRemainingItems: this.sourceEntries.length - this.processingSourceIndex_, | 628 numRemainingItems: this.numRemainingItems, |
| 623 totalBytes: this.totalBytes, | 629 totalBytes: this.totalBytes, |
| 624 processedBytes: this.processedBytes, | 630 processedBytes: this.processedBytes, |
| 625 processingEntryName: processingEntry ? processingEntry.name : '' | 631 processingEntryName: processingEntry ? processingEntry.name : '' |
| 626 }; | 632 }; |
| 627 }; | 633 }; |
| 628 | 634 |
| 629 /** | 635 /** |
| 630 * Obtains the number of total processed bytes. | 636 * Obtains the number of total processed bytes. |
| 631 * @return {number} Number of total processed bytes. | 637 * @return {number} Number of total processed bytes. |
| 632 * @private | 638 * @private |
| 633 */ | 639 */ |
| 634 fileOperationUtil.Task.prototype.calcProcessedBytes_ = function() { | 640 fileOperationUtil.Task.prototype.calcProcessedBytes_ = function() { |
| 635 var bytes = 0; | 641 var bytes = 0; |
| 636 for (var i = 0; i < this.processingSourceIndex_ + 1; i++) { | 642 for (var i = 0; i < this.processingSourceIndex_ + 1; i++) { |
| 637 var entryMap = this.processingEntries[i]; | 643 var entryMap = this.processingEntries[i]; |
| 638 if (!entryMap) | 644 if (!entryMap) |
| 639 break; | 645 break; |
| 640 for (var name in entryMap) { | 646 for (var name in entryMap) { |
| 641 bytes += i < this.processingSourceIndex_ ? | 647 bytes += i < this.processingSourceIndex_ ? |
| 642 entryMap[name].size : entryMap[name].processedBytes; | 648 entryMap[name].size : entryMap[name].processedBytes; |
| 643 } | 649 } |
| 644 } | 650 } |
| 645 return bytes; | 651 return bytes; |
| 646 }; | 652 }; |
| 647 | 653 |
| 648 /** | 654 /** |
| 655 * Obtains the number of remaining items. |
| 656 * @return {number} Number of remaining items. |
| 657 * @private |
| 658 */ |
| 659 fileOperationUtil.Task.prototype.calcNumRemainingItems_ = function() { |
| 660 var numRemainingItems = 0; |
| 661 |
| 662 var resolvedEntryMap; |
| 663 if (this.processingEntries && this.processingEntries.length > 0) |
| 664 resolvedEntryMap = this.processingEntries[this.processingSourceIndex_]; |
| 665 |
| 666 if (resolvedEntryMap) { |
| 667 for (var key in resolvedEntryMap) { |
| 668 if (resolvedEntryMap.hasOwnProperty(key) && |
| 669 resolvedEntryMap[key].processedBytes === 0) { |
| 670 numRemainingItems++; |
| 671 } |
| 672 } |
| 673 for (var i = this.processingSourceIndex_ + 1; |
| 674 i < this.processingEntries.length; i++) { |
| 675 numRemainingItems += Object.keys(this.processingEntries[i] || {}).length; |
| 676 } |
| 677 } else { |
| 678 numRemainingItems = this.sourceEntries.length - this.processingSourceIndex_; |
| 679 } |
| 680 |
| 681 return numRemainingItems; |
| 682 }; |
| 683 |
| 684 /** |
| 649 * Task to copy entries. | 685 * Task to copy entries. |
| 650 * | 686 * |
| 651 * @param {string} taskId A unique ID for identifying this task. | 687 * @param {string} taskId A unique ID for identifying this task. |
| 652 * @param {Array<Entry>} sourceEntries Array of source entries. | 688 * @param {Array<Entry>} sourceEntries Array of source entries. |
| 653 * @param {DirectoryEntry} targetDirEntry Target directory. | 689 * @param {DirectoryEntry} targetDirEntry Target directory. |
| 654 * @param {boolean} deleteAfterCopy Whether the delete original files after | 690 * @param {boolean} deleteAfterCopy Whether the delete original files after |
| 655 * copy. | 691 * copy. |
| 656 * @constructor | 692 * @constructor |
| 657 * @extends {fileOperationUtil.Task} | 693 * @extends {fileOperationUtil.Task} |
| 658 * @struct | 694 * @struct |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 * dropped, all bytes of the entry are considered to be processed. | 823 * dropped, all bytes of the entry are considered to be processed. |
| 788 */ | 824 */ |
| 789 var updateProgress = function(index, sourceEntryUrl, opt_size) { | 825 var updateProgress = function(index, sourceEntryUrl, opt_size) { |
| 790 if (!sourceEntryUrl) | 826 if (!sourceEntryUrl) |
| 791 return; | 827 return; |
| 792 | 828 |
| 793 var processedEntry = this.processingEntries[index][sourceEntryUrl]; | 829 var processedEntry = this.processingEntries[index][sourceEntryUrl]; |
| 794 if (!processedEntry) | 830 if (!processedEntry) |
| 795 return; | 831 return; |
| 796 | 832 |
| 833 var alreadyCompleted = |
| 834 processedEntry.processedBytes === processedEntry.size; |
| 835 |
| 797 // Accumulates newly processed bytes. | 836 // Accumulates newly processed bytes. |
| 798 var size = opt_size !== undefined ? opt_size : processedEntry.size; | 837 var size = opt_size !== undefined ? opt_size : processedEntry.size; |
| 799 this.processedBytes += size - processedEntry.processedBytes; | 838 this.processedBytes += size - processedEntry.processedBytes; |
| 800 processedEntry.processedBytes = size; | 839 processedEntry.processedBytes = size; |
| 801 | 840 |
| 841 // updateProgress can be called multiple times for a single file copy, and |
| 842 // it might not be called for a small file. |
| 843 // The following prevents multiple call for a single file to decrement |
| 844 // numRemainingItems multiple times. |
| 845 // For small files, it will be decremented by next calcNumRemainingItems_(). |
| 846 if (!alreadyCompleted && |
| 847 processedEntry.processedBytes === processedEntry.size) { |
| 848 this.numRemainingItems--; |
| 849 } |
| 850 |
| 802 // Updates progress bar in limited frequency so that intervals between | 851 // Updates progress bar in limited frequency so that intervals between |
| 803 // updates have at least 200ms. | 852 // updates have at least 200ms. |
| 804 this.updateProgressRateLimiter_.run(); | 853 this.updateProgressRateLimiter_.run(); |
| 805 }; | 854 }; |
| 806 updateProgress = updateProgress.bind(this); | 855 updateProgress = updateProgress.bind(this); |
| 807 | 856 |
| 808 this.updateProgressRateLimiter_ = new AsyncUtil.RateLimiter(progressCallback); | 857 this.updateProgressRateLimiter_ = new AsyncUtil.RateLimiter(progressCallback); |
| 809 | 858 |
| 859 this.numRemainingItems = this.calcNumRemainingItems_(); |
| 860 |
| 810 // Number of consecutive errors. Increases while failing and resets to zero | 861 // Number of consecutive errors. Increases while failing and resets to zero |
| 811 // when one of them succeeds. | 862 // when one of them succeeds. |
| 812 var errorCount = 0; | 863 var errorCount = 0; |
| 813 var lastError; | 864 var lastError; |
| 814 | 865 |
| 815 AsyncUtil.forEach( | 866 AsyncUtil.forEach( |
| 816 this.sourceEntries, | 867 this.sourceEntries, |
| 817 function(callback, entry, index) { | 868 function(callback, entry, index) { |
| 818 if (this.cancelRequested_) { | 869 if (this.cancelRequested_) { |
| 819 errorCallback(new fileOperationUtil.Error( | 870 errorCallback(new fileOperationUtil.Error( |
| (...skipping 15 matching lines...) Expand all Loading... |
| 835 }, | 886 }, |
| 836 function(sourceEntryUrl, size) { | 887 function(sourceEntryUrl, size) { |
| 837 updateProgress(index, sourceEntryUrl, size); | 888 updateProgress(index, sourceEntryUrl, size); |
| 838 }, | 889 }, |
| 839 function() { | 890 function() { |
| 840 // Finishes off delayed updates if necessary. | 891 // Finishes off delayed updates if necessary. |
| 841 this.updateProgressRateLimiter_.runImmediately(); | 892 this.updateProgressRateLimiter_.runImmediately(); |
| 842 // Update current source index and processing bytes. | 893 // Update current source index and processing bytes. |
| 843 this.processingSourceIndex_ = index + 1; | 894 this.processingSourceIndex_ = index + 1; |
| 844 this.processedBytes = this.calcProcessedBytes_(); | 895 this.processedBytes = this.calcProcessedBytes_(); |
| 896 this.numRemainingItems = this.calcNumRemainingItems_(); |
| 845 errorCount = 0; | 897 errorCount = 0; |
| 846 callback(); | 898 callback(); |
| 847 }.bind(this), | 899 }.bind(this), |
| 848 function(error) { | 900 function(error) { |
| 849 // Finishes off delayed updates if necessary. | 901 // Finishes off delayed updates if necessary. |
| 850 this.updateProgressRateLimiter_.runImmediately(); | 902 this.updateProgressRateLimiter_.runImmediately(); |
| 851 // Update current source index and processing bytes. | 903 // Update current source index and processing bytes. |
| 852 this.processingSourceIndex_ = index + 1; | 904 this.processingSourceIndex_ = index + 1; |
| 853 this.processedBytes = this.calcProcessedBytes_(); | 905 this.processedBytes = this.calcProcessedBytes_(); |
| 906 this.numRemainingItems = this.calcNumRemainingItems_(); |
| 854 errorCount++; | 907 errorCount++; |
| 855 lastError = error; | 908 lastError = error; |
| 856 if (errorCount < | 909 if (errorCount < |
| 857 fileOperationUtil.CopyTask.CONSECUTIVE_ERROR_LIMIT_) { | 910 fileOperationUtil.CopyTask.CONSECUTIVE_ERROR_LIMIT_) { |
| 858 callback(); | 911 callback(); |
| 859 } else { | 912 } else { |
| 860 errorCallback(error); | 913 errorCallback(error); |
| 861 } | 914 } |
| 862 }.bind(this)); | 915 }.bind(this)); |
| 863 }, | 916 }, |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 util.createDOMError(util.FileError.ABORT_ERR))); | 1048 util.createDOMError(util.FileError.ABORT_ERR))); |
| 996 return; | 1049 return; |
| 997 } | 1050 } |
| 998 progressCallback(); | 1051 progressCallback(); |
| 999 fileOperationUtil.MoveTask.processEntry_( | 1052 fileOperationUtil.MoveTask.processEntry_( |
| 1000 entry, this.targetDirEntry, entryChangedCallback, | 1053 entry, this.targetDirEntry, entryChangedCallback, |
| 1001 function() { | 1054 function() { |
| 1002 // Update current source index. | 1055 // Update current source index. |
| 1003 this.processingSourceIndex_ = index + 1; | 1056 this.processingSourceIndex_ = index + 1; |
| 1004 this.processedBytes = this.calcProcessedBytes_(); | 1057 this.processedBytes = this.calcProcessedBytes_(); |
| 1058 this.numRemainingItems = this.calcNumRemainingItems_(); |
| 1005 callback(); | 1059 callback(); |
| 1006 }.bind(this), | 1060 }.bind(this), |
| 1007 errorCallback); | 1061 errorCallback); |
| 1008 }, | 1062 }, |
| 1009 function() { | 1063 function() { |
| 1010 successCallback(); | 1064 successCallback(); |
| 1011 }.bind(this), | 1065 }.bind(this), |
| 1012 this); | 1066 this); |
| 1013 }; | 1067 }; |
| 1014 | 1068 |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1292 fileOperationUtil.EventRouter.prototype.sendDeleteEvent = function( | 1346 fileOperationUtil.EventRouter.prototype.sendDeleteEvent = function( |
| 1293 reason, task) { | 1347 reason, task) { |
| 1294 var event = /** @type {FileOperationProgressEvent} */ (new Event('delete')); | 1348 var event = /** @type {FileOperationProgressEvent} */ (new Event('delete')); |
| 1295 event.reason = reason; | 1349 event.reason = reason; |
| 1296 event.taskId = task.taskId; | 1350 event.taskId = task.taskId; |
| 1297 event.entries = task.entries; | 1351 event.entries = task.entries; |
| 1298 event.totalBytes = task.totalBytes; | 1352 event.totalBytes = task.totalBytes; |
| 1299 event.processedBytes = task.processedBytes; | 1353 event.processedBytes = task.processedBytes; |
| 1300 this.dispatchEvent(event); | 1354 this.dispatchEvent(event); |
| 1301 }; | 1355 }; |
| OLD | NEW |