| Index: ui/file_manager/file_manager/foreground/js/list_thumbnail_loader.js
|
| diff --git a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader.js b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader.js
|
| index adabbaa8a59fe3d2c239fc86fe9e535e5f779c83..3184679664eb411e75cb72c17d561d1cd1692c9c 100644
|
| --- a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader.js
|
| +++ b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader.js
|
| @@ -12,6 +12,7 @@
|
| *
|
| * @param {!FileListModel} dataModel A file list model.
|
| * @param {!ThumbnailModel} thumbnailModel Thumbnail metadata model.
|
| + * @param {!VolumeManagerWrapper} volumeManager Volume manager.
|
| * @param {Function=} opt_thumbnailLoaderConstructor A constructor of thumbnail
|
| * loader. This argument is used for testing.
|
| * @struct
|
| @@ -20,60 +21,61 @@
|
| * @suppress {checkStructDictInheritance}
|
| */
|
| function ListThumbnailLoader(
|
| - dataModel, thumbnailModel, opt_thumbnailLoaderConstructor) {
|
| + dataModel, thumbnailModel, volumeManager, opt_thumbnailLoaderConstructor) {
|
| /**
|
| - * @type {!FileListModel}
|
| - * @private
|
| + * @private {!FileListModel}
|
| */
|
| this.dataModel_ = dataModel;
|
|
|
| /**
|
| - * @type {!ThumbnailModel}
|
| - * @private
|
| + * @private {!ThumbnailModel}
|
| */
|
| this.thumbnailModel_ = thumbnailModel;
|
|
|
| /**
|
| + * @private {!VolumeManagerWrapper}
|
| + */
|
| + this.volumeManager_ = volumeManager;
|
| +
|
| + /**
|
| * Constructor of thumbnail loader.
|
| - * @type {!Function}
|
| - * @private
|
| + * @private {!Function}
|
| */
|
| this.thumbnailLoaderConstructor_ =
|
| opt_thumbnailLoaderConstructor || ThumbnailLoader;
|
|
|
| /**
|
| - * @type {Object<string, !ListThumbnailLoader.Task>}
|
| - * @private
|
| + * @private {Object<string, !ListThumbnailLoader.Task>}
|
| */
|
| this.active_ = {};
|
|
|
| /**
|
| - * @type {LRUCache<!ListThumbnailLoader.ThumbnailData>}
|
| - * @private
|
| + * @private {LRUCache<!ListThumbnailLoader.ThumbnailData>}
|
| */
|
| this.cache_ = new LRUCache(ListThumbnailLoader.CACHE_SIZE);
|
|
|
| /**
|
| - * @type {number}
|
| - * @private
|
| + * @private {number}
|
| */
|
| this.beginIndex_ = 0;
|
|
|
| /**
|
| - * @type {number}
|
| - * @private
|
| + * @private {number}
|
| */
|
| this.endIndex_ = 0;
|
|
|
| /**
|
| * Cursor.
|
| - * @type {number}
|
| - * @private
|
| + * @private {number}
|
| */
|
| this.cursor_ = 0;
|
|
|
| - // TODO(yawano): Change FileListModel to dispatch change event for file
|
| - // change, and change this class to handle it.
|
| + /**
|
| + * Current volume type.
|
| + * @private {?ListThumbnailLoader.VolumeType}
|
| + */
|
| + this.currentVolumeType_ = null;
|
| +
|
| this.dataModel_.addEventListener('splice', this.onSplice_.bind(this));
|
| this.dataModel_.addEventListener('sorted', this.onSorted_.bind(this));
|
| this.dataModel_.addEventListener('change', this.onChange_.bind(this));
|
| @@ -82,23 +84,64 @@ function ListThumbnailLoader(
|
| ListThumbnailLoader.prototype.__proto__ = cr.EventTarget.prototype;
|
|
|
| /**
|
| - * Number of maximum active tasks.
|
| + * Cache size. Cache size must be larger than sum of high priority range size
|
| + * and number of prefetch tasks.
|
| * @const {number}
|
| */
|
| -ListThumbnailLoader.NUM_OF_MAX_ACTIVE_TASKS = 10;
|
| +ListThumbnailLoader.CACHE_SIZE = 500;
|
| +
|
| +/**
|
| + * Volume type for testing.
|
| + * @const {string}
|
| + */
|
| +ListThumbnailLoader.TEST_VOLUME_TYPE = 'test_volume_type';
|
|
|
| /**
|
| - * Number of prefetch requests.
|
| - * @const {number}
|
| + * Number of maximum active tasks for testing.
|
| + * @type {number}
|
| */
|
| -ListThumbnailLoader.NUM_OF_PREFETCH = 20;
|
| +ListThumbnailLoader.numOfMaxActiveTasksForTest = 2;
|
|
|
| /**
|
| - * Cache size. Cache size must be larger than sum of high priority range size
|
| - * and number of prefetch tasks.
|
| - * @const {number}
|
| + * @typedef {(VolumeManagerCommon.VolumeType|string)}
|
| */
|
| -ListThumbnailLoader.CACHE_SIZE = 500;
|
| +ListThumbnailLoader.VolumeType;
|
| +
|
| +/**
|
| + * Gets number of prefetch requests. This number changes based on current volume
|
| + * type.
|
| + * @return {number} Number of prefetch requests.
|
| + * @private
|
| + */
|
| +ListThumbnailLoader.prototype.getNumOfPrefetch_ = function () {
|
| + switch (/** @type {?ListThumbnailLoader.VolumeType} */
|
| + (this.currentVolumeType_)) {
|
| + case VolumeManagerCommon.VolumeType.MTP:
|
| + return 0;
|
| + case ListThumbnailLoader.TEST_VOLUME_TYPE:
|
| + return 1;
|
| + default:
|
| + return 20;
|
| + }
|
| +};
|
| +
|
| +/**
|
| + * Gets maximum number of active thumbnail fetch tasks. This number changes
|
| + * based on current volume type.
|
| + * @return {number} Maximum number of active thumbnail fetch tasks.
|
| + * @private
|
| + */
|
| +ListThumbnailLoader.prototype.getNumOfMaxActiveTasks_ = function() {
|
| + switch (/** @type {?ListThumbnailLoader.VolumeType} */
|
| + (this.currentVolumeType_)) {
|
| + case VolumeManagerCommon.VolumeType.MTP:
|
| + return 1;
|
| + case ListThumbnailLoader.TEST_VOLUME_TYPE:
|
| + return ListThumbnailLoader.numOfMaxActiveTasksForTest;
|
| + default:
|
| + return 10;
|
| + }
|
| +};
|
|
|
| /**
|
| * An event handler for splice event of data model. When list is changed, start
|
| @@ -171,21 +214,24 @@ ListThumbnailLoader.prototype.getThumbnailFromCache = function(entry) {
|
|
|
| /**
|
| * Enqueues tasks if available.
|
| - *
|
| - * TODO(yawano): Make queueing for low priority thumbnail fetches more moderate
|
| - * and smart.
|
| */
|
| ListThumbnailLoader.prototype.continue_ = function() {
|
| - // If tasks are running full or all items are scanned, do nothing.
|
| - if (!(Object.keys(this.active_).length <
|
| - ListThumbnailLoader.NUM_OF_MAX_ACTIVE_TASKS) ||
|
| - !(this.cursor_ < this.dataModel_.length) ||
|
| - !(this.cursor_ < this.endIndex_ + ListThumbnailLoader.NUM_OF_PREFETCH)) {
|
| + // If all items are scanned, do nothing.
|
| + if (!(this.cursor_ < this.dataModel_.length))
|
| return;
|
| - }
|
|
|
| var entry = /** @type {Entry} */ (this.dataModel_.item(this.cursor_));
|
|
|
| + // Check volume type for optimizing the parameters.
|
| + var volumeInfo = this.volumeManager_.getVolumeInfo(entry);
|
| + this.currentVolumeType_ = volumeInfo ? volumeInfo.volumeType : null;
|
| +
|
| + // If tasks are running full or all items are scanned, do nothing.
|
| + if (!(Object.keys(this.active_).length < this.getNumOfMaxActiveTasks_()) ||
|
| + !(this.cursor_ < this.endIndex_ + this.getNumOfPrefetch_())) {
|
| + return;
|
| + }
|
| +
|
| // If the entry is a directory, already in cache as valid or fetching, skip.
|
| var thumbnail = this.cache_.get(entry.toURL());
|
| if (entry.isDirectory ||
|
|
|