| 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 |