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>