DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (5350524bb654)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=507902
-->
<head>
  <title>Test for Bug 507902</title>
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=507902">Mozilla Bug 507902</a>

<iframe id="testFrameElem"></iframe>

<pre id="test">
<script class="testbody" type="text/javascript">

//
// Mochitest to test nsImageFrame icons
//
// The 'loading' icon should be displayed up until we have enough image
// data to determine the frame size.
//
// The 'broken' icon should be displayed when the URL is invalid (either
// a bad server or a file that fails to be sniffed to an appropriate
// mimetype).
//

// Boilerplate
gWindowUtils = SpecialPowers.getDOMWindowUtils(window);

// URL + paths
//
// We have a separate copy of the icons in the test directory to
// avoid any firefox caching mechanisms that might affect the
// behavior of the load.
var us = window.location.href;
var baseURL = us.substring(0, us.lastIndexOf('/') + 1);
var loadIconFilename = "file_LoadingImageReference.png";
var imageFilename = "file_Dolske.png";
var brokenIconFilename = "file_BrokenImageReference.png";
var serverFilename = "file_IconTestServer.sjs";
var serverContinueFlag = "?continue=true";
var bogusFilename = "oneuponatimewhendolskewasyoung.png";

// Our test image element, inside a div, inside an iframe
var testFrameElem = document.getElementById("testFrameElem");
var innerDoc = testFrameElem.contentWindow.document;
var divContainer = innerDoc.createElement("div");
divContainer.style.cssFloat = "left";
innerDoc.body.appendChild(divContainer);
var testImageElem = new Image();
divContainer.appendChild(testImageElem);
var pingImage = new Image();

// Set up the canvases
var canvases = {};
var canvasNames = [ "brokenIconTest",  "brokenIconReference",
                    "loadingIconTest", "loadingIconReference",
                    "loadedTest",      "loadedReference" ];
var windowElem = document.documentElement;
for (var i in canvasNames) {
  var can = document.createElement("canvas");
  can.setAttribute("width", windowElem.getAttribute("width"));
  can.setAttribute("height", windowElem.getAttribute("height"));
  canvases[canvasNames[i]] = can;

  // When the image frame has no idea how to size itself, it sizes itself
  // to dimensions capable of displaying the alt feedback icons. However, if
  // the image has been loaded before, something (I don't know what) seems to
  // remember the size of the last successful image for that URL. So when we
  // create a new image frame for that URL, it uses that size until it hears
  // something different. This happens through a refresh (not sure if this is
  // desired behavior). This means that if you refresh the test, the "loading"
  // icon for the test image will appear with a border that stretches further
  // right and down, because that URL previously displayed an image with larger
  // dimensions. This causes the verify stage to fail. To allow for
  // successful test refreshes (only useful for people, not automated tests),
  // we add a clipping region so that we see the left and top borders, along
  // with the image, but not the bottom and right borders.

  if ((i > 1) && (i < 4)) {
    var ctx = can.getContext("2d");
    ctx.beginPath();
    ctx.rect(0,0, 30, 30);
    ctx.clip();
   }

}

// Stage 1 - Load the reference image for the broken icon
function loadBrokenIconReference() {

  // Debugging - Let's see if setting onload after src is a problem
  testImageElem.onload = function(event) { dump("test_bug507902.html DEBUG - uh oh, placeholder onload 1 called\n");};

  // Debug - Figure out if we're getting an onerror instead of onload
  testImageElem.onerror = function(event) {dump("test_bug507902.html DEBUG - Got onerror for testImageElem!\n");};

  testImageElem.src = baseURL + brokenIconFilename;
  stageTransition();
}

// Stage 2 - Draw the reference image for the broken icon to a canvas
function drawBrokenIconReference() {

  enableBorderAndPad();
  drawWindowToCanvas("brokenIconReference");
  disableBorderAndPad();

  stageTransition();
}

// Stage 3 - Load the reference image for the loading icon
function loadLoadingIconReference() {

  // Debugging - Let's see if setting onload after src is a problem
  testImageElem.onload = function(event) { dump("test_bug507902.html DEBUG - uh oh, placeholder onload 3 called\n");};

  testImageElem.src = baseURL + loadIconFilename;
  stageTransition();
}

// Stage 4 - Draw the reference image for the loading icon to a canvas
function drawLoadingIconReference() {

  enableBorderAndPad();
  drawWindowToCanvas("loadingIconReference");
  disableBorderAndPad();

  stageTransition();
}

// Stage 5 - Try to load a broken image
function loadBrokenImage() {
  resetImage();
  testImageElem.src = baseURL + bogusFilename;
  stageTransition();
}

// Stage 6 - Draw the screen to a canvas. This should hopefully
// be the broken icon.
function drawBrokenIcon() {
  drawWindowToCanvas("brokenIconTest");
  stageTransition();
}

// Stage 7 - Load the reference image for the test image
function loadImageReference() {
  resetImage();

  // Debugging - Let's see if setting onload after src is a problem
  testImageElem.onload = function(event) { dump("test_bug507902.html DEBUG - uh oh, placeholder onload 7 called\n");};

  testImageElem.src = baseURL + imageFilename;
  stageTransition();
}

// Stage 8 - Draw the reference image for the test image to a canvas
function drawImageReference() {
  drawWindowToCanvas("loadedReference");
  stageTransition();
}

// Stage 9 - Start a load of the test image from the delay-generating server
function startServerLoad() {

  // Reset the image
  resetImage();

  // Debugging info so we can figure out the hang
  dump("test_bug507902.html DEBUG - starting server load\n");

  // Load the image
  testImageElem.src = baseURL + serverFilename;
  stageTransition();
}

// Stage 10 - Draw the screen to a canvas. This should hopefully be the loading
// icon.
function drawLoadingIcon() {

  // Debugging info so we can figure out the hang
  dump("test_bug507902.html DEBUG - drawing loading icon\n");

  drawWindowToCanvas("loadingIconTest");
  stageTransition();
}

// Stage 11 - Tell the server to continue.
function signalServerContinue() {

  // Debugging info so we can figure out the hang
  dump("test_bug507902.html DEBUG - signaling server to continue\n");

  pingImage.src = baseURL + serverFilename + serverContinueFlag;
  stageTransition();
}

// Stage 12 - Draw the screen to a canvas. This should hopefully be the loaded
// test image.
function drawLoadedImage() {
  drawWindowToCanvas("loadedTest");
  stageTransition();
}


// Stage 13 - Verify That the appropriate canvases match
function verifyCanvases() {

  // Verify the broken icon
  ok(canvasesAreEqual("brokenIconTest", "brokenIconReference"),
     "Window drawn on broken load should match broken icon reference");

  // Verify the loading icon
  ok(canvasesAreEqual("loadingIconTest", "loadingIconReference"),
     "Window drawn mid-load should match loading icon reference");

  // Verify the loaded image
  ok(canvasesAreEqual("loadedTest", "loadedReference"),
     "Window drawn post-load should match reference image");

  stageTransition();
}

// We have a bunch of different things that need to happen in order
// with different transitions. We make a "stage table" here where
// each entry contains the stage function ('fn') and a transition
// ('trans'), which can be one of the following:
// "instant" - Just calls the next stage directly
// "onload" - Sets the next stage as an onload event for the image element
// "onerror" - Sets the next stage as an onerror event for the image element
// integer  - Sets the next stage to be called after the given timeout duration
// "finish" - Finish the test
var testStages = [
  { "fn" : loadBrokenIconReference,  "trans" : "onload"},
  { "fn" : drawBrokenIconReference,  "trans" : "instant"},
  { "fn" : loadLoadingIconReference, "trans" : "onload" },
  { "fn" : drawLoadingIconReference, "trans" : "instant" },
  { "fn" : loadBrokenImage,          "trans" : "onerror" },
  { "fn" : drawBrokenIcon,           "trans" : "instant" },
  { "fn" : loadImageReference,       "trans" : "onload" },
  { "fn" : drawImageReference,       "trans" : "instant" },
  // XXXbholley - We use a timeout here because resetting the
  // image doesn't seem to be quite synchronous. If we make
  // this transition "instant", then the drawImage call draws
  // an empty (0,0,0,0) rect to the canvas and we're left with
  // whatever was there before. I don't know of any good event
  // mechanism to figure out when the image frame is bootstrapped
  // enough to display the loading image, so I did trial-and-error
  // with timeouts. 50ms seems to be enough time for things to work
  // reliably, so *= 6 for good measure.
  { "fn" : startServerLoad,          "trans" : 300 },
  { "fn" : drawLoadingIcon,          "trans" : "instant" },
  { "fn" : signalServerContinue,     "trans" : "onload" },
  { "fn" : drawLoadedImage,          "trans" : "instant" },
  { "fn" : verifyCanvases,           "trans" : "finish" } ];
var currentStage = 0;

// Transition function called at the end of each stage
function stageTransition() {

  // Debugging info so we can figure out the hang
  dump("test_bug507902.html DEBUG - Current Stage: " + currentStage + "\n");

  // What's our transition?
  var trans = testStages[currentStage++].trans;

  // If the transition is finish, stop now before we access out of bounds
  if (trans == "finish") {
    makeCanvasesVisible(); // Useful for debugging
    SimpleTest.finish();
    return;
  }

  // Otherwise, get the next function
  var nextfn = testStages[currentStage].fn;

  // Switch based on transition
  switch (trans) {

    // Continue right away
    case "instant":
      nextfn();
      break;

    // Continue after we get an onload event on the test image
    case "onload":
      testImageElem.onload = function(event) {testImageElem.onload = undefined; nextfn();};
      break;

    // Continue after we get an onerror event on the test image
    case "onerror":
      testImageElem.onerror = function(event) {testImageElem.onerror = undefined; nextfn();};
      break;

    // Timeout
    default:
      setTimeout(nextfn, trans);
      break
  }
}

// Lots if asynchronous behavior here
SimpleTest.waitForExplicitFinish();

// Catch somebody's eye
dump("This test is failing intermittently, see bug 510001 - If you see orange here, please paste the following debugging output on the bug!\n");

// Kick off the test by invoking the first stage. The stages call each other
testStages[0].fn();


// We need to get rid of the old image element and make a new one. If we
// don't, the "current/pending" machinery will display the old image until
// the new one is loaded, so we won't see the loading icon.
function resetImage() {
  divContainer.removeChild(testImageElem);
  testImageElem = null;
  testImageElem = new Image();
  divContainer.appendChild(testImageElem);
}

//
// Makes the canvases visible. Called before the tests finish. This is useful for
// debugging.
//
function makeCanvasesVisible() {
  for (var i = 0; i < canvasNames.length - 1; i += 2) {
    var title = document.createElement("h3");
    title.innerHTML = canvasNames[i] + ", " + canvasNames[i+1] + ":";
    document.body.appendChild(title);
    var myDiv = document.createElement("div");
    myDiv.appendChild(canvases[canvasNames[i]]);
    myDiv.appendChild(canvases[canvasNames[i+1]]);
    document.body.appendChild(myDiv);
  }
}

//
// Enables and disables bordering/padding to mimic the look of alt feedback icons
//
function enableBorderAndPad() {
  divContainer.style.border = "1px";
  divContainer.style.borderStyle = "inset";
  testImageElem.style.padding = "3px";
}

function disableBorderAndPad() {
  testImageElem.style.padding = 0;
  divContainer.style.border = "0px";
  divContainer.style.borderStyle = "";
}

//
// Helper canvas methods. This is mostly copped directly from the reftest framework
//

function drawWindowToCanvas(canvasName) {
  var win = testFrameElem.contentWindow;
  var ctx = canvases[canvasName].getContext("2d");
  // drawWindow always draws one canvas pixel for each CSS pixel in the source
  // window, so scale the drawing to show the zoom (making each canvas pixel be one
  // device pixel instead)
  ctx.drawWindow(win, win.scrollX, win.scrollY,
                 Math.ceil(canvases[canvasName].width),
                 Math.ceil(canvases[canvasName].height),
                 "rgb(255,255,255)");
}

function canvasesAreEqual(canvas1Name, canvas2Name) {
  var c1 = canvases[canvas1Name];
  var c2 = canvases[canvas2Name];
  var differences = gWindowUtils.compareCanvases(c1, c2, {});
  return (differences == 0);
}

</script>
</pre>
</body>
</html>