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 |