1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/jsdownloads/test/unit/test_DownloadIntegration.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,423 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + * http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +/** 1.8 + * Tests the DownloadIntegration object. 1.9 + */ 1.10 + 1.11 +"use strict"; 1.12 + 1.13 +//////////////////////////////////////////////////////////////////////////////// 1.14 +//// Globals 1.15 + 1.16 +/** 1.17 + * Enable test mode for the _confirmCancelDownloads method to return 1.18 + * the number of downloads instead of showing the prompt to cancel or not. 1.19 + */ 1.20 +function enableObserversTestMode() { 1.21 + DownloadIntegration.testMode = true; 1.22 + DownloadIntegration.dontLoadObservers = false; 1.23 + function cleanup() { 1.24 + DownloadIntegration.testMode = false; 1.25 + DownloadIntegration.dontLoadObservers = true; 1.26 + } 1.27 + do_register_cleanup(cleanup); 1.28 +} 1.29 + 1.30 +/** 1.31 + * Notifies the prompt observers and verify the expected downloads count. 1.32 + * 1.33 + * @param aIsPrivate 1.34 + * Flag to know is test private observers. 1.35 + * @param aExpectedCount 1.36 + * the expected downloads count for quit and offline observers. 1.37 + * @param aExpectedPBCount 1.38 + * the expected downloads count for private browsing observer. 1.39 + */ 1.40 +function notifyPromptObservers(aIsPrivate, aExpectedCount, aExpectedPBCount) { 1.41 + let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]. 1.42 + createInstance(Ci.nsISupportsPRBool); 1.43 + 1.44 + // Notify quit application requested observer. 1.45 + DownloadIntegration.testPromptDownloads = -1; 1.46 + Services.obs.notifyObservers(cancelQuit, "quit-application-requested", null); 1.47 + do_check_eq(DownloadIntegration.testPromptDownloads, aExpectedCount); 1.48 + 1.49 + // Notify offline requested observer. 1.50 + DownloadIntegration.testPromptDownloads = -1; 1.51 + Services.obs.notifyObservers(cancelQuit, "offline-requested", null); 1.52 + do_check_eq(DownloadIntegration.testPromptDownloads, aExpectedCount); 1.53 + 1.54 + if (aIsPrivate) { 1.55 + // Notify last private browsing requested observer. 1.56 + DownloadIntegration.testPromptDownloads = -1; 1.57 + Services.obs.notifyObservers(cancelQuit, "last-pb-context-exiting", null); 1.58 + do_check_eq(DownloadIntegration.testPromptDownloads, aExpectedPBCount); 1.59 + } 1.60 +} 1.61 + 1.62 +//////////////////////////////////////////////////////////////////////////////// 1.63 +//// Tests 1.64 + 1.65 +XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() { 1.66 + return Services.strings. 1.67 + createBundle("chrome://mozapps/locale/downloads/downloads.properties"); 1.68 +}); 1.69 + 1.70 +/** 1.71 + * Tests that the getSystemDownloadsDirectory returns a valid download 1.72 + * directory string path. 1.73 + */ 1.74 +add_task(function test_getSystemDownloadsDirectory() 1.75 +{ 1.76 + // Enable test mode for the getSystemDownloadsDirectory method to return 1.77 + // temp directory instead so we can check whether the desired directory 1.78 + // is created or not. 1.79 + DownloadIntegration.testMode = true; 1.80 + function cleanup() { 1.81 + DownloadIntegration.testMode = false; 1.82 + } 1.83 + do_register_cleanup(cleanup); 1.84 + 1.85 + let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); 1.86 + let downloadDir; 1.87 + 1.88 + // OSX / Linux / Windows but not XP/2k 1.89 + if (Services.appinfo.OS == "Darwin" || 1.90 + Services.appinfo.OS == "Linux" || 1.91 + (Services.appinfo.OS == "WINNT" && 1.92 + parseFloat(Services.sysinfo.getProperty("version")) >= 6)) { 1.93 + downloadDir = yield DownloadIntegration.getSystemDownloadsDirectory(); 1.94 + do_check_eq(downloadDir, tempDir.path); 1.95 + do_check_true(yield OS.File.exists(downloadDir)); 1.96 + 1.97 + let info = yield OS.File.stat(downloadDir); 1.98 + do_check_true(info.isDir); 1.99 + } else { 1.100 + let targetPath = OS.Path.join(tempDir.path, 1.101 + gStringBundle.GetStringFromName("downloadsFolder")); 1.102 + try { 1.103 + yield OS.File.removeEmptyDir(targetPath); 1.104 + } catch(e) {} 1.105 + downloadDir = yield DownloadIntegration.getSystemDownloadsDirectory(); 1.106 + do_check_eq(downloadDir, targetPath); 1.107 + do_check_true(yield OS.File.exists(downloadDir)); 1.108 + 1.109 + let info = yield OS.File.stat(downloadDir); 1.110 + do_check_true(info.isDir); 1.111 + yield OS.File.removeEmptyDir(targetPath); 1.112 + } 1.113 + 1.114 + let downloadDirBefore = yield DownloadIntegration.getSystemDownloadsDirectory(); 1.115 + cleanup(); 1.116 + let downloadDirAfter = yield DownloadIntegration.getSystemDownloadsDirectory(); 1.117 + do_check_neq(downloadDirBefore, downloadDirAfter); 1.118 +}); 1.119 + 1.120 +/** 1.121 + * Tests that the getPreferredDownloadsDirectory returns a valid download 1.122 + * directory string path. 1.123 + */ 1.124 +add_task(function test_getPreferredDownloadsDirectory() 1.125 +{ 1.126 + let folderListPrefName = "browser.download.folderList"; 1.127 + let dirPrefName = "browser.download.dir"; 1.128 + function cleanup() { 1.129 + Services.prefs.clearUserPref(folderListPrefName); 1.130 + Services.prefs.clearUserPref(dirPrefName); 1.131 + } 1.132 + do_register_cleanup(cleanup); 1.133 + 1.134 + // Should return the system downloads directory. 1.135 + Services.prefs.setIntPref(folderListPrefName, 1); 1.136 + let systemDir = yield DownloadIntegration.getSystemDownloadsDirectory(); 1.137 + let downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); 1.138 + do_check_neq(downloadDir, ""); 1.139 + do_check_eq(downloadDir, systemDir); 1.140 + 1.141 + // Should return the desktop directory. 1.142 + Services.prefs.setIntPref(folderListPrefName, 0); 1.143 + downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); 1.144 + do_check_neq(downloadDir, ""); 1.145 + do_check_eq(downloadDir, Services.dirsvc.get("Desk", Ci.nsIFile).path); 1.146 + 1.147 + // Should return the system downloads directory because the dir preference 1.148 + // is not set. 1.149 + Services.prefs.setIntPref(folderListPrefName, 2); 1.150 + let downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); 1.151 + do_check_neq(downloadDir, ""); 1.152 + do_check_eq(downloadDir, systemDir); 1.153 + 1.154 + // Should return the directory which is listed in the dir preference. 1.155 + let time = (new Date()).getTime(); 1.156 + let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); 1.157 + tempDir.append(time); 1.158 + Services.prefs.setComplexValue("browser.download.dir", Ci.nsIFile, tempDir); 1.159 + downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); 1.160 + do_check_neq(downloadDir, ""); 1.161 + do_check_eq(downloadDir, tempDir.path); 1.162 + do_check_true(yield OS.File.exists(downloadDir)); 1.163 + yield OS.File.removeEmptyDir(tempDir.path); 1.164 + 1.165 + // Should return the system downloads directory beacause the path is invalid 1.166 + // in the dir preference. 1.167 + tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); 1.168 + tempDir.append("dir_not_exist"); 1.169 + tempDir.append(time); 1.170 + Services.prefs.setComplexValue("browser.download.dir", Ci.nsIFile, tempDir); 1.171 + downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); 1.172 + do_check_eq(downloadDir, systemDir); 1.173 + 1.174 + // Should return the system downloads directory because the folderList 1.175 + // preference is invalid 1.176 + Services.prefs.setIntPref(folderListPrefName, 999); 1.177 + let downloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); 1.178 + do_check_eq(downloadDir, systemDir); 1.179 + 1.180 + cleanup(); 1.181 +}); 1.182 + 1.183 +/** 1.184 + * Tests that the getTemporaryDownloadsDirectory returns a valid download 1.185 + * directory string path. 1.186 + */ 1.187 +add_task(function test_getTemporaryDownloadsDirectory() 1.188 +{ 1.189 + let downloadDir = yield DownloadIntegration.getTemporaryDownloadsDirectory(); 1.190 + do_check_neq(downloadDir, ""); 1.191 + 1.192 + if ("nsILocalFileMac" in Ci) { 1.193 + let preferredDownloadDir = yield DownloadIntegration.getPreferredDownloadsDirectory(); 1.194 + do_check_eq(downloadDir, preferredDownloadDir); 1.195 + } else { 1.196 + let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); 1.197 + do_check_eq(downloadDir, tempDir.path); 1.198 + } 1.199 +}); 1.200 + 1.201 +//////////////////////////////////////////////////////////////////////////////// 1.202 +//// Tests DownloadObserver 1.203 + 1.204 +/** 1.205 + * Tests notifications prompts when observers are notified if there are public 1.206 + * and private active downloads. 1.207 + */ 1.208 +add_task(function test_notifications() 1.209 +{ 1.210 + enableObserversTestMode(); 1.211 + 1.212 + for (let isPrivate of [false, true]) { 1.213 + mustInterruptResponses(); 1.214 + 1.215 + let list = yield promiseNewList(isPrivate); 1.216 + let download1 = yield promiseNewDownload(httpUrl("interruptible.txt")); 1.217 + let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); 1.218 + let download3 = yield promiseNewDownload(httpUrl("interruptible.txt")); 1.219 + let promiseAttempt1 = download1.start(); 1.220 + let promiseAttempt2 = download2.start(); 1.221 + download3.start(); 1.222 + 1.223 + // Add downloads to list. 1.224 + yield list.add(download1); 1.225 + yield list.add(download2); 1.226 + yield list.add(download3); 1.227 + // Cancel third download 1.228 + yield download3.cancel(); 1.229 + 1.230 + notifyPromptObservers(isPrivate, 2, 2); 1.231 + 1.232 + // Allow the downloads to complete. 1.233 + continueResponses(); 1.234 + yield promiseAttempt1; 1.235 + yield promiseAttempt2; 1.236 + 1.237 + // Clean up. 1.238 + yield list.remove(download1); 1.239 + yield list.remove(download2); 1.240 + yield list.remove(download3); 1.241 + } 1.242 +}); 1.243 + 1.244 +/** 1.245 + * Tests that notifications prompts observers are not notified if there are no 1.246 + * public or private active downloads. 1.247 + */ 1.248 +add_task(function test_no_notifications() 1.249 +{ 1.250 + enableObserversTestMode(); 1.251 + 1.252 + for (let isPrivate of [false, true]) { 1.253 + let list = yield promiseNewList(isPrivate); 1.254 + let download1 = yield promiseNewDownload(httpUrl("interruptible.txt")); 1.255 + let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); 1.256 + download1.start(); 1.257 + download2.start(); 1.258 + 1.259 + // Add downloads to list. 1.260 + yield list.add(download1); 1.261 + yield list.add(download2); 1.262 + 1.263 + yield download1.cancel(); 1.264 + yield download2.cancel(); 1.265 + 1.266 + notifyPromptObservers(isPrivate, 0, 0); 1.267 + 1.268 + // Clean up. 1.269 + yield list.remove(download1); 1.270 + yield list.remove(download2); 1.271 + } 1.272 +}); 1.273 + 1.274 +/** 1.275 + * Tests notifications prompts when observers are notified if there are public 1.276 + * and private active downloads at the same time. 1.277 + */ 1.278 +add_task(function test_mix_notifications() 1.279 +{ 1.280 + enableObserversTestMode(); 1.281 + mustInterruptResponses(); 1.282 + 1.283 + let publicList = yield promiseNewList(); 1.284 + let privateList = yield Downloads.getList(Downloads.PRIVATE); 1.285 + let download1 = yield promiseNewDownload(httpUrl("interruptible.txt")); 1.286 + let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); 1.287 + let promiseAttempt1 = download1.start(); 1.288 + let promiseAttempt2 = download2.start(); 1.289 + 1.290 + // Add downloads to lists. 1.291 + yield publicList.add(download1); 1.292 + yield privateList.add(download2); 1.293 + 1.294 + notifyPromptObservers(true, 2, 1); 1.295 + 1.296 + // Allow the downloads to complete. 1.297 + continueResponses(); 1.298 + yield promiseAttempt1; 1.299 + yield promiseAttempt2; 1.300 + 1.301 + // Clean up. 1.302 + yield publicList.remove(download1); 1.303 + yield privateList.remove(download2); 1.304 +}); 1.305 + 1.306 +/** 1.307 + * Tests suspending and resuming as well as going offline and then online again. 1.308 + * The downloads should stop when suspending and start again when resuming. 1.309 + */ 1.310 +add_task(function test_suspend_resume() 1.311 +{ 1.312 + enableObserversTestMode(); 1.313 + 1.314 + // The default wake delay is 10 seconds, so set the wake delay to be much 1.315 + // faster for these tests. 1.316 + Services.prefs.setIntPref("browser.download.manager.resumeOnWakeDelay", 5); 1.317 + 1.318 + let addDownload = function(list) 1.319 + { 1.320 + return Task.spawn(function () { 1.321 + let download = yield promiseNewDownload(httpUrl("interruptible.txt")); 1.322 + download.start(); 1.323 + list.add(download); 1.324 + throw new Task.Result(download); 1.325 + }); 1.326 + } 1.327 + 1.328 + let publicList = yield promiseNewList(); 1.329 + let privateList = yield promiseNewList(true); 1.330 + 1.331 + let download1 = yield addDownload(publicList); 1.332 + let download2 = yield addDownload(publicList); 1.333 + let download3 = yield addDownload(privateList); 1.334 + let download4 = yield addDownload(privateList); 1.335 + let download5 = yield addDownload(publicList); 1.336 + 1.337 + // First, check that the downloads are all canceled when going to sleep. 1.338 + Services.obs.notifyObservers(null, "sleep_notification", null); 1.339 + do_check_true(download1.canceled); 1.340 + do_check_true(download2.canceled); 1.341 + do_check_true(download3.canceled); 1.342 + do_check_true(download4.canceled); 1.343 + do_check_true(download5.canceled); 1.344 + 1.345 + // Remove a download. It should not be started again. 1.346 + publicList.remove(download5); 1.347 + do_check_true(download5.canceled); 1.348 + 1.349 + // When waking up again, the downloads start again after the wake delay. To be 1.350 + // more robust, don't check after a delay but instead just wait for the 1.351 + // downloads to finish. 1.352 + Services.obs.notifyObservers(null, "wake_notification", null); 1.353 + yield download1.whenSucceeded(); 1.354 + yield download2.whenSucceeded(); 1.355 + yield download3.whenSucceeded(); 1.356 + yield download4.whenSucceeded(); 1.357 + 1.358 + // Downloads should no longer be canceled. However, as download5 was removed 1.359 + // from the public list, it will not be restarted. 1.360 + do_check_false(download1.canceled); 1.361 + do_check_true(download5.canceled); 1.362 + 1.363 + // Create four new downloads and check for going offline and then online again. 1.364 + 1.365 + download1 = yield addDownload(publicList); 1.366 + download2 = yield addDownload(publicList); 1.367 + download3 = yield addDownload(privateList); 1.368 + download4 = yield addDownload(privateList); 1.369 + 1.370 + // Going offline should cancel the downloads. 1.371 + Services.obs.notifyObservers(null, "network:offline-about-to-go-offline", null); 1.372 + do_check_true(download1.canceled); 1.373 + do_check_true(download2.canceled); 1.374 + do_check_true(download3.canceled); 1.375 + do_check_true(download4.canceled); 1.376 + 1.377 + // Going back online should start the downloads again. 1.378 + Services.obs.notifyObservers(null, "network:offline-status-changed", "online"); 1.379 + yield download1.whenSucceeded(); 1.380 + yield download2.whenSucceeded(); 1.381 + yield download3.whenSucceeded(); 1.382 + yield download4.whenSucceeded(); 1.383 + 1.384 + Services.prefs.clearUserPref("browser.download.manager.resumeOnWakeDelay"); 1.385 +}); 1.386 + 1.387 +/** 1.388 + * Tests both the downloads list and the in-progress downloads are clear when 1.389 + * private browsing observer is notified. 1.390 + */ 1.391 +add_task(function test_exit_private_browsing() 1.392 +{ 1.393 + enableObserversTestMode(); 1.394 + mustInterruptResponses(); 1.395 + 1.396 + let privateList = yield promiseNewList(true); 1.397 + let download1 = yield promiseNewDownload(httpUrl("source.txt")); 1.398 + let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); 1.399 + let promiseAttempt1 = download1.start(); 1.400 + let promiseAttempt2 = download2.start(); 1.401 + 1.402 + // Add downloads to list. 1.403 + yield privateList.add(download1); 1.404 + yield privateList.add(download2); 1.405 + 1.406 + // Complete the download. 1.407 + yield promiseAttempt1; 1.408 + 1.409 + do_check_eq((yield privateList.getAll()).length, 2); 1.410 + 1.411 + // Simulate exiting the private browsing. 1.412 + DownloadIntegration._deferTestClearPrivateList = Promise.defer(); 1.413 + Services.obs.notifyObservers(null, "last-pb-context-exited", null); 1.414 + let result = yield DownloadIntegration._deferTestClearPrivateList.promise; 1.415 + 1.416 + do_check_eq(result, "success"); 1.417 + do_check_eq((yield privateList.getAll()).length, 0); 1.418 + 1.419 + continueResponses(); 1.420 +}); 1.421 + 1.422 +//////////////////////////////////////////////////////////////////////////////// 1.423 +//// Termination 1.424 + 1.425 +let tailFile = do_get_file("tail.js"); 1.426 +Services.scriptloader.loadSubScript(NetUtil.newURI(tailFile).spec);