browser_slow_download.js (4953B)
1 "use strict"; 2 3 // Create a uri for an https site 4 const testPath = getRootDirectory(gTestPath).replace( 5 "chrome://mochitests/content", 6 "https://example.com" 7 ); 8 const TEST_URI = testPath + "file_slow_download.html"; 9 const EXPECTED_DOWNLOAD_URL = 10 "example.com/browser/dom/security/test/https-first/file_slow_download.sjs"; 11 12 // Since the server send the complete download file after 3 seconds we need an longer timeout 13 requestLongerTimeout(4); 14 15 function promisePanelOpened() { 16 if (DownloadsPanel.panel && DownloadsPanel.panel.state == "open") { 17 return Promise.resolve(); 18 } 19 return BrowserTestUtils.waitForEvent(DownloadsPanel.panel, "popupshown"); 20 } 21 22 /** 23 * Waits for a download to finish, in case it has not finished already. 24 * 25 * @param aDownload 26 * The Download object to wait upon. 27 * 28 * @returns {Promise<void>} 29 * Resolves when the download has finished successfully. 30 * @rejects JavaScript exception if the download failed. 31 */ 32 function promiseDownloadStopped(aDownload) { 33 if (!aDownload.stopped) { 34 // The download is in progress, wait for the current attempt to finish and 35 // report any errors that may occur. 36 return aDownload.start(); 37 } 38 39 if (aDownload.succeeded) { 40 return Promise.resolve(); 41 } 42 43 // The download failed or was canceled. 44 return Promise.reject(aDownload.error || new Error("Download canceled.")); 45 } 46 47 // Verifys that no background request was send 48 let requestCounter = 0; 49 function examiner() { 50 SpecialPowers.addObserver(this, "specialpowers-http-notify-request"); 51 } 52 53 examiner.prototype = { 54 observe(subject, topic, data) { 55 if (topic !== "specialpowers-http-notify-request") { 56 return; 57 } 58 // On Android we have other requests appear here as well. Let's make 59 // sure we only evaluate requests triggered by the test. 60 if ( 61 !data.startsWith("http://example.com") && 62 !data.startsWith("https://example.com") 63 ) { 64 return; 65 } 66 ++requestCounter; 67 if (requestCounter == 1) { 68 is(data, TEST_URI, "Download start page is https"); 69 return; 70 } 71 if (requestCounter == 2) { 72 // The specialpowers-http-notify-request fires before the internal redirect( /upgrade) to 73 // https happens. 74 is( 75 data, 76 "http://" + EXPECTED_DOWNLOAD_URL, 77 "First download request is http (internal)" 78 ); 79 return; 80 } 81 if (requestCounter == 3) { 82 is( 83 data, 84 "https://" + EXPECTED_DOWNLOAD_URL, 85 "Download got upgraded to https" 86 ); 87 return; 88 } 89 ok(false, "we should never get here, but just in case"); 90 }, 91 remove() { 92 SpecialPowers.removeObserver(this, "specialpowers-http-notify-request"); 93 }, 94 }; 95 96 // Test description: 97 // 1. Open https://example.com 98 // 2. Start download - location of download is http 99 // 3. https-first upgrades to https 100 // 4. Server send first part of download and after 3 seconds the rest 101 // 5. Complete download of text file 102 add_task(async function test_slow_download() { 103 await SpecialPowers.pushPrefEnv({ 104 set: [["dom.security.https_first", true]], 105 }); 106 107 // remove all previous downloads 108 let downloadsList = await Downloads.getList(Downloads.PUBLIC); 109 await downloadsList.removeFinished(); 110 111 // add observer to ensure that the background request gets canceled for the upgraded Download 112 this.examiner = new examiner(); 113 114 let downloadsPanelPromise = promisePanelOpened(); 115 let downloadsPromise = Downloads.getList(Downloads.PUBLIC); 116 BrowserTestUtils.startLoadingURIString(gBrowser, TEST_URI); 117 // wait for downloadsPanel to open before continuing with test 118 await downloadsPanelPromise; 119 let downloadList = await downloadsPromise; 120 is(DownloadsPanel.isPanelShowing, true, "DownloadsPanel should be open."); 121 is(downloadList._downloads.length, 1, "File should be downloaded."); 122 let [download] = downloadList._downloads; 123 // wait for download to finish (with success or error) 124 await promiseDownloadStopped(download); 125 is(download.contentType, "text/plain", "File contentType should be correct."); 126 // ensure https-first did upgrade the scheme. 127 is( 128 download.source.url, 129 "https://" + EXPECTED_DOWNLOAD_URL, 130 "Scheme should be https." 131 ); 132 // ensure that no background request was send 133 is( 134 requestCounter, 135 3, 136 "three requests total (download page, download http, download https/ upgraded)" 137 ); 138 // ensure that downloaded is complete 139 is(download.target.size, 25, "Download size is correct"); 140 //clean up 141 this.examiner.remove(); 142 info("cleaning up downloads"); 143 try { 144 if (Services.appinfo.OS === "WINNT") { 145 // We need to make the file writable to delete it on Windows. 146 await IOUtils.setPermissions(download.target.path, 0o600); 147 } 148 await IOUtils.remove(download.target.path); 149 } catch (error) { 150 info("The file " + download.target.path + " is not removed, " + error); 151 } 152 153 await downloadList.remove(download); 154 await download.finalize(); 155 });