Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<head>
<style>
#light { color-scheme: light }
#dark { color-scheme: dark }
</style>
</head>
<body>
<div id="dynamic-test">
<xul:browser type="content" remote="true" nodefaultsrc="true" class="remote" />
<xul:browser type="content" src="about:blank" class="nonremote" />
</div>
<div id="light">
<xul:browser type="content" remote="true" nodefaultsrc="true" class="remote" />
<xul:browser type="content" src="about:blank" class="nonremote" />
</div>
<div id="dark">
<xul:browser type="content" remote="true" nodefaultsrc="true" class="remote" />
<xul:browser type="content" src="about:blank" class="nonremote" />
</div>
<script><![CDATA[
SimpleTest.requestCompleteLog(); // to help diagnose intermittent bug 1787008
// FIXME: This shouldn't be needed if remote browsers would block the load event.
add_task(async function ensureBrowsersLoaded() {
info("Entering ensureBrowsersLoaded callback");
const triggeringPrincipal = document.nodePrincipal;
for (let b of document.querySelectorAll("browser[remote=true]")) {
let listener;
let loaded = new Promise(resolve => {
info("Entering 'loaded' callback; about to add progress listener");
listener = {
onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
info(`Got state change for ${b.parentNode.id}: ${aStateFlags}, ${aStatus}`);
if (
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP
) {
resolve();
b.removeProgressListener(this);
}
},
// Note: the following "onFoo" callbacks are only here for
// diagnostic purposes, and otherwise aren't relevant to the test.
onProgressChange(aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress) {
info(`Got progress change for ${b.parentNode.id}: ` +
`${aCurSelfProgress}/${aMaxSelfProgress}, ` +
`${aCurTotalProgress}/${aMaxTotalProgress}`);
},
onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
info(`Got location change for ${b.parentNode.id}: ${aLocation.spec}, ${aFlags}`);
},
onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {
info(`Got status change for ${b.parentNode.id}: ${aStatus}, ${aMessage}`);
},
onSecurityChange(aWebProgress, aRequest, aState) {
info(`Got security change for ${b.parentNode.id}: ${aState}`);
},
onContentBlockingEvent(aWebProgress, aRequest, aEvent) {
info(`Got content blocking event for ${b.parentNode.id}: ${aEvent}`);
},
QueryInterface: ChromeUtils.generateQI([
"nsIWebProgressListener",
"nsISupportsWeakReference",
]),
};
b.addProgressListener(listener);
});
info(`Calling b.loadURI for ${b.parentNode.id}`);
// Keep the listener alive, since it's a weak ref otherwise.
window.ALIVE_LISTENER = listener;
b.loadURI(null /*blank*/, { triggeringPrincipal });
await loaded;
delete window.ALIVE_LISTENER;
}
});
async function getBrowserColorScheme(browser) {
return SpecialPowers.spawn(browser, [], () => {
return content.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
});
}
async function tick() {
return new Promise(resolve => {
requestAnimationFrame(() => requestAnimationFrame(resolve));
});
}
async function testElement(id, expectedIfTop, expectedIfNonTop) {
let element = document.getElementById(id);
for (let browser of element.querySelectorAll("browser")) {
let scheme = await getBrowserColorScheme(browser);
let expected = browser.browsingContext.top == browser.browsingContext ? expectedIfTop : expectedIfNonTop;
is(scheme, expected, `${id}: ${browser.className} should be ${expected}`);
}
}
add_task(async function test_browser_color_scheme() {
let current = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
for (let id of ["dynamic-test", "light", "dark"]) {
let expected = id == "dynamic-test" ? current : id;
await testElement(id, expected, expected);
}
});
add_task(async function test_browser_color_scheme_dynamic_style() {
let current = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
let dynamicTest = document.getElementById("dynamic-test");
for (let value of ["light", "dark"]) {
await tick();
dynamicTest.style.colorScheme = value;
await testElement("dynamic-test", value, value);
}
dynamicTest.style.colorScheme = "";
await tick();
});
add_task(async function test_browser_color_scheme_dynamic_system() {
const ACTIVE_THEME_ID = Services.prefs.getCharPref("extensions.activeThemeID");
const DEFAULT_THEME_ID = "default-theme@mozilla.org";
if (ACTIVE_THEME_ID != DEFAULT_THEME_ID) {
info(`skipping test_browser_color_scheme_dynamic_system because the active theme is ${ACTIVE_THEME_ID} instead of ${DEFAULT_THEME_ID}`);
return;
}
for (let dark of [true, false]) {
await SpecialPowers.pushPrefEnv({
set: [
["layout.css.prefers-color-scheme.content-override", 2],
["ui.systemUsesDarkTheme", dark ? 1 : 0],
]
});
await tick();
let expected = dark ? "dark" : "light";
await testElement("dynamic-test", expected, expected);
await SpecialPowers.popPrefEnv();
}
});
]]></script>
</body>
</html>