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 |