diff --git a/browser/devtools/performance/test/browser.ini b/browser/devtools/performance/test/browser.ini index ac81c60c079..03dab2776e5 100644 --- a/browser/devtools/performance/test/browser.ini +++ b/browser/devtools/performance/test/browser.ini @@ -62,6 +62,7 @@ support-files = [browser_perf-shared-connection-02.js] [browser_perf-shared-connection-03.js] [browser_perf-states.js] +[browser_perf-refresh.js] [browser_perf-ui-recording.js] [browser_perf-recording-notices-01.js] [browser_perf-recording-notices-02.js] diff --git a/browser/devtools/performance/test/browser_perf-refresh.js b/browser/devtools/performance/test/browser_perf-refresh.js new file mode 100644 index 00000000000..ee4cdcbe6b6 --- /dev/null +++ b/browser/devtools/performance/test/browser_perf-refresh.js @@ -0,0 +1,42 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Rough test that the recording still continues after a refresh. + */ +function spawnTest () { + let { panel, target } = yield initPerformance(SIMPLE_URL); + let { EVENTS, PerformanceController } = panel.panelWin; + + // Enable memory to test all the overview graphs. + Services.prefs.setBoolPref(MEMORY_PREF, true); + + yield startRecording(panel); + + yield reload(target) + + let rec = PerformanceController.getCurrentRecording(); + let { markers, memory, ticks } = rec.getAllData(); + // Store current length of items + let markersLength = markers.length; + let memoryLength = memory.length; + let ticksLength = ticks.length; + + ok(rec.isRecording(), "RecordingModel should still be recording after reload"); + + yield busyWait(100); + yield waitUntil(() => rec.getMarkers().length > markersLength); + yield waitUntil(() => rec.getMemory().length > memoryLength); + yield waitUntil(() => rec.getTicks().length > ticksLength); + ok("Markers, memory and ticks continue after reload"); + + yield stopRecording(panel); + + let { allocations, profile, frames } = rec.getAllData(); + ok(allocations, "allocations exist after refresh"); + ok(profile, "profile exists after refresh"); + ok(frames, "frames exist after refresh"); + + yield teardown(panel); + finish(); +} diff --git a/browser/devtools/performance/test/head.js b/browser/devtools/performance/test/head.js index c090b7498d4..0976b11496d 100644 --- a/browser/devtools/performance/test/head.js +++ b/browser/devtools/performance/test/head.js @@ -417,3 +417,8 @@ function getSourceActor(aSources, aURL) { function fireKey (e) { EventUtils.synthesizeKey(e, {}); } + +function reload (aTarget, aEvent = "navigate") { + aTarget.activeTab.reload(); + return once(aTarget, aEvent); +} diff --git a/toolkit/devtools/server/actors/framerate.js b/toolkit/devtools/server/actors/framerate.js index 1726f5ce453..fe69a894c2c 100644 --- a/toolkit/devtools/server/actors/framerate.js +++ b/toolkit/devtools/server/actors/framerate.js @@ -20,10 +20,13 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({ initialize: function(conn, tabActor) { protocol.Actor.prototype.initialize.call(this, conn); this.tabActor = tabActor; - this._chromeWin = getChromeWin(tabActor.window); + this._contentWin = tabActor.window; this._onRefreshDriverTick = this._onRefreshDriverTick.bind(this); + this._onGlobalCreated = this._onGlobalCreated.bind(this); + on(this.tabActor, "window-ready", this._onGlobalCreated); }, destroy: function(conn) { + off(this.tabActor, "window-ready", this._onGlobalCreated); protocol.Actor.prototype.destroy.call(this, conn); this.stopRecording(); }, @@ -38,8 +41,8 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({ this._recording = true; this._ticks = []; - this._startTime = this._chromeWin.performance.now(); - this._rafID = this._chromeWin.requestAnimationFrame(this._onRefreshDriverTick); + this._startTime = this._contentWin.performance.now(); + this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick); }, { }), @@ -65,7 +68,7 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({ * Stops monitoring framerate, without returning the recorded values. */ cancelRecording: method(function() { - this._chromeWin.cancelAnimationFrame(this._rafID); + this._contentWin.cancelAnimationFrame(this._rafID); this._recording = false; this._ticks = null; this._rafID = -1; @@ -104,12 +107,27 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({ if (!this._recording) { return; } - this._rafID = this._chromeWin.requestAnimationFrame(this._onRefreshDriverTick); + this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick); // Store the amount of time passed since the recording started. - let currentTime = this._chromeWin.performance.now(); - let elapsedTime = currentTime - this._startTime; - this._ticks.push(elapsedTime); + let currentTime = this._contentWin.performance.now(); + + // Store _elapsedTime so we can use this as a new starting time on a page refresh + // to normalize times. + this._elapsedTime = currentTime - this._startTime; + this._ticks.push(this._elapsedTime); + }, + + /** + * When the content window for the tab actor is created. + */ + _onGlobalCreated: function (win) { + if (this._recording) { + // Set _startTime to the currently elapsed time so we can get a wholistic + // elapsed time in _onRefreshDriverTick. + this._startTime = -this._elapsedTime; + this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick); + } } }); @@ -171,18 +189,3 @@ FramerateFront.plotFPS = function(ticks, interval = 100, clamp = 60) { return timeline; }; - -/** - * Gets the top level browser window from a content window. - * - * @param nsIDOMWindow innerWin - * The content window to query. - * @return nsIDOMWindow - * The top level browser window. - */ -function getChromeWin(innerWin) { - return innerWin - .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem - .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow); -}