/** * Tests that chromeFlags are set properly on windows that are * being opened from content. */ // The following are not allowed from web content. // // : { // flag: , // defaults_to: // } const DISALLOWED = { location: { flag: Ci.nsIWebBrowserChrome.CHROME_LOCATIONBAR, defaults_to: true, }, chrome: { flag: Ci.nsIWebBrowserChrome.CHROME_OPENAS_CHROME, defaults_to: false, }, dialog: { flag: Ci.nsIWebBrowserChrome.CHROME_OPENAS_DIALOG, defaults_to: false, }, private: { flag: Ci.nsIWebBrowserChrome.CHROME_PRIVATE_WINDOW, defaults_to: false, }, "non-private": { flag: Ci.nsIWebBrowserChrome.CHROME_NON_PRIVATE_WINDOW, defaults_to: false, }, // "all": // checked manually, since this is an aggregate // flag. // // "remote": // checked manually, since its default value will // depend on whether or not e10s is enabled by default. alwaysLowered: { flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_LOWERED, defaults_to: false, }, "z-lock": { flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_LOWERED, // Renamed to alwaysLowered defaults_to: false, }, alwaysRaised: { flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_RAISED, defaults_to: false, }, alwaysOnTop: { flag: Ci.nsIWebBrowserChrome.CHROME_ALWAYS_ON_TOP, defaults_to: false, }, suppressanimation: { flag: Ci.nsIWebBrowserChrome.CHROME_SUPPRESS_ANIMATION, defaults_to: false, }, extrachrome: { flag: Ci.nsIWebBrowserChrome.CHROME_EXTRA, defaults_to: false, }, centerscreen: { flag: Ci.nsIWebBrowserChrome.CHROME_CENTER_SCREEN, defaults_to: false, }, dependent: { flag: Ci.nsIWebBrowserChrome.CHROME_DEPENDENT, defaults_to: false, }, modal: { flag: Ci.nsIWebBrowserChrome.CHROME_MODAL, defaults_to: false, }, titlebar: { flag: Ci.nsIWebBrowserChrome.CHROME_TITLEBAR, defaults_to: true, }, close: { flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_CLOSE, defaults_to: true, }, resizable: { flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_RESIZE, defaults_to: true, }, status: { flag: Ci.nsIWebBrowserChrome.CHROME_STATUSBAR, defaults_to: true, }, }; // This magic value of 2 means that by default, when content tries // to open a new window, it'll actually open in a new window instead // of a new tab. Services.prefs.setIntPref("browser.link.open_newwindow", 2); registerCleanupFunction(() => { Services.prefs.clearUserPref("browser.link.open_newwindow"); }); /** * Given some nsIDOMWindow for a window running in the parent process, * asynchronously return the nsIWebBrowserChrome chrome flags for the * associated content window. * * @param win (nsIDOMWindow) * @returns int */ function getContentChromeFlags(win) { let b = win.gBrowser.selectedBrowser; return SpecialPowers.spawn(b, [], async function () { // Content scripts provide docShell as a global. /* global docShell */ docShell.QueryInterface(Ci.nsIInterfaceRequestor); try { // This will throw if we're not a remote browser. return docShell .getInterface(Ci.nsIBrowserChild) .QueryInterface(Ci.nsIWebBrowserChrome).chromeFlags; } catch (e) { // This must be a non-remote browser... return docShell.treeOwner.QueryInterface( Ci.nsIWebBrowserChrome ).chromeFlags; } }); } /** * For some chromeFlags, ensures that flags in the DISALLOWED * group were not modified. * * @param chromeFlags (int) * Some chromeFlags to check. */ function assertContentFlags(chromeFlags, isPopup) { for (let feature in DISALLOWED) { let flag = DISALLOWED[feature].flag; Assert.ok(flag, "Expected flag to be a non-zeroish value"); if (DISALLOWED[feature].defaults_to) { // The feature is supposed to default to true, so it should // stay true. Assert.ok( chromeFlags & flag, `Expected feature ${feature} to be unchanged` ); } else { // The feature is supposed to default to false, so it should // stay false. Assert.ok( !(chromeFlags & flag), `Expected feature ${feature} to be unchanged` ); } } } /** * Opens a window from content using window.open with the * features computed from DISALLOWED. The computed feature string attempts to * flip every feature away from their default. */ add_task(async function test_disallowed_flags() { // Construct a features string that flips all DISALLOWED features // to not be their defaults. const DISALLOWED_STRING = Object.keys(DISALLOWED) .map(feature => { let toValue = DISALLOWED[feature].defaults_to ? "no" : "yes"; return `${feature}=${toValue}`; }) .join(","); const FEATURES = [DISALLOWED_STRING].join(","); const SCRIPT_PAGE = `data:text/html,`; const SCRIPT_PAGE_FOR_CHROME_ALL = `data:text/html,`; let newWinPromise = BrowserTestUtils.waitForNewWindow(); await BrowserTestUtils.withNewTab( { gBrowser, url: SCRIPT_PAGE, }, async function (browser) { let win = await newWinPromise; let parentChromeFlags = getParentChromeFlags(win); assertContentFlags(parentChromeFlags); if (win.gMultiProcessBrowser) { Assert.ok( parentChromeFlags & Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW, "Should be remote by default" ); } else { Assert.ok( !(parentChromeFlags & Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW), "Should not be remote by default" ); } // Confusingly, chromeFlags also exist in the content process // as part of the BrowserChild, so we have to check those too. let contentChromeFlags = await getContentChromeFlags(win); assertContentFlags(contentChromeFlags); Assert.equal( parentChromeFlags & Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW, contentChromeFlags & Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW, "Should have matching remote value in parent and content" ); Assert.equal( parentChromeFlags & Ci.nsIWebBrowserChrome.CHROME_FISSION_WINDOW, contentChromeFlags & Ci.nsIWebBrowserChrome.CHROME_FISSION_WINDOW, "Should have matching fission value in parent and content" ); await BrowserTestUtils.closeWindow(win); } ); // We check "all" manually, since that's an aggregate flag // and doesn't fit nicely into the ALLOWED / DISALLOWED scheme newWinPromise = BrowserTestUtils.waitForNewWindow(); await BrowserTestUtils.withNewTab( { gBrowser, url: SCRIPT_PAGE_FOR_CHROME_ALL, }, async function (browser) { let win = await newWinPromise; let parentChromeFlags = getParentChromeFlags(win); Assert.notEqual( parentChromeFlags & Ci.nsIWebBrowserChrome.CHROME_ALL, Ci.nsIWebBrowserChrome.CHROME_ALL, "Should not have been able to set CHROME_ALL" ); await BrowserTestUtils.closeWindow(win); } ); }); /** * Opens a window with some chrome flags specified, which should not affect * scrollbars flag which defaults to true when not disabled explicitly. */ add_task(async function test_scrollbars_flag() { const SCRIPT = 'window.open("about:blank", "_blank", "toolbar=0");'; const SCRIPT_PAGE = `data:text/html,`; let newWinPromise = BrowserTestUtils.waitForNewWindow(); await BrowserTestUtils.withNewTab( { gBrowser, url: SCRIPT_PAGE, }, async function (browser) { let win = await newWinPromise; let parentChromeFlags = getParentChromeFlags(win); Assert.ok( parentChromeFlags & Ci.nsIWebBrowserChrome.CHROME_SCROLLBARS, "Should have scrollbars when not disabled explicitly" ); let contentChromeFlags = await getContentChromeFlags(win); Assert.ok( contentChromeFlags & Ci.nsIWebBrowserChrome.CHROME_SCROLLBARS, "Should have scrollbars when not disabled explicitly" ); await BrowserTestUtils.closeWindow(win); } ); });