# HG changeset patch # User Joel Maher # Date 1316032898 14400 # Node ID 0b38ce037298ee46adc379e7c9dd622437fda5a3 # Parent bffb8b1b0948913792f4b40fb52b26d335fa861d Bug 661918 - Tp should wait for MozAfterPaint after onload. r=tnikkel,vlad diff -r bffb8b1b0948 -r 0b38ce037298 chrome/pageloader.js --- a/chrome/pageloader.js Thu Apr 28 10:32:20 2011 -0700 +++ b/chrome/pageloader.js Wed Sep 14 16:41:38 2011 -0400 @@ -67,6 +67,14 @@ var running = false; var forceCC = true; +var useMozAfterPaint = false; +var gPaintWindow = window; +var gPaintListener = false; + +//when TEST_DOES_OWN_TIMING, we need to store the time from the page as MozAfterPaint can be slower than pageload +var gTime = -1; +var gStartTime = -1; + var content; var TEST_DOES_OWN_TIMING = 1; @@ -100,6 +108,8 @@ if (args.noisy) noisy = true; if (args.timeout) timeout = parseInt(args.timeout); if (args.delay) delay = parseInt(args.delay); + if (args.mozafterpaint) useMozAfterPaint = true; + forceCC = !args.noForceCC; doRenderTest = args.doRender; @@ -155,6 +165,7 @@ (null, "chrome://browser/content/", "_blank", "chrome,all,dialog=no,width=" + winWidth + ",height=" + winHeight, blank); + gPaintWindow = browserWindow; // get our window out of the way window.resizeTo(10,10); @@ -173,12 +184,30 @@ // Load the frame script for e10s / IPC message support if (content.getAttribute("remote") == "true") { - let contentScript = "data:,addEventListener('load', function(e) { " + + let contentScript = "data:,function _contentLoadHandler(e) { " + " if (e.originalTarget.defaultView == content) { " + - " sendAsyncMessage('PageLoader:Load', {}); " + - " content.wrappedJSObject.tpRecordTime = function(t) { sendAsyncMessage('PageLoader:RecordTime', { time: t }); } " + + " content.wrappedJSObject.tpRecordTime = function(t, s) { sendAsyncMessage('PageLoader:RecordTime', { time: t, startTime: s }); }; "; + if (useMozAfterPaint) { + contentScript += "" + + "function _contentPaintHandler() { " + + " var utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils); " + + " if (utils.isMozAfterPaintPending) { " + + " addEventListener('MozAfterPaint', function(e) { " + + " removeEventListener('MozAfterPaint', arguments.callee, true); " + + " sendAsyncMessage('PageLoader:MozAfterPaint', {}); " + + " }, true); " + + " } else { " + + " sendAsyncMessage('PageLoader:MozAfterPaint', {}); " + + " } " + + "}; " + + "content.wrappedJSObject.setTimeout(_contentPaintHandler, 0); "; + } else { + contentScript += " sendAsyncMessage('PageLoader:Load', {}); "; + } + contentScript += "" + " }" + - "}, true);" + "} " + + "addEventListener('load', _contentLoadHandler, true); "; content.messageManager.loadFrameScript(contentScript, false); } @@ -188,6 +217,7 @@ browserWindow.addEventListener('load', browserLoadFunc, true); } else { + gPaintWindow = window; window.resizeTo(winWidth, winHeight); content = document.getElementById('contentPageloader'); @@ -219,9 +249,14 @@ if (plPageFlags() & TEST_DOES_OWN_TIMING) { // if the page does its own timing, use a capturing handler // to make sure that we can set up the function for content to call + content.addEventListener('load', plLoadHandlerCapturing, true); removeLastAddedListener = function() { content.removeEventListener('load', plLoadHandlerCapturing, true); + if (useMozAfterPaint) { + content.removeEventListener("MozAfterPaint", plPaintedCapturing, true); + gPaintHandler = false; + } }; } else { // if the page doesn't do its own timing, use a bubbling handler @@ -232,6 +267,10 @@ content.addEventListener('load', plLoadHandler, true); removeLastAddedListener = function() { content.removeEventListener('load', plLoadHandler, true); + if (useMozAfterPaint) { + gPaintWindow.removeEventListener("MozAfterPaint", plPainted, true); + gPaintHandler = false; + } }; } @@ -239,9 +278,13 @@ if (content.getAttribute("remote") == "true") { content.messageManager.addMessageListener('PageLoader:Load', plLoadHandlerMessage); content.messageManager.addMessageListener('PageLoader:RecordTime', plRecordTimeMessage); + if (useMozAfterPaint) + content.messageManager.addMessageListener('PageLoader:MozAfterPaint', plPaintHandler); removeLastAddedMsgListener = function() { content.messageManager.removeMessageListener('PageLoader:Load', plLoadHandlerMessage); content.messageManager.removeMessageListener('PageLoader:RecordTime', plRecordTimeMessage); + if (useMozAfterPaint) + content.messageManager.removeMessageListener('PageLoader:MozAfterPaint', plPaintHandler); }; } @@ -297,6 +340,43 @@ if (evt.type != 'load' || evt.originalTarget.defaultView.frameElement) return; + + //set the tpRecordTime function (called from test pages we load to store a global time. + content.contentWindow.wrappedJSObject.tpRecordTime = function (time, startTime) { + gTime = time; + gStartTime = startTime; + setTimeout(plWaitForPaintingCapturing, 0); + } + + content.removeEventListener('load', plLoadHandlerCapturing, true); + + setTimeout(plWaitForPaintingCapturing, 0); +} + +function plWaitForPaintingCapturing() { + if (gPaintListener) + return; + + var utils = gPaintWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + + if (utils.isMozAfterPaintPending && useMozAfterPaint) { + if (gPaintListener == false) + gPaintWindow.addEventListener("MozAfterPaint", plPaintedCapturing, true); + gPaintListener = true; + return; + } + + _loadHandlerCapturing(); +} + +function plPaintedCapturing() { + gPaintWindow.removeEventListener("MozAfterPaint", plPaintedCapturing, true); + gPaintListener = false; + _loadHandlerCapturing(); +} + +function _loadHandlerCapturing() { if (timeout > 0) { clearTimeout(timeoutEvent); } @@ -306,9 +386,17 @@ plStop(true); } + if (useMozAfterPaint) { + if (gStartTime != null && gStartTime >= 0) { + gTime = (new Date()) - gStartTime; + gStartTime = -1; + } + } + // set up the function for content to call - content.contentWindow.wrappedJSObject.tpRecordTime = function (time) { - plRecordTime(time); + if (gTime >= 0) { + plRecordTime(gTime); + gTime = -1; setTimeout(plNextPage, delay); }; } @@ -319,6 +407,34 @@ if (evt.type != 'load' || evt.originalTarget.defaultView.frameElement) return; + + content.removeEventListener('load', plLoadHandler, true); + setTimeout(waitForPainted, 0); +} + +// This is called after we have received a load event, now we wait for painted +function waitForPainted() { + + var utils = gPaintWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindowUtils); + + if (!utils.isMozAfterPaintPending || !useMozAfterPaint) { + _loadHandler(); + return; + } + + if (gPaintListener == false) + gPaintWindow.addEventListener("MozAfterPaint", plPainted, true); + gPaintListener = true; +} + +function plPainted() { + gPaintWindow.removeEventListener("MozAfterPaint", plPainted, true); + gPaintListener = false; + _loadHandler(); +} + +function _loadHandler() { if (timeout > 0) { clearTimeout(timeoutEvent); } @@ -354,30 +470,59 @@ // the onload handler used for remote (e10s) browser function plLoadHandlerMessage(message) { + _loadHandlerMessage(); +} + +// the mozafterpaint handler for remote (e10s) browser +function plPaintHandler(message) { + _loadHandlerMessage(); +} + +// the core handler for remote (e10s) browser +function _loadHandlerMessage() { if (timeout > 0) { clearTimeout(timeoutEvent); } + var time = -1; + // does this page want to do its own timing? - // if so, let's bail - if (plPageFlags() & TEST_DOES_OWN_TIMING) - return; + if ((plPageFlags() & TEST_DOES_OWN_TIMING)) { + if (typeof(gStartTime) != "number") + gStartTime = Date.parse(gStartTime); - var end_time = Date.now(); - var time = (end_time - start_time); - - plRecordTime(time); + if (gTime >= 0) { + if (useMozAfterPaint && gStartTime >= 0) { + gTime = Date.now() - gStartTime; + gStartTime = -1; + } else if (useMozAfterPaint) { + gTime = -1; + } + time = gTime; + gTime = -1; + } - if (doRenderTest) - runRenderTest(); + } else { + var end_time = Date.now(); + time = (end_time - start_time); + } - plNextPage(); + if (time >= 0) { + plRecordTime(time); + if (doRenderTest) + runRenderTest(); + + plNextPage(); + } } // the record time handler used for remote (e10s) browser function plRecordTimeMessage(message) { - plRecordTime(message.json.time); - setTimeout(plNextPage, delay); + gTime = message.json.time; + if (useMozAfterPaint) { + gStartTime = message.json.startTime; + } + _loadHandlerMessage(); } function runRenderTest() { @@ -429,9 +574,20 @@ } if (content) { + content.removeEventListener('load', plLoadHandlerCapturing, true); content.removeEventListener('load', plLoadHandler, true); - if (content.getAttribute("remote") == "true") + if (useMozAfterPaint) + content.removeEventListener("MozAfterPaint", plPaintedCapturing, true); + content.removeEventListener("MozAfterPaint", plPainted, true); + + if (content.getAttribute("remote") == "true") { content.messageManager.removeMessageListener('PageLoader:Load', plLoadHandlerMessage); + content.messageManager.removeMessageListener('PageLoader:RecordTime', plRecordTimeMessage); + if (MozAfterPaint) + content.messageManager.removeMessageListener('PageLoader:MozAfterPaint', plPaintHandler); + + content.messageManager.loadFrameScript("data:,removeEventListener('load', _contentLoadHandler, true);", false); + } } if (MozillaFileLogger) diff -r bffb8b1b0948 -r 0b38ce037298 components/tp-cmdline.js --- a/components/tp-cmdline.js Thu Apr 28 10:32:20 2011 -0700 +++ b/components/tp-cmdline.js Wed Sep 14 16:41:38 2011 -0400 @@ -93,6 +93,7 @@ args.timeout = cmdLine.handleFlagWithParam("tptimeout", false); args.delay = cmdLine.handleFlagWithParam("tpdelay", false); args.noForceCC = cmdLine.handleFlag("tpnoforcecc", false); + args.mozafterpaint = cmdLine.handleFlag("tpmozafterpaint", false); } catch (e) { return; @@ -123,7 +124,8 @@ " -tpnoisy Dump the name of the last loaded page to console\n" + " -tptimeout Max amount of time given for a page to load, quit if exceeded\n" + " -tpdelay Amount of time to wait between each pageload\n" + - " -tpnoforcecc Don't force cycle collection between each pageload\n" + " -tpnoforcecc Don't force cycle collection between each pageload\n" + + " -tpmozafterpaint Measure Time after recieving MozAfterPaint event instead of load event\n" };