Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 // Shared cloud importer namespace | 5 // Shared cloud importer namespace |
| 6 var importer = importer || {}; | 6 var importer = importer || {}; |
| 7 | 7 |
| 8 /** @enum {string} */ | 8 /** @enum {string} */ |
| 9 importer.ScanEvent = { | 9 importer.ScanEvent = { |
| 10 FINALIZED: 'finalized', | 10 FINALIZED: 'finalized', |
| 11 INVALIDATED: 'invalidated', | 11 INVALIDATED: 'invalidated', |
| 12 UPDATED: 'updated' | 12 UPDATED: 'updated' |
| 13 }; | 13 }; |
| 14 | 14 |
| 15 /** | 15 /** |
| 16 * Storage keys for settings saved by importer. | 16 * Storage keys for settings saved by importer. |
| 17 * @enum {string} | 17 * @enum {string} |
| 18 */ | 18 */ |
| 19 importer.Setting = { | 19 importer.Setting = { |
| 20 HAS_COMPLETED_IMPORT: 'importer-has-completed-import', | 20 HAS_COMPLETED_IMPORT: 'importer-has-completed-import', |
| 21 MACHINE_ID: 'importer-machine-id', | 21 MACHINE_ID: 'importer-machine-id', |
| 22 PHOTOS_APP_ENABLED: 'importer-photo-app-enabled' | 22 PHOTOS_APP_ENABLED: 'importer-photo-app-enabled', |
| 23 LAST_KNOWN_LOG_ID: 'importer-last-known-log-id' | |
| 23 }; | 24 }; |
| 24 | 25 |
| 25 /** | 26 /** |
| 26 * @typedef {function( | 27 * @typedef {function( |
| 27 * !importer.ScanEvent, importer.ScanResult)} | 28 * !importer.ScanEvent, importer.ScanResult)} |
| 28 */ | 29 */ |
| 29 importer.ScanObserver; | 30 importer.ScanObserver; |
| 30 | 31 |
| 31 /** | 32 /** |
| 32 * Volume types eligible for the affections of Cloud Import. | 33 * Volume types eligible for the affections of Cloud Import. |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 216 }); | 217 }); |
| 217 }; | 218 }; |
| 218 | 219 |
| 219 /** | 220 /** |
| 220 * @return {!Promise.<string>} Resolves with the filename of this | 221 * @return {!Promise.<string>} Resolves with the filename of this |
| 221 * machines history file. | 222 * machines history file. |
| 222 */ | 223 */ |
| 223 importer.getHistoryFilename = function() { | 224 importer.getHistoryFilename = function() { |
| 224 return importer.getMachineId().then( | 225 return importer.getMachineId().then( |
| 225 function(machineId) { | 226 function(machineId) { |
| 226 return 'import-history.' + machineId + '.log'; | 227 return 'import-history-' + machineId + '.log'; |
| 227 }); | 228 }); |
| 228 }; | 229 }; |
| 229 | 230 |
| 230 /** | 231 /** |
| 232 * @param {number} logId | |
| 231 * @return {!Promise.<string>} Resolves with the filename of this | 233 * @return {!Promise.<string>} Resolves with the filename of this |
| 232 * machines debug log file. | 234 * machines debug log file. |
| 233 */ | 235 */ |
| 234 importer.getDebugLogFilename = function() { | 236 importer.getDebugLogFilename = function(logId) { |
| 235 return importer.getMachineId().then( | 237 return importer.getMachineId().then( |
| 236 function(machineId) { | 238 function(machineId) { |
| 237 return 'import-debug.' + machineId + '.log'; | 239 return 'import-debug-' + machineId + '-' + logId + '.log'; |
| 238 }); | 240 }); |
| 239 }; | 241 }; |
| 240 | 242 |
| 241 /** | 243 /** |
| 242 * @return {number} A relatively unique six digit integer that is most likely | 244 * @return {number} A relatively unique six digit integer that is most likely |
| 243 * unique to this machine among a user's machines. Used only to segregate | 245 * unique to this machine among a user's machines. Used only to segregate |
| 244 * log files on sync storage. | 246 * log files on sync storage. |
| 245 */ | 247 */ |
| 246 importer.generateMachineId_ = function() { | 248 importer.generateMachineId_ = function() { |
| 247 return Math.floor(Math.random() * 899999) + 100000; | 249 return Math.floor(Math.random() * 899999) + 100000; |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 662 | 664 |
| 663 /** @override */ | 665 /** @override */ |
| 664 importer.RuntimeLogger.prototype.error = function(content) { | 666 importer.RuntimeLogger.prototype.error = function(content) { |
| 665 this.write_('ERROR', content); | 667 this.write_('ERROR', content); |
| 666 console.error(content); | 668 console.error(content); |
| 667 }; | 669 }; |
| 668 | 670 |
| 669 /** @override */ | 671 /** @override */ |
| 670 importer.RuntimeLogger.prototype.catcher = function(context) { | 672 importer.RuntimeLogger.prototype.catcher = function(context) { |
| 671 return function(error) { | 673 return function(error) { |
| 672 this.error('Caught promise error. Context: ' + context + | 674 var prefix = '(' + context + ')'; |
| 673 ' Error: ' + error.message); | 675 var message = prefix + ' Caught error in promise chain.'; |
| 676 | |
| 677 if (error) { | |
| 678 this.error(message + ' Error' + error.message); | |
| 679 this.write_('STACK', prefix + ' Trace: ' + error.stack); | |
| 680 } else { | |
| 681 this.error(message); | |
| 682 error = new Error(message); | |
| 683 } | |
| 684 | |
| 685 throw error; | |
| 674 }.bind(this); | 686 }.bind(this); |
| 675 }; | 687 }; |
| 676 | 688 |
| 677 /** | 689 /** |
| 678 * Writes a message to the logger followed by a new line. | 690 * Writes a message to the logger followed by a new line. |
| 679 * | 691 * |
| 680 * @param {string} type | 692 * @param {string} type |
| 681 * @param {string} message | 693 * @param {string} message |
| 682 */ | 694 */ |
| 683 importer.RuntimeLogger.prototype.write_ = function(type, message) { | 695 importer.RuntimeLogger.prototype.write_ = function(type, message) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 721 /** @private {importer.Logger} */ | 733 /** @private {importer.Logger} */ |
| 722 importer.logger_ = null; | 734 importer.logger_ = null; |
| 723 | 735 |
| 724 /** | 736 /** |
| 725 * Creates a new logger instance...all ready to go. | 737 * Creates a new logger instance...all ready to go. |
| 726 * | 738 * |
| 727 * @return {!importer.Logger} | 739 * @return {!importer.Logger} |
| 728 */ | 740 */ |
| 729 importer.getLogger = function() { | 741 importer.getLogger = function() { |
| 730 if (!importer.logger_) { | 742 if (!importer.logger_) { |
| 743 var nextLogId = importer.getNextDebugLogId_(); | |
| 744 | |
| 745 /** @return {!Promise} */ | |
| 746 var rotator = function() { | |
| 747 return importer.rotateLogs( | |
| 748 nextLogId, | |
| 749 importer.ChromeSyncFileEntryProvider.getFileEntry); | |
| 750 }; | |
| 751 | |
| 752 // This is a sligtly odd arrangement in service of two goals. | |
| 753 // | |
| 754 // 1) Make a logger available synchronously. | |
| 755 // 2) Nuke old log files before reusing their names. | |
| 756 // | |
| 757 // In support of these goals we push the "rotator" between | |
| 758 // the call to load the file entry and the method that | |
| 759 // produces the name of the file to load. That method | |
| 760 // (getDebugLogFilename) returns promise. We exploit this. | |
| 731 importer.logger_ = new importer.RuntimeLogger( | 761 importer.logger_ = new importer.RuntimeLogger( |
| 732 importer.ChromeSyncFileEntryProvider.getFileEntry( | 762 importer.ChromeSyncFileEntryProvider.getFileEntry( |
| 733 importer.getDebugLogFilename())); | 763 /** @type {!Promise<string>} */ (rotator().then( |
| 764 importer.getDebugLogFilename.bind(null, nextLogId))))); | |
| 734 } | 765 } |
| 766 | |
| 735 return importer.logger_; | 767 return importer.logger_; |
| 736 }; | 768 }; |
| 737 | 769 |
| 738 /** | 770 /** |
| 771 * Returns the log ID for the next debug log to use. | |
| 772 * @private | |
| 773 */ | |
| 774 importer.getNextDebugLogId_ = function() { | |
| 775 return new Date().getMonth() % 2; | |
| 776 }; | |
| 777 | |
| 778 /** | |
| 779 * Deletes the "next" log file if it has just-now become active. | |
| 780 * | |
| 781 * Basically we toggle back and forth writing to two log files. At the time | |
| 782 * we flip from one to another we want to delete the oldest data we have. | |
| 783 * In this case it will be the "next" log. | |
| 784 * | |
| 785 * This function must be run befor instantiating the logger. | |
|
fukino
2015/02/23 03:42:26
nit: s/befor/before
Steve McKay
2015/02/23 03:50:18
Done.
| |
| 786 * | |
| 787 * @param {number} nextLogId | |
| 788 * @param {function(!Promise<string>): !Promise<!FileEntry>} fileFactory | |
| 789 * Injected primarily to facilitate testing. | |
| 790 * @return {!Promise} Resolves when trimming is complete. | |
| 791 */ | |
| 792 importer.rotateLogs = function(nextLogId, fileFactory) { | |
| 793 var storage = importer.ChromeLocalStorage.getInstance(); | |
| 794 | |
| 795 /** @return {!Promise} */ | |
| 796 var rememberLogId = function() { | |
| 797 return storage.set( | |
| 798 importer.Setting.LAST_KNOWN_LOG_ID, | |
| 799 nextLogId); | |
| 800 }; | |
| 801 | |
| 802 return storage.get(importer.Setting.LAST_KNOWN_LOG_ID) | |
| 803 .then( | |
| 804 /** @param {number} lastKnownLogId */ | |
| 805 function(lastKnownLogId) { | |
| 806 if (nextLogId === lastKnownLogId || | |
| 807 lastKnownLogId === undefined) { | |
| 808 return Promise.resolve(); | |
| 809 } | |
| 810 | |
| 811 return fileFactory(importer.getDebugLogFilename(nextLogId)) | |
| 812 .then( | |
| 813 /** | |
| 814 * @param {!FileEntry} entry | |
| 815 * @return {!Promise} | |
| 816 * @suppress {checkTypes} | |
| 817 */ | |
| 818 function(entry) { | |
| 819 return new Promise(entry.remove.bind(entry)); | |
| 820 }); | |
| 821 }) | |
| 822 .then(rememberLogId) | |
| 823 .catch(rememberLogId); | |
| 824 }; | |
| 825 | |
| 826 /** | |
| 739 * Friendly wrapper around chrome.storage.local. | 827 * Friendly wrapper around chrome.storage.local. |
| 740 * | 828 * |
| 741 * NOTE: If you want to use this in a test, install MockChromeStorageAPI. | 829 * NOTE: If you want to use this in a test, install MockChromeStorageAPI. |
| 742 * | 830 * |
| 743 * @constructor | 831 * @constructor |
| 744 */ | 832 */ |
| 745 importer.ChromeLocalStorage = function() {}; | 833 importer.ChromeLocalStorage = function() {}; |
| 746 | 834 |
| 747 /** | 835 /** |
| 748 * @param {string} key | 836 * @param {string} key |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 791 }); | 879 }); |
| 792 }; | 880 }; |
| 793 | 881 |
| 794 /** @private @const {!importer.ChromeLocalStorage} */ | 882 /** @private @const {!importer.ChromeLocalStorage} */ |
| 795 importer.ChromeLocalStorage.INSTANCE_ = new importer.ChromeLocalStorage(); | 883 importer.ChromeLocalStorage.INSTANCE_ = new importer.ChromeLocalStorage(); |
| 796 | 884 |
| 797 /** @return {!importer.ChromeLocalStorage} */ | 885 /** @return {!importer.ChromeLocalStorage} */ |
| 798 importer.ChromeLocalStorage.getInstance = function() { | 886 importer.ChromeLocalStorage.getInstance = function() { |
| 799 return importer.ChromeLocalStorage.INSTANCE_; | 887 return importer.ChromeLocalStorage.INSTANCE_; |
| 800 }; | 888 }; |
| OLD | NEW |