OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 // downloads api test | |
6 // browser_tests.exe --gtest_filter=DownloadsApiTest.Downloads | |
7 | |
8 // Comment this out to enable debugging. | |
9 console.debug = function() {}; | |
10 | |
11 function debugObject(obj) { | |
12 for (var property in obj) { | |
13 console.debug(property + ': ' + obj[property]); | |
14 } | |
15 } | |
16 | |
17 var downloads = chrome.experimental.downloads; | |
18 window.requestFileSystem = (window.requestFileSystem || | |
19 window.webkitRequestFileSystem); | |
20 window.BlobBuilder = (window.BlobBuilder || | |
21 window.WebKitBlobBuilder); | |
22 | |
23 chrome.test.getConfig(function(testConfig) { | |
24 function getURL(path) { | |
25 return 'http://localhost:' + testConfig.testServer.port + '/' + path; | |
26 } | |
27 | |
28 var nextId = 0; | |
29 function getNextId() { | |
30 return nextId++; | |
31 } | |
32 | |
33 // There can be only one assertThrows per test function. This should be | |
34 // called as follows: | |
35 // | |
36 // assertThrows(exceptionMessage, function, [arg1, [arg2, ... ]]) | |
37 // | |
38 // ... where |exceptionMessage| is the expected exception message. | |
39 // |arg1|, |arg2|, etc.. are arguments to |function|. | |
40 function assertThrows(exceptionMessage, func) { | |
41 var args = Array.prototype.slice.call(arguments, 2); | |
42 try { | |
43 args.push(function() { | |
44 // Don't use chrome.test.callbackFail because it requires the | |
45 // callback to be called. | |
46 chrome.test.fail('Failed to throw exception (' + | |
47 exceptionMessage + ')'); | |
48 }); | |
49 func.apply(null, args); | |
50 } catch (exception) { | |
51 chrome.test.assertEq(exceptionMessage, exception.message); | |
52 chrome.test.succeed(); | |
53 } | |
54 } | |
55 | |
56 // The "/slow" handler waits a specified amount of time before returning a | |
57 // safe file. Specify zero seconds to return quickly. | |
58 var SAFE_FAST_URL = getURL('slow?0'); | |
59 | |
60 var NEVER_FINISH_URL = getURL('download-known-size'); | |
61 | |
62 // This URL should only work with the POST method and a request body | |
63 // containing 'BODY'. | |
64 var POST_URL = getURL('files/post/downloads/a_zip_file.zip?' + | |
65 'expected_body=BODY'); | |
66 | |
67 // This URL should only work with headers 'Foo: bar' and 'Qx: yo'. | |
68 var HEADERS_URL = getURL('files/downloads/a_zip_file.zip?' + | |
69 'expected_headers=Foo:bar&expected_headers=Qx:yo'); | |
70 | |
71 // A simple handler that requires http auth basic. | |
72 var AUTH_BASIC_URL = getURL('auth-basic'); | |
73 | |
74 // This is just base64 of 'username:secret'. | |
75 var AUTHORIZATION = 'dXNlcm5hbWU6c2VjcmV0'; | |
76 | |
77 chrome.test.runTests([ | |
78 // TODO(benjhayden): Test onErased using remove(). | |
79 | |
80 // TODO(benjhayden): Sub-directories depend on http://crbug.com/109443 | |
81 // TODO(benjhayden): Windows slashes. | |
82 // function downloadSubDirectoryFilename() { | |
83 // var downloadId = getNextId(); | |
84 // var callbackCompleted = chrome.test.callbackAdded(); | |
85 // function myListener(delta) { | |
86 // if ((delta.id != downloadId) || | |
87 // !delta.filename || | |
88 // (delta.filename.new.indexOf('/foo/slow') == -1)) | |
89 // return; | |
90 // downloads.onChanged.removeListener(myListener); | |
91 // callbackCompleted(); | |
92 // } | |
93 // downloads.onChanged.addListener(myListener); | |
94 // downloads.download( | |
95 // {'url': SAFE_FAST_URL, 'filename': 'foo/slow'}, | |
96 // chrome.test.callback(function(id) { | |
97 // chrome.test.assertEq(downloadId, id); | |
98 // })); | |
99 // }, | |
100 | |
101 function downloadBlob() { | |
102 // Test that we can begin a download for a blob. | |
103 var downloadId = getNextId(); | |
104 console.debug(downloadId); | |
105 function getBlobURL(data, filename, callback) { | |
106 var dirname = '' + Math.random(); | |
107 function fileSystemError(operation, data) { | |
108 return function(fileError) { | |
109 callback(null, {operation: operation, | |
110 data: data, | |
111 code: fileError.code}); | |
112 } | |
113 } | |
114 window.requestFileSystem(TEMPORARY, 5*1024*1024, function(fs) { | |
115 fs.root.getDirectory(dirname, {create: true, exclusive: true}, | |
116 function(dirEntry) { | |
117 dirEntry.getFile(filename, {create: true, exclusive: true}, | |
118 function(fileEntry) { | |
119 fileEntry.createWriter(function(fileWriter) { | |
120 fileWriter.onwriteend = function(e) { | |
121 callback(fileEntry.toURL(), null); | |
122 }; | |
123 fileWriter.onerror = function(e) { | |
124 callback(null, ('Write failed: ' + e.toString())); | |
125 }; | |
126 var bb = new window.BlobBuilder(); | |
127 bb.append(data); | |
128 fileWriter.write(bb.getBlob()); | |
129 }, fileSystemError('createWriter')); | |
130 }, fileSystemError('getFile', filename)); | |
131 }, fileSystemError('getDirectory', dirname)); | |
132 }, fileSystemError('requestFileSystem')); | |
133 } | |
134 | |
135 getBlobURL('Lorem ipsum', downloadId + '.txt', | |
136 chrome.test.callback(function(blobUrl, blobError) { | |
137 if (blobError) | |
138 throw blobError; | |
139 console.debug(blobUrl); | |
140 downloads.download( | |
141 {'url': blobUrl}, | |
142 chrome.test.callback(function(id) { | |
143 console.debug(id); | |
144 chrome.test.assertEq(downloadId, id); | |
145 })); | |
146 })); | |
147 }, | |
148 | |
149 function downloadSimple() { | |
150 // Test that we can begin a download. | |
151 var downloadId = getNextId(); | |
152 console.debug(downloadId); | |
153 downloads.download( | |
154 {'url': SAFE_FAST_URL}, | |
155 chrome.test.callback(function(id) { | |
156 chrome.test.assertEq(downloadId, id); | |
157 })); | |
158 }, | |
159 | |
160 function downloadOnChanged() { | |
161 // Test that download completion is detectable by an onChanged event | |
162 // listener. | |
163 var downloadId = getNextId(); | |
164 console.debug(downloadId); | |
165 var callbackCompleted = chrome.test.callbackAdded(); | |
166 function myListener(delta) { | |
167 console.debug(delta.id); | |
168 if ((delta.id != downloadId) || | |
169 !delta.state) | |
170 return; | |
171 chrome.test.assertEq(downloads.STATE_COMPLETE, delta.state.new); | |
172 console.debug(downloadId); | |
173 downloads.onChanged.removeListener(myListener); | |
174 callbackCompleted(); | |
175 } | |
176 downloads.onChanged.addListener(myListener); | |
177 downloads.download( | |
178 {"url": SAFE_FAST_URL}, | |
179 chrome.test.callback(function(id) { | |
180 console.debug(downloadId); | |
181 chrome.test.assertEq(downloadId, id); | |
182 })); | |
183 }, | |
184 | |
185 function downloadAuthBasicFail() { | |
186 var downloadId = getNextId(); | |
187 console.debug(downloadId); | |
188 | |
189 var changedCompleted = chrome.test.callbackAdded(); | |
190 function changedListener(delta) { | |
191 console.debug(delta.id); | |
192 // Ignore onChanged events for downloads besides our own, or events that | |
193 // signal any change besides completion. | |
194 if ((delta.id != downloadId) || | |
195 !delta.state || | |
196 !delta.error) | |
197 return; | |
198 console.debug(downloadId); | |
199 chrome.test.assertEq(downloads.STATE_INTERRUPTED, delta.state.new); | |
200 chrome.test.assertEq(30, delta.error.new); | |
201 downloads.onChanged.removeListener(changedListener); | |
202 if (changedCompleted) { | |
203 changedCompleted(); | |
204 changedCompleted = null; | |
205 } | |
206 } | |
207 downloads.onChanged.addListener(changedListener); | |
208 | |
209 // Sometimes the DownloadsEventRouter detects the item for the first time | |
210 // after the item has already been interrupted. In this case, the | |
211 // onChanged event never fires, so run the changedListener manually. If | |
212 // the DownloadsEventRouter detects the item before it's interrupted, then | |
213 // the onChanged event should fire correctly. | |
214 var createdCompleted = chrome.test.callbackAdded(); | |
215 function createdListener(createdItem) { | |
216 console.debug(createdItem.id); | |
217 // Ignore events for any download besides our own. | |
218 if (createdItem.id != downloadId) | |
219 return; | |
220 console.debug(downloadId); | |
221 downloads.onCreated.removeListener(createdListener); | |
222 createdCompleted(); | |
223 if (createdItem.state == downloads.STATE_INTERRUPTED) { | |
224 changedListener({id: downloadId, state: {new: createdItem.state}, | |
225 error: {new: createdItem.error}}); | |
226 } | |
227 } | |
228 downloads.onCreated.addListener(createdListener); | |
229 | |
230 downloads.download( | |
231 {'url': AUTH_BASIC_URL, | |
232 'filename': downloadId + '.txt'}, | |
233 chrome.test.callback(function(id) { | |
234 console.debug(downloadId); | |
235 chrome.test.assertEq(downloadId, id); | |
236 })); | |
237 }, | |
238 | |
239 function downloadAuthBasicSucceed() { | |
240 var downloadId = getNextId(); | |
241 console.debug(downloadId); | |
242 | |
243 var changedCompleted = chrome.test.callbackAdded(); | |
244 function changedListener(delta) { | |
245 console.debug(delta.id); | |
246 // Ignore onChanged events for downloads besides our own, or events that | |
247 // signal any change besides completion. | |
248 if ((delta.id != downloadId) || | |
249 !delta.state) | |
250 return; | |
251 chrome.test.assertEq(downloads.STATE_COMPLETE, delta.state.new); | |
252 console.debug(downloadId); | |
253 downloads.onChanged.removeListener(changedListener); | |
254 changedCompleted(); | |
255 } | |
256 downloads.onChanged.addListener(changedListener); | |
257 | |
258 downloads.download( | |
259 {'url': AUTH_BASIC_URL, | |
260 'headers': [{'name': 'Authorization', | |
261 'value': 'Basic ' + AUTHORIZATION}], | |
262 'filename': downloadId + '.txt'}, | |
263 chrome.test.callback(function(id) { | |
264 console.debug(downloadId); | |
265 chrome.test.assertEq(downloadId, id); | |
266 })); | |
267 }, | |
268 | |
269 function downloadPostSuccess() { | |
270 // Test the |method| download option. | |
271 var downloadId = getNextId(); | |
272 console.debug(downloadId); | |
273 var changedCompleted = chrome.test.callbackAdded(); | |
274 function changedListener(delta) { | |
275 console.debug(delta.id); | |
276 // Ignore onChanged events for downloads besides our own, or events that | |
277 // signal any change besides completion. | |
278 if ((delta.id != downloadId) || | |
279 !delta.state) | |
280 return; | |
281 chrome.test.assertEq(downloads.STATE_COMPLETE, delta.state.new); | |
282 console.debug(downloadId); | |
283 downloads.search({id: downloadId}, | |
284 chrome.test.callback(function(items) { | |
285 console.debug(downloadId); | |
286 chrome.test.assertEq(1, items.length); | |
287 chrome.test.assertEq(downloadId, items[0].id); | |
288 debugObject(items[0]); | |
289 var EXPECTED_SIZE = 164; | |
290 chrome.test.assertEq(EXPECTED_SIZE, items[0].bytesReceived); | |
291 })); | |
292 downloads.onChanged.removeListener(changedListener); | |
293 changedCompleted(); | |
294 } | |
295 downloads.onChanged.addListener(changedListener); | |
296 | |
297 downloads.download( | |
298 {'url': POST_URL, | |
299 'method': 'POST', | |
300 'filename': downloadId + '.txt', | |
301 'body': 'BODY'}, | |
302 chrome.test.callback(function(id) { | |
303 console.debug(downloadId); | |
304 chrome.test.assertEq(downloadId, id); | |
305 })); | |
306 }, | |
307 | |
308 function downloadPostWouldFailWithoutMethod() { | |
309 // Test that downloadPostSuccess would fail if the resource requires the | |
310 // POST method, and chrome fails to propagate the |method| parameter back | |
311 // to the server. This tests both that testserver.py does not succeed when | |
312 // it should fail, and this tests how the downloads extension api exposes | |
313 // the failure to extensions. | |
314 var downloadId = getNextId(); | |
315 console.debug(downloadId); | |
316 | |
317 var changedCompleted = chrome.test.callbackAdded(); | |
318 function changedListener(delta) { | |
319 console.debug(delta.id); | |
320 // Ignore onChanged events for downloads besides our own, or events that | |
321 // signal any change besides interruption. | |
322 if ((delta.id != downloadId) || | |
323 !delta.state || | |
324 !delta.error) | |
325 return; | |
326 chrome.test.assertEq(downloads.STATE_INTERRUPTED, delta.state.new); | |
327 chrome.test.assertEq(33, delta.error.new); | |
328 console.debug(downloadId); | |
329 downloads.onChanged.removeListener(changedListener); | |
330 if (changedCompleted) { | |
331 changedCompleted(); | |
332 changedCompleted = null; | |
333 } | |
334 } | |
335 downloads.onChanged.addListener(changedListener); | |
336 | |
337 // Sometimes the DownloadsEventRouter detects the item for the first time | |
338 // after the item has already been interrupted. In this case, the | |
339 // onChanged event never fires, so run the changedListener manually. If | |
340 // the DownloadsEventRouter detects the item before it's interrupted, then | |
341 // the onChanged event should fire correctly. | |
342 var createdCompleted = chrome.test.callbackAdded(); | |
343 function createdListener(createdItem) { | |
344 console.debug(createdItem.id); | |
345 // Ignore events for any download besides our own. | |
346 if (createdItem.id != downloadId) | |
347 return; | |
348 console.debug(downloadId); | |
349 downloads.onCreated.removeListener(createdListener); | |
350 createdCompleted(); | |
351 if (createdItem.state == downloads.STATE_INTERRUPTED) { | |
352 changedListener({id: downloadId, state: {new: createdItem.state}, | |
353 error: {new: createdItem.error}}); | |
354 } | |
355 } | |
356 downloads.onCreated.addListener(createdListener); | |
357 | |
358 downloads.download( | |
359 {'url': POST_URL, | |
360 'filename': downloadId + '.txt', // Prevent 'file' danger. | |
361 'body': 'BODY'}, | |
362 chrome.test.callback(function(id) { | |
363 console.debug(downloadId); | |
364 chrome.test.assertEq(downloadId, id); | |
365 })); | |
366 }, | |
367 | |
368 function downloadPostWouldFailWithoutBody() { | |
369 // Test that downloadPostSuccess would fail if the resource requires the | |
370 // POST method and a request body, and chrome fails to propagate the | |
371 // |body| parameter back to the server. This tests both that testserver.py | |
372 // does not succeed when it should fail, and this tests how the downloads | |
373 // extension api exposes the failure to extensions. | |
374 var downloadId = getNextId(); | |
375 console.debug(downloadId); | |
376 | |
377 var changedCompleted = chrome.test.callbackAdded(); | |
378 function changedListener(delta) { | |
379 console.debug(delta.id); | |
380 // Ignore onChanged events for downloads besides our own, or events that | |
381 // signal any change besides interruption. | |
382 if ((delta.id != downloadId) || | |
383 !delta.state || | |
384 !delta.error) | |
385 return; | |
386 chrome.test.assertEq(downloads.STATE_INTERRUPTED, delta.state.new); | |
387 chrome.test.assertEq(33, delta.error.new); | |
388 if (delta.error) console.debug(delta.error.new); | |
389 console.debug(downloadId); | |
390 downloads.onChanged.removeListener(changedListener); | |
391 if (changedCompleted) { | |
392 changedCompleted(); | |
393 changedCompleted = null; | |
394 } | |
395 } | |
396 downloads.onChanged.addListener(changedListener); | |
397 | |
398 // Sometimes the DownloadsEventRouter detects the item for the first time | |
399 // after the item has already been interrupted. In this case, the | |
400 // onChanged event never fires, so run the changedListener manually. If | |
401 // the DownloadsEventRouter detects the item before it's interrupted, then | |
402 // the onChanged event should fire correctly. | |
403 var createdCompleted = chrome.test.callbackAdded(); | |
404 function createdListener(createdItem) { | |
405 console.debug(createdItem.id); | |
406 // Ignore events for any download besides our own. | |
407 if (createdItem.id != downloadId) | |
408 return; | |
409 console.debug(downloadId); | |
410 downloads.onCreated.removeListener(createdListener); | |
411 createdCompleted(); | |
412 if (createdItem.state == downloads.STATE_INTERRUPTED) { | |
413 changedListener({id: downloadId, state: {new: createdItem.state}, | |
414 error: {new: createdItem.error}}); | |
415 } | |
416 } | |
417 downloads.onCreated.addListener(createdListener); | |
418 | |
419 downloads.download( | |
420 {'url': POST_URL, | |
421 'filename': downloadId + '.txt', // Prevent 'file' danger. | |
422 'method': 'POST'}, | |
423 chrome.test.callback(function(id) { | |
424 console.debug(downloadId); | |
425 chrome.test.assertEq(downloadId, id); | |
426 })); | |
427 }, | |
428 | |
429 function downloadHeadersSuccess() { | |
430 // Test the |header| download option. | |
431 var downloadId = getNextId(); | |
432 console.debug(downloadId); | |
433 var changedCompleted = chrome.test.callbackAdded(); | |
434 function changedListener(delta) { | |
435 console.debug(delta.id); | |
436 // Ignore onChanged events for downloads besides our own, or events that | |
437 // signal any change besides completion. | |
438 if ((delta.id != downloadId) || | |
439 !delta.state) | |
440 return; | |
441 chrome.test.assertEq(downloads.STATE_COMPLETE, delta.state.new); | |
442 console.debug(downloadId); | |
443 downloads.search({id: downloadId}, | |
444 chrome.test.callback(function(items) { | |
445 console.debug(downloadId); | |
446 chrome.test.assertEq(1, items.length); | |
447 chrome.test.assertEq(downloadId, items[0].id); | |
448 debugObject(items[0]); | |
449 var EXPECTED_SIZE = 164; | |
450 chrome.test.assertEq(EXPECTED_SIZE, items[0].bytesReceived); | |
451 })); | |
452 downloads.onChanged.removeListener(changedListener); | |
453 changedCompleted(); | |
454 } | |
455 downloads.onChanged.addListener(changedListener); | |
456 | |
457 downloads.download( | |
458 {'url': HEADERS_URL, | |
459 'filename': downloadId + '.txt', // Prevent 'file' danger. | |
460 'headers': [{'name': 'Foo', 'value': 'bar'}, | |
461 {'name': 'Qx', 'value': 'yo'}]}, | |
462 chrome.test.callback(function(id) { | |
463 console.debug(downloadId); | |
464 chrome.test.assertEq(downloadId, id); | |
465 })); | |
466 }, | |
467 | |
468 function downloadHeadersBinarySuccess() { | |
469 // Test the |header| download option. | |
470 var downloadId = getNextId(); | |
471 console.debug(downloadId); | |
472 var changedCompleted = chrome.test.callbackAdded(); | |
473 function changedListener(delta) { | |
474 console.debug(delta.id); | |
475 // Ignore onChanged events for downloads besides our own, or events that | |
476 // signal any change besides completion. | |
477 if ((delta.id != downloadId) || | |
478 !delta.state) | |
479 return; | |
480 chrome.test.assertEq(downloads.STATE_COMPLETE, delta.state.new); | |
481 console.debug(downloadId); | |
482 downloads.search({id: downloadId}, | |
483 chrome.test.callback(function(items) { | |
484 console.debug(downloadId); | |
485 chrome.test.assertEq(1, items.length); | |
486 chrome.test.assertEq(downloadId, items[0].id); | |
487 debugObject(items[0]); | |
488 var EXPECTED_SIZE = 164; | |
489 chrome.test.assertEq(EXPECTED_SIZE, items[0].bytesReceived); | |
490 })); | |
491 downloads.onChanged.removeListener(changedListener); | |
492 changedCompleted(); | |
493 } | |
494 downloads.onChanged.addListener(changedListener); | |
495 | |
496 downloads.download( | |
497 {'url': HEADERS_URL, | |
498 'filename': downloadId + '.txt', // Prevent 'file' danger. | |
499 'headers': [{'name': 'Foo', 'binaryValue': [98, 97, 114]}, | |
500 {'name': 'Qx', 'binaryValue': [121, 111]}]}, | |
501 chrome.test.callback(function(id) { | |
502 console.debug(downloadId); | |
503 chrome.test.assertEq(downloadId, id); | |
504 })); | |
505 }, | |
506 | |
507 function downloadHeadersWouldFail() { | |
508 // Test that downloadHeadersSuccess() would fail if the resource requires | |
509 // the headers, and chrome fails to propagate them back to the server. | |
510 // This tests both that testserver.py does not succeed when it should | |
511 // fail as well as how the downloads extension api exposes the | |
512 // failure to extensions. | |
513 var downloadId = getNextId(); | |
514 console.debug(downloadId); | |
515 | |
516 var changedCompleted = chrome.test.callbackAdded(); | |
517 function changedListener(delta) { | |
518 console.debug(delta.id); | |
519 // Ignore onChanged events for downloads besides our own, or events that | |
520 // signal any change besides interruption. | |
521 if ((delta.id != downloadId) || | |
522 !delta.state || | |
523 !delta.error) | |
524 return; | |
525 chrome.test.assertEq(downloads.STATE_INTERRUPTED, delta.state.new); | |
526 chrome.test.assertEq(33, delta.error.new); | |
527 console.debug(downloadId); | |
528 downloads.onChanged.removeListener(changedListener); | |
529 if (changedCompleted) { | |
530 changedCompleted(); | |
531 changedCompleted = null; | |
532 } | |
533 } | |
534 downloads.onChanged.addListener(changedListener); | |
535 | |
536 // Sometimes the DownloadsEventRouter detects the item for the first time | |
537 // after the item has already been interrupted. In this case, the | |
538 // onChanged event never fires, so run the changedListener manually. If | |
539 // the DownloadsEventRouter detects the item before it's interrupted, then | |
540 // the onChanged event should fire correctly. | |
541 var createdCompleted = chrome.test.callbackAdded(); | |
542 function createdListener(createdItem) { | |
543 console.debug(createdItem.id); | |
544 // Ignore events for any download besides our own. | |
545 if (createdItem.id != downloadId) | |
546 return; | |
547 console.debug(downloadId); | |
548 downloads.onCreated.removeListener(createdListener); | |
549 createdCompleted(); | |
550 if (createdItem.state == downloads.STATE_INTERRUPTED) { | |
551 changedListener({id: downloadId, state: {new: createdItem.state}, | |
552 error: {new: createdItem.error}}); | |
553 } | |
554 } | |
555 downloads.onCreated.addListener(createdListener); | |
556 | |
557 downloads.download( | |
558 {'url': HEADERS_URL}, | |
559 chrome.test.callback(function(id) { | |
560 console.debug(downloadId); | |
561 chrome.test.assertEq(downloadId, id); | |
562 })); | |
563 }, | |
564 | |
565 function downloadHeadersInvalid0() { | |
566 // Test that we disallow certain headers case-insensitive. | |
567 downloads.download( | |
568 {'url': SAFE_FAST_URL, | |
569 'headers': [{'name': 'Accept-chArsEt', 'value': 'evil'}]}, | |
570 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
571 }, | |
572 | |
573 function downloadHeadersInvalid1() { | |
574 // Test that we disallow certain headers. | |
575 downloads.download( | |
576 {'url': SAFE_FAST_URL, | |
577 'headers': [{'name': 'accept-eNcoding', 'value': 'evil'}]}, | |
578 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
579 }, | |
580 | |
581 function downloadHeadersInvalid2() { | |
582 // Test that we disallow certain headers. | |
583 downloads.download( | |
584 {'url': SAFE_FAST_URL, | |
585 'headers': [{'name': 'coNNection', 'value': 'evil'}]}, | |
586 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
587 }, | |
588 | |
589 function downloadHeadersInvalid3() { | |
590 // Test that we disallow certain headers. | |
591 downloads.download( | |
592 {'url': SAFE_FAST_URL, | |
593 'headers': [{'name': 'coNteNt-leNgth', 'value': 'evil'}]}, | |
594 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
595 }, | |
596 | |
597 function downloadHeadersInvalid4() { | |
598 // Test that we disallow certain headers. | |
599 downloads.download( | |
600 {'url': SAFE_FAST_URL, | |
601 'headers': [{'name': 'cooKIE', 'value': 'evil'}]}, | |
602 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
603 }, | |
604 | |
605 function downloadHeadersInvalid5() { | |
606 // Test that we disallow certain headers. | |
607 downloads.download( | |
608 {'url': SAFE_FAST_URL, | |
609 'headers': [{'name': 'cOOkie2', 'value': 'evil'}]}, | |
610 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
611 }, | |
612 | |
613 function downloadHeadersInvalid6() { | |
614 // Test that we disallow certain headers. | |
615 downloads.download( | |
616 {'url': SAFE_FAST_URL, | |
617 'headers': [{'name': 'coNteNt-traNsfer-eNcodiNg', 'value': 'evil'}]}, | |
618 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
619 }, | |
620 | |
621 function downloadHeadersInvalid7() { | |
622 // Test that we disallow certain headers. | |
623 downloads.download( | |
624 {'url': SAFE_FAST_URL, | |
625 'headers': [{'name': 'dAtE', 'value': 'evil'}]}, | |
626 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
627 }, | |
628 | |
629 function downloadHeadersInvalid8() { | |
630 // Test that we disallow certain headers. | |
631 downloads.download( | |
632 {'url': SAFE_FAST_URL, | |
633 'headers': [{'name': 'ExpEcT', 'value': 'evil'}]}, | |
634 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
635 }, | |
636 | |
637 function downloadHeadersInvalid9() { | |
638 // Test that we disallow certain headers. | |
639 downloads.download( | |
640 {'url': SAFE_FAST_URL, | |
641 'headers': [{'name': 'hOsT', 'value': 'evil'}]}, | |
642 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
643 }, | |
644 | |
645 function downloadHeadersInvalid10() { | |
646 // Test that we disallow certain headers. | |
647 downloads.download( | |
648 {'url': SAFE_FAST_URL, | |
649 'headers': [{'name': 'kEEp-aLivE', 'value': 'evil'}]}, | |
650 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
651 }, | |
652 | |
653 function downloadHeadersInvalid11() { | |
654 // Test that we disallow certain headers. | |
655 downloads.download( | |
656 {'url': SAFE_FAST_URL, | |
657 'headers': [{'name': 'rEfErEr', 'value': 'evil'}]}, | |
658 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
659 }, | |
660 | |
661 function downloadHeadersInvalid12() { | |
662 // Test that we disallow certain headers. | |
663 downloads.download( | |
664 {'url': SAFE_FAST_URL, | |
665 'headers': [{'name': 'tE', 'value': 'evil'}]}, | |
666 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
667 }, | |
668 | |
669 function downloadHeadersInvalid13() { | |
670 // Test that we disallow certain headers. | |
671 downloads.download( | |
672 {'url': SAFE_FAST_URL, | |
673 'headers': [{'name': 'trAilER', 'value': 'evil'}]}, | |
674 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
675 }, | |
676 | |
677 function downloadHeadersInvalid14() { | |
678 // Test that we disallow certain headers. | |
679 downloads.download( | |
680 {'url': SAFE_FAST_URL, | |
681 'headers': [{'name': 'trANsfer-eNcodiNg', 'value': 'evil'}]}, | |
682 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
683 }, | |
684 | |
685 function downloadHeadersInvalid15() { | |
686 // Test that we disallow certain headers. | |
687 downloads.download( | |
688 {'url': SAFE_FAST_URL, | |
689 'headers': [{'name': 'upGRAde', 'value': 'evil'}]}, | |
690 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
691 }, | |
692 | |
693 function downloadHeadersInvalid16() { | |
694 // Test that we disallow certain headers. | |
695 downloads.download( | |
696 {'url': SAFE_FAST_URL, | |
697 'headers': [{'name': 'usER-agENt', 'value': 'evil'}]}, | |
698 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
699 }, | |
700 | |
701 function downloadHeadersInvalid17() { | |
702 // Test that we disallow certain headers. | |
703 downloads.download( | |
704 {'url': SAFE_FAST_URL, | |
705 'headers': [{'name': 'viA', 'value': 'evil'}]}, | |
706 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
707 }, | |
708 | |
709 function downloadHeadersInvalid18() { | |
710 // Test that we disallow certain headers. | |
711 downloads.download( | |
712 {'url': SAFE_FAST_URL, | |
713 'headers': [{'name': 'pRoxY-', 'value': 'evil'}]}, | |
714 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
715 }, | |
716 | |
717 function downloadHeadersInvalid19() { | |
718 // Test that we disallow certain headers. | |
719 downloads.download( | |
720 {'url': SAFE_FAST_URL, | |
721 'headers': [{'name': 'sEc-', 'value': 'evil'}]}, | |
722 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
723 }, | |
724 | |
725 function downloadHeadersInvalid20() { | |
726 // Test that we disallow certain headers. | |
727 downloads.download( | |
728 {'url': SAFE_FAST_URL, | |
729 'headers': [{'name': 'pRoxY-probably-not-evil', 'value': 'evil'}]}, | |
730 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
731 }, | |
732 | |
733 function downloadHeadersInvalid21() { | |
734 // Test that we disallow certain headers. | |
735 downloads.download( | |
736 {'url': SAFE_FAST_URL, | |
737 'headers': [{'name': 'sEc-probably-not-evil', 'value': 'evil'}]}, | |
738 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
739 }, | |
740 | |
741 function downloadHeadersInvalid22() { | |
742 // Test that we disallow certain headers. | |
743 downloads.download( | |
744 {'url': SAFE_FAST_URL, | |
745 'headers': [{'name': 'oRiGiN', 'value': 'evil'}]}, | |
746 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
747 }, | |
748 | |
749 function downloadHeadersInvalid23() { | |
750 // Test that we disallow certain headers. | |
751 downloads.download( | |
752 {'url': SAFE_FAST_URL, | |
753 'headers': [{'name': 'Access-Control-Request-Headers', | |
754 'value': 'evil'}]}, | |
755 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
756 }, | |
757 | |
758 function downloadHeadersInvalid24() { | |
759 // Test that we disallow certain headers. | |
760 downloads.download( | |
761 {'url': SAFE_FAST_URL, | |
762 'headers': [{'name': 'Access-Control-Request-Method', | |
763 'value': 'evil'}]}, | |
764 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
765 }, | |
766 | |
767 function downloadInterrupted() { | |
768 // Test that cancel()ing an in-progress download causes its state to | |
769 // transition to interrupted, and test that that state transition is | |
770 // detectable by an onChanged event listener. | |
771 // TODO(benjhayden): Test other sources of interruptions such as server | |
772 // death. | |
773 var downloadId = getNextId(); | |
774 console.debug(downloadId); | |
775 | |
776 var createdCompleted = chrome.test.callbackAdded(); | |
777 function createdListener(createdItem) { | |
778 console.debug(createdItem.id); | |
779 // Ignore onCreated events for any download besides our own. | |
780 if (createdItem.id != downloadId) | |
781 return; | |
782 console.debug(downloadId); | |
783 // TODO(benjhayden) Move this cancel() into the download() callback | |
784 // after ensuring that DownloadItems are created before that callback | |
785 // is fired. | |
786 downloads.cancel(downloadId, chrome.test.callback(function() { | |
787 console.debug(downloadId); | |
788 })); | |
789 downloads.onCreated.removeListener(createdListener); | |
790 createdCompleted(); | |
791 } | |
792 downloads.onCreated.addListener(createdListener); | |
793 | |
794 var changedCompleted = chrome.test.callbackAdded(); | |
795 function changedListener(delta) { | |
796 console.debug(delta.id); | |
797 // Ignore onChanged events for downloads besides our own, or events that | |
798 // signal any change besides interruption. | |
799 if ((delta.id != downloadId) || | |
800 !delta.state || | |
801 !delta.error) | |
802 return; | |
803 chrome.test.assertEq(downloads.STATE_INTERRUPTED, delta.state.new); | |
804 chrome.test.assertEq(40, delta.error.new); | |
805 console.debug(downloadId); | |
806 downloads.onChanged.removeListener(changedListener); | |
807 changedCompleted(); | |
808 } | |
809 downloads.onChanged.addListener(changedListener); | |
810 | |
811 downloads.download( | |
812 {'url': NEVER_FINISH_URL}, | |
813 chrome.test.callback(function(id) { | |
814 console.debug(downloadId); | |
815 chrome.test.assertEq(downloadId, id); | |
816 })); | |
817 }, | |
818 | |
819 function downloadFilename() { | |
820 // Test that we can suggest a filename for a new download, and test that | |
821 // we can detect filename changes with an onChanged event listener. | |
822 var FILENAME = 'owiejtoiwjrfoiwjroiwjroiwjroiwjrfi'; | |
823 var downloadId = getNextId(); | |
824 console.debug(downloadId); | |
825 var callbackCompleted = chrome.test.callbackAdded(); | |
826 function myListener(delta) { | |
827 console.debug(delta.id); | |
828 if ((delta.id != downloadId) || | |
829 !delta.filename || | |
830 (delta.filename.new.indexOf(FILENAME) == -1)) | |
831 return; | |
832 console.debug(downloadId); | |
833 downloads.onChanged.removeListener(myListener); | |
834 callbackCompleted(); | |
835 } | |
836 downloads.onChanged.addListener(myListener); | |
837 downloads.download( | |
838 {'url': SAFE_FAST_URL, 'filename': FILENAME}, | |
839 chrome.test.callback(function(id) { | |
840 console.debug(downloadId); | |
841 chrome.test.assertEq(downloadId, id); | |
842 })); | |
843 }, | |
844 | |
845 // TODO(benjhayden): Update this test when downloading to sub-directories is | |
846 // supported. | |
847 function downloadFilenameDisallowSlashes() { | |
848 downloads.download( | |
849 {'url': SAFE_FAST_URL, 'filename': 'subdirectory/file.txt'}, | |
850 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
851 }, | |
852 | |
853 function downloadOnCreated() { | |
854 // Test that the onCreated event fires when we start a download. | |
855 var downloadId = getNextId(); | |
856 console.debug(downloadId); | |
857 var createdCompleted = chrome.test.callbackAdded(); | |
858 function createdListener(item) { | |
859 console.debug(item.id); | |
860 if (item.id != downloadId) | |
861 return; | |
862 console.debug(downloadId); | |
863 createdCompleted(); | |
864 downloads.onCreated.removeListener(createdListener); | |
865 }; | |
866 downloads.onCreated.addListener(createdListener); | |
867 downloads.download( | |
868 {'url': SAFE_FAST_URL}, | |
869 chrome.test.callback(function(id) { | |
870 console.debug(downloadId); | |
871 chrome.test.assertEq(downloadId, id); | |
872 })); | |
873 }, | |
874 | |
875 function downloadInvalidFilename() { | |
876 // Test that we disallow invalid filenames for new downloads. | |
877 downloads.download( | |
878 {'url': SAFE_FAST_URL, 'filename': '../../../../../etc/passwd'}, | |
879 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
880 }, | |
881 | |
882 function downloadEmpty() { | |
883 assertThrows(('Invalid value for argument 1. Property \'url\': ' + | |
884 'Property is required.'), | |
885 downloads.download, {}); | |
886 }, | |
887 | |
888 function downloadInvalidSaveAs() { | |
889 assertThrows(('Invalid value for argument 1. Property \'saveAs\': ' + | |
890 'Expected \'boolean\' but got \'string\'.'), | |
891 downloads.download, | |
892 {'url': SAFE_FAST_URL, 'saveAs': 'GOAT'}); | |
893 }, | |
894 | |
895 function downloadInvalidHeadersOption() { | |
896 assertThrows(('Invalid value for argument 1. Property \'headers\': ' + | |
897 'Expected \'array\' but got \'string\'.'), | |
898 downloads.download, | |
899 {'url': SAFE_FAST_URL, 'headers': 'GOAT'}); | |
900 }, | |
901 | |
902 function downloadInvalidURL0() { | |
903 // Test that download() requires a valid url. | |
904 downloads.download( | |
905 {'url': 'foo bar'}, | |
906 chrome.test.callbackFail(downloads.ERROR_INVALID_URL)); | |
907 }, | |
908 | |
909 function downloadInvalidURL1() { | |
910 // Test that download() requires a valid url, including protocol and | |
911 // hostname. | |
912 downloads.download( | |
913 {'url': '../hello'}, | |
914 chrome.test.callbackFail(downloads.ERROR_INVALID_URL)); | |
915 }, | |
916 | |
917 function downloadInvalidURL2() { | |
918 // Test that download() requires a valid url, including protocol and | |
919 // hostname. | |
920 downloads.download( | |
921 {'url': '/hello'}, | |
922 chrome.test.callbackFail(downloads.ERROR_INVALID_URL)); | |
923 }, | |
924 | |
925 function downloadInvalidURL3() { | |
926 // Test that download() requires a valid url, including protocol. | |
927 downloads.download( | |
928 {'url': 'google.com/'}, | |
929 chrome.test.callbackFail(downloads.ERROR_INVALID_URL)); | |
930 }, | |
931 | |
932 function downloadInvalidURL4() { | |
933 // Test that download() requires a valid url, including protocol and | |
934 // hostname. | |
935 downloads.download( | |
936 {'url': 'http://'}, | |
937 chrome.test.callbackFail(downloads.ERROR_INVALID_URL)); | |
938 }, | |
939 | |
940 function downloadInvalidURL5() { | |
941 // Test that download() requires a valid url, including protocol and | |
942 // hostname. | |
943 downloads.download( | |
944 {'url': '#frag'}, | |
945 chrome.test.callbackFail(downloads.ERROR_INVALID_URL)); | |
946 }, | |
947 | |
948 function downloadInvalidURL6() { | |
949 // Test that download() requires a valid url, including protocol and | |
950 // hostname. | |
951 downloads.download( | |
952 {'url': 'foo/bar.html#frag'}, | |
953 chrome.test.callbackFail(downloads.ERROR_INVALID_URL)); | |
954 }, | |
955 | |
956 function downloadAllowFragments() { | |
957 // Valid URLs plus fragments are still valid URLs. | |
958 var downloadId = getNextId(); | |
959 console.debug(downloadId); | |
960 downloads.download( | |
961 {'url': SAFE_FAST_URL + '#frag'}, | |
962 chrome.test.callback(function(id) { | |
963 chrome.test.assertEq(downloadId, id); | |
964 })); | |
965 }, | |
966 | |
967 function downloadAllowDataURLs() { | |
968 var downloadId = getNextId(); | |
969 downloads.download( | |
970 {'url': 'data:text/plain,hello'}, | |
971 chrome.test.callback(function(id) { | |
972 chrome.test.assertEq(downloadId, id); | |
973 })); | |
974 }, | |
975 | |
976 function downloadAllowFileURLs() { | |
977 // Valid file URLs are valid URLs. | |
978 var downloadId = getNextId(); | |
979 console.debug(downloadId); | |
980 downloads.download( | |
981 {'url': 'file:///'}, | |
982 chrome.test.callback(function(id) { | |
983 chrome.test.assertEq(downloadId, id); | |
984 })); | |
985 }, | |
986 | |
987 function downloadInvalidURL7() { | |
988 // Test that download() rejects javascript urls. | |
989 downloads.download( | |
990 {'url': 'javascript:document.write("hello");'}, | |
991 chrome.test.callbackFail(downloads.ERROR_INVALID_URL)); | |
992 }, | |
993 | |
994 function downloadInvalidURL8() { | |
995 // Test that download() rejects javascript urls. | |
996 downloads.download( | |
997 {'url': 'javascript:return false;'}, | |
998 chrome.test.callbackFail(downloads.ERROR_INVALID_URL)); | |
999 }, | |
1000 | |
1001 function downloadInvalidURL9() { | |
1002 // Test that download() rejects otherwise-valid URLs that fail the host | |
1003 // permissions check. | |
1004 downloads.download( | |
1005 {'url': 'ftp://example.com/example.txt'}, | |
1006 chrome.test.callbackFail(downloads.ERROR_INVALID_URL)); | |
1007 }, | |
1008 | |
1009 // TODO(benjhayden): Set up a test ftp server, add ftp://localhost* to | |
1010 // permissions, maybe update downloadInvalidURL9. | |
1011 // function downloadAllowFTPURLs() { | |
1012 // // Valid ftp URLs are valid URLs. | |
1013 // var downloadId = getNextId(); | |
1014 // console.debug(downloadId); | |
1015 // downloads.download( | |
1016 // {'url': 'ftp://localhost:' + testConfig.testServer.port + '/'}, | |
1017 // chrome.test.callback(function(id) { | |
1018 // chrome.test.assertEq(downloadId, id); | |
1019 // })); | |
1020 // }, | |
1021 | |
1022 function downloadInvalidMethod() { | |
1023 assertThrows(('Invalid value for argument 1. Property \'method\': ' + | |
1024 'Value must be one of: [GET, POST].'), | |
1025 downloads.download, | |
1026 {'url': SAFE_FAST_URL, 'method': 'GOAT'}); | |
1027 }, | |
1028 | |
1029 function downloadInvalidHeader() { | |
1030 // Test that download() disallows setting the Cookie header. | |
1031 downloads.download( | |
1032 {'url': SAFE_FAST_URL, | |
1033 'headers': [{ 'name': 'Cookie', 'value': 'fake'}] | |
1034 }, | |
1035 chrome.test.callbackFail(downloads.ERROR_GENERIC)); | |
1036 }, | |
1037 | |
1038 function downloadGetFileIconInvalidOptions() { | |
1039 assertThrows(('Invalid value for argument 2. Property \'cat\': ' + | |
1040 'Unexpected property.'), | |
1041 downloads.getFileIcon, | |
1042 -1, {cat: 'mouse'}); | |
1043 }, | |
1044 | |
1045 function downloadGetFileIconInvalidSize() { | |
1046 assertThrows(('Invalid value for argument 2. Property \'size\': ' + | |
1047 'Value must be one of: [16, 32].'), | |
1048 downloads.getFileIcon, -1, {size: 31}); | |
1049 }, | |
1050 | |
1051 function downloadGetFileIconInvalidId() { | |
1052 downloads.getFileIcon(-42, {size: 32}, | |
1053 chrome.test.callbackFail(downloads.ERROR_INVALID_OPERATION)); | |
1054 }, | |
1055 | |
1056 function downloadPauseInvalidId() { | |
1057 downloads.pause(-42, chrome.test.callbackFail( | |
1058 downloads.ERROR_INVALID_OPERATION)); | |
1059 }, | |
1060 | |
1061 function downloadPauseInvalidType() { | |
1062 assertThrows(('Invocation of form experimental.downloads.pause(string,' + | |
1063 ' function) doesn\'t match definition experimental.' + | |
1064 'downloads.pause(integer id, optional function callback)'), | |
1065 downloads.pause, | |
1066 'foo'); | |
1067 }, | |
1068 | |
1069 function downloadResumeInvalidId() { | |
1070 downloads.resume(-42, chrome.test.callbackFail( | |
1071 downloads.ERROR_INVALID_OPERATION)); | |
1072 }, | |
1073 | |
1074 function downloadResumeInvalidType() { | |
1075 assertThrows(('Invocation of form experimental.downloads.resume(string,' + | |
1076 ' function) doesn\'t match definition experimental.' + | |
1077 'downloads.resume(integer id, optional function callback)'), | |
1078 downloads.resume, | |
1079 'foo'); | |
1080 }, | |
1081 | |
1082 function downloadCancelInvalidId() { | |
1083 // Canceling a non-existent download is not considered an error. | |
1084 downloads.cancel(-42, chrome.test.callback(function() { | |
1085 console.debug(''); | |
1086 })); | |
1087 }, | |
1088 | |
1089 function downloadCancelInvalidType() { | |
1090 assertThrows(('Invocation of form experimental.downloads.cancel(string,' + | |
1091 ' function) doesn\'t match definition experimental.' + | |
1092 'downloads.cancel(integer id, optional function callback)'), | |
1093 downloads.cancel, 'foo'); | |
1094 }, | |
1095 | |
1096 function downloadNoComplete() { | |
1097 // This is used partly to test cleanUp. | |
1098 var downloadId = getNextId(); | |
1099 console.debug(downloadId); | |
1100 downloads.download( | |
1101 {'url': NEVER_FINISH_URL}, | |
1102 chrome.test.callback(function(id) { | |
1103 console.debug(downloadId); | |
1104 chrome.test.assertEq(downloadId, id); | |
1105 })); | |
1106 }, | |
1107 | |
1108 function cleanUp() { | |
1109 // cleanUp must come last. It clears out all in-progress downloads | |
1110 // so the browser can shutdown cleanly. | |
1111 console.debug(nextId); | |
1112 function makeCallback(id) { | |
1113 return function() { | |
1114 console.debug(id); | |
1115 } | |
1116 } | |
1117 for (var id = 0; id < nextId; ++id) { | |
1118 downloads.cancel(id, chrome.test.callback(makeCallback(id))); | |
1119 } | |
1120 }, | |
1121 | |
1122 function callNotifyPass() { | |
1123 chrome.test.notifyPass(); | |
1124 setTimeout(chrome.test.callback(function() { | |
1125 console.debug(''); | |
1126 }), 0); | |
1127 } | |
1128 ]); | |
1129 }); | |
OLD | NEW |