diff options
Diffstat (limited to '')
-rw-r--r-- | devtools/server/actors/network-monitor/network-content.js | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/devtools/server/actors/network-monitor/network-content.js b/devtools/server/actors/network-monitor/network-content.js new file mode 100644 index 0000000000..c292d9da05 --- /dev/null +++ b/devtools/server/actors/network-monitor/network-content.js @@ -0,0 +1,144 @@ +/* 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 { Actor } = require("resource://devtools/shared/protocol.js"); +const { + networkContentSpec, +} = require("resource://devtools/shared/specs/network-content.js"); + +const lazy = {}; +ChromeUtils.defineModuleGetter( + lazy, + "NetUtil", + "resource://gre/modules/NetUtil.jsm" +); + +ChromeUtils.defineESModuleGetters(lazy, { + NetworkUtils: + "resource://devtools/shared/network-observer/NetworkUtils.sys.mjs", +}); + +loader.lazyRequireGetter( + this, + "WebConsoleUtils", + "resource://devtools/server/actors/webconsole/utils.js", + true +); + +const { + TYPES: { NETWORK_EVENT_STACKTRACE }, + getResourceWatcher, +} = require("resource://devtools/server/actors/resources/index.js"); + +/** + * This actor manages all network functionality runnning + * in the content process. + * + * @constructor + * + */ +class NetworkContentActor extends Actor { + constructor(conn, targetActor) { + super(conn, networkContentSpec); + this.targetActor = targetActor; + } + + get networkEventStackTraceWatcher() { + return getResourceWatcher(this.targetActor, NETWORK_EVENT_STACKTRACE); + } + + /** + * Send an HTTP request + * + * @param {Object} request + * The details of the HTTP Request. + * @return {Number} + * The channel id for the request + */ + async sendHTTPRequest(request) { + return new Promise(resolve => { + const { url, method, headers, body, cause } = request; + // Set the loadingNode and loadGroup to the target document - otherwise the + // request won't show up in the opened netmonitor. + const doc = this.targetActor.window.document; + + const channel = lazy.NetUtil.newChannel({ + uri: lazy.NetUtil.newURI(url), + loadingNode: doc, + securityFlags: + Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, + contentPolicyType: + lazy.NetworkUtils.stringToCauseType(cause.type) || + Ci.nsIContentPolicy.TYPE_OTHER, + }); + + channel.QueryInterface(Ci.nsIHttpChannel); + channel.loadGroup = doc.documentLoadGroup; + channel.loadFlags |= + Ci.nsIRequest.LOAD_BYPASS_CACHE | + Ci.nsIRequest.INHIBIT_CACHING | + Ci.nsIRequest.LOAD_ANONYMOUS; + + if (method == "CONNECT") { + throw new Error( + "The CONNECT method is restricted and cannot be sent by devtools" + ); + } + channel.requestMethod = method; + + if (headers) { + for (const { name, value } of headers) { + if (name.toLowerCase() == "referer") { + // The referer header and referrerInfo object should always match. So + // if we want to set the header from privileged context, we should set + // referrerInfo. The referrer header will get set internally. + channel.setNewReferrerInfo( + value, + Ci.nsIReferrerInfo.UNSAFE_URL, + true + ); + } else { + channel.setRequestHeader(name, value, false); + } + } + } + + if (body) { + channel.QueryInterface(Ci.nsIUploadChannel2); + const bodyStream = Cc[ + "@mozilla.org/io/string-input-stream;1" + ].createInstance(Ci.nsIStringInputStream); + bodyStream.setData(body, body.length); + channel.explicitSetUploadStream(bodyStream, null, -1, method, false); + } + + // Make sure the fetch has completed before sending the channel id, + // so that there is a higher possibilty that the request get into the + // redux store beforehand (but this does not gurantee that). + lazy.NetUtil.asyncFetch(channel, () => + resolve({ channelId: channel.channelId }) + ); + }); + } + + /** + * Gets the stacktrace for the specified network resource. + * @param {Number} resourceId + * The id for the network resource + * @return {Object} + * The response packet - stack trace. + */ + getStackTrace(resourceId) { + if (!this.networkEventStackTraceWatcher) { + throw new Error("Not listening for network event stacktraces"); + } + const stacktrace = + this.networkEventStackTraceWatcher.getStackTrace(resourceId); + return WebConsoleUtils.removeFramesAboveDebuggerEval(stacktrace); + } +} + +exports.NetworkContentActor = NetworkContentActor; |