michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: /** michael@0: * Tests the DownloadIntegration object. michael@0: */ michael@0: michael@0: "use strict"; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// Globals michael@0: michael@0: /** michael@0: * Enable test mode for the _confirmCancelDownloads method to return michael@0: * the number of downloads instead of showing the prompt to cancel or not. michael@0: */ michael@0: function enableObserversTestMode() { michael@0: DownloadIntegration.testMode = true; michael@0: DownloadIntegration.dontLoadObservers = false; michael@0: function cleanup() { michael@0: DownloadIntegration.testMode = false; michael@0: DownloadIntegration.dontLoadObservers = true; michael@0: } michael@0: do_register_cleanup(cleanup); michael@0: } michael@0: michael@0: /** michael@0: * Notifies the prompt observers and verify the expected downloads count. michael@0: * michael@0: * @param aIsPrivate michael@0: * Flag to know is test private observers. michael@0: * @param aExpectedCount michael@0: * the expected downloads count for quit and offline observers. michael@0: * @param aExpectedPBCount michael@0: * the expected downloads count for private browsing observer. michael@0: */ michael@0: function notifyPromptObservers(aIsPrivate, aExpectedCount, aExpectedPBCount) { michael@0: let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]. michael@0: createInstance(Ci.nsISupportsPRBool); michael@0: michael@0: // Notify quit application requested observer. michael@0: DownloadIntegration.testPromptDownloads = -1; michael@0: Services.obs.notifyObservers(cancelQuit, "quit-application-requested", null); michael@0: do_check_eq(DownloadIntegration.testPromptDownloads, aExpectedCount); michael@0: michael@0: // Notify offline requested observer. michael@0: DownloadIntegration.testPromptDownloads = -1; michael@0: Services.obs.notifyObservers(cancelQuit, "offline-requested", null); michael@0: do_check_eq(DownloadIntegration.testPromptDownloads, aExpectedCount); michael@0: michael@0: if (aIsPrivate) { michael@0: // Notify last private browsing requested observer. michael@0: DownloadIntegration.testPromptDownloads = -1; michael@0: Services.obs.notifyObservers(cancelQuit, "last-pb-context-exiting", null); michael@0: do_check_eq(DownloadIntegration.testPromptDownloads, aExpectedPBCount); michael@0: } michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// Tests michael@0: michael@0: XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() { michael@0: return Services.strings. michael@0: createBundle("chrome://mozapps/locale/downloads/downloads.properties"); michael@0: }); michael@0: michael@0: /** michael@0: * Tests that the getSystemDownloadsDirectory returns a valid download michael@0: * directory string path. michael@0: */ michael@0: add_task(function test_getSystemDownloadsDirectory() michael@0: { michael@0: // Enable test mode for the getSystemDownloadsDirectory method to return michael@0: // temp directory instead so we can check whether the desired directory michael@0: // is created or not. michael@0: DownloadIntegration.testMode = true; michael@0: function cleanup() { michael@0: DownloadIntegration.testMode = false; michael@0: } michael@0: do_register_cleanup(cleanup); michael@0: michael@0: let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); michael@0: let downloadDir; michael@0: michael@0: // OSX / Linux / Windows but not XP/2k michael@0: if (Services.appinfo.OS == "Darwin" || michael@0: Services.appinfo.OS == "Linux" || michael@0: (Services.appinfo.OS == "WINNT" && michael@0: parseFloat(Services.sysinfo.getProperty("version")) >= 6)) { michael@0: downloadDir = yield DownloadIntegration.getSystemDownloadsDirectory(); michael@0: do_check_eq(downloadDir, tempDir.path); michael@0: do_check_true(yield OS.File.exists(downloadDir)); michael@0: michael@0: let info = yield OS.File.stat(downloadDir); michael@0: do_check_true(info.isDir); michael@0: } else { michael@0: let targetPath = OS.Path.join(tempDir.path, michael@0: gStringBundle.GetStringFromName("downloadsFolder")); michael@0: try { michael@0: yield OS.File.removeEmptyDir(targetPath); michael@0: } catch(e) {} michael@0: downloadDir = yield DownloadIntegration.getSystemDownloadsDirectory(); michael@0: do_check_eq(downloadDir, targetPath); michael@0: do_check_true(yield OS.File.exists(downloadDir)); michael@0: michael@0: let info = yield OS.File.stat(downloadDir); michael@0: do_check_true(info.isDir); michael@0: yield OS.File.removeEmptyDir(targetPath); michael@0: } michael@0: michael@0: let downloadDirBefore = yield DownloadIntegration.getSystemDownloadsDirectory(); michael@0: cleanup(); michael@0: let downloadDirAfter = yield DownloadIntegration.getSystemDownloadsDirectory(); michael@0: do_check_neq(downloadDirBefore, downloadDirAfter); michael@0: }); michael@0: michael@0: /** michael@0: * Tests that the getPreferredDownloadsDirectory returns a valid download michael@0: * directory string path. michael@0: */ michael@0: add_task(function test_getPreferredDownloadsDirectory() michael@0: { michael@0: let folderListPrefName = "browser.download.folderList"; michael@0: let dirPrefName = "browser.download.dir"; michael@0: function cleanup() { michael@0: Services.prefs.clearUserPref(folderListPrefName); michael@0: Services.prefs.clearUserPref(dirPrefName); michael@0: } michael@0: do_register_cleanup(cleanup); michael@0: michael@0: // Should return the system downloads directory. michael@0: Services.prefs.setIntPref(folderListPrefName, 1); michael@0: let systemDir = yield DownloadIntegration.getSystemDownloadsDirectory(); michael@0: let downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); michael@0: do_check_neq(downloadDir, ""); michael@0: do_check_eq(downloadDir, systemDir); michael@0: michael@0: // Should return the desktop directory. michael@0: Services.prefs.setIntPref(folderListPrefName, 0); michael@0: downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); michael@0: do_check_neq(downloadDir, ""); michael@0: do_check_eq(downloadDir, Services.dirsvc.get("Desk", Ci.nsIFile).path); michael@0: michael@0: // Should return the system downloads directory because the dir preference michael@0: // is not set. michael@0: Services.prefs.setIntPref(folderListPrefName, 2); michael@0: let downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); michael@0: do_check_neq(downloadDir, ""); michael@0: do_check_eq(downloadDir, systemDir); michael@0: michael@0: // Should return the directory which is listed in the dir preference. michael@0: let time = (new Date()).getTime(); michael@0: let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); michael@0: tempDir.append(time); michael@0: Services.prefs.setComplexValue("browser.download.dir", Ci.nsIFile, tempDir); michael@0: downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); michael@0: do_check_neq(downloadDir, ""); michael@0: do_check_eq(downloadDir, tempDir.path); michael@0: do_check_true(yield OS.File.exists(downloadDir)); michael@0: yield OS.File.removeEmptyDir(tempDir.path); michael@0: michael@0: // Should return the system downloads directory beacause the path is invalid michael@0: // in the dir preference. michael@0: tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); michael@0: tempDir.append("dir_not_exist"); michael@0: tempDir.append(time); michael@0: Services.prefs.setComplexValue("browser.download.dir", Ci.nsIFile, tempDir); michael@0: downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); michael@0: do_check_eq(downloadDir, systemDir); michael@0: michael@0: // Should return the system downloads directory because the folderList michael@0: // preference is invalid michael@0: Services.prefs.setIntPref(folderListPrefName, 999); michael@0: let downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); michael@0: do_check_eq(downloadDir, systemDir); michael@0: michael@0: cleanup(); michael@0: }); michael@0: michael@0: /** michael@0: * Tests that the getTemporaryDownloadsDirectory returns a valid download michael@0: * directory string path. michael@0: */ michael@0: add_task(function test_getTemporaryDownloadsDirectory() michael@0: { michael@0: let downloadDir = yield DownloadIntegration.getTemporaryDownloadsDirectory(); michael@0: do_check_neq(downloadDir, ""); michael@0: michael@0: if ("nsILocalFileMac" in Ci) { michael@0: let preferredDownloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); michael@0: do_check_eq(downloadDir, preferredDownloadDir); michael@0: } else { michael@0: let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); michael@0: do_check_eq(downloadDir, tempDir.path); michael@0: } michael@0: }); michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// Tests DownloadObserver michael@0: michael@0: /** michael@0: * Tests notifications prompts when observers are notified if there are public michael@0: * and private active downloads. michael@0: */ michael@0: add_task(function test_notifications() michael@0: { michael@0: enableObserversTestMode(); michael@0: michael@0: for (let isPrivate of [false, true]) { michael@0: mustInterruptResponses(); michael@0: michael@0: let list = yield promiseNewList(isPrivate); michael@0: let download1 = yield promiseNewDownload(httpUrl("interruptible.txt")); michael@0: let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); michael@0: let download3 = yield promiseNewDownload(httpUrl("interruptible.txt")); michael@0: let promiseAttempt1 = download1.start(); michael@0: let promiseAttempt2 = download2.start(); michael@0: download3.start(); michael@0: michael@0: // Add downloads to list. michael@0: yield list.add(download1); michael@0: yield list.add(download2); michael@0: yield list.add(download3); michael@0: // Cancel third download michael@0: yield download3.cancel(); michael@0: michael@0: notifyPromptObservers(isPrivate, 2, 2); michael@0: michael@0: // Allow the downloads to complete. michael@0: continueResponses(); michael@0: yield promiseAttempt1; michael@0: yield promiseAttempt2; michael@0: michael@0: // Clean up. michael@0: yield list.remove(download1); michael@0: yield list.remove(download2); michael@0: yield list.remove(download3); michael@0: } michael@0: }); michael@0: michael@0: /** michael@0: * Tests that notifications prompts observers are not notified if there are no michael@0: * public or private active downloads. michael@0: */ michael@0: add_task(function test_no_notifications() michael@0: { michael@0: enableObserversTestMode(); michael@0: michael@0: for (let isPrivate of [false, true]) { michael@0: let list = yield promiseNewList(isPrivate); michael@0: let download1 = yield promiseNewDownload(httpUrl("interruptible.txt")); michael@0: let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); michael@0: download1.start(); michael@0: download2.start(); michael@0: michael@0: // Add downloads to list. michael@0: yield list.add(download1); michael@0: yield list.add(download2); michael@0: michael@0: yield download1.cancel(); michael@0: yield download2.cancel(); michael@0: michael@0: notifyPromptObservers(isPrivate, 0, 0); michael@0: michael@0: // Clean up. michael@0: yield list.remove(download1); michael@0: yield list.remove(download2); michael@0: } michael@0: }); michael@0: michael@0: /** michael@0: * Tests notifications prompts when observers are notified if there are public michael@0: * and private active downloads at the same time. michael@0: */ michael@0: add_task(function test_mix_notifications() michael@0: { michael@0: enableObserversTestMode(); michael@0: mustInterruptResponses(); michael@0: michael@0: let publicList = yield promiseNewList(); michael@0: let privateList = yield Downloads.getList(Downloads.PRIVATE); michael@0: let download1 = yield promiseNewDownload(httpUrl("interruptible.txt")); michael@0: let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); michael@0: let promiseAttempt1 = download1.start(); michael@0: let promiseAttempt2 = download2.start(); michael@0: michael@0: // Add downloads to lists. michael@0: yield publicList.add(download1); michael@0: yield privateList.add(download2); michael@0: michael@0: notifyPromptObservers(true, 2, 1); michael@0: michael@0: // Allow the downloads to complete. michael@0: continueResponses(); michael@0: yield promiseAttempt1; michael@0: yield promiseAttempt2; michael@0: michael@0: // Clean up. michael@0: yield publicList.remove(download1); michael@0: yield privateList.remove(download2); michael@0: }); michael@0: michael@0: /** michael@0: * Tests suspending and resuming as well as going offline and then online again. michael@0: * The downloads should stop when suspending and start again when resuming. michael@0: */ michael@0: add_task(function test_suspend_resume() michael@0: { michael@0: enableObserversTestMode(); michael@0: michael@0: // The default wake delay is 10 seconds, so set the wake delay to be much michael@0: // faster for these tests. michael@0: Services.prefs.setIntPref("browser.download.manager.resumeOnWakeDelay", 5); michael@0: michael@0: let addDownload = function(list) michael@0: { michael@0: return Task.spawn(function () { michael@0: let download = yield promiseNewDownload(httpUrl("interruptible.txt")); michael@0: download.start(); michael@0: list.add(download); michael@0: throw new Task.Result(download); michael@0: }); michael@0: } michael@0: michael@0: let publicList = yield promiseNewList(); michael@0: let privateList = yield promiseNewList(true); michael@0: michael@0: let download1 = yield addDownload(publicList); michael@0: let download2 = yield addDownload(publicList); michael@0: let download3 = yield addDownload(privateList); michael@0: let download4 = yield addDownload(privateList); michael@0: let download5 = yield addDownload(publicList); michael@0: michael@0: // First, check that the downloads are all canceled when going to sleep. michael@0: Services.obs.notifyObservers(null, "sleep_notification", null); michael@0: do_check_true(download1.canceled); michael@0: do_check_true(download2.canceled); michael@0: do_check_true(download3.canceled); michael@0: do_check_true(download4.canceled); michael@0: do_check_true(download5.canceled); michael@0: michael@0: // Remove a download. It should not be started again. michael@0: publicList.remove(download5); michael@0: do_check_true(download5.canceled); michael@0: michael@0: // When waking up again, the downloads start again after the wake delay. To be michael@0: // more robust, don't check after a delay but instead just wait for the michael@0: // downloads to finish. michael@0: Services.obs.notifyObservers(null, "wake_notification", null); michael@0: yield download1.whenSucceeded(); michael@0: yield download2.whenSucceeded(); michael@0: yield download3.whenSucceeded(); michael@0: yield download4.whenSucceeded(); michael@0: michael@0: // Downloads should no longer be canceled. However, as download5 was removed michael@0: // from the public list, it will not be restarted. michael@0: do_check_false(download1.canceled); michael@0: do_check_true(download5.canceled); michael@0: michael@0: // Create four new downloads and check for going offline and then online again. michael@0: michael@0: download1 = yield addDownload(publicList); michael@0: download2 = yield addDownload(publicList); michael@0: download3 = yield addDownload(privateList); michael@0: download4 = yield addDownload(privateList); michael@0: michael@0: // Going offline should cancel the downloads. michael@0: Services.obs.notifyObservers(null, "network:offline-about-to-go-offline", null); michael@0: do_check_true(download1.canceled); michael@0: do_check_true(download2.canceled); michael@0: do_check_true(download3.canceled); michael@0: do_check_true(download4.canceled); michael@0: michael@0: // Going back online should start the downloads again. michael@0: Services.obs.notifyObservers(null, "network:offline-status-changed", "online"); michael@0: yield download1.whenSucceeded(); michael@0: yield download2.whenSucceeded(); michael@0: yield download3.whenSucceeded(); michael@0: yield download4.whenSucceeded(); michael@0: michael@0: Services.prefs.clearUserPref("browser.download.manager.resumeOnWakeDelay"); michael@0: }); michael@0: michael@0: /** michael@0: * Tests both the downloads list and the in-progress downloads are clear when michael@0: * private browsing observer is notified. michael@0: */ michael@0: add_task(function test_exit_private_browsing() michael@0: { michael@0: enableObserversTestMode(); michael@0: mustInterruptResponses(); michael@0: michael@0: let privateList = yield promiseNewList(true); michael@0: let download1 = yield promiseNewDownload(httpUrl("source.txt")); michael@0: let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); michael@0: let promiseAttempt1 = download1.start(); michael@0: let promiseAttempt2 = download2.start(); michael@0: michael@0: // Add downloads to list. michael@0: yield privateList.add(download1); michael@0: yield privateList.add(download2); michael@0: michael@0: // Complete the download. michael@0: yield promiseAttempt1; michael@0: michael@0: do_check_eq((yield privateList.getAll()).length, 2); michael@0: michael@0: // Simulate exiting the private browsing. michael@0: DownloadIntegration._deferTestClearPrivateList = Promise.defer(); michael@0: Services.obs.notifyObservers(null, "last-pb-context-exited", null); michael@0: let result = yield DownloadIntegration._deferTestClearPrivateList.promise; michael@0: michael@0: do_check_eq(result, "success"); michael@0: do_check_eq((yield privateList.getAll()).length, 0); michael@0: michael@0: continueResponses(); michael@0: }); michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// Termination michael@0: michael@0: let tailFile = do_get_file("tail.js"); michael@0: Services.scriptloader.loadSubScript(NetUtil.newURI(tailFile).spec);