Commit 95a98a7d authored by Bo Majewski's avatar Bo Majewski Committed by Commit Bot

Renames ImageRequest to ImageRequestTask

During a cleanup https://codereview.chromium.org/1148563004 the image
Request class was renamed to ImageRequest. However, the file name was
kept as request.js. Make the class and its file name the same.

Bug: 903742
Change-Id: I6f2d7bbfb6f3f94001d0cd1e629fc27f83061c45
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2245429Reviewed-by: default avatarLuciano Pacheco <lucmult@chromium.org>
Commit-Queue: Bo Majewski <majewski@chromium.org>
Cr-Commit-Position: refs/heads/master@{#779705}
parent c18c02f9
...@@ -22,3 +22,7 @@ IN_PROC_BROWSER_TEST_F(ImageLoaderJsTest, CacheTest) { ...@@ -22,3 +22,7 @@ IN_PROC_BROWSER_TEST_F(ImageLoaderJsTest, CacheTest) {
IN_PROC_BROWSER_TEST_F(ImageLoaderJsTest, ImageLoaderTest) { IN_PROC_BROWSER_TEST_F(ImageLoaderJsTest, ImageLoaderTest) {
RunTestURL("image_loader_unittest_gen.html"); RunTestURL("image_loader_unittest_gen.html");
} }
IN_PROC_BROWSER_TEST_F(ImageLoaderJsTest, SchedulerTest) {
RunTestURL("scheduler_unittest_gen.html");
}
...@@ -14,9 +14,9 @@ js_type_check("closure_compile_module") { ...@@ -14,9 +14,9 @@ js_type_check("closure_compile_module") {
":image_loader", ":image_loader",
":image_loader_client", ":image_loader_client",
":image_loader_util", ":image_loader_util",
":image_request_task",
":load_image_request", ":load_image_request",
":piex_loader", ":piex_loader",
":request",
":scheduler", ":scheduler",
] ]
} }
...@@ -39,9 +39,9 @@ js_unittest("cache_unittest") { ...@@ -39,9 +39,9 @@ js_unittest("cache_unittest") {
js_library("image_loader") { js_library("image_loader") {
deps = [ deps = [
":cache", ":cache",
":image_request_task",
":load_image_request", ":load_image_request",
":piex_loader", ":piex_loader",
":request",
":scheduler", ":scheduler",
"//ui/file_manager/externs:file_manager_private", "//ui/file_manager/externs:file_manager_private",
] ]
...@@ -96,7 +96,7 @@ js_library("piex_loader") { ...@@ -96,7 +96,7 @@ js_library("piex_loader") {
externs_list = [ "//ui/file_manager/externs/platform.js" ] externs_list = [ "//ui/file_manager/externs/platform.js" ]
} }
js_library("request") { js_library("image_request_task") {
deps = [ deps = [
":cache", ":cache",
":image_loader_util", ":image_loader_util",
...@@ -108,7 +108,14 @@ js_library("request") { ...@@ -108,7 +108,14 @@ js_library("request") {
} }
js_library("scheduler") { js_library("scheduler") {
deps = [ ":request" ] deps = [ ":image_request_task" ]
}
js_unittest("scheduler_unittest") {
deps = [
":scheduler",
"//ui/webui/resources/js:webui_resource_test",
]
} }
js_test_gen_html("js_test_gen_html") { js_test_gen_html("js_test_gen_html") {
...@@ -117,6 +124,7 @@ js_test_gen_html("js_test_gen_html") { ...@@ -117,6 +124,7 @@ js_test_gen_html("js_test_gen_html") {
":cache_unittest", ":cache_unittest",
":image_loader_client_unittest", ":image_loader_client_unittest",
":image_loader_unittest", ":image_loader_unittest",
":scheduler_unittest",
] ]
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
// <include src="image_loader.js"> // <include src="image_loader.js">
// <include src="image_loader_util.js"> // <include src="image_loader_util.js">
// <include src="piex_loader.js"> // <include src="piex_loader.js">
// <include src="request.js"> // <include src="image_request_task.js">
// <include src="scheduler.js"> // <include src="scheduler.js">
// Entry point. // Entry point.
// <include src="background.js"> // <include src="background.js">
...@@ -131,7 +131,7 @@ ImageLoader.prototype.onMessage_ = function(senderOrigin, request, callback) { ...@@ -131,7 +131,7 @@ ImageLoader.prototype.onMessage_ = function(senderOrigin, request, callback) {
return false; // No callback calls. return false; // No callback calls.
} else { } else {
// Create a request task and add it to the scheduler (queue). // Create a request task and add it to the scheduler (queue).
const requestTask = new ImageRequest( const requestTask = new ImageRequestTask(
requestId, this.cache_, this.piexLoader_, request, callback); requestId, this.cache_, this.piexLoader_, request, callback);
this.scheduler_.add(requestTask); this.scheduler_.add(requestTask);
return true; // Request will call the callback. return true; // Request will call the callback.
......
...@@ -3,43 +3,44 @@ ...@@ -3,43 +3,44 @@
// found in the LICENSE file. // found in the LICENSE file.
/** /**
* Scheduler for requests. Fetches requests from a queue and processes them * Scheduler for ImageRequestTask objects. Fetches tasks from a queue and
* synchronously, taking into account priorities. The highest priority is 0. * processes them synchronously, taking into account priorities. The highest
* priority is 0.
* @constructor * @constructor
*/ */
function Scheduler() { function Scheduler() {
/** /**
* List of requests waiting to be checked. If these items are available in * List of tasks waiting to be checked. If these items are available in
* cache, then they are processed immediately after starting the scheduler. * cache, then they are processed immediately after starting the scheduler.
* However, if they have to be downloaded, then these requests are moved * However, if they have to be downloaded, then these tasks are moved
* to pendingRequests_. * to pendingTasks_.
* *
* @type {Array<ImageRequest>} * @type {Array<ImageRequestTask>}
* @private * @private
*/ */
this.newRequests_ = []; this.newTasks_ = [];
/** /**
* List of pending requests for images to be downloaded. * List of pending tasks for images to be downloaded.
* @type {Array<ImageRequest>} * @type {Array<ImageRequestTask>}
* @private * @private
*/ */
this.pendingRequests_ = []; this.pendingTasks_ = [];
/** /**
* List of requests being processed. * List of tasks being processed.
* @type {Array<ImageRequest>} * @type {Array<ImageRequestTask>}
* @private * @private
*/ */
this.activeRequests_ = []; this.activeTasks_ = [];
/** /**
* Map of requests being added to the queue, but not finalized yet. Keyed by * Map of tasks being added to the queue, but not finalized yet. Keyed by
* the ImageRequest id. * the ImageRequestTask id.
* @type {Object<string, ImageRequest>}> * @type {Object<string, ImageRequestTask>}>
* @private * @private
*/ */
this.requests_ = {}; this.tasks_ = {};
/** /**
* If the scheduler has been started. * If the scheduler has been started.
...@@ -50,121 +51,119 @@ function Scheduler() { ...@@ -50,121 +51,119 @@ function Scheduler() {
} }
/** /**
* Maximum download requests to be run in parallel. * Maximum download tasks to be run in parallel.
* @type {number} * @type {number}
* @const * @const
*/ */
Scheduler.MAXIMUM_IN_PARALLEL = 5; Scheduler.MAXIMUM_IN_PARALLEL = 5;
/** /**
* Adds a request to the internal priority queue and executes it when requests * Adds a task to the internal priority queue and executes it when tasks
* with higher priorities are finished. If the result is cached, then it is * with higher priorities are finished. If the result is cached, then it is
* processed immediately once the scheduler is started. * processed immediately once the scheduler is started.
* *
* @param {ImageRequest} request Request object. * @param {ImageRequestTask} task A task to be run
*/ */
Scheduler.prototype.add = function(request) { Scheduler.prototype.add = function(task) {
if (!this.started_) { if (!this.started_) {
this.newRequests_.push(request); this.newTasks_.push(task);
this.requests_[request.getId()] = request; this.tasks_[task.getId()] = task;
return; return;
} }
// Enqueue the request, since already started. // Enqueue the tasks, since already started.
this.pendingRequests_.push(request); this.pendingTasks_.push(task);
this.sortPendingRequests_(); this.sortPendingTasks_();
this.continue_(); this.continue_();
}; };
/** /**
* Removes a request from the scheduler (if exists). * Removes a task from the scheduler (if exists).
* @param {string} requestId Unique ID of the request. * @param {string} taskId Unique ID of the task.
*/ */
Scheduler.prototype.remove = function(requestId) { Scheduler.prototype.remove = function(taskId) {
const request = this.requests_[requestId]; const task = this.tasks_[taskId];
if (!request) { if (!task) {
return; return;
} }
// Remove from the internal queues with pending tasks. // Remove from the internal queues with pending tasks.
const newIndex = this.pendingRequests_.indexOf(request); const newIndex = this.newTasks_.indexOf(task);
if (newIndex != -1) { if (newIndex != -1) {
this.newRequests_.splice(newIndex, 1); this.newTasks_.splice(newIndex, 1);
} }
const pendingIndex = this.pendingRequests_.indexOf(request); const pendingIndex = this.pendingTasks_.indexOf(task);
if (pendingIndex != -1) { if (pendingIndex != -1) {
this.pendingRequests_.splice(pendingIndex, 1); this.pendingTasks_.splice(pendingIndex, 1);
} }
// Cancel the request. // Cancel the task.
request.cancel(); task.cancel();
delete this.requests_[requestId]; delete this.tasks_[taskId];
}; };
/** /**
* Starts handling requests. * Starts handling tasks.
*/ */
Scheduler.prototype.start = function() { Scheduler.prototype.start = function() {
this.started_ = true; this.started_ = true;
// Process tasks added before scheduler has been started. // Process tasks added before scheduler has been started.
this.pendingRequests_ = this.newRequests_; this.pendingTasks_ = this.newTasks_;
this.sortPendingRequests_(); this.sortPendingTasks_();
this.newRequests_ = []; this.newTasks_ = [];
// Start serving enqueued requests. // Start serving enqueued tasks.
this.continue_(); this.continue_();
}; };
/** /**
* Sorts pending requests by priorities. * Sorts pending tasks by priorities.
* @private * @private
*/ */
Scheduler.prototype.sortPendingRequests_ = function() { Scheduler.prototype.sortPendingTasks_ = function() {
this.pendingRequests_.sort(function(a, b) { this.pendingTasks_.sort(function(a, b) {
return a.getPriority() - b.getPriority(); return a.getPriority() - b.getPriority();
}); });
}; };
/** /**
* Processes pending requests from the queue. There is no guarantee that * Processes pending tasks from the queue. There is no guarantee that
* all of the tasks will be processed at once. * all of the tasks will be processed at once.
* *
* @private * @private
*/ */
Scheduler.prototype.continue_ = function() { Scheduler.prototype.continue_ = function() {
// Run only up to MAXIMUM_IN_PARALLEL in the same time. // Run only up to MAXIMUM_IN_PARALLEL in the same time.
while (this.pendingRequests_.length && while (this.pendingTasks_.length &&
this.activeRequests_.length < Scheduler.MAXIMUM_IN_PARALLEL) { this.activeTasks_.length < Scheduler.MAXIMUM_IN_PARALLEL) {
const request = this.pendingRequests_.shift(); const task = this.pendingTasks_.shift();
this.activeRequests_.push(request); this.activeTasks_.push(task);
// Try to load from cache. If doesn't exist, then download. // Try to load from cache. If doesn't exist, then download.
request.loadFromCacheAndProcess( task.loadFromCacheAndProcess(
this.finish_.bind(this, request), this.finish_.bind(this, task), function(currentTask) {
function(currentRequest) { currentTask.downloadAndProcess(this.finish_.bind(this, currentTask));
currentRequest.downloadAndProcess( }.bind(this, task));
this.finish_.bind(this, currentRequest));
}.bind(this, request));
} }
}; };
/** /**
* Handles finished requests. * Handles finished tasks.
* *
* @param {ImageRequest} request Finished request. * @param {ImageRequestTask} task Finished task.
* @private * @private
*/ */
Scheduler.prototype.finish_ = function(request) { Scheduler.prototype.finish_ = function(task) {
const index = this.activeRequests_.indexOf(request); const index = this.activeTasks_.indexOf(task);
if (index < 0) { if (index < 0) {
console.warn('Request not found.'); console.warn('ImageRequestTask not found.');
} }
this.activeRequests_.splice(index, 1); this.activeTasks_.splice(index, 1);
delete this.requests_[request.getId()]; delete this.tasks_[task.getId()];
// Continue handling the most important requests (if started). // Continue handling the most important tasks (if started).
if (this.started_) { if (this.started_) {
this.continue_(); this.continue_();
} }
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
/**
* Fake global clock used to record the "time" at which a task was run.
*/
let globalTime = 0;
function setUp() {
globalTime = 0;
}
/**
* @typedef{{
* cancelCallCount: number,
* runTime: number,
* }}
*/
let FakeImageRequestTask;
/**
* @param {string} taskId
* @return {!FakeImageRequestTask}
*/
function newTask(taskId, priority) {
return /** @type !FakeImageRequestTask */ ({
// Counts how many times cancel method was called.
// Used to test multiple cancellation of the same task.
cancelCallCount: 0,
// Records value of globalTime variable at the time the main method,
// loadFromCacheAndProcess is called. Used to test if the task was
// executed and in what orders tasks were executed.
runTime: 0,
getId() {
return taskId;
},
getPriority() {
return priority;
},
cancel() {
++this.cancelCallCount;
},
loadFromCacheAndProcess(resolve, reject) {
this.runTime = ++globalTime;
setTimeout(resolve);
},
});
}
/**
* Checks that adding and removing tasks before the scheduler is started works.
*/
function testIdleSchedulerAddRemove() {
const scheduler = new Scheduler();
const fakeTask = newTask('task-1', 0);
scheduler.add(/** @type {!ImageRequestTask} */ (fakeTask));
assertEquals(0, fakeTask.cancelCallCount);
scheduler.remove('task-1');
assertEquals(1, fakeTask.cancelCallCount);
scheduler.remove('task-1');
assertEquals(1, fakeTask.cancelCallCount);
}
/**
* Checks that tasks that were in newTasks are correctly copied to pending
* tasks when scheduler is started. They also should be executed in the
* order of their priorities.
*/
function testNewTasksMovedAndRunInPriorityOrder() {
const fakeTask1 = newTask('task-1', 1);
const fakeTask2 = newTask('task-2', 0);
const scheduler = new Scheduler();
scheduler.add(/** @type {!ImageRequestTask} */ (fakeTask1));
scheduler.add(/** @type {!ImageRequestTask} */ (fakeTask2));
scheduler.start();
assertEquals(2, fakeTask1.runTime);
assertEquals(1, fakeTask2.runTime);
}
/**
* Checks that the scheduler only launches MAXIMUM_IN_PARALLEL tasks.
*/
function testParallelTasks() {
const scheduler = new Scheduler();
const taskList = [];
for (let i = 0; i <= Scheduler.MAXIMUM_IN_PARALLEL; ++i) {
taskList.push(newTask(`task-${i}`, 0));
scheduler.add(/** @type {!ImageRequestTask} */ (taskList[i]));
}
scheduler.start();
for (let i = 0; i < Scheduler.MAXIMUM_IN_PARALLEL; ++i) {
assertEquals(i + 1, taskList[i].runTime, `task ${i} did not run`);
}
assertEquals(0, taskList[Scheduler.MAXIMUM_IN_PARALLEL].runTime);
}
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