Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/**
* Tests that chromeFlags are set properly on windows that are
* being opened from content.
*/
// The following are not allowed from web content.
//
// <feature string>: {
// flag: <associated nsIWebBrowserChrome flag>,
// defaults_to: <what this feature defaults to normally>
// }
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.
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) {
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,<script>window.open("about:blank", "_blank", "${FEATURES}");</script>`;
const SCRIPT_PAGE_FOR_CHROME_ALL = `data:text/html,<script>window.open("about:blank", "_blank", "all");</script>`;
let newWinPromise = BrowserTestUtils.waitForNewWindow();
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: SCRIPT_PAGE,
},
async function () {
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 () {
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,<script>${SCRIPT}</script>`;
let newWinPromise = BrowserTestUtils.waitForNewWindow();
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: SCRIPT_PAGE,
},
async function () {
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);
}
);
});