tor-browser

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

window_wheel_default_action.html (187342B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <title>Test for default action of WheelEvent</title>
      5  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6  <script src="/tests/SimpleTest/EventUtils.js"></script>
      7  <script src="/tests/SimpleTest/paint_listener.js"></script>
      8  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
      9 </head>
     10 <body>
     11 <p id="display"></p>
     12 <div id="scrollable" style="overflow: auto; width: 200px; height: 200px;">
     13  <div id="clipper" style="margin: 0; padding: 0; overflow: hidden; width: 3000px; height: 3000px;">
     14    <div id="scrolled" style="width: 5000px; height: 5000px;">
     15      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     16      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     17      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     18      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     19      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     20      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     21      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     22      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     23      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     24      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     25      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     26      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     27      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     28      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     29      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     30      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     31      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     32      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     33      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     34      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     35      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     36      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     37      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     38      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     39      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     40      Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text. Tere is a lot of text.<br>
     41    </div>
     42  </div>
     43 </div>
     44 <div id="spacerForBody"></div>
     45 <div id="content" style="display: none">
     46 
     47 </div>
     48 <pre id="test">
     49 <script type="application/javascript">
     50 
     51 // Until the first non-blank paint, the parent will set the opacity of our
     52 // browser to 0 using the 'blank' attribute.
     53 // Until the blank attribute is removed, we can't send scroll events.
     54 SimpleTest.waitForFocus(function() {
     55  let chromeScript = SpecialPowers.loadChromeScript(_ => {
     56    /* eslint-env mozilla/chrome-script */
     57    let win = Services.wm.getMostRecentWindow("navigator:browser");
     58    win.requestAnimationFrame(() => {
     59      win.gBrowser.selectedBrowser.removeAttribute("blank");
     60      win.requestAnimationFrame(() => {
     61        sendAsyncMessage("blank-attribute-removed");
     62      });
     63    });
     64  });
     65  chromeScript.promiseOneMessage("blank-attribute-removed").then(() => {
     66    chromeScript.destroy();
     67    runTests();
     68  });
     69 }, window);
     70 
     71 SimpleTest.requestLongerTimeout(6);
     72 SimpleTest.requestFlakyTimeout("untriaged");
     73 
     74 var winUtils = SpecialPowers.getDOMWindowUtils(window);
     75 // grab refresh driver
     76 winUtils.advanceTimeAndRefresh(100);
     77 
     78 var gScrollableElement = document.getElementById("scrollable");
     79 var gScrolledElement = document.getElementById("scrolled");
     80 var gSpacerForBodyElement = document.getElementById("spacerForBody");
     81 
     82 const kDefaultActionNone                 = 0;
     83 const kDefaultActionScroll               = 1;
     84 const kDefaultActionHistory              = 2;
     85 const kDefaultActionZoom                 = 3;
     86 const kDefaultActionHorizontalizedScroll = 4;
     87 
     88 const kDefaultActionOverrideXNoOverride = -1;
     89 const kDefaultActionOverrideXNone       = kDefaultActionNone;
     90 const kDefaultActionOverrideXScroll     = kDefaultActionScroll;
     91 const kDefaultActionOverrideXHistory    = kDefaultActionHistory;
     92 const kDefaultActionOverrideXZoom       = kDefaultActionZoom;
     93 
     94 // We sometimes rely on the scroll position not getting preserved across tests.
     95 function resetScrollPosition(element) {
     96  element.style.display = "none";
     97  element.offsetTop;
     98  element.style.display = "";
     99 }
    100 
    101 function is()
    102 {
    103  window.opener.is.apply(window.opener, arguments);
    104 }
    105 
    106 function ok()
    107 {
    108  window.opener.ok.apply(window.opener, arguments);
    109 }
    110 
    111 function sendWheelAndWait(aX, aY, aEvent, aCallback)
    112 {
    113  sendWheelAndPaint(gScrollableElement, aX, aY, aEvent, aCallback);
    114 }
    115 
    116 function hitEventLoop(aFunc, aTimes)
    117 {
    118  winUtils.advanceTimeAndRefresh(100);
    119 
    120  if (--aTimes) {
    121    setTimeout(hitEventLoop, 0, aFunc, aTimes);
    122  } else {
    123    setTimeout(aFunc, 20);
    124  }
    125 }
    126 
    127 function onZoomReset(aCallback) {
    128  var fullZoom = SpecialPowers.getFullZoom(window);
    129  if (fullZoom == 1) {
    130    SimpleTest.executeSoon(aCallback);
    131    return;
    132  }
    133  // Zoom causes a resize of the viewport.
    134  window.addEventListener("resize", function onResize(event) {
    135    is(SpecialPowers.getFullZoom(window), 1, "Zoom should be reset to 1");
    136    window.removeEventListener("resize", onResize);
    137    SimpleTest.executeSoon(aCallback);
    138  });
    139 }
    140 
    141 function setDeltaMultiplierSettings(aSettings, aCallback)
    142 {
    143  SpecialPowers.pushPrefEnv({"set": [
    144    ["mousewheel.default.delta_multiplier_x", aSettings.deltaMultiplierX * 100],
    145    ["mousewheel.default.delta_multiplier_y", aSettings.deltaMultiplierY * 100],
    146    ["mousewheel.default.delta_multiplier_z", aSettings.deltaMultiplierZ * 100],
    147    ["mousewheel.with_alt.delta_multiplier_x", aSettings.deltaMultiplierX * 100],
    148    ["mousewheel.with_alt.delta_multiplier_y", aSettings.deltaMultiplierY * 100],
    149    ["mousewheel.with_alt.delta_multiplier_z", aSettings.deltaMultiplierZ * 100],
    150    ["mousewheel.with_control.delta_multiplier_x", aSettings.deltaMultiplierX * 100],
    151    ["mousewheel.with_control.delta_multiplier_y", aSettings.deltaMultiplierY * 100],
    152    ["mousewheel.with_control.delta_multiplier_z", aSettings.deltaMultiplierZ * 100],
    153    ["mousewheel.with_meta.delta_multiplier_x", aSettings.deltaMultiplierX * 100],
    154    ["mousewheel.with_meta.delta_multiplier_y", aSettings.deltaMultiplierY * 100],
    155    ["mousewheel.with_meta.delta_multiplier_z", aSettings.deltaMultiplierZ * 100],
    156    ["mousewheel.with_shift.delta_multiplier_x", aSettings.deltaMultiplierX * 100],
    157    ["mousewheel.with_shift.delta_multiplier_y", aSettings.deltaMultiplierY * 100],
    158    ["mousewheel.with_shift.delta_multiplier_z", aSettings.deltaMultiplierZ * 100],
    159   ]}, aCallback);
    160 }
    161 
    162 function doTestScroll(aSettings, aCallback)
    163 {
    164  const kNoScroll    = 0x00;
    165  const kScrollUp    = 0x01;
    166  const kScrollDown  = 0x02;
    167  const kScrollLeft  = 0x04;
    168  const kScrollRight = 0x08;
    169 
    170  const kTests = [
    171    { description: "Scroll to bottom by pixel scroll even if lineOrPageDelta is 0",
    172      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    173               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
    174               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    175               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    176               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    177      expected: kScrollDown },
    178    { description: "Scroll to bottom by pixel scroll when lineOrPageDelta is 1",
    179      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    180               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
    181               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
    182               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    183               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    184      expected: kScrollDown },
    185    { description: "Scroll to top by pixel scroll even if lineOrPageDelta is 0",
    186      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    187               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
    188               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    189               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    190               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    191      expected: kScrollUp },
    192    { description: "Scroll to top by pixel scroll when lineOrPageDelta is -1",
    193      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    194               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
    195               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
    196               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    197               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    198      expected: kScrollUp },
    199    { description: "Scroll to right by pixel scroll even if lineOrPageDelta is 0",
    200      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    201               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
    202               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    203               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    204               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    205      expected: kScrollRight },
    206    { description: "Scroll to right by pixel scroll when lineOrPageDelta is 1",
    207      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    208               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
    209               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
    210               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    211               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    212      expected: kScrollRight },
    213    { description: "Scroll to left by pixel scroll even if lineOrPageDelta is 0",
    214      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    215               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
    216               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    217               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    218               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    219      expected: kScrollLeft },
    220    { description: "Scroll to left by pixel scroll when lineOrPageDelta is -1",
    221      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    222               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
    223               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
    224               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    225               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    226      expected: kScrollLeft },
    227    { description: "Scroll to bottom-right by pixel scroll",
    228      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    229               deltaX: 8.0, deltaY: 8.0, deltaZ: 0.0,
    230               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    231               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    232               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    233      expected: kScrollDown | kScrollRight },
    234    { description: "Scroll to bottom-left by pixel scroll",
    235      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    236               deltaX: -8.0, deltaY: 8.0, deltaZ: 0.0,
    237               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    238               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    239               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    240      expected: kScrollDown | kScrollLeft },
    241    { description: "Scroll to top-left by pixel scroll",
    242      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    243               deltaX: -8.0, deltaY: -8.0, deltaZ: 0.0,
    244               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    245               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    246               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    247      expected: kScrollUp | kScrollLeft },
    248    { description: "Scroll to top-right by pixel scroll",
    249      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    250               deltaX: 8.0, deltaY: -8.0, deltaZ: 0.0,
    251               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    252               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    253               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    254      expected: kScrollUp | kScrollRight },
    255    { description: "Not Scroll by pixel scroll for z",
    256      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    257               deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
    258               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    259               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    260               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    261      expected: kNoScroll },
    262 
    263    { description: "Scroll to bottom by line scroll even if lineOrPageDelta is 0",
    264      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    265               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
    266               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
    267               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    268               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    269      expected: kScrollDown },
    270    { description: "Scroll to bottom by line scroll when lineOrPageDelta is 1",
    271      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    272               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
    273               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
    274               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    275               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    276      expected: kScrollDown },
    277    { description: "Scroll to top by line scroll even if lineOrPageDelta is 0",
    278      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    279               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
    280               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    281               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    282               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    283      expected: kScrollUp },
    284    { description: "Scroll to top by line scroll when lineOrPageDelta is -1",
    285      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    286               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
    287               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
    288               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    289               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    290      expected: kScrollUp },
    291    { description: "Scroll to right by line scroll even if lineOrPageDelta is 0",
    292      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    293               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
    294               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    295               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    296               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    297      expected: kScrollRight },
    298    { description: "Scroll to right by line scroll when lineOrPageDelta is 1",
    299      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    300               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
    301               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
    302               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    303               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    304      expected: kScrollRight },
    305    { description: "Scroll to left by line scroll even if lineOrPageDelta is 0",
    306      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    307               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
    308               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    309               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    310               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    311      expected: kScrollLeft },
    312    { description: "Scroll to left by line scroll when lineOrPageDelta is -1",
    313      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    314               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
    315               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
    316               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    317               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    318      expected: kScrollLeft },
    319    { description: "Scroll to bottom-right by line scroll",
    320      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    321               deltaX: 0.5, deltaY: 0.5, deltaZ: 0.0,
    322               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    323               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    324               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    325      expected: kScrollDown | kScrollRight },
    326    { description: "Scroll to bottom-left by line scroll",
    327      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    328               deltaX: -0.5, deltaY: 0.5, deltaZ: 0.0,
    329               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    330               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    331               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    332      expected: kScrollDown | kScrollLeft },
    333    { description: "Scroll to top-left by line scroll",
    334      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    335               deltaX: -0.5, deltaY: -0.5, deltaZ: 0.0,
    336               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    337               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    338               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    339      expected: kScrollUp | kScrollLeft },
    340    { description: "Scroll to top-right by line scroll",
    341      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    342               deltaX: 0.5, deltaY: -0.5, deltaZ: 0.0,
    343               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    344               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    345               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    346      expected: kScrollUp | kScrollRight },
    347    { description: "Not Scroll by line scroll for z",
    348      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    349               deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
    350               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    351               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    352               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    353      expected: kNoScroll },
    354 
    355    { description: "Scroll to bottom by page scroll even if lineOrPageDelta is 0",
    356      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    357               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
    358               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
    359               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    360               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    361      expected: kScrollDown },
    362    { description: "Scroll to bottom by page scroll when lineOrPageDelta is 1",
    363      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    364               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
    365               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
    366               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    367               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    368      expected: kScrollDown },
    369    { description: "Scroll to top by page scroll even if lineOrPageDelta is 0",
    370      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    371               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
    372               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    373               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    374               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    375      expected: kScrollUp },
    376    { description: "Scroll to top by page scroll when lineOrPageDelta is -1",
    377      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    378               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
    379               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
    380               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    381               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    382      expected: kScrollUp },
    383    { description: "Scroll to right by page scroll even if lineOrPageDelta is 0",
    384      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    385               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
    386               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    387               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    388               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    389      expected: kScrollRight },
    390    { description: "Scroll to right by page scroll when lineOrPageDelta is 1",
    391      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    392               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
    393               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
    394               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    395               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    396      expected: kScrollRight },
    397    { description: "Scroll to left by page scroll even if lineOrPageDelta is 0",
    398      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    399               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
    400               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    401               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    402               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    403      expected: kScrollLeft },
    404    { description: "Scroll to left by page scroll when lineOrPageDelta is -1",
    405      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    406               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
    407               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
    408               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    409               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    410      expected: kScrollLeft },
    411    { description: "Scroll to bottom-right by page scroll",
    412      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    413               deltaX: 0.5, deltaY: 0.5, deltaZ: 0.0,
    414               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    415               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    416               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    417      expected: kScrollDown | kScrollRight },
    418    { description: "Scroll to bottom-left by page scroll",
    419      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    420               deltaX: -0.5, deltaY: 0.5, deltaZ: 0.0,
    421               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    422               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    423               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    424      expected: kScrollDown | kScrollLeft },
    425    { description: "Scroll to top-left by page scroll",
    426      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    427               deltaX: -0.5, deltaY: -0.5, deltaZ: 0.0,
    428               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    429               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    430               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    431      expected: kScrollUp | kScrollLeft },
    432    { description: "Scroll to top-right by page scroll",
    433      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    434               deltaX: 0.5, deltaY: -0.5, deltaZ: 0.0,
    435               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    436               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    437               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    438      expected: kScrollUp | kScrollRight },
    439    { description: "Not Scroll by page scroll for z",
    440      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    441               deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
    442               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    443               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    444               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    445      expected: kNoScroll },
    446 
    447    // special cases.
    448 
    449    // momentum scroll should cause scroll even if the action is zoom, but if the default action is none,
    450    // shouldn't do it.
    451    { description: "Scroll to bottom by momentum pixel scroll when lineOrPageDelta is 0, even if the action is zoom",
    452      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    453               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
    454               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    455               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    456               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    457      expected: kScrollDown },
    458    { description: "Scroll to bottom by momentum pixel scroll when lineOrPageDelta is 1, even if the action is zoom",
    459      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    460               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
    461               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: true,
    462               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    463               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    464      expected: kScrollDown },
    465    { description: "Scroll to top by momentum pixel scroll when lineOrPageDelta is 0, even if the action is zoom",
    466      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    467               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
    468               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    469               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    470               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    471      expected: kScrollUp },
    472    { description: "Scroll to top by momentum pixel scroll when lineOrPageDelta is -1, even if the action is zoom",
    473      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    474               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
    475               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: true,
    476               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    477               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    478      expected: kScrollUp },
    479    { description: "Scroll to right by momentum pixel scroll when lineOrPageDelta is 0, even if the action is zoom",
    480      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    481               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
    482               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    483               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    484               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    485      expected: kScrollRight },
    486    { description: "Scroll to right by momentum pixel scroll when lineOrPageDelta is 1, even if the action is zoom",
    487      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    488               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
    489               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: true,
    490               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    491               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    492      expected: kScrollRight },
    493    { description: "Scroll to left by momentum pixel scroll when lineOrPageDelta is 0, even if the action is zoom",
    494      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    495               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
    496               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    497               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    498               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    499      expected: kScrollLeft },
    500    { description: "Scroll to left by momentum pixel scroll when lineOrPageDelta is -1, even if the action is zoom",
    501      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    502               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
    503               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: true,
    504               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    505               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    506      expected: kScrollLeft },
    507    { description: "Scroll to bottom-right by momentum pixel scroll even if the action is zoom",
    508      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    509               deltaX: 8.0, deltaY: 8.0, deltaZ: 0.0,
    510               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    511               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    512               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    513      expected: kScrollDown | kScrollRight },
    514    { description: "Scroll to bottom-left by momentum pixel scroll even if the action is zoom",
    515      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    516               deltaX: -8.0, deltaY: 8.0, deltaZ: 0.0,
    517               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    518               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    519               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    520      expected: kScrollDown | kScrollLeft },
    521    { description: "Scroll to top-left by momentum pixel scroll even if the action is zoom",
    522      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    523               deltaX: -8.0, deltaY: -8.0, deltaZ: 0.0,
    524               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    525               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    526               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    527      expected: kScrollUp | kScrollLeft },
    528    { description: "Scroll to top-right by momentum pixel scroll even if the action is zoom",
    529      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    530               deltaX: 8.0, deltaY: -8.0, deltaZ: 0.0,
    531               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    532               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    533               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    534      expected: kScrollUp | kScrollRight },
    535    { description: "Not Scroll by momentum pixel scroll for z (action is zoom)",
    536      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    537               deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
    538               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    539               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    540               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    541      expected: kNoScroll },
    542    { description: "Not Scroll by momentum pixel scroll if default action is none (action is zoom)",
    543      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    544               deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
    545               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    546               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    547               shiftKey: false, ctrlKey: true, altKey: false, metaKey: false },
    548      expected: kNoScroll,
    549      prepare (cb) { SpecialPowers.pushPrefEnv({"set": [["mousewheel.default.action", 0]]}, cb); },
    550      cleanup (cb) { SpecialPowers.pushPrefEnv({"set": [["mousewheel.default.action", 1]]}, cb); } },
    551 
    552    // momentum scroll should cause scroll even if the action is history, but if the default action is none,
    553    // shouldn't do it.
    554    { description: "Scroll to bottom by momentum pixel scroll when lineOrPageDelta is 0, even if the action is history",
    555      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    556               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
    557               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    558               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    559               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    560      expected: kScrollDown },
    561    { description: "Scroll to bottom by momentum pixel scroll when lineOrPageDelta is 1, even if the action is history",
    562      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    563               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
    564               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: true,
    565               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    566               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    567      expected: kScrollDown },
    568    { description: "Scroll to top by momentum pixel scroll when lineOrPageDelta is 0, even if the action is history",
    569      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    570               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
    571               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    572               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    573               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    574      expected: kScrollUp },
    575    { description: "Scroll to top by momentum pixel scroll when lineOrPageDelta is -1, even if the action is history",
    576      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    577               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
    578               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: true,
    579               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    580               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    581      expected: kScrollUp },
    582    { description: "Scroll to right by momentum pixel scroll when lineOrPageDelta is 0, even if the action is history",
    583      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    584               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
    585               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    586               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    587               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    588      expected: kScrollRight },
    589    { description: "Scroll to right by momentum pixel scroll when lineOrPageDelta is 1, even if the action is history",
    590      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    591               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
    592               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: true,
    593               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    594               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    595      expected: kScrollRight },
    596    { description: "Scroll to left by momentum pixel scroll when lineOrPageDelta is 0, even if the action is history",
    597      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    598               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
    599               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    600               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    601               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    602      expected: kScrollLeft },
    603    { description: "Scroll to left by momentum pixel scroll when lineOrPageDelta is -1, even if the action is history",
    604      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    605               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
    606               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: true,
    607               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    608               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    609      expected: kScrollLeft },
    610    { description: "Scroll to bottom-right by momentum pixel scroll even if the action is history",
    611      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    612               deltaX: 8.0, deltaY: 8.0, deltaZ: 0.0,
    613               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    614               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    615               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    616      expected: kScrollDown | kScrollRight },
    617    { description: "Scroll to bottom-left by momentum pixel scroll even if the action is history",
    618      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    619               deltaX: -8.0, deltaY: 8.0, deltaZ: 0.0,
    620               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    621               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    622               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    623      expected: kScrollDown | kScrollLeft },
    624    { description: "Scroll to top-left by momentum pixel scroll even if the action is history",
    625      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    626               deltaX: -8.0, deltaY: -8.0, deltaZ: 0.0,
    627               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    628               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    629               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    630      expected: kScrollUp | kScrollLeft },
    631    { description: "Scroll to top-right by momentum pixel scroll even if the action is history",
    632      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    633               deltaX: 8.0, deltaY: -8.0, deltaZ: 0.0,
    634               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    635               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    636               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    637      expected: kScrollUp | kScrollRight },
    638    { description: "Not Scroll by momentum pixel scroll for z (action is history)",
    639      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    640               deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
    641               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    642               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    643               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    644      expected: kNoScroll },
    645    { description: "Not Scroll by momentum pixel scroll if default action is none (action is history)",
    646      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    647               deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
    648               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
    649               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    650               shiftKey: false, ctrlKey: false, altKey: true, metaKey: false },
    651      expected: kNoScroll,
    652      prepare (cb) { SpecialPowers.pushPrefEnv({"set": [["mousewheel.default.action", 0]]}, cb); },
    653      cleanup (cb) { SpecialPowers.pushPrefEnv({"set": [["mousewheel.default.action", 1]]}, cb); } },
    654 
    655    // Don't scroll along axis whose overflow style is hidden.
    656    { description: "Scroll to only bottom by oblique pixel wheel event with overflow-x: hidden",
    657      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    658               deltaX: 16.0, deltaY: 16.0, deltaZ: 0.0,
    659               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    660               expectedOverflowDeltaX: 1, expectedOverflowDeltaY: 0,
    661               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    662      expected: kScrollDown,
    663      prepare(cb) { gScrollableElement.style.overflowX = "hidden"; cb(); } },
    664    { description: "Scroll to only bottom by oblique line wheel event with overflow-x: hidden",
    665      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    666               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
    667               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    668               expectedOverflowDeltaX: 1, expectedOverflowDeltaY: 0,
    669               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    670      expected: kScrollDown },
    671    { description: "Scroll to only bottom by oblique page wheel event with overflow-x: hidden",
    672      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    673               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
    674               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    675               expectedOverflowDeltaX: 1, expectedOverflowDeltaY: 0,
    676               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    677      expected: kScrollDown },
    678    { description: "Scroll to only top by oblique pixel wheel event with overflow-x: hidden",
    679      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    680               deltaX: -16.0, deltaY: -16.0, deltaZ: 0.0,
    681               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    682               expectedOverflowDeltaX: -1, expectedOverflowDeltaY: 0,
    683               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    684      expected: kScrollUp },
    685    { description: "Scroll to only top by oblique line wheel event with overflow-x: hidden",
    686      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    687               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
    688               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    689               expectedOverflowDeltaX: -1, expectedOverflowDeltaY: 0,
    690               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    691      expected: kScrollUp },
    692    { description: "Scroll to only top by oblique page wheel event with overflow-x: hidden",
    693      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    694               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
    695               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    696               expectedOverflowDeltaX: -1, expectedOverflowDeltaY: 0,
    697               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    698      expected: kScrollUp,
    699      cleanup (cb) { gScrollableElement.style.overflowX = "auto"; cb(); } },
    700    { description: "Scroll to only right by oblique pixel wheel event with overflow-y: hidden",
    701      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    702               deltaX: 16.0, deltaY: 16.0, deltaZ: 0.0,
    703               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    704               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 1,
    705               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    706      expected: kScrollRight,
    707      prepare(cb) { gScrollableElement.style.overflowY = "hidden"; cb(); } },
    708    { description: "Scroll to only right by oblique line wheel event with overflow-y: hidden",
    709      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    710               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
    711               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    712               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 1,
    713               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    714      expected: kScrollRight },
    715    { description: "Scroll to only right by oblique page wheel event with overflow-y: hidden",
    716      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    717               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
    718               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    719               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 1,
    720               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    721      expected: kScrollRight },
    722    { description: "Scroll to only left by oblique pixel wheel event with overflow-y: hidden",
    723      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    724               deltaX: -16.0, deltaY: -16.0, deltaZ: 0.0,
    725               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    726               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: -1,
    727               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    728      expected: kScrollLeft },
    729    { description: "Scroll to only top by oblique line wheel event with overflow-y: hidden",
    730      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    731               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
    732               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    733               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: -1,
    734               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    735      expected: kScrollLeft },
    736    { description: "Scroll to only top by oblique page wheel event with overflow-y: hidden",
    737      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    738               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
    739               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    740               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: -1,
    741               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    742      expected: kScrollLeft,
    743      cleanup (cb) { gScrollableElement.style.overflowY = "auto"; cb(); } },
    744    { description: "Don't be scrolled by oblique pixel wheel event with overflow: hidden",
    745      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    746               deltaX: 16.0, deltaY: 16.0, deltaZ: 0.0,
    747               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    748               expectedOverflowDeltaX: 1, expectedOverflowDeltaY: 1,
    749               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    750      expected: kNoScroll,
    751      prepare(cb) { gScrollableElement.style.overflow = "hidden"; cb(); } },
    752    { description: "Don't be scrolled by oblique line wheel event with overflow: hidden",
    753      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    754               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
    755               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    756               expectedOverflowDeltaX: 1, expectedOverflowDeltaY: 1,
    757               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    758      expected: kNoScroll },
    759    { description: "Don't be scrolled by oblique page wheel event with overflow: hidden",
    760      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    761               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
    762               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    763               expectedOverflowDeltaX: 1, expectedOverflowDeltaY: 1,
    764               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    765      expected: kNoScroll },
    766    { description: "Don't be scrolled by oblique pixel wheel event with overflow: hidden",
    767      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    768               deltaX: -16.0, deltaY: -16.0, deltaZ: 0.0,
    769               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    770               expectedOverflowDeltaX: -1, expectedOverflowDeltaY: -1,
    771               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    772      expected: kNoScroll },
    773    { description: "Don't be scrolled by oblique line wheel event with overflow: hidden",
    774      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    775               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
    776               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    777               expectedOverflowDeltaX: -1, expectedOverflowDeltaY: -1,
    778               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    779      expected: kNoScroll },
    780    { description: "Don't be scrolled by oblique page wheel event with overflow: hidden",
    781      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    782               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
    783               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    784               expectedOverflowDeltaX: -1, expectedOverflowDeltaY: -1,
    785               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    786      expected: kNoScroll,
    787      cleanup (cb) { gScrollableElement.style.overflow = "auto"; cb(); } },
    788 
    789    // Don't scroll along axis whose overflow style is hidden and overflow delta values should
    790    // be zero if there is ancestor scrollable element.
    791    { description: "Scroll to only bottom by oblique pixel wheel event with overflow-x: hidden (body is scrollable)",
    792      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    793               deltaX: 16.0, deltaY: 16.0, deltaZ: 0.0,
    794               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    795               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    796               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    797      expected: kScrollDown,
    798      prepare(cb) {
    799        gScrollableElement.style.overflowX = "hidden";
    800        gScrollableElement.style.position = "fixed";
    801        gScrollableElement.style.top = "30px";
    802        gScrollableElement.style.left = "30px";
    803        // Make body element scrollable.
    804        gSpacerForBodyElement.style.width = "5000px";
    805        gSpacerForBodyElement.style.height = "5000px";
    806        document.documentElement.scrollTop = 500;
    807        document.documentElement.scrollLeft = 500;
    808        cb();
    809      } },
    810    { description: "Scroll to only bottom by oblique line wheel event with overflow-x: hidden (body is scrollable)",
    811      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    812               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
    813               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    814               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    815      expected: kScrollDown },
    816    { description: "Scroll to only bottom by oblique page wheel event with overflow-x: hidden (body is scrollable)",
    817      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    818               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
    819               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    820               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    821               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    822      expected: kScrollDown },
    823    { description: "Scroll to only top by oblique pixel wheel event with overflow-x: hidden (body is scrollable)",
    824      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    825               deltaX: -16.0, deltaY: -16.0, deltaZ: 0.0,
    826               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    827               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    828               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    829      expected: kScrollUp },
    830    { description: "Scroll to only top by oblique line wheel event with overflow-x: hidden (body is scrollable)",
    831      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    832               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
    833               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    834               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    835               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    836      expected: kScrollUp },
    837    { description: "Scroll to only top by oblique page wheel event with overflow-x: hidden (body is scrollable)",
    838      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    839               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
    840               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    841               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    842               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    843      expected: kScrollUp,
    844      cleanup (cb) { gScrollableElement.style.overflowX = "auto"; cb(); } },
    845    { description: "Scroll to only right by oblique pixel wheel event with overflow-y: hidden (body is scrollable)",
    846      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    847               deltaX: 16.0, deltaY: 16.0, deltaZ: 0.0,
    848               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    849               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    850               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    851      expected: kScrollRight,
    852      prepare(cb) { gScrollableElement.style.overflowY = "hidden"; cb(); } },
    853    { description: "Scroll to only right by oblique line wheel event with overflow-y: hidden (body is scrollable)",
    854      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    855               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
    856               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    857               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    858               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    859      expected: kScrollRight },
    860    { description: "Scroll to only right by oblique page wheel event with overflow-y: hidden (body is scrollable)",
    861      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    862               deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
    863               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1,
    864               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    865               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    866      expected: kScrollRight },
    867    { description: "Scroll to only left by oblique pixel wheel event with overflow-y: hidden (body is scrollable)",
    868      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    869               deltaX: -16.0, deltaY: -16.0, deltaZ: 0.0,
    870               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    871               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    872               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    873      expected: kScrollLeft },
    874    { description: "Scroll to only top by oblique line wheel event with overflow-y: hidden (body is scrollable)",
    875      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
    876               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
    877               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    878               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    879               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    880      expected: kScrollLeft },
    881    { description: "Scroll to only top by oblique page wheel event with overflow-y: hidden (body is scrollable)",
    882      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
    883               deltaX: -1.0, deltaY: -1.0, deltaZ: 0.0,
    884               lineOrPageDeltaX: -1, lineOrPageDeltaY: -1,
    885               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    886               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
    887      expected: kScrollLeft,
    888      cleanup (cb) {
    889        gScrollableElement.style.overflowY = "auto";
    890        gScrollableElement.style.position = "static";
    891        gSpacerForBodyElement.style.width = "";
    892        gSpacerForBodyElement.style.height = "";
    893        cb();
    894      } },
    895  ];
    896 
    897  var description;
    898 
    899  var currentTestIndex = -1;
    900  var isXReverted = (aSettings.deltaMultiplierX < 0);
    901  var isYReverted = (aSettings.deltaMultiplierY < 0);
    902 
    903  function doNextTest()
    904  {
    905    if (++currentTestIndex >= kTests.length) {
    906      SimpleTest.executeSoon(aCallback);
    907      return;
    908    }
    909 
    910    gScrollableElement.scrollTop = 1000;
    911    gScrollableElement.scrollLeft = 1000;
    912 
    913    var currentTest = kTests[currentTestIndex];
    914    description = "doTestScroll(aSettings=" + aSettings.description + "), " + currentTest.description + ": ";
    915    if (currentTest.prepare) {
    916      // prepare() can make changes to a page such as
    917      // changing the 'overflow' property which requires
    918      // a repaint to take effect before sending
    919      // scroll-wheel events.
    920      currentTest.prepare(doWaitForPaintsAndScroll);
    921    } else {
    922      doTestCurrentScroll();
    923    }
    924  }
    925 
    926  function doWaitForPaintsAndScroll() {
    927   waitForAllPaintsFlushed(doTestCurrentScroll);
    928  }
    929 
    930  function doTestCurrentScroll() {
    931    var currentTest = kTests[currentTestIndex];
    932    sendWheelAndWait(10, 10, currentTest.event, function () {
    933      if (currentTest.expected == kNoScroll) {
    934        is(gScrollableElement.scrollTop, 1000, description + "scrolled vertical");
    935        is(gScrollableElement.scrollLeft, 1000, description + "scrolled horizontal");
    936      } else {
    937        var scrollUp = !isYReverted ? (currentTest.expected & kScrollUp) :
    938                                      (currentTest.expected & kScrollDown);
    939        var scrollDown = !isYReverted ? (currentTest.expected & kScrollDown) :
    940                                        (currentTest.expected & kScrollUp);
    941        if (scrollUp) {
    942          ok(gScrollableElement.scrollTop < 1000, description + "not scrolled up, got " + gScrollableElement.scrollTop);
    943        } else if (scrollDown) {
    944          ok(gScrollableElement.scrollTop > 1000, description + "not scrolled down, got " + gScrollableElement.scrollTop);
    945        } else {
    946          is(gScrollableElement.scrollTop, 1000, description + "scrolled vertical");
    947        }
    948        var scrollLeft = !isXReverted ? (currentTest.expected & kScrollLeft) :
    949                                        (currentTest.expected & kScrollRight);
    950        var scrollRight = !isXReverted ? (currentTest.expected & kScrollRight) :
    951                                         (currentTest.expected & kScrollLeft);
    952        if (scrollLeft) {
    953          ok(gScrollableElement.scrollLeft < 1000, description + "not scrolled to left, got " + gScrollableElement.scrollLeft);
    954        } else if (scrollRight) {
    955          ok(gScrollableElement.scrollLeft > 1000, description + "not scrolled to right, got " + gScrollableElement.scrollLeft);
    956        } else {
    957          is(gScrollableElement.scrollLeft, 1000, description + "scrolled horizontal");
    958        }
    959      }
    960      if (currentTest.cleanup) {
    961        currentTest.cleanup(nextStep);
    962      } else {
    963        nextStep();
    964      }
    965 
    966      function nextStep() {
    967        winUtils.advanceTimeAndRefresh(100);
    968        doNextTest();
    969      }
    970    });
    971  }
    972  doNextTest();
    973 }
    974 
    975 function doTestHorizontalizedScroll(aSettings, aCallback)
    976 {
    977  const kNoScroll    = 0x00;
    978  const kScrollLeft  = 0x01;
    979  const kScrollRight = 0x02;
    980 
    981  const kTests = [
    982    { description: "Scroll to right by pixel scroll even if lineOrPageDelta is 0",
    983      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    984               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
    985               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
    986               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    987               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
    988      expected: kScrollRight },
    989    { description: "Scroll to right by pixel scroll when lineOrPageDelta is 1",
    990      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    991               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
    992               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
    993               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
    994               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
    995      expected: kScrollRight },
    996    { description: "Scroll to left by pixel scroll even if lineOrPageDelta is 0",
    997      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
    998               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
    999               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1000               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1001               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1002      expected: kScrollLeft },
   1003    { description: "Scroll to left by pixel scroll when lineOrPageDelta is -1",
   1004      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1005               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
   1006               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   1007               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1008               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1009      expected: kScrollLeft },
   1010    { description: "Don't scroll by deltaX (pixel scroll, lineOrPageDelta is 0)",
   1011      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1012               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
   1013               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1014               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1015               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1016      expected: kNoScroll },
   1017    { description: "Don't scroll by deltaX (pixel scroll, lineOrPageDelta is 1)",
   1018      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1019               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
   1020               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   1021               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1022               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1023      expected: kNoScroll },
   1024    { description: "Don't scroll by negative deltaX (pixel scroll, lineOrPageDelta is 0)",
   1025      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1026               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
   1027               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1028               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1029               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1030      expected: kNoScroll },
   1031    { description: "Don't scroll by negative deltaX (pixel scroll, lineOrPageDelta is -1)",
   1032      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1033               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
   1034               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   1035               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1036               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1037      expected: kNoScroll },
   1038    { description: "Scroll only to right by diagonal pixel scroll (to bottom-right)",
   1039      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1040               deltaX: 8.0, deltaY: 8.0, deltaZ: 0.0,
   1041               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1042               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1043               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1044      expected: kScrollRight },
   1045    { description: "Scroll only to right by diagonal pixel scroll (to bottom-left)",
   1046      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1047               deltaX: -8.0, deltaY: 8.0, deltaZ: 0.0,
   1048               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1049               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1050               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1051      expected: kScrollRight },
   1052    { description: "Scroll only to left by diagonal pixel scroll (to top-left)",
   1053      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1054               deltaX: -8.0, deltaY: -8.0, deltaZ: 0.0,
   1055               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1056               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1057               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1058      expected: kScrollLeft },
   1059    { description: "Scroll only to left by pixel scroll (to bottom-right)",
   1060      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1061               deltaX: 8.0, deltaY: -8.0, deltaZ: 0.0,
   1062               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1063               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1064               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1065      expected: kScrollLeft },
   1066    { description: "Don't scroll by pixel scroll for z-axis",
   1067      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1068               deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
   1069               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1070               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1071               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1072      expected: kNoScroll },
   1073 
   1074    { description: "Scroll to right by line scroll even if lineOrPageDelta is 0",
   1075      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1076               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   1077               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   1078               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1079               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1080      expected: kScrollRight },
   1081    { description: "Scroll to right by line scroll when lineOrPageDelta is 1",
   1082      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1083               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   1084               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   1085               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1086               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1087      expected: kScrollRight },
   1088    { description: "Scroll to left by line scroll even if lineOrPageDelta is 0",
   1089      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1090               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   1091               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1092               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1093               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1094      expected: kScrollLeft },
   1095    { description: "Scroll to left by line scroll when lineOrPageDelta is -1",
   1096      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1097               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   1098               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   1099               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1100               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1101      expected: kScrollLeft },
   1102    { description: "Don't scroll by deltaX (line scroll, lineOrPageDelta is 0)",
   1103      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1104               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   1105               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1106               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1107               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1108      expected: kNoScroll },
   1109    { description: "Don't scroll by deltaX (line scroll, lineOrPageDelta is 1)",
   1110      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1111               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   1112               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   1113               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1114               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1115      expected: kNoScroll },
   1116    { description: "Don't scroll by negative deltaX (line scroll, lineOrPageDelta is 0)",
   1117      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1118               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   1119               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1120               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1121               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1122      expected: kNoScroll },
   1123    { description: "Don't scroll by negative deltaY (line scroll, lineOrPageDelta is -1)",
   1124      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1125               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   1126               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   1127               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1128               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1129      expected: kNoScroll },
   1130    { description: "Scroll only to right by diagonal line scroll (to bottom-right)",
   1131      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1132               deltaX: 0.5, deltaY: 0.5, deltaZ: 0.0,
   1133               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1134               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1135               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1136      expected: kScrollRight },
   1137    { description: "Scroll only to right by diagonal line scroll (to bottom-left)",
   1138      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1139               deltaX: -0.5, deltaY: 0.5, deltaZ: 0.0,
   1140               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1141               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1142               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1143      expected: kScrollRight },
   1144    { description: "Scroll only to left by diagonal line scroll (to top-left)",
   1145      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1146               deltaX: -0.5, deltaY: -0.5, deltaZ: 0.0,
   1147               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1148               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1149               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1150      expected: kScrollLeft },
   1151    { description: "Scroll only to left by line scroll (to top-right)",
   1152      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1153               deltaX: 0.5, deltaY: -0.5, deltaZ: 0.0,
   1154               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1155               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1156               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1157      expected: kScrollLeft },
   1158    { description: "Don't scroll by line scroll for z-axis",
   1159      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1160               deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
   1161               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1162               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1163               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1164      expected: kNoScroll },
   1165 
   1166    { description: "Scroll to right by page scroll even if lineOrPageDelta is 0",
   1167      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1168               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   1169               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   1170               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1171               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1172      expected: kScrollRight },
   1173    { description: "Scroll to right by page scroll when lineOrPageDelta is 1",
   1174      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1175               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   1176               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   1177               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1178               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1179      expected: kScrollRight },
   1180    { description: "Scroll to left by page scroll even if lineOrPageDelta is 0",
   1181      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1182               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   1183               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1184               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1185               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1186      expected: kScrollLeft },
   1187    { description: "Scroll to left by page scroll when lineOrPageDelta is -1",
   1188      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1189               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   1190               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   1191               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1192               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1193      expected: kScrollLeft },
   1194    { description: "Don't scroll by deltaX (page scroll, lineOrPageDelta is 0)",
   1195      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1196               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   1197               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1198               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1199               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1200      expected: kNoScroll },
   1201    { description: "Don't scroll by deltaX (page scroll, lineOrPageDelta is 1)",
   1202      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1203               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   1204               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   1205               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1206               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1207      expected: kNoScroll },
   1208    { description: "Don't scroll by deltaX (page scroll, lineOrPageDelta is 0)",
   1209      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1210               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   1211               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1212               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1213               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1214      expected: kNoScroll },
   1215    { description: "Don't scroll by deltaX (page scroll, lineOrPageDelta is -1)",
   1216      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1217               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   1218               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   1219               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1220               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1221      expected: kNoScroll },
   1222    { description: "Scroll only to right by diagonal page scroll (to bottom-right)",
   1223      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1224               deltaX: 0.5, deltaY: 0.5, deltaZ: 0.0,
   1225               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1226               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1227               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1228      expected: kScrollRight },
   1229    { description: "Scroll only to right by diagonal page scroll (to bottom-left)",
   1230      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1231               deltaX: -0.5, deltaY: 0.5, deltaZ: 0.0,
   1232               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1233               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1234               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1235      expected: kScrollRight },
   1236    { description: "Scroll only to left by diagonal page scroll (to top-left)",
   1237      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1238               deltaX: -0.5, deltaY: -0.5, deltaZ: 0.0,
   1239               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1240               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1241               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1242      expected: kScrollLeft },
   1243    { description: "Scroll only to left by diagonal page scroll (to top-right)",
   1244      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1245               deltaX: 0.5, deltaY: -0.5, deltaZ: 0.0,
   1246               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1247               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1248               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1249      expected: kScrollLeft },
   1250    { description: "Don't scroll by page scroll for z-axis",
   1251      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1252               deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
   1253               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1254               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1255               shiftKey: true, ctrlKey: false, altKey: false, metaKey: false },
   1256      expected: kNoScroll },
   1257  ];
   1258 
   1259  var description;
   1260 
   1261  var currentTestIndex = -1;
   1262  // deltaY should cause horizontal scroll and affected by deltaMultiplierY.
   1263  // So, horizontal scroll amount and direction is affected by deltaMultiplierY.
   1264  var isXReverted = (aSettings.deltaMultiplierY < 0);
   1265 
   1266  function doNextTest()
   1267  {
   1268    if (++currentTestIndex >= kTests.length) {
   1269      SimpleTest.executeSoon(aCallback);
   1270      return;
   1271    }
   1272 
   1273    gScrollableElement.scrollTop = 1000;
   1274    gScrollableElement.scrollLeft = 1000;
   1275 
   1276    var currentTest = kTests[currentTestIndex];
   1277    description = "doTestHorizontalizedScroll(aSettings=" + aSettings.description + "), " + currentTest.description + ": ";
   1278    if (currentTest.prepare) {
   1279      currentTest.prepare(doTestCurrentScroll);
   1280    } else {
   1281      doTestCurrentScroll();
   1282    }
   1283  }
   1284 
   1285  function doTestCurrentScroll() {
   1286    var currentTest = kTests[currentTestIndex];
   1287    sendWheelAndWait(10, 10, currentTest.event, function () {
   1288      is(gScrollableElement.scrollTop, 1000, description + "scrolled vertical");
   1289      if (currentTest.expected == kNoScroll) {
   1290        is(gScrollableElement.scrollLeft, 1000, description + "scrolled horizontal");
   1291      } else {
   1292        var scrollLeft = !isXReverted ? (currentTest.expected & kScrollLeft) :
   1293                                        (currentTest.expected & kScrollRight);
   1294        var scrollRight = !isXReverted ? (currentTest.expected & kScrollRight) :
   1295                                         (currentTest.expected & kScrollLeft);
   1296        if (scrollLeft) {
   1297          ok(gScrollableElement.scrollLeft < 1000, description + "not scrolled to left, got " + gScrollableElement.scrollLeft);
   1298        } else if (scrollRight) {
   1299          ok(gScrollableElement.scrollLeft > 1000, description + "not scrolled to right, got " + gScrollableElement.scrollLeft);
   1300        } else {
   1301          is(gScrollableElement.scrollLeft, 1000, description + "scrolled horizontal");
   1302        }
   1303      }
   1304      if (currentTest.cleanup) {
   1305        currentTest.cleanup(nextStep);
   1306      } else {
   1307        nextStep();
   1308      }
   1309 
   1310      function nextStep() {
   1311        winUtils.advanceTimeAndRefresh(100);
   1312        doNextTest();
   1313      }
   1314    });
   1315  }
   1316  doNextTest();
   1317 }
   1318 
   1319 // It will take *freaking* long time(maybe *hours*) to test all the writing mode
   1320 // combinations for the scroll target and its root, because there are altogether
   1321 // *one hundred* combinations (10 x 10)!
   1322 //
   1323 // So unless you really don't care a snap on time-consuming testing or a strict
   1324 // criteria is required for testing, it is strongly recommeneded that you
   1325 // comment out at least the writing modes which are marked as "peculiar" before
   1326 // running this test, you are encouraged to also comment out those "uncommon"
   1327 // writing modes in order to further shorten testing time.
   1328 //
   1329 // Note that if you are going to run time-consuming tests without commenting out
   1330 // most of the writing modes, don't forget to increase the value of the
   1331 // parameter in SimpleTest.requestLongerTimeout in this file; otherwise it'll
   1332 // most likely lead you to a timed-out failure.
   1333 //
   1334 // Also note that |isBTT| has nothing to do with the behaviour of auto-dir
   1335 // scrolling, it's just used to set the sign of |kOrigScrollTop|.
   1336 const kWritingModes = [
   1337  {
   1338    isRTL: true,
   1339    isBTT: false,
   1340    styles: [
   1341      {
   1342        writingMode: "horizontal-tb",
   1343        direction:   "rtl",
   1344      },
   1345      {
   1346        writingMode: "vertical-rl",
   1347        direction:   "ltr",
   1348      },
   1349      // uncommon
   1350      //{
   1351      //  writingMode: "sideways-rl",
   1352      //  direction:   "ltr",
   1353      //},
   1354    ],
   1355  },
   1356  {
   1357    isRTL: false,
   1358    isBTT: false,
   1359    styles: [
   1360      {
   1361        writingMode: "horizontal-tb",
   1362        direction:   "ltr",
   1363      },
   1364      // uncommon
   1365      //{
   1366      //  writingMode: "vertical-lr",
   1367      //  direction:   "ltr",
   1368      //},
   1369      // uncommon
   1370      //{
   1371      //  writingMode: "sideways-lr",
   1372      //  direction:   "ltr",
   1373      //},
   1374    ],
   1375  },
   1376  {
   1377    isRTL: true,
   1378    isBTT: true,
   1379    styles: [
   1380      // peculiar
   1381      //{
   1382      //  writingMode: "vertical-rl",
   1383      //  direction:   "rtl",
   1384      //},
   1385      // peculiar
   1386      //{
   1387      //  writingMode: "sideways-rl",
   1388      //  direction:   "rtl",
   1389      //},
   1390    ],
   1391  },
   1392  {
   1393    isRTL: false,
   1394    isBTT: true,
   1395    styles: [
   1396      // peculiar
   1397      //{
   1398      //  writingMode: "vertical-lr",
   1399      //  direction:   "rtl",
   1400      //},
   1401      // peculiar
   1402      //{
   1403      //  writingMode: "sideways-lr",
   1404      //  direction:   "rtl",
   1405      //},
   1406    ],
   1407  },
   1408 ];
   1409 
   1410 function getFirstWritingModeStyle()
   1411 {
   1412  if (kWritingModes.length < 1) {
   1413    return false;
   1414  }
   1415  let typeIndex = 0;
   1416  while (!kWritingModes[typeIndex].styles.length) {
   1417    typeIndex++;
   1418    if (typeIndex >= kWritingModes.length) {
   1419      return false;
   1420    }
   1421  }
   1422  return {typeIndex, styleIndex: 0};
   1423 }
   1424 
   1425 function getNextWritingModeStyle(curStyle)
   1426 {
   1427  let typeIndex  = curStyle.typeIndex;
   1428  let styleIndex = curStyle.styleIndex + 1;
   1429  while (typeIndex < kWritingModes.length) {
   1430    if (styleIndex < kWritingModes[typeIndex].styles.length) {
   1431      return {typeIndex, styleIndex};
   1432    }
   1433    typeIndex++;
   1434    styleIndex = 0;
   1435  }
   1436  return false;
   1437 }
   1438 
   1439 function doTestAutoDirScroll(aSettings, aAutoDirTrait, aCallback)
   1440 {
   1441  // Go through all the writing-mode combinations for the scroll target and its
   1442  // root.
   1443 
   1444  let firstStyle = getFirstWritingModeStyle();
   1445  if (!firstStyle) {
   1446    // The whole writing mode list is empty, no need to do any test for auto-dir
   1447    // scrolling. Go ahead with the subsequent tests.
   1448    SimpleTest.executeSoon(aCallback);
   1449    return;
   1450  }
   1451 
   1452  // Begin with the first style for both the root and the scroll target.
   1453  // doTestAutoDirScroll2 will recursively call itself back for every
   1454  // style combination with getNextWritingModeStyle until all combinations have
   1455  // been enumerated, and then it will call SimpleTest.executeSoon(aCallback).
   1456  doTestAutoDirScroll2(aSettings, aAutoDirTrait,
   1457                       firstStyle, firstStyle,
   1458                       aCallback);
   1459 }
   1460 
   1461 function doTestAutoDirScroll2(aSettings, aAutoDirTrait,
   1462                              aStyleForRoot, aStyleForTarget,
   1463                              aCallback)
   1464 {
   1465  const kStyleTypeForRoot   = kWritingModes[aStyleForRoot.typeIndex];
   1466  const kStyleTypeForTarget = kWritingModes[aStyleForTarget.typeIndex];
   1467 
   1468  const kStyleForRoot   = kStyleTypeForRoot.styles[aStyleForRoot.styleIndex];
   1469  const kStyleForTarget = kStyleTypeForTarget.styles[aStyleForTarget.styleIndex];
   1470 
   1471  const kIsRootRTL   = kStyleTypeForRoot.isRTL;
   1472  const kIsTargetRTL = kStyleTypeForTarget.isRTL;
   1473  // Just used to set the sign of |kOrigScrollTop|, not related to the auto-dir
   1474  // behaviour.
   1475  const kIsTargetBTT = kStyleTypeForTarget.isBTT;
   1476 
   1477  const kOldStyleForRoot   = {};
   1478  const kOldStyleForTarget = {};
   1479 
   1480  const kHonoursRoot = Boolean(aAutoDirTrait.honoursRoot);
   1481 
   1482  const kNoScroll    = 0x00;
   1483  const kScrollUp    = 0x01;
   1484  const kScrollDown  = 0x02;
   1485  const kScrollLeft  = 0x04;
   1486  const kScrollRight = 0x08;
   1487 
   1488  // The four constants indicate the expected result if the scroll direction is
   1489  // adjusted.
   1490  const kAdjustedForUp    = {};
   1491  const kAdjustedForDown  = {};
   1492  const kAdjustedForLeft  = {};
   1493  const kAdjustedForRight = {};
   1494  if (kHonoursRoot ? kIsRootRTL : kIsTargetRTL) {
   1495    kAdjustedForUp.result    = kScrollRight;
   1496    kAdjustedForUp.desc      = "right";
   1497    kAdjustedForDown.result  = kScrollLeft;
   1498    kAdjustedForDown.desc    = "left";
   1499    kAdjustedForLeft.result  = kScrollDown;
   1500    kAdjustedForLeft.desc    = "bottom";
   1501    kAdjustedForRight.result = kScrollUp;
   1502    kAdjustedForRight.desc   = "top";
   1503  } else {
   1504    kAdjustedForUp.result    = kScrollLeft;
   1505    kAdjustedForUp.desc      = "left";
   1506    kAdjustedForDown.result  = kScrollRight;
   1507    kAdjustedForDown.desc    = "right";
   1508    kAdjustedForLeft.result  = kScrollUp;
   1509    kAdjustedForLeft.desc    = "top";
   1510    kAdjustedForRight.result = kScrollDown;
   1511    kAdjustedForRight.desc   = "bottom";
   1512  }
   1513 
   1514  const kTests = [
   1515    // Tests:   Test pixel scrolling towards four edges when the target
   1516    //          overflows in both the two directions.
   1517    // Results: All are unadjusted.
   1518    // Reason:  Auto-dir adjustment never applies to a target which overflows in
   1519    //          both the two directions.
   1520    { description: "auto-dir scroll to bottom by pixel scroll even if lineOrPageDelta is 0",
   1521      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1522               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
   1523               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1524               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1525               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1526      adjusted: false,
   1527      expected: kScrollDown,
   1528      prepare (cb) {
   1529                 // Static contents will not start from the topleft side in some
   1530                 // writing modes, for ease of coding, we simply absolutely
   1531                 // position the target to the topleft in every case.
   1532                 gScrollableElement.style.position = "absolute";
   1533                 gScrollableElement.style.top      = "10px";
   1534                 gScrollableElement.style.left     = "10px";
   1535                 SpecialPowers.pushPrefEnv({
   1536                   "set": [["mousewheel.autodir.enabled", true],
   1537                           ["mousewheel.autodir.honourroot", kHonoursRoot]]
   1538                 }, cb);
   1539               } },
   1540    { description: "auto-dir scroll to bottom by pixel scroll when lineOrPageDelta is 1",
   1541      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1542               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
   1543               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   1544               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1545               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1546      adjusted: false,
   1547      expected: kScrollDown },
   1548    { description: "auto-dir scroll to top by pixel scroll even if lineOrPageDelta is 0",
   1549      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1550               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
   1551               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1552               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1553               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1554      adjusted: false,
   1555      expected: kScrollUp },
   1556    { description: "auto-dir scroll to top by pixel scroll when lineOrPageDelta is -1",
   1557      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1558               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
   1559               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   1560               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1561               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1562      adjusted: false,
   1563      expected: kScrollUp },
   1564    { description: "auto-dir scroll to right by pixel scroll even if lineOrPageDelta is 0",
   1565      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1566               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
   1567               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1568               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1569               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1570      adjusted: false,
   1571      expected: kScrollRight },
   1572    { description: "auto-dir scroll to right by pixel scroll when lineOrPageDelta is 1",
   1573      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1574               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
   1575               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   1576               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1577               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1578      adjusted: false,
   1579      expected: kScrollRight },
   1580    { description: "auto-dir scroll to left by pixel scroll even if lineOrPageDelta is 0",
   1581      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1582               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
   1583               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1584               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1585               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1586      adjusted: false,
   1587      expected: kScrollLeft },
   1588    { description: "auto-dir scroll to left by pixel scroll when lineOrPageDelta is -1",
   1589      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1590               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
   1591               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   1592               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1593               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1594      adjusted: false,
   1595      expected: kScrollLeft },
   1596 
   1597    // Tests:   Test diagonal pixel scrolling when the target overflows in both
   1598    //          the two directions.
   1599    // Results: All are unadjusted.
   1600    // Reason:  Auto-dir adjustment never applies to a target which overflows in
   1601    //          both the two directions, furthermore, it never applies to
   1602    //          diagonal scrolling.
   1603    { description: "auto-dir scroll to bottom-right by pixel scroll",
   1604      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1605               deltaX: 8.0, deltaY: 8.0, deltaZ: 0.0,
   1606               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1607               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1608               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1609      adjusted: false,
   1610      expected: kScrollDown | kScrollRight },
   1611    { description: "auto-dir scroll to bottom-left by pixel scroll",
   1612      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1613               deltaX: -8.0, deltaY: 8.0, deltaZ: 0.0,
   1614               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1615               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1616               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1617      adjusted: false,
   1618      expected: kScrollDown | kScrollLeft },
   1619    { description: "auto-dir scroll to top-left by pixel scroll",
   1620      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1621               deltaX: -8.0, deltaY: -8.0, deltaZ: 0.0,
   1622               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1623               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1624               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1625      adjusted: false,
   1626      expected: kScrollUp | kScrollLeft },
   1627    { description: "auto-dir scroll to top-right by pixel scroll",
   1628      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1629               deltaX: 8.0, deltaY: -8.0, deltaZ: 0.0,
   1630               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1631               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1632               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1633      adjusted: false,
   1634      expected: kScrollUp | kScrollRight },
   1635 
   1636    // Tests:   Test line scrolling towards four edges when the target overflows
   1637    //          in both the two directions.
   1638    // Results: All are unadjusted.
   1639    // Reason:  Auto-dir adjustment never applies to a target which overflows in
   1640    //          both the two directions.
   1641    { description: "auto-dir scroll to bottom by line scroll even if lineOrPageDelta is 0",
   1642      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1643               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   1644               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   1645               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1646               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1647      adjusted: false,
   1648      expected: kScrollDown },
   1649    { description: "auto-dir scroll to bottom by line scroll when lineOrPageDelta is 1",
   1650      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1651               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   1652               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   1653               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1654               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1655      adjusted: false,
   1656      expected: kScrollDown },
   1657    { description: "auto-dir scroll to top by line scroll even if lineOrPageDelta is 0",
   1658      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1659               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   1660               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1661               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1662               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1663      adjusted: false,
   1664      expected: kScrollUp },
   1665    { description: "auto-dir scroll to top by line scroll when lineOrPageDelta is -1",
   1666      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1667               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   1668               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   1669               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1670               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1671      adjusted: false,
   1672      expected: kScrollUp },
   1673    { description: "auto-dir scroll to right by line scroll even if lineOrPageDelta is 0",
   1674      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1675               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   1676               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1677               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1678               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1679      adjusted: false,
   1680      expected: kScrollRight },
   1681    { description: "auto-dir scroll to right by line scroll when lineOrPageDelta is 1",
   1682      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1683               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   1684               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   1685               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1686               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1687      adjusted: false,
   1688      expected: kScrollRight },
   1689    { description: "auto-dir scroll to left by line scroll even if lineOrPageDelta is 0",
   1690      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1691               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   1692               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1693               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1694               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1695      adjusted: false,
   1696      expected: kScrollLeft },
   1697    { description: "auto-dir scroll to left by line scroll when lineOrPageDelta is -1",
   1698      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1699               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   1700               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   1701               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1702               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1703      adjusted: false,
   1704      expected: kScrollLeft },
   1705 
   1706    // Tests:   Test diagonal line scrolling when the target overflows in both
   1707    //          the two directions.
   1708    // Results: All are unadjusted.
   1709    // Reason:  Auto-dir adjustment never applies to a target which overflows in
   1710    //          both the two directions, furthermore, it never applies to
   1711    //          diagonal scrolling.
   1712    { description: "auto-dir scroll to bottom-right by line scroll",
   1713      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1714               deltaX: 0.5, deltaY: 0.5, deltaZ: 0.0,
   1715               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1716               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1717               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1718      adjusted: false,
   1719      expected: kScrollDown | kScrollRight },
   1720    { description: "auto-dir scroll to bottom-left by line scroll",
   1721      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1722               deltaX: -0.5, deltaY: 0.5, deltaZ: 0.0,
   1723               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1724               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1725               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1726      adjusted: false,
   1727      expected: kScrollDown | kScrollLeft },
   1728    { description: "auto-dir scroll to top-left by line scroll",
   1729      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1730               deltaX: -0.5, deltaY: -0.5, deltaZ: 0.0,
   1731               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1732               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1733               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1734      adjusted: false,
   1735      expected: kScrollUp | kScrollLeft },
   1736    { description: "auto-dir scroll to top-right by line scroll",
   1737      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1738               deltaX: 0.5, deltaY: -0.5, deltaZ: 0.0,
   1739               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1740               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1741               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1742      adjusted: false,
   1743      expected: kScrollUp | kScrollRight },
   1744 
   1745    // Tests:   Test page scrolling towards four edges when the target overflows
   1746    //          in both the two directions.
   1747    // Results: All are unadjusted.
   1748    // Reason:  Auto-dir adjustment never applies to a target which overflows in
   1749    //          both the two directions.
   1750    { description: "auto-dir scroll to bottom by page scroll even if lineOrPageDelta is 0",
   1751      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1752               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   1753               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   1754               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1755               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1756      adjusted: false,
   1757      expected: kScrollDown },
   1758    { description: "auto-dir scroll to bottom by page scroll when lineOrPageDelta is 1",
   1759      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1760               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   1761               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   1762               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1763               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1764      adjusted: false,
   1765      expected: kScrollDown },
   1766    { description: "auto-dir scroll to top by page scroll even if lineOrPageDelta is 0",
   1767      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   1768               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   1769               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1770               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1771               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1772      adjusted: false,
   1773      expected: kScrollUp },
   1774    { description: "auto-dir scroll to top by page scroll when lineOrPageDelta is -1",
   1775      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1776               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   1777               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   1778               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1779               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1780      adjusted: false,
   1781      expected: kScrollUp },
   1782    { description: "auto-dir scroll to right by page scroll even if lineOrPageDelta is 0",
   1783      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1784               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   1785               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1786               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1787               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1788      adjusted: false,
   1789      expected: kScrollRight },
   1790    { description: "auto-dir scroll to right by page scroll when lineOrPageDelta is 1",
   1791      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1792               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   1793               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   1794               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1795               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1796      adjusted: false,
   1797      expected: kScrollRight },
   1798    { description: "auto-dir scroll to left by page scroll even if lineOrPageDelta is 0",
   1799      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1800               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   1801               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1802               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1803               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1804      adjusted: false,
   1805      expected: kScrollLeft },
   1806    { description: "auto-dir scroll to left by page scroll when lineOrPageDelta is -1",
   1807      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1808               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   1809               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   1810               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1811               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1812      adjusted: false,
   1813      expected: kScrollLeft },
   1814 
   1815    // Tests:   Test diagonal page scrolling when the target overflows in both
   1816    //          the two directions.
   1817    // Results: All are unadjusted.
   1818    // Reason:  Auto-dir adjustment never applies to a target which overflows in
   1819    //          both the two directions, furthermore, it never applies to
   1820    //          diagonal scrolling.
   1821    { description: "auto-dir scroll to bottom-right by page scroll",
   1822      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1823               deltaX: 0.5, deltaY: 0.5, deltaZ: 0.0,
   1824               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1825               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1826               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1827      adjusted: false,
   1828      expected: kScrollDown | kScrollRight },
   1829    { description: "auto-dir scroll to bottom-left by page scroll",
   1830      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1831               deltaX: -0.5, deltaY: 0.5, deltaZ: 0.0,
   1832               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1833               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1834               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1835      adjusted: false,
   1836      expected: kScrollDown | kScrollLeft },
   1837    { description: "auto-dir scroll to top-left by page scroll",
   1838      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1839               deltaX: -0.5, deltaY: -0.5, deltaZ: 0.0,
   1840               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1841               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1842               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1843      adjusted: false,
   1844      expected: kScrollUp | kScrollLeft },
   1845    { description: "auto-dir scroll to top-right by page scroll",
   1846      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   1847               deltaX: 0.5, deltaY: -0.5, deltaZ: 0.0,
   1848               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1849               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1850               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1851      adjusted: false,
   1852      expected: kScrollUp | kScrollRight },
   1853 
   1854    // The tests above in this function are all for testing a target with two
   1855    // scrollbars. All of them should not be adjustable.
   1856    // From here on, the tests below in this function are all for testing a
   1857    // target with only one scrollbar, either a vertical scrollbar or horizontal
   1858    // scrollbar. Some of them are adjustable.
   1859 
   1860    // Tests:   Test pixel scrolling towards four edges when the target
   1861    //          overflows only in the horizontal direction.
   1862    // Results: Vertical wheel scrolls are adjusted to be horizontal whereas the
   1863    //          horizontal wheel scrolls are unadjusted.
   1864    // Reason:  Auto-dir adjustment applies to a target if the target overflows
   1865    //          in only one direction and the direction is orthogonal to the
   1866    //          wheel and deltaZ is zero.
   1867    { description: "auto-dir scroll to " + kAdjustedForDown.desc +
   1868                   "(originally bottom) by pixel scroll even if lineOrPageDelta is 0, " +
   1869                   "no vertical scrollbar",
   1870      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1871               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
   1872               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1873               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1874               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1875      adjusted: true,
   1876      expected: kAdjustedForDown.result,
   1877      prepare (cb) {
   1878                 gScrollableElement.style.overflowX = "auto";
   1879                 gScrollableElement.style.overflowY = "hidden";
   1880                 resetScrollPosition(gScrollableElement);
   1881                 cb();
   1882               } },
   1883    { description: "auto-dir scroll to " + kAdjustedForDown.desc +
   1884                   "(originally bottom) by pixel scroll when lineOrPageDelta is 1, " +
   1885                   "no vertical scrollbar",
   1886      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1887               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
   1888               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   1889               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1890               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1891      adjusted: true,
   1892      expected: kAdjustedForDown.result },
   1893    { description: "auto-dir scroll to " + kAdjustedForUp.desc +
   1894                   "(originally top) by pixel scroll even if lineOrPageDelta is 0, " +
   1895                   "no vertical scrollbar",
   1896      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1897               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
   1898               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1899               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1900               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1901      adjusted: true,
   1902      expected: kAdjustedForUp.result },
   1903    { description: "auto-dir scroll to " + kAdjustedForUp.desc +
   1904                   "(originally top) by pixel scroll when lineOrPageDelta is -1, " +
   1905                   "no vertical scrollbar",
   1906      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1907               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
   1908               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   1909               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1910               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1911      adjusted: true,
   1912      expected: kAdjustedForUp.result },
   1913    { description: "auto-dir scroll to right by pixel scroll even if lineOrPageDelta is 0, " +
   1914                   "no vertical scrollbar",
   1915      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1916               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
   1917               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1918               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1919               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1920      adjusted: false,
   1921      expected: kScrollRight },
   1922    { description: "auto-dir scroll to right by pixel scroll when lineOrPageDelta is 1, " +
   1923                   "no vertical scrollbar",
   1924      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1925               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
   1926               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   1927               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1928               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1929      adjusted: false,
   1930      expected: kScrollRight },
   1931    { description: "auto-dir scroll to left by pixel scroll even if lineOrPageDelta is 0, " +
   1932                   "no vertical scrollbar",
   1933      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1934               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
   1935               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1936               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1937               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1938      adjusted: false,
   1939      expected: kScrollLeft },
   1940    { description: "auto-dir scroll to left by pixel scroll when lineOrPageDelta is -1, " +
   1941                   "no vertical scrollbar",
   1942      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1943               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
   1944               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   1945               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1946               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1947      adjusted: false,
   1948      expected: kScrollLeft },
   1949 
   1950    // Tests:   Test pixel scrolling towards four edges when the target
   1951    //          overflows only in the vertical direction.
   1952    // Results: Horizontal wheel scrolls are adjusted to be vertical whereas the
   1953    //          vertical wheel scrolls are unadjusted.
   1954    // Reason:  Auto-dir adjustment applies to a target if the target overflows
   1955    //          in only one direction and the direction is orthogonal to the
   1956    //          wheel and deltaZ is zero.
   1957    { description: "auto-dir scroll to bottom by pixel scroll even if lineOrPageDelta is 0, " +
   1958                   "no horizontal scrollbar",
   1959      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1960               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
   1961               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1962               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1963               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1964      adjusted: false,
   1965      expected: kScrollDown,
   1966      prepare (cb) {
   1967                 gScrollableElement.style.overflowX = "hidden";
   1968                 gScrollableElement.style.overflowY = "auto";
   1969                 resetScrollPosition(gScrollableElement);
   1970                 cb();
   1971               } },
   1972    { description: "auto-dir scroll to bottom by pixel scroll when lineOrPageDelta is 1, " +
   1973                   "no horizontal scrollbar",
   1974      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1975               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
   1976               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   1977               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1978               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1979      adjusted: false,
   1980      expected: kScrollDown },
   1981    { description: "auto-dir scroll to top by pixel scroll even if lineOrPageDelta is 0, " +
   1982                   "no horizontal scrollbar",
   1983      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1984               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
   1985               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   1986               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1987               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1988      adjusted: false,
   1989      expected: kScrollUp },
   1990    { description: "auto-dir scroll to top by pixel scroll when lineOrPageDelta is -1, " +
   1991                   "no horizontal scrollbar",
   1992      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   1993               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
   1994               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   1995               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   1996               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   1997      adjusted: false,
   1998      expected: kScrollUp },
   1999    { description: "auto-dir scroll to " + kAdjustedForRight.desc +
   2000                   "(originally right) by pixel scroll even if lineOrPageDelta is 0, " +
   2001                   "no horizontal scrollbar",
   2002      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2003               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
   2004               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2005               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2006               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2007      adjusted: true,
   2008      expected: kAdjustedForRight.result },
   2009    { description: "auto-dir scroll to " + kAdjustedForRight.desc +
   2010                   "(originally right) by pixel scroll when lineOrPageDelta is 1, " +
   2011                   "no horizontal scrollbar",
   2012      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2013               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
   2014               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   2015               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2016               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2017      adjusted: true,
   2018      expected: kAdjustedForRight.result },
   2019    { description: "auto-dir scroll to " + kAdjustedForLeft.desc +
   2020                   "(originally left) by pixel scroll even if lineOrPageDelta is 0, " +
   2021                   "no horizontal scrollbar",
   2022      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2023               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
   2024               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2025               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2026               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2027      adjusted: true,
   2028      expected: kAdjustedForLeft.result },
   2029    { description: "auto-dir scroll to " + kAdjustedForLeft.desc +
   2030                   "(originally left) by pixel scroll when lineOrPageDelta is -1, " +
   2031                   "no horizontal scrollbar",
   2032      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2033               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
   2034               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   2035               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2036               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2037      adjusted: true,
   2038      expected: kAdjustedForLeft.result },
   2039 
   2040    // Tests:   Test line scrolling towards four edges when the target overflows
   2041    //          only in the horizontal direction.
   2042    // Results: Vertical wheel scrolls are adjusted to be horizontal whereas the
   2043    //          horizontal wheel scrolls are unadjusted.
   2044    // Reason:  Auto-dir adjustment applies to a target if the target overflows
   2045    //          in only one direction and the direction is orthogonal to the
   2046    //          wheel and deltaZ is zero.
   2047    { description: "auto-dir scroll to " + kAdjustedForDown.desc +
   2048                   "(originally bottom) by line scroll even if lineOrPageDelta is 0, " +
   2049                   "no vertical scrollbar",
   2050      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2051               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   2052               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2053               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2054               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2055      adjusted: true,
   2056      expected: kAdjustedForDown.result,
   2057      prepare (cb) {
   2058                 gScrollableElement.style.overflowX = "auto";
   2059                 gScrollableElement.style.overflowY = "hidden";
   2060                 resetScrollPosition(gScrollableElement);
   2061                 cb();
   2062               } },
   2063    { description: "auto-dir scroll to " + kAdjustedForDown.desc +
   2064                   "(originally bottom) by line scroll when lineOrPageDelta is 1, " +
   2065                   "no vertical scrollbar",
   2066      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2067               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   2068               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   2069               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2070               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2071      adjusted: true,
   2072      expected: kAdjustedForDown.result },
   2073    { description: "auto-dir scroll to " + kAdjustedForUp.desc +
   2074                   "(originally top) by line scroll even if lineOrPageDelta is 0, " +
   2075                   "no vertical scrollbar",
   2076      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2077               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   2078               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2079               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2080               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2081      adjusted: true,
   2082      expected: kAdjustedForUp.result },
   2083    { description: "auto-dir scroll to " + kAdjustedForUp.desc +
   2084                   "(originally top) by line scroll when lineOrPageDelta is -1, " +
   2085                   "no vertical scrollbar",
   2086      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2087               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   2088               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   2089               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2090               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2091      adjusted: true,
   2092      expected: kAdjustedForUp.result },
   2093    { description: "auto-dir scroll to right by line scroll even if lineOrPageDelta is 0, " +
   2094                   "no vertical scrollbar",
   2095      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2096               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   2097               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2098               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2099               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2100      adjusted: false,
   2101      expected: kScrollRight },
   2102    { description: "auto-dir scroll to right by line scroll when lineOrPageDelta is 1, " +
   2103                   "no vertical scrollbar",
   2104      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2105               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   2106               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   2107               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2108               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2109      adjusted: false,
   2110      expected: kScrollRight },
   2111    { description: "auto-dir scroll to left by line scroll even if lineOrPageDelta is 0, " +
   2112                   "no vertical scrollbar",
   2113      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2114               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   2115               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2116               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2117               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2118      adjusted: false,
   2119      expected: kScrollLeft },
   2120    { description: "auto-dir scroll to left by line scroll when lineOrPageDelta is -1, " +
   2121                   "no vertical scrollbar",
   2122      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2123               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   2124               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   2125               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2126               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2127      adjusted: false,
   2128      expected: kScrollLeft },
   2129 
   2130    // Tests:   Test line scrolling towards four edges when the target overflows
   2131    //          only in the vertical direction.
   2132    // Results: Horizontal wheel scrolls are adjusted to be vertical whereas the
   2133    //          vertical wheel scrolls are unadjusted.
   2134    // Reason:  Auto-dir adjustment applies to a target if the target overflows
   2135    //          in only one direction and the direction is orthogonal to the
   2136    //          wheel and deltaZ is zero.
   2137    { description: "auto-dir scroll to bottom by line scroll even if lineOrPageDelta is 0, " +
   2138                   "no horizontal scrollbar",
   2139      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2140               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   2141               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2142               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2143               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2144      adjusted: false,
   2145      expected: kScrollDown,
   2146      prepare (cb) {
   2147                 gScrollableElement.style.overflowX = "hidden";
   2148                 gScrollableElement.style.overflowY = "auto";
   2149                 resetScrollPosition(gScrollableElement);
   2150                 cb();
   2151               } },
   2152    { description: "auto-dir scroll to bottom by line scroll when lineOrPageDelta is 1, " +
   2153                   "no horizontal scrollbar",
   2154      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2155               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   2156               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   2157               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2158               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2159      adjusted: false,
   2160      expected: kScrollDown },
   2161    { description: "auto-dir scroll to top by line scroll even if lineOrPageDelta is 0, " +
   2162                   "no horizontal scrollbar",
   2163      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2164               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   2165               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2166               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2167               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2168      adjusted: false,
   2169      expected: kScrollUp },
   2170    { description: "auto-dir scroll to top by line scroll when lineOrPageDelta is -1, " +
   2171                   "no horizontal scrollbar",
   2172      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2173               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   2174               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   2175               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2176               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2177      adjusted: false,
   2178      expected: kScrollUp },
   2179    { description: "auto-dir scroll to " + kAdjustedForRight.desc +
   2180                   "(originally right) by line scroll even if lineOrPageDelta is 0, " +
   2181                   "no horizontal scrollbar",
   2182      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2183               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   2184               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2185               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2186               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2187      adjusted: true,
   2188      expected: kAdjustedForRight.result },
   2189    { description: "auto-dir scroll to " + kAdjustedForRight.desc +
   2190                   "(originally right) by line scroll when lineOrPageDelta is 1, " +
   2191                   "no horizontal scrollbar",
   2192      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2193               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   2194               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   2195               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2196               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2197      adjusted: true,
   2198      expected: kAdjustedForRight.result },
   2199    { description: "auto-dir scroll to " + kAdjustedForLeft.desc +
   2200                   "(originally left) by line scroll even if lineOrPageDelta is 0, " +
   2201                   "no horizontal scrollbar",
   2202      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2203               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   2204               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2205               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2206               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2207      adjusted: true,
   2208      expected: kAdjustedForLeft.result },
   2209    { description: "auto-dir scroll to " + kAdjustedForLeft.desc +
   2210                   "(originally left) by line scroll when lineOrPageDelta is -1, " +
   2211                   "no horizontal scrollbar",
   2212      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2213               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   2214               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   2215               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2216               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2217      adjusted: true,
   2218      expected: kAdjustedForLeft.result },
   2219 
   2220    // Tests:   Test page scrolling towards four edges when the target overflows
   2221    //          only in the horizontal direction.
   2222    // Results: Vertical wheel scrolls are adjusted to be horizontal whereas the
   2223    //          horizontal wheel scrolls are unadjusted.
   2224    // Reason:  Auto-dir adjustment applies to a target if the target overflows
   2225    //          in only one direction and the direction is orthogonal to the
   2226    //          wheel and deltaZ is zero.
   2227    { description: "auto-dir scroll to " + kAdjustedForDown.desc +
   2228                   "(originally bottom) by page scroll when lineOrPageDelta is 1, " +
   2229                   "no vertical scrollbar",
   2230      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2231               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   2232               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   2233               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2234               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2235      adjusted: true,
   2236      expected: kAdjustedForDown.result,
   2237      prepare (cb) {
   2238                 gScrollableElement.style.overflowX = "auto";
   2239                 gScrollableElement.style.overflowY = "hidden";
   2240                 resetScrollPosition(gScrollableElement);
   2241                 cb();
   2242               } },
   2243    { description: "auto-dir scroll to " + kAdjustedForDown.desc +
   2244                   "(originally bottom) by page scroll even if lineOrPageDelta is 0, " +
   2245                   "no vertical scrollbar",
   2246      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2247               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   2248               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2249               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2250               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2251      adjusted: true,
   2252      expected: kAdjustedForDown.result },
   2253    { description: "auto-dir scroll to " + kAdjustedForUp.desc +
   2254                   "(originally top) by page scroll when lineOrPageDelta is -1, " +
   2255                   "no vertical scrollbar",
   2256      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2257               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   2258               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   2259               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2260               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2261      adjusted: true,
   2262      expected: kAdjustedForUp.result },
   2263    { description: "auto-dir scroll to " + kAdjustedForUp.desc +
   2264                   "(originally top) by page scroll even if lineOrPageDelta is 0, " +
   2265                   "no vertical scrollbar",
   2266      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2267               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   2268               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2269               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2270               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2271      adjusted: true,
   2272      expected: kAdjustedForUp.result },
   2273    { description: "auto-dir scroll to right by page scroll when lineOrPageDelta is 1, " +
   2274                   "no vertical scrollbar",
   2275      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2276               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   2277               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   2278               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2279               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2280      adjusted: false,
   2281      expected: kScrollRight },
   2282    { description: "auto-dir scroll to right by page scroll even if lineOrPageDelta is 0, " +
   2283                   "no vertical scrollbar",
   2284      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2285               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   2286               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2287               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2288               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2289      adjusted: false,
   2290      expected: kScrollRight },
   2291    { description: "auto-dir scroll to left by page scroll when lineOrPageDelta is -1, " +
   2292                   "no vertical scrollbar",
   2293      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2294               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   2295               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   2296               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2297               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2298      adjusted: false,
   2299      expected: kScrollLeft },
   2300    { description: "auto-dir scroll to left by page scroll even if lineOrPageDelta is 0, " +
   2301                   "no vertical scrollbar",
   2302      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2303               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   2304               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2305               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2306               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2307      adjusted: false,
   2308      expected: kScrollLeft },
   2309 
   2310    // Tests:   Test page scrolling towards four edges when the target overflows
   2311    //          only in the vertical direction.
   2312    // Results: Horizontal wheel scrolls are adjusted to be vertical whereas the
   2313    //          vertical wheel scrolls are unadjusted.
   2314    // Reason:  Auto-dir adjustment applies to a target if the target overflows
   2315    //          in only one direction and the direction is orthogonal to the
   2316    //          wheel and deltaZ is zero.
   2317    { description: "auto-dir scroll to bottom by page scroll when lineOrPageDelta is 1, " +
   2318                   "no horizontal scrollbar",
   2319      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2320               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   2321               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   2322               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2323               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2324      adjusted: false,
   2325      expected: kScrollDown,
   2326      prepare (cb) {
   2327                 gScrollableElement.style.overflowX = "hidden";
   2328                 gScrollableElement.style.overflowY = "auto";
   2329                 resetScrollPosition(gScrollableElement);
   2330                 cb();
   2331               } },
   2332    { description: "auto-dir scroll to bottom by page scroll even if lineOrPageDelta is 0, " +
   2333                   "no horizontal scrollbar",
   2334      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2335               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   2336               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2337               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2338               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2339      adjusted: false,
   2340      expected: kScrollDown },
   2341    { description: "auto-dir scroll to top by page scroll when lineOrPageDelta is -1, " +
   2342                   "no horizontal scrollbar",
   2343      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2344               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   2345               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   2346               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2347               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2348      adjusted: false,
   2349      expected: kScrollUp },
   2350    { description: "auto-dir scroll to top by page scroll even if lineOrPageDelta is 0, " +
   2351                   "no horizontal scrollbar",
   2352      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2353               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   2354               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2355               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2356               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2357      adjusted: false,
   2358      expected: kScrollUp },
   2359    { description: "auto-dir scroll to " + kAdjustedForRight.desc +
   2360                   "(originally right) by page scroll when lineOrPageDelta is 1, " +
   2361                   "no horizontal scrollbar",
   2362      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2363               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   2364               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   2365               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2366               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2367      adjusted: true,
   2368      expected: kAdjustedForRight.result },
   2369    { description: "auto-dir scroll to " + kAdjustedForRight.desc +
   2370                   "(originally right) by page scroll even if lineOrPageDelta is 0, " +
   2371                   "no horizontal scrollbar",
   2372      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2373               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   2374               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2375               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2376               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2377      adjusted: true,
   2378      expected: kAdjustedForRight.result },
   2379    { description: "auto-dir scroll to " + kAdjustedForLeft.desc +
   2380                   "(originally left) by page scroll when lineOrPageDelta is -1, " +
   2381                   "no horizontal scrollbar",
   2382      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2383               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   2384               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   2385               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2386               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2387      adjusted: true,
   2388      expected: kAdjustedForLeft.result },
   2389    { description: "auto-dir scroll to " + kAdjustedForLeft.desc +
   2390                   "(originally left) by page scroll even if lineOrPageDelta is 0, " +
   2391                   "no horizontal scrollbar",
   2392      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2393               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   2394               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2395               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2396               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2397      adjusted: true,
   2398      expected: kAdjustedForLeft.result,
   2399      cleanup (cb) {
   2400                 SpecialPowers.pushPrefEnv({"set":
   2401                                               [["mousewheel.autodir.enabled",
   2402                                                 false]]},
   2403                                            cb);
   2404               } },
   2405    // Tests:   Test that autodir scrolling can be force-enabled using windowUtils.
   2406    //          This only tests vertical wheel scrolls being adjusted to be
   2407    //          horizontal, rather than re-testing all autodir behaviours just for
   2408    //          this way of enabling it.
   2409    // Results: Vertical wheel scrolls are adjusted to be horizontal whereas the
   2410    //          horizontal wheel scrolls are unadjusted.
   2411    // Reason:  Auto-dir adjustment applies to a target if the target overflows
   2412    //          in only one direction and the direction is orthogonal to the
   2413    //          wheel and deltaZ is zero.
   2414    { description: "force-enabled auto-dir scroll to " + kAdjustedForDown.desc +
   2415                   "(originally bottom) by pixel scroll even if lineOrPageDelta is 0, " +
   2416                   "no vertical scrollbar",
   2417      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2418               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
   2419               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2420               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2421               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2422      adjusted: true,
   2423      expected: kAdjustedForDown.result,
   2424      prepare (cb) {
   2425                 gScrollableElement.style.overflowX = "auto";
   2426                 gScrollableElement.style.overflowY = "hidden";
   2427                 resetScrollPosition(gScrollableElement);
   2428                 winUtils.setMousewheelAutodir(gScrollableElement, true, kHonoursRoot)
   2429                 cb();
   2430               } },
   2431    { description: "force-enabled auto-dir scroll to " + kAdjustedForDown.desc +
   2432                   "(originally bottom) by pixel scroll when lineOrPageDelta is 1, " +
   2433                   "no vertical scrollbar",
   2434      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2435               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
   2436               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
   2437               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2438               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2439      adjusted: true,
   2440      expected: kAdjustedForDown.result },
   2441    { description: "force-enabled auto-dir scroll to " + kAdjustedForUp.desc +
   2442                   "(originally top) by pixel scroll even if lineOrPageDelta is 0, " +
   2443                   "no vertical scrollbar",
   2444      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2445               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
   2446               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2447               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2448               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2449      adjusted: true,
   2450      expected: kAdjustedForUp.result },
   2451    { description: "force-enabled auto-dir scroll to " + kAdjustedForUp.desc +
   2452                   "(originally top) by pixel scroll when lineOrPageDelta is -1, " +
   2453                   "no vertical scrollbar",
   2454      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2455               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
   2456               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
   2457               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2458               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2459      adjusted: true,
   2460      expected: kAdjustedForUp.result },
   2461    { description: "force-enabled auto-dir scroll to right by pixel scroll even if lineOrPageDelta is 0, " +
   2462                   "no vertical scrollbar",
   2463      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2464               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
   2465               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2466               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2467               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2468      adjusted: false,
   2469      expected: kScrollRight },
   2470    { description: "force-enabled auto-dir scroll to right by pixel scroll when lineOrPageDelta is 1, " +
   2471                   "no vertical scrollbar",
   2472      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2473               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
   2474               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
   2475               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2476               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2477      adjusted: false,
   2478      expected: kScrollRight },
   2479    { description: "force-enabled auto-dir scroll to left by pixel scroll even if lineOrPageDelta is 0, " +
   2480                   "no vertical scrollbar",
   2481      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2482               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
   2483               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
   2484               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2485               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2486      adjusted: false,
   2487      expected: kScrollLeft },
   2488    { description: "force-enabled auto-dir scroll to left by pixel scroll when lineOrPageDelta is -1, " +
   2489                   "no vertical scrollbar",
   2490      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2491               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
   2492               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
   2493               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
   2494               shiftKey: false, ctrlKey: false, altKey: false, metaKey: false },
   2495      adjusted: false,
   2496      expected: kScrollLeft,
   2497      cleanup (cb) {
   2498                 gScrollableElement.style.position = "static";
   2499                 gScrollableElement.style.top = "auto";
   2500                 gScrollableElement.style.left = "auto";
   2501                 gScrollableElement.style.overflow = "auto";
   2502                 Object.assign(document.body.style, kOldStyleForRoot);
   2503                 Object.assign(gScrollableElement.style, kOldStyleForTarget);
   2504                 winUtils.setMousewheelAutodir(gScrollableElement, false, false);
   2505                 cb();
   2506              } },
   2507  ];
   2508 
   2509  let styleDescForRoot = "";
   2510  let styleDescForTarget = "";
   2511  Object.keys(kStyleForRoot).forEach(function(property)
   2512  {
   2513    kOldStyleForRoot[property] = document.body.style[property];
   2514    document.body.style[property] = kStyleForRoot[property];
   2515    if ("" !== styleDescForRoot) {
   2516      styleDescForRoot += " ";
   2517    }
   2518    styleDescForRoot += property + ": " + kStyleForRoot[property] + ";";
   2519  });
   2520  Object.keys(kStyleForTarget).forEach(function(property)
   2521  {
   2522    kOldStyleForTarget[property] = gScrollableElement.style[property];
   2523    gScrollableElement.style[property] = kStyleForTarget[property];
   2524    if ("" !== styleDescForTarget) {
   2525      styleDescForTarget += " ";
   2526    }
   2527    styleDescForTarget += property + ": " +
   2528                            kStyleForTarget[property] + ";";
   2529  });
   2530 
   2531  let description;
   2532  let currentTestIndex = -1;
   2533  let isXReverted = aSettings.deltaMultiplierX < 0;
   2534  let isYReverted = aSettings.deltaMultiplierY < 0;
   2535 
   2536  // We are doing a "trick" here:
   2537  // If the `kHonoursRoot` is true and the scroll target and the root's contents
   2538  // are both LTR or both RTL, we can safely skip these tests, because the same
   2539  // behavior is tested when the `kHonoursRoot` is false.
   2540  if (kHonoursRoot && kIsRootRTL === kIsTargetRTL) {
   2541    currentTestIndex = kTests.length;
   2542  }
   2543 
   2544  const kOrigScrollLeft = kIsTargetRTL ? -1000 : 1000;
   2545  const kOrigScrollTop = kIsTargetBTT ? -1000 : 1000;
   2546 
   2547  function doNextTest()
   2548  {
   2549    if (++currentTestIndex >= kTests.length) {
   2550      // The tests for the current writing mode combination have been finished.
   2551      // Continue the tests for the next writing mode combination, if any.
   2552      let nextStyleForRoot;
   2553      let nextStyleForTarget;
   2554      nextStyleForTarget = getNextWritingModeStyle(aStyleForTarget);
   2555      if (nextStyleForTarget) {
   2556        nextStyleForRoot = aStyleForRoot;
   2557      } else {
   2558        nextStyleForRoot = getNextWritingModeStyle(aStyleForRoot);
   2559        if (!nextStyleForRoot) {
   2560          // All writing mode combinations have been enumerated, so stop
   2561          // recursively calling doTestAutoDirScroll2, and go ahead with the
   2562          // subsequent tests.
   2563          SimpleTest.executeSoon(aCallback);
   2564          return;
   2565        }
   2566        nextStyleForTarget = getFirstWritingModeStyle();
   2567      }
   2568      doTestAutoDirScroll2(aSettings, aAutoDirTrait,
   2569                           nextStyleForRoot, nextStyleForTarget,
   2570                           aCallback);
   2571      return;
   2572    }
   2573 
   2574    gScrollableElement.scrollTop = kOrigScrollTop;
   2575    gScrollableElement.scrollLeft = kOrigScrollLeft;
   2576 
   2577    var currentTest = kTests[currentTestIndex];
   2578    description = "doTestAutoDirScroll(aSettings=" + aSettings.description + ", ";
   2579    if (kHonoursRoot) {
   2580      description += "{honoursRoot: true}), ";
   2581    } else {
   2582      description += "{honoursRoot: false}), ";
   2583    }
   2584    description += "root = " + styleDescForRoot + " ";
   2585    description += "target = " + styleDescForTarget + " ";
   2586    if (currentTest.adjusted) {
   2587      description += "adjusted ";
   2588    } else {
   2589      description += "unadjusted ";
   2590    }
   2591    description += currentTest.description + ": ";
   2592    if (currentTest.prepare) {
   2593      currentTest.prepare(doTestCurrentScroll);
   2594    } else {
   2595      doTestCurrentScroll();
   2596    }
   2597  }
   2598 
   2599  function doTestCurrentScroll() {
   2600    var currentTest = kTests[currentTestIndex];
   2601    sendWheelAndWait(100, 100, currentTest.event, function () {
   2602      if (currentTest.expected == kNoScroll) {
   2603        is(gScrollableElement.scrollTop, kOrigScrollTop, description + "scrolled vertical");
   2604        is(gScrollableElement.scrollLeft, kOrigScrollLeft, description + "scrolled horizontal");
   2605      } else {
   2606        // If auto-dir adjustment occurs, temporarily swap |isYReverted| and
   2607        // |isXReverted|.
   2608        if (currentTest.adjusted) {
   2609          [isYReverted, isXReverted] = [isXReverted, isYReverted];
   2610        }
   2611        let scrollUp = !isYReverted ? (currentTest.expected & kScrollUp) :
   2612                                      (currentTest.expected & kScrollDown);
   2613        let scrollDown = !isYReverted ? (currentTest.expected & kScrollDown) :
   2614                                        (currentTest.expected & kScrollUp);
   2615        if (scrollUp) {
   2616          ok(gScrollableElement.scrollTop < kOrigScrollTop,
   2617             description + "not scrolled up, got " + gScrollableElement.scrollTop);
   2618        } else if (scrollDown) {
   2619          ok(gScrollableElement.scrollTop > kOrigScrollTop,
   2620             description + "not scrolled down, got " + gScrollableElement.scrollTop);
   2621        } else {
   2622          is(gScrollableElement.scrollTop, kOrigScrollTop,
   2623             description + "scrolled vertical");
   2624        }
   2625        var scrollLeft = !isXReverted ? (currentTest.expected & kScrollLeft) :
   2626                                        (currentTest.expected & kScrollRight);
   2627        var scrollRight = !isXReverted ? (currentTest.expected & kScrollRight) :
   2628                                         (currentTest.expected & kScrollLeft);
   2629        if (scrollLeft) {
   2630          ok(gScrollableElement.scrollLeft < kOrigScrollLeft,
   2631             description + "not scrolled to left, got " + gScrollableElement.scrollLeft);
   2632        } else if (scrollRight) {
   2633          ok(gScrollableElement.scrollLeft > kOrigScrollLeft,
   2634             description + "not scrolled to right, got " + gScrollableElement.scrollLeft);
   2635        } else {
   2636          is(gScrollableElement.scrollLeft, kOrigScrollLeft,
   2637             description + "scrolled horizontal");
   2638        }
   2639        // |isYReverted| and |isXReverted| have been temporarily swaped for
   2640        // auto-dir adjustment, restore them.
   2641        if (currentTest.adjusted) {
   2642          [isYReverted, isXReverted] = [isXReverted, isYReverted];
   2643        }
   2644      }
   2645      if (currentTest.cleanup) {
   2646        currentTest.cleanup(nextStep);
   2647      } else {
   2648        nextStep();
   2649      }
   2650 
   2651      function nextStep() {
   2652        winUtils.advanceTimeAndRefresh(100);
   2653        doNextTest();
   2654      }
   2655    });
   2656  }
   2657  doNextTest();
   2658 }
   2659 
   2660 function doTestZoom(aSettings, aCallback)
   2661 {
   2662  if ((aSettings.deltaMultiplierX != 1.0  && aSettings.deltaMultiplierX != -1.0) ||
   2663      (aSettings.deltaMultiplierY != 1.0  && aSettings.deltaMultiplierY != -1.0)) {
   2664    todo(false, "doTestZoom doesn't support to test with aSettings=" + aSettings.description);
   2665    SimpleTest.executeSoon(aCallback);
   2666    return;
   2667  }
   2668 
   2669  const kNone     = 0x00;
   2670  const kPositive = 0x01;
   2671  const kNegative = 0x02;
   2672  const kUseX     = 0x10;
   2673  const kUseY     = 0x20;
   2674  const kTests = [
   2675    { description: "by vertical/positive pixel event when its lineOrPageDeltaY is 0",
   2676      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2677               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
   2678               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2679               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2680      expected: kNone },
   2681    { description: "by vertical/positive pixel event when its lineOrPageDeltaY is 1",
   2682      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2683               deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
   2684               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1,
   2685               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2686      expected: kPositive | kUseY },
   2687    { description: "by vertical/negative pixel event when its lineOrPageDeltaY is 0",
   2688      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2689               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
   2690               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2691               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2692      expected: kNone },
   2693    { description: "by vertical/negative pixel event when its lineOrPageDeltaY is -1",
   2694      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2695               deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
   2696               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1,
   2697               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2698      expected: kNegative | kUseY },
   2699    { description: "by horizotal/positive pixel event when its lineOrPageDeltaX is 0",
   2700      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2701               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
   2702               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2703               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2704      expected: kNone },
   2705    { description: "by horizotal/positive pixel event when its lineOrPageDeltaX is 1",
   2706      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2707               deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
   2708               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0,
   2709               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2710      expected: kPositive | kUseX },
   2711    { description: "by horizotal/negative pixel event when its lineOrPageDeltaX is 0",
   2712      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2713               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
   2714               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2715               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2716      expected: kNone },
   2717    { description: "by horizotal/negative pixel event when its lineOrPageDeltaX is -1",
   2718      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2719               deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
   2720               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0,
   2721               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2722      expected: kNegative | kUseX },
   2723    { description: "by z pixel event",
   2724      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2725               deltaX: 0.0, deltaY: 0.0, deltaZ: 16.0,
   2726               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2727               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2728      expected: kNone },
   2729 
   2730    { description: "by vertical/positive line event when its lineOrPageDeltaY is 0",
   2731      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2732               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   2733               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2734               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2735      expected: kNone },
   2736    { description: "by vertical/positive line event when its lineOrPageDeltaY is 1",
   2737      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2738               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   2739               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1,
   2740               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2741      expected: kPositive | kUseY },
   2742    { description: "by vertical/negative line event when its lineOrPageDeltaY is 0",
   2743      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2744               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   2745               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2746               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2747      expected: kNone },
   2748    { description: "by vertical/negative line event when its lineOrPageDeltaY is -1",
   2749      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2750               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   2751               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1,
   2752               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2753      expected: kNegative | kUseY },
   2754    { description: "by horizotal/positive line event when its lineOrPageDeltaX is 0",
   2755      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2756               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   2757               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2758               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2759      expected: kNone },
   2760    { description: "by horizotal/positive line event when its lineOrPageDeltaX is 1",
   2761      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2762               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   2763               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0,
   2764               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2765      expected: kPositive | kUseX },
   2766    { description: "by horizotal/negative line event when its lineOrPageDeltaX is 0",
   2767      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2768               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   2769               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2770               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2771      expected: kNone },
   2772    { description: "by horizotal/negative line event when its lineOrPageDeltaX is -1",
   2773      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2774               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   2775               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0,
   2776               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2777      expected: kNegative | kUseX },
   2778    { description: "by z line event",
   2779      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   2780               deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
   2781               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2782               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2783      expected: kNone },
   2784 
   2785    { description: "by vertical/positive page event when its lineOrPageDeltaY is 0",
   2786      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2787               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   2788               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2789               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2790      expected: kNone },
   2791    { description: "by vertical/positive page event when its lineOrPageDeltaY is 1",
   2792      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2793               deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
   2794               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1,
   2795               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2796      expected: kPositive | kUseY },
   2797    { description: "by vertical/negative page event when its lineOrPageDeltaY is 0",
   2798      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2799               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   2800               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2801               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2802      expected: kNone },
   2803    { description: "by vertical/negative page event when its lineOrPageDeltaY is -1",
   2804      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2805               deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
   2806               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1,
   2807               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2808      expected: kNegative | kUseY },
   2809    { description: "by horizotal/positive page event when its lineOrPageDeltaX is 0",
   2810      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2811               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   2812               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2813               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2814      expected: kNone },
   2815    { description: "by horizotal/positive page event when its lineOrPageDeltaX is 1",
   2816      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2817               deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
   2818               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0,
   2819               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2820      expected: kPositive | kUseX },
   2821    { description: "by horizotal/negative page event when its lineOrPageDeltaX is 0",
   2822      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2823               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   2824               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2825               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2826      expected: kNone },
   2827    { description: "by horizotal/negative page event when its lineOrPageDeltaX is -1",
   2828      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2829               deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
   2830               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0,
   2831               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2832      expected: kNegative | kUseX },
   2833    { description: "by z page event",
   2834      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   2835               deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
   2836               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0,
   2837               expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0 },
   2838      expected: kNone },
   2839  ];
   2840 
   2841  var description, currentTest;
   2842  var currentTestIndex = -1;
   2843  var isXReverted = (aSettings.deltaMultiplierX < 0);
   2844  var isYReverted = (aSettings.deltaMultiplierY < 0);
   2845 
   2846  function doNextTest() {
   2847    if (++currentTestIndex >= kTests.length) {
   2848      SimpleTest.executeSoon(aCallback);
   2849      return;
   2850    }
   2851 
   2852    gScrollableElement.scrollTop = 1000;
   2853    gScrollableElement.scrollLeft = 1000;
   2854 
   2855    currentTest = kTests[currentTestIndex];
   2856    description = "doTestZoom(aSettings=" + aSettings.description + "), ";
   2857    if (currentTest.expected == kNone) {
   2858      description += "Shouldn't ";
   2859    } else {
   2860      description += "Should ";
   2861    }
   2862    description += "zoom " + currentTest.description + ": ";
   2863 
   2864    var event = currentTest.event;
   2865    event.ctrlKey  = true;
   2866 
   2867    // NOTE: Zooming might change scrollTop and scrollLeft by rounding fraction.
   2868    //       This test assume that zoom happens synchronously and scrolling
   2869    //       happens asynchronously.
   2870    var scrollTop = gScrollableElement.scrollTop;
   2871    var scrollLeft = gScrollableElement.scrollLeft;
   2872 
   2873    fullZoomChangePromise = new Promise(resolve => {
   2874      if (currentTest.expected & (kNegative | kPositive)) {
   2875        // Zoom causes a resize of the viewport.
   2876        window.addEventListener("resize", function onResize() {
   2877          if (SpecialPowers.getFullZoom(window) != 1) {
   2878            window.removeEventListener("resize", onResize);
   2879            setTimeout(() => resolve(), 0);
   2880          }
   2881        });
   2882      } else {
   2883        resolve();
   2884      }
   2885    });
   2886 
   2887    sendWheelAndWait(10, 10, event, function () {
   2888      is(gScrollableElement.scrollTop, scrollTop, description + "scrolled vertical");
   2889      is(gScrollableElement.scrollLeft, scrollLeft, description + "scrolled horizontal");
   2890 
   2891      fullZoomChangePromise.then(() => {
   2892        // When input event prioritization is enabled, the wheel event may be
   2893        // dispatched to the content process before the message 'FullZoom' to
   2894        // zoom in/out. Waiting for the event 'FullZoomChange' and then check
   2895        // the result.
   2896        if (!(currentTest.expected & (kNegative | kPositive))) {
   2897          is(SpecialPowers.getFullZoom(window), 1.0, description + "zoomed");
   2898        } else {
   2899          var isReverted = (currentTest.expected & kUseX) ? isXReverted :
   2900                           (currentTest.expected & kUseY) ? isYReverted : false;
   2901          if ((!isReverted && (currentTest.expected & kNegative)) ||
   2902              (isReverted && (currentTest.expected & kPositive))) {
   2903            ok(SpecialPowers.getFullZoom(window) > 1.0,
   2904               description + "not zoomed in, got " + SpecialPowers.getFullZoom(window));
   2905          } else {
   2906            ok(SpecialPowers.getFullZoom(window) < 1.0,
   2907               description + "not zoomed out, got " + SpecialPowers.getFullZoom(window));
   2908          }
   2909        }
   2910        if (SpecialPowers.getFullZoom(window) != 1) {
   2911          // Only synthesizes key event to reset zoom when necessary to avoid
   2912          // triggering the next test before the key event is handled. In that
   2913          // case, the key event may break the next test.
   2914          synthesizeKey("0", { accelKey: true });
   2915        }
   2916        onZoomReset(function () {
   2917          hitEventLoop(doNextTest, 20);
   2918        });
   2919      });
   2920    });
   2921  }
   2922  doNextTest();
   2923 }
   2924 
   2925 function doTestZoomedScroll(aCallback)
   2926 {
   2927  var zoom = 1.0;
   2928  function setFullZoom(aWindow, aZoom)
   2929  {
   2930    zoom = aZoom;
   2931    SpecialPowers.setFullZoom(aWindow, aZoom);
   2932  }
   2933 
   2934  function prepareTestZoomedPixelScroll()
   2935  {
   2936    // Reset zoom and store the scroll amount into the data.
   2937    synthesizeKey("0", { accelKey: true });
   2938    zoom = 1.0;
   2939    onZoomReset(testZoomedPixelScroll);
   2940  }
   2941 
   2942  function testZoomedPixelScroll()
   2943  {
   2944    gScrollableElement.scrollTop = 1000;
   2945    gScrollableElement.scrollLeft = 1000;
   2946    // Ensure not to be in reflow.
   2947    hitEventLoop(function () {
   2948      function mousePixelScrollHandler(aEvent)
   2949      {
   2950        if (aEvent.axis == MouseScrollEvent.HORIZONTAL_AXIS) {
   2951          is(aEvent.detail, 16,
   2952             "doTestZoomedScroll: The detail of horizontal MozMousePixelScroll for pixel wheel event is wrong");
   2953        } else if (aEvent.axis == MouseScrollEvent.VERTICAL_AXIS) {
   2954          is(aEvent.detail, 16,
   2955             "doTestZoomedScroll: The detail of vertical MozMousePixelScroll for pixel wheel event is wrong");
   2956        } else {
   2957          ok(false, "doTestZoomedScroll: The axis of MozMousePixelScroll for pixel wheel event is invalid, got " + aEvent.axis);
   2958        }
   2959      }
   2960      function wheelHandler(aEvent)
   2961      {
   2962        is(aEvent.deltaX, 16.0 / zoom,
   2963           "doTestZoomedScroll: The deltaX of wheel for pixel is wrong");
   2964        is(aEvent.deltaY, 16.0 / zoom,
   2965           "doTestZoomedScroll: The deltaY of wheel for pixel is wrong");
   2966      }
   2967      window.addEventListener("MozMousePixelScroll", mousePixelScrollHandler, true);
   2968      window.addEventListener("wheel", wheelHandler, true);
   2969      var event = {
   2970        deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2971        deltaX: 16.0,
   2972        deltaY: 16.0,
   2973        lineOrPageDeltaX: 0,
   2974        lineOrPageDeltaY: 0
   2975      };
   2976      // wait scrolled actually.
   2977      sendWheelAndWait(10, 10, event, function () {
   2978        var scrolledX = gScrollableElement.scrollLeft;
   2979        var scrolledY = gScrollableElement.scrollTop;
   2980        ok(scrolledX > 1000,
   2981           "doTestZoomedScroll: scrolledX must be larger than 1000 for pixel wheel event, got " + scrolledX);
   2982        ok(scrolledY > 1000,
   2983           "doTestZoomedScroll: scrolledY must be larger than 1000 for pixel wheel event, got " + scrolledY);
   2984 
   2985        // Zoom
   2986        setFullZoom(window, 2.0);
   2987        // Ensure not to be in reflow.
   2988        hitEventLoop(function () {
   2989          gScrollableElement.scrollTop = 1000;
   2990          gScrollableElement.scrollLeft = 1000;
   2991          var evt = {
   2992            deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   2993            deltaX: 16.0,
   2994            deltaY: 16.0,
   2995            lineOrPageDeltaX: 0,
   2996            lineOrPageDeltaY: 0
   2997          };
   2998          // wait scrolled actually.
   2999          sendWheelAndWait(10, 10, evt, function () {
   3000            ok(Math.abs(gScrollableElement.scrollLeft - (1000 + (scrolledX - 1000) / 2)) <= 1,
   3001               "doTestZoomedScroll: zoomed horizontal scroll amount by pixel wheel event is different from normal, scrollLeft=" +
   3002                 gScrollableElement.scrollLeft + ", scrolledX=" + scrolledX);
   3003            ok(Math.abs(gScrollableElement.scrollTop - (1000 + (scrolledY - 1000) / 2)) <= 1,
   3004               "doTestZoomedScroll: zoomed vertical scroll amount by pixel wheel event is different from normal, scrollTop=" +
   3005                 gScrollableElement.scrollTop + ", scrolledY=" + scrolledY);
   3006            window.removeEventListener("MozMousePixelScroll", mousePixelScrollHandler, true);
   3007            window.removeEventListener("wheel", wheelHandler, true);
   3008 
   3009            synthesizeKey("0", { accelKey: true });
   3010            onZoomReset(prepareTestZoomedLineScroll);
   3011          });
   3012        }, 20);
   3013      });
   3014    }, 20);
   3015  }
   3016 
   3017  function prepareTestZoomedLineScroll()
   3018  {
   3019    // Reset zoom and store the scroll amount into the data.
   3020    synthesizeKey("0", { accelKey: true });
   3021    zoom = 1.0;
   3022    onZoomReset(testZoomedLineScroll);
   3023  }
   3024  function testZoomedLineScroll()
   3025  {
   3026    gScrollableElement.scrollTop = 1000;
   3027    gScrollableElement.scrollLeft = 1000;
   3028    // Ensure not to be in reflow.
   3029    hitEventLoop(function () {
   3030      var lineHeightX, lineHeightY;
   3031      function handler(aEvent)
   3032      {
   3033        if (aEvent.axis == MouseScrollEvent.HORIZONTAL_AXIS) {
   3034          if (lineHeightX == undefined) {
   3035            lineHeightX = aEvent.detail;
   3036          } else {
   3037            ok(Math.abs(aEvent.detail - lineHeightX) <= 1,
   3038               "doTestZoomedScroll: The detail of horizontal MozMousePixelScroll for line wheel event is wrong, aEvent.detail=" +
   3039                 aEvent.detail + ", lineHeightX=" + lineHeightX);
   3040          }
   3041        } else if (aEvent.axis == MouseScrollEvent.VERTICAL_AXIS) {
   3042          if (lineHeightY == undefined) {
   3043            lineHeightY = aEvent.detail;
   3044          } else {
   3045            ok(Math.abs(aEvent.detail - lineHeightY) <= 1,
   3046               "doTestZoomedScroll: The detail of vertical MozMousePixelScroll for line wheel event is wrong, aEvent.detail=" +
   3047                 aEvent.detail + ", lineHeightY=" + lineHeightY);
   3048          }
   3049        } else {
   3050          ok(false, "doTestZoomedScroll: The axis of MozMousePixelScroll for line wheel event is invalid, got " + aEvent.axis);
   3051        }
   3052      }
   3053      window.addEventListener("MozMousePixelScroll", handler, true);
   3054      var event = {
   3055        deltaMode: WheelEvent.DOM_DELTA_LINE,
   3056        deltaX: 1.0,
   3057        deltaY: 1.0,
   3058        lineOrPageDeltaX: 1,
   3059        lineOrPageDeltaY: 1
   3060      };
   3061      // wait scrolled actually.
   3062      sendWheelAndWait(10, 10, event, function () {
   3063        var scrolledX = gScrollableElement.scrollLeft;
   3064        var scrolledY = gScrollableElement.scrollTop;
   3065        ok(scrolledX > 1000,
   3066           "doTestZoomedScroll: scrolledX must be larger than 1000 for line wheel event, got " + scrolledX);
   3067        ok(scrolledY > 1000,
   3068           "doTestZoomedScroll: scrolledY must be larger than 1000 for line wheel event, got " + scrolledY);
   3069 
   3070        // Zoom
   3071        setFullZoom(window, 2.0);
   3072        // Ensure not to be in reflow.
   3073        hitEventLoop(function () {
   3074          gScrollableElement.scrollTop = 1000;
   3075          gScrollableElement.scrollLeft = 1000;
   3076          var evt = {
   3077            deltaMode: WheelEvent.DOM_DELTA_LINE,
   3078            deltaX: 1.0,
   3079            deltaY: 1.0,
   3080            lineOrPageDeltaX: 1,
   3081            lineOrPageDeltaY: 1
   3082          };
   3083          // wait scrolled actually.
   3084          sendWheelAndWait(10, 10, evt, function () {
   3085            ok(Math.abs(gScrollableElement.scrollLeft - scrolledX) <= 1,
   3086               "doTestZoomedScroll: zoomed horizontal scroll amount by line wheel event is different from normal, scrollLeft=" +
   3087                 gScrollableElement.scrollLeft + ", scrolledX=" + scrolledX);
   3088            ok(Math.abs(gScrollableElement.scrollTop - scrolledY) <= 1,
   3089               "doTestZoomedScroll: zoomed vertical scroll amount by line wheel event is different from normal, scrollTop=" +
   3090                 gScrollableElement.scrollTop + ", scrolledY=" + scrolledY);
   3091 
   3092            window.removeEventListener("MozMousePixelScroll", handler, true);
   3093 
   3094            synthesizeKey("0", { accelKey: true });
   3095            onZoomReset(aCallback);
   3096          });
   3097        }, 20);
   3098      });
   3099    }, 20);
   3100  }
   3101 
   3102  // XXX It's too difficult to test page scroll because the page scroll amount
   3103  //     is computed by complex logic.
   3104 
   3105  prepareTestZoomedPixelScroll();
   3106 }
   3107 
   3108 function doTestWholeScroll(aCallback)
   3109 {
   3110  SpecialPowers.pushPrefEnv({"set": [
   3111    ["mousewheel.default.delta_multiplier_x", 999999],
   3112    ["mousewheel.default.delta_multiplier_y", 999999]]},
   3113    function() { doTestWholeScroll2(aCallback); });
   3114 }
   3115 
   3116 function doTestWholeScroll2(aCallback)
   3117 {
   3118  const kTests = [
   3119    { description: "try whole-scroll to top (line)",
   3120      prepare () {
   3121        gScrollableElement.scrollTop = 1000;
   3122        gScrollableElement.scrollLeft = 1000;
   3123      },
   3124      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3125               deltaX: 0.0, deltaY: -1.0,
   3126               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1 },
   3127      expectedScrollTop: 0,
   3128      expectedScrollLeft: 1000
   3129    },
   3130    { description: "try whole-scroll to top when scrollTop is already top-most (line)",
   3131      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3132               deltaX: 0.0, deltaY: -1.0,
   3133               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1 },
   3134      expectedScrollTop: 0,
   3135      expectedScrollLeft: 1000
   3136    },
   3137    { description: "try whole-scroll to bottom (line)",
   3138      prepare () {
   3139        gScrollableElement.scrollTop = 1000;
   3140        gScrollableElement.scrollLeft = 1000;
   3141      },
   3142      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3143               deltaX: 0.0, deltaY: 1.0,
   3144               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1 },
   3145      expectedScrollTop: gScrollableElement.scrollTopMax,
   3146      expectedScrollLeft: 1000
   3147    },
   3148    { description: "try whole-scroll to bottom when scrollTop is already bottom-most (line)",
   3149      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3150               deltaX: 0, deltaY: 1.0,
   3151               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1 },
   3152      expectedScrollTop: gScrollableElement.scrollTopMax,
   3153      expectedScrollLeft: 1000
   3154    },
   3155    { description: "try whole-scroll to left (line)",
   3156      prepare () {
   3157        gScrollableElement.scrollTop = 1000;
   3158        gScrollableElement.scrollLeft = 1000;
   3159      },
   3160      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3161               deltaX: -1.0, deltaY: 0.0,
   3162               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0 },
   3163      expectedScrollTop: 1000,
   3164      expectedScrollLeft: 0
   3165    },
   3166    { description: "try whole-scroll to left when scrollLeft is already left-most (line)",
   3167      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3168               deltaX: -1.0, deltaY: 0,
   3169               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0 },
   3170      expectedScrollTop: 1000,
   3171      expectedScrollLeft: 0
   3172    },
   3173    { description: "try whole-scroll to right (line)",
   3174      prepare () {
   3175        gScrollableElement.scrollTop = 1000;
   3176        gScrollableElement.scrollLeft = 1000;
   3177      },
   3178      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3179               deltaX: 1.0, deltaY: 0.0,
   3180               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0 },
   3181      expectedScrollTop: 1000,
   3182      expectedScrollLeft: gScrollableElement.scrollLeftMax
   3183    },
   3184    { description: "try whole-scroll to right when scrollLeft is already right-most (line)",
   3185      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3186               deltaX: 1.0, deltaY: 0.0,
   3187               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0 },
   3188      expectedScrollTop: 1000,
   3189      expectedScrollLeft: gScrollableElement.scrollLeftMax
   3190    },
   3191 
   3192 
   3193    { description: "try whole-scroll to top (pixel)",
   3194      prepare () {
   3195        gScrollableElement.scrollTop = 1000;
   3196        gScrollableElement.scrollLeft = 1000;
   3197      },
   3198      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   3199               deltaX: 0.0, deltaY: -1.0,
   3200               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
   3201      expectedScrollTop: 0,
   3202      expectedScrollLeft: 1000
   3203    },
   3204    { description: "try whole-scroll to top when scrollTop is already top-most (pixel)",
   3205      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   3206               deltaX: 0.0, deltaY: -1.0,
   3207               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
   3208      expectedScrollTop: 0,
   3209      expectedScrollLeft: 1000
   3210    },
   3211    { description: "try whole-scroll to bottom (pixel)",
   3212      prepare () {
   3213        gScrollableElement.scrollTop = 1000;
   3214        gScrollableElement.scrollLeft = 1000;
   3215      },
   3216      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   3217               deltaX: 0.0, deltaY: 1.0,
   3218               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
   3219      expectedScrollTop: gScrollableElement.scrollTopMax,
   3220      expectedScrollLeft: 1000
   3221    },
   3222    { description: "try whole-scroll to bottom when scrollTop is already bottom-most (pixel)",
   3223      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   3224               deltaX: 0, deltaY: 1.0,
   3225               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
   3226      expectedScrollTop: gScrollableElement.scrollTopMax,
   3227      expectedScrollLeft: 1000
   3228    },
   3229    { description: "try whole-scroll to left (pixel)",
   3230      prepare () {
   3231        gScrollableElement.scrollTop = 1000;
   3232        gScrollableElement.scrollLeft = 1000;
   3233      },
   3234      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   3235               deltaX: -1.0, deltaY: 0.0,
   3236               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
   3237      expectedScrollTop: 1000,
   3238      expectedScrollLeft: 0
   3239    },
   3240    { description: "try whole-scroll to left when scrollLeft is already left-most (pixel)",
   3241      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   3242               deltaX: -1.0, deltaY: 0,
   3243               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
   3244      expectedScrollTop: 1000,
   3245      expectedScrollLeft: 0
   3246    },
   3247    { description: "try whole-scroll to right (pixel)",
   3248      prepare () {
   3249        gScrollableElement.scrollTop = 1000;
   3250        gScrollableElement.scrollLeft = 1000;
   3251      },
   3252      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   3253               deltaX: 1.0, deltaY: 0.0,
   3254               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
   3255      expectedScrollTop: 1000,
   3256      expectedScrollLeft: gScrollableElement.scrollLeftMax
   3257    },
   3258    { description: "try whole-scroll to right when scrollLeft is already right-most (pixel)",
   3259      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
   3260               deltaX: 1.0, deltaY: 0.0,
   3261               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
   3262      expectedScrollTop: 1000,
   3263      expectedScrollLeft: gScrollableElement.scrollLeftMax
   3264    },
   3265 
   3266 
   3267    { description: "try whole-scroll to top (page)",
   3268      prepare () {
   3269        gScrollableElement.scrollTop = 1000;
   3270        gScrollableElement.scrollLeft = 1000;
   3271      },
   3272      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   3273               deltaX: 0.0, deltaY: -1.0,
   3274               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1 },
   3275      expectedScrollTop: 0,
   3276      expectedScrollLeft: 1000
   3277    },
   3278    { description: "try whole-scroll to top when scrollTop is already top-most (page)",
   3279      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   3280               deltaX: 0.0, deltaY: -1.0,
   3281               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1 },
   3282      expectedScrollTop: 0,
   3283      expectedScrollLeft: 1000
   3284    },
   3285    { description: "try whole-scroll to bottom (page)",
   3286      prepare () {
   3287        gScrollableElement.scrollTop = 1000;
   3288        gScrollableElement.scrollLeft = 1000;
   3289      },
   3290      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   3291               deltaX: 0.0, deltaY: 1.0,
   3292               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1 },
   3293      expectedScrollTop: gScrollableElement.scrollTopMax,
   3294      expectedScrollLeft: 1000
   3295    },
   3296    { description: "try whole-scroll to bottom when scrollTop is already bottom-most (page)",
   3297      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   3298               deltaX: 0, deltaY: 1.0,
   3299               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1 },
   3300      expectedScrollTop: gScrollableElement.scrollTopMax,
   3301      expectedScrollLeft: 1000
   3302    },
   3303    { description: "try whole-scroll to left (page)",
   3304      prepare () {
   3305        gScrollableElement.scrollTop = 1000;
   3306        gScrollableElement.scrollLeft = 1000;
   3307      },
   3308      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   3309               deltaX: -1.0, deltaY: 0.0,
   3310               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0 },
   3311      expectedScrollTop: 1000,
   3312      expectedScrollLeft: 0
   3313    },
   3314    { description: "try whole-scroll to left when scrollLeft is already left-most (page)",
   3315      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   3316               deltaX: -1.0, deltaY: 0,
   3317               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0 },
   3318      expectedScrollTop: 1000,
   3319      expectedScrollLeft: 0
   3320    },
   3321    { description: "try whole-scroll to right (page)",
   3322      prepare () {
   3323        gScrollableElement.scrollTop = 1000;
   3324        gScrollableElement.scrollLeft = 1000;
   3325      },
   3326      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   3327               deltaX: 1.0, deltaY: 0.0,
   3328               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0 },
   3329      expectedScrollTop: 1000,
   3330      expectedScrollLeft: gScrollableElement.scrollLeftMax
   3331    },
   3332    { description: "try whole-scroll to right when scrollLeft is already right-most (page)",
   3333      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
   3334               deltaX: 1.0, deltaY: 0.0,
   3335               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0 },
   3336      expectedScrollTop: 1000,
   3337      expectedScrollLeft: gScrollableElement.scrollLeftMax
   3338    },
   3339  ];
   3340 
   3341  var index = 0;
   3342 
   3343  function doIt()
   3344  {
   3345    const kTest = kTests[index];
   3346    if (kTest.prepare) {
   3347      kTest.prepare();
   3348    }
   3349    sendWheelAndWait(10, 10, kTest.event, function () {
   3350      is(gScrollableElement.scrollTop, kTest.expectedScrollTop,
   3351         "doTestWholeScroll, " + kTest.description + ": unexpected scrollTop");
   3352      is(gScrollableElement.scrollLeft, kTest.expectedScrollLeft,
   3353         "doTestWholeScroll, " + kTest.description + ": unexpected scrollLeft");
   3354      if (++index == kTests.length) {
   3355        SimpleTest.executeSoon(aCallback);
   3356      } else {
   3357        doIt();
   3358      }
   3359    });
   3360  }
   3361  doIt();
   3362 }
   3363 
   3364 function doTestActionOverride(aCallback)
   3365 {
   3366  const kNoScroll    = 0x00;
   3367  const kScrollUp    = 0x01;
   3368  const kScrollDown  = 0x02;
   3369  const kScrollLeft  = 0x04;
   3370  const kScrollRight = 0x08;
   3371 
   3372  const kTests = [
   3373    { action: kDefaultActionScroll, override_x: kDefaultActionOverrideXNoOverride,
   3374      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3375               deltaX: 1.0, deltaY: 1.0,
   3376               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3377      expected: kScrollDown | kScrollRight
   3378    },
   3379    { action: kDefaultActionScroll, override_x: kDefaultActionOverrideXNone,
   3380      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3381               deltaX: 1.0, deltaY: 1.0,
   3382               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3383      expected: kScrollDown | kScrollRight
   3384    },
   3385    { action: kDefaultActionScroll, override_x: kDefaultActionOverrideXScroll,
   3386      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3387               deltaX: 1.0, deltaY: 1.0,
   3388               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3389      expected: kScrollDown | kScrollRight
   3390    },
   3391    { action: kDefaultActionNone, override_x: kDefaultActionOverrideXNoOverride,
   3392      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3393               deltaX: 1.0, deltaY: 1.0,
   3394               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3395      expected: kNoScroll
   3396    },
   3397    { action: kDefaultActionNone, override_x: kDefaultActionOverrideXNone,
   3398      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3399               deltaX: 1.0, deltaY: 1.0,
   3400               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3401      expected: kNoScroll
   3402    },
   3403    { action: kDefaultActionNone, override_x: kDefaultActionOverrideXScroll,
   3404      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3405               deltaX: 1.0, deltaY: 1.0,
   3406               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3407      expected: kNoScroll
   3408    },
   3409    { action: kDefaultActionScroll, override_x: kDefaultActionOverrideXNoOverride,
   3410      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3411               deltaX: 1.0, deltaY: 0.5,
   3412               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3413      expected: kScrollDown | kScrollRight
   3414    },
   3415    { action: kDefaultActionScroll, override_x: kDefaultActionOverrideXNone,
   3416      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3417               deltaX: 1.0, deltaY: 0.5,
   3418               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3419      expected: kNoScroll
   3420    },
   3421    { action: kDefaultActionScroll, override_x: kDefaultActionOverrideXScroll,
   3422      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3423               deltaX: 1.0, deltaY: 0.5,
   3424               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3425      expected: kScrollDown | kScrollRight
   3426    },
   3427    { action: kDefaultActionNone, override_x: kDefaultActionOverrideXNoOverride,
   3428      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3429               deltaX: 1.0, deltaY: 0.5,
   3430               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3431      expected: kNoScroll
   3432    },
   3433    { action: kDefaultActionNone, override_x: kDefaultActionOverrideXNone,
   3434      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3435               deltaX: 1.0, deltaY: 0.5,
   3436               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3437      expected: kNoScroll
   3438    },
   3439    { action: kDefaultActionNone, override_x: kDefaultActionOverrideXScroll,
   3440      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3441               deltaX: 1.0, deltaY: 0.5,
   3442               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3443      expected: kScrollDown | kScrollRight
   3444    },
   3445    { action: kDefaultActionScroll, override_x: kDefaultActionOverrideXNoOverride,
   3446      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3447               deltaX: 0.5, deltaY: 1.0,
   3448               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3449      expected: kScrollDown | kScrollRight
   3450    },
   3451    { action: kDefaultActionScroll, override_x: kDefaultActionOverrideXNone,
   3452      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3453               deltaX: 0.5, deltaY: 1.0,
   3454               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3455      expected: kScrollDown | kScrollRight
   3456    },
   3457    { action: kDefaultActionScroll, override_x: kDefaultActionOverrideXScroll,
   3458      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3459               deltaX: 0.5, deltaY: 1.0,
   3460               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3461      expected: kScrollDown | kScrollRight
   3462    },
   3463    { action: kDefaultActionNone, override_x: kDefaultActionOverrideXNoOverride,
   3464      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3465               deltaX: 0.5, deltaY: 1.0,
   3466               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3467      expected: kNoScroll
   3468    },
   3469    { action: kDefaultActionNone, override_x: kDefaultActionOverrideXNone,
   3470      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3471               deltaX: 0.5, deltaY: 1.0,
   3472               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3473      expected: kNoScroll
   3474    },
   3475    { action: kDefaultActionNone, override_x: kDefaultActionOverrideXScroll,
   3476      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
   3477               deltaX: 0.5, deltaY: 1.0,
   3478               lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
   3479      expected: kNoScroll
   3480    },
   3481  ];
   3482 
   3483  var index = 0;
   3484 
   3485  function doIt()
   3486  {
   3487    const kTest = kTests[index];
   3488    SpecialPowers.pushPrefEnv({"set": [
   3489      ["mousewheel.default.action", kTest.action],
   3490      ["mousewheel.default.action.override_x", kTest.override_x]]},
   3491      doIt2
   3492    );
   3493  }
   3494 
   3495  function doIt2()
   3496  {
   3497    const kTest = kTests[index];
   3498    description = "doTestActionOverride(action=" + kTest.action + ", " +
   3499                  "override_x=" + kTest.override_x + ", " +
   3500                  "deltaX=" + kTest.event.deltaX + ", " +
   3501                  "deltaY=" + kTest.event.deltaY + "): ";
   3502    gScrollableElement.scrollTop = 1000;
   3503    gScrollableElement.scrollLeft = 1000;
   3504    sendWheelAndWait(10, 10, kTest.event, function () {
   3505      if (kTest.expected & kScrollUp) {
   3506        ok(gScrollableElement.scrollTop < 1000, description + "not scrolled up, got " + gScrollableElement.scrollTop);
   3507      } else if (kTest.expected & kScrollDown) {
   3508        ok(gScrollableElement.scrollTop > 1000, description + "not scrolled down, got " + gScrollableElement.scrollTop);
   3509      } else {
   3510        is(gScrollableElement.scrollTop, 1000, description + "scrolled vertical");
   3511      }
   3512      if (kTest.expected & kScrollLeft) {
   3513        ok(gScrollableElement.scrollLeft < 1000, description + "not scrolled to left, got " + gScrollableElement.scrollLeft);
   3514      } else if (kTest.expected & kScrollRight) {
   3515        ok(gScrollableElement.scrollLeft > 1000, description + "not scrolled to right, got " + gScrollableElement.scrollLeft);
   3516      } else {
   3517        is(gScrollableElement.scrollLeft, 1000, description + "scrolled horizontal");
   3518      }
   3519      if (++index == kTests.length) {
   3520        SimpleTest.executeSoon(aCallback);
   3521      } else {
   3522        doIt();
   3523      }
   3524    });
   3525  }
   3526  doIt();
   3527 }
   3528 
   3529 function runTests()
   3530 {
   3531  SpecialPowers.pushPrefEnv({"set": [
   3532    ["test.events.async.enabled", true],
   3533    ["general.smoothScroll", false],
   3534    ["mousewheel.default.action", kDefaultActionScroll],
   3535    ["mousewheel.default.action.override_x", kDefaultActionOverrideXNoOverride],
   3536    ["mousewheel.with_shift.action", kDefaultActionHorizontalizedScroll],
   3537    ["mousewheel.with_shift.action.override_x", kDefaultActionOverrideXNoOverride],
   3538    ["mousewheel.with_control.action", kDefaultActionZoom],
   3539    ["mousewheel.with_control.action.override_x", kDefaultActionOverrideXNoOverride],
   3540    ["mousewheel.with_alt.action", kDefaultActionHistory],
   3541    ["mousewheel.with_alt.action.override_x", kDefaultActionOverrideXNoOverride]]},
   3542    runTests2);
   3543 }
   3544 
   3545 function runTests2()
   3546 {
   3547  const kSettings = [
   3548    { description: "all delta values are not customized",
   3549      deltaMultiplierX:  1.0, deltaMultiplierY:  1.0, deltaMultiplierZ:  1.0 },
   3550    { description: "deltaX is reverted",
   3551      deltaMultiplierX: -1.0, deltaMultiplierY:  1.0, deltaMultiplierZ:  1.0 },
   3552    { description: "deltaY is reverted",
   3553      deltaMultiplierX:  1.0, deltaMultiplierY: -1.0, deltaMultiplierZ:  1.0 },
   3554    // Unless you really don't care a snap on time-consuming testing or a strict
   3555    // criteria is required for testing, it is strongly recommeneded that you
   3556    // comment the unrealistic case out.
   3557    //{ description: "deltaZ is reverted",
   3558    //  deltaMultiplierX:  1.0, deltaMultiplierY:  1.0, deltaMultiplierZ: -1.0 },*/
   3559    { description: "deltaX is 2.0",
   3560      deltaMultiplierX:  2.0, deltaMultiplierY:  1.0, deltaMultiplierZ:  1.0 },
   3561    { description: "deltaY is 2.0",
   3562      deltaMultiplierX:  1.0, deltaMultiplierY:  2.0, deltaMultiplierZ:  1.0 },
   3563    // Unless you really don't care a snap on time-consuming testing or a strict
   3564    // criteria is required for testing, it is strongly recommeneded that you
   3565    // comment the unrealistic case out.
   3566    //{ description: "deltaZ is 2.0",
   3567    //  deltaMultiplierX:  1.0, deltaMultiplierY:  1.0, deltaMultiplierZ:  2.0 },
   3568    //{ description: "deltaX is -2.0",
   3569    //  deltaMultiplierX: -2.0, deltaMultiplierY:  1.0, deltaMultiplierZ:  1.0 },
   3570    //{ description: "deltaY is -2.0",
   3571    //  deltaMultiplierX:  1.0, deltaMultiplierY: -2.0, deltaMultiplierZ:  1.0 },
   3572    //{ description: "deltaZ is -2.0",
   3573    //  deltaMultiplierX:  1.0, deltaMultiplierY:  1.0, deltaMultiplierZ: -2.0 },
   3574  ];
   3575 
   3576  var index = 0;
   3577 
   3578  function doTest() {
   3579    setDeltaMultiplierSettings(kSettings[index], function () {
   3580      doTestScroll(kSettings[index], function () {
   3581        doTestAutoDirScroll(kSettings[index], {honoursRoot: false}, function () {
   3582          doTestAutoDirScroll(kSettings[index], {honoursRoot: true}, function () {
   3583            doTestHorizontalizedScroll(kSettings[index], function() {
   3584              doTestZoom(kSettings[index], function() {
   3585                if (++index == kSettings.length) {
   3586                  setDeltaMultiplierSettings(kSettings[0], function() {
   3587                    doTestZoomedScroll(function() {
   3588                      doTestWholeScroll(function() {
   3589                        doTestActionOverride(function() {
   3590                          finishTests();
   3591                        });
   3592                      });
   3593                    });
   3594                  });
   3595                } else {
   3596                  doTest();
   3597                }
   3598              });
   3599            });
   3600          });
   3601        });
   3602      });
   3603    });
   3604  }
   3605  doTest();
   3606 }
   3607 
   3608 function finishTests()
   3609 {
   3610  winUtils.restoreNormalRefresh();
   3611 
   3612  window.opener.finish();
   3613 }
   3614 
   3615 </script>
   3616 </pre>
   3617 </body>
   3618 </html>