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