mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 15:28:39 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
75
devtools/client/webconsole/net/components/cookies-tab.js
Normal file
75
devtools/client/webconsole/net/components/cookies-tab.js
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/* 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 React = require("devtools/client/shared/vendor/react");
|
||||
const NetInfoGroupList = React.createFactory(require("./net-info-group-list"));
|
||||
const Spinner = React.createFactory(require("./spinner"));
|
||||
|
||||
// Shortcuts
|
||||
const DOM = React.DOM;
|
||||
const PropTypes = React.PropTypes;
|
||||
|
||||
/**
|
||||
* This template represents 'Cookies' tab displayed when the user
|
||||
* expands network log in the Console panel. It's responsible for rendering
|
||||
* sent and received cookies.
|
||||
*/
|
||||
var CookiesTab = React.createClass({
|
||||
propTypes: {
|
||||
actions: PropTypes.shape({
|
||||
requestData: PropTypes.func.isRequired
|
||||
}),
|
||||
data: PropTypes.object.isRequired,
|
||||
},
|
||||
|
||||
displayName: "CookiesTab",
|
||||
|
||||
componentDidMount() {
|
||||
let { actions, data } = this.props;
|
||||
let requestCookies = data.request.cookies;
|
||||
let responseCookies = data.response.cookies;
|
||||
|
||||
// TODO: use async action objects as soon as Redux is in place
|
||||
if (!requestCookies || !requestCookies.length) {
|
||||
actions.requestData("requestCookies");
|
||||
}
|
||||
|
||||
if (!responseCookies || !responseCookies.length) {
|
||||
actions.requestData("responseCookies");
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
let { actions, data: file } = this.props;
|
||||
let requestCookies = file.request.cookies;
|
||||
let responseCookies = file.response.cookies;
|
||||
|
||||
// The cookie panel displays two groups of cookies:
|
||||
// 1) Response Cookies
|
||||
// 2) Request Cookies
|
||||
let groups = [{
|
||||
key: "responseCookies",
|
||||
name: Locale.$STR("responseCookies"),
|
||||
params: responseCookies
|
||||
}, {
|
||||
key: "requestCookies",
|
||||
name: Locale.$STR("requestCookies"),
|
||||
params: requestCookies
|
||||
}];
|
||||
|
||||
return (
|
||||
DOM.div({className: "cookiesTabBox"},
|
||||
DOM.div({className: "panelContent"},
|
||||
NetInfoGroupList({
|
||||
groups: groups
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
module.exports = CookiesTab;
|
||||
79
devtools/client/webconsole/net/components/headers-tab.js
Normal file
79
devtools/client/webconsole/net/components/headers-tab.js
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* 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 React = require("devtools/client/shared/vendor/react");
|
||||
const NetInfoGroupList = React.createFactory(require("./net-info-group-list"));
|
||||
const Spinner = React.createFactory(require("./spinner"));
|
||||
|
||||
// Shortcuts
|
||||
const DOM = React.DOM;
|
||||
const PropTypes = React.PropTypes;
|
||||
|
||||
/**
|
||||
* This template represents 'Headers' tab displayed when the user
|
||||
* expands network log in the Console panel. It's responsible for rendering
|
||||
* request and response HTTP headers.
|
||||
*/
|
||||
var HeadersTab = React.createClass({
|
||||
propTypes: {
|
||||
actions: PropTypes.shape({
|
||||
requestData: PropTypes.func.isRequired
|
||||
}),
|
||||
data: PropTypes.object.isRequired,
|
||||
},
|
||||
|
||||
displayName: "HeadersTab",
|
||||
|
||||
componentDidMount() {
|
||||
let { actions, data } = this.props;
|
||||
let requestHeaders = data.request.headers;
|
||||
let responseHeaders = data.response.headers;
|
||||
|
||||
// Request headers if they are not available yet.
|
||||
// TODO: use async action objects as soon as Redux is in place
|
||||
if (!requestHeaders) {
|
||||
actions.requestData("requestHeaders");
|
||||
}
|
||||
|
||||
if (!responseHeaders) {
|
||||
actions.requestData("responseHeaders");
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
let { data } = this.props;
|
||||
let requestHeaders = data.request.headers;
|
||||
let responseHeaders = data.response.headers;
|
||||
|
||||
// TODO: Another groups to implement:
|
||||
// 1) Cached Headers
|
||||
// 2) Headers from upload stream
|
||||
let groups = [{
|
||||
key: "responseHeaders",
|
||||
name: Locale.$STR("responseHeaders"),
|
||||
params: responseHeaders
|
||||
}, {
|
||||
key: "requestHeaders",
|
||||
name: Locale.$STR("requestHeaders"),
|
||||
params: requestHeaders
|
||||
}];
|
||||
|
||||
// If response headers are not available yet, display a spinner
|
||||
if (!responseHeaders || !responseHeaders.length) {
|
||||
groups[0].content = Spinner();
|
||||
}
|
||||
|
||||
return (
|
||||
DOM.div({className: "headersTabBox"},
|
||||
DOM.div({className: "panelContent"},
|
||||
NetInfoGroupList({groups: groups})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
module.exports = HeadersTab;
|
||||
25
devtools/client/webconsole/net/components/moz.build
Normal file
25
devtools/client/webconsole/net/components/moz.build
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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(
|
||||
'cookies-tab.js',
|
||||
'headers-tab.js',
|
||||
'net-info-body.css',
|
||||
'net-info-body.js',
|
||||
'net-info-group-list.js',
|
||||
'net-info-group.css',
|
||||
'net-info-group.js',
|
||||
'net-info-params.css',
|
||||
'net-info-params.js',
|
||||
'params-tab.js',
|
||||
'post-tab.js',
|
||||
'response-tab.css',
|
||||
'response-tab.js',
|
||||
'size-limit.css',
|
||||
'size-limit.js',
|
||||
'spinner.js',
|
||||
'stacktrace-tab.js',
|
||||
)
|
||||
112
devtools/client/webconsole/net/components/net-info-body.css
Normal file
112
devtools/client/webconsole/net/components/net-info-body.css
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Network Info Body */
|
||||
|
||||
.netInfoBody {
|
||||
margin: 10px 0 0 0;
|
||||
width: 100%;
|
||||
cursor: default;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.netInfoBody *:focus {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
.netInfoBody .panelContent {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Network Info Body Tabs */
|
||||
|
||||
.netInfoBody > .tabs {
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.netInfoBody > .tabs .tabs-navigation {
|
||||
border-bottom-color: var(--net-border);
|
||||
background-color: transparent;
|
||||
text-decoration: none;
|
||||
padding-top: 3px;
|
||||
padding-left: 7px;
|
||||
padding-bottom: 1px;
|
||||
border-bottom: 1px solid var(--net-border);
|
||||
}
|
||||
|
||||
.netInfoBody > .tabs .tabs-menu {
|
||||
display: table;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* This is the trick that makes the tab bottom border invisible */
|
||||
.netInfoBody > .tabs .tabs-menu-item {
|
||||
position: relative;
|
||||
bottom: -2px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.netInfoBody > .tabs .tabs-menu-item a {
|
||||
display: block;
|
||||
border: 1px solid transparent;
|
||||
text-decoration: none;
|
||||
padding: 5px 8px 4px 8px;;
|
||||
font-weight: bold;
|
||||
color: var(--theme-body-color);
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.netInfoBody > .tabs .tab-panel {
|
||||
background-color: var(--theme-body-background);
|
||||
border: 1px solid transparent;
|
||||
border-top: none;
|
||||
padding: 10px;
|
||||
overflow: auto;
|
||||
height: calc(100% - 31px); /* minus the height of the tab bar */
|
||||
}
|
||||
|
||||
.netInfoBody > .tabs .tab-panel > div,
|
||||
.netInfoBody > .tabs .tab-panel > div > div {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.netInfoBody > .tabs .tabs-menu-item.is-active a,
|
||||
.netInfoBody > .tabs .tabs-menu-item.is-active a:focus,
|
||||
.netInfoBody > .tabs .tabs-menu-item.is-active:hover a {
|
||||
background-color: var(--theme-body-background);
|
||||
border: 1px solid transparent;
|
||||
border-bottom-color: var(--theme-highlight-bluegrey);
|
||||
color: var(--theme-highlight-bluegrey);
|
||||
}
|
||||
|
||||
.netInfoBody > .tabs .tabs-menu-item:hover a {
|
||||
border: 1px solid transparent;
|
||||
border-bottom: 1px solid var(--net-border);
|
||||
background-color: var(--theme-body-background);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Themes */
|
||||
|
||||
.theme-firebug .netInfoBody > .tabs .tab-panel {
|
||||
border-color: var(--net-border);
|
||||
}
|
||||
|
||||
.theme-firebug .netInfoBody > .tabs .tabs-menu-item.is-active a,
|
||||
.theme-firebug .netInfoBody > .tabs .tabs-menu-item.is-active:hover a,
|
||||
.theme-firebug .netInfoBody > .tabs .tabs-menu-item.is-active a:focus {
|
||||
border: 1px solid var(--net-border);
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
.theme-firebug .netInfoBody > .tabs .tabs-menu-item:hover a {
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
179
devtools/client/webconsole/net/components/net-info-body.js
Normal file
179
devtools/client/webconsole/net/components/net-info-body.js
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/* 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 React = require("devtools/client/shared/vendor/react");
|
||||
const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
|
||||
const { Tabs, TabPanel } = createFactories(require("devtools/client/shared/components/tabs/tabs"));
|
||||
|
||||
// Network
|
||||
const HeadersTab = React.createFactory(require("./headers-tab"));
|
||||
const ResponseTab = React.createFactory(require("./response-tab"));
|
||||
const ParamsTab = React.createFactory(require("./params-tab"));
|
||||
const CookiesTab = React.createFactory(require("./cookies-tab"));
|
||||
const PostTab = React.createFactory(require("./post-tab"));
|
||||
const StackTraceTab = React.createFactory(require("./stacktrace-tab"));
|
||||
const NetUtils = require("../utils/net");
|
||||
|
||||
// Shortcuts
|
||||
const PropTypes = React.PropTypes;
|
||||
|
||||
/**
|
||||
* This template renders the basic Network log info body. It's not
|
||||
* visible by default, the user needs to expand the network log
|
||||
* to see it.
|
||||
*
|
||||
* This is the set of tabs displaying details about network events:
|
||||
* 1) Headers - request and response headers
|
||||
* 2) Params - URL parameters
|
||||
* 3) Response - response body
|
||||
* 4) Cookies - request and response cookies
|
||||
* 5) Post - posted data
|
||||
*/
|
||||
var NetInfoBody = React.createClass({
|
||||
propTypes: {
|
||||
tabActive: PropTypes.number.isRequired,
|
||||
actions: PropTypes.object.isRequired,
|
||||
data: PropTypes.shape({
|
||||
request: PropTypes.object.isRequired,
|
||||
response: PropTypes.object.isRequired
|
||||
})
|
||||
},
|
||||
|
||||
displayName: "NetInfoBody",
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
tabActive: 0
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
data: {
|
||||
request: {},
|
||||
response: {}
|
||||
},
|
||||
tabActive: this.props.tabActive,
|
||||
};
|
||||
},
|
||||
|
||||
onTabChanged(index) {
|
||||
this.setState({tabActive: index});
|
||||
},
|
||||
|
||||
hasCookies() {
|
||||
let {request, response} = this.state.data;
|
||||
return this.state.hasCookies ||
|
||||
NetUtils.getHeaderValue(request.headers, "Cookie") ||
|
||||
NetUtils.getHeaderValue(response.headers, "Set-Cookie");
|
||||
},
|
||||
|
||||
hasStackTrace() {
|
||||
let {cause} = this.state.data;
|
||||
return cause && cause.stacktrace && cause.stacktrace.length > 0;
|
||||
},
|
||||
|
||||
getTabPanels() {
|
||||
let actions = this.props.actions;
|
||||
let data = this.state.data;
|
||||
let {request} = data;
|
||||
|
||||
// Flags for optional tabs. Some tabs are visible only if there
|
||||
// are data to display.
|
||||
let hasParams = request.queryString && request.queryString.length;
|
||||
let hasPostData = request.bodySize > 0;
|
||||
|
||||
let panels = [];
|
||||
|
||||
// Headers tab
|
||||
panels.push(
|
||||
TabPanel({
|
||||
className: "headers",
|
||||
key: "headers",
|
||||
title: Locale.$STR("netRequest.headers")},
|
||||
HeadersTab({data: data, actions: actions})
|
||||
)
|
||||
);
|
||||
|
||||
// URL parameters tab
|
||||
if (hasParams) {
|
||||
panels.push(
|
||||
TabPanel({
|
||||
className: "params",
|
||||
key: "params",
|
||||
title: Locale.$STR("netRequest.params")},
|
||||
ParamsTab({data: data, actions: actions})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Posted data tab
|
||||
if (hasPostData) {
|
||||
panels.push(
|
||||
TabPanel({
|
||||
className: "post",
|
||||
key: "post",
|
||||
title: Locale.$STR("netRequest.post")},
|
||||
PostTab({data: data, actions: actions})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Response tab
|
||||
panels.push(
|
||||
TabPanel({className: "response", key: "response",
|
||||
title: Locale.$STR("netRequest.response")},
|
||||
ResponseTab({data: data, actions: actions})
|
||||
)
|
||||
);
|
||||
|
||||
// Cookies tab
|
||||
if (this.hasCookies()) {
|
||||
panels.push(
|
||||
TabPanel({
|
||||
className: "cookies",
|
||||
key: "cookies",
|
||||
title: Locale.$STR("netRequest.cookies")},
|
||||
CookiesTab({
|
||||
data: data,
|
||||
actions: actions
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Stacktrace tab
|
||||
if (this.hasStackTrace()) {
|
||||
panels.push(
|
||||
TabPanel({
|
||||
className: "stacktrace-tab",
|
||||
key: "stacktrace",
|
||||
title: Locale.$STR("netRequest.callstack")},
|
||||
StackTraceTab({
|
||||
data: data,
|
||||
actions: actions
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return panels;
|
||||
},
|
||||
|
||||
render() {
|
||||
let tabActive = this.state.tabActive;
|
||||
let tabPanels = this.getTabPanels();
|
||||
return (
|
||||
Tabs({
|
||||
tabActive: tabActive,
|
||||
onAfterChange: this.onTabChanged},
|
||||
tabPanels
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
module.exports = NetInfoBody;
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/* 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 React = require("devtools/client/shared/vendor/react");
|
||||
const NetInfoGroup = React.createFactory(require("./net-info-group"));
|
||||
|
||||
// Shortcuts
|
||||
const DOM = React.DOM;
|
||||
const PropTypes = React.PropTypes;
|
||||
|
||||
/**
|
||||
* This template is responsible for rendering sections/groups inside tabs.
|
||||
* It's used e.g to display Response and Request headers as separate groups.
|
||||
*/
|
||||
var NetInfoGroupList = React.createClass({
|
||||
propTypes: {
|
||||
groups: PropTypes.array.isRequired,
|
||||
},
|
||||
|
||||
displayName: "NetInfoGroupList",
|
||||
|
||||
render() {
|
||||
let groups = this.props.groups;
|
||||
|
||||
// Filter out empty groups.
|
||||
groups = groups.filter(group => {
|
||||
return group && ((group.params && group.params.length) || group.content);
|
||||
});
|
||||
|
||||
// Render groups
|
||||
groups = groups.map(group => {
|
||||
group.type = group.key;
|
||||
return NetInfoGroup(group);
|
||||
});
|
||||
|
||||
return (
|
||||
DOM.div({className: "netInfoGroupList"},
|
||||
groups
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
module.exports = NetInfoGroupList;
|
||||
80
devtools/client/webconsole/net/components/net-info-group.css
Normal file
80
devtools/client/webconsole/net/components/net-info-group.css
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Net Info Group */
|
||||
|
||||
.netInfoBody .netInfoGroup {
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
/* Last group doesn't need bottom padding */
|
||||
.netInfoBody .netInfoGroup:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.netInfoBody .netInfoGroup:last-child .netInfoGroupContent {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.netInfoBody .netInfoGroupTitle {
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
-moz-user-select: none;
|
||||
cursor: pointer;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
.netInfoBody .netInfoGroupTwisty {
|
||||
background-image: url("chrome://devtools/skin/images/controls.png");
|
||||
background-size: 56px 28px;
|
||||
background-position: 0 -14px;
|
||||
background-repeat: no-repeat;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.netInfoBody .netInfoGroup.opened .netInfoGroupTwisty {
|
||||
background-position: -14px -14px;
|
||||
}
|
||||
|
||||
/* Group content is expandable/collapsible by clicking on the title */
|
||||
.netInfoBody .netInfoGroupContent {
|
||||
padding-top: 7px;
|
||||
margin-top: 3px;
|
||||
padding-bottom: 14px;
|
||||
border-top: 1px solid var(--net-border);
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Toggle group visibility */
|
||||
.netInfoBody .netInfoGroup.opened .netInfoGroupContent {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Themes */
|
||||
|
||||
.theme-dark .netInfoBody .netInfoGroup {
|
||||
color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.theme-dark .netInfoBody .netInfoGroup .netInfoGroupTwisty {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
/* Twisties */
|
||||
.theme-firebug .netInfoBody .netInfoGroup .netInfoGroupTwisty {
|
||||
background-image: url("chrome://devtools/skin/images/firebug/twisty-closed-firebug.svg");
|
||||
background-position: 0 2px;
|
||||
background-size: 11px 11px;
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.theme-firebug .netInfoBody .netInfoGroup.opened .netInfoGroupTwisty {
|
||||
background-image: url("chrome://devtools/skin/images/firebug/twisty-open-firebug.svg");
|
||||
}
|
||||
80
devtools/client/webconsole/net/components/net-info-group.js
Normal file
80
devtools/client/webconsole/net/components/net-info-group.js
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/* 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 React = require("devtools/client/shared/vendor/react");
|
||||
const NetInfoParams = React.createFactory(require("./net-info-params"));
|
||||
|
||||
// Shortcuts
|
||||
const DOM = React.DOM;
|
||||
const PropTypes = React.PropTypes;
|
||||
|
||||
/**
|
||||
* This template represents a group of data within a tab. For example,
|
||||
* Headers tab has two groups 'Request Headers' and 'Response Headers'
|
||||
* The Response tab can also have two groups 'Raw Data' and 'JSON'
|
||||
*/
|
||||
var NetInfoGroup = React.createClass({
|
||||
propTypes: {
|
||||
type: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
params: PropTypes.array,
|
||||
content: PropTypes.element,
|
||||
open: PropTypes.bool
|
||||
},
|
||||
|
||||
displayName: "NetInfoGroup",
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
open: true,
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
open: this.props.open,
|
||||
};
|
||||
},
|
||||
|
||||
onToggle(event) {
|
||||
this.setState({
|
||||
open: !this.state.open
|
||||
});
|
||||
},
|
||||
|
||||
render() {
|
||||
let content = this.props.content;
|
||||
|
||||
if (!content && this.props.params) {
|
||||
content = NetInfoParams({
|
||||
params: this.props.params
|
||||
});
|
||||
}
|
||||
|
||||
let open = this.state.open;
|
||||
let className = open ? "opened" : "";
|
||||
|
||||
return (
|
||||
DOM.div({className: "netInfoGroup" + " " + className + " " +
|
||||
this.props.type},
|
||||
DOM.span({
|
||||
className: "netInfoGroupTwisty",
|
||||
onClick: this.onToggle
|
||||
}),
|
||||
DOM.span({
|
||||
className: "netInfoGroupTitle",
|
||||
onClick: this.onToggle},
|
||||
this.props.name
|
||||
),
|
||||
DOM.div({className: "netInfoGroupContent"},
|
||||
content
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
module.exports = NetInfoGroup;
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Net Info Params */
|
||||
|
||||
.netInfoBody .netInfoParamName {
|
||||
padding: 0 10px 0 0;
|
||||
font-weight: bold;
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.netInfoBody .netInfoParamValue {
|
||||
width: 100%;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.netInfoBody .netInfoParamValue > code {
|
||||
font-family: var(--monospace-font-family);
|
||||
}
|
||||
58
devtools/client/webconsole/net/components/net-info-params.js
Normal file
58
devtools/client/webconsole/net/components/net-info-params.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/* 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 React = require("devtools/client/shared/vendor/react");
|
||||
|
||||
// Shortcuts
|
||||
const DOM = React.DOM;
|
||||
const PropTypes = React.PropTypes;
|
||||
|
||||
/**
|
||||
* This template renders list of parameters within a group.
|
||||
* It's essentially a list of name + value pairs.
|
||||
*/
|
||||
var NetInfoParams = React.createClass({
|
||||
displayName: "NetInfoParams",
|
||||
|
||||
propTypes: {
|
||||
params: PropTypes.arrayOf(PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
value: PropTypes.string.isRequired
|
||||
})).isRequired,
|
||||
},
|
||||
|
||||
render() {
|
||||
let params = this.props.params || [];
|
||||
|
||||
params.sort(function (a, b) {
|
||||
return a.name > b.name ? 1 : -1;
|
||||
});
|
||||
|
||||
let rows = [];
|
||||
params.forEach((param, index) => {
|
||||
rows.push(
|
||||
DOM.tr({key: index},
|
||||
DOM.td({className: "netInfoParamName"},
|
||||
DOM.span({title: param.name}, param.name)
|
||||
),
|
||||
DOM.td({className: "netInfoParamValue"},
|
||||
DOM.code({}, param.value)
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
DOM.table({cellPadding: 0, cellSpacing: 0},
|
||||
DOM.tbody({},
|
||||
rows
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
module.exports = NetInfoParams;
|
||||
41
devtools/client/webconsole/net/components/params-tab.js
Normal file
41
devtools/client/webconsole/net/components/params-tab.js
Normal file
|
|
@ -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 React = require("devtools/client/shared/vendor/react");
|
||||
const NetInfoParams = React.createFactory(require("./net-info-params"));
|
||||
|
||||
// Shortcuts
|
||||
const DOM = React.DOM;
|
||||
const PropTypes = React.PropTypes;
|
||||
|
||||
/**
|
||||
* This template represents 'Params' tab displayed when the user
|
||||
* expands network log in the Console panel. It's responsible for
|
||||
* displaying URL parameters (query string).
|
||||
*/
|
||||
var ParamsTab = React.createClass({
|
||||
propTypes: {
|
||||
data: PropTypes.shape({
|
||||
request: PropTypes.object.isRequired
|
||||
})
|
||||
},
|
||||
|
||||
displayName: "ParamsTab",
|
||||
|
||||
render() {
|
||||
let data = this.props.data;
|
||||
|
||||
return (
|
||||
DOM.div({className: "paramsTabBox"},
|
||||
DOM.div({className: "panelContent"},
|
||||
NetInfoParams({params: data.request.queryString})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
module.exports = ParamsTab;
|
||||
279
devtools/client/webconsole/net/components/post-tab.js
Normal file
279
devtools/client/webconsole/net/components/post-tab.js
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
/* 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 React = require("devtools/client/shared/vendor/react");
|
||||
|
||||
// Reps
|
||||
const { createFactories, parseURLEncodedText } = require("devtools/client/shared/components/reps/rep-utils");
|
||||
const TreeView = React.createFactory(require("devtools/client/shared/components/tree/tree-view"));
|
||||
const { Rep } = createFactories(require("devtools/client/shared/components/reps/rep"));
|
||||
|
||||
// Network
|
||||
const NetInfoParams = React.createFactory(require("./net-info-params"));
|
||||
const NetInfoGroupList = React.createFactory(require("./net-info-group-list"));
|
||||
const Spinner = React.createFactory(require("./spinner"));
|
||||
const SizeLimit = React.createFactory(require("./size-limit"));
|
||||
const NetUtils = require("../utils/net");
|
||||
const Json = require("../utils/json");
|
||||
|
||||
// Shortcuts
|
||||
const DOM = React.DOM;
|
||||
const PropTypes = React.PropTypes;
|
||||
|
||||
/**
|
||||
* This template represents 'Post' tab displayed when the user
|
||||
* expands network log in the Console panel. It's responsible for
|
||||
* displaying posted data (HTTP post body).
|
||||
*/
|
||||
var PostTab = React.createClass({
|
||||
propTypes: {
|
||||
data: PropTypes.shape({
|
||||
request: PropTypes.object.isRequired
|
||||
}),
|
||||
actions: PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
displayName: "PostTab",
|
||||
|
||||
isJson(file) {
|
||||
let text = file.request.postData.text;
|
||||
let value = NetUtils.getHeaderValue(file.request.headers, "content-type");
|
||||
return Json.isJSON(value, text);
|
||||
},
|
||||
|
||||
parseJson(file) {
|
||||
let postData = file.request.postData;
|
||||
if (!postData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let jsonString = new String(postData.text);
|
||||
return Json.parseJSONString(jsonString);
|
||||
},
|
||||
|
||||
/**
|
||||
* Render JSON post data as an expandable tree.
|
||||
*/
|
||||
renderJson(file) {
|
||||
let text = file.request.postData.text;
|
||||
if (!text || isLongString(text)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this.isJson(file)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let json = this.parseJson(file);
|
||||
if (!json) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
key: "json",
|
||||
content: TreeView({
|
||||
columns: [{id: "value"}],
|
||||
object: json,
|
||||
mode: "tiny",
|
||||
renderValue: props => Rep(Object.assign({}, props, {
|
||||
cropLimit: 50,
|
||||
})),
|
||||
}),
|
||||
name: Locale.$STR("jsonScopeName")
|
||||
};
|
||||
},
|
||||
|
||||
parseXml(file) {
|
||||
let text = file.request.postData.text;
|
||||
if (isLongString(text)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return NetUtils.parseXml({
|
||||
mimeType: NetUtils.getHeaderValue(file.request.headers, "content-type"),
|
||||
text: text,
|
||||
});
|
||||
},
|
||||
|
||||
isXml(file) {
|
||||
if (isLongString(file.request.postData.text)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let value = NetUtils.getHeaderValue(file.request.headers, "content-type");
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return NetUtils.isHTML(value);
|
||||
},
|
||||
|
||||
renderXml(file) {
|
||||
let text = file.request.postData.text;
|
||||
if (!text || isLongString(text)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this.isXml(file)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let doc = this.parseXml(file);
|
||||
if (!doc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Proper component for rendering XML should be used (see bug 1247392)
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Multipart post data are parsed and nicely rendered
|
||||
* as an expandable tree of individual parts.
|
||||
*/
|
||||
renderMultiPart(file) {
|
||||
let text = file.request.postData.text;
|
||||
if (!text || isLongString(text)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NetUtils.isMultiPartRequest(file)) {
|
||||
// TODO: render multi part request (bug: 1247423)
|
||||
}
|
||||
|
||||
return;
|
||||
},
|
||||
|
||||
/**
|
||||
* URL encoded post data are nicely rendered as a list
|
||||
* of parameters.
|
||||
*/
|
||||
renderUrlEncoded(file) {
|
||||
let text = file.request.postData.text;
|
||||
if (!text || isLongString(text)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!NetUtils.isURLEncodedRequest(file)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let lines = text.split("\n");
|
||||
let params = parseURLEncodedText(lines[lines.length - 1]);
|
||||
|
||||
return {
|
||||
key: "url-encoded",
|
||||
content: NetInfoParams({params: params}),
|
||||
name: Locale.$STR("netRequest.params")
|
||||
};
|
||||
},
|
||||
|
||||
renderRawData(file) {
|
||||
let text = file.request.postData.text;
|
||||
|
||||
let group;
|
||||
|
||||
// The post body might reached the limit, so check if we are
|
||||
// dealing with a long string.
|
||||
if (typeof text == "object") {
|
||||
group = {
|
||||
key: "raw-longstring",
|
||||
name: Locale.$STR("netRequest.rawData"),
|
||||
content: DOM.div({className: "netInfoResponseContent"},
|
||||
sanitize(text.initial),
|
||||
SizeLimit({
|
||||
actions: this.props.actions,
|
||||
data: file.request.postData,
|
||||
message: Locale.$STR("netRequest.sizeLimitMessage"),
|
||||
link: Locale.$STR("netRequest.sizeLimitMessageLink")
|
||||
})
|
||||
)
|
||||
};
|
||||
} else {
|
||||
group = {
|
||||
key: "raw",
|
||||
name: Locale.$STR("netRequest.rawData"),
|
||||
content: DOM.div({className: "netInfoResponseContent"},
|
||||
sanitize(text)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
return group;
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
let { actions, data: file } = this.props;
|
||||
|
||||
if (!file.request.postData) {
|
||||
// TODO: use async action objects as soon as Redux is in place
|
||||
actions.requestData("requestPostData");
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
let { actions, data: file } = this.props;
|
||||
|
||||
if (file.discardRequestBody) {
|
||||
return DOM.span({className: "netInfoBodiesDiscarded"},
|
||||
Locale.$STR("netRequest.requestBodyDiscarded")
|
||||
);
|
||||
}
|
||||
|
||||
if (!file.request.postData) {
|
||||
return (
|
||||
Spinner()
|
||||
);
|
||||
}
|
||||
|
||||
// Render post body data. The right representation of the data
|
||||
// is picked according to the content type.
|
||||
let groups = [];
|
||||
groups.push(this.renderUrlEncoded(file));
|
||||
// TODO: render multi part request (bug: 1247423)
|
||||
// groups.push(this.renderMultiPart(file));
|
||||
groups.push(this.renderJson(file));
|
||||
groups.push(this.renderXml(file));
|
||||
groups.push(this.renderRawData(file));
|
||||
|
||||
// Filter out empty groups.
|
||||
groups = groups.filter(group => group);
|
||||
|
||||
// The raw response is collapsed by default if a nice formatted
|
||||
// version is available.
|
||||
if (groups.length > 1) {
|
||||
groups[groups.length - 1].open = false;
|
||||
}
|
||||
|
||||
return (
|
||||
DOM.div({className: "postTabBox"},
|
||||
DOM.div({className: "panelContent"},
|
||||
NetInfoGroupList({
|
||||
groups: groups
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Helpers
|
||||
|
||||
/**
|
||||
* Workaround for a "not well-formed" error that react
|
||||
* reports when there's multipart data passed to render.
|
||||
*/
|
||||
function sanitize(text) {
|
||||
text = JSON.stringify(text);
|
||||
text = text.replace(/\\r\\n/g, "\r\n").replace(/\\"/g, "\"");
|
||||
return text.slice(1, text.length - 1);
|
||||
}
|
||||
|
||||
function isLongString(text) {
|
||||
return typeof text == "object";
|
||||
}
|
||||
|
||||
// Exports from this module
|
||||
module.exports = PostTab;
|
||||
21
devtools/client/webconsole/net/components/response-tab.css
Normal file
21
devtools/client/webconsole/net/components/response-tab.css
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Response Tab */
|
||||
|
||||
.netInfoBody .netInfoBodiesDiscarded {
|
||||
font-style: italic;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.netInfoBody .netInfoResponseContent {
|
||||
font-family: var(--monospace-font-family);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.netInfoBody .responseTabBox img {
|
||||
max-width: 300px;
|
||||
max-height: 300px;
|
||||
}
|
||||
277
devtools/client/webconsole/net/components/response-tab.js
Normal file
277
devtools/client/webconsole/net/components/response-tab.js
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
/* 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 React = require("devtools/client/shared/vendor/react");
|
||||
|
||||
// Reps
|
||||
const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
|
||||
const TreeView = React.createFactory(require("devtools/client/shared/components/tree/tree-view"));
|
||||
const { Rep } = createFactories(require("devtools/client/shared/components/reps/rep"));
|
||||
|
||||
// Network
|
||||
const SizeLimit = React.createFactory(require("./size-limit"));
|
||||
const NetInfoGroupList = React.createFactory(require("./net-info-group-list"));
|
||||
const Spinner = React.createFactory(require("./spinner"));
|
||||
const Json = require("../utils/json");
|
||||
const NetUtils = require("../utils/net");
|
||||
|
||||
// Shortcuts
|
||||
const DOM = React.DOM;
|
||||
const PropTypes = React.PropTypes;
|
||||
|
||||
/**
|
||||
* This template represents 'Response' tab displayed when the user
|
||||
* expands network log in the Console panel. It's responsible for
|
||||
* rendering HTTP response body.
|
||||
*
|
||||
* In case of supported response mime-type (e.g. application/json,
|
||||
* text/xml, etc.), the response is parsed using appropriate parser
|
||||
* and rendered accordingly.
|
||||
*/
|
||||
var ResponseTab = React.createClass({
|
||||
propTypes: {
|
||||
data: PropTypes.shape({
|
||||
request: PropTypes.object.isRequired,
|
||||
response: PropTypes.object.isRequired
|
||||
}),
|
||||
actions: PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
displayName: "ResponseTab",
|
||||
|
||||
// Response Types
|
||||
|
||||
isJson(content) {
|
||||
if (isLongString(content.text)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Json.isJSON(content.mimeType, content.text);
|
||||
},
|
||||
|
||||
parseJson(file) {
|
||||
let content = file.response.content;
|
||||
if (isLongString(content.text)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let jsonString = new String(content.text);
|
||||
return Json.parseJSONString(jsonString);
|
||||
},
|
||||
|
||||
isImage(content) {
|
||||
if (isLongString(content.text)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return NetUtils.isImage(content.mimeType);
|
||||
},
|
||||
|
||||
isXml(content) {
|
||||
if (isLongString(content.text)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return NetUtils.isHTML(content.mimeType);
|
||||
},
|
||||
|
||||
parseXml(file) {
|
||||
let content = file.response.content;
|
||||
if (isLongString(content.text)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return NetUtils.parseXml(content);
|
||||
},
|
||||
|
||||
// Rendering
|
||||
|
||||
renderJson(file) {
|
||||
let content = file.response.content;
|
||||
if (!this.isJson(content)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let json = this.parseJson(file);
|
||||
if (!json) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
key: "json",
|
||||
content: TreeView({
|
||||
columns: [{id: "value"}],
|
||||
object: json,
|
||||
mode: "tiny",
|
||||
renderValue: props => Rep(Object.assign({}, props, {
|
||||
cropLimit: 50,
|
||||
})),
|
||||
}),
|
||||
name: Locale.$STR("jsonScopeName")
|
||||
};
|
||||
},
|
||||
|
||||
renderImage(file) {
|
||||
let content = file.response.content;
|
||||
if (!this.isImage(content)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let dataUri = "data:" + content.mimeType + ";base64," + content.text;
|
||||
return {
|
||||
key: "image",
|
||||
content: DOM.img({src: dataUri}),
|
||||
name: Locale.$STR("netRequest.image")
|
||||
};
|
||||
},
|
||||
|
||||
renderXml(file) {
|
||||
let content = file.response.content;
|
||||
if (!this.isXml(content)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let doc = this.parseXml(file);
|
||||
if (!doc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Proper component for rendering XML should be used (see bug 1247392)
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* If full response text is available, let's try to parse and
|
||||
* present nicely according to the underlying format.
|
||||
*/
|
||||
renderFormattedResponse(file) {
|
||||
let content = file.response.content;
|
||||
if (typeof content.text == "object") {
|
||||
return null;
|
||||
}
|
||||
|
||||
let group = this.renderJson(file);
|
||||
if (group) {
|
||||
return group;
|
||||
}
|
||||
|
||||
group = this.renderImage(file);
|
||||
if (group) {
|
||||
return group;
|
||||
}
|
||||
|
||||
group = this.renderXml(file);
|
||||
if (group) {
|
||||
return group;
|
||||
}
|
||||
},
|
||||
|
||||
renderRawResponse(file) {
|
||||
let group;
|
||||
let content = file.response.content;
|
||||
|
||||
// The response might reached the limit, so check if we are
|
||||
// dealing with a long string.
|
||||
if (typeof content.text == "object") {
|
||||
group = {
|
||||
key: "raw-longstring",
|
||||
name: Locale.$STR("netRequest.rawData"),
|
||||
content: DOM.div({className: "netInfoResponseContent"},
|
||||
content.text.initial,
|
||||
SizeLimit({
|
||||
actions: this.props.actions,
|
||||
data: content,
|
||||
message: Locale.$STR("netRequest.sizeLimitMessage"),
|
||||
link: Locale.$STR("netRequest.sizeLimitMessageLink")
|
||||
})
|
||||
)
|
||||
};
|
||||
} else {
|
||||
group = {
|
||||
key: "raw",
|
||||
name: Locale.$STR("netRequest.rawData"),
|
||||
content: DOM.div({className: "netInfoResponseContent"},
|
||||
content.text
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
return group;
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
let { actions, data: file } = this.props;
|
||||
let content = file.response.content;
|
||||
|
||||
if (!content || typeof (content.text) == "undefined") {
|
||||
// TODO: use async action objects as soon as Redux is in place
|
||||
actions.requestData("responseContent");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The response panel displays two groups:
|
||||
*
|
||||
* 1) Formatted response (in case of supported format, e.g. JSON, XML, etc.)
|
||||
* 2) Raw response data (always displayed if not discarded)
|
||||
*/
|
||||
render() {
|
||||
let { actions, data: file } = this.props;
|
||||
|
||||
// If response bodies are discarded (not collected) let's just
|
||||
// display a info message indicating what to do to collect even
|
||||
// response bodies.
|
||||
if (file.discardResponseBody) {
|
||||
return DOM.span({className: "netInfoBodiesDiscarded"},
|
||||
Locale.$STR("netRequest.responseBodyDiscarded")
|
||||
);
|
||||
}
|
||||
|
||||
// Request for the response content is done only if the response
|
||||
// is not fetched yet - i.e. the `content.text` is undefined.
|
||||
// Empty content.text` can also be a valid response either
|
||||
// empty or not available yet.
|
||||
let content = file.response.content;
|
||||
if (!content || typeof (content.text) == "undefined") {
|
||||
return (
|
||||
Spinner()
|
||||
);
|
||||
}
|
||||
|
||||
// Render response body data. The right representation of the data
|
||||
// is picked according to the content type.
|
||||
let groups = [];
|
||||
groups.push(this.renderFormattedResponse(file));
|
||||
groups.push(this.renderRawResponse(file));
|
||||
|
||||
// Filter out empty groups.
|
||||
groups = groups.filter(group => group);
|
||||
|
||||
// The raw response is collapsed by default if a nice formatted
|
||||
// version is available.
|
||||
if (groups.length > 1) {
|
||||
groups[1].open = false;
|
||||
}
|
||||
|
||||
return (
|
||||
DOM.div({className: "responseTabBox"},
|
||||
DOM.div({className: "panelContent"},
|
||||
NetInfoGroupList({
|
||||
groups: groups
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Helpers
|
||||
|
||||
function isLongString(text) {
|
||||
return typeof text == "object";
|
||||
}
|
||||
|
||||
// Exports from this module
|
||||
module.exports = ResponseTab;
|
||||
15
devtools/client/webconsole/net/components/size-limit.css
Normal file
15
devtools/client/webconsole/net/components/size-limit.css
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Response Size Limit */
|
||||
|
||||
.netInfoBody .netInfoSizeLimit {
|
||||
font-weight: bold;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.netInfoBody .netInfoSizeLimit .objectLink {
|
||||
color: var(--theme-highlight-blue);
|
||||
}
|
||||
62
devtools/client/webconsole/net/components/size-limit.js
Normal file
62
devtools/client/webconsole/net/components/size-limit.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* 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 React = require("devtools/client/shared/vendor/react");
|
||||
|
||||
// Shortcuts
|
||||
const DOM = React.DOM;
|
||||
const PropTypes = React.PropTypes;
|
||||
|
||||
/**
|
||||
* This template represents a size limit notification message
|
||||
* used e.g. in the Response tab when response body exceeds
|
||||
* size limit. The message contains a link allowing the user
|
||||
* to fetch the rest of the data from the backend (debugger server).
|
||||
*/
|
||||
var SizeLimit = React.createClass({
|
||||
propTypes: {
|
||||
data: PropTypes.object.isRequired,
|
||||
message: PropTypes.string.isRequired,
|
||||
link: PropTypes.string.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
resolveString: PropTypes.func.isRequired
|
||||
}),
|
||||
},
|
||||
|
||||
displayName: "SizeLimit",
|
||||
|
||||
// Event Handlers
|
||||
|
||||
onClickLimit(event) {
|
||||
let actions = this.props.actions;
|
||||
let content = this.props.data;
|
||||
|
||||
actions.resolveString(content, "text");
|
||||
},
|
||||
|
||||
// Rendering
|
||||
|
||||
render() {
|
||||
let message = this.props.message;
|
||||
let link = this.props.link;
|
||||
let reLink = /^(.*)\{\{link\}\}(.*$)/;
|
||||
let m = message.match(reLink);
|
||||
|
||||
return (
|
||||
DOM.div({className: "netInfoSizeLimit"},
|
||||
DOM.span({}, m[1]),
|
||||
DOM.a({
|
||||
className: "objectLink",
|
||||
onClick: this.onClickLimit},
|
||||
link
|
||||
),
|
||||
DOM.span({}, m[2])
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
module.exports = SizeLimit;
|
||||
26
devtools/client/webconsole/net/components/spinner.js
Normal file
26
devtools/client/webconsole/net/components/spinner.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* 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 React = require("devtools/client/shared/vendor/react");
|
||||
|
||||
// Shortcuts
|
||||
const DOM = React.DOM;
|
||||
|
||||
/**
|
||||
* This template represents a throbber displayed when the UI
|
||||
* is waiting for data coming from the backend (debugging server).
|
||||
*/
|
||||
var Spinner = React.createClass({
|
||||
displayName: "Spinner",
|
||||
|
||||
render() {
|
||||
return (
|
||||
DOM.div({className: "devtools-throbber"})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
module.exports = Spinner;
|
||||
29
devtools/client/webconsole/net/components/stacktrace-tab.js
Normal file
29
devtools/client/webconsole/net/components/stacktrace-tab.js
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/* 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 { PropTypes, createClass, createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const StackTrace = createFactory(require("devtools/client/shared/components/stack-trace"));
|
||||
|
||||
const StackTraceTab = createClass({
|
||||
displayName: "StackTraceTab",
|
||||
|
||||
propTypes: {
|
||||
data: PropTypes.object.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
onViewSourceInDebugger: PropTypes.func.isRequired
|
||||
})
|
||||
},
|
||||
|
||||
render() {
|
||||
let { stacktrace } = this.props.data.cause;
|
||||
let { actions } = this.props;
|
||||
let onViewSourceInDebugger = actions.onViewSourceInDebugger.bind(actions);
|
||||
|
||||
return StackTrace({ stacktrace, onViewSourceInDebugger });
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
module.exports = StackTraceTab;
|
||||
Loading…
Add table
Add a link
Reference in a new issue