| 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 ca7500945c715ff98c230b1e38e45a689d40701c..4769c693d3e62770abada37a9bea3f6be80bb403 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
|
| @@ -14,9 +14,8 @@
|
| * The following list is a todo list for this class. This list will be deleted
|
| * after all of them are implemented.
|
| * * Done: Fetch thumbnails with range based priority control.
|
| - * * Implement cache size limitation.
|
| - * * Modest queueing for low priority thumbnail fetches (i.e. not to use up IO
|
| - * by low priority tasks).
|
| + * * Done: Implement cache size limitation.
|
| + * * Done: Modest queueing for low priority thumbnail fetches.
|
| * * Handle other event types of FileListModel, e.g. sort.
|
| * * Change ThumbnailLoader to directly return dataUrl.
|
| * * Handle file types for which generic images are used.
|
| @@ -66,12 +65,12 @@ function ListThumbnailLoader(
|
| this.active_ = {};
|
|
|
| /**
|
| - * @type {Object<string, !Object>}
|
| + * @type {LRUCache<!Object>}
|
| * @private
|
| *
|
| - * TODO(yawano) Add size limitation to the cache.
|
| + * TODO(yawano): After ThumbnailData class is created, type this with it.
|
| */
|
| - this.cache_ = {};
|
| + this.cache_ = new LRUCache(ListThumbnailLoader.CACHE_SIZE);
|
|
|
| /**
|
| * @type {number}
|
| @@ -92,7 +91,7 @@ function ListThumbnailLoader(
|
| */
|
| this.cursor_ = 0;
|
|
|
| - // TODO(yawano) Handle other event types of FileListModel, e.g. sort.
|
| + // TODO(yawano): Handle other event types of FileListModel, e.g. sort.
|
| this.dataModel_.addEventListener('splice', this.onSplice_.bind(this));
|
| }
|
|
|
| @@ -105,19 +104,25 @@ ListThumbnailLoader.prototype.__proto__ = cr.EventTarget.prototype;
|
| ListThumbnailLoader.NUM_OF_MAX_ACTIVE_TASKS = 5;
|
|
|
| /**
|
| + * Number of prefetch requests.
|
| + * @const {number}
|
| + */
|
| +ListThumbnailLoader.NUM_OF_PREFETCH = 10;
|
| +
|
| +/**
|
| + * Cache size. Cache size must be larger than sum of high priority range size
|
| + * and number of prefetch tasks.
|
| + * @const {number}
|
| + */
|
| +ListThumbnailLoader.CACHE_SIZE = 100;
|
| +
|
| +/**
|
| * An event handler for splice event of data model. When list is changed, start
|
| * to rescan items.
|
| *
|
| * @param {!Event} event Event
|
| */
|
| ListThumbnailLoader.prototype.onSplice_ = function(event) {
|
| - // Delete thumbnails of removed items from cache.
|
| - for (var i = 0; i < event.removed.length; i++) {
|
| - var removedItem = event.removed[i];
|
| - if (this.cache_[removedItem.toURL()])
|
| - delete this.cache_[removedItem.toURL()];
|
| - }
|
| -
|
| this.cursor_ = this.beginIndex_;
|
| this.continue_();
|
| }
|
| @@ -146,7 +151,9 @@ ListThumbnailLoader.prototype.setHighPriorityRange = function(
|
| * @return {Object} If the thumbnail is not in cache, this returns null.
|
| */
|
| ListThumbnailLoader.prototype.getThumbnailFromCache = function(entry) {
|
| - return this.cache_[entry.toURL()] || null;
|
| + // Since we want to evict cache based on high priority range, we use peek here
|
| + // instead of get.
|
| + return this.cache_.peek(entry.toURL()) || null;
|
| }
|
|
|
| /**
|
| @@ -156,7 +163,8 @@ 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.dataModel_.length) ||
|
| + !(this.cursor_ < this.endIndex_ + ListThumbnailLoader.NUM_OF_PREFETCH)) {
|
| return;
|
| }
|
|
|
| @@ -164,7 +172,7 @@ ListThumbnailLoader.prototype.continue_ = function() {
|
|
|
| // If the entry is a directory, already in cache or fetching, skip it.
|
| if (entry.isDirectory ||
|
| - this.cache_[entry.toURL()] ||
|
| + this.cache_.get(entry.toURL()) ||
|
| this.active_[entry.toURL()]) {
|
| this.continue_();
|
| return;
|
| @@ -188,7 +196,7 @@ ListThumbnailLoader.prototype.enqueue_ = function(entry) {
|
|
|
| task.fetch().then(function(thumbnail) {
|
| delete this.active_[thumbnail.fileUrl];
|
| - this.cache_[thumbnail.fileUrl] = thumbnail;
|
| + this.cache_.put(thumbnail.fileUrl, thumbnail);
|
| this.dispatchThumbnailLoaded_(thumbnail);
|
| this.continue_();
|
| }.bind(this));
|
| @@ -200,7 +208,7 @@ ListThumbnailLoader.prototype.enqueue_ = function(entry) {
|
| * @param {Object} thumbnail Thumbnail.
|
| */
|
| ListThumbnailLoader.prototype.dispatchThumbnailLoaded_ = function(thumbnail) {
|
| - // TODO(yawano) Create ThumbnailLoadedEvent class.
|
| + // TODO(yawano): Create ThumbnailLoadedEvent class.
|
| var event = new Event('thumbnailLoaded');
|
| event.fileUrl = thumbnail.fileUrl;
|
| event.dataUrl = thumbnail.dataUrl;
|
| @@ -230,7 +238,7 @@ ListThumbnailLoader.Task = function(
|
|
|
| /**
|
| * Fetches thumbnail.
|
| - * TODO(yawano) Add error handling.
|
| + * TODO(yawano): Add error handling.
|
| *
|
| * @return {!Promise} A promise which is resolved when thumbnail is fetched.
|
| */
|
| @@ -239,7 +247,7 @@ ListThumbnailLoader.Task.prototype.fetch = function() {
|
| this.metadataCache_.getOne(this.entry_,
|
| 'thumbnail|filesystem|external|media',
|
| function(metadata) {
|
| - // TODO(yawano) Change ThumbnailLoader to directly return data url of
|
| + // TODO(yawano): Change ThumbnailLoader to directly return data url of
|
| // an image.
|
| var box = this.document_.createElement('div');
|
|
|
| @@ -251,7 +259,7 @@ ListThumbnailLoader.Task.prototype.fetch = function() {
|
| ThumbnailLoader.FillMode.FIT,
|
| ThumbnailLoader.OptimizationMode.DISCARD_DETACHED,
|
| function(image, transform) {
|
| - // TODO(yawano) Transform an image if necessary.
|
| + // TODO(yawano): Transform an image if necessary.
|
| var canvas = this.document_.createElement('canvas');
|
| canvas.width = image.width;
|
| canvas.height = image.height;
|
| @@ -259,7 +267,7 @@ ListThumbnailLoader.Task.prototype.fetch = function() {
|
| var context = canvas.getContext('2d');
|
| context.drawImage(image, 0, 0);
|
|
|
| - // TODO(yawano) Create ThumbnailData class.
|
| + // TODO(yawano): Create ThumbnailData class.
|
| resolve({
|
| fileUrl: this.entry_.toURL(),
|
| dataUrl: canvas.toDataURL('image/jpeg', 0.5),
|
|
|