OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 'use strict'; | 5 'use strict'; |
6 | 6 |
7 /** | 7 /** |
8 * @type {DOMFileSystem} | 8 * @type {DOMFileSystem} |
9 */ | 9 */ |
10 var fileSystem = null; | 10 var fileSystem = null; |
11 | 11 |
12 /** | 12 /** |
13 * Map of opened files, from a <code>openRequestId</code> to <code>filePath | 13 * Map of opened files, from a <code>openRequestId</code> to <code>filePath |
14 * </code>. | 14 * </code>. |
15 * @type {Object.<number, string>} | 15 * @type {Object.<number, string>} |
16 */ | 16 */ |
17 var openedFiles = {}; | 17 var openedFiles = {}; |
18 | 18 |
19 /** | 19 /** |
20 * @type {string} | |
21 * @const | |
22 */ | |
23 var FILE_SYSTEM_ID = 'chocolate-id'; | |
24 | |
25 /** | |
26 * @type {Object} | 20 * @type {Object} |
27 * @const | 21 * @const |
28 */ | 22 */ |
29 var TESTING_ROOT = Object.freeze({ | 23 var TESTING_ROOT = Object.freeze({ |
30 isDirectory: true, | 24 isDirectory: true, |
31 name: '', | 25 name: '', |
32 size: 0, | 26 size: 0, |
33 modificationTime: new Date(2014, 4, 28, 10, 39, 15) | 27 modificationTime: new Date(2014, 4, 28, 10, 39, 15) |
34 }); | 28 }); |
35 | 29 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 * @const | 69 * @const |
76 */ | 70 */ |
77 var TESTING_RELATIVE_NAME_FILE = Object.freeze({ | 71 var TESTING_RELATIVE_NAME_FILE = Object.freeze({ |
78 isDirectory: false, | 72 isDirectory: false, |
79 name: '../../../b.txt', | 73 name: '../../../b.txt', |
80 size: 1 * 1024 * 1024, // 1MB | 74 size: 1 * 1024 * 1024, // 1MB |
81 modificationTime: new Date(2014, 1, 25, 7, 36, 12) | 75 modificationTime: new Date(2014, 1, 25, 7, 36, 12) |
82 }); | 76 }); |
83 | 77 |
84 /** | 78 /** |
85 * Gets volume information for the provided file system. | |
86 * | |
87 * @param {string} fileSystemId Id of the provided file system. | |
88 * @param {function(Object)} callback Callback to be called on result, with the | |
89 * volume information object in case of success, or null if not found. | |
90 */ | |
91 function getVolumeInfo(fileSystemId, callback) { | |
92 chrome.fileBrowserPrivate.getVolumeMetadataList(function(volumeList) { | |
93 for (var i = 0; i < volumeList.length; i++) { | |
94 if (volumeList[i].extensionId == chrome.runtime.id && | |
95 volumeList[i].fileSystemId == fileSystemId) { | |
96 callback(volumeList[i]); | |
97 return; | |
98 } | |
99 } | |
100 callback(null); | |
101 }); | |
102 } | |
103 | |
104 /** | |
105 * Returns metadata for the requested entry. | 79 * Returns metadata for the requested entry. |
106 * | 80 * |
107 * To successfully acquire a DirectoryEntry, or even a DOMFileSystem, this event | 81 * To successfully acquire a DirectoryEntry, or even a DOMFileSystem, this event |
108 * must be implemented and return correct values. | 82 * must be implemented and return correct values. |
109 * | 83 * |
110 * @param {GetMetadataRequestedOptions} options Options. | 84 * @param {GetMetadataRequestedOptions} options Options. |
111 * @param {function(Object)} onSuccess Success callback with metadata passed | 85 * @param {function(Object)} onSuccess Success callback with metadata passed |
112 * an argument. | 86 * an argument. |
113 * @param {function(string)} onError Error callback with an error code. | 87 * @param {function(string)} onError Error callback with an error code. |
114 */ | 88 */ |
115 function onGetMetadataRequested(options, onSuccess, onError) { | 89 function onGetMetadataRequested(options, onSuccess, onError) { |
116 if (options.fileSystemId != FILE_SYSTEM_ID) { | 90 if (options.fileSystemId != test_util.FILE_SYSTEM_ID) { |
117 onError('INVALID_OPERATION'); // enum ProviderError. | 91 onError('INVALID_OPERATION'); // enum ProviderError. |
118 return; | 92 return; |
119 } | 93 } |
120 | 94 |
121 if (options.entryPath == '/') { | 95 if (options.entryPath == '/') { |
122 onSuccess(TESTING_ROOT); | 96 onSuccess(TESTING_ROOT); |
123 return; | 97 return; |
124 } | 98 } |
125 | 99 |
126 if (options.entryPath == '/' + TESTING_TOO_LARGE_CHUNK_FILE.name) { | 100 if (options.entryPath == '/' + TESTING_TOO_LARGE_CHUNK_FILE.name) { |
(...skipping 21 matching lines...) Expand all Loading... |
148 | 122 |
149 /** | 123 /** |
150 * Requests opening a file at <code>filePath</code>. Further file operations | 124 * Requests opening a file at <code>filePath</code>. Further file operations |
151 * will be associated with the <code>requestId</code> | 125 * will be associated with the <code>requestId</code> |
152 * | 126 * |
153 * @param {OpenFileRequestedOptions} options Options. | 127 * @param {OpenFileRequestedOptions} options Options. |
154 * @param {function()} onSuccess Success callback. | 128 * @param {function()} onSuccess Success callback. |
155 * @param {function(string)} onError Error callback. | 129 * @param {function(string)} onError Error callback. |
156 */ | 130 */ |
157 function onOpenFileRequested(options, onSuccess, onError) { | 131 function onOpenFileRequested(options, onSuccess, onError) { |
158 if (options.fileSystemId != FILE_SYSTEM_ID) { | 132 if (options.fileSystemId != test_util.FILE_SYSTEM_ID) { |
159 onError('INVALID_OPERATION'); // enum ProviderError. | 133 onError('INVALID_OPERATION'); // enum ProviderError. |
160 return; | 134 return; |
161 } | 135 } |
162 | 136 |
163 if (options.mode != 'READ' || options.create) { | 137 if (options.mode != 'READ' || options.create) { |
164 onError('ACCESS_DENIED'); // enum ProviderError. | 138 onError('ACCESS_DENIED'); // enum ProviderError. |
165 return; | 139 return; |
166 } | 140 } |
167 | 141 |
168 if (options.filePath != '/' + TESTING_TOO_LARGE_CHUNK_FILE.name || | 142 if (options.filePath != '/' + TESTING_TOO_LARGE_CHUNK_FILE.name || |
169 options.filePath != '/' + TESTING_INVALID_CALLBACK_FILE.name || | 143 options.filePath != '/' + TESTING_INVALID_CALLBACK_FILE.name || |
170 options.filePath != '/' + TESTING_NEGATIVE_SIZE_FILE.name || | 144 options.filePath != '/' + TESTING_NEGATIVE_SIZE_FILE.name || |
171 options.filePath != '/' + TESTING_RELATIVE_NAME_FILE.name) { | 145 options.filePath != '/' + TESTING_RELATIVE_NAME_FILE.name) { |
172 onError('NOT_FOUND'); // enum ProviderError. | 146 onError('NOT_FOUND'); // enum ProviderError. |
173 return; | 147 return; |
174 } | 148 } |
175 | 149 |
176 openedFiles[options.requestId] = options.filePath; | 150 openedFiles[options.requestId] = options.filePath; |
177 onSuccess(); | 151 onSuccess(); |
178 } | 152 } |
179 | 153 |
180 /** | 154 /** |
181 * Requests closing a file previously opened with <code>openRequestId</code>. | 155 * Requests closing a file previously opened with <code>openRequestId</code>. |
182 * | 156 * |
183 * @param {CloseFileRequestedOptions} options Options. | 157 * @param {CloseFileRequestedOptions} options Options. |
184 * @param {function()} onSuccess Success callback. | 158 * @param {function()} onSuccess Success callback. |
185 * @param {function(string)} onError Error callback. | 159 * @param {function(string)} onError Error callback. |
186 */ | 160 */ |
187 function onCloseFileRequested(options, onSuccess, onError) { | 161 function onCloseFileRequested(options, onSuccess, onError) { |
188 if (options.fileSystemId != FILE_SYSTEM_ID || | 162 if (options.fileSystemId != test_util.FILE_SYSTEM_ID || |
189 !openedFiles[options.openRequestId]) { | 163 !openedFiles[options.openRequestId]) { |
190 onError('INVALID_OPERATION'); // enum ProviderError. | 164 onError('INVALID_OPERATION'); // enum ProviderError. |
191 return; | 165 return; |
192 } | 166 } |
193 | 167 |
194 delete openedFiles[options.openRequestId]; | 168 delete openedFiles[options.openRequestId]; |
195 onSuccess(); | 169 onSuccess(); |
196 } | 170 } |
197 | 171 |
198 /** | 172 /** |
199 * Requests reading contents of a file, previously opened with <code> | 173 * Requests reading contents of a file, previously opened with <code> |
200 * openRequestId</code>. | 174 * openRequestId</code>. |
201 * | 175 * |
202 * @param {ReadFileRequestedOptions} options Options. | 176 * @param {ReadFileRequestedOptions} options Options. |
203 * @param {function(ArrayBuffer, boolean)} onSuccess Success callback with a | 177 * @param {function(ArrayBuffer, boolean)} onSuccess Success callback with a |
204 * chunk of data, and information if more data will be provided later. | 178 * chunk of data, and information if more data will be provided later. |
205 * @param {function(string)} onError Error callback. | 179 * @param {function(string)} onError Error callback. |
206 */ | 180 */ |
207 function onReadFileRequested(options, onSuccess, onError) { | 181 function onReadFileRequested(options, onSuccess, onError) { |
208 var filePath = openedFiles[options.openRequestId]; | 182 var filePath = openedFiles[options.openRequestId]; |
209 if (options.fileSystemId != FILE_SYSTEM_ID || !filePath) { | 183 if (options.fileSystemId != test_util.FILE_SYSTEM_ID || !filePath) { |
210 onError('INVALID_OPERATION'); // enum ProviderError. | 184 onError('INVALID_OPERATION'); // enum ProviderError. |
211 return; | 185 return; |
212 } | 186 } |
213 | 187 |
214 if (filePath == '/' + TESTING_TOO_LARGE_CHUNK_FILE.name) { | 188 if (filePath == '/' + TESTING_TOO_LARGE_CHUNK_FILE.name) { |
215 var buffer = ''; | 189 var buffer = ''; |
216 while (buffer.length < 4 * TESTING_TOO_LARGE_CHUNK_FILE.size) { | 190 while (buffer.length < 4 * TESTING_TOO_LARGE_CHUNK_FILE.size) { |
217 buffer += 'I-LIKE-ICE-CREAM!'; | 191 buffer += 'I-LIKE-ICE-CREAM!'; |
218 } | 192 } |
219 var reader = new FileReader(); | 193 var reader = new FileReader(); |
(...skipping 29 matching lines...) Expand all Loading... |
249 onError('INVALID_OPERATION'); // enum ProviderError. | 223 onError('INVALID_OPERATION'); // enum ProviderError. |
250 } | 224 } |
251 | 225 |
252 /** | 226 /** |
253 * Sets up the tests. Called once per all test cases. In case of a failure, | 227 * Sets up the tests. Called once per all test cases. In case of a failure, |
254 * the callback is not called. | 228 * the callback is not called. |
255 * | 229 * |
256 * @param {function()} callback Success callback. | 230 * @param {function()} callback Success callback. |
257 */ | 231 */ |
258 function setUp(callback) { | 232 function setUp(callback) { |
259 chrome.fileSystemProvider.mount( | 233 chrome.fileSystemProvider.onGetMetadataRequested.addListener( |
260 {fileSystemId: FILE_SYSTEM_ID, displayName: 'chocolate.zip'}, | 234 onGetMetadataRequested); |
261 function() { | 235 chrome.fileSystemProvider.onOpenFileRequested.addListener( |
262 chrome.fileSystemProvider.onGetMetadataRequested.addListener( | 236 onOpenFileRequested); |
263 onGetMetadataRequested); | 237 chrome.fileSystemProvider.onReadFileRequested.addListener( |
264 chrome.fileSystemProvider.onOpenFileRequested.addListener( | 238 onReadFileRequested); |
265 onOpenFileRequested); | 239 chrome.fileSystemProvider.onCloseFileRequested.addListener( |
266 chrome.fileSystemProvider.onReadFileRequested.addListener( | 240 onCloseFileRequested); |
267 onReadFileRequested); | 241 test_util.mountFileSystem(callback); |
268 var volumeId = | |
269 'provided:' + chrome.runtime.id + '-' + FILE_SYSTEM_ID + '-user'; | |
270 | |
271 getVolumeInfo(FILE_SYSTEM_ID, function(volumeInfo) { | |
272 chrome.test.assertTrue(!!volumeInfo); | |
273 chrome.fileBrowserPrivate.requestFileSystem( | |
274 volumeInfo.volumeId, | |
275 function(inFileSystem) { | |
276 chrome.test.assertTrue(!!inFileSystem); | |
277 | |
278 fileSystem = inFileSystem; | |
279 callback(); | |
280 }); | |
281 }); | |
282 }, function() { | |
283 chrome.test.fail(); | |
284 }); | |
285 } | 242 } |
286 | 243 |
287 /** | 244 /** |
288 * Runs all of the test cases, one by one. | 245 * Runs all of the test cases, one by one. |
289 */ | 246 */ |
290 function runTests() { | 247 function runTests() { |
291 chrome.test.runTests([ | 248 chrome.test.runTests([ |
292 // Tests that returning a too big chunk (4 times larger than the file size, | 249 // Tests that returning a too big chunk (4 times larger than the file size, |
293 // and also much more than requested 1 KB of data). | 250 // and also much more than requested 1 KB of data). |
294 function returnTooLargeChunk() { | 251 function returnTooLargeChunk() { |
295 var onTestSuccess = chrome.test.callbackPass(); | 252 var onTestSuccess = chrome.test.callbackPass(); |
296 fileSystem.root.getFile( | 253 test_util.fileSystem.root.getFile( |
297 TESTING_TOO_LARGE_CHUNK_FILE.name, | 254 TESTING_TOO_LARGE_CHUNK_FILE.name, |
298 {create: false}, | 255 {create: false}, |
299 function(fileEntry) { | 256 function(fileEntry) { |
300 fileEntry.file(function(file) { | 257 fileEntry.file(function(file) { |
301 // Read 1 KB of data. | 258 // Read 1 KB of data. |
302 var fileSlice = file.slice(0, 1024); | 259 var fileSlice = file.slice(0, 1024); |
303 var fileReader = new FileReader(); | 260 var fileReader = new FileReader(); |
304 fileReader.onload = function(e) { | 261 fileReader.onload = function(e) { |
305 chrome.test.fail('Reading should fail.'); | 262 chrome.test.fail('Reading should fail.'); |
306 }; | 263 }; |
307 fileReader.onerror = function(e) { | 264 fileReader.onerror = function(e) { |
308 onTestSuccess(); | 265 onTestSuccess(); |
309 }; | 266 }; |
310 fileReader.readAsText(fileSlice); | 267 fileReader.readAsText(fileSlice); |
311 }, | 268 }, |
312 function(error) { | 269 function(error) { |
313 chrome.test.fail(error.name); | 270 chrome.test.fail(error.name); |
314 }); | 271 }); |
315 }, | 272 }, |
316 function(error) { | 273 function(error) { |
317 chrome.test.fail(error.name); | 274 chrome.test.fail(error.name); |
318 }); | 275 }); |
319 }, | 276 }, |
320 | 277 |
321 // Tests that calling a success callback with a non-existing request id | 278 // Tests that calling a success callback with a non-existing request id |
322 // doesn't cause any harm. | 279 // doesn't cause any harm. |
323 function invalidCallback() { | 280 function invalidCallback() { |
324 var onTestSuccess = chrome.test.callbackPass(); | 281 var onTestSuccess = chrome.test.callbackPass(); |
325 fileSystem.root.getFile( | 282 test_util.fileSystem.root.getFile( |
326 TESTING_INVALID_CALLBACK_FILE.name, | 283 TESTING_INVALID_CALLBACK_FILE.name, |
327 {create: false}, | 284 {create: false}, |
328 function(fileEntry) { | 285 function(fileEntry) { |
329 fileEntry.file(function(file) { | 286 fileEntry.file(function(file) { |
330 // Read 1 KB of data. | 287 // Read 1 KB of data. |
331 var fileSlice = file.slice(0, 1024); | 288 var fileSlice = file.slice(0, 1024); |
332 var fileReader = new FileReader(); | 289 var fileReader = new FileReader(); |
333 fileReader.onload = function(e) { | 290 fileReader.onload = function(e) { |
334 chrome.test.fail('Reading should fail.'); | 291 chrome.test.fail('Reading should fail.'); |
335 }; | 292 }; |
336 fileReader.onerror = function(e) { | 293 fileReader.onerror = function(e) { |
337 onTestSuccess(); | 294 onTestSuccess(); |
338 }; | 295 }; |
339 fileReader.readAsText(fileSlice); | 296 fileReader.readAsText(fileSlice); |
340 }, | 297 }, |
341 function(error) { | 298 function(error) { |
342 chrome.test.fail(error.name); | 299 chrome.test.fail(error.name); |
343 }); | 300 }); |
344 }, | 301 }, |
345 function(error) { | 302 function(error) { |
346 chrome.test.fail(error.name); | 303 chrome.test.fail(error.name); |
347 }); | 304 }); |
348 }, | 305 }, |
349 | 306 |
350 // Test that reading from files with negative size is not allowed. | 307 // Test that reading from files with negative size is not allowed. |
351 function negativeSize() { | 308 function negativeSize() { |
352 var onTestSuccess = chrome.test.callbackPass(); | 309 var onTestSuccess = chrome.test.callbackPass(); |
353 fileSystem.root.getFile( | 310 test_util.fileSystem.root.getFile( |
354 TESTING_NEGATIVE_SIZE_FILE.name, | 311 TESTING_NEGATIVE_SIZE_FILE.name, |
355 {create: false}, | 312 {create: false}, |
356 function(fileEntry) { | 313 function(fileEntry) { |
357 fileEntry.file(function(file) { | 314 fileEntry.file(function(file) { |
358 // Read 1 KB of data. | 315 // Read 1 KB of data. |
359 var fileSlice = file.slice(0, 1024); | 316 var fileSlice = file.slice(0, 1024); |
360 var fileReader = new FileReader(); | 317 var fileReader = new FileReader(); |
361 fileReader.onload = function(e) { | 318 fileReader.onload = function(e) { |
362 var text = fileReader.result; | 319 var text = fileReader.result; |
363 chrome.test.assertEq(0, text.length); | 320 chrome.test.assertEq(0, text.length); |
(...skipping 10 matching lines...) Expand all Loading... |
374 }, | 331 }, |
375 function(error) { | 332 function(error) { |
376 chrome.test.fail(error.name); | 333 chrome.test.fail(error.name); |
377 }); | 334 }); |
378 }, | 335 }, |
379 | 336 |
380 // Tests that URLs generated from a file containing .. inside is properly | 337 // Tests that URLs generated from a file containing .. inside is properly |
381 // escaped. | 338 // escaped. |
382 function relativeName() { | 339 function relativeName() { |
383 var onTestSuccess = chrome.test.callbackPass(); | 340 var onTestSuccess = chrome.test.callbackPass(); |
384 fileSystem.root.getFile( | 341 test_util.fileSystem.root.getFile( |
385 TESTING_RELATIVE_NAME_FILE.name, | 342 TESTING_RELATIVE_NAME_FILE.name, |
386 {create: false}, | 343 {create: false}, |
387 function(fileEntry) { | 344 function(fileEntry) { |
388 chrome.test.fail('Opening a file should fail.'); | 345 chrome.test.fail('Opening a file should fail.'); |
389 }, | 346 }, |
390 function(error) { | 347 function(error) { |
391 onTestSuccess(); | 348 onTestSuccess(); |
392 }); | 349 }); |
393 }, ]); | 350 }, ]); |
394 } | 351 } |
395 | 352 |
396 // Setup and run all of the test cases. | 353 // Setup and run all of the test cases. |
397 setUp(runTests); | 354 setUp(runTests); |
OLD | NEW |