forked from mirrors/gecko-dev
		
	 7810a6da05
			
		
	
	
		7810a6da05
		
	
	
	
	
		
			
			When downloading a file, we check for existing mime types and construct a new one if it's unrecognized. Mime types have a flag, alwaysAskBeforeHandling, that determines whether the unknown content type dialog should be opened before handling the file. Before bug 1733492, the default value for that flag was simply true. Since the new downloads flow is intended to avoid unnecessary steps, the default value was changed to the inverted value of the new downloads panel improvements pref. This patch adds a new pref that the mime info constructor will read in configuring the flag's value. If the improvements pref is not enabled, then the flag will be true, so the UCT dialog will open. If the improvements pref is enabled, then it'll use the value of the new pref. Also add a an interface for the pref to the about:preferences UI, and automatically migrate a false value for browser.download.improvements_to_download_panel to a true value for this pref. I'm updating some tangentially related test files since they happen to be touched slightly by this change. Strictly speaking they would still work, but if the pref value was somehow changed from the default they would fail. Differential Revision: https://phabricator.services.mozilla.com/D143002
		
			
				
	
	
		
			414 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			414 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| 
 | |
| const { E10SUtils } = ChromeUtils.import(
 | |
|   "resource://gre/modules/E10SUtils.jsm"
 | |
| );
 | |
| 
 | |
| const COOP_PREF = "browser.tabs.remote.useCrossOriginOpenerPolicy";
 | |
| 
 | |
| async function setPref() {
 | |
|   await SpecialPowers.pushPrefEnv({
 | |
|     set: [[COOP_PREF, true]],
 | |
|   });
 | |
| }
 | |
| 
 | |
| async function unsetPref() {
 | |
|   await SpecialPowers.pushPrefEnv({
 | |
|     set: [[COOP_PREF, false]],
 | |
|   });
 | |
| }
 | |
| 
 | |
| function httpURL(filename, host = "https://example.com") {
 | |
|   let root = getRootDirectory(gTestPath).replace(
 | |
|     "chrome://mochitests/content",
 | |
|     host
 | |
|   );
 | |
|   return root + filename;
 | |
| }
 | |
| 
 | |
| async function performLoad(browser, opts, action) {
 | |
|   let loadedPromise = BrowserTestUtils.browserStopped(
 | |
|     browser,
 | |
|     opts.url,
 | |
|     opts.maybeErrorPage
 | |
|   );
 | |
|   await action();
 | |
|   await loadedPromise;
 | |
| }
 | |
| 
 | |
| async function test_coop(
 | |
|   start,
 | |
|   target,
 | |
|   expectedProcessSwitch,
 | |
|   startRemoteTypeCheck,
 | |
|   targetRemoteTypeCheck
 | |
| ) {
 | |
|   return BrowserTestUtils.withNewTab(
 | |
|     {
 | |
|       gBrowser,
 | |
|       url: start,
 | |
|       waitForStateStop: true,
 | |
|     },
 | |
|     async function(_browser) {
 | |
|       info(`test_coop: Test tab ready: ${start}`);
 | |
| 
 | |
|       let browser = gBrowser.selectedBrowser;
 | |
|       let firstRemoteType = browser.remoteType;
 | |
|       let firstBC = browser.browsingContext;
 | |
| 
 | |
|       info(`firstBC: ${firstBC.id} remoteType: ${firstRemoteType}`);
 | |
| 
 | |
|       if (startRemoteTypeCheck) {
 | |
|         startRemoteTypeCheck(firstRemoteType);
 | |
|       }
 | |
| 
 | |
|       await performLoad(
 | |
|         browser,
 | |
|         {
 | |
|           url: target,
 | |
|           maybeErrorPage: false,
 | |
|         },
 | |
|         async () => BrowserTestUtils.loadURI(browser, target)
 | |
|       );
 | |
| 
 | |
|       info(`Navigated to: ${target}`);
 | |
|       browser = gBrowser.selectedBrowser;
 | |
|       let secondRemoteType = browser.remoteType;
 | |
|       let secondBC = browser.browsingContext;
 | |
| 
 | |
|       info(`secondBC: ${secondBC.id} remoteType: ${secondRemoteType}`);
 | |
|       if (targetRemoteTypeCheck) {
 | |
|         targetRemoteTypeCheck(secondRemoteType);
 | |
|       }
 | |
|       if (expectedProcessSwitch) {
 | |
|         Assert.notEqual(firstBC.id, secondBC.id, `from: ${start} to ${target}`);
 | |
|       } else {
 | |
|         Assert.equal(firstBC.id, secondBC.id, `from: ${start} to ${target}`);
 | |
|       }
 | |
|     }
 | |
|   );
 | |
| }
 | |
| 
 | |
| function waitForDownloadWindow() {
 | |
|   return new Promise(resolve => {
 | |
|     var listener = {
 | |
|       onOpenWindow: aXULWindow => {
 | |
|         info("Download window shown...");
 | |
|         Services.wm.removeListener(listener);
 | |
| 
 | |
|         function downloadOnLoad() {
 | |
|           domwindow.removeEventListener("load", downloadOnLoad, true);
 | |
| 
 | |
|           is(
 | |
|             domwindow.document.location.href,
 | |
|             "chrome://mozapps/content/downloads/unknownContentType.xhtml",
 | |
|             "Download page appeared"
 | |
|           );
 | |
|           resolve(domwindow);
 | |
|         }
 | |
| 
 | |
|         var domwindow = aXULWindow.docShell.domWindow;
 | |
|         domwindow.addEventListener("load", downloadOnLoad, true);
 | |
|       },
 | |
|       onCloseWindow: aXULWindow => {},
 | |
|     };
 | |
| 
 | |
|     Services.wm.addListener(listener);
 | |
|   });
 | |
| }
 | |
| 
 | |
| async function waitForDownloadUI() {
 | |
|   return BrowserTestUtils.waitForEvent(DownloadsPanel.panel, "popupshown");
 | |
| }
 | |
| 
 | |
| async function cleanupDownloads(downloadList) {
 | |
|   info("cleaning up downloads");
 | |
|   let [download] = await downloadList.getAll();
 | |
|   await downloadList.remove(download);
 | |
|   await download.finalize(true);
 | |
| 
 | |
|   try {
 | |
|     if (Services.appinfo.OS === "WINNT") {
 | |
|       // We need to make the file writable to delete it on Windows.
 | |
|       await IOUtils.setPermissions(download.target.path, 0o600);
 | |
|     }
 | |
|     await IOUtils.remove(download.target.path);
 | |
|   } catch (error) {
 | |
|     info("The file " + download.target.path + " is not removed, " + error);
 | |
|   }
 | |
| 
 | |
|   if (DownloadsPanel.panel.state !== "closed") {
 | |
|     let hiddenPromise = BrowserTestUtils.waitForEvent(
 | |
|       DownloadsPanel.panel,
 | |
|       "popuphidden"
 | |
|     );
 | |
|     DownloadsPanel.hidePanel();
 | |
|     await hiddenPromise;
 | |
|   }
 | |
|   is(
 | |
|     DownloadsPanel.panel.state,
 | |
|     "closed",
 | |
|     "Check that the download panel is closed"
 | |
|   );
 | |
| }
 | |
| 
 | |
| async function test_download_from(initCoop, downloadCoop) {
 | |
|   return BrowserTestUtils.withNewTab("about:blank", async function(_browser) {
 | |
|     info(`test_download: Test tab ready`);
 | |
| 
 | |
|     let start = httpURL(
 | |
|       "coop_header.sjs?downloadPage&coop=" + initCoop,
 | |
|       "https://example.com"
 | |
|     );
 | |
|     await performLoad(
 | |
|       _browser,
 | |
|       {
 | |
|         url: start,
 | |
|         maybeErrorPage: false,
 | |
|       },
 | |
|       async () => {
 | |
|         info(`test_download: Loading download page ${start}`);
 | |
|         return BrowserTestUtils.loadURI(_browser, start);
 | |
|       }
 | |
|     );
 | |
| 
 | |
|     info(`test_download: Download page ready ${start}`);
 | |
|     info(`Downloading ${downloadCoop}`);
 | |
| 
 | |
|     let expectDialog = Services.prefs.getBoolPref(
 | |
|       "browser.download.always_ask_before_handling_new_types",
 | |
|       false
 | |
|     );
 | |
|     let resultPromise = expectDialog
 | |
|       ? waitForDownloadWindow()
 | |
|       : waitForDownloadUI();
 | |
|     let browser = gBrowser.selectedBrowser;
 | |
|     SpecialPowers.spawn(browser, [downloadCoop], downloadCoop => {
 | |
|       content.document.getElementById(downloadCoop).click();
 | |
|     });
 | |
| 
 | |
|     // if the download page doesn't appear, the promise leads a timeout.
 | |
|     if (expectDialog) {
 | |
|       let win = await resultPromise;
 | |
|       await BrowserTestUtils.closeWindow(win);
 | |
|     } else {
 | |
|       // verify link target will get automatically downloaded
 | |
|       await resultPromise;
 | |
|       let downloadList = await Downloads.getList(Downloads.PUBLIC);
 | |
|       is((await downloadList.getAll()).length, 1, "Target was downloaded");
 | |
|       await cleanupDownloads(downloadList);
 | |
|       is((await downloadList.getAll()).length, 0, "Downloads were cleaned up");
 | |
|     }
 | |
|   });
 | |
| }
 | |
| 
 | |
| // Check that multiple navigations of the same tab will only switch processes
 | |
| // when it's expected.
 | |
| add_task(async function test_multiple_nav_process_switches() {
 | |
|   await setPref();
 | |
|   await BrowserTestUtils.withNewTab(
 | |
|     {
 | |
|       gBrowser,
 | |
|       url: httpURL("coop_header.sjs", "https://example.org"),
 | |
|       waitForStateStop: true,
 | |
|     },
 | |
|     async function(browser) {
 | |
|       let prevBC = browser.browsingContext;
 | |
| 
 | |
|       let target = httpURL("coop_header.sjs?.", "https://example.org");
 | |
|       await performLoad(
 | |
|         browser,
 | |
|         {
 | |
|           url: target,
 | |
|           maybeErrorPage: false,
 | |
|         },
 | |
|         async () => BrowserTestUtils.loadURI(browser, target)
 | |
|       );
 | |
| 
 | |
|       Assert.equal(prevBC, browser.browsingContext);
 | |
|       prevBC = browser.browsingContext;
 | |
| 
 | |
|       target = httpURL(
 | |
|         "coop_header.sjs?coop=same-origin",
 | |
|         "https://example.org"
 | |
|       );
 | |
|       await performLoad(
 | |
|         browser,
 | |
|         {
 | |
|           url: target,
 | |
|           maybeErrorPage: false,
 | |
|         },
 | |
|         async () => BrowserTestUtils.loadURI(browser, target)
 | |
|       );
 | |
| 
 | |
|       Assert.notEqual(prevBC, browser.browsingContext);
 | |
|       prevBC = browser.browsingContext;
 | |
| 
 | |
|       target = httpURL(
 | |
|         "coop_header.sjs?coop=same-origin",
 | |
|         "https://example.com"
 | |
|       );
 | |
|       await performLoad(
 | |
|         browser,
 | |
|         {
 | |
|           url: target,
 | |
|           maybeErrorPage: false,
 | |
|         },
 | |
|         async () => BrowserTestUtils.loadURI(browser, target)
 | |
|       );
 | |
| 
 | |
|       Assert.notEqual(prevBC, browser.browsingContext);
 | |
|       prevBC = browser.browsingContext;
 | |
| 
 | |
|       target = httpURL(
 | |
|         "coop_header.sjs?coop=same-origin&index=4",
 | |
|         "https://example.com"
 | |
|       );
 | |
|       await performLoad(
 | |
|         browser,
 | |
|         {
 | |
|           url: target,
 | |
|           maybeErrorPage: false,
 | |
|         },
 | |
|         async () => BrowserTestUtils.loadURI(browser, target)
 | |
|       );
 | |
| 
 | |
|       Assert.equal(prevBC, browser.browsingContext);
 | |
|     }
 | |
|   );
 | |
| });
 | |
| 
 | |
| add_task(async function test_disabled() {
 | |
|   await unsetPref();
 | |
|   await test_coop(
 | |
|     httpURL("coop_header.sjs", "https://example.com"),
 | |
|     httpURL("coop_header.sjs", "https://example.com"),
 | |
|     false
 | |
|   );
 | |
|   await test_coop(
 | |
|     httpURL("coop_header.sjs?coop=same-origin", "http://example.com"),
 | |
|     httpURL("coop_header.sjs", "http://example.com"),
 | |
|     false
 | |
|   );
 | |
|   await test_coop(
 | |
|     httpURL("coop_header.sjs", "http://example.com"),
 | |
|     httpURL("coop_header.sjs?coop=same-origin", "http://example.com"),
 | |
|     false
 | |
|   );
 | |
| });
 | |
| 
 | |
| add_task(async function test_enabled() {
 | |
|   await setPref();
 | |
| 
 | |
|   function checkIsCoopRemoteType(remoteType) {
 | |
|     Assert.ok(
 | |
|       remoteType.startsWith(E10SUtils.WEB_REMOTE_COOP_COEP_TYPE_PREFIX),
 | |
|       `${remoteType} expected to be coop`
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   function checkIsNotCoopRemoteType(remoteType) {
 | |
|     if (gFissionBrowser) {
 | |
|       Assert.ok(
 | |
|         remoteType.startsWith("webIsolated="),
 | |
|         `${remoteType} expected to start with webIsolated=`
 | |
|       );
 | |
|     } else {
 | |
|       Assert.equal(
 | |
|         remoteType,
 | |
|         E10SUtils.WEB_REMOTE_TYPE,
 | |
|         `${remoteType} expected to be web`
 | |
|       );
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   await test_coop(
 | |
|     httpURL("coop_header.sjs", "https://example.com"),
 | |
|     httpURL("coop_header.sjs", "https://example.com"),
 | |
|     false,
 | |
|     checkIsNotCoopRemoteType,
 | |
|     checkIsNotCoopRemoteType
 | |
|   );
 | |
|   await test_coop(
 | |
|     httpURL("coop_header.sjs", "https://example.com"),
 | |
|     httpURL("coop_header.sjs?coop=same-origin", "https://example.org"),
 | |
|     true,
 | |
|     checkIsNotCoopRemoteType,
 | |
|     checkIsNotCoopRemoteType
 | |
|   );
 | |
|   await test_coop(
 | |
|     httpURL("coop_header.sjs?coop=same-origin&index=1", "https://example.com"),
 | |
|     httpURL("coop_header.sjs?coop=same-origin&index=1", "https://example.org"),
 | |
|     true,
 | |
|     checkIsNotCoopRemoteType,
 | |
|     checkIsNotCoopRemoteType
 | |
|   );
 | |
|   await test_coop(
 | |
|     httpURL("coop_header.sjs", "https://example.com"),
 | |
|     httpURL(
 | |
|       "coop_header.sjs?coop=same-origin&coep=require-corp",
 | |
|       "https://example.com"
 | |
|     ),
 | |
|     true,
 | |
|     checkIsNotCoopRemoteType,
 | |
|     checkIsCoopRemoteType
 | |
|   );
 | |
|   await test_coop(
 | |
|     httpURL(
 | |
|       "coop_header.sjs?coop=same-origin&coep=require-corp&index=2",
 | |
|       "https://example.com"
 | |
|     ),
 | |
|     httpURL(
 | |
|       "coop_header.sjs?coop=same-origin&coep=require-corp&index=3",
 | |
|       "https://example.com"
 | |
|     ),
 | |
|     false,
 | |
|     checkIsCoopRemoteType,
 | |
|     checkIsCoopRemoteType
 | |
|   );
 | |
|   await test_coop(
 | |
|     httpURL(
 | |
|       "coop_header.sjs?coop=same-origin&coep=require-corp&index=4",
 | |
|       "https://example.com"
 | |
|     ),
 | |
|     httpURL("coop_header.sjs", "https://example.com"),
 | |
|     true,
 | |
|     checkIsCoopRemoteType,
 | |
|     checkIsNotCoopRemoteType
 | |
|   );
 | |
|   await test_coop(
 | |
|     httpURL(
 | |
|       "coop_header.sjs?coop=same-origin&coep=require-corp&index=5",
 | |
|       "https://example.com"
 | |
|     ),
 | |
|     httpURL(
 | |
|       "coop_header.sjs?coop=same-origin&coep=require-corp&index=6",
 | |
|       "https://example.org"
 | |
|     ),
 | |
|     true,
 | |
|     checkIsCoopRemoteType,
 | |
|     checkIsCoopRemoteType
 | |
|   );
 | |
| });
 | |
| 
 | |
| add_task(async function test_download() {
 | |
|   requestLongerTimeout(4);
 | |
|   await setPref();
 | |
| 
 | |
|   let initCoopArray = ["", "same-origin"];
 | |
| 
 | |
|   let downloadCoopArray = [
 | |
|     "no-coop",
 | |
|     "same-origin",
 | |
|     "same-origin-allow-popups",
 | |
|   ];
 | |
| 
 | |
|   // If the coop mismatch between current page and download link, clicking the
 | |
|   // download link will make the page empty and popup the download window. That
 | |
|   // forces us to reload the page every time.
 | |
|   for (var initCoop of initCoopArray) {
 | |
|     for (var downloadCoop of downloadCoopArray) {
 | |
|       await test_download_from(initCoop, downloadCoop);
 | |
|     }
 | |
|   }
 | |
| });
 |