diff --git a/devtools/client/locales/en-US/netmonitor.properties b/devtools/client/locales/en-US/netmonitor.properties index 51a3b76fbcbc..943fa5bcb3ba 100644 --- a/devtools/client/locales/en-US/netmonitor.properties +++ b/devtools/client/locales/en-US/netmonitor.properties @@ -320,3 +320,8 @@ netRequest.cookies=Cookies # LOCALIZATION NOTE (netRequest.params): A label used for URL parameters tab # This tab displays data parsed from URL query string. netRequest.params=Params + +# LOCALIZATION NOTE (netRequest.callstack): A label used for request stacktrace tab +# This tab displays the request's JavaScript stack trace. Should be identical to +# debuggerUI.tabs.callstack +netRequest.callstack=Call Stack diff --git a/devtools/client/webconsole/net/components/moz.build b/devtools/client/webconsole/net/components/moz.build index ff70b2747078..4b43dab80511 100644 --- a/devtools/client/webconsole/net/components/moz.build +++ b/devtools/client/webconsole/net/components/moz.build @@ -21,4 +21,5 @@ DevToolsModules( 'size-limit.css', 'size-limit.js', 'spinner.js', + 'stacktrace-tab.js', ) diff --git a/devtools/client/webconsole/net/components/net-info-body.js b/devtools/client/webconsole/net/components/net-info-body.js index b1b9bce9c4ac..8d7f7ae3ff39 100644 --- a/devtools/client/webconsole/net/components/net-info-body.js +++ b/devtools/client/webconsole/net/components/net-info-body.js @@ -13,6 +13,7 @@ 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 @@ -68,6 +69,11 @@ var NetInfoBody = React.createClass({ NetUtils.getHeaderValue(response.headers, "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; @@ -137,6 +143,21 @@ var NetInfoBody = React.createClass({ ); } + // 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; }, diff --git a/devtools/client/webconsole/net/components/stacktrace-tab.js b/devtools/client/webconsole/net/components/stacktrace-tab.js new file mode 100644 index 000000000000..51eb7689baae --- /dev/null +++ b/devtools/client/webconsole/net/components/stacktrace-tab.js @@ -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; diff --git a/devtools/client/webconsole/net/net-request.js b/devtools/client/webconsole/net/net-request.js index 2495e151234f..c42787cc0db3 100644 --- a/devtools/client/webconsole/net/net-request.js +++ b/devtools/client/webconsole/net/net-request.js @@ -39,7 +39,8 @@ function NetRequest(log) { NetRequest.prototype = { initialize: function (log) { - this.client = log.client; + this.client = log.consoleFrame.webConsoleClient; + this.owner = log.consoleFrame.owner; // 'this.file' field is following HAR spec. // http://www.softwareishard.com/blog/har-12-spec/ @@ -277,6 +278,10 @@ NetRequest.prototype = { return this.resolveHeaders(this.file.response.cookies); }, + onViewSourceInDebugger: function (frame) { + this.owner.viewSourceInDebugger(frame.source, frame.line); + }, + resolveHeaders: function (headers) { let promises = []; diff --git a/devtools/client/webconsole/webconsole.js b/devtools/client/webconsole/webconsole.js index 5ca93e58e388..54123b45ea60 100644 --- a/devtools/client/webconsole/webconsole.js +++ b/devtools/client/webconsole/webconsole.js @@ -1623,7 +1623,7 @@ WebConsoleFrame.prototype = { if (this.window.NetRequest) { this.window.NetRequest.onNetworkEvent({ - client: this.webConsoleClient, + consoleFrame: this, response: networkInfo, node: messageNode, update: false