diff options
Diffstat (limited to 'layout/style/test/chrome')
27 files changed, 1568 insertions, 0 deletions
diff --git a/layout/style/test/chrome/bug418986-2.js b/layout/style/test/chrome/bug418986-2.js new file mode 100644 index 0000000000..7dbdde2e55 --- /dev/null +++ b/layout/style/test/chrome/bug418986-2.js @@ -0,0 +1,371 @@ +// # Bug 418986, part 2. + +const is_chrome_window = window.location.protocol === "chrome:"; + +const HTML_NS = "http://www.w3.org/1999/xhtml"; + +// Expected values. Format: [name, pref_off_value, pref_on_value] +// If pref_*_value is an array with two values, then we will match +// any value in between those two values. If a value is null, then +// we skip the media query. +var expected_values = [ + ["color", null, 8], + ["color-index", null, 0], + ["aspect-ratio", null, window.innerWidth + "/" + window.innerHeight], + [ + "device-aspect-ratio", + screen.width + "/" + screen.height, + window.innerWidth + "/" + window.innerHeight, + ], + ["device-height", screen.height + "px", window.innerHeight + "px"], + ["device-width", screen.width + "px", window.innerWidth + "px"], + ["grid", null, 0], + ["height", window.innerHeight + "px", window.innerHeight + "px"], + ["monochrome", null, 0], + // Square is defined as portrait: + [ + "orientation", + null, + window.innerWidth > window.innerHeight ? "landscape" : "portrait", + ], + ["resolution", null, "96dpi"], + [ + "resolution", + [ + 0.999 * window.devicePixelRatio + "dppx", + 1.001 * window.devicePixelRatio + "dppx", + ], + "1dppx", + ], + ["width", window.innerWidth + "px", window.innerWidth + "px"], + ["-moz-device-pixel-ratio", window.devicePixelRatio, 1], + [ + "-moz-device-orientation", + screen.width > screen.height ? "landscape" : "portrait", + window.innerWidth > window.innerHeight ? "landscape" : "portrait", + ], +]; + +// These media queries return value 0 or 1 when the pref is off. +// When the pref is on, they should not match. +var suppressed_toggles = [ + "-moz-mac-graphite-theme", + // Not available on most OSs. + // "-moz-maemo-classic", + "-moz-scrollbar-end-backward", + "-moz-scrollbar-end-forward", + "-moz-scrollbar-start-backward", + "-moz-scrollbar-start-forward", + "-moz-scrollbar-thumb-proportional", + "-moz-windows-compositor", + "-moz-windows-default-theme", + "-moz-windows-glass", + "-moz-gtk-csd-available", + "-moz-gtk-csd-hide-titlebar-by-default", + "-moz-gtk-csd-transparent-background", + "-moz-gtk-csd-minimize-button", + "-moz-gtk-csd-maximize-button", + "-moz-gtk-csd-close-button", + "-moz-gtk-csd-reversed-placement", +]; + +var toggles_enabled_in_content = []; + +// Possible values for '-moz-os-version' +var windows_versions = ["windows-win7", "windows-win8", "windows-win10"]; + +// Read the current OS. +var OS = SpecialPowers.Services.appinfo.OS; + +// If we are using Windows, add an extra toggle only +// available on that OS. +if (OS === "WINNT") { + suppressed_toggles.push("-moz-windows-classic"); +} + +// __keyValMatches(key, val)__. +// Runs a media query and returns true if key matches to val. +var keyValMatches = (key, val) => + matchMedia("(" + key + ":" + val + ")").matches; + +// __testMatch(key, val)__. +// Attempts to run a media query match for the given key and value. +// If value is an array of two elements [min max], then matches any +// value in-between. +var testMatch = function(key, val) { + if (val === null) { + return; + } else if (Array.isArray(val)) { + ok( + keyValMatches("min-" + key, val[0]) && + keyValMatches("max-" + key, val[1]), + "Expected " + key + " between " + val[0] + " and " + val[1] + ); + } else { + ok(keyValMatches(key, val), "Expected " + key + ":" + val); + } +}; + +// __testToggles(resisting)__. +// Test whether we are able to match the "toggle" media queries. +var testToggles = function(resisting) { + suppressed_toggles.forEach(function(key) { + var exists = keyValMatches(key, 0) || keyValMatches(key, 1); + if (!toggles_enabled_in_content.includes(key) && !is_chrome_window) { + ok(!exists, key + " should not exist."); + } else { + ok(exists, key + " should exist."); + if (resisting) { + ok( + keyValMatches(key, 0) && !keyValMatches(key, 1), + "Should always match as false" + ); + } + } + }); +}; + +// __testWindowsSpecific__. +// Runs a media query on the queryName with the given possible matching values. +var testWindowsSpecific = function(resisting, queryName, possibleValues) { + let foundValue = null; + possibleValues.forEach(function(val) { + if (keyValMatches(queryName, val)) { + foundValue = val; + } + }); + if (resisting || !is_chrome_window) { + ok(!foundValue, queryName + " should have no match"); + } else { + ok( + foundValue, + foundValue + ? "Match found: '" + queryName + ":" + foundValue + "'" + : "Should have a match for '" + queryName + "'" + ); + } +}; + +// __generateHtmlLines(resisting)__. +// Create a series of div elements that look like: +// `<div class='spoof' id='resolution'>resolution</div>`, +// where each line corresponds to a different media query. +var generateHtmlLines = function(resisting) { + let fragment = document.createDocumentFragment(); + expected_values.forEach(function([key, offVal, onVal]) { + let val = resisting ? onVal : offVal; + if (val) { + let div = document.createElementNS(HTML_NS, "div"); + div.setAttribute("class", "spoof"); + div.setAttribute("id", key); + div.textContent = key; + fragment.appendChild(div); + } + }); + suppressed_toggles.forEach(function(key) { + let div = document.createElementNS(HTML_NS, "div"); + div.setAttribute("class", "suppress"); + div.setAttribute("id", key); + div.textContent = key; + fragment.appendChild(div); + }); + if (OS === "WINNT") { + let div = document.createElementNS(HTML_NS, "div"); + div.setAttribute("class", "windows"); + div.setAttribute("id", "-moz-os-version"); + div.textContent = "-moz-os-version"; + fragment.appendChild(div); + } + return fragment; +}; + +// __cssLine__. +// Creates a line of css that looks something like +// `@media (resolution: 1ppx) { .spoof#resolution { background-color: green; } }`. +var cssLine = function(query, clazz, id, color) { + return ( + "@media " + + query + + " { ." + + clazz + + "#" + + id + + " { background-color: " + + color + + "; } }\n" + ); +}; + +// __constructQuery(key, val)__. +// Creates a CSS media query from key and val. If key is an array of +// two elements, constructs a range query (using min- and max-). +var constructQuery = function(key, val) { + return Array.isArray(val) + ? "(min-" + key + ": " + val[0] + ") and (max-" + key + ": " + val[1] + ")" + : "(" + key + ": " + val + ")"; +}; + +// __mediaQueryCSSLine(key, val, color)__. +// Creates a line containing a CSS media query and a CSS expression. +var mediaQueryCSSLine = function(key, val, color) { + if (val === null) { + return ""; + } + return cssLine(constructQuery(key, val), "spoof", key, color); +}; + +// __suppressedMediaQueryCSSLine(key, color)__. +// Creates a CSS line that matches the existence of a +// media query that is supposed to be suppressed. +var suppressedMediaQueryCSSLine = function(key, color, suppressed) { + let query = "(" + key + ": 0), (" + key + ": 1)"; + return cssLine(query, "suppress", key, color); +}; + +// __generateCSSLines(resisting)__. +// Creates a series of lines of CSS, each of which corresponds to +// a different media query. If the query produces a match to the +// expected value, then the element will be colored green. +var generateCSSLines = function(resisting) { + let lines = ".spoof { background-color: red;}\n"; + expected_values.forEach(function([key, offVal, onVal]) { + lines += mediaQueryCSSLine(key, resisting ? onVal : offVal, "green"); + }); + lines += + ".suppress { background-color: " + (resisting ? "green" : "red") + ";}\n"; + suppressed_toggles.forEach(function(key) { + if ( + !toggles_enabled_in_content.includes(key) && + !resisting && + !is_chrome_window + ) { + lines += "#" + key + " { background-color: green; }\n"; + } else { + lines += suppressedMediaQueryCSSLine(key, "green"); + } + }); + if (OS === "WINNT") { + lines += + ".windows { background-color: " + (resisting ? "green" : "red") + ";}\n"; + lines += + windows_versions.map(val => "(-moz-os-version: " + val + ")").join(", ") + + " { #-moz-os-version { background-color: " + + (resisting ? "red" : "green") + + ";} }\n"; + } + return lines; +}; + +// __green__. +// Returns the computed color style corresponding to green. +var green = "rgb(0, 128, 0)"; + +// __testCSS(resisting)__. +// Creates a series of divs and CSS using media queries to set their +// background color. If all media queries match as expected, then +// all divs should have a green background color. +var testCSS = function(resisting) { + document.getElementById("display").appendChild(generateHtmlLines(resisting)); + document.getElementById("test-css").textContent = generateCSSLines(resisting); + let cssTestDivs = document.querySelectorAll(".spoof,.suppress"); + for (let div of cssTestDivs) { + let color = window.getComputedStyle(div).backgroundColor; + ok(color === green, "CSS for '" + div.id + "'"); + } +}; + +// __testOSXFontSmoothing(resisting)__. +// When fingerprinting resistance is enabled, the `getComputedStyle` +// should always return `undefined` for `MozOSXFontSmoothing`. +var testOSXFontSmoothing = function(resisting) { + let div = document.createElementNS(HTML_NS, "div"); + div.style.MozOsxFontSmoothing = "unset"; + document.documentElement.appendChild(div); + let readBack = window.getComputedStyle(div).MozOsxFontSmoothing; + div.remove(); + let smoothingPref = SpecialPowers.getBoolPref( + "layout.css.osx-font-smoothing.enabled", + false + ); + is( + readBack, + resisting ? "" : smoothingPref ? "auto" : "", + "-moz-osx-font-smoothing" + ); +}; + +// __sleep(timeoutMs)__. +// Returns a promise that resolves after the given timeout. +var sleep = function(timeoutMs) { + return new Promise(function(resolve, reject) { + window.setTimeout(resolve); + }); +}; + +// __testMediaQueriesInPictureElements(resisting)__. +// Test to see if media queries are properly spoofed in picture elements +// when we are resisting fingerprinting. +var testMediaQueriesInPictureElements = async function(resisting) { + let picture = document.createElementNS(HTML_NS, "picture"); + for (let [key, offVal, onVal] of expected_values) { + let expected = resisting ? onVal : offVal; + if (expected) { + let query = constructQuery(key, expected); + + let source = document.createElementNS(HTML_NS, "source"); + source.setAttribute( + "srcset", + "/tests/layout/style/test/chrome/match.png" + ); + source.setAttribute("media", query); + + let image = document.createElementNS(HTML_NS, "img"); + image.setAttribute("title", key + ":" + expected); + image.setAttribute("class", "testImage"); + image.setAttribute("src", "/tests/layout/style/test/chrome/mismatch.png"); + image.setAttribute("alt", key); + + picture.appendChild(source); + picture.appendChild(image); + } + } + document.getElementById("pictures").appendChild(picture); + var testImages = document.getElementsByClassName("testImage"); + await sleep(0); + for (let testImage of testImages) { + ok( + testImage.currentSrc.endsWith("/match.png"), + "Media query '" + testImage.title + "' in picture should match." + ); + } +}; + +// __pushPref(key, value)__. +// Set a pref value asynchronously, returning a promise that resolves +// when it succeeds. +var pushPref = function(key, value) { + return new Promise(function(resolve, reject) { + SpecialPowers.pushPrefEnv({ set: [[key, value]] }, resolve); + }); +}; + +// __test(isContent)__. +// Run all tests. +var test = async function(isContent) { + for (prefValue of [false, true]) { + await pushPref("privacy.resistFingerprinting", prefValue); + let resisting = prefValue && isContent; + expected_values.forEach(function([key, offVal, onVal]) { + testMatch(key, resisting ? onVal : offVal); + }); + testToggles(resisting); + if (OS === "WINNT") { + testWindowsSpecific(resisting, "-moz-os-version", windows_versions); + } + testCSS(resisting); + if (OS === "Darwin") { + testOSXFontSmoothing(resisting); + } + await testMediaQueriesInPictureElements(resisting); + } +}; diff --git a/layout/style/test/chrome/bug535806-css.css b/layout/style/test/chrome/bug535806-css.css new file mode 100644 index 0000000000..bda339f776 --- /dev/null +++ b/layout/style/test/chrome/bug535806-css.css @@ -0,0 +1 @@ +fooBar[fooBar] { color: green; } diff --git a/layout/style/test/chrome/bug535806-html.html b/layout/style/test/chrome/bug535806-html.html new file mode 100644 index 0000000000..e4395da3f3 --- /dev/null +++ b/layout/style/test/chrome/bug535806-html.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html> + <head> + <link rel="stylesheet" type="text/css" href="bug535806-css.css"> + </head> + <body onload="window.parent.wrappedJSObject.htmlLoaded()"> + </body> +</html> diff --git a/layout/style/test/chrome/bug535806-xul.xhtml b/layout/style/test/chrome/bug535806-xul.xhtml new file mode 100644 index 0000000000..3d9a82b91e --- /dev/null +++ b/layout/style/test/chrome/bug535806-xul.xhtml @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="data:text/css,fooBar{color:red;}"?> +<?xml-stylesheet type="text/css" href="bug535806-css.css"?> +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + onload="window.parent.wrappedJSObject.xulLoaded()"> + <fooBar fooBar="" id="s"/> +</window> diff --git a/layout/style/test/chrome/chrome.ini b/layout/style/test/chrome/chrome.ini new file mode 100644 index 0000000000..1aea243298 --- /dev/null +++ b/layout/style/test/chrome/chrome.ini @@ -0,0 +1,29 @@ +[DEFAULT] +skip-if = os == 'android' +support-files = + bug418986-2.js + bug535806-css.css + bug535806-html.html + bug535806-xul.xhtml + hover_helper.html + match.png + mismatch.png + +[test_bug1346623.html] +[test_bug1371453.html] +[test_bug418986-2.xhtml] +[test_bug1157097.html] +[test_bug1160724.xhtml] +[test_bug535806.xhtml] +[test_chrome_only_media_queries.html] +[test_display_mode.html] +support-files = display_mode.html +tags = fullscreen +[test_display_mode_reflow.html] +support-files = display_mode_reflow.html +tags = fullscreen +[test_hover.html] +skip-if = true # bug 1346353 +[test_moz_document_rules.html] +[test_stylesheet_clone_import_rule.html] +support-files = import_useless1.css import_useless2.css diff --git a/layout/style/test/chrome/display_mode.html b/layout/style/test/chrome/display_mode.html new file mode 100644 index 0000000000..0e9724226c --- /dev/null +++ b/layout/style/test/chrome/display_mode.html @@ -0,0 +1,123 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1104916 +--> +<head> + <meta charset="utf-8"> + <title>Test for Display Mode</title> + <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + var imports = [ "SimpleTest", "is", "isnot", "ok" ]; + for (var n of imports) { + window[n] = window.opener.wrappedJSObject[n]; + } + + /** Test for Display Mode **/ + const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); + + function waitOneEvent(element, name) { + return new Promise(function(resolve, reject) { + element.addEventListener(name, function() { + resolve(); + }, {once: true}); + }); + } + + function promiseNextTick() { + return new Promise(resolve => setTimeout(resolve, 0)); + } + + async function test_task() { + var iframe = document.getElementById("subdoc"); + var subdoc = iframe.contentDocument; + var style = subdoc.getElementById("style"); + var bodyComputedStyled = subdoc.defaultView.getComputedStyle(subdoc.body); + var win = Services.wm.getMostRecentWindow("navigator:browser"); + + function queryApplies(q) { + style.setAttribute("media", q); + return bodyComputedStyled.getPropertyValue("text-decoration-line") == + "underline"; + } + + function shouldApply(q) { + ok(queryApplies(q), q + " should apply"); + } + + function shouldNotApply(q) { + ok(!queryApplies(q), q + " should not apply"); + } + + function setDisplayMode(mode) { + window.browsingContext.top.displayMode = mode; + } + + shouldApply("all and (display-mode: browser)"); + shouldNotApply("all and (display-mode: fullscreen)"); + shouldNotApply("all and (display-mode: standalone)"); + shouldNotApply("all and (display-mode: minimal-ui)"); + + // Test entering the OS's fullscreen mode. + var fullScreenEntered = waitOneEvent(win, "sizemodechange"); + synthesizeKey("KEY_F11"); + await fullScreenEntered; + // Wait for the next tick to apply media feature changes. See bug 1430380. + await promiseNextTick(); + shouldApply("all and (display-mode: fullscreen)"); + shouldNotApply("all and (display-mode: browser)"); + var fullScreenExited = waitOneEvent(win, "sizemodechange"); + synthesizeKey("KEY_F11"); + await fullScreenExited; + // Wait for the next tick to apply media feature changes. See bug 1430380. + await promiseNextTick(); + shouldNotApply("all and (display-mode: fullscreen)"); + shouldApply("all and (display-mode: browser)"); + + // Test entering fullscreen through document requestFullScreen. + fullScreenEntered = waitOneEvent(document, "mozfullscreenchange"); + document.body.mozRequestFullScreen(); + await fullScreenEntered + ok(document.mozFullScreenElement, "window entered fullscreen"); + shouldApply("all and (display-mode: fullscreen)"); + shouldNotApply("all and (display-mode: browser)"); + fullScreenExited = waitOneEvent(document, "mozfullscreenchange"); + document.mozCancelFullScreen(); + await fullScreenExited; + ok(!document.mozFullScreenElement, "window exited fullscreen"); + shouldNotApply("all and (display-mode: fullscreen)"); + shouldApply("all and (display-mode: browser)"); + + // Test entering display mode mode through docshell + setDisplayMode("standalone"); + shouldApply("all and (display-mode: standalone)"); + shouldNotApply("all and (display-mode: fullscreen)"); + shouldNotApply("all and (display-mode: browser)"); + shouldNotApply("all and (display-mode: minimal-ui)"); + + // Test that changes in the display mode are reflected + setDisplayMode("minimal-ui"); + shouldApply("all and (display-mode: minimal-ui)"); + shouldNotApply("all and (display-mode: standalone)"); + + // Set the display mode back. + setDisplayMode("browser"); + + window.close(); + window.SimpleTest.finish(); + } + </script> +</head> +<body onload="test_task()"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1104916">Mozilla Bug 1104916</a> +<iframe id="subdoc" src="http://mochi.test:8888/tests/layout/style/test/chrome/media_queries_iframe.html" allowfullscreen></iframe> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/layout/style/test/chrome/display_mode_reflow.html b/layout/style/test/chrome/display_mode_reflow.html new file mode 100644 index 0000000000..ef639d7d57 --- /dev/null +++ b/layout/style/test/chrome/display_mode_reflow.html @@ -0,0 +1,85 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1256084 +--> +<head> + <meta charset="utf-8"> + <title>Test for Display Mode</title> + <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + var imports = [ "SimpleTest", "is", "isnot", "ok" ]; + for (var n of imports) { + window[n] = window.opener.wrappedJSObject[n]; + } + + /** Test for Display Mode **/ + const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); + + function waitOneEvent(element, name) { + return new Promise(function(resolve, reject) { + element.addEventListener(name, function() { + resolve(); + }, {once: true}); + }); + } + + function promiseNextTick() { + return new Promise(resolve => setTimeout(resolve, 0)); + } + + async function test_task() { + var iframe = document.getElementById("subdoc"); + var subdoc = iframe.contentDocument; + var style = subdoc.getElementById("style"); + var bodyComputedStyled = subdoc.defaultView.getComputedStyle(subdoc.body); + var win = Services.wm.getMostRecentWindow("navigator:browser"); + + var secondDiv = subdoc.getElementById("b"); + var offsetTop = secondDiv.offsetTop; + + // Test entering the OS's fullscreen mode. + var fullScreenEntered = waitOneEvent(win, "sizemodechange"); + synthesizeKey("KEY_F11"); + await fullScreenEntered; + + // Wait for the next tick to apply media feature changes. See bug 1430380. + await promiseNextTick(); + ok(offsetTop !== secondDiv.offsetTop, "offset top changes"); + var fullScreenExited = waitOneEvent(win, "sizemodechange"); + synthesizeKey("KEY_F11"); + await fullScreenExited; + + // Wait for the next tick to apply media feature changes. See bug 1430380. + await promiseNextTick(); + ok(offsetTop === secondDiv.offsetTop, "offset top returns to original value"); + + offsetTop = secondDiv.offsetTop; + // Test entering fullscreen through document requestFullScreen. + fullScreenEntered = waitOneEvent(document, "mozfullscreenchange"); + document.body.mozRequestFullScreen(); + await fullScreenEntered + ok(offsetTop !== secondDiv.offsetTop, "offset top changes"); + fullScreenExited = waitOneEvent(document, "mozfullscreenchange"); + document.mozCancelFullScreen(); + await fullScreenExited; + ok(offsetTop === secondDiv.offsetTop, "offset top returns to original value"); + + window.close(); + window.SimpleTest.finish(); + } + </script> +</head> +<body onload="test_task()"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1256084">Mozilla Bug 1256084</a> +<iframe id="subdoc" src="http://mochi.test:8888/tests/layout/style/test/chrome/display_mode_reflow_iframe.html"></iframe> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/layout/style/test/chrome/display_mode_reflow_iframe.html b/layout/style/test/chrome/display_mode_reflow_iframe.html new file mode 100644 index 0000000000..c05880ce7f --- /dev/null +++ b/layout/style/test/chrome/display_mode_reflow_iframe.html @@ -0,0 +1,23 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> +<html lang="en-US"> +<head> + <title>Display Mode Reflow inner frame</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <meta http-equiv="Content-Style-Type" content="text/css"> + <style type="text/css" id="style" media="all"> + div { + border: 2px solid black; + width: 50px; + height: 50px; + } + @media (display-mode: fullscreen) { + #a { height: 100px; } + } + </style> +</head> +<body> + <div id="a"></div> + <div id="b"></div> +</body> +</html> diff --git a/layout/style/test/chrome/hover_empty.html b/layout/style/test/chrome/hover_empty.html new file mode 100644 index 0000000000..7879e1ce9f --- /dev/null +++ b/layout/style/test/chrome/hover_empty.html @@ -0,0 +1,4 @@ +<html> +<body> +</body> +</html> diff --git a/layout/style/test/chrome/hover_helper.html b/layout/style/test/chrome/hover_helper.html new file mode 100644 index 0000000000..b1ae14e8cc --- /dev/null +++ b/layout/style/test/chrome/hover_helper.html @@ -0,0 +1,270 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for :hover</title> + <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> + <style type="text/css"> + + div#one { height: 10px; width: 10px; } + div#one:hover { background: #00f; } + div#one > div { height: 5px; width: 20px; } + div#one > div:hover { background: #f00; } + + div#twoparent { overflow: hidden; height: 20px; } + div#two { width: 10px; height: 10px; } + div#two:hover { margin-left: 5px; background: #0f0; } + div#two + iframe { width: 50px; height: 10px; } + div#two:hover + iframe { width: 100px; } + + </style> +</head> +<!-- need a set timeout because we need things to start after painting suppression ends --> +<body onload="setTimeout(step1, 0)"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a> +<div id="display" style="position: absolute; top: 0; left: 0; width: 300px; height: 300px"> + + <div id="one"><div></div></div> + + <div id="twoparent"> + <div id="two"></div> + <iframe id="twoi" src="hover_empty.html"></iframe> + <div style="width: 5000px; height: 10px;"></div> + </div> + +</div> +<pre id="test"> +<script type="application/javascript"> + +var imports = [ "SimpleTest", "is", "isnot", "ok" ]; +for (var name of imports) { + window[name] = window.opener.wrappedJSObject[name]; +} + +var div = document.getElementById("display"); +var divtwo = document.getElementById("two"); +var iframe = document.getElementById("twoi"); +var divtwoparent = document.getElementById("twoparent"); + +iframe.contentDocument.open(); +iframe.contentDocument.write("<style type='text/css'>html, body { margin: 0; padding: 0; }<\/style><body>"); +iframe.contentDocument.close(); + +var moveEvent = { type: "mousemove", clickCount: "0" }; + +function setResize(str) { + var handler = function() { + iframe.contentWindow.removeEventListener("resize", arguments.callee); + setTimeout(str, 100); + }; + iframe.contentWindow.addEventListener("resize", handler); +} + +function step1() { + /** test basic hover **/ + var divone = document.getElementById("one"); + synthesizeMouse(divone, 5, 7, moveEvent, window); + is(getComputedStyle(divone, "").backgroundColor, "rgb(0, 0, 255)", + ":hover applies"); + is(getComputedStyle(divone.firstChild, "").backgroundColor, "rgba(0, 0, 0, 0)", + ":hover does not apply"); + synthesizeMouse(divone, 5, 2, moveEvent, window); + is(getComputedStyle(divone, "").backgroundColor, "rgb(0, 0, 255)", + ":hover applies hierarchically"); + is(getComputedStyle(divone.firstChild, "").backgroundColor, "rgb(255, 0, 0)", + ":hover applies"); + synthesizeMouse(divone, 15, 7, moveEvent, window); + is(getComputedStyle(divone, "").backgroundColor, "rgba(0, 0, 0, 0)", + ":hover does not apply"); + is(getComputedStyle(divone.firstChild, "").backgroundColor, "rgba(0, 0, 0, 0)", + ":hover does not apply"); + synthesizeMouse(divone, 15, 2, moveEvent, window); + is(getComputedStyle(divone, "").backgroundColor, "rgb(0, 0, 255)", + ":hover applies hierarchically"); + is(getComputedStyle(divone.firstChild, "").backgroundColor, "rgb(255, 0, 0)", + ":hover applies"); + + /** Test for Bug 302561 **/ + setResize("step2();"); + is(iframe.contentDocument.body.offsetWidth, 50, + ":hover does not apply (iframe body width)"); + synthesizeMouse(divtwoparent, 7, 5, moveEvent, window); + is(iframe.contentDocument.body.offsetWidth, 100, + ":hover applies (iframe body width)"); +} + +var step2called = false; +function step2() { + is(step2called, false, "step2 called only once"); + step2called = true; + is(getComputedStyle(divtwo, "").backgroundColor, "rgb(0, 255, 0)", + ":hover applies"); + is(iframe.contentDocument.body.offsetWidth, 100, + ":hover applies (iframe body width)"); + setResize("step3()"); + synthesizeMouse(divtwoparent, 2, 5, moveEvent, window); + is(iframe.contentDocument.body.offsetWidth, 50, + ":hover does not apply (iframe body width)"); +} + +var step3called = false; +function step3() { + is(step3called, false, "step3 called only once"); + step3called = true; + if (getComputedStyle(iframe, "").width == "100px") { + // The two resize events may be coalesced into a single one. + step4(); + return; + } + is(getComputedStyle(divtwo, "").backgroundColor, "rgba(0, 0, 0, 0)", + ":hover does not apply"); + setResize("step4()"); + /* expect to get a second resize from the oscillation */ +} + +var step4called = false; +function step4() { + is(step4called, false, "step4 called only once (more than two cycles of oscillation)"); + if (step4called) + return; + step4called = true; + is(getComputedStyle(divtwo, "").backgroundColor, "rgb(0, 255, 0)", + ":hover applies"); + setTimeout(step5, 500); // time to detect oscillations if they exist +} + +var step5called = false; +function step5() { + is(step5called, false, "step5 called only once"); + step5called = true; + setResize("step6()"); + synthesizeMouse(divtwoparent, 25, 5, moveEvent, window); +} + +var step6called = false; +function step6() { + is(step6called, false, "step6 called only once"); + step6called = true; + is(getComputedStyle(divtwo, "").backgroundColor, "rgba(0, 0, 0, 0)", + ":hover does not apply"); + synthesizeMouse(divtwoparent, 2, 5, moveEvent, window); + setTimeout(step7, 500); // time to detect oscillations if they exist +} + +var step7called = false; +function step7() { + is(step7called, false, "step7 called only once (more than two cycles of oscillation)"); + if (step7called) + return; + step7called = true; + is(getComputedStyle(divtwo, "").backgroundColor, "rgba(0, 0, 0, 0)", + ":hover does not apply"); + setTimeout(step8, 500); // time to detect oscillations if they exist +} + +/* test the same case with scrolltop */ + +var step8called = false; +function step8() { + is(step8called, false, "step8 called only once"); + step8called = true; + iframe.contentDocument.body.removeAttribute("onresize"); + /* move the mouse out of the way */ + synthesizeMouse(divtwoparent, 200, 5, moveEvent, window); + divtwoparent.scrollLeft = 5; + setResize("step9()"); + synthesizeMouse(divtwoparent, 2, 5, moveEvent, window); + /* mouse now over 7, 5 */ +} + +var step9called = false; +function step9() { + is(step9called, false, "step9 called only once"); + step9called = true; + is(getComputedStyle(divtwo, "").backgroundColor, "rgb(0, 255, 0)", + ":hover applies"); + setResize("step10()"); + divtwoparent.scrollLeft = 0; /* mouse now over 2,5 */ +} + +var step10called = false; +function step10() { + is(step10called, false, "step10 called only once"); + step10called = true; + if (getComputedStyle(iframe, "").width == "100px") { + // The two resize events may be coalesced into a single one. + step11(); + return; + } + is(getComputedStyle(divtwo, "").backgroundColor, "rgba(0, 0, 0, 0)", + ":hover does not apply"); + setResize("step11()"); + /* expect to get a second resize from the oscillation */ +} + +var step11called = false; +function step11() { + is(step11called, false, "step11 called only once (more than two cycles of oscillation)"); + if (step11called) + return; + step11called = true; + is(getComputedStyle(divtwo, "").backgroundColor, "rgb(0, 255, 0)", + ":hover applies"); + setTimeout(step12, 500); // time to detect oscillations if they exist +} + +var step12called = false; +function step12() { + is(step12called, false, "step12 called only once"); + step12called = true; + setResize("step13()"); + divtwoparent.scrollLeft = 25; /* mouse now over 27,5 */ +} + +var step13called = false; +function step13() { + is(step13called, false, "step13 called only once"); + step13called = true; + is(getComputedStyle(divtwo, "").backgroundColor, "rgba(0, 0, 0, 0)", + ":hover does not apply"); + setResize("step14()"); + divtwoparent.scrollLeft = 0; /* mouse now over 2,5 */ +} + +var step14called = false; +function step14() { + is(step14called, false, "step14 called only once"); + step14called = true; + if (getComputedStyle(iframe, "").width == "50px") { + // The two resize events may be coalesced into a single one. + step15(); + return; + } + is(getComputedStyle(divtwo, "").backgroundColor, "rgb(0, 255, 0)", + ":hover applies"); + setResize("step15()"); + /* expect to get a second resize from the oscillation */ +} + +var step15called = false; +function step15() { + is(step15called, false, "step15 called only once (more than two cycles of oscillation)"); + if (step15called) + return; + step15called = true; + is(getComputedStyle(divtwo, "").backgroundColor, "rgba(0, 0, 0, 0)", + ":hover does not apply"); + setTimeout(finish, 500); // time to detect oscillations if they exist +} + +function finish() { + document.getElementById("display").style.display = "none"; + + var tester = window.SimpleTest; + window.close(); + tester.finish(); +} + +</script> +</pre> +</body> +</html> diff --git a/layout/style/test/chrome/import_useless1.css b/layout/style/test/chrome/import_useless1.css new file mode 100644 index 0000000000..37e1a3d1d9 --- /dev/null +++ b/layout/style/test/chrome/import_useless1.css @@ -0,0 +1,3 @@ +.unlikely_to_match_anything { + color: black; +} diff --git a/layout/style/test/chrome/import_useless2.css b/layout/style/test/chrome/import_useless2.css new file mode 100644 index 0000000000..37e1a3d1d9 --- /dev/null +++ b/layout/style/test/chrome/import_useless2.css @@ -0,0 +1,3 @@ +.unlikely_to_match_anything { + color: black; +} diff --git a/layout/style/test/chrome/match.png b/layout/style/test/chrome/match.png Binary files differnew file mode 100644 index 0000000000..d3f299bf58 --- /dev/null +++ b/layout/style/test/chrome/match.png diff --git a/layout/style/test/chrome/mismatch.png b/layout/style/test/chrome/mismatch.png Binary files differnew file mode 100644 index 0000000000..8f9da3f00f --- /dev/null +++ b/layout/style/test/chrome/mismatch.png diff --git a/layout/style/test/chrome/moz_document_helper.html b/layout/style/test/chrome/moz_document_helper.html new file mode 100644 index 0000000000..8b331b19e0 --- /dev/null +++ b/layout/style/test/chrome/moz_document_helper.html @@ -0,0 +1,2 @@ +<!DOCTYPE HTML> +<div id="display" style="position: relative"></div> diff --git a/layout/style/test/chrome/test_bug1157097.html b/layout/style/test/chrome/test_bug1157097.html new file mode 100644 index 0000000000..febf4952fb --- /dev/null +++ b/layout/style/test/chrome/test_bug1157097.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>Test for bug 1157097</title> +<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"> +<style> +.blue { color: blue; } +.red { color: red; } +.inline-block { display: inline-block; } +</style> +<body onload=run()> +<p><span id=s1 class=blue><b></b></span><span id=s2 class=red><b></b></span></p> +<script> +function run() { + window.windowUtils.postRestyleSelfEvent(document.querySelector("p")); + document.querySelectorAll("span")[0].className = ""; + document.querySelectorAll("b")[0].className = "inline-block"; + document.querySelectorAll("span")[1].className = "blue"; + window.windowUtils.postRestyleSelfEvent(document.querySelectorAll("b")[1]); + + document.body.offsetTop; + + ok(true, "finished (hopefully we didn't assert)"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +</script> diff --git a/layout/style/test/chrome/test_bug1160724.xhtml b/layout/style/test/chrome/test_bug1160724.xhtml new file mode 100644 index 0000000000..f8140fcb47 --- /dev/null +++ b/layout/style/test/chrome/test_bug1160724.xhtml @@ -0,0 +1,75 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> + +<?xml-stylesheet href="data:text/css,:root{--test:9px}" type="text/css"?> + +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1160724 +--> +<window title="Mozilla Bug 1160724" onload="test()" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1160724" + target="_blank">Mozilla Bug 1160724</a> + </body> + + <script type="application/javascript"> + <![CDATA[ + var errorLogged = false; + const serv = Cc["@mozilla.org/consoleservice;1"] + .getService(Ci.nsIConsoleService); + var listener = { + QueryInterface(iid) { + if (!iid.equals(Ci.nsISupports) && + !iid.equals(Ci.nsIConsoleListener)) { + throw Components.Exception("", Cr.NS_NOINTERFACE); + } + return this; + }, + + observe(msg) { + if (msg.toString().includes("transform")) { + errorLogged = true; + } + } + }; + serv.registerListener(listener); + ]]> + </script> + + <vbox id="w" style="-moz-binding: url(#binding)"> + <vbox id="v" style="display: none; transform: translateY(var(--test));" /> + </vbox> + + <bindings xmlns="http://www.mozilla.org/xbl"> + <binding id="binding"> + <implementation> + <constructor>this.firstChild</constructor> + </implementation> + </binding> + </bindings> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 1160724 **/ + SimpleTest.waitForExplicitFinish(); + + function test() { + var v = document.getElementById("v"); + is(getComputedStyle(v, "").transform, "matrix(1, 0, 0, 1, 0, 9)"); + + // nsIConsoleListeners are notified by a runnable. + setTimeout(() => { + ok(!errorLogged, "Should be no errors"); + serv.unregisterListener(listener); + SimpleTest.finish(); + }) + } + ]]> + </script> +</window> diff --git a/layout/style/test/chrome/test_bug1346623.html b/layout/style/test/chrome/test_bug1346623.html new file mode 100644 index 0000000000..30e21bcc36 --- /dev/null +++ b/layout/style/test/chrome/test_bug1346623.html @@ -0,0 +1,59 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for bug 1346623</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body onload="startTest();"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1346623">Mozilla Bug 1346623</a> +<div id="display"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +var winUtils = window.windowUtils; + +function startTest() { + // load some styles at the agent level + var css = ` + #ac-parent { color: green; } + #ac-child.abc { } + `; + var sheetURL = "data:text/css," + encodeURIComponent(css); + winUtils.loadSheetUsingURIString(sheetURL, winUtils.AGENT_SHEET); + + // add canvas anonymous content + var bq = document.createElement("blockquote"); + bq.id = "ac-parent"; + bq.textContent = "This blockquote text should be green."; + var div = document.createElement("div"); + div.id = "ac-child"; + div.textContent = " This div text should be green."; + bq.appendChild(div); + var ac = document.insertAnonymousContent(bq); + document.body.offsetWidth; + + is(ac.getComputedStylePropertyValue("ac-child", "color"), "rgb(0, 128, 0)", + "color before reframing"); + + // reframe the root + document.documentElement.style.display = "flex"; + document.body.offsetWidth; + + // restyle the div + ac.setAttributeForElement("ac-child", "class", "abc"); + document.body.offsetWidth; + + is(ac.getComputedStylePropertyValue("ac-child", "color"), "rgb(0, 128, 0)", + "color after reframing"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +</script> +</pre> +</body> +</html> diff --git a/layout/style/test/chrome/test_bug1371453.html b/layout/style/test/chrome/test_bug1371453.html new file mode 100644 index 0000000000..dc61d02caf --- /dev/null +++ b/layout/style/test/chrome/test_bug1371453.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Test for Bug 1371453</title> +<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +<link rel="stylesheet" href="data:text/css,{}"> +<body> +<script> +SimpleTest.waitForExplicitFinish(); + +const Cu = SpecialPowers.Components.utils; +const { ContentTaskUtils } = ChromeUtils.import("resource://testing-common/ContentTaskUtils.jsm"); +document.styleSheetChangeEventsEnabled = true; + +onload = runTest; + +async function runTest() { + const sheet = document.getElementsByTagName("link")[1].sheet; + sheet.insertRule('@import url("blahblah")', 0); + + const rule = sheet.cssRules[0]; + is(rule.type, CSSRule.IMPORT_RULE, "Got expected import rule."); + isnot(rule.styleSheet, null, "Import rule contains a stylesheet."); + isnot(rule.media, null, "Import rule contains a media list."); + is(rule.href, "blahblah", "Import rule contains expected href."); + + SimpleTest.finish(); +} + +</script> +</body> +</html> diff --git a/layout/style/test/chrome/test_bug418986-2.xhtml b/layout/style/test/chrome/test_bug418986-2.xhtml new file mode 100644 index 0000000000..152cac004e --- /dev/null +++ b/layout/style/test/chrome/test_bug418986-2.xhtml @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=418986 +--> +<window title="Mozilla Bug 418986" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <style id="test-css" scoped="true"></style> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=418986" + target="_blank">Mozilla Bug 418986</a> + <p id="display"></p> + <p id="pictures"></p> + </body> + + <script type="text/javascript" src="bug418986-2.js"></script> + <!-- test code goes here --> + <script type="text/javascript"> + // Run all tests now. + window.onload = function () { + add_task(async function() { + await test(false); + }); + }; + </script> +</window> diff --git a/layout/style/test/chrome/test_bug535806.xhtml b/layout/style/test/chrome/test_bug535806.xhtml new file mode 100644 index 0000000000..7f4ec286bc --- /dev/null +++ b/layout/style/test/chrome/test_bug535806.xhtml @@ -0,0 +1,43 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=535806 +--> +<window title="Mozilla Bug 535806" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=535806" + target="_blank">Mozilla Bug 535806</a> + </body> + + <iframe id="f"/> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 535806 **/ + SimpleTest.waitForExplicitFinish(); + + window.addEventListener("load", function() { + $("f").setAttribute("src", "bug535806-html.html"); + }); + + function htmlLoaded() { + $("f").setAttribute("src", "bug535806-xul.xhtml"); + } + + function xulLoaded() { + var doc = $("f").contentDocument; + is(doc.defaultView.getComputedStyle(doc.getElementById("s")).color, + "rgb(0, 128, 0)"); + SimpleTest.finish(); + } + + + ]]> + </script> +</window> diff --git a/layout/style/test/chrome/test_chrome_only_media_queries.html b/layout/style/test/chrome/test_chrome_only_media_queries.html new file mode 100644 index 0000000000..9c346076ff --- /dev/null +++ b/layout/style/test/chrome/test_chrome_only_media_queries.html @@ -0,0 +1,80 @@ +<!doctype html> +<title>Test for parsing of non-content-exposed media-queries.</title> +<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> +<style></style> +<script> +const SHEET = document.querySelector('style'); + +function expect(q, shouldBeParseable) { + const NOT_PARSEABLE_TEXT = "@media screen, not all {\n}"; + + let text = "@media screen, " + q + " {\n}"; + SHEET.textContent = text; + + let rules = SHEET.sheet.cssRules; + is(rules.length, 1, `Rule not parsed for ${q}`); + is(rules[0].cssText, + shouldBeParseable ? text : NOT_PARSEABLE_TEXT, + `Serialization for ${q}`); +} + +function expectParseable(q) { + expect(q, true); +} + +function expectNonParseable(q) { + expect(q, false); +} + +// Test a toggle that should always match for `1` or `0`. +function testToggle(toggle) { + expectParseable(`(${toggle})`); + expectParseable(`(${toggle}: 1)`); + expectParseable(`(${toggle}: 0)`); + + expectNonParseable(`(${toggle}: foo)`); + expectNonParseable(`(min-${toggle}: 0)`); + expectNonParseable(`(max-${toggle}: 0)`); + expectNonParseable(`(max-${toggle})`); + expectNonParseable(`(min-${toggle})`); + + let matches_1 = matchMedia(`(${toggle}: 1)`).matches; + let matches_0 = matchMedia(`(${toggle}: 0)`).matches; + isnot(matches_0, matches_1, `Should not match both true and false: ${toggle}`); + is(matches_0 || matches_1, true, `Should match at least one: ${toggle}`); +} + +const TOGGLES = [ + "-moz-is-glyph", + "-moz-print-preview", + "-moz-non-native-content-theme", + "-moz-scrollbar-start-backward", + "-moz-scrollbar-start-forward", + "-moz-scrollbar-end-backward", + "-moz-scrollbar-end-forward", + "-moz-overlay-scrollbars", + "-moz-windows-default-theme", + "-moz-mac-graphite-theme", + "-moz-mac-big-sur-theme", + "-moz-windows-accent-color-in-titlebar", + "-moz-windows-compositor", + "-moz-windows-classic", + "-moz-windows-glass", + "-moz-swipe-animation-enabled", +]; + +for (let i = 0; i < TOGGLES.length; ++i) { + testToggle(TOGGLES[i]) +} + +expectParseable("(-moz-os-version: windows-win7)"); +expectParseable("(-moz-os-version: windows-win8)"); +expectParseable("(-moz-os-version: windows-win10)"); +expectNonParseable("(-moz-os-version: )"); + +expectParseable("(prefers-contrast: more)") +expectParseable("(prefers-contrast: forced)") +expectParseable("(prefers-contrast: no-preference)") +expectParseable("(prefers-contrast: less)"); +expectParseable("(prefers-contrast)") +</script> diff --git a/layout/style/test/chrome/test_display_mode.html b/layout/style/test/chrome/test_display_mode.html new file mode 100644 index 0000000000..69e72d5ab8 --- /dev/null +++ b/layout/style/test/chrome/test_display_mode.html @@ -0,0 +1,39 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1104916 +--> +<head> + <meta charset="utf-8"> + <title>Test for Display Mode</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + SimpleTest.waitForExplicitFinish(); + async function startTest() { + await new Promise(r => { + SpecialPowers.pushPrefEnv( + { + set: [ + ["dom.security.featurePolicy.header.enabled", true], + ["dom.security.featurePolicy.webidl.enabled", true], + ], + }, + r + ); + }); + // Chrome test run tests in iframe, and fullscreen is disabled by default. + // So run the test in a separate window. + window.open("display_mode.html", "display_mode", "width=500,height=500,resizable"); + } + </script> +</head> +<body onload="startTest();"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1104916">Mozilla Bug 1104916</a> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/layout/style/test/chrome/test_display_mode_reflow.html b/layout/style/test/chrome/test_display_mode_reflow.html new file mode 100644 index 0000000000..01022207f3 --- /dev/null +++ b/layout/style/test/chrome/test_display_mode_reflow.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1256084 +--> +<head> + <meta charset="utf-8"> + <title>Test for Display Mode</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + SimpleTest.waitForExplicitFinish(); + async function startTest() { + await new Promise(r => { + SpecialPowers.pushPrefEnv( + { + set: [ + ["dom.security.featurePolicy.header.enabled", true], + ["dom.security.featurePolicy.webidl.enabled", true], + ], + }, + r + ); + }); + // Chrome test run tests in iframe, and fullscreen is disabled by default. + // So run the test in a separate window. + window.open("display_mode_reflow.html", "display_mode_reflow", "width=500,height=500,resizable"); + } + </script> +</head> +<body onload="startTest();"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1256084">Mozilla Bug 1256084</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/layout/style/test/chrome/test_hover.html b/layout/style/test/chrome/test_hover.html new file mode 100644 index 0000000000..019f537e8c --- /dev/null +++ b/layout/style/test/chrome/test_hover.html @@ -0,0 +1,29 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for :hover</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body onload="startTest();"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a> +<div id="display"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +SimpleTest.waitForExplicitFinish(); + +function startTest() { + // Run the test in a separate window so that the parent document doesn't have + // anything that will cause reflows and dispatch synth mouse moves when we don't + // want them and disturb our test. + window.open("hover_helper.html", "hover_helper", "width=200,height=300"); +} + +</script> +</pre> +</body> +</html> diff --git a/layout/style/test/chrome/test_moz_document_rules.html b/layout/style/test/chrome/test_moz_document_rules.html new file mode 100644 index 0000000000..c28fc964ed --- /dev/null +++ b/layout/style/test/chrome/test_moz_document_rules.html @@ -0,0 +1,97 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for @-moz-document rules</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body onload="run()"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=398962">Mozilla Bug 398962</a> +<iframe id="iframe" src="http://mochi.test:8888/tests/layout/style/test/chrome/moz_document_helper.html"></iframe> +<pre id="test"> +<script type="application/javascript"> + +var [gStyleSheetService, gIOService] = (function() { + return [ + Cc["@mozilla.org/content/style-sheet-service;1"] + .getService(Ci.nsIStyleSheetService), + Cc["@mozilla.org/network/io-service;1"] + .getService(Ci.nsIIOService) + ]; +})(); +function set_user_sheet(sheeturi) +{ + var uri = gIOService.newURI(sheeturi); + gStyleSheetService.loadAndRegisterSheet(uri, gStyleSheetService.USER_SHEET); +} +function remove_user_sheet(sheeturi) +{ + var uri = gIOService.newURI(sheeturi); + gStyleSheetService.unregisterSheet(uri, gStyleSheetService.USER_SHEET); +} + +function run() +{ + var iframe = document.getElementById("iframe"); + var subdoc = iframe.contentDocument; + var subwin = iframe.contentWindow; + var cs = subwin.getComputedStyle(subdoc.getElementById("display")); + var zIndexCounter = 0; + + function test_document_rule(urltests, shouldapply) + { + var zIndex = ++zIndexCounter; + var encodedRule = encodeURI("@-moz-document " + urltests + " { ") + + "%23" + // encoded hash character for "#display" + encodeURI("display { z-index: " + zIndex + " } }"); + var sheeturi = "data:text/css," + encodedRule; + set_user_sheet(sheeturi); + if (shouldapply) { + is(cs.zIndex, String(zIndex), + "@-moz-document " + urltests + + " should apply to this document"); + } else { + is(cs.zIndex, "auto", + "@-moz-document " + urltests + + " should NOT apply to this document"); + } + remove_user_sheet(sheeturi); + } + + test_document_rule("domain(mochi.test)", true); + test_document_rule("domain(\"mochi.test\")", true); + test_document_rule("domain('mochi.test')", true); + test_document_rule("domain('test')", true); + test_document_rule("domain(.test)", false); + test_document_rule("domain('.test')", false); + test_document_rule("domain('ochi.test')", false); + test_document_rule("domain(ochi.test)", false); + test_document_rule("url-prefix(http://moch)", true); + test_document_rule("url-prefix(http://och)", false); + test_document_rule("url-prefix(http://mochi.test)", true); + test_document_rule("url-prefix(http://mochi.test:88)", true); + test_document_rule("url-prefix(http://mochi.test:8888)", true); + test_document_rule("url-prefix(http://mochi.test:8888/)", true); + test_document_rule("url-prefix('http://mochi.test:8888/tests/layout/style/test/chrome/moz_document_helper.html')", true); + test_document_rule("url-prefix('http://mochi.test:8888/tests/layout/style/test/chrome/moz_document_helper.htmlx')", false); + test_document_rule("url(http://mochi.test:8888/)", false); + test_document_rule("url('http://mochi.test:8888/tests/layout/style/test/chrome/moz_document_helper.html')", true); + test_document_rule("url('http://mochi.test:8888/tests/layout/style/test/chrome/moz_document_helper.htmlx')", false); + test_document_rule("regexp(.*ochi.*)", false); // syntax error + test_document_rule("regexp('.*ochi.*')", true); + test_document_rule("regexp('ochi.*')", false); + test_document_rule("regexp('.*ochi')", false); + test_document_rule("regexp('http:.*ochi.*')", true); + test_document_rule("regexp('http:.*ochi')", false); + test_document_rule("regexp('http:.*oCHi.*')", false); // case sensitive + + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); + +</script> +</pre> +</body> +</html> diff --git a/layout/style/test/chrome/test_stylesheet_clone_import_rule.html b/layout/style/test/chrome/test_stylesheet_clone_import_rule.html new file mode 100644 index 0000000000..ce2bef8016 --- /dev/null +++ b/layout/style/test/chrome/test_stylesheet_clone_import_rule.html @@ -0,0 +1,86 @@ +<!DOCTYPE html> +<html lang="en-US"> +<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + +<style>div { color: green; }</style> + +<link id="theOnlyLink" rel="stylesheet" type="text/css" href="import_useless1.css"> + +<div id="theOnlyDiv">This text will change colors several times.</div> + +<script> + SimpleTest.waitForExplicitFinish(); + + const Cu = SpecialPowers.Components.utils; + const { ContentTaskUtils } = ChromeUtils.import("resource://testing-common/ContentTaskUtils.jsm"); + + let theOnlyDiv = document.getElementById("theOnlyDiv"); + let link = document.getElementById("theOnlyLink"); + let stylesheet = link.sheet; + + runTest().catch(function(reason) { + ok(false, "Failed with reason: " + reason); + }).then(function() { + SimpleTest.finish(); + }); + + function cssRulesToString(cssRules) { + return Array.from(cssRules).map(rule => rule.cssText).join(''); + } + + async function runTest() { + // Test that the div is initially red (from base.css) + is(getComputedStyle(theOnlyDiv).color, "rgb(0, 128, 0)", "div begins as green."); + + // Insert some import rules. + stylesheet.insertRule('@import url("import_useless2.css")', 0); + stylesheet.insertRule('@import url("import_useless2.css")', 1); + + // Do some sanity checking of our import rules. + let primaryRules = stylesheet.cssRules; + await ContentTaskUtils.waitForCondition(function() { + try { + primaryRules[0].styleSheet.cssRules; + primaryRules[1].styleSheet.cssRules; + return true; + } catch (ex) { + return false; + } + }); + + // Make some helper variables for the comparison tests. + let importSheet1 = primaryRules[0].styleSheet; + let rules1 = importSheet1.cssRules; + + let importSheet2 = primaryRules[1].styleSheet; + let rules2 = importSheet2.cssRules; + + // Confirm that these two sheets are meaningfully the same. + is(cssRulesToString(rules1), cssRulesToString(rules2), "Cloned sheet rules are equivalent."); + + // Add a color-changing rule to the first stylesheet. + importSheet1.insertRule('div { color: blue; }'); + rules1 = importSheet1.cssRules; + + // And make sure that it has an effect. + is(getComputedStyle(theOnlyDiv).color, "rgb(0, 0, 255)", "div becomes blue."); + + // Make sure that the two sheets have different rules now. + isnot(cssRulesToString(rules1), cssRulesToString(rules2), "Cloned sheet rules are no longer equivalent."); + + // Add a color-changing rule to the second stylesheet (that will mask the first). + importSheet2.insertRule('div { color: red; }'); + // And make sure that it has an effect. + is(getComputedStyle(theOnlyDiv).color, "rgb(255, 0, 0)", "div becomes red."); + + // Delete the second sheet by removing the import rule, and make sure the color changes back. + stylesheet.deleteRule(1); + is(getComputedStyle(theOnlyDiv).color, "rgb(0, 0, 255)", "div goes back to blue."); + + // Delete the first sheet by removing the import rule, and make sure the color changes back. + stylesheet.deleteRule(0); + is(getComputedStyle(theOnlyDiv).color, "rgb(0, 128, 0)", "div goes back to green."); + } +</script> +</html> |