1 /* Any copyright is dedicated to the Public Domain.
2 * http://creativecommons.org/publicdomain/zero/1.0/ */
5 * Tests the DownloadIntegration object.
13 * Notifies the prompt observers and verify the expected downloads count.
16 * Flag to know is test private observers.
17 * @param aExpectedCount
18 * the expected downloads count for quit and offline observers.
19 * @param aExpectedPBCount
20 * the expected downloads count for private browsing observer.
22 function notifyPromptObservers(aIsPrivate, aExpectedCount, aExpectedPBCount) {
23 let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(
27 // Notify quit application requested observer.
28 DownloadIntegration._testPromptDownloads = -1;
29 Services.obs.notifyObservers(cancelQuit, "quit-application-requested");
30 Assert.equal(DownloadIntegration._testPromptDownloads, aExpectedCount);
32 // Notify offline requested observer.
33 DownloadIntegration._testPromptDownloads = -1;
34 Services.obs.notifyObservers(cancelQuit, "offline-requested");
35 Assert.equal(DownloadIntegration._testPromptDownloads, aExpectedCount);
38 // Notify last private browsing requested observer.
39 DownloadIntegration._testPromptDownloads = -1;
40 Services.obs.notifyObservers(cancelQuit, "last-pb-context-exiting");
41 Assert.equal(DownloadIntegration._testPromptDownloads, aExpectedPBCount);
44 delete DownloadIntegration._testPromptDownloads;
50 * Allows re-enabling the real download directory logic during one test.
52 function allowDirectoriesInTest() {
53 DownloadIntegration.allowDirectories = true;
55 DownloadIntegration.allowDirectories = false;
57 registerCleanupFunction(cleanup);
61 ChromeUtils.defineLazyGetter(this, "gStringBundle", function () {
62 return Services.strings.createBundle(
63 "chrome://mozapps/locale/downloads/downloads.properties"
68 * Tests that getSystemDownloadsDirectory returns an existing directory or
69 * creates a new directory depending on the platform. Instead of the real
70 * directory, this test is executed in the temporary directory so we can safely
71 * delete the created folder to check whether it is created again.
73 add_task(async function test_getSystemDownloadsDirectory_exists_or_creates() {
74 let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
77 // OSX / Linux / Windows but not XP/2k
79 Services.appinfo.OS == "Darwin" ||
80 Services.appinfo.OS == "Linux" ||
81 (Services.appinfo.OS == "WINNT" &&
82 parseFloat(Services.sysinfo.getProperty("version")) >= 6)
84 downloadDir = await DownloadIntegration.getSystemDownloadsDirectory();
85 Assert.equal(downloadDir, tempDir.path);
86 Assert.ok(await IOUtils.exists(downloadDir));
88 let info = await IOUtils.stat(downloadDir);
89 Assert.equal(info.type, "directory");
91 let targetPath = PathUtils.join(
93 gStringBundle.GetStringFromName("downloadsFolder")
96 await IOUtils.remove(targetPath);
98 downloadDir = await DownloadIntegration.getSystemDownloadsDirectory();
99 Assert.equal(downloadDir, targetPath);
100 Assert.ok(await IOUtils.exists(downloadDir));
102 let info = await IOUtils.stat(downloadDir);
103 Assert.equal(info.type, "directory");
104 await IOUtils.remove(targetPath);
109 * Tests that the real directory returned by getSystemDownloadsDirectory is not
110 * the one that is used during unit tests. Since this is the actual downloads
111 * directory of the operating system, we don't try to delete it afterwards.
113 add_task(async function test_getSystemDownloadsDirectory_real() {
114 let fakeDownloadDir = await DownloadIntegration.getSystemDownloadsDirectory();
116 let cleanup = allowDirectoriesInTest();
117 let realDownloadDir = await DownloadIntegration.getSystemDownloadsDirectory();
120 Assert.notEqual(fakeDownloadDir, realDownloadDir);
124 * Tests that the getPreferredDownloadsDirectory returns a valid download
125 * directory string path.
127 add_task(async function test_getPreferredDownloadsDirectory() {
128 let cleanupDirectories = allowDirectoriesInTest();
130 let folderListPrefName = "browser.download.folderList";
131 let dirPrefName = "browser.download.dir";
132 function cleanupPrefs() {
133 Services.prefs.clearUserPref(folderListPrefName);
134 Services.prefs.clearUserPref(dirPrefName);
136 registerCleanupFunction(cleanupPrefs);
138 // For legacy cloudstorage users with folderListPrefName as 3,
139 // Should return the system downloads directory because the dir preference
141 Services.prefs.setIntPref(folderListPrefName, 3);
142 let systemDir = await DownloadIntegration.getSystemDownloadsDirectory();
143 let downloadDir = await DownloadIntegration.getPreferredDownloadsDirectory();
144 Assert.notEqual(downloadDir, "");
145 Assert.equal(downloadDir, systemDir);
147 // Should return the system downloads directory.
148 Services.prefs.setIntPref(folderListPrefName, 1);
149 systemDir = await DownloadIntegration.getSystemDownloadsDirectory();
150 downloadDir = await DownloadIntegration.getPreferredDownloadsDirectory();
151 Assert.notEqual(downloadDir, "");
152 Assert.equal(downloadDir, systemDir);
154 // Should return the desktop directory.
155 Services.prefs.setIntPref(folderListPrefName, 0);
156 downloadDir = await DownloadIntegration.getPreferredDownloadsDirectory();
157 Assert.notEqual(downloadDir, "");
158 Assert.equal(downloadDir, Services.dirsvc.get("Desk", Ci.nsIFile).path);
160 // Should return the system downloads directory because the dir preference
162 Services.prefs.setIntPref(folderListPrefName, 2);
163 downloadDir = await DownloadIntegration.getPreferredDownloadsDirectory();
164 Assert.notEqual(downloadDir, "");
165 Assert.equal(downloadDir, systemDir);
167 // Should return the directory which is listed in the dir preference.
168 let time = new Date().getTime();
169 let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
170 tempDir.append(time);
171 Services.prefs.setComplexValue("browser.download.dir", Ci.nsIFile, tempDir);
172 downloadDir = await DownloadIntegration.getPreferredDownloadsDirectory();
173 Assert.notEqual(downloadDir, "");
174 Assert.equal(downloadDir, tempDir.path);
175 Assert.ok(await IOUtils.exists(downloadDir));
176 await IOUtils.remove(tempDir.path);
178 // Should return the system downloads directory beacause the path is invalid
179 // in the dir preference.
180 tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
181 tempDir.append("dir_not_exist");
182 tempDir.append(time);
183 Services.prefs.setComplexValue("browser.download.dir", Ci.nsIFile, tempDir);
184 downloadDir = await DownloadIntegration.getPreferredDownloadsDirectory();
185 Assert.equal(downloadDir, systemDir);
187 // Should return the system downloads directory because the folderList
188 // preference is invalid
189 Services.prefs.setIntPref(folderListPrefName, 999);
190 downloadDir = await DownloadIntegration.getPreferredDownloadsDirectory();
191 Assert.equal(downloadDir, systemDir);
194 cleanupDirectories();
198 * Tests that the getTemporaryDownloadsDirectory returns a valid download
199 * directory string path.
201 add_task(async function test_getTemporaryDownloadsDirectory() {
202 let cleanup = allowDirectoriesInTest();
204 let downloadDir = await DownloadIntegration.getTemporaryDownloadsDirectory();
205 Assert.notEqual(downloadDir, "");
207 if ("nsILocalFileMac" in Ci) {
208 let preferredDownloadDir =
209 await DownloadIntegration.getPreferredDownloadsDirectory();
210 Assert.equal(downloadDir, preferredDownloadDir);
212 let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
213 Assert.equal(downloadDir, tempDir.path);
219 // Tests DownloadObserver
222 * Re-enables the default observers for the following tests.
224 * This takes effect the first time a DownloadList object is created, and lasts
225 * until this test file has completed.
227 add_task(async function test_observers_setup() {
228 DownloadIntegration.allowObservers = true;
229 registerCleanupFunction(function () {
230 DownloadIntegration.allowObservers = false;
235 * Tests notifications prompts when observers are notified if there are public
236 * and private active downloads.
238 add_task(async function test_notifications() {
239 for (let isPrivate of [false, true]) {
240 mustInterruptResponses();
242 let list = await promiseNewList(isPrivate);
243 let download1 = await promiseNewDownload(httpUrl("interruptible.txt"));
244 let download2 = await promiseNewDownload(httpUrl("interruptible.txt"));
245 let download3 = await promiseNewDownload(httpUrl("interruptible.txt"));
246 let promiseAttempt1 = download1.start();
247 let promiseAttempt2 = download2.start();
248 download3.start().catch(() => {});
250 // Add downloads to list.
251 await list.add(download1);
252 await list.add(download2);
253 await list.add(download3);
254 // Cancel third download
255 await download3.cancel();
257 notifyPromptObservers(isPrivate, 2, 2);
259 // Allow the downloads to complete.
261 await promiseAttempt1;
262 await promiseAttempt2;
265 await list.remove(download1);
266 await list.remove(download2);
267 await list.remove(download3);
272 * Tests that notifications prompts observers are not notified if there are no
273 * public or private active downloads.
275 add_task(async function test_no_notifications() {
276 for (let isPrivate of [false, true]) {
277 let list = await promiseNewList(isPrivate);
278 let download1 = await promiseNewDownload(httpUrl("interruptible.txt"));
279 let download2 = await promiseNewDownload(httpUrl("interruptible.txt"));
280 download1.start().catch(() => {});
281 download2.start().catch(() => {});
283 // Add downloads to list.
284 await list.add(download1);
285 await list.add(download2);
287 await download1.cancel();
288 await download2.cancel();
290 notifyPromptObservers(isPrivate, 0, 0);
293 await list.remove(download1);
294 await list.remove(download2);
299 * Tests notifications prompts when observers are notified if there are public
300 * and private active downloads at the same time.
302 add_task(async function test_mix_notifications() {
303 mustInterruptResponses();
305 let publicList = await promiseNewList();
306 let privateList = await Downloads.getList(Downloads.PRIVATE);
307 let download1 = await promiseNewDownload(httpUrl("interruptible.txt"));
308 let download2 = await promiseNewDownload(httpUrl("interruptible.txt"));
309 let promiseAttempt1 = download1.start();
310 let promiseAttempt2 = download2.start();
312 // Add downloads to lists.
313 await publicList.add(download1);
314 await privateList.add(download2);
316 notifyPromptObservers(true, 2, 1);
318 // Allow the downloads to complete.
320 await promiseAttempt1;
321 await promiseAttempt2;
324 await publicList.remove(download1);
325 await privateList.remove(download2);
329 * Tests suspending and resuming as well as going offline and then online again.
330 * The downloads should stop when suspending and start again when resuming.
332 add_task(async function test_suspend_resume() {
333 // The default wake delay is 10 seconds, so set the wake delay to be much
334 // faster for these tests.
335 Services.prefs.setIntPref("browser.download.manager.resumeOnWakeDelay", 5);
337 let addDownload = function (list) {
338 return (async function () {
339 let download = await promiseNewDownload(httpUrl("interruptible.txt"));
340 download.start().catch(() => {});
346 let publicList = await promiseNewList();
347 let privateList = await promiseNewList(true);
349 let download1 = await addDownload(publicList);
350 let download2 = await addDownload(publicList);
351 let download3 = await addDownload(privateList);
352 let download4 = await addDownload(privateList);
353 let download5 = await addDownload(publicList);
355 // First, check that the downloads are all canceled when going to sleep.
356 Services.obs.notifyObservers(null, "sleep_notification");
357 Assert.ok(download1.canceled);
358 Assert.ok(download2.canceled);
359 Assert.ok(download3.canceled);
360 Assert.ok(download4.canceled);
361 Assert.ok(download5.canceled);
363 // Remove a download. It should not be started again.
364 publicList.remove(download5);
365 Assert.ok(download5.canceled);
367 // When waking up again, the downloads start again after the wake delay. To be
368 // more robust, don't check after a delay but instead just wait for the
369 // downloads to finish.
370 Services.obs.notifyObservers(null, "wake_notification");
371 await download1.whenSucceeded();
372 await download2.whenSucceeded();
373 await download3.whenSucceeded();
374 await download4.whenSucceeded();
376 // Downloads should no longer be canceled. However, as download5 was removed
377 // from the public list, it will not be restarted.
378 Assert.ok(!download1.canceled);
379 Assert.ok(download5.canceled);
381 // Create four new downloads and check for going offline and then online again.
383 download1 = await addDownload(publicList);
384 download2 = await addDownload(publicList);
385 download3 = await addDownload(privateList);
386 download4 = await addDownload(privateList);
388 // Going offline should cancel the downloads.
389 Services.obs.notifyObservers(null, "network:offline-about-to-go-offline");
390 Assert.ok(download1.canceled);
391 Assert.ok(download2.canceled);
392 Assert.ok(download3.canceled);
393 Assert.ok(download4.canceled);
395 // Going back online should start the downloads again.
396 Services.obs.notifyObservers(
398 "network:offline-status-changed",
401 await download1.whenSucceeded();
402 await download2.whenSucceeded();
403 await download3.whenSucceeded();
404 await download4.whenSucceeded();
406 Services.prefs.clearUserPref("browser.download.manager.resumeOnWakeDelay");
410 * Tests both the downloads list and the in-progress downloads are clear when
411 * private browsing observer is notified.
413 add_task(async function test_exit_private_browsing() {
414 mustInterruptResponses();
416 let privateList = await promiseNewList(true);
417 let download1 = await promiseNewDownload(httpUrl("source.txt"));
418 let download2 = await promiseNewDownload(httpUrl("interruptible.txt"));
419 let promiseAttempt1 = download1.start();
422 // Add downloads to list.
423 await privateList.add(download1);
424 await privateList.add(download2);
426 // Complete the download.
427 await promiseAttempt1;
429 Assert.equal((await privateList.getAll()).length, 2);
431 // Simulate exiting the private browsing.
432 await new Promise(resolve => {
433 DownloadIntegration._testResolveClearPrivateList = resolve;
434 Services.obs.notifyObservers(null, "last-pb-context-exited");
436 delete DownloadIntegration._testResolveClearPrivateList;
438 Assert.equal((await privateList.getAll()).length, 0);