tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_rule_insertion.html (9081B)


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