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

Side by Side Diff: ui/file_manager/file_manager/common/js/importer_common.js

Issue 1013893002: Update ImportHistory with support for reading history from multiple files. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Respond to review comments. Created 5 years, 9 months 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
OLDNEW
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',
(...skipping 25 matching lines...) Expand all
36 }; 36 };
37 37
38 /** 38 /**
39 * @typedef {function( 39 * @typedef {function(
40 * !importer.ScanEvent, importer.ScanResult)} 40 * !importer.ScanEvent, importer.ScanResult)}
41 */ 41 */
42 importer.ScanObserver; 42 importer.ScanObserver;
43 43
44 /** 44 /**
45 * Volume types eligible for the affections of Cloud Import. 45 * Volume types eligible for the affections of Cloud Import.
46 * @private @const {!Array.<!VolumeManagerCommon.VolumeType>} 46 * @private @const {!Array<!VolumeManagerCommon.VolumeType>}
47 */ 47 */
48 importer.ELIGIBLE_VOLUME_TYPES_ = [ 48 importer.ELIGIBLE_VOLUME_TYPES_ = [
49 VolumeManagerCommon.VolumeType.MTP, 49 VolumeManagerCommon.VolumeType.MTP,
50 VolumeManagerCommon.VolumeType.REMOVABLE 50 VolumeManagerCommon.VolumeType.REMOVABLE
51 ]; 51 ];
52 52
53 /** 53 /**
54 * @enum {string} 54 * @enum {string}
55 */ 55 */
56 importer.Destination = { 56 importer.Destination = {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 path !== '/MP_ROOT' && path !== '/MP_ROOT/') { 137 path !== '/MP_ROOT' && path !== '/MP_ROOT/') {
138 return false; 138 return false;
139 } 139 }
140 140
141 console.assert(volumeInfoProvider !== null); 141 console.assert(volumeInfoProvider !== null);
142 var volumeInfo = volumeInfoProvider.getVolumeInfo(entry); 142 var volumeInfo = volumeInfoProvider.getVolumeInfo(entry);
143 return importer.isEligibleVolume(volumeInfo); 143 return importer.isEligibleVolume(volumeInfo);
144 }; 144 };
145 145
146 /** 146 /**
147 * @return {!Promise.<boolean>} Resolves with true when Cloud Import feature 147 * @return {!Promise<boolean>} Resolves with true when Cloud Import feature
148 * is enabled. 148 * is enabled.
149 */ 149 */
150 importer.importEnabled = function() { 150 importer.importEnabled = function() {
151 return new Promise( 151 return new Promise(
152 function(resolve, reject) { 152 function(resolve, reject) {
153 chrome.commandLinePrivate.hasSwitch( 153 chrome.commandLinePrivate.hasSwitch(
154 'disable-cloud-import', 154 'disable-cloud-import',
155 /** @param {boolean} disabled */ 155 /** @param {boolean} disabled */
156 function(disabled) { 156 function(disabled) {
157 resolve(!disabled); 157 resolve(!disabled);
(...skipping 17 matching lines...) Expand all
175 console.error( 175 console.error(
176 'Unrecognized message type received from photos app: ' + message); 176 'Unrecognized message type received from photos app: ' + message);
177 return Promise.reject(); 177 return Promise.reject();
178 } 178 }
179 179
180 var storage = importer.ChromeLocalStorage.getInstance(); 180 var storage = importer.ChromeLocalStorage.getInstance();
181 return storage.set(importer.Setting.PHOTOS_APP_ENABLED, message); 181 return storage.set(importer.Setting.PHOTOS_APP_ENABLED, message);
182 }; 182 };
183 183
184 /** 184 /**
185 * @return {!Promise.<boolean>} Resolves with true when Cloud Import feature 185 * @return {!Promise<boolean>} Resolves with true when Cloud Import feature
186 * is enabled. 186 * is enabled.
187 */ 187 */
188 importer.isPhotosAppImportEnabled = function() { 188 importer.isPhotosAppImportEnabled = function() {
189 var storage = importer.ChromeLocalStorage.getInstance(); 189 var storage = importer.ChromeLocalStorage.getInstance();
190 return storage.get(importer.Setting.PHOTOS_APP_ENABLED, false); 190 return storage.get(importer.Setting.PHOTOS_APP_ENABLED, false);
191 }; 191 };
192 192
193 /** 193 /**
194 * @param {!Date} date 194 * @param {!Date} date
195 * @return {string} The current date, in YYYY-MM-DD format. 195 * @return {string} The current date, in YYYY-MM-DD format.
196 */ 196 */
197 importer.getDirectoryNameForDate = function(date) { 197 importer.getDirectoryNameForDate = function(date) {
198 var padAndConvert = function(i) { 198 var padAndConvert = function(i) {
199 return (i < 10 ? '0' : '') + i.toString(); 199 return (i < 10 ? '0' : '') + i.toString();
200 }; 200 };
201 201
202 var year = date.getFullYear().toString(); 202 var year = date.getFullYear().toString();
203 // Months are 0-based, but days aren't. 203 // Months are 0-based, but days aren't.
204 var month = padAndConvert(date.getMonth() + 1); 204 var month = padAndConvert(date.getMonth() + 1);
205 var day = padAndConvert(date.getDate()); 205 var day = padAndConvert(date.getDate());
206 206
207 // NOTE: We use YYYY-MM-DD since it sorts numerically. 207 // NOTE: We use YYYY-MM-DD since it sorts numerically.
208 // Ideally this would be localized and appropriate sorting would 208 // Ideally this would be localized and appropriate sorting would
209 // be done behind the scenes. 209 // be done behind the scenes.
210 return year + '-' + month + '-' + day; 210 return year + '-' + month + '-' + day;
211 }; 211 };
212 212
213 /** 213 /**
214 * @return {!Promise.<number>} Resolves with an integer that is probably 214 * @return {!Promise<number>} Resolves with an integer that is probably
215 * relatively unique to this machine (among a users machines). 215 * relatively unique to this machine (among a users machines).
216 */ 216 */
217 importer.getMachineId = function() { 217 importer.getMachineId = function() {
218 var storage = importer.ChromeLocalStorage.getInstance(); 218 var storage = importer.ChromeLocalStorage.getInstance();
219 return storage.get(importer.Setting.MACHINE_ID) 219 return storage.get(importer.Setting.MACHINE_ID)
220 .then( 220 .then(
221 function(id) { 221 function(id) {
222 if (id) { 222 if (id) {
223 return id; 223 return id;
224 } 224 }
225 var id = importer.generateMachineId_(); 225 var id = importer.generateMachineId_();
226 return storage.set(importer.Setting.MACHINE_ID, id) 226 return storage.set(importer.Setting.MACHINE_ID, id)
227 .then( 227 .then(
228 function() { 228 function() {
229 return id; 229 return id;
230 }); 230 });
231 }); 231 });
232 }; 232 };
233 233
234 /** 234 /**
235 * @return {!Promise.<string>} Resolves with the filename of this 235 * @return {!Promise<string>} Resolves with the filename of this
236 * machines history file. 236 * machines history file.
237 */ 237 */
238 importer.getHistoryFilename = function() { 238 importer.getHistoryFilename = function() {
239 return importer.getMachineId().then( 239 return importer.getMachineId().then(
240 function(machineId) { 240 function(machineId) {
241 return machineId + '-import-history.log'; 241 return machineId + '-import-history.log';
242 }); 242 });
243 }; 243 };
244 244
245 /** 245 /**
246 * @param {number} logId 246 * @param {number} logId
247 * @return {!Promise.<string>} Resolves with the filename of this 247 * @return {!Promise<string>} Resolves with the filename of this
248 * machines debug log file. 248 * machines debug log file.
249 */ 249 */
250 importer.getDebugLogFilename = function(logId) { 250 importer.getDebugLogFilename = function(logId) {
251 return importer.getMachineId().then( 251 return importer.getMachineId().then(
252 function(machineId) { 252 function(machineId) {
253 return machineId + '-import-debug-' + logId + '.log'; 253 return machineId + '-import-debug-' + logId + '.log';
254 }); 254 });
255 }; 255 };
256 256
257 /** 257 /**
(...skipping 15 matching lines...) Expand all
273 importer.Resolver = function() { 273 importer.Resolver = function() {
274 /** @private {boolean} */ 274 /** @private {boolean} */
275 this.settled_ = false; 275 this.settled_ = false;
276 276
277 /** @private {function(T=)} */ 277 /** @private {function(T=)} */
278 this.resolve_; 278 this.resolve_;
279 279
280 /** @private {function(*=)} */ 280 /** @private {function(*=)} */
281 this.reject_; 281 this.reject_;
282 282
283 /** @private {!Promise.<T>} */ 283 /** @private {!Promise<T>} */
284 this.promise_ = new Promise( 284 this.promise_ = new Promise(
285 function(resolve, reject) { 285 function(resolve, reject) {
286 this.resolve_ = resolve; 286 this.resolve_ = resolve;
287 this.reject_ = reject; 287 this.reject_ = reject;
288 }.bind(this)); 288 }.bind(this));
289 289
290 var settler = function() { 290 var settler = function() {
291 this.settled_ = true; 291 this.settled_ = true;
292 }.bind(this); 292 }.bind(this);
293 293
294 this.promise_.then(settler, settler); 294 this.promise_.then(settler, settler);
295 }; 295 };
296 296
297 importer.Resolver.prototype = /** @struct */ { 297 importer.Resolver.prototype = /** @struct */ {
298 /** 298 /**
299 * @return {function(T=)} 299 * @return {function(T=)}
300 * @template T 300 * @template T
301 */ 301 */
302 get resolve() { 302 get resolve() {
303 return this.resolve_; 303 return this.resolve_;
304 }, 304 },
305 /** 305 /**
306 * @return {function(*=)} 306 * @return {function(*=)}
307 * @template T 307 * @template T
308 */ 308 */
309 get reject() { 309 get reject() {
310 return this.reject_; 310 return this.reject_;
311 }, 311 },
312 /** 312 /**
313 * @return {!Promise.<T>} 313 * @return {!Promise<T>}
314 * @template T 314 * @template T
315 */ 315 */
316 get promise() { 316 get promise() {
317 return this.promise_; 317 return this.promise_;
318 }, 318 },
319 /** @return {boolean} */ 319 /** @return {boolean} */
320 get settled() { 320 get settled() {
321 return this.settled_; 321 return this.settled_;
322 } 322 }
323 }; 323 };
(...skipping 27 matching lines...) Expand all
351 * @struct 351 * @struct
352 * 352 *
353 * @param {!FileEntry} fileEntry 353 * @param {!FileEntry} fileEntry
354 */ 354 */
355 importer.PromisingFileEntry = function(fileEntry) { 355 importer.PromisingFileEntry = function(fileEntry) {
356 /** @private {!FileEntry} */ 356 /** @private {!FileEntry} */
357 this.fileEntry_ = fileEntry; 357 this.fileEntry_ = fileEntry;
358 }; 358 };
359 359
360 /** 360 /**
361 * Convenience method for creating new instances. Can, for example,
362 * be passed to Array.map.
363 *
364 * @param {!FileEntry} entry
365 * @return {!importer.PromisingFileEntry}
366 */
367 importer.PromisingFileEntry.create = function(entry) {
368 return new importer.PromisingFileEntry(entry);
369 };
370
371 /**
361 * A "Promisary" wrapper around entry.getWriter. 372 * A "Promisary" wrapper around entry.getWriter.
362 * @return {!Promise.<!FileWriter>} 373 * @return {!Promise<!FileWriter>}
363 */ 374 */
364 importer.PromisingFileEntry.prototype.createWriter = function() { 375 importer.PromisingFileEntry.prototype.createWriter = function() {
365 return new Promise(this.fileEntry_.createWriter.bind(this.fileEntry_)); 376 return new Promise(this.fileEntry_.createWriter.bind(this.fileEntry_));
366 }; 377 };
367 378
368 /** 379 /**
369 * A "Promisary" wrapper around entry.file. 380 * A "Promisary" wrapper around entry.file.
370 * @return {!Promise.<!File>} 381 * @return {!Promise<!File>}
371 */ 382 */
372 importer.PromisingFileEntry.prototype.file = function() { 383 importer.PromisingFileEntry.prototype.file = function() {
373 return new Promise(this.fileEntry_.file.bind(this.fileEntry_)); 384 return new Promise(this.fileEntry_.file.bind(this.fileEntry_));
374 }; 385 };
375 386
376 /** 387 /**
377 * @return {!Promise.<!Object>} 388 * @return {!Promise<!Object>}
378 */ 389 */
379 importer.PromisingFileEntry.prototype.getMetadata = function() { 390 importer.PromisingFileEntry.prototype.getMetadata = function() {
380 return new Promise(this.fileEntry_.getMetadata.bind(this.fileEntry_)); 391 return new Promise(this.fileEntry_.getMetadata.bind(this.fileEntry_));
381 }; 392 };
382 393
383 /** 394 /**
384 * This prefix is stripped from URL used in import history. It is stripped 395 * This prefix is stripped from URL used in import history. It is stripped
385 * to same on disk space, parsing time, and runtime memory. 396 * to same on disk space, parsing time, and runtime memory.
386 * @private @const {string} 397 * @private @const {string}
387 */ 398 */
(...skipping 25 matching lines...) Expand all
413 */ 424 */
414 importer.inflateAppUrl = function(deflated) { 425 importer.inflateAppUrl = function(deflated) {
415 if (deflated.substring(0, 1) === '$') { 426 if (deflated.substring(0, 1) === '$') {
416 return importer.APP_URL_PREFIX_ + deflated.substring(1); 427 return importer.APP_URL_PREFIX_ + deflated.substring(1);
417 } 428 }
418 return deflated; 429 return deflated;
419 }; 430 };
420 431
421 /** 432 /**
422 * @param {!FileEntry} fileEntry 433 * @param {!FileEntry} fileEntry
423 * @return {!Promise.<string>} Resolves with a "hashcode" consisting of 434 * @return {!Promise<string>} Resolves with a "hashcode" consisting of
424 * just the last modified time and the file size. 435 * just the last modified time and the file size.
425 */ 436 */
426 importer.createMetadataHashcode = function(fileEntry) { 437 importer.createMetadataHashcode = function(fileEntry) {
427 var entry = new importer.PromisingFileEntry(fileEntry); 438 var entry = new importer.PromisingFileEntry(fileEntry);
428 return new Promise( 439 return new Promise(
429 /** 440 /**
430 * @param {function()} resolve 441 * @param {function()} resolve
431 * @param {function()} reject 442 * @param {function()} reject
432 * @this {importer.PersistentImportHistory} 443 * @this {importer.PersistentImportHistory}
433 */ 444 */
434 function(resolve, reject) { 445 function(resolve, reject) {
435 entry.getMetadata() 446 entry.getMetadata()
436 .then( 447 .then(
437 /** 448 /**
438 * @param {!Object} metadata 449 * @param {!Object} metadata
439 * @return {!Promise.<string>} 450 * @return {!Promise<string>}
440 * @this {importer.PersistentImportHistory} 451 * @this {importer.PersistentImportHistory}
441 */ 452 */
442 function(metadata) { 453 function(metadata) {
443 if (!('modificationTime' in metadata)) { 454 if (!('modificationTime' in metadata)) {
444 reject('File entry missing "modificationTime" field.'); 455 reject('File entry missing "modificationTime" field.');
445 } else if (!('size' in metadata)) { 456 } else if (!('size' in metadata)) {
446 reject('File entry missing "size" field.'); 457 reject('File entry missing "size" field.');
447 } else { 458 } else {
448 var secondsSinceEpoch = 459 var secondsSinceEpoch =
449 importer.toSecondsFromEpoch(metadata.modificationTime); 460 importer.toSecondsFromEpoch(metadata.modificationTime);
(...skipping 12 matching lines...) Expand all
462 importer.toSecondsFromEpoch = function(date) { 473 importer.toSecondsFromEpoch = function(date) {
463 // Since we're parsing a value that only has 474 // Since we're parsing a value that only has
464 // precision to the second, our last three digits 475 // precision to the second, our last three digits
465 // will always be 000. We strip them and end up 476 // will always be 000. We strip them and end up
466 // with seconds. 477 // with seconds.
467 var milliseconds = String(Date.parse(date)); 478 var milliseconds = String(Date.parse(date));
468 return milliseconds.substring(0, milliseconds.length - 3); 479 return milliseconds.substring(0, milliseconds.length - 3);
469 }; 480 };
470 481
471 /** 482 /**
472 * Factory interface for creating/accessing synced {@code FileEntry} 483 * Namespace for ChromeSyncFilesystem related stuffs.
473 * instances and listening to sync events on those files.
474 *
475 * @interface
476 */ 484 */
477 importer.SyncFileEntryProvider = function() {}; 485 importer.ChromeSyncFilesystem = {};
478
479 /**
480 * Provides accsess to the sync FileEntry owned/managed by this class.
481 *
482 * @return {!Promise.<!FileEntry>}
483 */
484 importer.SyncFileEntryProvider.prototype.getSyncFileEntry;
485
486 /**
487 * Factory for synchronized files based on chrome.syncFileSystem.
488 *
489 * @constructor
490 * @implements {importer.SyncFileEntryProvider}
491 * @struct
492 *
493 * @param {string} fileName
494 */
495 importer.ChromeSyncFileEntryProvider = function(fileName) {
496
497 /** @private {string} */
498 this.fileName_ = fileName;
499
500 /** @private {!Array.<function()>} */
501 this.syncListeners_ = [];
502
503 /** @private {Promise.<!FileEntry>} */
504 this.fileEntryPromise_ = null;
505 };
506
507 /**
508 * Returns a sync FileEntry. Convenience method for class that just want
509 * a file, but don't need to monitor changes.
510 * @param {!Promise.<string>} fileNamePromise
511 * @return {!Promise.<!FileEntry>}
512 */
513 importer.ChromeSyncFileEntryProvider.getFileEntry =
514 function(fileNamePromise) {
515 return fileNamePromise.then(
516 function(fileName) {
517 return new importer.ChromeSyncFileEntryProvider(fileName)
518 .getSyncFileEntry();
519 });
520 };
521
522 /** @override */
523 importer.ChromeSyncFileEntryProvider.prototype.getSyncFileEntry = function() {
524 if (this.fileEntryPromise_) {
525 return /** @type {!Promise.<!FileEntry>} */ (this.fileEntryPromise_);
526 };
527
528 this.fileEntryPromise_ = this.getFileSystem_()
529 .then(
530 /**
531 * @param {!FileSystem} fileSystem
532 * @return {!Promise.<!FileEntry>}
533 * @this {importer.ChromeSyncFileEntryProvider}
534 */
535 function(fileSystem) {
536 return this.getFileEntry_(fileSystem);
537 }.bind(this));
538
539 return /** @type {!Promise.<!FileEntry>} */ (this.fileEntryPromise_);
540 };
541 486
542 /** 487 /**
543 * Wraps chrome.syncFileSystem in a Promise. 488 * Wraps chrome.syncFileSystem in a Promise.
544 * 489 *
545 * @return {!Promise.<!FileSystem>} 490 * @return {!Promise<!FileSystem>}
546 * @private 491 * @private
547 */ 492 */
548 importer.ChromeSyncFileEntryProvider.prototype.getFileSystem_ = function() { 493 importer.ChromeSyncFilesystem.getFileSystem_ = function() {
549 return new Promise( 494 return new Promise(
550 /**
551 * @param {function()} resolve
552 * @param {function()} reject
553 * @this {importer.ChromeSyncFileEntryProvider}
554 */
555 function(resolve, reject) { 495 function(resolve, reject) {
556 chrome.syncFileSystem.requestFileSystem( 496 chrome.syncFileSystem.requestFileSystem(
557 /** 497 /** @param {FileSystem} fileSystem */
558 * @param {FileSystem} fileSystem
559 * @this {importer.ChromeSyncFileEntryProvider}
560 */
561 function(fileSystem) { 498 function(fileSystem) {
562 if (chrome.runtime.lastError) { 499 if (chrome.runtime.lastError) {
563 reject(chrome.runtime.lastError.message); 500 reject(chrome.runtime.lastError.message);
564 } else { 501 } else {
565 resolve(/** @type {!FileSystem} */ (fileSystem)); 502 resolve(/** @type {!FileSystem} */ (fileSystem));
566 } 503 }
567 }); 504 });
568 }.bind(this)); 505 });
569 }; 506 };
570 507
571 /** 508 /**
572 * @param {!FileSystem} fileSystem 509 * Returns a sync file entry for the named file, creating it as needed.
573 * @return {!Promise.<!FileEntry>} 510 *
574 * @private 511 * @param {!Promise<string>} fileNamePromise
512 * @return {!Promise<!FileEntry>}
575 */ 513 */
576 importer.ChromeSyncFileEntryProvider.prototype.getFileEntry_ = 514 importer.ChromeSyncFilesystem.getOrCreateFileEntry = function(fileNamePromise) {
577 function(fileSystem) { 515 var promise = importer.ChromeSyncFilesystem.getFileSystem_()
578 return new Promise( 516 .then(
579 /** 517 /**
580 * @param {function()} resolve 518 * @param {!FileSystem} fileSystem
581 * @param {function()} reject 519 * @return {!Promise<!FileEntry>}
582 * @this {importer.ChromeSyncFileEntryProvider} 520 */
583 */ 521 function(fileSystem) {
584 function(resolve, reject) { 522 fileNamePromise.then(
585 fileSystem.root.getFile( 523 /** @param {string} fileName */
586 this.fileName_, 524 function(fileName) {
587 { 525 return new Promise(
588 create: true, 526 function(resolve, reject) {
589 exclusive: false 527 fileSystem.root.getFile(
590 }, 528 fileName,
591 resolve, 529 {
592 reject); 530 create: true,
593 }.bind(this)); 531 exclusive: false
532 },
533 resolve,
534 reject);
535 });
536
537 });
538 });
539
540 return /** @type {!Promise<!FileEntry>} */ (promise);
594 }; 541 };
595 542
596 /** 543 /**
597 * Handles sync events. Checks to see if the event is for the file
598 * we track, and sync-direction, and if so, notifies syncListeners.
599 *
600 * @see https://developer.chrome.com/apps/syncFileSystem
601 * #event-onFileStatusChanged
602 *
603 * @param {!Object} event Having a structure not unlike: {
604 * fileEntry: Entry,
605 * status: string,
606 * action: (string|undefined),
607 * direction: (string|undefined)}
608 *
609 * @private
610 */
611 importer.ChromeSyncFileEntryProvider.prototype.handleSyncEvent_ =
612 function(event) {
613 if (!this.fileEntryPromise_) {
614 return;
615 }
616
617 this.fileEntryPromise_.then(
618 /**
619 * @param {!FileEntry} fileEntry
620 * @this {importer.ChromeSyncFileEntryProvider}
621 */
622 function(fileEntry) {
623 if (event['fileEntry'].fullPath !== fileEntry.fullPath) {
624 return;
625 }
626
627 if (event.direction && event.direction !== 'remote_to_local') {
628 return;
629 }
630
631 if (event.action && event.action !== 'updated') {
632 console.warn(
633 'Unusual sync event action for sync file: ' + event.action);
634 return;
635 }
636
637 this.syncListeners_.forEach(
638 /**
639 * @param {function()} listener
640 * @this {importer.ChromeSyncFileEntryProvider}
641 */
642 function(listener) {
643 // Notify by way of a promise so that it is fully asynchronous
644 // (which can rationalize testing).
645 Promise.resolve().then(listener);
646 }.bind(this));
647 }.bind(this));
648 };
649
650 /**
651 * A basic logging mechanism. 544 * A basic logging mechanism.
652 * 545 *
653 * @interface 546 * @interface
654 */ 547 */
655 importer.Logger = function() {}; 548 importer.Logger = function() {};
656 549
657 /** 550 /**
658 * Writes an error message to the logger followed by a new line. 551 * Writes an error message to the logger followed by a new line.
659 * 552 *
660 * @param {string} message 553 * @param {string} message
(...skipping 16 matching lines...) Expand all
677 importer.Logger.prototype.catcher; 570 importer.Logger.prototype.catcher;
678 571
679 /** 572 /**
680 * A {@code importer.Logger} that persists data in a {@code FileEntry}. 573 * A {@code importer.Logger} that persists data in a {@code FileEntry}.
681 * 574 *
682 * @constructor 575 * @constructor
683 * @implements {importer.Logger} 576 * @implements {importer.Logger}
684 * @struct 577 * @struct
685 * @final 578 * @final
686 * 579 *
687 * @param {!Promise.<!FileEntry>} fileEntryPromise 580 * @param {!Promise<!FileEntry>} fileEntryPromise
688 * @param {!Promise.<!analytics.Tracker>} trackerPromise 581 * @param {!Promise<!analytics.Tracker>} trackerPromise
689 */ 582 */
690 importer.RuntimeLogger = function(fileEntryPromise, trackerPromise) { 583 importer.RuntimeLogger = function(fileEntryPromise, trackerPromise) {
691 584
692 /** @private {!Promise.<!importer.PromisingFileEntry>} */ 585 /** @private {!Promise<!importer.PromisingFileEntry>} */
693 this.fileEntryPromise_ = fileEntryPromise.then( 586 this.fileEntryPromise_ = fileEntryPromise.then(
694 /** @param {!FileEntry} fileEntry */ 587 /** @param {!FileEntry} fileEntry */
695 function(fileEntry) { 588 function(fileEntry) {
696 return new importer.PromisingFileEntry(fileEntry); 589 return new importer.PromisingFileEntry(fileEntry);
697 }); 590 });
698 591
699 /** @private {!Promise.<!analytics.Tracker>} */ 592 /** @private {!Promise<!analytics.Tracker>} */
700 this.trackerPromise_ = trackerPromise; 593 this.trackerPromise_ = trackerPromise;
701 }; 594 };
702 595
703 /** 596 /**
704 * Reports an error to analytics. 597 * Reports an error to analytics.
705 * 598 *
706 * @param {string} context MUST NOT contain any dynamic error content, 599 * @param {string} context MUST NOT contain any dynamic error content,
707 * only statically defined string will dooooo. 600 * only statically defined string will dooooo.
708 */ 601 */
709 importer.RuntimeLogger.prototype.reportErrorContext_ = function(context) { 602 importer.RuntimeLogger.prototype.reportErrorContext_ = function(context) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 /** @private {importer.Logger} */ 691 /** @private {importer.Logger} */
799 importer.logger_ = null; 692 importer.logger_ = null;
800 693
801 /** 694 /**
802 * Creates a new logger instance...all ready to go. 695 * Creates a new logger instance...all ready to go.
803 * 696 *
804 * @return {!importer.Logger} 697 * @return {!importer.Logger}
805 */ 698 */
806 importer.getLogger = function() { 699 importer.getLogger = function() {
807 if (!importer.logger_) { 700 if (!importer.logger_) {
701
808 var nextLogId = importer.getNextDebugLogId_(); 702 var nextLogId = importer.getNextDebugLogId_();
809 703
810 /** @return {!Promise} */ 704 /** @return {!Promise} */
811 var rotator = function() { 705 var rotator = function() {
812 return importer.rotateLogs( 706 return importer.rotateLogs(
813 nextLogId, 707 nextLogId,
814 importer.ChromeSyncFileEntryProvider.getFileEntry); 708 importer.ChromeSyncFilesystem.getOrCreateFileEntry);
815 }; 709 };
816 710
817 // This is a sligtly odd arrangement in service of two goals. 711 // This is a sligtly odd arrangement in service of two goals.
818 // 712 //
819 // 1) Make a logger available synchronously. 713 // 1) Make a logger available synchronously.
820 // 2) Nuke old log files before reusing their names. 714 // 2) Nuke old log files before reusing their names.
821 // 715 //
822 // In support of these goals we push the "rotator" between 716 // In support of these goals we push the "rotator" between
823 // the call to load the file entry and the method that 717 // the call to load the file entry and the method that
824 // produces the name of the file to load. That method 718 // produces the name of the file to load. That method
825 // (getDebugLogFilename) returns promise. We exploit this. 719 // (getDebugLogFilename) returns promise. We exploit this.
826 importer.logger_ = new importer.RuntimeLogger( 720 importer.logger_ = new importer.RuntimeLogger(
827 importer.ChromeSyncFileEntryProvider.getFileEntry( 721 importer.ChromeSyncFilesystem.getOrCreateFileEntry(
828 /** @type {!Promise.<string>} */ (rotator().then( 722 /** @type {!Promise<string>} */ (rotator().then(
829 importer.getDebugLogFilename.bind(null, nextLogId)))), 723 importer.getDebugLogFilename.bind(null, nextLogId)))),
830 importer.getTracker_()); 724 importer.getTracker_());
831 } 725 }
832 726
833 return importer.logger_; 727 return importer.logger_;
834 }; 728 };
835 729
836 /** 730 /**
837 * Fetch analytics.Tracker from background page. 731 * Fetch analytics.Tracker from background page.
838 * @return {!Promise.<!analytics.Tracker>} 732 * @return {!Promise<!analytics.Tracker>}
839 * @private 733 * @private
840 */ 734 */
841 importer.getTracker_ = function() { 735 importer.getTracker_ = function() {
842 return new Promise( 736 return new Promise(
843 function(resolve, reject) { 737 function(resolve, reject) {
844 chrome.runtime.getBackgroundPage( 738 chrome.runtime.getBackgroundPage(
845 /** @param {Window=} opt_background */ 739 /** @param {Window=} opt_background */
846 function(opt_background) { 740 function(opt_background) {
847 if (chrome.runtime.lastError) { 741 if (chrome.runtime.lastError) {
848 reject(chrome.runtime.lastError); 742 reject(chrome.runtime.lastError);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
939 } else { 833 } else {
940 resolve(undefined); 834 resolve(undefined);
941 } 835 }
942 }); 836 });
943 }); 837 });
944 }; 838 };
945 839
946 /** 840 /**
947 * @param {string} key 841 * @param {string} key
948 * @param {T=} opt_default 842 * @param {T=} opt_default
949 * @return {!Promise.<T>} Resolves with the value, or {@code opt_default} when 843 * @return {!Promise<T>} Resolves with the value, or {@code opt_default} when
950 * no value entry existis, or {@code undefined}. 844 * no value entry existis, or {@code undefined}.
951 * @template T 845 * @template T
952 */ 846 */
953 importer.ChromeLocalStorage.prototype.get = function(key, opt_default) { 847 importer.ChromeLocalStorage.prototype.get = function(key, opt_default) {
954 return new Promise( 848 return new Promise(
955 function(resolve, reject) { 849 function(resolve, reject) {
956 chrome.storage.local.get( 850 chrome.storage.local.get(
957 key, 851 key,
958 /** @param {Object.<string, ?>} values */ 852 /** @param {Object.<string, ?>} values */
959 function(values) { 853 function(values) {
960 if (chrome.runtime.lastError) { 854 if (chrome.runtime.lastError) {
961 reject(chrome.runtime.lastError); 855 reject(chrome.runtime.lastError);
962 } else if (key in values) { 856 } else if (key in values) {
963 resolve(values[key]); 857 resolve(values[key]);
964 } else { 858 } else {
965 resolve(opt_default); 859 resolve(opt_default);
966 } 860 }
967 }); 861 });
968 }); 862 });
969 }; 863 };
970 864
971 /** @private @const {!importer.ChromeLocalStorage} */ 865 /** @private @const {!importer.ChromeLocalStorage} */
972 importer.ChromeLocalStorage.INSTANCE_ = new importer.ChromeLocalStorage(); 866 importer.ChromeLocalStorage.INSTANCE_ = new importer.ChromeLocalStorage();
973 867
974 /** @return {!importer.ChromeLocalStorage} */ 868 /** @return {!importer.ChromeLocalStorage} */
975 importer.ChromeLocalStorage.getInstance = function() { 869 importer.ChromeLocalStorage.getInstance = function() {
976 return importer.ChromeLocalStorage.INSTANCE_; 870 return importer.ChromeLocalStorage.INSTANCE_;
977 }; 871 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698