summaryrefslogtreecommitdiffstats
path: root/devtools/client/netmonitor/src/components/request-list/RequestListColumnWaterfall.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /devtools/client/netmonitor/src/components/request-list/RequestListColumnWaterfall.js
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/client/netmonitor/src/components/request-list/RequestListColumnWaterfall.js')
-rw-r--r--devtools/client/netmonitor/src/components/request-list/RequestListColumnWaterfall.js209
1 files changed, 209 insertions, 0 deletions
diff --git a/devtools/client/netmonitor/src/components/request-list/RequestListColumnWaterfall.js b/devtools/client/netmonitor/src/components/request-list/RequestListColumnWaterfall.js
new file mode 100644
index 0000000000..19523399b6
--- /dev/null
+++ b/devtools/client/netmonitor/src/components/request-list/RequestListColumnWaterfall.js
@@ -0,0 +1,209 @@
+/* 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 {
+ Component,
+} = 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 {
+ connect,
+} = require("resource://devtools/client/shared/redux/visibility-handler-connect.js");
+const {
+ getWaterfallScale,
+} = require("resource://devtools/client/netmonitor/src/selectors/index.js");
+
+const {
+ L10N,
+} = require("resource://devtools/client/netmonitor/src/utils/l10n.js");
+const {
+ fetchNetworkUpdatePacket,
+ propertiesEqual,
+} = require("resource://devtools/client/netmonitor/src/utils/request-utils.js");
+
+// List of properties of the timing info we want to create boxes for
+const {
+ TIMING_KEYS,
+} = require("resource://devtools/client/netmonitor/src/constants.js");
+
+const { div } = dom;
+
+const UPDATED_WATERFALL_ITEM_PROPS = ["eventTimings", "totalTime"];
+const UPDATED_WATERFALL_PROPS = [
+ "item",
+ "firstRequestStartedMs",
+ "scale",
+ "isVisible",
+];
+
+class RequestListColumnWaterfall extends Component {
+ static get propTypes() {
+ return {
+ connector: PropTypes.object.isRequired,
+ firstRequestStartedMs: PropTypes.number.isRequired,
+ item: PropTypes.object.isRequired,
+ onWaterfallMouseDown: PropTypes.func.isRequired,
+ scale: PropTypes.number,
+ isVisible: PropTypes.bool.isRequired,
+ };
+ }
+
+ constructor() {
+ super();
+ this.handleMouseOver = this.handleMouseOver.bind(this);
+ }
+
+ componentDidMount() {
+ const { connector, item } = this.props;
+ fetchNetworkUpdatePacket(connector.requestData, item, ["eventTimings"]);
+ }
+
+ // FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=1774507
+ UNSAFE_componentWillReceiveProps(nextProps) {
+ if (nextProps.isVisible && nextProps.item.totalTime) {
+ const { connector, item } = nextProps;
+ fetchNetworkUpdatePacket(connector.requestData, item, ["eventTimings"]);
+ }
+ }
+
+ shouldComponentUpdate(nextProps) {
+ return (
+ nextProps.isVisible &&
+ (!propertiesEqual(UPDATED_WATERFALL_PROPS, this.props, nextProps) ||
+ !propertiesEqual(
+ UPDATED_WATERFALL_ITEM_PROPS,
+ this.props.item,
+ nextProps.item
+ ))
+ );
+ }
+
+ handleMouseOver({ target }) {
+ if (!target.title) {
+ target.title = this.timingTooltip();
+ }
+ }
+
+ timingTooltip() {
+ const { eventTimings, totalTime } = this.props.item;
+ const tooltip = [];
+
+ if (eventTimings) {
+ for (const key of TIMING_KEYS) {
+ const width = eventTimings.timings[key];
+
+ if (width > 0) {
+ tooltip.push(
+ L10N.getFormatStr("netmonitor.waterfall.tooltip." + key, width)
+ );
+ }
+ }
+ }
+
+ if (typeof totalTime === "number") {
+ tooltip.push(
+ L10N.getFormatStr("netmonitor.waterfall.tooltip.total", totalTime)
+ );
+ }
+
+ return tooltip.join(L10N.getStr("netmonitor.waterfall.tooltip.separator"));
+ }
+
+ timingBoxes() {
+ const {
+ scale,
+ item: { eventTimings, totalTime },
+ } = this.props;
+ const boxes = [];
+
+ // Physical pixel as minimum size
+ const minPixel = 1 / window.devicePixelRatio;
+
+ if (typeof totalTime === "number") {
+ if (eventTimings) {
+ // Add a set of boxes representing timing information.
+ for (const key of TIMING_KEYS) {
+ if (eventTimings.timings[key] > 0) {
+ boxes.push(
+ div({
+ key,
+ className: `requests-list-timings-box ${key}`,
+ style: {
+ width: Math.max(eventTimings.timings[key] * scale, minPixel),
+ },
+ })
+ );
+ }
+ }
+ }
+ // Minimal box to at least show start and total time
+ if (!boxes.length) {
+ boxes.push(
+ div({
+ className: "requests-list-timings-box filler",
+ key: "filler",
+ style: { width: Math.max(totalTime * scale, minPixel) },
+ })
+ );
+ }
+
+ const title = L10N.getFormatStr("networkMenu.totalMS2", totalTime);
+ boxes.push(
+ div(
+ {
+ key: "total",
+ className: "requests-list-timings-total",
+ title,
+ },
+ title
+ )
+ );
+ } else {
+ // Pending requests are marked for start time
+ boxes.push(
+ div({
+ className: "requests-list-timings-box filler",
+ key: "pending",
+ style: { width: minPixel },
+ })
+ );
+ }
+
+ return boxes;
+ }
+
+ render() {
+ const {
+ firstRequestStartedMs,
+ item: { startedMs },
+ scale,
+ onWaterfallMouseDown,
+ } = this.props;
+
+ return dom.td(
+ {
+ className: "requests-list-column requests-list-waterfall",
+ onMouseOver: this.handeMouseOver,
+ },
+ div(
+ {
+ className: "requests-list-timings",
+ style: {
+ paddingInlineStart: `${
+ (startedMs - firstRequestStartedMs) * scale
+ }px`,
+ },
+ onMouseDown: onWaterfallMouseDown,
+ },
+ this.timingBoxes()
+ )
+ );
+ }
+}
+
+module.exports = connect(state => ({
+ scale: getWaterfallScale(state),
+}))(RequestListColumnWaterfall);