OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 'use strict'; | |
6 | |
7 /** | |
8 * @type {number} | |
9 */ | |
10 var fileSystemId = 0; | |
11 | |
12 /** | |
13 * @type {?DOMFileSystem} | |
14 */ | |
15 var fileSystem = null; | |
16 | |
17 /** | |
18 * Map of opened files, from a <code>openRequestId</code> to <code>filePath | |
19 * </code>. | |
20 * @type {Object.<number, string>} | |
21 */ | |
22 var openedFiles = {}; | |
23 | |
24 /** | |
25 * @type {Object} | |
26 * @const | |
27 */ | |
28 var TESTING_ROOT = Object.freeze({ | |
29 isDirectory: true, | |
30 name: '', | |
31 size: 0, | |
32 modificationTime: new Date(2014, 4, 28, 10, 39, 15) | |
33 }); | |
34 | |
35 /** | |
36 * Testing contents for files. | |
37 * @type {string} | |
38 * @const | |
39 */ | |
40 var TESTING_TEXT = 'I have a basket full of fruits.'; | |
41 | |
42 /** | |
43 * Metadata of a healthy file used to read contents from. | |
44 * @type {Object} | |
45 * @const | |
46 */ | |
47 var TESTING_TIRAMISU_FILE = Object.freeze({ | |
48 isDirectory: false, | |
49 name: 'tiramisu.txt', | |
50 size: TESTING_TEXT.length, | |
51 modificationTime: new Date(2014, 1, 25, 7, 36, 12) | |
52 }); | |
53 | |
54 /** | |
55 * Metadata of a broken file used to read contents from. | |
56 * @type {Object} | |
57 * @const | |
58 */ | |
59 var TESTING_BROKEN_TIRAMISU_FILE = Object.freeze({ | |
60 isDirectory: false, | |
61 name: 'broken-tiramisu.txt', | |
62 size: TESTING_TEXT.length, | |
63 modificationTime: new Date(2014, 1, 25, 7, 36, 12) | |
64 }); | |
65 | |
66 /** | |
67 * Returns entries in the requested directory. | |
68 * | |
69 * @param {number} inFileSystemId ID of the file system. | |
70 * @param {string} directoryPath Path of the directory. | |
71 * @param {function(Array.<Object>, boolean)} onSuccess Success callback with | |
72 * a list of entries. May be called multiple times. | |
73 * @param {function(string)} onError Error callback with an error code. | |
74 */ | |
75 function onReadDirectoryRequested( | |
76 inFileSystemId, directoryPath, onSuccess, onError) { | |
77 if (inFileSystemId != fileSystemId) { | |
78 onError('SECURITY_ERROR'); // enum ProviderError. | |
79 return; | |
80 } | |
81 | |
82 if (directoryPath != '/' + TESTING_HELLO_DIR.name) { | |
83 onError('NOT_FOUND'); // enum ProviderError. | |
84 return; | |
85 } | |
86 | |
87 onSuccess([TESTING_TIRAMISU_FILE], true /* has_next */); | |
88 onSuccess([TESTING_BROKEN_TIRAMISU_FILE], false /* has_next */); | |
hirono
2014/05/16 04:06:47
The comment is wrong?
mtomasz
2014/05/16 06:19:08
Which comment? has_next in the comment is a name o
hirono
2014/05/16 06:23:41
Ah, I misunderstood as it is the meaning of value.
| |
89 } | |
90 | |
91 /** | |
92 * Returns metadata for the requested entry. | |
93 * | |
94 * To successfully acquire a DirectoryEntry, or even a DOMFileSystem, this event | |
95 * must be implemented and return correct values. | |
96 * | |
97 * @param {number} inFileSystemId ID of the file system. | |
98 * @param {string} entryPath Path of the requested entry. | |
99 * @param {function(Object)} onSuccess Success callback with metadata passed | |
100 * an argument. | |
101 * @param {function(string)} onError Error callback with an error code. | |
102 */ | |
103 function onGetMetadataRequested( | |
104 inFileSystemId, entryPath, onSuccess, onError) { | |
105 if (inFileSystemId != fileSystemId) { | |
106 onError('SECURITY_ERROR'); // enum ProviderError. | |
107 return; | |
108 } | |
109 | |
110 if (entryPath == '/') { | |
111 onSuccess(TESTING_ROOT); | |
112 return; | |
113 } | |
114 | |
115 if (entryPath == '/' + TESTING_TIRAMISU_FILE.name) { | |
116 onSuccess(TESTING_TIRAMISU_FILE); | |
117 return; | |
118 } | |
119 | |
120 if (entryPath == '/' + TESTING_BROKEN_TIRAMISU_FILE.name) { | |
121 onSuccess(TESTING_BROKEN_TIRAMISU_FILE); | |
122 return; | |
123 } | |
124 | |
125 onError('NOT_FOUND'); // enum ProviderError. | |
126 } | |
127 | |
128 /** | |
129 * Requests opening a file at <code>filePath</code>. Further file operations | |
130 * will be associated with the <code>requestId</code> | |
131 * | |
132 * @param {number} inFileSystemId ID of the file system. | |
133 * @param {number} requestId ID of the opening request. Used later for reading. | |
134 * @param {string} filePath Path of the file to be opened. | |
135 * @param {string} mode Mode, either reading or writing. | |
136 * @param {boolean} create True to create if doesn't exist. | |
137 * @param {function()} onSuccess Success callback. | |
138 * @param {function(string)} onError Error callback. | |
139 */ | |
140 function onOpenFileRequested( | |
141 inFileSystemId, requestId, filePath, mode, create, onSuccess, onError) { | |
142 if (inFileSystemId != fileSystemId || mode != 'READ' || create) { | |
143 onError('SECURITY_ERROR'); // enum ProviderError. | |
144 return; | |
145 } | |
146 | |
147 if (filePath == '/' + TESTING_TIRAMISU_FILE.name || | |
148 filePath == '/' + TESTING_BROKEN_TIRAMISU_FILE.name) { | |
149 openedFiles[requestId] = filePath; | |
150 onSuccess(); | |
151 } else { | |
152 onError('NOT_FOUND'); // enum ProviderError. | |
153 } | |
154 } | |
155 | |
156 /** | |
157 * Requests closing a file previously opened with <code>openRequestId</code>. | |
158 * | |
159 * @param {number} inFileSystemId ID of the file system. | |
160 * @param {number} openRequestId ID of the request used to open the file. | |
161 * @param {function()} onSuccess Success callback. | |
162 * @param {function(string)} onError Error callback. | |
163 */ | |
164 function onCloseFileRequested( | |
165 inFileSystemId, openRequestId, onSuccess, onError) { | |
166 if (inFileSystemId != fileSystemId || !openedFiles[openRequestId]) { | |
167 onError('SECURITY_ERROR'); // enum ProviderError. | |
168 return; | |
169 } | |
170 | |
171 delete openedFiles[requestId]; | |
172 onSuccess(); | |
173 } | |
174 | |
175 /** | |
176 * Requests reading contents of a file, previously opened with <code> | |
177 * openRequestId</code>. | |
178 * | |
179 * @param {number} inFileSystemId ID of the file system. | |
180 * @param {number} openRequestId ID of the request used to open the file. | |
181 * @param {number} offset Offset of the file. | |
182 * @param {number} length Number of bytes to read. | |
183 * @param {function(string, boolean)} onSuccess Success callback with a chunk | |
184 * of data, and information if more data will be provided later. | |
185 * @param {function(string)} onError Error callback. | |
186 */ | |
187 function onReadFileRequested( | |
188 inFileSystemId, openRequestId, offset, length, onSuccess, onError) { | |
189 var filePath = openedFiles[openRequestId]; | |
190 if (inFileSystemId != fileSystemId || !filePath) { | |
191 onError('SECURITY_ERROR'); // enum ProviderError. | |
192 return; | |
193 } | |
194 | |
195 if (filePath == '/' + TESTING_TIRAMISU_FILE.name) { | |
196 var textToSend = TESTING_TEXT.substr(offset, length); | |
197 var textToSendInChunks = textToSend.split('(?= )'); | |
hirono
2014/05/16 04:06:47
/(?= )/
This one?
mtomasz
2014/05/16 06:19:08
Very good catch. It revealed a bug in the code. Do
| |
198 | |
199 textToSendInChunks.forEach(function(item, index) { | |
200 onSuccess(item, index < textToSendInChunks.length - 1 /* has_next */); | |
201 }); | |
202 return; | |
203 } | |
204 | |
205 if (filePath == '/' + TESTING_BROKEN_TIRAMISU_FILE.name) { | |
206 onError('ACCESS_DENIED'); // enum ProviderError. | |
207 return; | |
208 } | |
209 | |
210 onError('INVALID_OPERATION'); // enum ProviderError. | |
211 } | |
212 | |
213 /** | |
214 * Sets up the tests. Called once per all test cases. In case of a failure, | |
215 * the callback is not called. | |
216 * | |
217 * @param {function()} callback Success callback. | |
218 */ | |
219 function setUp(callback) { | |
220 chrome.fileSystemProvider.mount('chocolate.zip', function(id) { | |
221 fileSystemId = id; | |
222 chrome.fileSystemProvider.onReadDirectoryRequested.addListener( | |
223 onReadDirectoryRequested); | |
224 chrome.fileSystemProvider.onGetMetadataRequested.addListener( | |
225 onGetMetadataRequested); | |
226 chrome.fileSystemProvider.onOpenFileRequested.addListener( | |
227 onOpenFileRequested); | |
228 chrome.fileSystemProvider.onReadFileRequested.addListener( | |
229 onReadFileRequested); | |
230 var volumeId = | |
231 'provided:' + chrome.runtime.id + '-' + fileSystemId + '-user'; | |
232 | |
233 chrome.fileBrowserPrivate.requestFileSystem( | |
234 volumeId, | |
235 function(inFileSystem) { | |
236 chrome.test.assertTrue(!!inFileSystem); | |
237 | |
238 fileSystem = inFileSystem; | |
239 callback(); | |
240 }); | |
241 }, function() { | |
242 chrome.test.fail(); | |
243 }); | |
244 } | |
245 | |
246 /** | |
247 * Runs all of the test cases, one by one. | |
248 */ | |
249 function runTests() { | |
250 chrome.test.runTests([ | |
251 // Read contents of the /tiramisu.txt file. This file exists, so it should | |
252 // succeed. | |
253 function readFileSuccess() { | |
254 var onTestSuccess = chrome.test.callbackPass(function() {}); | |
hirono
2014/05/16 04:06:47
I just noticed we don't need "function() {}".
chro
mtomasz
2014/05/16 06:19:08
Done.
| |
255 fileSystem.root.getFile( | |
256 TESTING_TIRAMISU_FILE.name, | |
257 {create: false}, | |
258 function(fileEntry) { | |
259 fileEntry.file(function(file) { | |
260 var fileReader = new FileReader(); | |
261 fileReader.onload = function(e) { | |
262 var text = fileReader.result; | |
263 chrome.test.assertEq(TESTING_TEXT, text); | |
264 onTestSuccess(); | |
265 }; | |
266 fileReader.onerror = function(e) { | |
267 chrome.test.fail(fileReader.error.name); | |
268 }; | |
269 fileReader.readAsText(file); | |
270 }, | |
271 function(error) { | |
272 chrome.test.fail(error.name); | |
273 }); | |
274 }, | |
275 function(error) { | |
276 chrome.test.fail(error.name); | |
277 }); | |
278 }, | |
279 // Read contents of a file file, but with an error on the way. This should | |
280 // result in an error. | |
281 function readEntriesError() { | |
282 var onTestSuccess = chrome.test.callbackPass(function() {}); | |
283 fileSystem.root.getFile( | |
284 TESTING_BROKEN_TIRAMISU_FILE.name, | |
285 {create: false}, | |
286 function(fileEntry) { | |
287 fileEntry.file(function(file) { | |
288 var fileReader = new FileReader(); | |
289 fileReader.onload = function(e) { | |
290 chrome.test.fail(); | |
291 }; | |
292 fileReader.onerror = function(e) { | |
293 chrome.test.assertEq('NotReadableError', fileReader.error.name); | |
294 onTestSuccess(); | |
295 }; | |
296 fileReader.readAsText(file); | |
297 }, | |
298 function(error) { | |
299 chrome.test.fail(); | |
300 }); | |
301 }, | |
302 function(error) { | |
303 chrome.test.fail(error.name); | |
304 }); | |
305 } | |
306 ]); | |
307 } | |
308 | |
309 // Setup and run all of the test cases. | |
310 setUp(runTests); | |
OLD | NEW |