| 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 ||
 | 
| 
 |