Commit 79796fe5 authored by yawano's avatar yawano Committed by Commit bot

Change ListThumbnailLoader to use ThumbnailLoader.loadAsDataUrl.

BUG=438050
TEST=out/Release/browser_tests --gtest_filter=FileManagerJsTest.ListThumbnailLoader

Review URL: https://codereview.chromium.org/895093003

Cr-Commit-Position: refs/heads/master@{#314795}
parent a9bfa5b4
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* * Done: Implement cache size limitation. * * Done: Implement cache size limitation.
* * Done: Modest queueing for low priority thumbnail fetches. * * Done: Modest queueing for low priority thumbnail fetches.
* * Handle other event types of FileListModel, e.g. sort. * * Handle other event types of FileListModel, e.g. sort.
* * Change ThumbnailLoader to directly return dataUrl. * * Done: Change ThumbnailLoader to directly return dataUrl.
* * Handle file types for which generic images are used. * * Handle file types for which generic images are used.
* *
* @param {!FileListModel} dataModel A file list model. * @param {!FileListModel} dataModel A file list model.
...@@ -65,10 +65,8 @@ function ListThumbnailLoader( ...@@ -65,10 +65,8 @@ function ListThumbnailLoader(
this.active_ = {}; this.active_ = {};
/** /**
* @type {LRUCache<!Object>} * @type {LRUCache<!ListThumbnailLoader.ThumbnailData>}
* @private * @private
*
* TODO(yawano): After ThumbnailData class is created, type this with it.
*/ */
this.cache_ = new LRUCache(ListThumbnailLoader.CACHE_SIZE); this.cache_ = new LRUCache(ListThumbnailLoader.CACHE_SIZE);
...@@ -192,13 +190,17 @@ ListThumbnailLoader.prototype.enqueue_ = function(entry) { ...@@ -192,13 +190,17 @@ ListThumbnailLoader.prototype.enqueue_ = function(entry) {
entry, this.metadataCache_, this.document_, entry, this.metadataCache_, this.document_,
this.thumbnailLoaderConstructor_); this.thumbnailLoaderConstructor_);
this.active_[entry.toURL()] = task; var url = entry.toURL();
this.active_[url] = task;
task.fetch().then(function(thumbnail) { task.fetch().then(function(thumbnail) {
delete this.active_[thumbnail.fileUrl]; delete this.active_[url];
this.cache_.put(thumbnail.fileUrl, thumbnail); this.cache_.put(url, thumbnail);
this.dispatchThumbnailLoaded_(thumbnail); this.dispatchThumbnailLoaded_(thumbnail);
this.continue_(); this.continue_();
}.bind(this), function() {
delete this.active_[url];
this.continue_();
}.bind(this)); }.bind(this));
} }
...@@ -217,6 +219,37 @@ ListThumbnailLoader.prototype.dispatchThumbnailLoaded_ = function(thumbnail) { ...@@ -217,6 +219,37 @@ ListThumbnailLoader.prototype.dispatchThumbnailLoaded_ = function(thumbnail) {
this.dispatchEvent(event); this.dispatchEvent(event);
}; };
/**
* A class to represent thumbnail data.
* @param {string} fileUrl File url of an original image.
* @param {string} dataUrl Data url of thumbnail.
* @param {number} width Width of thumbnail.
* @param {number} height Height of thumbnail.
* @constructor
* @struct
*/
ListThumbnailLoader.ThumbnailData = function(fileUrl, dataUrl, width, height) {
/**
* @const {string}
*/
this.fileUrl = fileUrl;
/**
* @const {string}
*/
this.dataUrl = dataUrl;
/**
* @const {number}
*/
this.width = width;
/**
* @const {number}
*/
this.height = height;
}
/** /**
* A task to load thumbnail. * A task to load thumbnail.
* *
...@@ -238,43 +271,20 @@ ListThumbnailLoader.Task = function( ...@@ -238,43 +271,20 @@ ListThumbnailLoader.Task = function(
/** /**
* Fetches thumbnail. * Fetches thumbnail.
* TODO(yawano): Add error handling.
* *
* @return {!Promise} A promise which is resolved when thumbnail is fetched. * @return {!Promise<!ListThumbnailLoader.ThumbnailData>} A promise which is
* resolved when thumbnail is fetched.
*/ */
ListThumbnailLoader.Task.prototype.fetch = function() { ListThumbnailLoader.Task.prototype.fetch = function() {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
this.metadataCache_.getOne(this.entry_, this.metadataCache_.getOne(
'thumbnail|filesystem|external|media', this.entry_, 'thumbnail|filesystem|external|media', resolve);
function(metadata) { }.bind(this)).then(function(metadata) {
// TODO(yawano): Change ThumbnailLoader to directly return data url of return new this.thumbnailLoaderConstructor_(
// an image. this.entry_, ThumbnailLoader.LoaderType.IMAGE, metadata)
var box = this.document_.createElement('div'); .loadAsDataUrl();
}.bind(this)).then(function(result) {
var thumbnailLoader = new this.thumbnailLoaderConstructor_( return new ListThumbnailLoader.ThumbnailData(
this.entry_, this.entry_.toURL(), result.data, result.width, result.height);
ThumbnailLoader.LoaderType.IMAGE,
metadata);
thumbnailLoader.load(box,
ThumbnailLoader.FillMode.FIT,
ThumbnailLoader.OptimizationMode.DISCARD_DETACHED,
function(image, transform) {
// TODO(yawano): Transform an image if necessary.
var canvas = this.document_.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
// TODO(yawano): Create ThumbnailData class.
resolve({
fileUrl: this.entry_.toURL(),
dataUrl: canvas.toDataURL('image/jpeg', 0.5),
width: image.width,
height: image.height
});
}.bind(this));
}.bind(this));
}.bind(this)); }.bind(this));
} }
...@@ -58,7 +58,10 @@ function setUp() { ...@@ -58,7 +58,10 @@ function setUp() {
ListThumbnailLoader.NUM_OF_MAX_ACTIVE_TASKS = 2; ListThumbnailLoader.NUM_OF_MAX_ACTIVE_TASKS = 2;
ListThumbnailLoader.NUM_OF_PREFETCH = 1; ListThumbnailLoader.NUM_OF_PREFETCH = 1;
ListThumbnailLoader.CACHE_SIZE = 5; ListThumbnailLoader.CACHE_SIZE = 5;
MockThumbnailLoader.setTestImageDataUrl(generateSampleImageDataUrl(document)); MockThumbnailLoader.errorUrls = [];
MockThumbnailLoader.testImageDataUrl = generateSampleImageDataUrl(document);
MockThumbnailLoader.testImageWidth = 160;
MockThumbnailLoader.testImageHeight = 160;
getOneCallbacks = {}; getOneCallbacks = {};
var metadataCache = { var metadataCache = {
...@@ -221,3 +224,21 @@ function testCache(callback) { ...@@ -221,3 +224,21 @@ function testCache(callback) {
}); });
}), callback); }), callback);
} }
/**
* Test case for thumbnail fetch error. In this test case, thumbnail fetch for
* entry 2 is failed.
*/
function testErrorHandling(callback) {
MockThumbnailLoader.errorUrls = [entry2.toURL()];
listThumbnailLoader.setHighPriorityRange(0, 2);
fileListModel.push(entry1, entry2, entry3, entry4);
resolveGetOneCallback(entry2.toURL());
// Assert that new task is enqueued for entry3.
reportPromise(waitUntil(function() {
return !!getOneCallbacks[entry3.toURL()];
}), callback);
}
...@@ -14,43 +14,46 @@ ...@@ -14,43 +14,46 @@
*/ */
function MockThumbnailLoader(entry, opt_loaderType, opt_metadata, opt_mediaType, function MockThumbnailLoader(entry, opt_loaderType, opt_metadata, opt_mediaType,
opt_loadTargets, opt_priority) { opt_loadTargets, opt_priority) {
this.testImageDataUrl_ = null; this.entry_ = entry;
} }
/** /**
* @type {string} Data url of an image. * Data url of test image.
* @private {string}
*/ */
MockThumbnailLoader.testImageDataUrl_ = null; MockThumbnailLoader.testImageDataUrl = null;
/** /**
* Set data url of an image which is returned for testing. * Width of test image.
* * @private {number}
* @param {string} dataUrl Data url of an image.
*/ */
MockThumbnailLoader.setTestImageDataUrl = function(dataUrl) { MockThumbnailLoader.testImageWidth = 0;
MockThumbnailLoader.testImageDataUrl_ = dataUrl;
}; /**
* Height of test image.
* @private {number}
*/
MockThumbnailLoader.testImageHeight = 0;
/** /**
* Load an image. (This mock implementation does not attach an image to the * Error urls.
* box). * @private {Array<string>}
*/
MockThumbnailLoader.errorUrls = [];
/**
* Loads thumbnail as data url.
* *
* @param {Element} box Box. * @return {!Promise<{data:string, width:number, height:number}>} A promise
* @param {ThumbnailLoader.FillMode} fillMode Fill mode. * which is resolved with data url.
* @param {ThumbnailLoader.OptimizationMode=} opt_optimizationMode Optimization.
* @param {function(Image, Object)=} opt_onSuccess Success callback.
* @param {function()=} opt_onError Error callback.
* @param {function()=} opt_onGeneric Callback which is called when generic
* image is used.
*/ */
MockThumbnailLoader.prototype.load = function( MockThumbnailLoader.prototype.loadAsDataUrl = function() {
box, fillMode, opt_optimizationMode, opt_onSuccess, opt_onError, if (MockThumbnailLoader.errorUrls.indexOf(this.entry_.toURL()) !== -1)
opt_onGeneric) { throw new Error('Failed to load thumbnail.');
if (opt_onSuccess && MockThumbnailLoader.testImageDataUrl_) {
var image = new Image(); return Promise.resolve({
image.onload = function() { data: MockThumbnailLoader.testImageDataUrl,
opt_onSuccess(image, null); width: MockThumbnailLoader.testImageWidth,
}; height: MockThumbnailLoader.testImageHeight
image.src = MockThumbnailLoader.testImageDataUrl_; });
}
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment