зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1559398 - Implement table and preview sections in WebSocket side panel. r=Honza
Implement table and preview sections in WebSocket side panel. Differential Revision: https://phabricator.services.mozilla.com/D35983 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
fb05c2c381
Коммит
44c6145f6e
|
@ -637,6 +637,34 @@ netmonitor.toolbar.contentSize=Size
|
|||
# in the network table toolbar, above the "waterfall" column.
|
||||
netmonitor.toolbar.waterfall=Timeline
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.ws.toolbar.frameType): This is the label displayed
|
||||
# in the websocket frame table header, above the "type" column.
|
||||
netmonitor.ws.toolbar.frameType=Type
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.ws.toolbar.size): This is the label displayed
|
||||
# in the websocket frame table header, above the "size" column.
|
||||
netmonitor.ws.toolbar.size=Size
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.ws.toolbar.payload): This is the label displayed
|
||||
# in the websocket frame table header, above the "payload" column.
|
||||
netmonitor.ws.toolbar.payload=Payload
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.ws.toolbar.opCode): This is the label displayed
|
||||
# in the websocket frame table header, above the "opCode" column.
|
||||
netmonitor.ws.toolbar.opCode=OpCode
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.ws.toolbar.maskBit): This is the label displayed
|
||||
# in the websocket frame table header, above the "maskBit" column.
|
||||
netmonitor.ws.toolbar.maskBit=MaskBit
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.ws.toolbar.finBit): This is the label displayed
|
||||
# in the websocket frame table header, above the "finBit" column.
|
||||
netmonitor.ws.toolbar.finBit=FinBit
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.ws.toolbar.time): This is the label displayed
|
||||
# in the websocket frame table header, above the "time" column.
|
||||
netmonitor.ws.toolbar.time=Time
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.tab.headers): This is the label displayed
|
||||
# in the network details pane identifying the headers tab.
|
||||
netmonitor.tab.headers=Headers
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { WS_ADD_FRAME } = require("../constants");
|
||||
const {
|
||||
WS_ADD_FRAME,
|
||||
WS_SELECT_FRAME,
|
||||
WS_OPEN_FRAME_DETAILS,
|
||||
} = require("../constants");
|
||||
|
||||
function addFrame(httpChannelId, data) {
|
||||
return {
|
||||
|
@ -14,6 +18,31 @@ function addFrame(httpChannelId, data) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Select frame.
|
||||
*/
|
||||
function selectFrame(frame) {
|
||||
return {
|
||||
type: WS_SELECT_FRAME,
|
||||
open: true,
|
||||
frame,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Open frame details panel.
|
||||
*
|
||||
* @param {boolean} open - expected frame details panel open state
|
||||
*/
|
||||
function openFrameDetails(open) {
|
||||
return {
|
||||
type: WS_OPEN_FRAME_DETAILS,
|
||||
open,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addFrame,
|
||||
selectFrame,
|
||||
openFrameDetails,
|
||||
};
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.ws-frame-list-empty-notice {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.empty-notice-element {
|
||||
padding-top: 12px;
|
||||
padding-left: 12px;
|
||||
|
@ -56,7 +60,8 @@
|
|||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.requests-list-table {
|
||||
.requests-list-table,
|
||||
.ws-frames-list-table {
|
||||
/* Reset default browser style of <table> */
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
|
@ -66,7 +71,8 @@
|
|||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.requests-list-column {
|
||||
.requests-list-column,
|
||||
.ws-frames-list-column {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
@ -82,7 +88,8 @@
|
|||
|
||||
/* Requests list headers */
|
||||
|
||||
.requests-list-headers-group {
|
||||
.requests-list-headers-group,
|
||||
.ws-frames-list-headers-group {
|
||||
/* Avoid .devtools-toolbar to override <thead> display type */
|
||||
display: table-header-group;
|
||||
|
||||
|
@ -93,16 +100,19 @@
|
|||
z-index: 1;
|
||||
}
|
||||
|
||||
.requests-list-headers {
|
||||
.requests-list-headers,
|
||||
.ws-frames-list-headers {
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.requests-list-headers .requests-list-column:first-child .requests-list-header-button {
|
||||
.requests-list-headers .requests-list-column:first-child .requests-list-header-button,
|
||||
.ws-frames-list-headers .ws-frames-list-column:first-child .ws-frames-list-header-button {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.requests-list-header-button {
|
||||
.requests-list-header-button,
|
||||
.ws-frames-list-header-button {
|
||||
background-color: transparent;
|
||||
border-image: linear-gradient(transparent 15%,
|
||||
var(--theme-splitter-color) 15%,
|
||||
|
@ -126,7 +136,8 @@
|
|||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.requests-list-header-button > .button-text {
|
||||
.requests-list-header-button > .button-text,
|
||||
.ws-frames-list-header-button > .button-text {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 100%;
|
||||
|
@ -134,7 +145,8 @@
|
|||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.requests-list-header-button > .button-icon {
|
||||
.requests-list-header-button > .button-icon,
|
||||
.ws-frames-list-header-button > .button-icon {
|
||||
/* display icon only when column sorted otherwise display:none */
|
||||
display: none;
|
||||
width: 7px;
|
||||
|
@ -309,7 +321,8 @@
|
|||
filter: brightness(500%);
|
||||
}
|
||||
|
||||
.request-list-item .requests-list-column {
|
||||
.request-list-item .requests-list-column,
|
||||
.ws-frame-list-item .ws-frames-list-column {
|
||||
padding-inline-start: 4px;
|
||||
}
|
||||
|
||||
|
@ -464,16 +477,19 @@
|
|||
|
||||
/* Request list item */
|
||||
|
||||
.request-list-item {
|
||||
.request-list-item,
|
||||
.ws-frame-list-item {
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.request-list-item:not(.selected).odd {
|
||||
.request-list-item:not(.selected).odd,
|
||||
.ws-frame-list-item:not(.selected).odd {
|
||||
background-color: var(--table-zebra-background);
|
||||
}
|
||||
|
||||
.request-list-item:not(.selected):hover {
|
||||
.request-list-item:not(.selected):hover,
|
||||
.ws-frame-list-item:not(.selected):hover {
|
||||
background-color: var(--table-selection-background-hover);
|
||||
}
|
||||
|
||||
|
@ -489,7 +505,8 @@
|
|||
* Put ahead of .request-list-item.blocked to avoid specificity conflict.
|
||||
* Bug 1530914 - Highlighted Security Value is difficult to read.
|
||||
*/
|
||||
.request-list-item.selected {
|
||||
.request-list-item.selected,
|
||||
.ws-frame-list-item.selected {
|
||||
background-color: var(--theme-selection-background);
|
||||
color: var(--theme-selection-color);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ const Tabbar = createFactory(require("devtools/client/shared/components/tabs/Tab
|
|||
const TabPanel = createFactory(require("devtools/client/shared/components/tabs/Tabs").TabPanel);
|
||||
const CookiesPanel = createFactory(require("./CookiesPanel"));
|
||||
const HeadersPanel = createFactory(require("./HeadersPanel"));
|
||||
const WebSocketsPanel = createFactory(require("./WebSocketsPanel"));
|
||||
const WebSocketsPanel = createFactory(require("./websockets/WebSocketsPanel"));
|
||||
const ParamsPanel = createFactory(require("./ParamsPanel"));
|
||||
const CachePanel = createFactory(require("./CachePanel"));
|
||||
const ResponsePanel = createFactory(require("./ResponsePanel"));
|
||||
|
@ -131,6 +131,7 @@ class TabboxPanel extends Component {
|
|||
},
|
||||
WebSocketsPanel({
|
||||
channelId,
|
||||
connector,
|
||||
}),
|
||||
),
|
||||
TabPanel({
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
/* 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("devtools/client/shared/vendor/react");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const {
|
||||
connect,
|
||||
} = require("devtools/client/shared/redux/visibility-handler-connect");
|
||||
const { getFramesByChannelId } = require("../selectors/index");
|
||||
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const { table, tbody, thead, tr, td, th, div } = dom;
|
||||
|
||||
const { L10N } = require("../utils/l10n");
|
||||
const FRAMES_EMPTY_TEXT = L10N.getStr("webSocketsEmptyText");
|
||||
|
||||
class WebSocketsPanel extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
channelId: PropTypes.number,
|
||||
frames: PropTypes.array,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { frames } = this.props;
|
||||
|
||||
if (!frames) {
|
||||
return div({ className: "empty-notice" },
|
||||
FRAMES_EMPTY_TEXT
|
||||
);
|
||||
}
|
||||
|
||||
const rows = [];
|
||||
frames.forEach((frame, index) => {
|
||||
rows.push(
|
||||
tr(
|
||||
{ key: index,
|
||||
className: "frames-row" },
|
||||
td({ className: "frames-cell" }, frame.type),
|
||||
td({ className: "frames-cell" }, frame.httpChannelId),
|
||||
td({ className: "frames-cell" }, frame.payload),
|
||||
td({ className: "frames-cell" }, frame.opCode),
|
||||
td({ className: "frames-cell" }, frame.maskBit.toString()),
|
||||
td({ className: "frames-cell" }, frame.finBit.toString()),
|
||||
td({ className: "frames-cell" }, frame.timeStamp)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return table(
|
||||
{ className: "frames-list-table" },
|
||||
thead(
|
||||
{ className: "frames-head" },
|
||||
tr(
|
||||
{ className: "frames-row" },
|
||||
th({ className: "frames-headerCell" }, "Type"),
|
||||
th({ className: "frames-headerCell" }, "Channel ID"),
|
||||
th({ className: "frames-headerCell" }, "Payload"),
|
||||
th({ className: "frames-headerCell" }, "OpCode"),
|
||||
th({ className: "frames-headerCell" }, "MaskBit"),
|
||||
th({ className: "frames-headerCell" }, "FinBit"),
|
||||
th({ className: "frames-headerCell" }, "Time")
|
||||
)
|
||||
),
|
||||
tbody(
|
||||
{
|
||||
className: "frames-list-tableBody",
|
||||
},
|
||||
rows
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = connect((state, props) => ({
|
||||
frames: getFramesByChannelId(state, props.channelId),
|
||||
}))(WebSocketsPanel);
|
|
@ -2,6 +2,10 @@
|
|||
# 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/.
|
||||
|
||||
DIRS += [
|
||||
'websockets',
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'App.js',
|
||||
'CachePanel.js',
|
||||
|
@ -47,5 +51,4 @@ DevToolsModules(
|
|||
'TabboxPanel.js',
|
||||
'TimingsPanel.js',
|
||||
'Toolbar.js',
|
||||
'WebSocketsPanel.js',
|
||||
)
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/* 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("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
/**
|
||||
* Renders the "FinBit" column of a WebSocket frame.
|
||||
*/
|
||||
class FrameListColumnFinBit extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
item: PropTypes.object.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return this.props.item.finBit !== nextProps.item.finBit;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { finBit } = this.props.item;
|
||||
const { index } = this.props;
|
||||
|
||||
return dom.td(
|
||||
{
|
||||
key: index,
|
||||
className: "ws-frames-list-column ws-frames-list-finBit",
|
||||
title: finBit.toString(),
|
||||
},
|
||||
finBit.toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FrameListColumnFinBit;
|
|
@ -0,0 +1,41 @@
|
|||
/* 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("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
/**
|
||||
* Renders the "MaskBit" column of a WebSocket frame.
|
||||
*/
|
||||
class FrameListColumnMaskBit extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
item: PropTypes.object.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return this.props.item.maskBit !== nextProps.item.maskBit;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { maskBit } = this.props.item;
|
||||
const { index } = this.props;
|
||||
|
||||
return dom.td(
|
||||
{
|
||||
key: index,
|
||||
className: "ws-frames-list-column ws-frames-list-maskBit",
|
||||
title: maskBit.toString(),
|
||||
},
|
||||
maskBit.toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FrameListColumnMaskBit;
|
|
@ -0,0 +1,41 @@
|
|||
/* 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("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
/**
|
||||
* Renders the "OpCode" column of a WebSocket frame.
|
||||
*/
|
||||
class FrameListColumnOpCode extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
item: PropTypes.object.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return this.props.item.opCode !== nextProps.item.opCode;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { opCode } = this.props.item;
|
||||
const { index } = this.props;
|
||||
|
||||
return dom.td(
|
||||
{
|
||||
key: index,
|
||||
className: "ws-frames-list-column ws-frames-list-opCode",
|
||||
title: opCode,
|
||||
},
|
||||
opCode
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FrameListColumnOpCode;
|
|
@ -0,0 +1,64 @@
|
|||
/* 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("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const { getFramePayload } = require("../../utils/request-utils");
|
||||
|
||||
/**
|
||||
* Renders the "Payload" column of a WebSocket frame.
|
||||
*/
|
||||
class FrameListColumnPayload extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
item: PropTypes.object.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
connector: PropTypes.object.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
payload: "",
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { item, connector } = this.props;
|
||||
getFramePayload(item.payload, connector.getLongString).then(payload => {
|
||||
this.setState({
|
||||
payload,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { item, connector } = nextProps;
|
||||
getFramePayload(item.payload, connector.getLongString).then(payload => {
|
||||
this.setState({
|
||||
payload,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { index } = this.props;
|
||||
|
||||
return dom.td(
|
||||
{
|
||||
key: index,
|
||||
className: "ws-frames-list-column ws-frames-list-payload",
|
||||
title: this.state.payload,
|
||||
},
|
||||
this.state.payload
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FrameListColumnPayload;
|
|
@ -0,0 +1,42 @@
|
|||
/* 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("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const { getFormattedSize } = require("../../utils/format-utils");
|
||||
|
||||
/**
|
||||
* Renders the "Size" column of a WebSocket frame.
|
||||
*/
|
||||
class FrameListColumnSize extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
item: PropTypes.object.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return this.props.item.payload !== nextProps.item.payload;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { payload } = this.props.item;
|
||||
const { index } = this.props;
|
||||
|
||||
return dom.td(
|
||||
{
|
||||
key: index,
|
||||
className: "ws-frames-list-column ws-frames-list-size",
|
||||
title: getFormattedSize(payload.length),
|
||||
},
|
||||
getFormattedSize(payload.length)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FrameListColumnSize;
|
|
@ -0,0 +1,44 @@
|
|||
/* 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("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
/**
|
||||
* Renders the "Time" column of a WebSocket frame.
|
||||
*/
|
||||
class FrameListColumnTime extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
item: PropTypes.object.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return this.props.item.timeStamp !== nextProps.item.timeStamp;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { timeStamp } = this.props.item;
|
||||
const { index } = this.props;
|
||||
|
||||
// Convert microseconds (DOMHighResTimeStamp) to milliseconds
|
||||
const time = timeStamp / 1000;
|
||||
|
||||
return dom.td(
|
||||
{
|
||||
key: index,
|
||||
className: "ws-frames-list-column ws-frames-list-time",
|
||||
title: timeStamp,
|
||||
},
|
||||
new Date(time).toLocaleTimeString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FrameListColumnTime;
|
|
@ -0,0 +1,41 @@
|
|||
/* 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("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
/**
|
||||
* Renders the "Type" column of a WebSocket frame.
|
||||
*/
|
||||
class FrameListColumnType extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
item: PropTypes.object.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return this.props.item.type !== nextProps.item.type;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { type } = this.props.item;
|
||||
const { index } = this.props;
|
||||
|
||||
return dom.td(
|
||||
{
|
||||
key: index,
|
||||
className: "ws-frames-list-column ws-frames-list-type",
|
||||
title: type,
|
||||
},
|
||||
type
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FrameListColumnType;
|
|
@ -0,0 +1,99 @@
|
|||
/* 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,
|
||||
createFactory,
|
||||
} = require("devtools/client/shared/vendor/react");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const {
|
||||
connect,
|
||||
} = require("devtools/client/shared/redux/visibility-handler-connect");
|
||||
const { getFramesByChannelId } = require("../../selectors/index");
|
||||
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const { table, tbody, div } = dom;
|
||||
|
||||
const { L10N } = require("../../utils/l10n");
|
||||
const FRAMES_EMPTY_TEXT = L10N.getStr("webSocketsEmptyText");
|
||||
const Actions = require("../../actions/index");
|
||||
|
||||
const { getSelectedFrame } = require("../../selectors/index");
|
||||
|
||||
loader.lazyGetter(this, "FrameListHeader", function() {
|
||||
return createFactory(require("./FrameListHeader"));
|
||||
});
|
||||
loader.lazyGetter(this, "FrameListItem", function() {
|
||||
return createFactory(require("./FrameListItem"));
|
||||
});
|
||||
|
||||
const LEFT_MOUSE_BUTTON = 0;
|
||||
|
||||
/**
|
||||
* Renders the actual contents of the WebSocket frame list.
|
||||
*/
|
||||
class FrameListContent extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
channelId: PropTypes.number,
|
||||
connector: PropTypes.object.isRequired,
|
||||
frames: PropTypes.array,
|
||||
selectedFrame: PropTypes.object,
|
||||
selectFrame: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
onMouseDown(evt, item) {
|
||||
if (evt.button === LEFT_MOUSE_BUTTON) {
|
||||
this.props.selectFrame(item);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { frames, selectedFrame, connector } = this.props;
|
||||
|
||||
if (!frames) {
|
||||
return div(
|
||||
{ className: "empty-notice ws-frame-list-empty-notice" },
|
||||
FRAMES_EMPTY_TEXT
|
||||
);
|
||||
}
|
||||
|
||||
return table(
|
||||
{ className: "ws-frames-list-table" },
|
||||
FrameListHeader(),
|
||||
tbody(
|
||||
{
|
||||
className: "ws-frames-list-body",
|
||||
},
|
||||
frames.map((item, index) =>
|
||||
FrameListItem({
|
||||
key: "ws-frame-list-item-" + index,
|
||||
item,
|
||||
index,
|
||||
isSelected: item === selectedFrame,
|
||||
onMouseDown: evt => this.onMouseDown(evt, item),
|
||||
connector,
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = connect(
|
||||
(state, props) => ({
|
||||
selectedFrame: getSelectedFrame(state),
|
||||
frames: getFramesByChannelId(state, props.channelId),
|
||||
}),
|
||||
dispatch => ({
|
||||
selectFrame: item => dispatch(Actions.selectFrame(item)),
|
||||
})
|
||||
)(FrameListContent);
|
|
@ -0,0 +1,67 @@
|
|||
/* 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("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const { WS_FRAMES_HEADERS } = require("../../constants");
|
||||
const { L10N } = require("../../utils/l10n");
|
||||
|
||||
const { div, button } = dom;
|
||||
|
||||
/**
|
||||
* Renders the frame list header.
|
||||
*/
|
||||
class FrameListHeader extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render one column header from the table headers.
|
||||
*/
|
||||
renderColumn(header) {
|
||||
const name = header.name;
|
||||
const label = L10N.getStr(`netmonitor.ws.toolbar.${name}`);
|
||||
|
||||
return dom.td(
|
||||
{
|
||||
id: `ws-frames-list-${name}-header-box`,
|
||||
className: `ws-frames-list-column ws-frames-list-${name}`,
|
||||
key: name,
|
||||
},
|
||||
button(
|
||||
{
|
||||
id: `ws-frames-list-${name}-button`,
|
||||
className: `ws-frames-list-header-button`,
|
||||
title: label,
|
||||
},
|
||||
div({ className: "button-text" }, label),
|
||||
div({ className: "button-icon" })
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render all columns in the table header
|
||||
*/
|
||||
renderColumns() {
|
||||
return WS_FRAMES_HEADERS.map(header => this.renderColumn(header));
|
||||
}
|
||||
|
||||
render() {
|
||||
return dom.thead(
|
||||
{ className: "devtools-toolbar ws-frames-list-headers-group" },
|
||||
dom.tr(
|
||||
{
|
||||
className: "ws-frames-list-headers",
|
||||
},
|
||||
this.renderColumns()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FrameListHeader;
|
|
@ -0,0 +1,87 @@
|
|||
/* 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,
|
||||
createFactory,
|
||||
} = require("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const { tr } = dom;
|
||||
|
||||
loader.lazyGetter(this, "FrameListColumnType", function() {
|
||||
return createFactory(require("./FrameListColumnType"));
|
||||
});
|
||||
loader.lazyGetter(this, "FrameListColumnSize", function() {
|
||||
return createFactory(require("./FrameListColumnSize"));
|
||||
});
|
||||
loader.lazyGetter(this, "FrameListColumnPayload", function() {
|
||||
return createFactory(require("./FrameListColumnPayload"));
|
||||
});
|
||||
loader.lazyGetter(this, "FrameListColumnOpCode", function() {
|
||||
return createFactory(require("./FrameListColumnOpCode"));
|
||||
});
|
||||
loader.lazyGetter(this, "FrameListColumnMaskBit", function() {
|
||||
return createFactory(require("./FrameListColumnMaskBit"));
|
||||
});
|
||||
loader.lazyGetter(this, "FrameListColumnFinBit", function() {
|
||||
return createFactory(require("./FrameListColumnFinBit"));
|
||||
});
|
||||
loader.lazyGetter(this, "FrameListColumnTime", function() {
|
||||
return createFactory(require("./FrameListColumnTime"));
|
||||
});
|
||||
|
||||
const COLUMN_COMPONENTS = [
|
||||
{ column: "type", ColumnComponent: FrameListColumnType },
|
||||
{ column: "size", ColumnComponent: FrameListColumnSize },
|
||||
{ column: "payload", ColumnComponent: FrameListColumnPayload },
|
||||
{ column: "opCode", ColumnComponent: FrameListColumnOpCode },
|
||||
{ column: "maskBit", ColumnComponent: FrameListColumnMaskBit },
|
||||
{ column: "finBit", ColumnComponent: FrameListColumnFinBit },
|
||||
{ column: "time", ColumnComponent: FrameListColumnTime },
|
||||
];
|
||||
|
||||
/**
|
||||
* Renders one row in the frame list.
|
||||
*/
|
||||
class FrameListItem extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
item: PropTypes.object.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
isSelected: PropTypes.bool.isRequired,
|
||||
onMouseDown: PropTypes.func.isRequired,
|
||||
connector: PropTypes.object.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { item, index, isSelected, onMouseDown, connector } = this.props;
|
||||
|
||||
const classList = ["ws-frame-list-item", index % 2 ? "odd" : "even"];
|
||||
if (isSelected) {
|
||||
classList.push("selected");
|
||||
}
|
||||
|
||||
return tr(
|
||||
{
|
||||
className: classList.join(" "),
|
||||
tabIndex: 0,
|
||||
onMouseDown,
|
||||
},
|
||||
COLUMN_COMPONENTS.map(({ ColumnComponent, column }) =>
|
||||
ColumnComponent({
|
||||
key: column + "-" + index,
|
||||
connector,
|
||||
item,
|
||||
index,
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FrameListItem;
|
|
@ -0,0 +1,60 @@
|
|||
/* 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("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const { div } = dom;
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const { getFramePayload } = require("../../utils/request-utils");
|
||||
|
||||
/**
|
||||
* Shows the full payload of a WebSocket frame.
|
||||
* The payload is unwrapped from the LongStringActor object.
|
||||
*/
|
||||
class FramePayload extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
connector: PropTypes.object.isRequired,
|
||||
selectedFrame: PropTypes.object,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
payload: "",
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { selectedFrame, connector } = this.props;
|
||||
getFramePayload(selectedFrame.payload, connector.getLongString).then(
|
||||
payload => {
|
||||
this.setState({
|
||||
payload,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { selectedFrame, connector } = nextProps;
|
||||
getFramePayload(selectedFrame.payload, connector.getLongString).then(
|
||||
payload => {
|
||||
this.setState({
|
||||
payload,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return div({ className: "ws-frame-payload" }, this.state.payload);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FramePayload;
|
|
@ -0,0 +1,109 @@
|
|||
/* 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 Services = require("Services");
|
||||
const {
|
||||
Component,
|
||||
createFactory,
|
||||
} = require("devtools/client/shared/vendor/react");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const {
|
||||
connect,
|
||||
} = require("devtools/client/shared/redux/visibility-handler-connect");
|
||||
const Actions = require("../../actions/index");
|
||||
|
||||
const {
|
||||
getSelectedFrame,
|
||||
isSelectedFrameVisible,
|
||||
} = require("../../selectors/index");
|
||||
|
||||
// Components
|
||||
const SplitBox = createFactory(
|
||||
require("devtools/client/shared/components/splitter/SplitBox")
|
||||
);
|
||||
const FrameListContent = createFactory(require("./FrameListContent"));
|
||||
|
||||
loader.lazyGetter(this, "FramePayload", function() {
|
||||
return createFactory(require("./FramePayload"));
|
||||
});
|
||||
|
||||
/**
|
||||
* Renders a list of WebSocket frames in table view.
|
||||
* Full payload is separated using a SplitBox.
|
||||
*/
|
||||
class WebSocketsPanel extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
channelId: PropTypes.number,
|
||||
connector: PropTypes.object.isRequired,
|
||||
selectedFrame: PropTypes.object,
|
||||
frameDetailsOpen: PropTypes.bool.isRequired,
|
||||
openFrameDetailsTab: PropTypes.func.isRequired,
|
||||
selectedFrameVisible: PropTypes.bool.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { selectedFrameVisible, openFrameDetailsTab } = this.props;
|
||||
if (!selectedFrameVisible) {
|
||||
openFrameDetailsTab(false);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
frameDetailsOpen,
|
||||
channelId,
|
||||
connector,
|
||||
selectedFrame,
|
||||
} = this.props;
|
||||
|
||||
const initialWidth = Services.prefs.getIntPref(
|
||||
"devtools.netmonitor.ws.payload-preview-width"
|
||||
);
|
||||
const initialHeight = Services.prefs.getIntPref(
|
||||
"devtools.netmonitor.ws.payload-preview-height"
|
||||
);
|
||||
|
||||
return SplitBox({
|
||||
className: "devtools-responsive-container",
|
||||
initialWidth: initialWidth,
|
||||
initialHeight: initialHeight,
|
||||
minSize: "50px",
|
||||
maxSize: "50%",
|
||||
splitterSize: frameDetailsOpen ? 1 : 0,
|
||||
startPanel: FrameListContent({ channelId, connector }),
|
||||
endPanel:
|
||||
frameDetailsOpen &&
|
||||
FramePayload({
|
||||
connector,
|
||||
selectedFrame,
|
||||
}),
|
||||
endPanelCollapsed: !frameDetailsOpen,
|
||||
endPanelControl: true,
|
||||
vert: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = connect(
|
||||
(state, props) => ({
|
||||
selectedFrame: getSelectedFrame(state),
|
||||
frameDetailsOpen: state.webSockets.frameDetailsOpen,
|
||||
selectedFrameVisible: isSelectedFrameVisible(
|
||||
state,
|
||||
props.channelId,
|
||||
getSelectedFrame(state)
|
||||
),
|
||||
}),
|
||||
dispatch => ({
|
||||
openFrameDetailsTab: open => dispatch(Actions.openFrameDetails(open)),
|
||||
})
|
||||
)(WebSocketsPanel);
|
|
@ -0,0 +1,18 @@
|
|||
# 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/.
|
||||
|
||||
DevToolsModules(
|
||||
'FrameListColumnFinBit.js',
|
||||
'FrameListColumnMaskBit.js',
|
||||
'FrameListColumnOpCode.js',
|
||||
'FrameListColumnPayload.js',
|
||||
'FrameListColumnSize.js',
|
||||
'FrameListColumnTime.js',
|
||||
'FrameListColumnType.js',
|
||||
'FrameListContent.js',
|
||||
'FrameListHeader.js',
|
||||
'FrameListItem.js',
|
||||
'FramePayload.js',
|
||||
'WebSocketsPanel.js',
|
||||
)
|
|
@ -35,6 +35,8 @@ const actionTypes = {
|
|||
WATERFALL_RESIZE: "WATERFALL_RESIZE",
|
||||
SET_COLUMNS_WIDTH: "SET_COLUMNS_WIDTH",
|
||||
WS_ADD_FRAME: "WS_ADD_FRAME",
|
||||
WS_SELECT_FRAME: "WS_SELECT_FRAME",
|
||||
WS_OPEN_FRAME_DETAILS: "WS_OPEN_FRAME_DETAILS",
|
||||
};
|
||||
|
||||
// Descriptions for what this frontend is currently doing.
|
||||
|
@ -316,6 +318,30 @@ const FILTER_TAGS = [
|
|||
"other",
|
||||
];
|
||||
|
||||
const WS_FRAMES_HEADERS = [
|
||||
{
|
||||
name: "frameType",
|
||||
},
|
||||
{
|
||||
name: "size",
|
||||
},
|
||||
{
|
||||
name: "payload",
|
||||
},
|
||||
{
|
||||
name: "opCode",
|
||||
},
|
||||
{
|
||||
name: "maskBit",
|
||||
},
|
||||
{
|
||||
name: "finBit",
|
||||
},
|
||||
{
|
||||
name: "time",
|
||||
},
|
||||
];
|
||||
|
||||
const REQUESTS_WATERFALL = {
|
||||
BACKGROUND_TICKS_MULTIPLE: 5, // ms
|
||||
BACKGROUND_TICKS_SCALES: 3,
|
||||
|
@ -444,6 +470,7 @@ const general = {
|
|||
FILTER_SEARCH_DELAY: 200,
|
||||
UPDATE_PROPS,
|
||||
HEADERS,
|
||||
WS_FRAMES_HEADERS,
|
||||
RESPONSE_HEADERS,
|
||||
FILTER_FLAGS,
|
||||
FILTER_TAGS,
|
||||
|
|
|
@ -11,14 +11,14 @@ const { sortReducer } = require("./sort");
|
|||
const { filters } = require("./filters");
|
||||
const { timingMarkers } = require("./timing-markers");
|
||||
const { ui } = require("./ui");
|
||||
const { webSocketsReducer } = require("./web-sockets");
|
||||
const { webSockets } = require("./web-sockets");
|
||||
const networkThrottling = require("devtools/client/shared/components/throttling/reducer");
|
||||
|
||||
module.exports = batchingReducer(
|
||||
combineReducers({
|
||||
requests: requestsReducer,
|
||||
sort: sortReducer,
|
||||
webSockets: webSocketsReducer,
|
||||
webSockets,
|
||||
filters,
|
||||
timingMarkers,
|
||||
ui,
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
const {
|
||||
WS_ADD_FRAME,
|
||||
WS_SELECT_FRAME,
|
||||
WS_OPEN_FRAME_DETAILS,
|
||||
} = require("../constants");
|
||||
|
||||
/**
|
||||
|
@ -16,17 +18,13 @@ function WebSockets() {
|
|||
return {
|
||||
// Map with all requests (key = channelId, value = array of frame objects)
|
||||
frames: new Map(),
|
||||
selectedFrame: null,
|
||||
frameDetailsOpen: false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This reducer is responsible for maintaining list of
|
||||
* WebSocket frames within the Network panel.
|
||||
*/
|
||||
function webSocketsReducer(state = WebSockets(), action) {
|
||||
switch (action.type) {
|
||||
// Appending new frame into the map.
|
||||
case WS_ADD_FRAME: {
|
||||
function addFrame(state, action) {
|
||||
const nextState = { ...state };
|
||||
|
||||
const newFrame = {
|
||||
|
@ -39,9 +37,20 @@ function webSocketsReducer(state = WebSockets(), action) {
|
|||
return nextState;
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
// Select specific frame.
|
||||
function selectFrame(state, action) {
|
||||
return {
|
||||
...state,
|
||||
selectedFrame: action.frame,
|
||||
frameDetailsOpen: action.open,
|
||||
};
|
||||
}
|
||||
|
||||
function openFrameDetails(state, action) {
|
||||
return {
|
||||
...state,
|
||||
frameDetailsOpen: action.open,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,7 +67,24 @@ function mapSet(map, key, value) {
|
|||
return newMap.set(key, [value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This reducer is responsible for maintaining list of
|
||||
* WebSocket frames within the Network panel.
|
||||
*/
|
||||
function webSockets(state = WebSockets(), action) {
|
||||
switch (action.type) {
|
||||
case WS_ADD_FRAME:
|
||||
return addFrame(state, action);
|
||||
case WS_SELECT_FRAME:
|
||||
return selectFrame(state, action);
|
||||
case WS_OPEN_FRAME_DETAILS:
|
||||
return openFrameDetails(state, action);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
WebSockets,
|
||||
webSocketsReducer,
|
||||
webSockets,
|
||||
};
|
||||
|
|
|
@ -4,10 +4,32 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { createSelector } = require("devtools/client/shared/vendor/reselect");
|
||||
|
||||
function getFramesByChannelId(state, channelId) {
|
||||
return state.webSockets.frames.get(channelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the selected frame is visible.
|
||||
* If the selected frame is not visible, the SplitBox component
|
||||
* should not show the FramePayload component.
|
||||
*/
|
||||
function isSelectedFrameVisible(state, channelId, targetFrame) {
|
||||
const displayedFrames = getFramesByChannelId(state, channelId);
|
||||
if (displayedFrames && targetFrame) {
|
||||
return displayedFrames.some(frame => frame === targetFrame);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const getSelectedFrame = createSelector(
|
||||
state => state.webSockets,
|
||||
({ selectedFrame }) => (selectedFrame ? selectedFrame : undefined)
|
||||
);
|
||||
|
||||
module.exports = {
|
||||
getFramesByChannelId,
|
||||
getSelectedFrame,
|
||||
isSelectedFrameVisible,
|
||||
};
|
||||
|
|
|
@ -520,6 +520,15 @@ async function updateFormDataSections(props) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This helper function helps to resolve the full payload of a WebSocket frame
|
||||
* that is wrapped in a LongStringActor object.
|
||||
*/
|
||||
async function getFramePayload(payload, getLongString) {
|
||||
const result = await getLongString(payload);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This helper function is used for additional processing of
|
||||
* incoming network update packets. It's used by Network and
|
||||
|
@ -561,6 +570,7 @@ module.exports = {
|
|||
getFileName,
|
||||
getEndTime,
|
||||
getFormattedProtocol,
|
||||
getFramePayload,
|
||||
getResponseHeader,
|
||||
getResponseTime,
|
||||
getStartTime,
|
||||
|
|
|
@ -169,6 +169,8 @@ pref("devtools.netmonitor.visibleColumns",
|
|||
);
|
||||
pref("devtools.netmonitor.columnsData",
|
||||
'[{"name":"status","minWidth":30,"width":5}, {"name":"method","minWidth":30,"width":5}, {"name":"domain","minWidth":30,"width":10}, {"name":"file","minWidth":30,"width":25}, {"name":"url","minWidth":30,"width":25}, {"name":"cause","minWidth":30,"width":10},{"name":"type","minWidth":30,"width":5},{"name":"transferred","minWidth":30,"width":10},{"name":"contentSize","minWidth":30,"width":5},{"name":"waterfall","minWidth":150,"width":25}]');
|
||||
pref("devtools.netmonitor.ws.payload-preview-width", 550);
|
||||
pref("devtools.netmonitor.ws.payload-preview-height", 450);
|
||||
|
||||
// Support for columns resizing pref is now enabled (after merge date 03/18/19).
|
||||
pref("devtools.netmonitor.features.resizeColumns", true);
|
||||
|
|
Загрузка…
Ссылка в новой задаче