tor-browser

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

printpreview_helper.xhtml (66394B)


      1 <?xml version="1.0"?>
      2 <?xml-stylesheet type="text/css" href="chrome://global/skin"?>
      3 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
      4                 type="text/css"?>
      5 <window onload="runTests()"
      6        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
      7  <iframe style="min-height: 200px; min-width: 600px" type="content"></iframe>
      8  <iframe style="min-height: 200px; min-width: 600px" type="content"></iframe>
      9 <script type="application/javascript">
     10 <![CDATA[
     11 // Note: We can't use window.frames directly here because the type="content"
     12 // attributes isolate the frames into their own BrowsingContext hierarchies.
     13 let frameElts = document.getElementsByTagName("iframe");
     14 
     15 var is = window.arguments[0].is;
     16 var isnot = window.arguments[0].isnot;
     17 var ok = window.arguments[0].ok;
     18 var todo = window.arguments[0].todo;
     19 var info = window.arguments[0].info;
     20 var SimpleTest = window.arguments[0].SimpleTest;
     21 var gWbp;
     22 var gPrintPreviewWindow;
     23 var gPrintPreviewBrowser;
     24 var ctx1;
     25 var ctx2;
     26 var counter = 0;
     27 
     28 var file = Cc["@mozilla.org/file/directory_service;1"]
     29             .getService(Ci.nsIProperties)
     30             .get("TmpD", Ci.nsIFile);
     31 filePath = file.path;
     32 
     33 function printpreview(options = {}) {
     34  let resolve;
     35  let promise = new Promise(r => { resolve = r });
     36  var listener = {
     37    onLocationChange: function(webProgress, request, location, flags) { },
     38    onProgressChange: function(webProgress, request, curSelfProgress,
     39                               maxSelfProgress, curTotalProgress,
     40                               maxTotalProgress) {
     41      info("onProgressChange", [...arguments].join(", "));
     42    },
     43    onSecurityChange: function(webProgress, request, state) { },
     44    onStateChange: function(webProgress, request, stateFlags, status) {
     45      info("onStateChange", [...arguments].join(", "));
     46      if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
     47        setTimeout(resolve, 0);
     48      }
     49    },
     50    onStatusChange: function(webProgress, request, status, message) {
     51      info("onStatusChange", [...arguments].join(", "));
     52    },
     53    onContentBlockingEvent: function(webProgress, request, event) {
     54      info("onContentBlockingEvent", [...arguments].join(", "));
     55    },
     56    QueryInterface: function(iid) {
     57      if (iid.equals(Ci.nsIWebProgressListener) ||
     58          iid.equals(Ci.nsISupportsWeakReference))
     59            return this;
     60      throw Components.Exception("", Cr.NS_NOINTERFACE);
     61    }
     62  }
     63  var settings = Cc["@mozilla.org/gfx/printsettings-service;1"]
     64                       .getService(Ci.nsIPrintSettingsService).createNewPrintSettings();
     65  settings.printBGColors = true;
     66  settings.headerStrLeft = "";
     67  settings.headerStrRight = "";
     68  settings.footerStrLeft = "";
     69  settings.footerStrRight = "";
     70  settings.unwriteableMarginTop = 0;
     71  settings.unwriteableMarginRight = 0;
     72  settings.unwriteableMarginLeft = 0;
     73  settings.unwriteableMarginBottom = 0;
     74  if (options.settings) {
     75    for (let key in options.settings) {
     76      settings[key] = options.settings[key];
     77    }
     78  }
     79  var before = 0;
     80  var after = 0;
     81  function beforeprint() { ++before; }
     82  function afterprint() { ++after; }
     83  frameElts[0].contentWindow.addEventListener("beforeprint", beforeprint, true);
     84  frameElts[0].contentWindow.addEventListener("afterprint", afterprint, true);
     85  {
     86    let bc = frameElts[0].contentWindow.browsingContext;
     87    let browser = document.createXULElement("browser");
     88    browser.setAttribute("type", "content");
     89    browser.style.minHeight = "800px";
     90    browser.style.maxWidth = browser.style.minWidth = "800px";
     91    browser.setAttribute("initialBrowsingContextGroupId", bc.group.id);
     92    browser.setAttribute("nodefaultsrc", "true");
     93    document.documentElement.appendChild(browser);
     94    gPrintPreviewBrowser = browser;
     95 
     96    // Force docViewer creation and layout.
     97    browser.browsingContext.docShell.document;
     98    browser.getBoundingClientRect();
     99 
    100    gPrintPreviewWindow = frameElts[0].contentWindow.printPreview(settings, listener, browser.browsingContext.docShell);
    101  }
    102  gWbp = gPrintPreviewWindow.docShell.docViewer;
    103  gWbp.QueryInterface(Ci.nsIWebBrowserPrint);
    104  is(before, 1, "Should have called beforeprint listener!");
    105  if (!options.hasMozPrintCallback) {
    106    // If there's a mozPrintCallback the after print event won't fire until
    107    // later.
    108    is(after, 1, "Should have called afterprint listener!");
    109  }
    110  frameElts[0].contentWindow.removeEventListener("beforeprint", beforeprint, true);
    111  frameElts[0].contentWindow.removeEventListener("afterprint", afterprint, true);
    112  return promise;
    113 }
    114 
    115 function exitprintpreview() {
    116  gPrintPreviewWindow.docShell.exitPrintPreview();
    117  gPrintPreviewBrowser.remove();
    118 }
    119 
    120 function finish() {
    121  SimpleTest.finish();
    122  window.close();
    123 }
    124 
    125 async function runTests()
    126 {
    127  // This ensures we actually test the lazy-load of images in printpreview_images.
    128  await SpecialPowers.pushPrefEnv({
    129    set: [
    130      ["dom.lazy-loading.margin.top", 0],
    131      ["dom.lazy-loading.margin.bottom", 0],
    132      ["dom.lazy-loading.margin.left", 0],
    133      ["dom.lazy-loading.margin.right", 0],
    134    ],
    135  });
    136  startTest1();
    137 }
    138 
    139 function compareCanvases(options = {}) {
    140  const canvas1 = document.getElementsByTagName("canvas")[0];
    141  const canvas2 = document.getElementsByTagName("canvas")[1];
    142  let maxDifference = {};
    143  const differingPixels = window.windowUtils.compareCanvases(canvas1, canvas2, maxDifference);
    144  if (differingPixels) {
    145    todo(false, "different: " + differingPixels + ", maxDifference: " + maxDifference.value);
    146    todo(false, "TEST CASE: " + canvas1.toDataURL());
    147    todo(false, "REFERENCE: " + canvas2.toDataURL());
    148  }
    149 
    150  let maxAllowedDifferent = options.maxDifferent || 0;
    151  let maxAllowedDifference = options.maxDifference || 0;
    152  return differingPixels <= maxAllowedDifferent && maxDifference.value <= maxAllowedDifference;
    153 }
    154 
    155 function addHTMLContent(parent) {
    156  var n = parent.ownerDocument.createElement("div");
    157  parent.appendChild(n);
    158  var s = "<iframe width='500' height='40' src='data:text/plain,ThisIsAnIframeCreatedDuringPrintPreview'></iframe>";
    159  s += "<table>";
    160  for (var i = 1; i < 501; ++i) {
    161    s += "<tr><td>Cell A" + i + "</td><td>Cell B" + i + "</td><td>Cell C" + i + "</td></tr>";
    162  }
    163  s += "</table>";
    164  n.innerHTML = s;
    165 }
    166 
    167 async function startTest1() {
    168  ctx1 = document.getElementsByTagName("canvas")[0].getContext("2d");
    169  ctx2 = document.getElementsByTagName("canvas")[1].getContext("2d");
    170  frameElts[0].contentDocument.body.innerHTML = "<div> </div><div>" + counter + " timers</div><div> </div>";
    171 
    172  // Note this timeout is needed so that we can check that timers run
    173  // after print preview, but not during it.
    174  frameElts[0].contentWindow.wrappedJSObject.counter = counter;
    175  frameElts[0].contentWindow.counterTimeout = "document.body.firstChild.nextSibling.innerHTML = ++counter + ' timers';" +
    176                                    "window.setTimeout(counterTimeout, 0);";
    177  frameElts[0].contentWindow.setTimeout(frameElts[0].contentWindow.counterTimeout, 0);
    178  frameElts[0].contentDocument.body.firstChild.innerHTML = "Print preview";
    179 
    180  await printpreview();
    181  drawPrintPreviewWindow(ctx1);
    182  frameElts[0].contentDocument.body.firstChild.innerHTML = "Galley presentation";
    183 
    184  // Add some elements.
    185  addHTMLContent(frameElts[0].contentDocument.body.lastChild);
    186  // Delete them.
    187  frameElts[0].contentDocument.body.lastChild.innerHTML = "";
    188  // And readd.
    189  addHTMLContent(frameElts[0].contentDocument.body.lastChild);
    190 
    191  setTimeout(finalizeTest1, 1000);
    192 }
    193 
    194 function finalizeTest1() {
    195  drawPrintPreviewWindow(ctx2);
    196  exitprintpreview();
    197  ok(compareCanvases(), "Canvas should be the same!");
    198  counter = frameElts[0].contentWindow.counter;
    199  // This timeout is needed so that we can check that timers do run after
    200  // print preview.
    201  setTimeout(runTest2, 1000);
    202 }
    203 
    204 function runTest2() {
    205  isnot(frameElts[0].contentDocument.body.firstChild.nextSibling.textContent, "0 timers", "Timers should have run!");
    206  isnot(frameElts[0].contentWindow.counter, 0, "Timers should have run!");
    207  counter = frameElts[0].contentWindow.counter;
    208  frameElts[0].contentWindow.counterTimeout = "";
    209  setTimeout(runTest3, 0);
    210 }
    211 
    212 var elementIndex = 0;
    213 var compareEmptyElement = true;
    214 var emptyFormElements =
    215  ["<input type='text'>",
    216   "<input type='password'>",
    217   "<input type='file'>",
    218   "<input type='button'>",
    219   "<input type='submit'>",
    220   "<input type='reset'>",
    221   "<input type='checkbox'>",
    222   "<input type='radio'>",
    223   "<select></select>",
    224   "<select size='5'></select>",
    225   "<textarea></textarea>"];
    226 
    227 var formElements =
    228  ["<input type='text' value='text'>",
    229   "<input type='password' value='password'>",
    230   "<input type='file' value='" + filePath + "'>",
    231   "<input type='button' value='button'>",
    232   "<input type='submit' value='submit button'>",
    233   "<input type='reset' value='reset button'>",
    234   "<input type='checkbox' checked>",
    235   "<input type='radio' checked>",
    236   "<select><option>option1</option></select>",
    237   "<select size='5'><option>1</option><option>2</option><option>3</option></select>",
    238   "<textarea value='textarea'>textarea</textarea>"];
    239 
    240 function runTest3() {
    241  if (compareEmptyElement) {
    242    var currentIndex = elementIndex;
    243    ++elementIndex;
    244    if (elementIndex >= emptyFormElements.length) {
    245      elementIndex = 0;
    246      compareEmptyElement = false;
    247    }
    248    compareFormElementPrint(emptyFormElements[currentIndex], emptyFormElements[currentIndex], true);
    249    return;
    250  } else if (elementIndex < emptyFormElements.length) {
    251    var currentIndex = elementIndex;
    252    ++elementIndex;
    253    compareFormElementPrint(emptyFormElements[currentIndex], formElements[currentIndex], false);
    254    return;
    255  }
    256 
    257  setTimeout(runTest4, 0)
    258 }
    259 
    260 async function compareFormElementPrint(el1, el2, equals) {
    261  frameElts[0].contentDocument.body.innerHTML = el1;
    262  frameElts[0].contentDocument.body.firstChild.value =
    263    frameElts[0].contentDocument.body.firstChild.getAttribute('value');
    264  await printpreview();
    265  drawPrintPreviewWindow(ctx1);
    266  exitprintpreview();
    267  frameElts[0].contentDocument.body.innerHTML = el2;
    268  frameElts[0].contentDocument.body.firstChild.value =
    269    frameElts[0].contentDocument.body.firstChild.getAttribute('value');
    270  await printpreview();
    271  drawPrintPreviewWindow(ctx2);
    272  exitprintpreview();
    273  is(compareCanvases(), equals,
    274     "Comparing print preview didn't succeed [" + el1 + " : " + el2 + "]");
    275  setTimeout(runTest3, 100);
    276 }
    277 
    278 // This is a crash test for bug 539060.
    279 function runTest4() {
    280  frameElts[0].contentDocument.body.innerHTML =
    281    "<iframe style='display: none;' src='data:text/html,<iframe>'></iframe>";
    282  setTimeout(runTest4end, 500);
    283 }
    284 
    285 async function runTest4end() {
    286  await printpreview();
    287  exitprintpreview();
    288 
    289  runTest5();
    290 }
    291 
    292 // This is a crash test for bug 595337
    293 async function runTest5() {
    294  frameElts[0].contentDocument.body.innerHTML =
    295    '<iframe style="position: fixed; visibility: hidden; bottom: 10em;"></iframe>' +
    296    '<input contenteditable="true" style="display: table; page-break-before: left; width: 10000px;">';
    297  await printpreview();
    298  exitprintpreview();
    299 
    300  setTimeout(runTest6, 0);
    301 }
    302 
    303 // Crash test for bug 878037
    304 function runTest6() {
    305  frameElts[0].contentDocument.body.innerHTML =
    306    '<style> li { list-style-image: url("animated.gif"); } </style>' +
    307    '<li>Firefox will crash if you try and print this page</li>';
    308 
    309  setTimeout(runTest6end, 500);
    310 }
    311 
    312 async function runTest6end() {
    313  await printpreview();
    314  exitprintpreview();
    315 
    316  requestAnimationFrame(function() { setTimeout(runTest7); } );
    317 }
    318 
    319 async function runTest7() {
    320  var contentText = "<a href='#'>mozilla</a><input>test<select><option>option1</option></select>";
    321  // Create normal content
    322  frameElts[0].contentDocument.body.innerHTML =
    323    "<div>" + contentText + "</div>";
    324  frameElts[0].contentDocument.body.firstChild.value =
    325    frameElts[0].contentDocument.body.firstChild.getAttribute('value');
    326  await printpreview();
    327  drawPrintPreviewWindow(ctx1);
    328  exitprintpreview();
    329 
    330  frameElts[0].contentDocument.body.innerHTML = "<div></div>";
    331  var sr = frameElts[0].contentDocument.body.firstChild.attachShadow({mode: "open"});
    332  sr.innerHTML = contentText;
    333  await printpreview();
    334  drawPrintPreviewWindow(ctx2);
    335  exitprintpreview();
    336  ok(compareCanvases(), "Printing light DOM and shadow DOM should create same output");
    337 
    338  requestAnimationFrame(function() { setTimeout(runTest8); } );
    339 }
    340 
    341 async function runTest8() {
    342  // Test that fonts loaded with CSS and JS are printed the same.
    343  const iframeElement = document.getElementsByTagName("iframe")[0];
    344 
    345  // First, snapshot the page with font defined in CSS.
    346  await new Promise((resolve) => {
    347    iframeElement.addEventListener("load", resolve, { capture: true, once: true });
    348    iframeElement.setAttribute("src", "printpreview_font_api_ref.html");
    349  });
    350  await printpreview();
    351  drawPrintPreviewWindow(ctx1);
    352  exitprintpreview();
    353 
    354  // Second, snapshot the page with font loaded in JS.
    355  await new Promise((resolve) => {
    356    iframeElement.addEventListener("message", resolve, { capture: true, once: true });
    357    iframeElement.setAttribute("src", "printpreview_font_api.html");
    358  });
    359  await printpreview();
    360  drawPrintPreviewWindow(ctx2);
    361  exitprintpreview();
    362  ok(compareCanvases(), "Printing pages with fonts loaded from CSS and JS should be the same.");
    363 
    364  requestAnimationFrame(function() { setTimeout(runTest9); } );
    365 }
    366 
    367 // Test for bug 1487649
    368 async function runTest9() {
    369  frameElts[0].contentDocument.body.innerHTML = `
    370    <svg width="100" height="100">
    371      <rect width='100' height='100' fill='lime'/>
    372    </svg>
    373  `;
    374 
    375  await printpreview();
    376  drawPrintPreviewWindow(ctx1);
    377  exitprintpreview();
    378 
    379  frameElts[0].contentDocument.body.innerHTML = `
    380    <svg width="100" height="100">
    381      <defs>
    382        <g id="useme">
    383          <rect width='100' height='100' fill='lime'/>
    384        </g>
    385      </defs>
    386      <use />
    387    </svg>
    388  `;
    389 
    390  // Set the attribute explicitly because this is a chrome document, and the
    391  // href attribute would get sanitized.
    392  frameElts[0].contentDocument.querySelector("use").setAttribute("href", "#useme");
    393 
    394  // Ensure the <use> shadow tree is created so we test what we want to test.
    395  frameElts[0].contentDocument.body.offsetTop;
    396 
    397  await printpreview();
    398  drawPrintPreviewWindow(ctx2);
    399  exitprintpreview();
    400  ok(compareCanvases(), "Printing <use> subtrees should create same output");
    401 
    402  requestAnimationFrame(function() { setTimeout(runTest10); } );
    403 }
    404 
    405 function drawPrintPreviewWindow(ctx) {
    406  let width = gPrintPreviewWindow.innerWidth;
    407  let height = gPrintPreviewWindow.innerHeight;
    408  ctx.canvas.width = width;
    409  ctx.canvas.height = height;
    410  ctx.drawWindow(gPrintPreviewWindow, 0, 0, width, height, "rgb(255, 255, 255)");
    411 }
    412 
    413 // Test for bug 1524640
    414 async function runTest10() {
    415  // Test that fonts loaded during mozprint callback are loaded into the cloned
    416  // document.
    417  const iframeElement = document.getElementsByTagName("iframe")[0];
    418 
    419  // First, snapshot the page with font defined in CSS.
    420  await new Promise((resolve) => {
    421    iframeElement.addEventListener("load", resolve, { capture: true, once: true });
    422    iframeElement.setAttribute("src", "printpreview_font_mozprintcallback_ref.html");
    423  });
    424  let mozPrintCallbackDone = new Promise((resolve) => {
    425    iframeElement.addEventListener("message", resolve, { capture: true, once: true });
    426  });
    427  await printpreview({ hasMozPrintCallback: true });
    428  await mozPrintCallbackDone;
    429  drawPrintPreviewWindow(ctx1);
    430  exitprintpreview();
    431 
    432  // Second, snapshot the page with font loaded in JS.
    433  await new Promise((resolve) => {
    434    iframeElement.addEventListener("load", resolve, { capture: true, once: true });
    435    iframeElement.setAttribute("src", "printpreview_font_mozprintcallback.html");
    436  });
    437  mozPrintCallbackDone = new Promise((resolve) => {
    438    iframeElement.addEventListener("message", resolve, { capture: true, once: true });
    439  });
    440  await printpreview({ hasMozPrintCallback: true });
    441  // Wait for the mozprintcallback to finish.
    442  await mozPrintCallbackDone;
    443  drawPrintPreviewWindow(ctx2);
    444 
    445  exitprintpreview();
    446  ok(compareCanvases(), "Printing pages with fonts loaded from a mozPrintCallback should be the same.");
    447 
    448  requestAnimationFrame(function() { setTimeout(runTest11); } );
    449 }
    450 
    451 async function compareFiles(src1, src2, options = {}) {
    452  const BASE = "https://example.org/chrome/layout/base/tests/chrome/";
    453 
    454  info(`Comparing ${src1} with ${src2}`);
    455  const iframeElement = document.getElementsByTagName("iframe")[0];
    456 
    457  let messagePromise = null;
    458  if (options.waitForMessage) {
    459    messagePromise = new Promise(resolve => {
    460      iframeElement.addEventListener("message", resolve, { capture: true, once: true });
    461    });
    462  }
    463 
    464  await new Promise((resolve) => {
    465    iframeElement.addEventListener("load", resolve, { capture: true, once: true });
    466    iframeElement.setAttribute("src", new URL(src1, BASE).href);
    467  });
    468  let mediaElements = iframeElement.contentDocument.querySelectorAll(
    469    "audio, video"
    470  );
    471  for (let mediaElement of mediaElements) {
    472    let { widget } = SpecialPowers.wrap(iframeElement.contentWindow)
    473      .windowGlobalChild.getActor("UAWidgets")
    474      .widgets.get(mediaElement);
    475    await widget.impl.Utils.l10n.translateRoots();
    476  }
    477 
    478  if (messagePromise) {
    479    info("awaiting for message to arrive");
    480    await messagePromise;
    481  }
    482 
    483  await printpreview(options.test || options);
    484  drawPrintPreviewWindow(ctx1);
    485  exitprintpreview();
    486 
    487  await new Promise((resolve) => {
    488    iframeElement.addEventListener("load", resolve, { capture: true, once: true });
    489    iframeElement.setAttribute("src", new URL(src2, BASE).href);
    490  });
    491  mediaElements = iframeElement.contentDocument.querySelectorAll(
    492    "audio, video"
    493  );
    494  for (let mediaElement of mediaElements) {
    495    let { widget } = SpecialPowers.wrap(iframeElement.contentWindow)
    496      .windowGlobalChild.getActor("UAWidgets")
    497      .widgets.get(mediaElement);
    498    await widget.impl.Utils.l10n.translateRoots();
    499  }
    500 
    501  await printpreview(options.ref || options);
    502  drawPrintPreviewWindow(ctx2);
    503  exitprintpreview();
    504 
    505  is(compareCanvases(options), !options.expectDifference, `Printing ${src1} and ${src2} should${options.expectDifference ? ' not' : ''} produce the same results`);
    506 }
    507 
    508 // bug 1567105
    509 async function runTest11() {
    510  await compareFiles("printpreview_quirks.html", "printpreview_quirks_ref.html");
    511  requestAnimationFrame(function() { setTimeout(runTest12); } );
    512 }
    513 
    514 // bug 1621415
    515 async function runTest12() {
    516  await compareFiles("test_document_adopted_styles.html", "test_document_adopted_styles_ref.html");
    517  requestAnimationFrame(function() { setTimeout(runTest13); } );
    518 }
    519 
    520 // bug 1621415
    521 async function runTest13() {
    522  await compareFiles("test_shadow_root_adopted_styles.html", "test_shadow_root_adopted_styles_ref.html");
    523  requestAnimationFrame(function() { setTimeout(runTest14); } );
    524 }
    525 
    526 // bug 1622322
    527 async function runTest14() {
    528  await compareFiles("test_shared_adopted_styles.html", "test_shared_adopted_styles_ref.html");
    529  requestAnimationFrame(function() { setTimeout(runTest15); } );
    530 }
    531 
    532 // Crash test for bug 1615261
    533 async function runTest15() {
    534  frameElts[0].contentDocument.body.innerHTML =
    535    '<style>div { width: 100px; height: 100px; background-image: url("animated.gif"); } </style>' +
    536    '<div>Firefox will crash if you try and print this page</div>';
    537 
    538  // XXX Is there a more reliable way to wait for the background-image to load?
    539  await new Promise(resolve => setTimeout(resolve, 500));
    540 
    541  await printpreview();
    542  await exitprintpreview();
    543 
    544  requestAnimationFrame(function() { setTimeout(runTest16); } );
    545 }
    546 
    547 // Various image tests.
    548 async function runTest16() {
    549  // fuzzy: SVG image in the test pixel-snaps different than <div> in the ref.
    550  // (And on WebRender, the pixel-snapping seems to shift some pixels over a
    551  // bit such that they're fully white vs. fully blue; hence 255 as the allowed
    552  // color-channel difference.)
    553  // XXXdholbert We should revisit this and adjust these thresholds (hopefully
    554  // lower) after bug 1602410 lands.
    555  await compareFiles("printpreview_images.html", "printpreview_images_ref.html", { maxDifferent: 118, maxDifference: 255 });
    556  requestAnimationFrame(function() { setTimeout(runTest17); } );
    557 }
    558 
    559 async function runTest17() {
    560  // fuzzy: SVG image in the test pixel-snaps different than <div> in the ref.
    561  // (And on WebRender, the pixel-snapping seems to shift some pixels over a
    562  // bit such that they're fully white vs. fully blue; hence 255 as the allowed
    563  // color-channel difference.)
    564  // XXXdholbert We should revisit this and adjust these thresholds (hopefully
    565  // lower) after bug 1602410 lands.
    566  await compareFiles("printpreview_images_sw.html", "printpreview_images_sw_ref.html", { waitForMessage: true, maxDifferent: 118, maxDifference: 255 });
    567  requestAnimationFrame(() => setTimeout(runTest18));
    568 }
    569 
    570 async function runTest18() {
    571  await compareFiles("printpreview_quirks.html", "printpreview_quirks_ref.html", {
    572    settings: {
    573      marginTop: 22,
    574      marginBottom: 22,
    575      marginLeft: 22,
    576      marginRight: 22,
    577    },
    578  });
    579 
    580  requestAnimationFrame(() => setTimeout(runTest19));
    581 }
    582 
    583 async function runTest19() {
    584  await compareFiles("color_adjust.html", "color_adjust_ref.html", {
    585    test: {
    586      settings: {
    587        printBGColors: false,
    588        printBGImages: false,
    589      },
    590    },
    591    ref: {
    592      settings: {
    593        printBGColors: true,
    594        printBGImages: true,
    595      },
    596    },
    597  });
    598 
    599  requestAnimationFrame(() => setTimeout(runTest20));
    600 }
    601 
    602 async function runTest20() {
    603  frameElts[0].contentDocument.body.innerHTML =
    604    '<style>div { page-break-after: always; }</style>' +
    605    '<div>1</div>' +
    606    '<div>2</div>' +
    607    '<div>3</div>';
    608  await printpreview();
    609 
    610  is(gWbp.printPreviewCurrentPageNumber, 1,
    611     "The initial current page number should be 1");
    612 
    613  // Scroll to the second page.
    614  gWbp.printPreviewScrollToPage(Ci.nsIWebBrowserPrint.PRINTPREVIEW_GOTO_PAGENUM, 2);
    615 
    616  is(gWbp.printPreviewCurrentPageNumber, 2,
    617     "The current page number should be 2");
    618 
    619  // Scroll to the last page.
    620  gWbp.printPreviewScrollToPage(Ci.nsIWebBrowserPrint.PRINTPREVIEW_END, 0);
    621 
    622  is(gWbp.printPreviewCurrentPageNumber, 3,
    623     "The current page number should be 3");
    624 
    625  exitprintpreview();
    626 
    627  requestAnimationFrame(() => setTimeout(runTest21));
    628 }
    629 
    630 async function runTest21() {
    631  await compareFiles("data:text/html,<audio controls>", "data:text/html,<audio controls >"); // Shouldn't crash.
    632  requestAnimationFrame(() => setTimeout(runTest22));
    633 }
    634 
    635 async function runTest22() {
    636  // Similar to above runtTest20 but more specific for the logic to choose
    637  // the current page in the new print preview UI so this test works only
    638  // in the new print preview.
    639  frameElts[0].contentDocument.body.innerHTML =
    640      '<style>div { page-break-after: always; max-height: 2in; }</style>' +
    641      '<div>1</div>' +
    642      '<div>2</div>' +
    643      '<div>3</div>' +
    644      '<div>4</div>' +
    645      '<div>5</div>' +
    646      '<div>6</div>' +
    647      '<div>7</div>' +
    648      '<div>8</div>' +
    649      '<div>9</div>' +
    650      '<div>10</div>';
    651 
    652  await printpreview({ settings: { paperHeight: 3 } });
    653 
    654  const initialCurrentPageNumber = gWbp.printPreviewCurrentPageNumber;
    655 
    656  // NOTE: In the cases the page hight is less than the half height of the
    657  // print preview scroll port height, the initial current page number will
    658  // not be 1.
    659  ok(initialCurrentPageNumber >= 1,
    660     "The initial current page number should be equal to or greater than 1");
    661 
    662  const totalPageNumber = gWbp.printPreviewNumPages;
    663  for (let n = initialCurrentPageNumber;
    664       n <= totalPageNumber - initialCurrentPageNumber;
    665       n++) {
    666    // Scroll to the given page number and check the current page number.
    667    gWbp.printPreviewScrollToPage(
    668      Ci.nsIWebBrowserPrint.PRINTPREVIEW_GOTO_PAGENUM, n);
    669    is(gWbp.printPreviewCurrentPageNumber, n,
    670       `The current page number should be ${n}`);
    671  }
    672 
    673  // Scroll to the end of the scroll region.
    674  gWbp.printPreviewScrollToPage(Ci.nsIWebBrowserPrint.PRINTPREVIEW_END, 0);
    675 
    676  // Same as the initial current page number case, the last page might not
    677  // be the current page if the page height is less than the half of the scroll
    678  // port.
    679  is(gWbp.printPreviewCurrentPageNumber,
    680     totalPageNumber + 1 - initialCurrentPageNumber,
    681     `The current page number should be ${totalPageNumber + 1 - initialCurrentPageNumber}`);
    682 
    683  exitprintpreview();
    684 
    685  requestAnimationFrame(() => setTimeout(runTest23));
    686 }
    687 
    688 async function runTest23() {
    689  await compareFiles("printpreview_prettyprint.xml", "printpreview_prettyprint_ref.xhtml");
    690  requestAnimationFrame(() => setTimeout(runTest24));
    691 }
    692 async function runTest24() {
    693  await compareFiles("printpreview_mask.html", "data:text/html,", {
    694    settings: {
    695      printBGColors: false,
    696      printBGImages: false,
    697    },
    698    expectDifference: true,
    699  });
    700  requestAnimationFrame(() => setTimeout(runTest25));
    701 }
    702 
    703 async function runTest25() {
    704  await compareFiles("printpreview_downloadable_font.html", "printpreview_downloadable_font_ref.html");
    705  requestAnimationFrame(() => setTimeout(runTest26));
    706 }
    707 
    708 async function runTest26() {
    709  await compareFiles("printpreview_downloadable_font_in_iframe.html", "printpreview_downloadable_font_in_iframe_ref.html");
    710  requestAnimationFrame(() => setTimeout(runTest27));
    711 }
    712 
    713 async function runTest27() {
    714  await compareFiles("data:text/html,<style>:root { background-color: red; background-image: linear-gradient(red, red) }</style>", "data:text/html,", {
    715    settings: {
    716      printBGColors: false,
    717      printBGImages: false,
    718    }
    719  });
    720  requestAnimationFrame(() => setTimeout(runTest28));
    721 }
    722 
    723 async function runTest28() {
    724  await compareFiles("data:text/html,<style>@page { margin: 0 }</style>Foo", "data:text/html,Foo", {
    725    settings: {
    726      honorPageRuleMargins: false,
    727      marginTop: 1,
    728    }
    729  });
    730 
    731  requestAnimationFrame(() => setTimeout(runTest29));
    732 }
    733 
    734 async function runTest29() {
    735  await compareFiles("data:text/html,<style>@page { margin: 0 }</style>Foo", "data:text/html,Foo", {
    736    settings: {
    737      honorPageRuleMargins: true,
    738      marginTop: 1,
    739    },
    740    expectDifference: true,
    741  });
    742 
    743  requestAnimationFrame(() => setTimeout(runTest30));
    744 }
    745 
    746 // Helper function to test trivial/unsupported pages-per-sheet values which we
    747 // just treat as 1 page-per-sheet (as if the attribute were unset.)
    748 // NOTE: The second data-URI's explicit "<body>" tag is not meant to affect the
    749 // rendering -- it's just a hack to ensure that the URIs themselves are
    750 // different, so that compareFiles() sees the two URIs as different and gets
    751 // the "load" notification that it depends on after switching between them.
    752 // We also include numPages in the tested URL/content here, so that if we get
    753 // a test-failure, it's easy to figure out which call to this function had the
    754 // failure.
    755 async function checkTrivialPagesPerSheetValue(numPages) {
    756    let stringToDisplay = "TrivialPagesPerSheetVal" + numPages;
    757    await compareFiles("data:text/html," + stringToDisplay,
    758                       "data:text/html,<body>" + stringToDisplay, {
    759    test: {
    760      settings: {
    761        numPagesPerSheet: numPages,
    762      },
    763    },
    764    ref: { settings: {} },
    765  });
    766 }
    767 
    768 async function runTest30() {
    769  await checkTrivialPagesPerSheetValue(1);
    770  await checkTrivialPagesPerSheetValue(0);
    771  await checkTrivialPagesPerSheetValue(-5);
    772  await checkTrivialPagesPerSheetValue(7);
    773  await checkTrivialPagesPerSheetValue(500);
    774 
    775  requestAnimationFrame(() => setTimeout(runTest31));
    776 }
    777 
    778 // Helper function to test supported pages-per-sheet values that actually do
    779 // tiling (i.e. values greater than 1).  We render the testcase and reference
    780 // case with zero page-margins and zero unwritable margins. (This makes it
    781 // tractable to create a reference case without having to account for margins
    782 // that are outside of the content area.)
    783 async function checkSupportedPagesPerSheetValue(src1, src2, numPages, fuzz) {
    784  await compareFiles(src1, src2, {
    785    maxDifferent: fuzz.maxDifferent,
    786    maxDifference: fuzz.maxDifference,
    787    test: {
    788      settings: {
    789        marginTop: 0,
    790        marginRight: 0,
    791        marginBottom: 0,
    792        marginLeft: 0,
    793        unwriteableMarginTop: 0,
    794        unwriteableMarginRight: 0,
    795        unwriteableMarginBottom: 0,
    796        unwriteableMarginLeft: 0,
    797        numPagesPerSheet: numPages,
    798      },
    799    },
    800    ref: {
    801      settings: {
    802        marginTop: 0,
    803        marginRight: 0,
    804        marginBottom: 0,
    805        marginLeft: 0,
    806        unwriteableMarginTop: 0,
    807        unwriteableMarginRight: 0,
    808        unwriteableMarginBottom: 0,
    809        unwriteableMarginLeft: 0,
    810      },
    811    },
    812  });
    813 }
    814 
    815 // Pages-per-sheet: test the supported values.
    816 // First we test the perfect-square values: 4, 9, 16.
    817 // Then we test the other values, 2 and 6. (They require some extra bespoke
    818 // configuration to mock up their page-rotation, so their runTest functions are
    819 // a bit more verbose.)
    820 async function runTest31() {
    821  // XXXdholbert On windows, our zero-margin settings aren't reliably respected
    822  // for some reason; see bug 1680838. For now, we just account for that with a
    823  // hefty amount of fuzz, guarded behind a platform-specific check so that we
    824  // can keep this strict on other platforms.
    825  let fuzz = navigator.platform.includes("Win") ?
    826      { maxDifferent: 101278, maxDifference: 255 } :
    827      { maxDifferent: 0, maxDifference: 0 };
    828 
    829  await checkSupportedPagesPerSheetValue("printpreview_pps4.html",
    830                                         "printpreview_pps4_ref.html", 4, fuzz);
    831 
    832  requestAnimationFrame(() => setTimeout(runTest32));
    833 }
    834 async function runTest32() {
    835  let fuzz = navigator.platform.includes("Win") ?
    836      { maxDifferent: 130170, maxDifference: 255 } :
    837      { maxDifferent: 0, maxDifference: 0 };
    838 
    839  await checkSupportedPagesPerSheetValue("printpreview_pps9.html",
    840                                         "printpreview_pps9_ref.html", 9, fuzz);
    841 
    842  requestAnimationFrame(() => setTimeout(runTest33));
    843 }
    844 async function runTest33() {
    845  let fuzz = navigator.platform.includes("Win") ?
    846      { maxDifferent: 145706, maxDifference: 255 } :
    847      { maxDifferent: 0, maxDifference: 0 };
    848 
    849  await checkSupportedPagesPerSheetValue("printpreview_pps16.html",
    850                                         "printpreview_pps16_ref.html", 16,
    851                                         fuzz);
    852 
    853  requestAnimationFrame(() => setTimeout(runTest34));
    854 }
    855 
    856 async function runTest34() {
    857  let fuzz = navigator.platform.includes("Win") ? // Workaround for bug 1680838
    858      { maxDifferent: 44256, maxDifference: 255 } :
    859      { maxDifferent: 0, maxDifference: 0 };
    860 
    861  let test = "printpreview_pps2.html";
    862  let ref = "printpreview_pps2_ref.html";
    863  await compareFiles(test, ref, {
    864    maxDifferent: fuzz.maxDifferent,
    865    maxDifference: fuzz.maxDifference,
    866    test: {
    867      settings: {
    868        paperWidth: 8,
    869        paperHeight: 10,
    870        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
    871        marginTop: 0,
    872        marginRight: 0,
    873        marginBottom: 0,
    874        marginLeft: 0,
    875        unwriteableMarginTop: 0,
    876        unwriteableMarginRight: 0,
    877        unwriteableMarginBottom: 0,
    878        unwriteableMarginLeft: 0,
    879        numPagesPerSheet: 2,
    880      },
    881    },
    882    ref: {
    883      settings: {
    884        paperWidth: 8,
    885        paperHeight: 10,
    886        marginTop: 0,
    887        marginRight: 0,
    888        marginBottom: 0,
    889        marginLeft: 0,
    890        unwriteableMarginTop: 0,
    891        unwriteableMarginRight: 0,
    892        unwriteableMarginBottom: 0,
    893        unwriteableMarginLeft: 0,
    894        orientation: 1, /* Landscape mode */
    895      },
    896    },
    897  });
    898 
    899  requestAnimationFrame(() => setTimeout(runTest35));
    900 }
    901 
    902 async function runTest35() {
    903  let fuzz = navigator.platform.includes("Win") ? // Workaround for bug 1680838
    904      { maxDifferent: 88751, maxDifference: 255 } :
    905      { maxDifferent: 0, maxDifference: 0 };
    906 
    907  let test = "printpreview_pps6.html";
    908  let ref = "printpreview_pps6_ref.html";
    909  await compareFiles(test, ref, {
    910    maxDifferent: fuzz.maxDifferent,
    911    maxDifference: fuzz.maxDifference,
    912    test: {
    913      settings: {
    914        paperWidth: 5,
    915        paperHeight: 6,
    916        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
    917        marginTop: 0,
    918        marginRight: 0,
    919        marginBottom: 0,
    920        marginLeft: 0,
    921        unwriteableMarginTop: 0,
    922        unwriteableMarginRight: 0,
    923        unwriteableMarginBottom: 0,
    924        unwriteableMarginLeft: 0,
    925        numPagesPerSheet: 6,
    926        orientation: 1, /* Landscape mode */
    927      },
    928    },
    929    ref: {
    930      settings: {
    931        paperWidth: 5,
    932        paperHeight: 6,
    933        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
    934        marginTop: 0,
    935        marginRight: 0,
    936        marginBottom: 0,
    937        marginLeft: 0,
    938        unwriteableMarginTop: 0,
    939        unwriteableMarginRight: 0,
    940        unwriteableMarginBottom: 0,
    941        unwriteableMarginLeft: 0,
    942      },
    943    },
    944  });
    945 
    946  requestAnimationFrame(() => setTimeout(runTest36));
    947 }
    948 
    949 // Testcases for pages-per-sheet with nonzero unwriteable margin values:
    950 // ---------------------------------------------------------------------
    951 
    952 // In this subtest, the vertical scale-factor is more-severe and hence ends up
    953 // "winning", and we have a bit of extra space in the horizontal axis which we
    954 // distribute equally on either side (see the _ref.html file used below for
    955 // more details).
    956 async function runTest36() {
    957  let fuzz = navigator.platform.includes("Win") ?
    958      { maxDifferent: 139464, maxDifference: 255 } :
    959      { maxDifferent: 0, maxDifference: 0 };
    960 
    961  let test = "printpreview_pps_uw4.html";
    962  let ref = "printpreview_pps_uw4_ref.html";
    963  await compareFiles(test, ref, {
    964    maxDifferent: fuzz.maxDifferent,
    965    maxDifference: fuzz.maxDifference,
    966    test: {
    967      settings: {
    968        paperWidth: 4,
    969        paperHeight: 5,
    970        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
    971        marginTop: 0,
    972        marginRight: 0,
    973        marginBottom: 0,
    974        marginLeft: 0,
    975        unwriteableMarginTop: 0.6,
    976        unwriteableMarginRight: 0.1,
    977        unwriteableMarginBottom: 0.4,
    978        unwriteableMarginLeft: 0.3,
    979        numPagesPerSheet: 4,
    980      },
    981    },
    982    ref: {
    983      settings: {
    984        paperWidth: 4,
    985        paperHeight: 5,
    986        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
    987        marginTop: 0,
    988        marginRight: 0,
    989        marginBottom: 0,
    990        marginLeft: 0,
    991        unwriteableMarginTop: 0,
    992        unwriteableMarginRight: 0,
    993        unwriteableMarginBottom: 0,
    994        unwriteableMarginLeft: 0,
    995      },
    996    },
    997  });
    998 
    999  requestAnimationFrame(() => setTimeout(runTest37));
   1000 }
   1001 
   1002 // In this subtest, the horizontal scale-factor is more-severe and hence ends
   1003 // up "winning", and we have a bit of extra space in the vertical axis which we
   1004 // distribute equally on either side (see the _ref.html file used below for
   1005 // more details).
   1006 async function runTest37() {
   1007  let fuzz = navigator.platform.includes("Win") ?
   1008      { maxDifferent: 152268, maxDifference: 255 } :
   1009      { maxDifferent: 0, maxDifference: 0 };
   1010 
   1011  let test = "printpreview_pps_uw9.html";
   1012  let ref = "printpreview_pps_uw9_ref.html";
   1013  await compareFiles(test, ref, {
   1014    maxDifferent: fuzz.maxDifferent,
   1015    maxDifference: fuzz.maxDifference,
   1016    test: {
   1017      settings: {
   1018        paperWidth: 5,
   1019        paperHeight: 10,
   1020        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1021        marginTop: 0,
   1022        marginRight: 0,
   1023        marginBottom: 0,
   1024        marginLeft: 0,
   1025        unwriteableMarginTop: 0.2,
   1026        unwriteableMarginRight: 0.8,
   1027        unwriteableMarginBottom: 0.4,
   1028        unwriteableMarginLeft: 1.2,
   1029        numPagesPerSheet: 9,
   1030      },
   1031    },
   1032    ref: {
   1033      settings: {
   1034        paperWidth: 5,
   1035        paperHeight: 10,
   1036        marginTop: 0,
   1037        marginRight: 0,
   1038        marginBottom: 0,
   1039        marginLeft: 0,
   1040        unwriteableMarginTop: 0,
   1041        unwriteableMarginRight: 0,
   1042        unwriteableMarginBottom: 0,
   1043        unwriteableMarginLeft: 0,
   1044      },
   1045    },
   1046  });
   1047 
   1048  requestAnimationFrame(() => setTimeout(runTest38));
   1049 }
   1050 
   1051 async function runTest38() {
   1052  let fuzz = navigator.platform.includes("Win") ? // Workaround for bug 1680838
   1053      { maxDifferent: 117744, maxDifference: 255 } :
   1054      { maxDifferent: 0, maxDifference: 0 };
   1055 
   1056  let test = "printpreview_pps_uw2.html";
   1057  let ref = "printpreview_pps_uw2_ref.html";
   1058  await compareFiles(test, ref, {
   1059    maxDifferent: fuzz.maxDifferent,
   1060    maxDifference: fuzz.maxDifference,
   1061    test: {
   1062      settings: {
   1063        paperWidth: 8,
   1064        paperHeight: 10,
   1065        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1066        marginTop: 0,
   1067        marginRight: 0,
   1068        marginBottom: 0,
   1069        marginLeft: 0,
   1070        unwriteableMarginTop: 0.8,
   1071        unwriteableMarginRight: 0.6,
   1072        unwriteableMarginBottom: 1.2,
   1073        unwriteableMarginLeft: 0.4,
   1074        numPagesPerSheet: 2,
   1075      },
   1076    },
   1077    ref: {
   1078      settings: {
   1079        paperWidth: 8,
   1080        paperHeight: 10,
   1081        marginTop: 0,
   1082        marginRight: 0,
   1083        marginBottom: 0,
   1084        marginLeft: 0,
   1085        /* Note: These are the same values we used for 'test' above, except
   1086           that here we've rotated the margins counterclockwise through the
   1087           sides, to account for the fact that we're specifying these margins
   1088           for a landscape-orientation page here vs. portrait-mode above.*/
   1089        unwriteableMarginTop: 0.6,
   1090        unwriteableMarginRight: 1.2,
   1091        unwriteableMarginBottom: 0.4,
   1092        unwriteableMarginLeft: 0.8,
   1093        orientation: 1, /* Landscape mode */
   1094      },
   1095    },
   1096  });
   1097 
   1098  requestAnimationFrame(() => setTimeout(runTest39));
   1099 }
   1100 
   1101 // In this subtest, the vertical unwriteable margins exactly consume the full
   1102 // pageHeight, so we don't have any space available for printing and we just
   1103 // print a blank sheet. (This is mostly a stress test to be sure we don't
   1104 // crash, hang, divide-by-zero, etc. in this edge case.)
   1105 async function runTest39() {
   1106  let fuzz = navigator.platform.includes("Win") ?
   1107      { maxDifferent: 254, maxDifference: 255 } :
   1108      { maxDifferent: 0, maxDifference: 0 };
   1109 
   1110  let test = "data:text/html,Unwriteable-Margins-Too-Tall-To-See-This";
   1111  let ref = "data:text/html,<!-- runTest39 -->";
   1112  await compareFiles(test, ref, {
   1113    maxDifferent: fuzz.maxDifferent,
   1114    maxDifference: fuzz.maxDifference,
   1115    test: {
   1116      settings: {
   1117        paperWidth: 4,
   1118        paperHeight: 5,
   1119        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1120        unwriteableMarginTop: 3,
   1121        unwriteableMarginBottom: 2,
   1122        numPagesPerSheet: 4,
   1123      },
   1124    },
   1125    ref: {
   1126      settings: {
   1127        paperWidth: 4,
   1128        paperHeight: 5,
   1129      },
   1130    },
   1131  });
   1132 
   1133  requestAnimationFrame(() => setTimeout(runTest40));
   1134 }
   1135 
   1136 // In this subtest, the horizontal unwriteable margins consume more than the
   1137 // full pageWidth, so we don't have any space available for printing and we
   1138 // just print a blank sheet. (This is mostly a stress test to be sure we don't
   1139 // crash, hang, divide-by-zero, etc. in this edge case.)
   1140 async function runTest40() {
   1141  let fuzz = navigator.platform.includes("Win") ?
   1142      { maxDifferent: 172, maxDifference: 255 } :
   1143      { maxDifferent: 0, maxDifference: 0 };
   1144 
   1145  let test = "data:text/html,Unwriteable-Margins-Too-Wide-To-See-This";
   1146  let ref = "data:text/html,<!-- runTest40 -->";
   1147  await compareFiles(test, ref, {
   1148    maxDifferent: fuzz.maxDifferent,
   1149    maxDifference: fuzz.maxDifference,
   1150    test: {
   1151      settings: {
   1152        paperWidth: 4,
   1153        paperHeight: 5,
   1154        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1155        unwriteableMarginRight: 3,
   1156        unwriteableMarginLeft: 4,
   1157        numPagesPerSheet: 9,
   1158      },
   1159    },
   1160    ref: {
   1161      settings: {
   1162        paperWidth: 4,
   1163        paperHeight: 5,
   1164      },
   1165    },
   1166  });
   1167 
   1168  requestAnimationFrame(() => setTimeout(runTest41));
   1169 }
   1170 
   1171 // Drawing headers/footers with very large unwriteable margins. The specific
   1172 // bug occurs when combined unwriteable are larger than half of the page's
   1173 // dimensions.
   1174 async function runTest41() {
   1175  // This test compares a rendered page to the headers/footers that print code
   1176  // generates. On Windows, workaround bug 1680838. On OS X, the headers/
   1177  // footers are sometimes slightly offset. See bug 1714217.
   1178  // It's not too big a deal to have a higher fuzz factor, since when
   1179  // bug 1713404 occurs no headers/footers at all are rendered. These higher
   1180  // fuzz factors will still catch this worst case on OS X.
   1181  if (navigator.platform.includes("Win")) {
   1182    var fuzz = { maxDifferent: 256, maxDifference: 255 }; // Bug 1680838
   1183  }
   1184  else if (navigator.platform.includes("Mac")) {
   1185    var fuzz = { maxDifferent: 60, maxDifference: 200 }; // Bug 1714217
   1186  }
   1187  else {
   1188    var fuzz = { maxDifferent: 14, maxDifference: 16 };
   1189  }
   1190 
   1191  let test = "data:text/html,<!-- runTest41 -->";
   1192  let ref = "printpreview_bug1713404_ref.html";
   1193  await compareFiles(test, ref, {
   1194    maxDifferent: fuzz.maxDifferent,
   1195    maxDifference: fuzz.maxDifference,
   1196    test: {
   1197      settings: {
   1198        paperWidth: 5,
   1199        paperHeight: 5,
   1200        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1201        unwriteableMarginLeft: 2,
   1202        unwriteableMarginRight: 2,
   1203        unwriteableMarginTop: 2,
   1204        unwriteableMarginBottom: 2,
   1205        headerStrLeft: "|",
   1206        headerStrRight: "||",
   1207        footerStrLeft: "|||",
   1208        footerStrRight: "||||",
   1209      },
   1210    },
   1211    ref: {
   1212      settings: {
   1213        paperWidth: 5,
   1214        paperHeight: 5,
   1215        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1216        unwriteableMarginLeft: 0,
   1217        unwriteableMarginRight: 0,
   1218        unwriteableMarginTop: 0,
   1219        unwriteableMarginBottom: 0,
   1220      },
   1221    },
   1222  });
   1223 
   1224  requestAnimationFrame(() => setTimeout(runTest42));
   1225 }
   1226 
   1227 // Test that @page{ size: ... } works correctly with a smaller specified
   1228 // @page{ size: ... } than the paper we are printing to. The test and ref use
   1229 // varying margin and size properties to place elements in the same location.
   1230 // This depends on Firefox's current behavior of putting undersized pages into
   1231 // the upper left corner, rather than scaling or centering the page.
   1232 async function runTest42() {
   1233  if (navigator.platform.includes("Mac")) {
   1234    var fuzz = { maxDifferent: 15, maxDifference: 8 };
   1235  }
   1236  let test = "print_page_size1.html";
   1237  let ref = "print_page_size1_ref.html";
   1238  await compareFiles(test, ref, fuzz);
   1239 
   1240  requestAnimationFrame(() => setTimeout(runTest43));
   1241 }
   1242 
   1243 // Test that @page{ size: ... } works correctly with a larger specified
   1244 // @page{ size: ... } than the paper we are printing to. This specifically
   1245 // tests scaling when only one page edge is too large.
   1246 // This depends on Firefox's current behavior of scaling down any oversized
   1247 // pages to fit onto a single physical page, and putting this aligned to the
   1248 // upper left corner rather than centering the page.
   1249 async function runTest43() {
   1250  if (navigator.platform.includes("Mac")) {
   1251    var fuzz = { maxDifferent: 15, maxDifference: 8 };
   1252  }
   1253  let test = "print_page_size2.html";
   1254  let ref = "print_page_size2_ref.html";
   1255  await compareFiles(test, ref, fuzz);
   1256 
   1257  requestAnimationFrame(() => setTimeout(runTest44));
   1258 }
   1259 
   1260 // Test that @page{ size: ... } works correctly with a smaller specified
   1261 // @page{ size: ... } than the paper we are printing to. The test case uses
   1262 // only the size property and the ref case uses only absolute positioning.
   1263 // This depends on Firefox's current behavior of putting undersized pages into
   1264 // the upper left corner, rather than scaling or centering the page.
   1265 async function runTest44() {
   1266  if (navigator.platform.includes("Mac")) {
   1267    var fuzz = { maxDifferent: 15, maxDifference: 8 };
   1268  }
   1269  let test = "print_page_size3.html";
   1270  let ref = "print_page_size3_ref.html";
   1271  await compareFiles(test, ref, fuzz);
   1272  requestAnimationFrame(() => setTimeout(runTest45));
   1273 }
   1274 
   1275 // Test that @page{ size: ... } results in scaling down the contents to fit on
   1276 // a smaller paper size.
   1277 // This depends on Firefox's current behavior of scaling oversized pages down
   1278 // to fit onto the paper size.
   1279 async function runTest45() {
   1280  if (navigator.platform.includes("Mac")) {
   1281    var fuzz = { maxDifferent: 15, maxDifference: 8 };
   1282  }
   1283  let test = "print_page_size4.html";
   1284  let ref = "print_page_size4_ref.html";
   1285  await compareFiles(test, ref, fuzz);
   1286  requestAnimationFrame(() => setTimeout(runTest46));
   1287 }
   1288 
   1289 // Test that small elements don't get clipped from the bottom of the page when
   1290 // using a < 1.0 scaling factor.
   1291 async function runTest46() {
   1292  var fuzz = { maxDifferent: 0, maxDifference: 0 };
   1293  let test = "bug1722890.html";
   1294  let ref = "bug1722890_ref.html";
   1295  await compareFiles(test, ref, {
   1296    maxDifferent: fuzz.maxDifferent,
   1297    maxDifference: fuzz.maxDifference,
   1298    test: {
   1299      settings: {
   1300        scaling: 0.5,
   1301        shrinkToFit: false
   1302      }
   1303    },
   1304    ref: {
   1305      settings: {
   1306        scaling: 1.0,
   1307        shrinkToFit: false
   1308      }
   1309    }
   1310  });
   1311  requestAnimationFrame(() => setTimeout(runTest47));
   1312 }
   1313 
   1314 // Test for header/footer text clipping when printing with scaling factor.
   1315 async function runTest47() {
   1316  // This test compares a rendered page to the headers/footers that print code
   1317  // generates. On Windows, workaround bug 1680838. On OS X, the headers/
   1318  // footers are sometimes slightly offset. See bug 1714217.
   1319  // It's not too big a deal to have a higher fuzz factor, since when
   1320  // bug 1730091 occurs most of the headers/footers are not rendered at all,
   1321  // and these fuzz factors will still catch that.
   1322  if (navigator.platform.includes("Win")) {
   1323    var fuzz = { maxDifferent: 200, maxDifference: 255 }; // Bug 1680838
   1324  }
   1325  else if (navigator.platform.includes("Mac")) {
   1326    var fuzz = { maxDifferent: 180, maxDifference: 255 }; // Bug 1714217
   1327  }
   1328  else {
   1329    var fuzz = { maxDifferent: 6, maxDifference: 16 };
   1330  }
   1331 
   1332  let test = "data:text/html,<!-- runTest47 -->";
   1333  let ref = "printpreview_bug1730091_ref.html";
   1334  await compareFiles(test, ref, {
   1335    maxDifferent: fuzz.maxDifferent,
   1336    maxDifference: fuzz.maxDifference,
   1337    test: {
   1338      settings: {
   1339        scaling: 1.3,
   1340        shrinkToFit: false,
   1341        paperWidth: 5,
   1342        paperHeight: 5,
   1343        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1344        unwriteableMarginLeft: 0,
   1345        unwriteableMarginRight: 0,
   1346        unwriteableMarginTop: 0,
   1347        unwriteableMarginBottom: 0,
   1348        headerStrLeft: "||||",
   1349        headerStrRight: "||||",
   1350        footerStrLeft: "||||",
   1351        footerStrRight: "||||",
   1352      },
   1353    },
   1354    ref: {
   1355      settings: {
   1356        paperWidth: 5,
   1357        paperHeight: 5,
   1358        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1359        unwriteableMarginLeft: 0,
   1360        unwriteableMarginRight: 0,
   1361        unwriteableMarginTop: 0,
   1362        unwriteableMarginBottom: 0,
   1363      },
   1364    },
   1365  });
   1366  requestAnimationFrame(() => setTimeout(runTest48));
   1367 }
   1368 
   1369 // Test that even when downscaling happens due to CSS page-size, the
   1370 // unwriteable margins are in units applicable to the resulting page as it is
   1371 // actually printed.
   1372 // https://bugzilla.mozilla.org/1769161
   1373 async function runTest48() {
   1374  if (navigator.platform.includes("Win")) {
   1375    var fuzz = { maxDifferent: 816, maxDifference: 255 }; // Bug 1680838
   1376  } else {
   1377    var fuzz = { maxDifferent: 16, maxDifference: 255 };
   1378  }
   1379  let test = "bug1769161_1.html";
   1380  let ref = "bug1769161_1_ref.html";
   1381  await compareFiles(test, ref, {
   1382    maxDifferent: fuzz.maxDifferent,
   1383    maxDifference: fuzz.maxDifference,
   1384    settings: {
   1385      paperWidth: 5,
   1386      paperHeight: 5,
   1387      paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1388      unwriteableMarginLeft: 1,
   1389      unwriteableMarginRight: 1,
   1390      unwriteableMarginTop: 1,
   1391      unwriteableMarginBottom: 1,
   1392    },
   1393  });
   1394  requestAnimationFrame(() => setTimeout(runTest49));
   1395 }
   1396 
   1397 // Same as runTest48, but uses different scaling factors.
   1398 async function runTest49() {
   1399  if (navigator.platform.includes("Win")) {
   1400    var fuzz = { maxDifferent: 6472, maxDifference: 255 }; // Bug 1680838
   1401  } else {
   1402    var fuzz = { maxDifferent: 24, maxDifference: 255 };
   1403  }
   1404  let test = "bug1769161_2.html";
   1405  let ref = "bug1769161_2_ref.html";
   1406  await compareFiles(test, ref, {
   1407    maxDifferent: fuzz.maxDifferent,
   1408    maxDifference: fuzz.maxDifference,
   1409    settings: {
   1410      paperWidth: 5,
   1411      paperHeight: 5,
   1412      paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1413      unwriteableMarginLeft: 1,
   1414      unwriteableMarginRight: 1,
   1415      unwriteableMarginTop: 1,
   1416      unwriteableMarginBottom: 1,
   1417    },
   1418  });
   1419  requestAnimationFrame(() => setTimeout(runTest50));
   1420 }
   1421 
   1422 // Test that when downscaling happens due to CSS page-size, the unwriteable
   1423 // margins are equivalent to the @page margins after those margins are scaled.
   1424 // https://bugzilla.mozilla.org/1769161
   1425 async function runTest50() {
   1426  if (navigator.platform.includes("Win")) {
   1427    var fuzz = { maxDifferent: 816, maxDifference: 255 }; // Bug 1680838
   1428  } else {
   1429    var fuzz = { maxDifferent: 16, maxDifference: 255 };
   1430  }
   1431  let test = "bug1769161_3.html";
   1432  let ref = "bug1769161_3_ref.html";
   1433  await compareFiles(test, ref, {
   1434    maxDifferent: fuzz.maxDifferent,
   1435    maxDifference: fuzz.maxDifference,
   1436    test: {
   1437      settings: {
   1438        paperWidth: 5,
   1439        paperHeight: 5,
   1440        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1441        unwriteableMarginLeft: 1,
   1442        unwriteableMarginRight: 1,
   1443        unwriteableMarginTop: 1,
   1444        unwriteableMarginBottom: 1,
   1445      },
   1446    },
   1447    ref: {
   1448      settings: {
   1449        paperWidth: 5,
   1450        paperHeight: 5,
   1451        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1452        unwriteableMarginLeft: 0,
   1453        unwriteableMarginRight: 0,
   1454        unwriteableMarginTop: 0,
   1455        unwriteableMarginBottom: 0,
   1456      },
   1457    },
   1458  });
   1459  requestAnimationFrame(() => setTimeout(runTest51));
   1460 }
   1461 
   1462 // Same as runTest50, but uses different scaling factors.
   1463 async function runTest51() {
   1464  if (navigator.platform.includes("Win")) {
   1465    var fuzz = { maxDifferent: 11764, maxDifference: 255 }; // Bug 1680838
   1466  } else {
   1467    var fuzz = { maxDifferent: 24, maxDifference: 255 };
   1468  }
   1469  let test = "bug1769161_4.html";
   1470  let ref = "bug1769161_4_ref.html";
   1471  await compareFiles(test, ref, {
   1472    maxDifferent: fuzz.maxDifferent,
   1473    maxDifference: fuzz.maxDifference,
   1474    test: {
   1475      settings: {
   1476        paperWidth: 5,
   1477        paperHeight: 5,
   1478        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1479        unwriteableMarginLeft: 1,
   1480        unwriteableMarginRight: 1,
   1481        unwriteableMarginTop: 1,
   1482        unwriteableMarginBottom: 1,
   1483      },
   1484    },
   1485    ref: {
   1486      settings: {
   1487        paperWidth: 5,
   1488        paperHeight: 5,
   1489        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1490        unwriteableMarginLeft: 0,
   1491        unwriteableMarginRight: 0,
   1492        unwriteableMarginTop: 0,
   1493        unwriteableMarginBottom: 0,
   1494      },
   1495    },
   1496  });
   1497  requestAnimationFrame(() => setTimeout(runTest52));
   1498 }
   1499 
   1500 async function runTest52() {
   1501  // Unwriteable margins can be ignored by setting the appropriate flag.
   1502  // Slightly different to avoid hang.
   1503  await compareFiles("data:text/html,Foo", "data:text/html,<div>Foo", {
   1504    maxDifferent: 0,
   1505    maxDifference: 0,
   1506    test: {
   1507      settings: {
   1508        paperWidth: 8,
   1509        paperHeight: 10,
   1510        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1511        marginTop: 0,
   1512        marginRight: 0,
   1513        marginBottom: 0,
   1514        marginLeft: 0,
   1515        unwriteableMarginTop: 1,
   1516        unwriteableMarginRight: 1,
   1517        unwriteableMarginBottom: 1,
   1518        unwriteableMarginLeft: 1,
   1519        ignoreUnwriteableMargins: true,
   1520      },
   1521    },
   1522    ref: {
   1523      settings: {
   1524        paperWidth: 8,
   1525        paperHeight: 10,
   1526        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1527        marginTop: 0,
   1528        marginRight: 0,
   1529        marginBottom: 0,
   1530        marginLeft: 0,
   1531        unwriteableMarginTop: 0,
   1532        unwriteableMarginRight: 0,
   1533        unwriteableMarginBottom: 0,
   1534        unwriteableMarginLeft: 0,
   1535      },
   1536    },
   1537  });
   1538 
   1539  requestAnimationFrame(() => setTimeout(runTest53));
   1540 }
   1541 
   1542 async function runTest53() {
   1543  // Ensure that even when unwriteable margins are set to be taken into
   1544  // account, page rule margins can override it.
   1545  await compareFiles(
   1546    "data:text/html,<style>@page { margin: 0 }</style>Foo",
   1547    "data:text/html,<div>Foo",
   1548    {
   1549      maxDifferent: 0,
   1550      maxDifference: 0,
   1551      test: {
   1552        settings: {
   1553          paperWidth: 8,
   1554          paperHeight: 10,
   1555          paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1556          marginTop: 0,
   1557          marginRight: 0,
   1558          marginBottom: 0,
   1559          marginLeft: 0,
   1560          unwriteableMarginTop: 1,
   1561          unwriteableMarginRight: 1,
   1562          unwriteableMarginBottom: 1,
   1563          unwriteableMarginLeft: 1,
   1564          ignoreUnwriteableMargins: false,
   1565          honorPageRuleMargins: true,
   1566        },
   1567      },
   1568      ref: {
   1569        settings: {
   1570          paperWidth: 8,
   1571          paperHeight: 10,
   1572          paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1573          marginTop: 0,
   1574          marginRight: 0,
   1575          marginBottom: 0,
   1576          marginLeft: 0,
   1577          unwriteableMarginTop: 0,
   1578          unwriteableMarginRight: 0,
   1579          unwriteableMarginBottom: 0,
   1580          unwriteableMarginLeft: 0,
   1581        },
   1582      },
   1583    });
   1584 
   1585    requestAnimationFrame(() => setTimeout(runTest54));
   1586 }
   1587 
   1588 async function runTest54() {
   1589  // `ignoreUnwriteableMargins` lets author-specified margins ignore
   1590  // unwriteable margins as well. Without this flag, the unwriteable
   1591  // margin is ignored iff `Margins: Default` is set (i.e.
   1592  // `honorPageRuleMargins` set) and the author specified CSS page
   1593  // margin is zero.
   1594  // Note: At least currently, both `ignoreUnwriteableMargins`
   1595  // and `honorPageRuleMargins` cannot be set through the printing UI.
   1596  // TODO: If this behaviour is desired is up for debate.
   1597  await compareFiles(
   1598    "data:text/html,<style>@page { margin: 0.1in }</style>Foo",
   1599    "data:text/html,<div>Foo",
   1600    {
   1601      maxDifferent: 0,
   1602      maxDifference: 0,
   1603      test: {
   1604        settings: {
   1605          paperWidth: 8,
   1606          paperHeight: 10,
   1607          paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1608          marginTop: 0,
   1609          marginRight: 0,
   1610          marginBottom: 0,
   1611          marginLeft: 0,
   1612          unwriteableMarginTop: 1,
   1613          unwriteableMarginRight: 1,
   1614          unwriteableMarginBottom: 1,
   1615          unwriteableMarginLeft: 1,
   1616          ignoreUnwriteableMargins: true,
   1617          honorPageRuleMargins: true,
   1618        },
   1619      },
   1620      ref: {
   1621        settings: {
   1622          paperWidth: 8,
   1623          paperHeight: 10,
   1624          paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1625          marginTop: 0.1,
   1626          marginRight: 0.1,
   1627          marginBottom: 0.1,
   1628          marginLeft: 0.1,
   1629          unwriteableMarginTop: 0,
   1630          unwriteableMarginRight: 0,
   1631          unwriteableMarginBottom: 0,
   1632          unwriteableMarginLeft: 0,
   1633        },
   1634      },
   1635    });
   1636 
   1637    requestAnimationFrame(() => setTimeout(runTest55));
   1638 }
   1639 
   1640 async function runTest55() {
   1641  let test = "printpreview_pps_uw2.html";
   1642  let ref = "printpreview_pps_uw2_no_margin_ref.html";
   1643  let fuzz = navigator.platform.includes("Win") ? // Workaround for bug 1680838
   1644      { maxDifferent: 12870, maxDifference: 255 } :
   1645      { maxDifferent: 0, maxDifference: 0 };
   1646 
   1647  // Unwriteable margins are successfully ignored, if requested,
   1648  // for pages-per-sheet.
   1649  await compareFiles(test, ref, {
   1650    maxDifferent: fuzz.maxDifferent,
   1651    maxDifference: fuzz.maxDifference,
   1652    test: {
   1653      settings: {
   1654        paperWidth: 8,
   1655        paperHeight: 10,
   1656        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1657        marginTop: 0,
   1658        marginRight: 0,
   1659        marginBottom: 0,
   1660        marginLeft: 0,
   1661        unwriteableMarginTop: 0.8,
   1662        unwriteableMarginRight: 0.6,
   1663        unwriteableMarginBottom: 1.2,
   1664        unwriteableMarginLeft: 0.4,
   1665        numPagesPerSheet: 2,
   1666        ignoreUnwriteableMargins: true,
   1667      },
   1668    },
   1669    ref: {
   1670      settings: {
   1671        paperWidth: 8,
   1672        paperHeight: 10,
   1673        marginTop: 0,
   1674        marginRight: 0,
   1675        marginBottom: 0,
   1676        marginLeft: 0,
   1677        unwriteableMarginTop: 0,
   1678        unwriteableMarginRight: 0,
   1679        unwriteableMarginBottom: 0,
   1680        unwriteableMarginLeft: 0,
   1681        orientation: 1, /* Landscape mode */
   1682      },
   1683    },
   1684  });
   1685 
   1686  requestAnimationFrame(() => setTimeout(runTest56));
   1687 }
   1688 
   1689 async function runTest56() {
   1690  await compareFiles("printpreview_image_select.html", "printpreview_image_select_ref.html");
   1691  requestAnimationFrame(() => setTimeout(runTest57));
   1692 }
   1693 
   1694 // Tests that printing with mixed page sizes doesn't crash.
   1695 // These tests can't actually compare any pages after the first, so this only
   1696 // verifies that we don't crash reflowing.
   1697 async function runTest57() {
   1698  let test = "printpreview_mixed_page_size_001.html";
   1699  // The params are just to give the file unique URLs.
   1700  await compareFiles(test + "?test", test + "?ref");
   1701  requestAnimationFrame(() => setTimeout(runTest58));
   1702 }
   1703 
   1704 // As with runTest57, this is only testing for crashes.
   1705 // This includes fixed-position content, as this is the only way to get content
   1706 // within the same chain of continuations onto pages with different sizes.
   1707 async function runTest58() {
   1708  let test = "printpreview_mixed_page_size_002.html";
   1709  // The params are just to give the file unique URLs.
   1710  await compareFiles(test + "?test", test + "?ref");
   1711  requestAnimationFrame(() => setTimeout(runTest59));
   1712 }
   1713 
   1714 // Creates a data URL that has a single div of |divSize| em square, on a page
   1715 // of size |pageSize| inches square.
   1716 // |center| determines if the div should be centered horizontally.
   1717 function createScalingTestSource(pageSize, center, name) {
   1718  // Styling always used.
   1719  let baseStyle = 'background: blue;';
   1720  if (center) {
   1721    baseStyle += 'margin: auto;';
   1722  }
   1723  const div = '<div style="width: 100px; height: 100px;' + baseStyle + '"></div>';
   1724  const style = '<style>@page{size:' + pageSize + 'in}body{margin:0}</style>';
   1725  // Add the name as a comment, to ensure every test has a unique source even
   1726  // if the parameters are identical.
   1727  const comment = '<!-- ' + name + ' -->';
   1728  return 'data:text/html,' + style + div + comment;
   1729 }
   1730 
   1731 async function runScalingCenteredTest(refPageSize, testPageSize, paperSize,
   1732    name, center = true, fuzz = null) {
   1733  const printSettings = {
   1734    settings: {
   1735      paperWidth: paperSize,
   1736      paperHeight: paperSize,
   1737      paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1738      marginTop: 0,
   1739      marginRight: 0,
   1740      marginBottom: 0,
   1741      marginLeft: 0,
   1742      unwriteableMarginTop: 0,
   1743      unwriteableMarginRight: 0,
   1744      unwriteableMarginBottom: 0,
   1745      unwriteableMarginLeft: 0,
   1746    }
   1747  };
   1748  let settings = Object.create(fuzz, {
   1749    ref: {value: printSettings},
   1750    test: {value: printSettings}
   1751  });
   1752  const testSrc = createScalingTestSource(testPageSize, center, name);
   1753  const refSrc = createScalingTestSource(refPageSize, center, name);
   1754  return compareFiles(testSrc, refSrc, settings);
   1755 }
   1756 
   1757 // Tests that auto-detection and use of page centering.
   1758 // Has a smaller page on a larger sheet, where the difference is within the
   1759 // tolerance for auto-detection.
   1760 async function runTest59() {
   1761  await SpecialPowers.pushPrefEnv({
   1762    set: [["print.center_page_on_sheet", 2]]
   1763  });
   1764  // See bug 1680838
   1765  const fuzz = navigator.platform.includes("Win") ?
   1766      { maxDifferent: 180, maxDifference: 255 } :
   1767      null;
   1768  await runScalingCenteredTest(10, 9.5, 10, "runTest59", true, fuzz);
   1769  await SpecialPowers.popPrefEnv();
   1770  requestAnimationFrame(() => setTimeout(runTest60));
   1771 }
   1772 
   1773 // Tests that centering won't occur when the pref disables it, using the same
   1774 // values as runTest59.
   1775 async function runTest60() {
   1776  await SpecialPowers.pushPrefEnv({
   1777    set: [["print.center_page_on_sheet", 0]]
   1778  });
   1779  // See bug 1680838
   1780  const fuzz = navigator.platform.includes("Win") ?
   1781      { maxDifferent: 180, maxDifference: 255 } :
   1782      null;
   1783  await runScalingCenteredTest(10, 9.5, 10, "runTest60", false, fuzz);
   1784  await SpecialPowers.popPrefEnv();
   1785  requestAnimationFrame(() => setTimeout(runTest61));
   1786 }
   1787 
   1788 // Tests that auto-detection will reject too big a difference for page
   1789 // centering. Has a much smaller page on a larger sheet, where the difference
   1790 // is outside the threshold for auto-detection.
   1791 async function runTest61() {
   1792  await SpecialPowers.pushPrefEnv({
   1793    set: [["print.center_page_on_sheet", 2]]
   1794  });
   1795  // See bug 1680838
   1796  const fuzz = navigator.platform.includes("Win") ?
   1797      { maxDifferent: 450, maxDifference: 255 } :
   1798      null;
   1799  await runScalingCenteredTest(10, 8.9, 10, "runTest61", false, fuzz);
   1800  await SpecialPowers.popPrefEnv();
   1801  requestAnimationFrame(() => setTimeout(runTest62));
   1802 }
   1803 
   1804 // Tests that we can force page centering with the pref, using the same values
   1805 // as runTest61.
   1806 async function runTest62() {
   1807  await SpecialPowers.pushPrefEnv({
   1808    set: [["print.center_page_on_sheet", 1]]
   1809  });
   1810  // See bug 1680838
   1811  const fuzz = navigator.platform.includes("Win") ?
   1812      { maxDifferent: 450, maxDifference: 255 } :
   1813      null;
   1814  await runScalingCenteredTest(10, 8.9, 10, "runTest62", true, fuzz);
   1815  await SpecialPowers.popPrefEnv();
   1816  requestAnimationFrame(() => setTimeout(runTest63));
   1817 }
   1818 
   1819 // Tests that centering will always happen if the pref forces it.
   1820 // The sizes used in these files are very large and the scale factor very high
   1821 // here to ensure that any errors in the calculation for centering will be
   1822 // magnified.
   1823 async function runTest63() {
   1824  let test = "printpreview_scale_test_001.html";
   1825  let ref = "printpreview_scale_test_001_ref.html";
   1826 
   1827  await SpecialPowers.pushPrefEnv({
   1828    set: [["print.center_page_on_sheet", 1]]
   1829  });
   1830  await compareFiles(test, ref, {
   1831    test: {
   1832      settings: {
   1833        paperWidth: 8.5,
   1834        paperHeight: 11,
   1835        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1836        marginTop: 0,
   1837        marginRight: 0,
   1838        marginBottom: 0,
   1839        marginLeft: 0,
   1840        unwriteableMarginTop: 0,
   1841        unwriteableMarginRight: 0,
   1842        unwriteableMarginBottom: 0,
   1843        unwriteableMarginLeft: 0,
   1844      },
   1845    },
   1846    ref: {
   1847      settings: {
   1848        paperWidth: 8.5,
   1849        paperHeight: 11,
   1850        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1851        marginTop: 0,
   1852        marginRight: 0,
   1853        marginBottom: 0,
   1854        marginLeft: 0,
   1855        unwriteableMarginTop: 0,
   1856        unwriteableMarginRight: 0,
   1857        unwriteableMarginBottom: 0,
   1858        unwriteableMarginLeft: 0,
   1859      },
   1860    },
   1861  });
   1862  await SpecialPowers.popPrefEnv();
   1863  requestAnimationFrame(() => setTimeout(runTest64));
   1864 }
   1865 
   1866 // Tests that printing A4 pages on US Letter will be a close enough fit
   1867 // that we will automatically center the page.
   1868 async function runTest64() {
   1869  let test = "printpreview_scale_test_002.html";
   1870  let ref = "printpreview_scale_test_002_ref.html";
   1871 
   1872  await SpecialPowers.pushPrefEnv({
   1873    set: [["print.center_page_on_sheet", 2]]
   1874  });
   1875  await compareFiles(test, ref, {
   1876    test: {
   1877      settings: {
   1878        paperWidth: 8.5,
   1879        paperHeight: 11,
   1880        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1881        marginTop: 0,
   1882        marginRight: 0,
   1883        marginBottom: 0,
   1884        marginLeft: 0,
   1885        unwriteableMarginTop: 0,
   1886        unwriteableMarginRight: 0,
   1887        unwriteableMarginBottom: 0,
   1888        unwriteableMarginLeft: 0,
   1889      },
   1890    },
   1891    ref: {
   1892      settings: {
   1893        paperWidth: 8.5,
   1894        paperHeight: 11,
   1895        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1896        marginTop: 0,
   1897        marginRight: 0,
   1898        marginBottom: 0,
   1899        marginLeft: 0,
   1900        unwriteableMarginTop: 0,
   1901        unwriteableMarginRight: 0,
   1902        unwriteableMarginBottom: 0,
   1903        unwriteableMarginLeft: 0,
   1904      },
   1905    },
   1906  });
   1907  await SpecialPowers.popPrefEnv();
   1908  requestAnimationFrame(() => setTimeout(runTest65));
   1909 }
   1910 
   1911 // Tests that auto-detection will reject a large enough difference in width
   1912 // when downscaling is used to make the page fit on the paper.
   1913 async function runTest65() {
   1914  let test = "printpreview_scale_test_003.html";
   1915  let ref = "printpreview_scale_test_003_ref.html";
   1916 
   1917  await SpecialPowers.pushPrefEnv({
   1918    set: [["print.center_page_on_sheet", 2]]
   1919  });
   1920  await compareFiles(test, ref, {
   1921    test: {
   1922      settings: {
   1923        paperWidth: 8.5,
   1924        paperHeight: 11,
   1925        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1926        marginTop: 0,
   1927        marginRight: 0,
   1928        marginBottom: 0,
   1929        marginLeft: 0,
   1930        unwriteableMarginTop: 0,
   1931        unwriteableMarginRight: 0,
   1932        unwriteableMarginBottom: 0,
   1933        unwriteableMarginLeft: 0,
   1934      },
   1935    },
   1936    ref: {
   1937      settings: {
   1938        paperWidth: 8.5,
   1939        paperHeight: 11,
   1940        paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeInches,
   1941        marginTop: 0,
   1942        marginRight: 0,
   1943        marginBottom: 0,
   1944        marginLeft: 0,
   1945        unwriteableMarginTop: 0,
   1946        unwriteableMarginRight: 0,
   1947        unwriteableMarginBottom: 0,
   1948        unwriteableMarginLeft: 0,
   1949      },
   1950    },
   1951  });
   1952  await SpecialPowers.popPrefEnv();
   1953  requestAnimationFrame(() => setTimeout(runTest66));
   1954 }
   1955 
   1956 // Basic test for black-and-white rendering. This is mostly a crashtest for
   1957 // bug 1961975, but it also serves to verify that a blank page looks the same
   1958 // whether rendered in color vs. in black-and-white.
   1959 // (Actual content -- even black-and-white content -- is harder to test because
   1960 // our black-and-white filter adds some subtle antialiasing effects.)
   1961 async function runTest66() {
   1962  // Note: these test/ref URIs are both blank; we're testing a blank page
   1963  // rendered under two different configurations. The HTML comments are
   1964  // only there to make the data-URIs different, so that a navigation
   1965  // actually happens -- and the 'load' event fires, etc. -- when we set the
   1966  // reference-case-URI.
   1967  let test = `data:text/html,<!--test-->`;
   1968  let ref = `data:text/html,<!--ref-->`;
   1969 
   1970  await compareFiles(test, ref, {
   1971    test: {
   1972      settings: {
   1973        printInColor: false,
   1974      },
   1975    },
   1976    ref: {
   1977      settings: {
   1978        printInColor: true,
   1979      },
   1980    },
   1981  });
   1982  finish();
   1983 }
   1984 
   1985 
   1986 ]]></script>
   1987 <table style="border: 1px solid black;" xmlns="http://www.w3.org/1999/xhtml">
   1988 <tr><th>Print preview canvas 1</th><th>Print preview canvas 2</th></tr>
   1989 <tr>
   1990 <td><canvas height="800" width="800"></canvas></td>
   1991 <td><canvas height="800" width="800"></canvas></td>
   1992 </tr></table>
   1993 </window>