Source code

Revision control

Copy as Markdown

Other Tools

/* 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";
const {
connect,
} = require("resource://devtools/client/shared/vendor/react-redux.js");
const {
createFactory,
PureComponent,
} = require("resource://devtools/client/shared/vendor/react.js");
const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js");
const FluentReact = require("resource://devtools/client/shared/vendor/fluent-react.js");
const Localized = createFactory(FluentReact.Localized);
const Actions = require("resource://devtools/client/aboutdebugging/src/actions/index.js");
const Types = require("resource://devtools/client/aboutdebugging/src/types/index.js");
const {
PROFILER_PAGE_CONTEXT,
} = require("resource://devtools/client/aboutdebugging/src/constants.js");
/**
* This component is a modal dialog containing the performance profiler UI. It uses
* the simplified DevTools panel located in devtools/client/performance-new. When
* using a custom preset, and editing the settings, the page context switches
* to about:profiling, which receives the PerfFront of the remote debuggee.
*/
class ProfilerDialog extends PureComponent {
static get propTypes() {
return {
runtimeDetails: Types.runtimeDetails.isRequired,
profilerContext: PropTypes.string.isRequired,
hideProfilerDialog: PropTypes.func.isRequired,
switchProfilerContext: PropTypes.func.isRequired,
};
}
hide() {
this.props.hideProfilerDialog();
}
setProfilerIframeDirection(frameWindow) {
// Set iframe direction according to the parent document direction.
const { documentElement } = document;
const dir = window.getComputedStyle(documentElement).direction;
frameWindow.document.documentElement.setAttribute("dir", dir);
}
/**
* The profiler iframe can either be the simplified devtools recording panel,
* or the more detailed about:profiling settings page.
*/
renderProfilerIframe() {
const {
runtimeDetails: { clientWrapper },
switchProfilerContext,
profilerContext,
} = this.props;
let src, onLoad;
switch (profilerContext) {
case PROFILER_PAGE_CONTEXT.DEVTOOLS_REMOTE:
src = clientWrapper.getPerformancePanelUrl();
onLoad = e => {
const frameWindow = e.target.contentWindow;
this.setProfilerIframeDirection(frameWindow);
clientWrapper.loadPerformanceProfiler(frameWindow, () => {
switchProfilerContext(PROFILER_PAGE_CONTEXT.ABOUTPROFILING_REMOTE);
});
};
break;
case PROFILER_PAGE_CONTEXT.ABOUTPROFILING_REMOTE:
src = "about:profiling#remote";
onLoad = e => {
const frameWindow = e.target.contentWindow;
this.setProfilerIframeDirection(frameWindow);
clientWrapper.loadAboutProfiling(frameWindow, () => {
switchProfilerContext(PROFILER_PAGE_CONTEXT.DEVTOOLS_REMOTE);
});
};
break;
default:
throw new Error(`Unhandled profiler context: "${profilerContext}"`);
}
return dom.iframe({
key: profilerContext,
className: "profiler-dialog__frame",
src,
onLoad,
});
}
render() {
const { profilerContext, switchProfilerContext } = this.props;
const dialogSizeClassName =
profilerContext === PROFILER_PAGE_CONTEXT.DEVTOOLS_REMOTE
? "profiler-dialog__inner--medium"
: "profiler-dialog__inner--large";
return dom.div(
{
className: "profiler-dialog__mask qa-profiler-dialog-mask",
onClick: () => this.hide(),
},
dom.article(
{
className: `profiler-dialog__inner ${dialogSizeClassName} qa-profiler-dialog`,
onClick: e => e.stopPropagation(),
},
dom.header(
{
className: "profiler-dialog__header",
},
Localized(
{
id: "about-debugging-profiler-dialog-title2",
},
dom.h1(
{
className: "profiler-dialog__header__title",
},
"about-debugging-profiler-dialog-title2"
)
),
dom.button(
{
className: "ghost-button qa-profiler-dialog-close",
onClick: () => {
if (profilerContext === PROFILER_PAGE_CONTEXT.DEVTOOLS_REMOTE) {
this.hide();
} else {
switchProfilerContext(PROFILER_PAGE_CONTEXT.DEVTOOLS_REMOTE);
}
},
},
dom.img({
src: "chrome://devtools/skin/images/close.svg",
})
)
),
this.renderProfilerIframe()
)
);
}
}
const mapStateToProps = state => {
return {
profilerContext: state.ui.profilerContext,
};
};
const mapDispatchToProps = {
hideProfilerDialog: Actions.hideProfilerDialog,
switchProfilerContext: Actions.switchProfilerContext,
};
module.exports = connect(mapStateToProps, mapDispatchToProps)(ProfilerDialog);