From 8539e837d43954fc1f66a1dd1eeec446376a3e49 Mon Sep 17 00:00:00 2001 From: Mike Conley Date: Fri, 29 Apr 2016 18:25:11 -0400 Subject: [PATCH] Bug 1261842 - Add a test for chromeflags for new windows from content. r=krizsa MozReview-Commit-ID: Fdbhat4894A --HG-- extra : rebase_source : 516880ddc89a9a6b9c00b87d1b29e790c7861ba5 extra : source : 8d708922e47ac2a5c56a8bceded6a84701536e17 --- .../components/windowwatcher/test/browser.ini | 1 + .../browser_new_content_window_chromeflags.js | 278 ++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 embedding/components/windowwatcher/test/browser_new_content_window_chromeflags.js diff --git a/embedding/components/windowwatcher/test/browser.ini b/embedding/components/windowwatcher/test/browser.ini index adcc498465e9..925b96e341e3 100644 --- a/embedding/components/windowwatcher/test/browser.ini +++ b/embedding/components/windowwatcher/test/browser.ini @@ -1,6 +1,7 @@ [DEFAULT] tags = openwindow +[browser_new_content_window_chromeflags.js] [browser_new_remote_window_flags.js] run-if = e10s [browser_new_content_window_from_chrome_principal.js] diff --git a/embedding/components/windowwatcher/test/browser_new_content_window_chromeflags.js b/embedding/components/windowwatcher/test/browser_new_content_window_chromeflags.js new file mode 100644 index 000000000000..887f86152b7a --- /dev/null +++ b/embedding/components/windowwatcher/test/browser_new_content_window_chromeflags.js @@ -0,0 +1,278 @@ +/** + * Tests that chromeFlags are set properly on windows that are + * being opened from content. + */ + +// The following features set chrome flags on new windows and are +// supported by web content. The schema for each property on this +// object is as follows: +// +// : { +// flag: , +// defaults_to: +// } +const ALLOWED = { + "toolbar": { + flag: Ci.nsIWebBrowserChrome.CHROME_TOOLBAR, + defaults_to: true, + }, + "personalbar": { + flag: Ci.nsIWebBrowserChrome.CHROME_PERSONAL_TOOLBAR, + defaults_to: true, + }, + "menubar": { + flag: Ci.nsIWebBrowserChrome.CHROME_MENUBAR, + defaults_to: true, + }, + "scrollbars": { + flag: Ci.nsIWebBrowserChrome.CHROME_SCROLLBARS, + defaults_to: false, + }, + "minimizable": { + flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_MIN, + defaults_to: true, + }, +}; + +// Construct a features string that flips all ALLOWED features +// to not be their defaults. +const ALLOWED_STRING = Object.keys(ALLOWED).map(feature => { + let toValue = ALLOWED[feature].defaults_to ? "no" : "yes"; + return `${feature}=${toValue}`; +}).join(","); + +// The following are not allowed from web content, at least +// in the default case (since some are disabled by default +// via the dom.disable_window_open_feature pref branch). +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. + "popup": { + flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_POPUP, + defaults_to: false, + }, + "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, + }, + "macsuppressanimation": { + flag: Ci.nsIWebBrowserChrome.CHROME_MAC_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, + }, +}; + +// 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 = [ALLOWED_STRING, DISALLOWED_STRING].join(","); + +const SCRIPT_PAGE = `data:text/html,`; +const SCRIPT_PAGE_FOR_CHROME_ALL = `data:text/html,`; + +// 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, return the nsIWebBrowserChrome chrome flags for + * the associated XUL window. + * + * @param win (nsIDOMWindow) + * Some window in the parent process. + * @returns int + */ +function getParentChromeFlags(win) { + return win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShellTreeItem) + .treeOwner + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIXULWindow) + .chromeFlags; +} + +/** + * For some chromeFlags, ensures that flags that are in the + * ALLOWED group were modified, and that flags in the DISALLOWED + * group were not modified. + * + * @param chromeFlags (int) + * Some chromeFlags to check. + */ +function assertContentFlags(chromeFlags) { + for (let feature in ALLOWED) { + let flag = ALLOWED[feature].flag; + + if (ALLOWED[feature].defaults_to) { + // The feature is supposed to default to true, so we should + // have been able to flip it off. + Assert.ok(!(chromeFlags & flag), + `Expected feature ${feature} to be disabled`); + } else { + // The feature is supposed to default to false, so we should + // have been able to flip it on. + Assert.ok((chromeFlags & flag), + `Expected feature ${feature} to be enabled`); + } + } + + for (let feature in DISALLOWED) { + let flag = DISALLOWED[feature].flag; + 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 ALLOWED and DISALLOWED. The computed + * feature string attempts to flip every feature away from their + * default. + */ +add_task(function* test_new_remote_window_flags() { + let newWinPromise = BrowserTestUtils.waitForNewWindow(); + + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: SCRIPT_PAGE, + }, function*(browser) { + let win = yield 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 TabChild, so we have to check those too. + let b = win.gBrowser.selectedBrowser; + let contentChromeFlags = yield ContentTask.spawn(b, null, function*() { + docShell.QueryInterface(Ci.nsIInterfaceRequestor); + try { + // This will throw if we're not a remote browser. + return docShell.getInterface(Ci.nsITabChild) + .QueryInterface(Ci.nsIWebBrowserChrome) + .chromeFlags; + } catch(e) { + // This must be a non-remote browser... + return docShell.QueryInterface(Ci.nsIDocShellTreeItem) + .treeOwner + .QueryInterface(Ci.nsIWebBrowserChrome) + .chromeFlags; + } + }); + + assertContentFlags(contentChromeFlags); + Assert.ok(!(contentChromeFlags & + Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW), + "Should not be remote in the content process."); + + yield 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(); + + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: SCRIPT_PAGE_FOR_CHROME_ALL, + }, function*(browser) { + let win = yield 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"); + yield BrowserTestUtils.closeWindow(win); + }); +});