michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: Test download manager's interaction with the private browsing service. michael@0: michael@0: An overview of what this test does follows: michael@0: michael@0: * Create a download (Download-A) with specific details. michael@0: * Check that Download-A is retrievable. michael@0: * Enter private browsing mode. michael@0: * Check that Download-A is not accessible. michael@0: * Create another download (Download-B) with specific and different details. michael@0: * Check that Download-B is retrievable. michael@0: * Exit private browsing mode. michael@0: * Check that Download-A is retrievable. michael@0: * Check that Download-B is not accessible. michael@0: * Create a new download (Download-C) with specific details. michael@0: Start it and enter private browsing mode immediately after. michael@0: * Check that Download-C has been paused. michael@0: * Exit the private browsing mode. michael@0: * Verify that Download-C resumes and finishes correctly now. michael@0: **/ michael@0: michael@0: Components.utils.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: this.__defineGetter__("dm", function() { michael@0: delete this.dm; michael@0: return this.dm = Cc["@mozilla.org/download-manager;1"]. michael@0: getService(Ci.nsIDownloadManager); michael@0: }); michael@0: michael@0: /** michael@0: * Try to see if an active download is available using the |activeDownloads| michael@0: * property. michael@0: */ michael@0: function is_active_download_available(aGUID, aSrc, aDst, aName, aPrivate) { michael@0: let enumerator = aPrivate ? dm.activePrivateDownloads : dm.activeDownloads; michael@0: while (enumerator.hasMoreElements()) { michael@0: let download = enumerator.getNext(); michael@0: if (download.guid == aGUID && michael@0: download.source.spec == aSrc && michael@0: download.targetFile.path == aDst.path && michael@0: download.displayName == aName && michael@0: download.isPrivate == aPrivate) michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: function expect_download_present(aGUID, aSrc, aDst, aName, aPrivate) { michael@0: is_download_available(aGUID, aSrc, aDst, aName, aPrivate, true); michael@0: } michael@0: michael@0: function expect_download_absent(aGUID, aSrc, aDst, aName, aPrivate) { michael@0: is_download_available(aGUID, aSrc, aDst, aName, aPrivate, false); michael@0: } michael@0: michael@0: /** michael@0: * Try to see if a download is available using the |getDownloadByGUID| method. The michael@0: * download can both be active or inactive. michael@0: */ michael@0: function is_download_available(aGUID, aSrc, aDst, aName, aPrivate, present) { michael@0: do_test_pending(); michael@0: dm.getDownloadByGUID(aGUID, function(status, download) { michael@0: if (!present) { michael@0: do_check_eq(download, null); michael@0: } else { michael@0: do_check_neq(download, null); michael@0: do_check_eq(download.guid, aGUID); michael@0: do_check_eq(download.source.spec, aSrc); michael@0: do_check_eq(download.targetFile.path, aDst.path); michael@0: do_check_eq(download.displayName, aName); michael@0: do_check_eq(download.isPrivate, aPrivate); michael@0: } michael@0: do_test_finished(); michael@0: }); michael@0: } michael@0: michael@0: function run_test() { michael@0: if (oldDownloadManagerDisabled()) { michael@0: return; michael@0: } michael@0: michael@0: let prefBranch = Cc["@mozilla.org/preferences-service;1"]. michael@0: getService(Ci.nsIPrefBranch); michael@0: michael@0: do_test_pending(); michael@0: let httpserv = new HttpServer(); michael@0: httpserv.registerDirectory("/", do_get_cwd()); michael@0: httpserv.start(-1); michael@0: michael@0: let tmpDir = do_get_tempdir(); michael@0: const nsIWBP = Ci.nsIWebBrowserPersist; michael@0: michael@0: // make sure we're starting with an empty DB michael@0: do_check_eq(dm.activeDownloadCount, 0); michael@0: do_check_eq(dm.activePrivateDownloadCount, 0); michael@0: michael@0: let listener = { michael@0: phase: 1, michael@0: handledC: false, michael@0: onDownloadStateChange: function(aState, aDownload) michael@0: { michael@0: switch (aDownload.state) { michael@0: case dm.DOWNLOAD_FAILED: michael@0: case dm.DOWNLOAD_CANCELED: michael@0: case dm.DOWNLOAD_DIRTY: michael@0: case dm.DOWNLOAD_BLOCKED_POLICY: michael@0: // Fail! michael@0: if (aDownload.targetFile.exists()) michael@0: aDownload.targetFile.remove(false); michael@0: dm.removeListener(this); michael@0: do_throw("Download failed (name: " + aDownload.displayName + ", state: " + aDownload.state + ")"); michael@0: do_test_finished(); michael@0: break; michael@0: michael@0: // We need to wait until Download-C has started, because otherwise it michael@0: // won't be resumable, so the private browsing mode won't correctly pause it. michael@0: case dm.DOWNLOAD_DOWNLOADING: michael@0: if (aDownload.guid == downloadC && !this.handledC && this.phase == 2) { michael@0: // Sanity check: Download-C must be resumable michael@0: do_check_true(dlC.resumable); michael@0: michael@0: // Check that Download-A is accessible michael@0: expect_download_present(downloadA, downloadASource, michael@0: fileA, downloadAName, false); michael@0: michael@0: // Check that Download-B is not accessible michael@0: expect_download_absent(downloadB, downloadBSource, michael@0: fileB, downloadBName, true); michael@0: michael@0: // Check that Download-C is accessible michael@0: expect_download_present(downloadC, downloadCSource, michael@0: fileC, downloadCName, false); michael@0: michael@0: // only perform these checks the first time that Download-C is started michael@0: this.handledC = true; michael@0: } michael@0: break; michael@0: michael@0: case dm.DOWNLOAD_FINISHED: michael@0: do_check_true(aDownload.targetFile.exists()); michael@0: aDownload.targetFile.remove(false); michael@0: this.onDownloadFinished(); michael@0: break; michael@0: } michael@0: }, michael@0: onStateChange: function(a, b, c, d, e) { }, michael@0: onProgressChange: function(a, b, c, d, e, f, g) { }, michael@0: onSecurityChange: function(a, b, c, d) { }, michael@0: onDownloadFinished: function () { michael@0: switch (this.phase) { michael@0: case 1: { michael@0: do_check_eq(dm.activeDownloadCount, 0); michael@0: michael@0: // Create Download-B michael@0: let dlB = addDownload(httpserv, { michael@0: isPrivate: true, michael@0: targetFile: fileB, michael@0: sourceURI: downloadBSource, michael@0: downloadName: downloadBName, michael@0: runBeforeStart: function (aDownload) { michael@0: // Check that Download-B is retrievable michael@0: do_check_eq(dm.activePrivateDownloadCount, 1); michael@0: do_check_eq(dm.activeDownloadCount, 0); michael@0: do_check_true(is_active_download_available(aDownload.guid, michael@0: downloadBSource, fileB, downloadBName, true)); michael@0: expect_download_present(aDownload.guid, michael@0: downloadBSource, fileB, downloadBName, true); michael@0: } michael@0: }); michael@0: downloadB = dlB.guid; michael@0: michael@0: // wait for Download-B to finish michael@0: ++this.phase; michael@0: } michael@0: break; michael@0: michael@0: case 2: { michael@0: do_check_eq(dm.activeDownloadCount, 0); michael@0: michael@0: // Simulate last private browsing context triggering cleanup michael@0: Services.obs.notifyObservers(null, "last-pb-context-exited", null); michael@0: michael@0: // Create Download-C michael@0: dlC = addDownload(httpserv, { michael@0: isPrivate: false, michael@0: targetFile: fileC, michael@0: sourceURI: downloadCSource, michael@0: downloadName: downloadCName, michael@0: runBeforeStart: function (aDownload) { michael@0: // Check that Download-C is retrievable michael@0: do_check_eq(dm.activePrivateDownloadCount, 0); michael@0: do_check_true(is_active_download_available(aDownload.guid, michael@0: downloadCSource, fileC, downloadCName, false)); michael@0: expect_download_present(aDownload.guid, michael@0: downloadCSource, fileC, downloadCName, false); michael@0: } michael@0: }); michael@0: downloadC = dlC.guid; michael@0: michael@0: // wait for Download-C to finish michael@0: ++this.phase; michael@0: michael@0: // Check that Download-A is accessible michael@0: expect_download_present(downloadA, downloadASource, michael@0: fileA, downloadAName, false); michael@0: michael@0: // Check that Download-B is not accessible michael@0: expect_download_absent(downloadB, downloadBSource, michael@0: fileB, downloadBName, true); michael@0: } michael@0: break; michael@0: michael@0: case 3: { michael@0: do_check_eq(dm.activePrivateDownloadCount, 0); michael@0: michael@0: // Check that Download-A is accessible michael@0: expect_download_present(downloadA, downloadASource, michael@0: fileA, downloadAName, false); michael@0: michael@0: // Check that Download-B is not accessible michael@0: expect_download_absent(downloadB, downloadBSource, michael@0: fileB, downloadBName, true); michael@0: michael@0: // Check that Download-C is accessible michael@0: expect_download_present(downloadC, downloadCSource, michael@0: fileC, downloadCName, false); michael@0: michael@0: // cleanup michael@0: dm.removeListener(this); michael@0: httpserv.stop(do_test_finished); michael@0: } michael@0: break; michael@0: michael@0: default: michael@0: do_throw("Unexpected phase: " + this.phase); michael@0: break; michael@0: } michael@0: } michael@0: }; michael@0: michael@0: dm.addPrivacyAwareListener(listener); michael@0: dm.addPrivacyAwareListener(getDownloadListener()); michael@0: michael@0: // properties of Download-A michael@0: let downloadA = -1; michael@0: const downloadASource = "data:image/png;base64,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"; michael@0: const downloadADest = "download-file-A"; michael@0: const downloadAName = "download-A"; michael@0: michael@0: // properties of Download-B michael@0: let downloadB = -1; michael@0: const downloadBSource = "data:application/octet-stream;base64,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"; michael@0: const downloadBDest = "download-file-B"; michael@0: const downloadBName = "download-B"; michael@0: michael@0: // properties of Download-C michael@0: let downloadC = -1; michael@0: const downloadCSource = "http://localhost:" + michael@0: httpserv.identity.primaryPort + michael@0: "/head_download_manager.js"; michael@0: const downloadCDest = "download-file-C"; michael@0: const downloadCName = "download-C"; michael@0: michael@0: // Create all target files michael@0: let fileA = tmpDir.clone(); michael@0: fileA.append(downloadADest); michael@0: fileA.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); michael@0: let fileB = tmpDir.clone(); michael@0: fileB.append(downloadBDest); michael@0: fileB.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); michael@0: let fileC = tmpDir.clone(); michael@0: fileC.append(downloadCDest); michael@0: fileC.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); michael@0: michael@0: // use js closures to access dlC michael@0: let dlC; michael@0: michael@0: // Create Download-A michael@0: let dlA = addDownload(httpserv, { michael@0: isPrivate: false, michael@0: targetFile: fileA, michael@0: sourceURI: downloadASource, michael@0: downloadName: downloadAName, michael@0: runBeforeStart: function (aDownload) { michael@0: // Check that Download-A is retrievable michael@0: do_check_eq(dm.activePrivateDownloadCount, 0); michael@0: do_check_true(is_active_download_available(aDownload.guid, downloadASource, fileA, downloadAName, false)); michael@0: expect_download_present(aDownload.guid, downloadASource, fileA, downloadAName, false); michael@0: } michael@0: }); michael@0: downloadA = dlA.guid; michael@0: michael@0: // wait for Download-A to finish michael@0: }