|
1 <!DOCTYPE HTML> |
|
2 <html> |
|
3 <!-- |
|
4 https://bugzilla.mozilla.org/show_bug.cgi?id=816720 |
|
5 --> |
|
6 <head> |
|
7 <title>Test for Bug 816720</title> |
|
8 <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
|
9 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> |
|
10 <style type="text/css" id="style"></style> |
|
11 </head> |
|
12 <body> |
|
13 |
|
14 <pre id="test"></pre> |
|
15 |
|
16 <p><span id=control-serif>........</span></p> |
|
17 <p><span id=control-monospace>........</span></p> |
|
18 <p><span id=test-font>........</span></p> |
|
19 |
|
20 <style id=other-styles> |
|
21 #test { font-size: 16px; animation: test 1s both } |
|
22 #control-serif { font: 16px serif } |
|
23 #test-font { font: 16px UnlikelyFontName, serif } |
|
24 </style> |
|
25 |
|
26 <script type="application/javascript"> |
|
27 |
|
28 // Monospace fonts available on all the platforms we're testing on. |
|
29 // |
|
30 // XXX Once bug 817220 is fixed we could instead use the value of |
|
31 // font.name.monospace.x-western as the monospace font to use. |
|
32 var MONOSPACE_FONTS = [ |
|
33 "Courier", |
|
34 "Courier New", |
|
35 "Monaco", |
|
36 "DejaVu Sans Mono", |
|
37 "Droid Sans Mono" |
|
38 ]; |
|
39 |
|
40 var test = document.getElementById("test"); |
|
41 var controlSerif = document.getElementById("control-serif"); |
|
42 var controlMonospace = document.getElementById("control-monospace"); |
|
43 var testFont = document.getElementById("test-font"); |
|
44 var otherStyles = document.getElementById("other-styles"); |
|
45 |
|
46 otherStyles.sheet.insertRule("#control-monospace { font: 16px " + |
|
47 MONOSPACE_FONTS + ", serif }", 0); |
|
48 |
|
49 var monospaceWidth = controlMonospace.getBoundingClientRect().width; |
|
50 var serifWidth = controlSerif.getBoundingClientRect().width; |
|
51 |
|
52 // [at-rule type, passing condition, failing condition] |
|
53 var outerRuleInfo = [ |
|
54 ["@media", "all", "not all"], |
|
55 ["@-moz-document", "url-prefix('')", "url-prefix('zzz')"], |
|
56 ["@supports", "(color: green)", "(unknown: unknown)"] |
|
57 ]; |
|
58 |
|
59 // [rule, function to test whether the rule was successfully inserted and applied] |
|
60 var innerRuleInfo = [ |
|
61 ["#test { text-decoration: underline; }", |
|
62 function(aApplied, aParent, aException) { |
|
63 return !aException && |
|
64 window.getComputedStyle(test, "").textDecoration == |
|
65 (aApplied ? "underline" : "none"); |
|
66 }], |
|
67 ["@page { margin: 4cm; }", |
|
68 function(aApplied, aParent, aException) { |
|
69 // just test whether it threw |
|
70 return !aException; |
|
71 }], |
|
72 ["@keyframes test { from { font-size: 100px; } to { font-size: 100px; } }", |
|
73 function(aApplied, aParent, aException) { |
|
74 return !aException && |
|
75 window.getComputedStyle(test, "").fontSize == |
|
76 (aApplied ? "100px" : "16px") |
|
77 }], |
|
78 ["@font-face { font-family: UnlikelyFontName; src: " + |
|
79 MONOSPACE_FONTS.map(function(s) { return "local('" + s + "')" }).join(", ") + "; }", |
|
80 function(aApplied, aParent, aException) { |
|
81 var width = testFont.getBoundingClientRect().width; |
|
82 if (aException) { |
|
83 return false; |
|
84 } |
|
85 if (navigator.oscpu.match(/Linux/) || |
|
86 navigator.oscpu.match(/Android/) || |
|
87 SpecialPowers.Services.appinfo.name == "B2G") { |
|
88 return true; |
|
89 } |
|
90 return Math.abs(width - (aApplied ? monospaceWidth : serifWidth)) <= 1; // bug 769194 prevents local() |
|
91 // fonts working on Android |
|
92 }], |
|
93 ["@charset 'UTF-8';", |
|
94 function(aApplied, aParent, aException) { |
|
95 // just test whether it threw |
|
96 return aParent instanceof CSSRule ? aException : !aException; |
|
97 }], |
|
98 ["@import url(nothing.css);", |
|
99 function(aApplied, aParent, aException) { |
|
100 // just test whether it threw |
|
101 return aParent instanceof CSSRule ? aException : !aException; |
|
102 }], |
|
103 ["@namespace test url(http://example.org);", |
|
104 function(aApplied, aParent, aException) { |
|
105 // just test whether it threw |
|
106 return aParent instanceof CSSRule ? aException : !aException; |
|
107 }], |
|
108 ]; |
|
109 |
|
110 function runTest() |
|
111 { |
|
112 // First, assert that our assumed available fonts are indeed available |
|
113 // and have expected metrics. |
|
114 ok(monospaceWidth > 0, "monospace text has width"); |
|
115 ok(serifWidth > 0, "serif text has width"); |
|
116 ok(Math.abs(monospaceWidth - serifWidth) > 1, "monospace and serif text have sufficiently different widths"); |
|
117 |
|
118 // And that the #test-font element starts off using the "serif" font. |
|
119 var initialFontTestWidth = testFont.getBoundingClientRect().width; |
|
120 is(initialFontTestWidth, serifWidth); |
|
121 |
|
122 // We construct a style sheet with zero, one or two levels of conditional |
|
123 // grouping rules (taken from outerRuleInfo), with one of the inner rules |
|
124 // at the deepest level. |
|
125 var style = document.getElementById("style"); |
|
126 |
|
127 // For each of the outer rule types... |
|
128 for (var outerRule1 = 0; outerRule1 < outerRuleInfo.length; outerRule1++) { |
|
129 // For each of { 0 = don't create an outer rule, |
|
130 // 1 = create an outer rule with a passing condition, |
|
131 // 2 = create an outer rule with a failing condition }... |
|
132 for (var outerRuleCondition1 = 0; outerRuleCondition1 <= 2; outerRuleCondition1++) { |
|
133 |
|
134 // For each of the outer rule types again... |
|
135 for (var outerRule2 = 0; outerRule2 < outerRuleInfo.length; outerRule2++) { |
|
136 // For each of { 0 = don't create an outer rule, |
|
137 // 1 = create an outer rule with a passing condition, |
|
138 // 2 = create an outer rule with a failing condition } again... |
|
139 for (var outerRuleCondition2 = 0; outerRuleCondition2 <= 2; outerRuleCondition2++) { |
|
140 |
|
141 // For each of the inner rule types... |
|
142 for (var innerRule = 0; innerRule < innerRuleInfo.length; innerRule++) { |
|
143 |
|
144 // Clear rules |
|
145 var object = style.sheet; |
|
146 while (object.cssRules.length) { |
|
147 object.deleteRule(0); |
|
148 } |
|
149 |
|
150 // We'll record whether the inner rule should have been applied, |
|
151 // according to whether we put passing or failing conditional |
|
152 // grouping rules around it. |
|
153 var applied = true; |
|
154 |
|
155 if (outerRuleCondition1) { |
|
156 // Create an outer conditional rule. |
|
157 object.insertRule([outerRuleInfo[outerRule1][0], |
|
158 outerRuleInfo[outerRule1][outerRuleCondition1], |
|
159 "{}"].join(" "), 0); |
|
160 object = object.cssRules[0]; |
|
161 |
|
162 if (outerRuleCondition1 == 2) { |
|
163 // If we used a failing condition, we don't expect the inner |
|
164 // rule to be applied. |
|
165 applied = false; |
|
166 } |
|
167 } |
|
168 |
|
169 if (outerRuleCondition2) { |
|
170 // Create another outer conditional rule as a child of the first |
|
171 // outer conditional rule (or the style sheet, if we didn't create |
|
172 // a first outer conditional rule). |
|
173 object.insertRule([outerRuleInfo[outerRule2][0], |
|
174 outerRuleInfo[outerRule2][outerRuleCondition2], |
|
175 "{}"].join(" "), 0); |
|
176 object = object.cssRules[0]; |
|
177 |
|
178 if (outerRuleCondition2 == 2) { |
|
179 // If we used a failing condition, we don't expect the inner |
|
180 // rule to be applied. |
|
181 applied = false; |
|
182 } |
|
183 } |
|
184 |
|
185 var outer = object instanceof CSSRule ? object.cssText : "style sheet"; |
|
186 var inner = innerRuleInfo[innerRule][0]; |
|
187 |
|
188 // Insert the inner rule. |
|
189 var exception = null; |
|
190 try { |
|
191 object.insertRule(inner, 0); |
|
192 } catch (e) { |
|
193 exception = e; |
|
194 } |
|
195 |
|
196 ok(innerRuleInfo[innerRule][1](applied, object, exception), |
|
197 "<" + [outerRule1, outerRuleCondition1, outerRule2, |
|
198 outerRuleCondition2, innerRule].join(",") + "> " + |
|
199 "inserting " + inner + " into " + outer.replace(/ *\n */g, ' ')); |
|
200 } |
|
201 } |
|
202 } |
|
203 } |
|
204 } |
|
205 |
|
206 SimpleTest.finish(); |
|
207 } |
|
208 |
|
209 SimpleTest.waitForExplicitFinish(); |
|
210 SpecialPowers.pushPrefEnv({ "set": [["layout.css.supports-rule.enabled", true]] }, runTest); |
|
211 |
|
212 </script> |
|
213 </body> |
|
214 </html> |