1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 * Map of opened files, from a <code>openRequestId</code> to <code>filePath
10 * @type {Object.<number, string>}
15 * Metadata for a testing file.
19 var TESTING_TOO_LARGE_CHUNK_FILE = Object.freeze({
21 name: 'too-large-chunk.txt',
22 size: 2 * 1024 * 1024, // 2MB
23 modificationTime: new Date(2014, 1, 25, 7, 36, 12)
27 * Metadata for a testing file.
31 var TESTING_INVALID_CALLBACK_FILE = Object.freeze({
33 name: 'invalid-request.txt',
34 size: 1 * 1024 * 1024, // 1MB
35 modificationTime: new Date(2014, 1, 25, 7, 36, 12)
39 * Metadata for a testing file.
43 var TESTING_NEGATIVE_SIZE_FILE = Object.freeze({
45 name: 'negative-size.txt',
46 size: -1 * 1024 * 1024, // -1MB
47 modificationTime: new Date(2014, 1, 25, 7, 36, 12)
51 * Metadata for a testing file.
55 var TESTING_RELATIVE_NAME_FILE = Object.freeze({
57 name: '../../../b.txt',
58 size: 1 * 1024 * 1024, // 1MB
59 modificationTime: new Date(2014, 1, 25, 7, 36, 12)
63 * Requests opening a file at <code>filePath</code>. Further file operations
64 * will be associated with the <code>requestId</code>
66 * @param {OpenFileRequestedOptions} options Options.
67 * @param {function()} onSuccess Success callback.
68 * @param {function(string)} onError Error callback.
70 function onOpenFileRequested(options, onSuccess, onError) {
71 if (options.fileSystemId != test_util.FILE_SYSTEM_ID) {
72 onError('INVALID_OPERATION'); // enum ProviderError.
76 if (options.mode != 'READ') {
77 onError('ACCESS_DENIED'); // enum ProviderError.
81 if (options.filePath != '/' + TESTING_TOO_LARGE_CHUNK_FILE.name ||
82 options.filePath != '/' + TESTING_INVALID_CALLBACK_FILE.name ||
83 options.filePath != '/' + TESTING_NEGATIVE_SIZE_FILE.name ||
84 options.filePath != '/' + TESTING_RELATIVE_NAME_FILE.name) {
85 onError('NOT_FOUND'); // enum ProviderError.
89 openedFiles[options.requestId] = options.filePath;
94 * Requests closing a file previously opened with <code>openRequestId</code>.
96 * @param {CloseFileRequestedOptions} options Options.
97 * @param {function()} onSuccess Success callback.
98 * @param {function(string)} onError Error callback.
100 function onCloseFileRequested(options, onSuccess, onError) {
101 if (options.fileSystemId != test_util.FILE_SYSTEM_ID ||
102 !openedFiles[options.openRequestId]) {
103 onError('INVALID_OPERATION'); // enum ProviderError.
107 delete openedFiles[options.openRequestId];
112 * Requests reading contents of a file, previously opened with <code>
113 * openRequestId</code>.
115 * @param {ReadFileRequestedOptions} options Options.
116 * @param {function(ArrayBuffer, boolean)} onSuccess Success callback with a
117 * chunk of data, and information if more data will be provided later.
118 * @param {function(string)} onError Error callback.
120 function onReadFileRequested(options, onSuccess, onError) {
121 var filePath = openedFiles[options.openRequestId];
122 if (options.fileSystemId != test_util.FILE_SYSTEM_ID || !filePath) {
123 onError('INVALID_OPERATION'); // enum ProviderError.
127 if (filePath == '/' + TESTING_TOO_LARGE_CHUNK_FILE.name) {
129 while (buffer.length < 4 * TESTING_TOO_LARGE_CHUNK_FILE.size) {
130 buffer += 'I-LIKE-ICE-CREAM!';
132 var reader = new FileReader();
133 reader.onload = function(e) {
134 onSuccess(e.target.result, true /* hasMore */);
135 onSuccess(e.target.result, true /* hasMore */);
136 onSuccess(e.target.result, true /* hasMore */);
137 onSuccess(e.target.result, false /* hasMore */);
139 reader.readAsArrayBuffer(new Blob([buffer]));
143 if (filePath == '/' + TESTING_INVALID_CALLBACK_FILE.name) {
144 // Calling onSuccess after onError is unexpected. After handling the error
145 // the request should be removed.
146 onError('NOT_FOUND');
147 onSuccess(new ArrayBuffer(options.length * 4), false /* hasMore */);
151 if (filePath == '/' + TESTING_NEGATIVE_SIZE_FILE.name) {
152 onSuccess(new ArrayBuffer(-TESTING_NEGATIVE_SIZE_FILE.size * 2),
153 false /* hasMore */);
157 if (filePath == '/' + TESTING_RELATIVE_NAME_FILE.name) {
158 onSuccess(new ArrayBuffer(options.length), false /* hasMore */);
162 onError('INVALID_OPERATION'); // enum ProviderError.
166 * Sets up the tests. Called once per all test cases. In case of a failure,
167 * the callback is not called.
169 * @param {function()} callback Success callback.
171 function setUp(callback) {
172 chrome.fileSystemProvider.onGetMetadataRequested.addListener(
173 test_util.onGetMetadataRequestedDefault);
175 test_util.defaultMetadata['/' + TESTING_TOO_LARGE_CHUNK_FILE.name] =
176 TESTING_TOO_LARGE_CHUNK_FILE;
177 test_util.defaultMetadata['/' + TESTING_INVALID_CALLBACK_FILE.name] =
178 TESTING_INVALID_CALLBACK_FILE;
179 test_util.defaultMetadata['/' + TESTING_NEGATIVE_SIZE_FILE.name] =
180 TESTING_NEGATIVE_SIZE_FILE;
181 test_util.defaultMetadata['/' + TESTING_RELATIVE_NAME_FILE.name] =
182 TESTING_RELATIVE_NAME_FILE;
184 chrome.fileSystemProvider.onOpenFileRequested.addListener(
185 onOpenFileRequested);
186 chrome.fileSystemProvider.onReadFileRequested.addListener(
187 onReadFileRequested);
188 chrome.fileSystemProvider.onCloseFileRequested.addListener(
189 onCloseFileRequested);
191 test_util.mountFileSystem(callback);
195 * Runs all of the test cases, one by one.
197 function runTests() {
198 chrome.test.runTests([
199 // Tests that returning a too big chunk (4 times larger than the file size,
200 // and also much more than requested 1 KB of data).
201 function returnTooLargeChunk() {
202 test_util.fileSystem.root.getFile(
203 TESTING_TOO_LARGE_CHUNK_FILE.name,
205 chrome.test.callbackPass(function(fileEntry) {
206 fileEntry.file(chrome.test.callbackPass(function(file) {
207 // Read 1 KB of data.
208 var fileSlice = file.slice(0, 1024);
209 var fileReader = new FileReader();
210 fileReader.onload = function(e) {
211 chrome.test.fail('Reading should fail.');
213 fileReader.onerror = chrome.test.callbackPass();
214 fileReader.readAsText(fileSlice);
217 chrome.test.fail(error.name);
221 chrome.test.fail(error.name);
225 // Tests that calling a success callback with a non-existing request id
226 // doesn't cause any harm.
227 function invalidCallback() {
228 test_util.fileSystem.root.getFile(
229 TESTING_INVALID_CALLBACK_FILE.name,
231 chrome.test.callbackPass(function(fileEntry) {
232 fileEntry.file(chrome.test.callbackPass(function(file) {
233 // Read 1 KB of data.
234 var fileSlice = file.slice(0, 1024);
235 var fileReader = new FileReader();
236 fileReader.onload = function(e) {
237 chrome.test.fail('Reading should fail.');
239 fileReader.onerror = chrome.test.callbackPass();
240 fileReader.readAsText(fileSlice);
243 chrome.test.fail(error.name);
247 chrome.test.fail(error.name);
251 // Test that reading from files with negative size is not allowed.
252 function negativeSize() {
253 test_util.fileSystem.root.getFile(
254 TESTING_NEGATIVE_SIZE_FILE.name,
256 chrome.test.callbackPass(function(fileEntry) {
257 fileEntry.file(chrome.test.callbackPass(function(file) {
258 // Read 1 KB of data.
259 var fileSlice = file.slice(0, 1024);
260 var fileReader = new FileReader();
261 fileReader.onload = chrome.test.callbackPass(function(e) {
262 var text = fileReader.result;
263 chrome.test.assertEq(0, text.length);
265 fileReader.readAsText(fileSlice);
268 chrome.test.fail(error.name);
272 chrome.test.fail(error.name);
276 // Tests that URLs generated from a file containing .. inside is properly
278 function relativeName() {
279 test_util.fileSystem.root.getFile(
280 TESTING_RELATIVE_NAME_FILE.name,
282 function(fileEntry) {
283 chrome.test.fail('Opening a file should fail.');
285 chrome.test.callbackPass(function(error) {
286 chrome.test.assertEq('NotFoundError', error.name);
292 // Setup and run all of the test cases.