Bug 1130204 - Hide views in the performance tool if they are not supported by the server actor. r=vp

This commit is contained in:
Jordan Santell 2015-02-14 10:51:00 +01:00
parent c6e14ec3ed
commit 2238c2c116
6 changed files with 110 additions and 23 deletions

View File

@ -40,7 +40,7 @@ support-files =
[browser_perf-jump-to-debugger-01.js]
[browser_perf-jump-to-debugger-02.js]
[browser_perf-options-01.js]
[browser_perf-options-02.js]
# [browser_perf-options-02.js] bug 1133230
[browser_perf-options-invert-call-tree-01.js]
[browser_perf-options-invert-call-tree-02.js]
[browser_perf-options-invert-flame-graph-01.js]

View File

@ -3,7 +3,7 @@
/**
* Tests that the recording model is populated correctly when using timeline
* and memory actor mocks.
* and memory actor mocks, and the correct views are shown.
*/
const WAIT_TIME = 1000;
@ -14,15 +14,15 @@ let test = Task.async(function*() {
TEST_MOCK_TIMELINE_ACTOR: true
});
Services.prefs.setBoolPref(MEMORY_PREF, true);
let { EVENTS, gFront, PerformanceController, PerformanceView } = panel.panelWin;
let { EVENTS, $, gFront, PerformanceController, PerformanceView, DetailsView, JsCallTreeView } = panel.panelWin;
let { memory: memoryMock, timeline: timelineMock } = gFront.getMocksInUse();
ok(memoryMock, "memory should be mocked.");
ok(timelineMock, "timeline should be mocked.");
yield startRecording(panel);
yield startRecording(panel, { waitForOverview: false });
busyWait(WAIT_TIME); // allow the profiler module to sample some cpu activity
yield stopRecording(panel);
yield stopRecording(panel, { waitForOverview: false });
let {
label, duration, markers, frames, memory, ticks, allocations, profile
@ -58,6 +58,23 @@ let test = Task.async(function*() {
ok(sampleCount > 0,
"At least some samples have been iterated over, checking for root nodes.");
is($("#overview-pane").hidden, true,
"overview pane hidden when timeline mocked.");
is($("#select-waterfall-view").hidden, true,
"waterfall view button hidden when timeline mocked");
is($("#select-js-calltree-view").hidden, false,
"jscalltree view button not hidden when timeline/memory mocked");
is($("#select-js-flamegraph-view").hidden, true,
"jsflamegraph view button hidden when timeline mocked");
is($("#select-memory-calltree-view").hidden, true,
"memorycalltree view button hidden when memory mocked");
is($("#select-memory-flamegraph-view").hidden, true,
"memoryflamegraph view button hidden when memory mocked");
ok(DetailsView.isViewSelected(JsCallTreeView),
"JS Call Tree view selected by default when timeline/memory mocked.");
yield teardown(panel);
finish();
});

View File

@ -3,7 +3,7 @@
/**
* Tests that the recording model is populated correctly when using timeline
* and memory actor mocks.
* and memory actor mocks, and that the correct button/overview displays are shown.
*/
const WAIT_TIME = 1000;
@ -13,7 +13,7 @@ let test = Task.async(function*() {
TEST_MOCK_MEMORY_ACTOR: true
});
Services.prefs.setBoolPref(MEMORY_PREF, true);
let { EVENTS, gFront, PerformanceController, PerformanceView } = panel.panelWin;
let { EVENTS, $, gFront, PerformanceController, PerformanceView, DetailsView, WaterfallView } = panel.panelWin;
let { memory: memoryMock, timeline: timelineMock } = gFront.getMocksInUse();
@ -57,6 +57,23 @@ let test = Task.async(function*() {
ok(sampleCount > 0,
"At least some samples have been iterated over, checking for root nodes.");
is($("#overview-pane").hidden, false,
"overview pane not hidden when only memory mocked.");
is($("#select-waterfall-view").hidden, false,
"waterfall view button not hidden when memory mocked");
is($("#select-js-calltree-view").hidden, false,
"jscalltree view button not hidden when memory mocked");
is($("#select-js-flamegraph-view").hidden, false,
"jsflamegraph view button not hidden when memory mocked");
is($("#select-memory-calltree-view").hidden, true,
"memorycalltree view button hidden when memory mocked");
is($("#select-memory-flamegraph-view").hidden, true,
"memoryflamegraph view button hidden when memory mocked");
ok(DetailsView.isViewSelected(WaterfallView),
"Waterfall view selected by default when memory mocked.");
yield teardown(panel);
finish();
});

View File

@ -266,7 +266,7 @@ function mousedown (win, button) {
EventUtils.sendMouseEvent({ type: "mousedown" }, button, win);
}
function* startRecording(panel) {
function* startRecording(panel, options={}) {
let win = panel.panelWin;
let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_START_RECORDING);
let willStart = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_WILL_START);
@ -290,7 +290,7 @@ function* startRecording(panel) {
let stateChanged = once(win.PerformanceView, win.EVENTS.UI_STATE_CHANGED);
yield hasStarted;
let overviewRendered = once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED);
let overviewRendered = options.waitForOverview ? once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED) : Promise.resolve();
yield stateChanged;
yield overviewRendered;
@ -304,7 +304,7 @@ function* startRecording(panel) {
"The record button should not be locked.");
}
function* stopRecording(panel) {
function* stopRecording(panel, options={}) {
let win = panel.panelWin;
let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_STOP_RECORDING);
let willStop = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_WILL_STOP);
@ -328,7 +328,7 @@ function* stopRecording(panel) {
let stateChanged = once(win.PerformanceView, win.EVENTS.UI_STATE_CHANGED);
yield hasStopped;
let overviewRendered = once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED);
let overviewRendered = options.waitForOverview ? once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED) : Promise.resolve();
yield stateChanged;
yield overviewRendered;

View File

@ -3,8 +3,6 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const DEFAULT_DETAILS_SUBVIEW = "waterfall";
/**
* Details view containing profiler call tree and markers waterfall. Manages
* subviews and toggles visibility between them.
@ -14,11 +12,11 @@ let DetailsView = {
* Name to node+object mapping of subviews.
*/
components: {
"waterfall": { id: "waterfall-view", view: WaterfallView },
"waterfall": { id: "waterfall-view", view: WaterfallView, requires: ["timeline"] },
"js-calltree": { id: "js-calltree-view", view: JsCallTreeView },
"js-flamegraph": { id: "js-flamegraph-view", view: JsFlameGraphView },
"memory-calltree": { id: "memory-calltree-view", view: MemoryCallTreeView, pref: "enable-memory" },
"memory-flamegraph": { id: "memory-flamegraph-view", view: MemoryFlameGraphView, pref: "enable-memory" }
"js-flamegraph": { id: "js-flamegraph-view", view: JsFlameGraphView, requires: ["timeline"] },
"memory-calltree": { id: "memory-calltree-view", view: MemoryCallTreeView, requires: ["memory"], pref: "enable-memory" },
"memory-flamegraph": { id: "memory-flamegraph-view", view: MemoryFlameGraphView, requires: ["memory", "timeline"], pref: "enable-memory" }
},
/**
@ -36,7 +34,7 @@ let DetailsView = {
button.addEventListener("command", this._onViewToggle);
}
yield this.selectView(DEFAULT_DETAILS_SUBVIEW);
yield this.selectDefaultView();
yield this.setAvailableViews();
PerformanceController.on(EVENTS.RECORDING_STOPPED, this._onRecordingStoppedOrSelected);
@ -62,22 +60,27 @@ let DetailsView = {
}),
/**
* Sets the possible views based off of prefs by hiding/showing the
* Sets the possible views based off of prefs and server actor support by hiding/showing the
* buttons that select them and going to default view if currently selected.
* Called when a preference changes in `devtools.performance.ui.`.
*/
setAvailableViews: Task.async(function* () {
for (let [name, { view, pref }] of Iterator(this.components)) {
let mocks = gFront.getMocksInUse();
for (let [name, { view, pref, requires }] of Iterator(this.components)) {
let recording = PerformanceController.getCurrentRecording();
let isRecorded = recording && !recording.isRecording();
// View is enabled view prefs
let isEnabled = !pref || PerformanceController.getPref(pref);
$(`toolbarbutton[data-view=${name}]`).hidden = !isRecorded || !isEnabled;
// View is supported by the server actor, and the requried actor is not being mocked
let isSupported = !requires || requires.every(r => !mocks[r]);
$(`toolbarbutton[data-view=${name}]`).hidden = !isRecorded || !(isEnabled && isSupported);
// If the view is currently selected and not enabled, go back to the
// default view.
if (!isEnabled && this.isViewSelected(view)) {
yield this.selectView(DEFAULT_DETAILS_SUBVIEW);
yield this.selectDefaultView();
}
}
}),
@ -106,6 +109,22 @@ let DetailsView = {
this.emit(EVENTS.DETAILS_VIEW_SELECTED, viewName);
}),
/**
* Selects a default view based off of protocol support
* and preferences enabled.
*/
selectDefaultView: function () {
let { timeline: mockTimeline } = gFront.getMocksInUse();
// If timelines are mocked, the first view available is the js-calltree.
if (mockTimeline) {
return this.selectView("js-calltree");
} else {
// In every other scenario with preferences and mocks, waterfall will
// be the default view.
return this.selectView("waterfall");
}
},
/**
* Checks if the provided view is currently selected.
*

View File

@ -26,6 +26,9 @@ let OverviewView = {
* Sets up the view with event binding.
*/
initialize: function () {
if (gFront.getMocksInUse().timeline) {
this.disable();
}
this._onRecordingWillStart = this._onRecordingWillStart.bind(this);
this._onRecordingStarted = this._onRecordingStarted.bind(this);
this._onRecordingWillStop = this._onRecordingWillStop.bind(this);
@ -60,6 +63,25 @@ let OverviewView = {
PerformanceController.off(EVENTS.RECORDING_SELECTED, this._onRecordingSelected);
},
/**
* Disabled in the event we're using a Timeline mock, so we'll have no
* markers, ticks or memory data to show, so just block rendering and hide
* the panel.
*/
disable: function () {
this._disabled = true;
$("#overview-pane").hidden = true;
},
/**
* Returns the disabled status.
*
* @return boolean
*/
isDisabled: function () {
return this._disabled;
},
/**
* Sets the time interval selection for all graphs in this overview.
*
@ -67,6 +89,10 @@ let OverviewView = {
* The { starTime, endTime }, in milliseconds.
*/
setTimeInterval: function(interval, options = {}) {
if (this.isDisabled()) {
return;
}
let recording = PerformanceController.getCurrentRecording();
if (recording == null) {
throw new Error("A recording should be available in order to set the selection.");
@ -83,10 +109,15 @@ let OverviewView = {
* Gets the time interval selection for all graphs in this overview.
*
* @return object
* The { starTime, endTime }, in milliseconds.
* The { startTime, endTime }, in milliseconds.
*/
getTimeInterval: function() {
let recording = PerformanceController.getCurrentRecording();
if (this.isDisabled()) {
return { startTime: 0, endTime: recording.getDuration() };
}
if (recording == null) {
throw new Error("A recording should be available in order to get the selection.");
}
@ -172,6 +203,9 @@ let OverviewView = {
* The fps graph resolution. @see Graphs.jsm
*/
render: Task.async(function *(resolution) {
if (this.isDisabled()) {
return;
}
let recording = PerformanceController.getCurrentRecording();
let duration = recording.getDuration();
let markers = recording.getMarkers();