summaryrefslogtreecommitdiffstats
path: root/devtools/client/performance/panel.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/performance/panel.js')
-rw-r--r--devtools/client/performance/panel.js162
1 files changed, 162 insertions, 0 deletions
diff --git a/devtools/client/performance/panel.js b/devtools/client/performance/panel.js
new file mode 100644
index 0000000000..28fef793f0
--- /dev/null
+++ b/devtools/client/performance/panel.js
@@ -0,0 +1,162 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
+
+function PerformancePanel(iframeWindow, toolbox) {
+ this.panelWin = iframeWindow;
+ this.toolbox = toolbox;
+ this._targetAvailablePromise = Promise.resolve();
+
+ this._onTargetAvailable = this._onTargetAvailable.bind(this);
+
+ EventEmitter.decorate(this);
+}
+
+exports.PerformancePanel = PerformancePanel;
+
+PerformancePanel.prototype = {
+ /**
+ * Open is effectively an asynchronous constructor.
+ *
+ * @return object
+ * A promise that is resolved when the Performance tool
+ * completes opening.
+ */
+ async open() {
+ if (this._opening) {
+ return this._opening;
+ }
+
+ this._checkRecordingStatus = this._checkRecordingStatus.bind(this);
+
+ const { PerformanceController, EVENTS } = this.panelWin;
+ PerformanceController.on(
+ EVENTS.RECORDING_ADDED,
+ this._checkRecordingStatus
+ );
+ PerformanceController.on(
+ EVENTS.RECORDING_STATE_CHANGE,
+ this._checkRecordingStatus
+ );
+
+ // In case that the target is switched across process, the corresponding front also
+ // will be changed. In order to detect that, watch the change.
+ // Also, we wait for `watchTargets` to end. Indeed the function `_onTargetAvailable
+ // will be called synchronously with current target as a parameter by
+ // the `watchTargets` function.
+ // So this `await` waits for initialization with current target, happening
+ // in `_onTargetAvailable`.
+ await this.toolbox.targetList.watchTargets(
+ [this.toolbox.targetList.TYPES.FRAME],
+ this._onTargetAvailable
+ );
+
+ // Fire this once incase we have an in-progress recording (console profile)
+ // that caused this start up, and no state change yet, so we can highlight the
+ // tab if we need.
+ this._checkRecordingStatus();
+
+ this.isReady = true;
+ this.emit("ready");
+
+ this._opening = new Promise(resolve => {
+ resolve(this);
+ });
+ return this._opening;
+ },
+
+ // DevToolPanel API
+
+ get target() {
+ return this.toolbox.target;
+ },
+
+ async destroy() {
+ // Make sure this panel is not already destroyed.
+ if (this._destroyed) {
+ return;
+ }
+
+ const { PerformanceController, PerformanceView, EVENTS } = this.panelWin;
+ PerformanceController.off(
+ EVENTS.RECORDING_ADDED,
+ this._checkRecordingStatus
+ );
+ PerformanceController.off(
+ EVENTS.RECORDING_STATE_CHANGE,
+ this._checkRecordingStatus
+ );
+
+ this.toolbox.targetList.unwatchTargets(
+ [this.toolbox.targetList.TYPES.FRAME],
+ this._onTargetAvailable
+ );
+ await PerformanceController.destroy();
+ await PerformanceView.destroy();
+ PerformanceController.disableFrontEventListeners();
+
+ this.emit("destroyed");
+ this._destroyed = true;
+ },
+
+ _checkRecordingStatus: function() {
+ if (this.panelWin.PerformanceController.isRecording()) {
+ this.toolbox.highlightTool("performance");
+ } else {
+ this.toolbox.unhighlightTool("performance");
+ }
+ },
+
+ /**
+ * This function executes actual logic for the target-switching.
+ *
+ * @param {TargetFront} - targetFront
+ * As we are watching only FRAME type for this panel,
+ * the target should be a instance of BrowsingContextTarget.
+ */
+ async _handleTargetAvailable({ targetFront }) {
+ if (targetFront.isTopLevel) {
+ const { PerformanceController, PerformanceView } = this.panelWin;
+ const performanceFront = await targetFront.getFront("performance");
+
+ if (!this._isPanelInitialized) {
+ await PerformanceController.initialize(
+ this.toolbox,
+ targetFront,
+ performanceFront
+ );
+ await PerformanceView.initialize();
+ PerformanceController.enableFrontEventListeners();
+ this._isPanelInitialized = true;
+ } else {
+ const isRecording = PerformanceController.isRecording();
+ if (isRecording) {
+ await PerformanceController.stopRecording();
+ }
+
+ PerformanceView.resetBufferStatus();
+ PerformanceController.updateFronts(targetFront, performanceFront);
+
+ if (isRecording) {
+ await PerformanceController.startRecording();
+ }
+ }
+ }
+ },
+
+ /**
+ * This function is called for every target is available.
+ */
+ _onTargetAvailable(parameters) {
+ // As this function is called asynchronous, while previous processing, this might be
+ // called. Thus, we wait until finishing previous one before starting next.
+ this._targetAvailablePromise = this._targetAvailablePromise.then(() =>
+ this._handleTargetAvailable(parameters)
+ );
+
+ return this._targetAvailablePromise;
+ },
+};