|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 /** |
|
5 * Tests the DownloadIntegration object. |
|
6 */ |
|
7 |
|
8 "use strict"; |
|
9 |
|
10 //////////////////////////////////////////////////////////////////////////////// |
|
11 //// Globals |
|
12 |
|
13 /** |
|
14 * Enable test mode for the _confirmCancelDownloads method to return |
|
15 * the number of downloads instead of showing the prompt to cancel or not. |
|
16 */ |
|
17 function enableObserversTestMode() { |
|
18 DownloadIntegration.testMode = true; |
|
19 DownloadIntegration.dontLoadObservers = false; |
|
20 function cleanup() { |
|
21 DownloadIntegration.testMode = false; |
|
22 DownloadIntegration.dontLoadObservers = true; |
|
23 } |
|
24 do_register_cleanup(cleanup); |
|
25 } |
|
26 |
|
27 /** |
|
28 * Notifies the prompt observers and verify the expected downloads count. |
|
29 * |
|
30 * @param aIsPrivate |
|
31 * Flag to know is test private observers. |
|
32 * @param aExpectedCount |
|
33 * the expected downloads count for quit and offline observers. |
|
34 * @param aExpectedPBCount |
|
35 * the expected downloads count for private browsing observer. |
|
36 */ |
|
37 function notifyPromptObservers(aIsPrivate, aExpectedCount, aExpectedPBCount) { |
|
38 let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]. |
|
39 createInstance(Ci.nsISupportsPRBool); |
|
40 |
|
41 // Notify quit application requested observer. |
|
42 DownloadIntegration.testPromptDownloads = -1; |
|
43 Services.obs.notifyObservers(cancelQuit, "quit-application-requested", null); |
|
44 do_check_eq(DownloadIntegration.testPromptDownloads, aExpectedCount); |
|
45 |
|
46 // Notify offline requested observer. |
|
47 DownloadIntegration.testPromptDownloads = -1; |
|
48 Services.obs.notifyObservers(cancelQuit, "offline-requested", null); |
|
49 do_check_eq(DownloadIntegration.testPromptDownloads, aExpectedCount); |
|
50 |
|
51 if (aIsPrivate) { |
|
52 // Notify last private browsing requested observer. |
|
53 DownloadIntegration.testPromptDownloads = -1; |
|
54 Services.obs.notifyObservers(cancelQuit, "last-pb-context-exiting", null); |
|
55 do_check_eq(DownloadIntegration.testPromptDownloads, aExpectedPBCount); |
|
56 } |
|
57 } |
|
58 |
|
59 //////////////////////////////////////////////////////////////////////////////// |
|
60 //// Tests |
|
61 |
|
62 XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() { |
|
63 return Services.strings. |
|
64 createBundle("chrome://mozapps/locale/downloads/downloads.properties"); |
|
65 }); |
|
66 |
|
67 /** |
|
68 * Tests that the getSystemDownloadsDirectory returns a valid download |
|
69 * directory string path. |
|
70 */ |
|
71 add_task(function test_getSystemDownloadsDirectory() |
|
72 { |
|
73 // Enable test mode for the getSystemDownloadsDirectory method to return |
|
74 // temp directory instead so we can check whether the desired directory |
|
75 // is created or not. |
|
76 DownloadIntegration.testMode = true; |
|
77 function cleanup() { |
|
78 DownloadIntegration.testMode = false; |
|
79 } |
|
80 do_register_cleanup(cleanup); |
|
81 |
|
82 let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); |
|
83 let downloadDir; |
|
84 |
|
85 // OSX / Linux / Windows but not XP/2k |
|
86 if (Services.appinfo.OS == "Darwin" || |
|
87 Services.appinfo.OS == "Linux" || |
|
88 (Services.appinfo.OS == "WINNT" && |
|
89 parseFloat(Services.sysinfo.getProperty("version")) >= 6)) { |
|
90 downloadDir = yield DownloadIntegration.getSystemDownloadsDirectory(); |
|
91 do_check_eq(downloadDir, tempDir.path); |
|
92 do_check_true(yield OS.File.exists(downloadDir)); |
|
93 |
|
94 let info = yield OS.File.stat(downloadDir); |
|
95 do_check_true(info.isDir); |
|
96 } else { |
|
97 let targetPath = OS.Path.join(tempDir.path, |
|
98 gStringBundle.GetStringFromName("downloadsFolder")); |
|
99 try { |
|
100 yield OS.File.removeEmptyDir(targetPath); |
|
101 } catch(e) {} |
|
102 downloadDir = yield DownloadIntegration.getSystemDownloadsDirectory(); |
|
103 do_check_eq(downloadDir, targetPath); |
|
104 do_check_true(yield OS.File.exists(downloadDir)); |
|
105 |
|
106 let info = yield OS.File.stat(downloadDir); |
|
107 do_check_true(info.isDir); |
|
108 yield OS.File.removeEmptyDir(targetPath); |
|
109 } |
|
110 |
|
111 let downloadDirBefore = yield DownloadIntegration.getSystemDownloadsDirectory(); |
|
112 cleanup(); |
|
113 let downloadDirAfter = yield DownloadIntegration.getSystemDownloadsDirectory(); |
|
114 do_check_neq(downloadDirBefore, downloadDirAfter); |
|
115 }); |
|
116 |
|
117 /** |
|
118 * Tests that the getPreferredDownloadsDirectory returns a valid download |
|
119 * directory string path. |
|
120 */ |
|
121 add_task(function test_getPreferredDownloadsDirectory() |
|
122 { |
|
123 let folderListPrefName = "browser.download.folderList"; |
|
124 let dirPrefName = "browser.download.dir"; |
|
125 function cleanup() { |
|
126 Services.prefs.clearUserPref(folderListPrefName); |
|
127 Services.prefs.clearUserPref(dirPrefName); |
|
128 } |
|
129 do_register_cleanup(cleanup); |
|
130 |
|
131 // Should return the system downloads directory. |
|
132 Services.prefs.setIntPref(folderListPrefName, 1); |
|
133 let systemDir = yield DownloadIntegration.getSystemDownloadsDirectory(); |
|
134 let downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); |
|
135 do_check_neq(downloadDir, ""); |
|
136 do_check_eq(downloadDir, systemDir); |
|
137 |
|
138 // Should return the desktop directory. |
|
139 Services.prefs.setIntPref(folderListPrefName, 0); |
|
140 downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); |
|
141 do_check_neq(downloadDir, ""); |
|
142 do_check_eq(downloadDir, Services.dirsvc.get("Desk", Ci.nsIFile).path); |
|
143 |
|
144 // Should return the system downloads directory because the dir preference |
|
145 // is not set. |
|
146 Services.prefs.setIntPref(folderListPrefName, 2); |
|
147 let downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); |
|
148 do_check_neq(downloadDir, ""); |
|
149 do_check_eq(downloadDir, systemDir); |
|
150 |
|
151 // Should return the directory which is listed in the dir preference. |
|
152 let time = (new Date()).getTime(); |
|
153 let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); |
|
154 tempDir.append(time); |
|
155 Services.prefs.setComplexValue("browser.download.dir", Ci.nsIFile, tempDir); |
|
156 downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); |
|
157 do_check_neq(downloadDir, ""); |
|
158 do_check_eq(downloadDir, tempDir.path); |
|
159 do_check_true(yield OS.File.exists(downloadDir)); |
|
160 yield OS.File.removeEmptyDir(tempDir.path); |
|
161 |
|
162 // Should return the system downloads directory beacause the path is invalid |
|
163 // in the dir preference. |
|
164 tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); |
|
165 tempDir.append("dir_not_exist"); |
|
166 tempDir.append(time); |
|
167 Services.prefs.setComplexValue("browser.download.dir", Ci.nsIFile, tempDir); |
|
168 downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); |
|
169 do_check_eq(downloadDir, systemDir); |
|
170 |
|
171 // Should return the system downloads directory because the folderList |
|
172 // preference is invalid |
|
173 Services.prefs.setIntPref(folderListPrefName, 999); |
|
174 let downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); |
|
175 do_check_eq(downloadDir, systemDir); |
|
176 |
|
177 cleanup(); |
|
178 }); |
|
179 |
|
180 /** |
|
181 * Tests that the getTemporaryDownloadsDirectory returns a valid download |
|
182 * directory string path. |
|
183 */ |
|
184 add_task(function test_getTemporaryDownloadsDirectory() |
|
185 { |
|
186 let downloadDir = yield DownloadIntegration.getTemporaryDownloadsDirectory(); |
|
187 do_check_neq(downloadDir, ""); |
|
188 |
|
189 if ("nsILocalFileMac" in Ci) { |
|
190 let preferredDownloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); |
|
191 do_check_eq(downloadDir, preferredDownloadDir); |
|
192 } else { |
|
193 let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); |
|
194 do_check_eq(downloadDir, tempDir.path); |
|
195 } |
|
196 }); |
|
197 |
|
198 //////////////////////////////////////////////////////////////////////////////// |
|
199 //// Tests DownloadObserver |
|
200 |
|
201 /** |
|
202 * Tests notifications prompts when observers are notified if there are public |
|
203 * and private active downloads. |
|
204 */ |
|
205 add_task(function test_notifications() |
|
206 { |
|
207 enableObserversTestMode(); |
|
208 |
|
209 for (let isPrivate of [false, true]) { |
|
210 mustInterruptResponses(); |
|
211 |
|
212 let list = yield promiseNewList(isPrivate); |
|
213 let download1 = yield promiseNewDownload(httpUrl("interruptible.txt")); |
|
214 let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); |
|
215 let download3 = yield promiseNewDownload(httpUrl("interruptible.txt")); |
|
216 let promiseAttempt1 = download1.start(); |
|
217 let promiseAttempt2 = download2.start(); |
|
218 download3.start(); |
|
219 |
|
220 // Add downloads to list. |
|
221 yield list.add(download1); |
|
222 yield list.add(download2); |
|
223 yield list.add(download3); |
|
224 // Cancel third download |
|
225 yield download3.cancel(); |
|
226 |
|
227 notifyPromptObservers(isPrivate, 2, 2); |
|
228 |
|
229 // Allow the downloads to complete. |
|
230 continueResponses(); |
|
231 yield promiseAttempt1; |
|
232 yield promiseAttempt2; |
|
233 |
|
234 // Clean up. |
|
235 yield list.remove(download1); |
|
236 yield list.remove(download2); |
|
237 yield list.remove(download3); |
|
238 } |
|
239 }); |
|
240 |
|
241 /** |
|
242 * Tests that notifications prompts observers are not notified if there are no |
|
243 * public or private active downloads. |
|
244 */ |
|
245 add_task(function test_no_notifications() |
|
246 { |
|
247 enableObserversTestMode(); |
|
248 |
|
249 for (let isPrivate of [false, true]) { |
|
250 let list = yield promiseNewList(isPrivate); |
|
251 let download1 = yield promiseNewDownload(httpUrl("interruptible.txt")); |
|
252 let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); |
|
253 download1.start(); |
|
254 download2.start(); |
|
255 |
|
256 // Add downloads to list. |
|
257 yield list.add(download1); |
|
258 yield list.add(download2); |
|
259 |
|
260 yield download1.cancel(); |
|
261 yield download2.cancel(); |
|
262 |
|
263 notifyPromptObservers(isPrivate, 0, 0); |
|
264 |
|
265 // Clean up. |
|
266 yield list.remove(download1); |
|
267 yield list.remove(download2); |
|
268 } |
|
269 }); |
|
270 |
|
271 /** |
|
272 * Tests notifications prompts when observers are notified if there are public |
|
273 * and private active downloads at the same time. |
|
274 */ |
|
275 add_task(function test_mix_notifications() |
|
276 { |
|
277 enableObserversTestMode(); |
|
278 mustInterruptResponses(); |
|
279 |
|
280 let publicList = yield promiseNewList(); |
|
281 let privateList = yield Downloads.getList(Downloads.PRIVATE); |
|
282 let download1 = yield promiseNewDownload(httpUrl("interruptible.txt")); |
|
283 let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); |
|
284 let promiseAttempt1 = download1.start(); |
|
285 let promiseAttempt2 = download2.start(); |
|
286 |
|
287 // Add downloads to lists. |
|
288 yield publicList.add(download1); |
|
289 yield privateList.add(download2); |
|
290 |
|
291 notifyPromptObservers(true, 2, 1); |
|
292 |
|
293 // Allow the downloads to complete. |
|
294 continueResponses(); |
|
295 yield promiseAttempt1; |
|
296 yield promiseAttempt2; |
|
297 |
|
298 // Clean up. |
|
299 yield publicList.remove(download1); |
|
300 yield privateList.remove(download2); |
|
301 }); |
|
302 |
|
303 /** |
|
304 * Tests suspending and resuming as well as going offline and then online again. |
|
305 * The downloads should stop when suspending and start again when resuming. |
|
306 */ |
|
307 add_task(function test_suspend_resume() |
|
308 { |
|
309 enableObserversTestMode(); |
|
310 |
|
311 // The default wake delay is 10 seconds, so set the wake delay to be much |
|
312 // faster for these tests. |
|
313 Services.prefs.setIntPref("browser.download.manager.resumeOnWakeDelay", 5); |
|
314 |
|
315 let addDownload = function(list) |
|
316 { |
|
317 return Task.spawn(function () { |
|
318 let download = yield promiseNewDownload(httpUrl("interruptible.txt")); |
|
319 download.start(); |
|
320 list.add(download); |
|
321 throw new Task.Result(download); |
|
322 }); |
|
323 } |
|
324 |
|
325 let publicList = yield promiseNewList(); |
|
326 let privateList = yield promiseNewList(true); |
|
327 |
|
328 let download1 = yield addDownload(publicList); |
|
329 let download2 = yield addDownload(publicList); |
|
330 let download3 = yield addDownload(privateList); |
|
331 let download4 = yield addDownload(privateList); |
|
332 let download5 = yield addDownload(publicList); |
|
333 |
|
334 // First, check that the downloads are all canceled when going to sleep. |
|
335 Services.obs.notifyObservers(null, "sleep_notification", null); |
|
336 do_check_true(download1.canceled); |
|
337 do_check_true(download2.canceled); |
|
338 do_check_true(download3.canceled); |
|
339 do_check_true(download4.canceled); |
|
340 do_check_true(download5.canceled); |
|
341 |
|
342 // Remove a download. It should not be started again. |
|
343 publicList.remove(download5); |
|
344 do_check_true(download5.canceled); |
|
345 |
|
346 // When waking up again, the downloads start again after the wake delay. To be |
|
347 // more robust, don't check after a delay but instead just wait for the |
|
348 // downloads to finish. |
|
349 Services.obs.notifyObservers(null, "wake_notification", null); |
|
350 yield download1.whenSucceeded(); |
|
351 yield download2.whenSucceeded(); |
|
352 yield download3.whenSucceeded(); |
|
353 yield download4.whenSucceeded(); |
|
354 |
|
355 // Downloads should no longer be canceled. However, as download5 was removed |
|
356 // from the public list, it will not be restarted. |
|
357 do_check_false(download1.canceled); |
|
358 do_check_true(download5.canceled); |
|
359 |
|
360 // Create four new downloads and check for going offline and then online again. |
|
361 |
|
362 download1 = yield addDownload(publicList); |
|
363 download2 = yield addDownload(publicList); |
|
364 download3 = yield addDownload(privateList); |
|
365 download4 = yield addDownload(privateList); |
|
366 |
|
367 // Going offline should cancel the downloads. |
|
368 Services.obs.notifyObservers(null, "network:offline-about-to-go-offline", null); |
|
369 do_check_true(download1.canceled); |
|
370 do_check_true(download2.canceled); |
|
371 do_check_true(download3.canceled); |
|
372 do_check_true(download4.canceled); |
|
373 |
|
374 // Going back online should start the downloads again. |
|
375 Services.obs.notifyObservers(null, "network:offline-status-changed", "online"); |
|
376 yield download1.whenSucceeded(); |
|
377 yield download2.whenSucceeded(); |
|
378 yield download3.whenSucceeded(); |
|
379 yield download4.whenSucceeded(); |
|
380 |
|
381 Services.prefs.clearUserPref("browser.download.manager.resumeOnWakeDelay"); |
|
382 }); |
|
383 |
|
384 /** |
|
385 * Tests both the downloads list and the in-progress downloads are clear when |
|
386 * private browsing observer is notified. |
|
387 */ |
|
388 add_task(function test_exit_private_browsing() |
|
389 { |
|
390 enableObserversTestMode(); |
|
391 mustInterruptResponses(); |
|
392 |
|
393 let privateList = yield promiseNewList(true); |
|
394 let download1 = yield promiseNewDownload(httpUrl("source.txt")); |
|
395 let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); |
|
396 let promiseAttempt1 = download1.start(); |
|
397 let promiseAttempt2 = download2.start(); |
|
398 |
|
399 // Add downloads to list. |
|
400 yield privateList.add(download1); |
|
401 yield privateList.add(download2); |
|
402 |
|
403 // Complete the download. |
|
404 yield promiseAttempt1; |
|
405 |
|
406 do_check_eq((yield privateList.getAll()).length, 2); |
|
407 |
|
408 // Simulate exiting the private browsing. |
|
409 DownloadIntegration._deferTestClearPrivateList = Promise.defer(); |
|
410 Services.obs.notifyObservers(null, "last-pb-context-exited", null); |
|
411 let result = yield DownloadIntegration._deferTestClearPrivateList.promise; |
|
412 |
|
413 do_check_eq(result, "success"); |
|
414 do_check_eq((yield privateList.getAll()).length, 0); |
|
415 |
|
416 continueResponses(); |
|
417 }); |
|
418 |
|
419 //////////////////////////////////////////////////////////////////////////////// |
|
420 //// Termination |
|
421 |
|
422 let tailFile = do_get_file("tail.js"); |
|
423 Services.scriptloader.loadSubScript(NetUtil.newURI(tailFile).spec); |