tor-browser

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

browser_bug666317.js (3840B)


      1 waitForExplicitFinish();
      2 
      3 var pageSource =
      4  "<html><body>" +
      5  '<img id="testImg" src="' +
      6  TESTROOT +
      7  'big.png">' +
      8  "</body></html>";
      9 
     10 var oldDiscardingPref, oldTab, newTab;
     11 var prefBranch = Services.prefs.getBranch("image.mem.");
     12 
     13 var gWaitingForDiscard = false;
     14 var gScriptedObserver;
     15 var gClonedRequest;
     16 
     17 function ImageObserver(decodeCallback, discardCallback) {
     18  this.decodeComplete = function onDecodeComplete() {
     19    decodeCallback();
     20  };
     21 
     22  this.discard = function onDiscard() {
     23    if (!gWaitingForDiscard) {
     24      return;
     25    }
     26 
     27    this.synchronous = false;
     28    discardCallback();
     29  };
     30 
     31  this.synchronous = true;
     32 }
     33 
     34 function currentRequest() {
     35  let img = gBrowser
     36    .getBrowserForTab(newTab)
     37    .contentWindow.document.getElementById("testImg");
     38  return img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
     39 }
     40 
     41 function isImgDecoded() {
     42  let request = currentRequest();
     43  return !!(request.imageStatus & Ci.imgIRequest.STATUS_DECODE_COMPLETE);
     44 }
     45 
     46 // Ensure that the image is decoded by drawing it to a canvas.
     47 function forceDecodeImg() {
     48  let doc = gBrowser.getBrowserForTab(newTab).contentWindow.document;
     49  let img = doc.getElementById("testImg");
     50  let canvas = doc.createElement("canvas");
     51  let ctx = canvas.getContext("2d");
     52  ctx.drawImage(img, 0, 0);
     53 }
     54 
     55 function runAfterAsyncEvents(aCallback) {
     56  function handlePostMessage(aEvent) {
     57    if (aEvent.data == "next") {
     58      window.removeEventListener("message", handlePostMessage);
     59      aCallback();
     60    }
     61  }
     62 
     63  window.addEventListener("message", handlePostMessage);
     64 
     65  // We'll receive the 'message' event after everything else that's currently in
     66  // the event queue (which is a stronger guarantee than setTimeout, because
     67  // setTimeout events may be coalesced). This lets us ensure that we run
     68  // aCallback *after* any asynchronous events are delivered.
     69  window.postMessage("next", "*");
     70 }
     71 
     72 function test() {
     73  // Enable the discarding pref.
     74  oldDiscardingPref = prefBranch.getBoolPref("discardable");
     75  prefBranch.setBoolPref("discardable", true);
     76 
     77  // Create and focus a new tab.
     78  oldTab = gBrowser.selectedTab;
     79  newTab = BrowserTestUtils.addTab(gBrowser, "data:text/html," + pageSource);
     80  gBrowser.selectedTab = newTab;
     81 
     82  // Run step2 after the tab loads.
     83  gBrowser.getBrowserForTab(newTab).addEventListener("pageshow", step2);
     84 }
     85 
     86 function step2() {
     87  // Create the image observer.
     88  var observer = new ImageObserver(
     89    () => runAfterAsyncEvents(step3), // DECODE_COMPLETE
     90    () => runAfterAsyncEvents(step5)
     91  ); // DISCARD
     92  gScriptedObserver = Cc["@mozilla.org/image/tools;1"]
     93    .getService(Ci.imgITools)
     94    .createScriptedObserver(observer);
     95 
     96  // Clone the current imgIRequest with our new observer.
     97  var request = currentRequest();
     98  gClonedRequest = request.clone(gScriptedObserver);
     99 
    100  // Check that the image is decoded.
    101  forceDecodeImg();
    102 
    103  // The DECODE_COMPLETE notification is delivered asynchronously. ImageObserver will
    104  // eventually call step3.
    105 }
    106 
    107 function step3() {
    108  ok(isImgDecoded(), "Image should initially be decoded.");
    109 
    110  // Focus the old tab, then fire a memory-pressure notification.  This should
    111  // cause the decoded image in the new tab to be discarded.
    112  gBrowser.selectedTab = oldTab;
    113 
    114  // Allow time to process the tab change.
    115  runAfterAsyncEvents(step4);
    116 }
    117 
    118 function step4() {
    119  gWaitingForDiscard = true;
    120 
    121  var os = Services.obs;
    122  os.notifyObservers(null, "memory-pressure", "heap-minimize");
    123 
    124  // The DISCARD notification is delivered asynchronously. ImageObserver will
    125  // eventually call step5. (Or else, sadly, the test will time out.)
    126 }
    127 
    128 function step5() {
    129  ok(true, "Image should be discarded.");
    130 
    131  // And we're done.
    132  gBrowser.removeTab(newTab);
    133  prefBranch.setBoolPref("discardable", oldDiscardingPref);
    134 
    135  gClonedRequest.cancelAndForgetObserver(0);
    136 
    137  finish();
    138 }