Commit 73506a4a authored by mtomasz's avatar mtomasz Committed by Commit bot

[fsp] Make the reading operation abortable.

Reading may be slow. We should be able to abort it to avoid unnecessary
consumption of resources such as network, cpu and memory.

TEST=browser_test: *FileSystemProvider*ReadFile*
BUG=400574

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

Cr-Commit-Position: refs/heads/master@{#291645}
parent c85a7365
......@@ -43,6 +43,11 @@ class FileStreamReader : public storage::FileStreamReader {
const net::Int64CompletionCallback& callback) OVERRIDE;
private:
// Helper class for executing operations on the provided file system. All
// of its methods must be called on UI thread. Callbacks are called on IO
// thread.
class OperationRunner;
// State of the file stream reader.
enum State { NOT_INITIALIZED, INITIALIZING, INITIALIZED, FAILED };
......@@ -59,9 +64,6 @@ class FileStreamReader : public storage::FileStreamReader {
void OnOpenFileCompleted(
const base::Closure& pending_closure,
const net::Int64CompletionCallback& error_callback,
base::WeakPtr<ProvidedFileSystemInterface> file_system,
const base::FilePath& file_path,
int file_handle,
base::File::Error result);
// Called when initialization is completed with either a success or an error.
......@@ -98,13 +100,9 @@ class FileStreamReader : public storage::FileStreamReader {
int64 current_offset_;
int64 current_length_;
base::Time expected_modification_time_;
scoped_refptr<OperationRunner> runner_;
State state_;
// Set during initialization (in case of a success).
base::WeakPtr<ProvidedFileSystemInterface> file_system_;
base::FilePath file_path_;
int file_handle_;
base::WeakPtrFactory<FileStreamReader> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(FileStreamReader);
};
......
......@@ -42,6 +42,19 @@ var TESTING_BROKEN_TIRAMISU_FILE = Object.freeze({
modificationTime: new Date(2014, 1, 25, 7, 36, 12)
});
/**
* Metadata of a broken file used to read contents from, but it simulates
* a very long read, in order to verify the aborting mechanism.
* @type {Object}
* @const
*/
var TESTING_VANILLA_FOR_ABORT_FILE = Object.freeze({
isDirectory: false,
name: 'vanilla.txt',
size: TESTING_TEXT.length,
modificationTime: new Date(2014, 1, 25, 7, 36, 12)
});
/**
* Requests reading contents of a file, previously opened with <code>
* openRequestId</code>.
......@@ -77,6 +90,11 @@ function onReadFileRequested(options, onSuccess, onError) {
return;
}
if (filePath == '/' + TESTING_VANILLA_FOR_ABORT_FILE.name) {
// Do nothing. This simulates a very slow read.
return;
}
if (filePath == '/' + TESTING_BROKEN_TIRAMISU_FILE.name) {
onError('ACCESS_DENIED'); // enum ProviderError.
return;
......@@ -103,6 +121,8 @@ function setUp(callback) {
TESTING_TIRAMISU_FILE;
test_util.defaultMetadata['/' + TESTING_BROKEN_TIRAMISU_FILE.name] =
TESTING_BROKEN_TIRAMISU_FILE;
test_util.defaultMetadata['/' + TESTING_VANILLA_FOR_ABORT_FILE.name] =
TESTING_VANILLA_FOR_ABORT_FILE;
chrome.fileSystemProvider.onReadFileRequested.addListener(
onReadFileRequested);
......@@ -143,7 +163,8 @@ function runTests() {
chrome.test.fail(error.name);
});
},
// Read contents of a file file, but with an error on the way. This should
// Read contents of a file, but with an error on the way. This should
// result in an error.
function readEntriesError() {
var onTestSuccess = chrome.test.callbackPass();
......@@ -163,7 +184,56 @@ function runTests() {
fileReader.readAsText(file);
},
function(error) {
chrome.test.fail(error.name);
});
},
function(error) {
chrome.test.fail(error.name);
});
},
// Abort reading a file with a registered abort handler. Should result in a
// gracefully terminated reading operation.
function abortReadingSuccess() {
var onTestSuccess = chrome.test.callbackPass();
var onAbortRequested = function(options, onSuccess, onError) {
chrome.fileSystemProvider.onAbortRequested.removeListener(
onAbortRequested);
onSuccess();
onTestSuccess();
};
chrome.fileSystemProvider.onAbortRequested.addListener(
onAbortRequested);
test_util.fileSystem.root.getFile(
TESTING_VANILLA_FOR_ABORT_FILE.name,
{create: false, exclusive: false},
function(fileEntry) {
fileEntry.file(function(file) {
var hadAbort = false;
var fileReader = new FileReader();
fileReader.onload = function(e) {
if (!hadAbort) {
chrome.test.fail(
'Unexpectedly finished writing, despite aborting.');
return;
}
chrome.test.fail();
};
fileReader.onerror = function(e) {
chrome.test.assertEq(
'AbortError', fileReader.error.name);
};
fileReader.readAsText(file);
setTimeout(function() {
// Abort the operation after it's started.
fileReader.abort();
}, 0);
},
function(error) {
chrome.test.fail(error.name);
});
},
function(error) {
......
......@@ -316,7 +316,7 @@ function runTests() {
},
// Abort writing to a valid file with a registered abort handler. Should
// resurt in a gracefully terminated writing operation.
// result in a gracefully terminated writing operation.
function abortWritingSuccess() {
var onTestSuccess = chrome.test.callbackPass();
......
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