tor-browser

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

test_contentViewer_overrideDPPX.html (13679B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <title>nsIDocumentViewer::overrideDPPX test</title>
      5  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6  <script src="/tests/SimpleTest/EventUtils.js"></script>
      7  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
      8 </head>
      9 
     10 <body>
     11 
     12 <iframe></iframe>
     13 <img>
     14 
     15 <script type="application/javascript">
     16 
     17 SimpleTest.waitForExplicitFinish();
     18 
     19 const frameWindow = document.querySelector("iframe").contentWindow;
     20 const image = document.querySelector("img");
     21 
     22 const originalDPR = window.devicePixelRatio;
     23 const originalZoom = SpecialPowers.getFullZoom(window);
     24 const dppx = originalDPR * 1.5;
     25 const zoom = originalZoom * 0.5;
     26 
     27 const imageSets = {
     28  "1x"  : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA" +
     29          "GUlEQVQ4jWP4z8DwnxLMMGrAqAGjBgwXAwAwxP4QWURl4wAAAABJRU5ErkJggg==",
     30  "1.5x": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA" +
     31          "GElEQVQ4jWNgaGD4TxEeNWDUgFEDhosBAOsIfxAZ/CYXAAAAAElFTkSuQmCC",
     32  "2x"  : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA" +
     33          "GElEQVQ4jWNgYPj/nzI8asCoAaMGDBMDADKm/hBZaHKGAAAAAElFTkSuQmCC",
     34  "8x"  : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA" +
     35          "GklEQVQ4jWP4f+D0f0oww6gBowaMGjBcDAAAskKJLhIvZvgAAAAASUVORK5CYII=",
     36 };
     37 
     38 const setOverrideDPPX = (value) => {
     39  if (value > 0) {
     40    info(`override window's dppx to ${value}`);
     41  } else {
     42    info(`restore window's dppx to default value`);
     43  }
     44 
     45  return SpecialPowers.spawnChrome([value], dppx => {
     46    browsingContext.top.overrideDPPX = dppx;
     47  });
     48 };
     49 
     50 const setFullZoom = (value) => {
     51  info(`set window's fullZoom to ${value}`);
     52  SpecialPowers.setFullZoom(window, value);
     53 }
     54 
     55 const createFontStyleForDPPX = (doc, value, size) => {
     56  info(`adding a stylesheet that set font size to ${size}px for ${value}dppx`);
     57 
     58  let style = doc.createElement("style");
     59 
     60  style.setAttribute("media", `(resolution: ${value}dppx)`);
     61 
     62  doc.head.appendChild(style);
     63 
     64  style.sheet.insertRule(`body {font-size: ${size}px}`, 0);
     65 
     66  return style;
     67 }
     68 
     69 const getBodyFontSize = (w) => w.getComputedStyle(w.document.body).fontSize;
     70 
     71 const assertValuesAreInitial = () => {
     72  is(window.devicePixelRatio, originalDPR,
     73    "devicePixelRatio has the original value.");
     74  is(SpecialPowers.getFullZoom(window), originalZoom,
     75    "fullZoom has the original value.");
     76 
     77  is(frameWindow.devicePixelRatio, originalDPR,
     78    "devicePixelRatio has the original value.");
     79  is(SpecialPowers.getFullZoom(frameWindow), originalZoom,
     80    "fullZoom has the original value.");
     81 }
     82 
     83 const waitForMediaQueryListEvent = (mediaQueryList) => {
     84  return new Promise(resolve => {
     85    mediaQueryList.addListener(function listener() {
     86      ok(true, "MediaQueryList's listener invoked for " + mediaQueryList.media);
     87      mediaQueryList.removeListener(listener);
     88      // We need to evacuate a media query list event to avoid changing any
     89      // media features inside this callback (and microtasks for the callbacks),
     90      // because we currently dispatch media query list events during flush
     91      // pending styles, and we want to make sure there is no pending media
     92      // feature changes after the event handling.
     93      // This workaround should be dropped in bug 1437688.
     94      setTimeout(resolve, 0);
     95    });
     96  });
     97 }
     98 
     99 const gTests = {
    100  "test overrideDPPX with devicePixelRatio": async (done) => {
    101    assertValuesAreInitial();
    102 
    103    await setOverrideDPPX(dppx);
    104 
    105    is(window.devicePixelRatio, dppx,
    106      "devicePixelRatio overridden.");
    107    is(frameWindow.devicePixelRatio, dppx,
    108      "frame's devicePixelRatio overridden.");
    109 
    110    await setOverrideDPPX(0);
    111 
    112    is(window.devicePixelRatio, originalDPR,
    113      "devicePixelRatio back to default.");
    114    is(frameWindow.devicePixelRatio, originalDPR,
    115      "frame's devicePixelRatio back to default.");
    116 
    117    done();
    118  },
    119  "test overrideDPPX with devicePixelRatio and fullZoom": async (done) => {
    120    assertValuesAreInitial();
    121 
    122    setFullZoom(zoom);
    123    await setOverrideDPPX(dppx);
    124 
    125    is(window.devicePixelRatio, dppx,
    126      "devicePixelRatio overridden; fullZoom ignored");
    127    is(SpecialPowers.wrap(window).devicePixelRatio, originalDPR * zoom,
    128      "devicePixelRatio is right for privileged code");
    129    is(frameWindow.devicePixelRatio, dppx,
    130      "frame's devicePixelRatio overridden; fullZoom ignored");
    131    is(SpecialPowers.wrap(frameWindow).devicePixelRatio, originalDPR * zoom,
    132      "frame's devicePixelRatio is right for privileged code");
    133 
    134    await setOverrideDPPX(0);
    135 
    136    is(window.devicePixelRatio, originalDPR * zoom,
    137      "devicePixelRatio now is affected by fullZoom");
    138    is(frameWindow.devicePixelRatio, originalDPR * zoom,
    139      "frame's devicePixelRatio now is affected by fullZoom");
    140    isnot(dppx, originalDPR * zoom,
    141          "test is no longer testing what it should be");
    142 
    143    setFullZoom(originalZoom);
    144 
    145    is(window.devicePixelRatio, originalDPR,
    146      "devicePixelRatio back to default.");
    147    is(frameWindow.devicePixelRatio, originalDPR,
    148      "frame's devicePixelRatio back to default.");
    149 
    150    done();
    151 
    152  },
    153  "test overrideDPPX with media queries": async (done) => {
    154    assertValuesAreInitial();
    155 
    156    let frameDoc = frameWindow.document;
    157 
    158    let originalFontSize = getBodyFontSize(window);
    159    let frameOriginalFontSize = getBodyFontSize(frameWindow);
    160 
    161    let style = createFontStyleForDPPX(document, dppx, "32");
    162    let frameStyle = createFontStyleForDPPX(frameDoc, dppx, "32");
    163 
    164    let currentFontSize = getBodyFontSize(window);
    165    let frameCurrentFontSize = getBodyFontSize(frameWindow);
    166 
    167    is(currentFontSize, originalFontSize,
    168      "media queries are not applied yet");
    169    is(frameCurrentFontSize, frameOriginalFontSize,
    170      "frame's media queries are not applied yet");
    171 
    172    await setOverrideDPPX(dppx);
    173 
    174    currentFontSize = getBodyFontSize(window);
    175    frameCurrentFontSize = getBodyFontSize(frameWindow);
    176 
    177    isnot(currentFontSize, originalFontSize,
    178      "media queries are applied.");
    179    isnot(frameCurrentFontSize, frameOriginalFontSize,
    180      "frame's media queries are applied.");
    181 
    182    is(currentFontSize, "32px",
    183      "font size has the expected value.");
    184    is(frameCurrentFontSize, "32px",
    185      "frame's font size has the expected value.");
    186 
    187    await setOverrideDPPX(0);
    188 
    189    currentFontSize = getBodyFontSize(window);
    190    frameCurrentFontSize = getBodyFontSize(frameWindow);
    191 
    192    is(currentFontSize, originalFontSize,
    193      "media queries are not applied anymore.");
    194    is(frameCurrentFontSize, frameOriginalFontSize,
    195      "media queries are not applied anymore.");
    196 
    197    style.remove();
    198    frameStyle.remove();
    199 
    200    done();
    201  },
    202  "test overrideDPPX with media queries and fullZoom": async (done) => {
    203    assertValuesAreInitial();
    204 
    205    let frameDoc = frameWindow.document;
    206 
    207    let styles = [
    208      createFontStyleForDPPX(document, originalDPR, "23"),
    209      createFontStyleForDPPX(document, dppx, "32"),
    210      createFontStyleForDPPX(document, originalDPR * zoom, "48"),
    211      createFontStyleForDPPX(frameDoc, originalDPR, "23"),
    212      createFontStyleForDPPX(frameDoc, dppx, "32"),
    213      createFontStyleForDPPX(frameDoc, originalDPR * zoom, "48")
    214    ];
    215 
    216    let currentFontSize = getBodyFontSize(window);
    217    let frameCurrentFontSize = getBodyFontSize(frameWindow);
    218    is(currentFontSize, "23px",
    219      "media queries are not applied yet");
    220    is(frameCurrentFontSize, "23px",
    221      "frame's media queries are not applied yet");
    222 
    223    setFullZoom(zoom);
    224    await setOverrideDPPX(dppx);
    225 
    226    currentFontSize = getBodyFontSize(window);
    227    frameCurrentFontSize = getBodyFontSize(frameWindow);
    228    is(currentFontSize, "32px",
    229      "media queries are applied for overridden DDPX; fullZoom ignored.");
    230    is(frameCurrentFontSize, "32px",
    231      "frame's media queries are applied for overridden DDPX; fullZoom ignored.");
    232 
    233    await setOverrideDPPX(0);
    234 
    235    currentFontSize = getBodyFontSize(window);
    236    frameCurrentFontSize = getBodyFontSize(frameWindow);
    237    is(currentFontSize, "48px",
    238      "media queries are applied for fullZoom.");
    239    is(frameCurrentFontSize, "48px",
    240      "frame's media queries are applied for fullZoom.");
    241 
    242    setFullZoom(originalZoom);
    243 
    244    currentFontSize = getBodyFontSize(window);
    245    frameCurrentFontSize = getBodyFontSize(frameWindow);
    246    is(currentFontSize, "23px",
    247      "media queries are not applied anymore.");
    248    is(frameCurrentFontSize, "23px",
    249      "frame's media queries are not applied anymore.");
    250 
    251    styles.forEach(style => style.remove());
    252 
    253    done();
    254  },
    255  "test OverrideDPPX with MediaQueryList": (done) => {
    256    assertValuesAreInitial();
    257 
    258    let promises = [
    259      waitForMediaQueryListEvent(
    260        window.matchMedia(`(resolution: ${dppx}dppx)`)),
    261      waitForMediaQueryListEvent(
    262        frameWindow.matchMedia(`(resolution: ${dppx}dppx)`)),
    263    ];
    264 
    265    Promise.all(promises)
    266      .then(() => setOverrideDPPX(0))
    267      .then(done, e => {throw e});
    268 
    269    setOverrideDPPX(dppx);
    270  },
    271  "test OverrideDPPX with MediaQueryList and fullZoom": async (done) => {
    272    assertValuesAreInitial();
    273 
    274    let promises = [
    275      waitForMediaQueryListEvent(
    276        window.matchMedia(`(resolution: ${dppx}dppx)`)),
    277      waitForMediaQueryListEvent(
    278        window.matchMedia(`(resolution: ${originalDPR * zoom}dppx)`)),
    279    ];
    280 
    281    await setOverrideDPPX(dppx);
    282    setFullZoom(zoom);
    283 
    284    promises[0]
    285      .then(() => setOverrideDPPX(0))
    286      .then(promises[1])
    287      .then(() => setFullZoom(originalZoom))
    288      .then(done, e => {throw e});
    289  },
    290  "test OverrideDPPX is kept on document navigation": async (done) => {
    291    assertValuesAreInitial();
    292 
    293    let frameOriginalFontSize = getBodyFontSize(frameWindow);
    294    let frameStyle = createFontStyleForDPPX(frameWindow.document, dppx, "32");
    295    let frameCurrentFontSize = getBodyFontSize(frameWindow);
    296 
    297    is(frameCurrentFontSize, frameOriginalFontSize,
    298      "frame's media queries are not applied yet");
    299 
    300    await setOverrideDPPX(dppx);
    301 
    302    frameCurrentFontSize = getBodyFontSize(frameWindow);
    303 
    304    is(frameWindow.devicePixelRatio, dppx,
    305      "frame's devicePixelRatio overridden.");
    306    isnot(frameCurrentFontSize, frameOriginalFontSize,
    307      "frame's media queries are applied.");
    308    is(frameCurrentFontSize, "32px",
    309      "frame's font size has the expected value.");
    310 
    311    frameWindow.frameElement.addEventListener("load", async function() {
    312      frameStyle = createFontStyleForDPPX(frameWindow.document, dppx, "32");
    313 
    314      frameCurrentFontSize = getBodyFontSize(frameWindow);
    315 
    316      is(frameWindow.devicePixelRatio, dppx,
    317        "frame's devicePixelRatio is still overridden.");
    318      isnot(frameCurrentFontSize, frameOriginalFontSize,
    319        "frame's media queries are still applied.");
    320      is(frameCurrentFontSize, "32px",
    321        "frame's font size has still the expected value.");
    322 
    323      frameStyle.remove();
    324 
    325      await setOverrideDPPX(0);
    326 
    327      done();
    328    }, {once: true});
    329 
    330    frameWindow.location.reload(true);
    331  },
    332 
    333  "test overrideDPPX with srcset": async function (done) {
    334    assertValuesAreInitial();
    335 
    336    let loaded;
    337 
    338    // Set the image srcset and default src.  This is delayed until this test so
    339    // that dppx overrides in other test blocks don't trigger load event on the
    340    // image.
    341    loaded = new Promise(resolve => image.onload = resolve);
    342    image.srcset = Object.entries(imageSets).map(v => v[1] + " " + v[0]).join(", ");
    343    image.src = imageSets["1x"];
    344    await loaded;
    345 
    346    let originalSrc = image.currentSrc;
    347 
    348    // Make sure to test some very large value that can't be the default density
    349    // so that the first override will always trigger a load.
    350    isnot(originalDPR, 8, "originalDPR differs from final test value");
    351    loaded = new Promise(resolve => image.onload = resolve);
    352    await setOverrideDPPX(8);
    353    await loaded;
    354 
    355    is(image.currentSrc, imageSets["8x"],
    356      "Image is properly set for 8dppx.");
    357 
    358    loaded = new Promise(resolve => image.onload = resolve);
    359    await setOverrideDPPX(1);
    360    await loaded;
    361 
    362    is(image.currentSrc, imageSets["1x"],
    363      "Image url is properly set for 1dppx.");
    364 
    365    loaded = new Promise(resolve => image.onload = resolve);
    366    await setOverrideDPPX(1.5);
    367    await loaded;
    368 
    369    is(image.currentSrc, imageSets["1.5x"],
    370      "Image url is properly set for 1.5dppx.");
    371 
    372    loaded = new Promise(resolve => image.onload = resolve);
    373    await setOverrideDPPX(2);
    374    await loaded;
    375 
    376    is(image.currentSrc, imageSets["2x"],
    377      "Image is properly set for 2dppx.");
    378 
    379    // Make sure to test some very large value that can't be the default density
    380    // so that resetting to the default will always trigger a load.
    381    isnot(originalDPR, 8, "originalDPR differs from final test value");
    382    loaded = new Promise(resolve => image.onload = resolve);
    383    await setOverrideDPPX(8);
    384    await loaded;
    385 
    386    is(image.currentSrc, imageSets["8x"],
    387      "Image is properly set for 8dppx.");
    388 
    389    loaded = new Promise(resolve => image.onload = resolve);
    390    await setOverrideDPPX(0);
    391    await loaded;
    392 
    393    is(image.currentSrc, originalSrc,
    394      "Image is properly restored to the default value.");
    395 
    396    // Clear sources so any future dppx test blocks don't trigger image loads.
    397    image.srcset = "";
    398    image.src = "";
    399 
    400    done();
    401  }
    402 };
    403 
    404 function* runner(tests) {
    405  for (let name of Object.keys(tests)) {
    406    info(name);
    407    tests[name](next);
    408    yield undefined;
    409  }
    410 };
    411 
    412 const gTestRunner = runner(gTests);
    413 
    414 function next() {
    415  SimpleTest.executeSoon(function() {
    416    if (gTestRunner.next().done) {
    417      SimpleTest.finish();
    418    }
    419  });
    420 }
    421 
    422 // Run the tests
    423 addLoadEvent(next);
    424 
    425 </script>
    426 
    427 </body>
    428 </html>