summaryrefslogtreecommitdiffstats
path: root/layout/generic/test/test_bug507902.html
diff options
context:
space:
mode:
Diffstat (limited to 'layout/generic/test/test_bug507902.html')
-rw-r--r--layout/generic/test/test_bug507902.html382
1 files changed, 382 insertions, 0 deletions
diff --git a/layout/generic/test/test_bug507902.html b/layout/generic/test/test_bug507902.html
new file mode 100644
index 000000000..efcca8ad7
--- /dev/null
+++ b/layout/generic/test/test_bug507902.html
@@ -0,0 +1,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>