diff options
Diffstat (limited to 'devtools/client/netmonitor/request-utils.js')
-rw-r--r-- | devtools/client/netmonitor/request-utils.js | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/devtools/client/netmonitor/request-utils.js b/devtools/client/netmonitor/request-utils.js new file mode 100644 index 000000000..ba54efb4f --- /dev/null +++ b/devtools/client/netmonitor/request-utils.js @@ -0,0 +1,185 @@ +"use strict"; +/* eslint-disable mozilla/reject-some-requires */ +const { Ci } = require("chrome"); +const { KeyCodes } = require("devtools/client/shared/keycodes"); +const { Task } = require("devtools/shared/task"); +const NetworkHelper = require("devtools/shared/webconsole/network-helper"); + +/** + * Helper method to get a wrapped function which can be bound to as + * an event listener directly and is executed only when data-key is + * present in event.target. + * + * @param function callback + * Function to execute execute when data-key + * is present in event.target. + * @param bool onlySpaceOrReturn + * Flag to indicate if callback should only be called + when the space or return button is pressed + * @return function + * Wrapped function with the target data-key as the first argument + * and the event as the second argument. + */ +exports.getKeyWithEvent = function (callback, onlySpaceOrReturn) { + return function (event) { + let key = event.target.getAttribute("data-key"); + let filterKeyboardEvent = !onlySpaceOrReturn || + event.keyCode === KeyCodes.DOM_VK_SPACE || + event.keyCode === KeyCodes.DOM_VK_RETURN; + + if (key && filterKeyboardEvent) { + callback.call(null, key); + } + }; +}; + +/** + * Extracts any urlencoded form data sections (e.g. "?foo=bar&baz=42") from a + * POST request. + * + * @param object headers + * The "requestHeaders". + * @param object uploadHeaders + * The "requestHeadersFromUploadStream". + * @param object postData + * The "requestPostData". + * @param object getString + Callback to retrieve a string from a LongStringGrip. + * @return array + * A promise that is resolved with the extracted form data. + */ +exports.getFormDataSections = Task.async(function* (headers, uploadHeaders, postData, + getString) { + let formDataSections = []; + + let { headers: requestHeaders } = headers; + let { headers: payloadHeaders } = uploadHeaders; + let allHeaders = [...payloadHeaders, ...requestHeaders]; + + let contentTypeHeader = allHeaders.find(e => { + return e.name.toLowerCase() == "content-type"; + }); + + let contentTypeLongString = contentTypeHeader ? contentTypeHeader.value : ""; + + let contentType = yield getString(contentTypeLongString); + + if (contentType.includes("x-www-form-urlencoded")) { + let postDataLongString = postData.postData.text; + let text = yield getString(postDataLongString); + + for (let section of text.split(/\r\n|\r|\n/)) { + // Before displaying it, make sure this section of the POST data + // isn't a line containing upload stream headers. + if (payloadHeaders.every(header => !section.startsWith(header.name))) { + formDataSections.push(section); + } + } + } + + return formDataSections; +}); + +/** + * Form a data: URI given a mime type, encoding, and some text. + * + * @param {String} mimeType the mime type + * @param {String} encoding the encoding to use; if not set, the + * text will be base64-encoded. + * @param {String} text the text of the URI. + * @return {String} a data: URI + */ +exports.formDataURI = function (mimeType, encoding, text) { + if (!encoding) { + encoding = "base64"; + text = btoa(text); + } + return "data:" + mimeType + ";" + encoding + "," + text; +}; + +/** + * Write out a list of headers into a chunk of text + * + * @param array headers + * Array of headers info {name, value} + * @return string text + * List of headers in text format + */ +exports.writeHeaderText = function (headers) { + return headers.map(({name, value}) => name + ": " + value).join("\n"); +}; + +/** + * Helper for getting an abbreviated string for a mime type. + * + * @param string mimeType + * @return string + */ +exports.getAbbreviatedMimeType = function (mimeType) { + if (!mimeType) { + return ""; + } + return (mimeType.split(";")[0].split("/")[1] || "").split("+")[0]; +}; + +/** + * Helpers for getting details about an nsIURL. + * + * @param nsIURL | string url + * @return string + */ +exports.getUriNameWithQuery = function (url) { + if (!(url instanceof Ci.nsIURL)) { + url = NetworkHelper.nsIURL(url); + } + + let name = NetworkHelper.convertToUnicode( + unescape(url.fileName || url.filePath || "/")); + let query = NetworkHelper.convertToUnicode(unescape(url.query)); + + return name + (query ? "?" + query : ""); +}; + +exports.getUriHostPort = function (url) { + if (!(url instanceof Ci.nsIURL)) { + url = NetworkHelper.nsIURL(url); + } + return NetworkHelper.convertToUnicode(unescape(url.hostPort)); +}; + +exports.getUriHost = function (url) { + return exports.getUriHostPort(url).replace(/:\d+$/, ""); +}; + +/** + * Convert a nsIContentPolicy constant to a display string + */ +const LOAD_CAUSE_STRINGS = { + [Ci.nsIContentPolicy.TYPE_INVALID]: "invalid", + [Ci.nsIContentPolicy.TYPE_OTHER]: "other", + [Ci.nsIContentPolicy.TYPE_SCRIPT]: "script", + [Ci.nsIContentPolicy.TYPE_IMAGE]: "img", + [Ci.nsIContentPolicy.TYPE_STYLESHEET]: "stylesheet", + [Ci.nsIContentPolicy.TYPE_OBJECT]: "object", + [Ci.nsIContentPolicy.TYPE_DOCUMENT]: "document", + [Ci.nsIContentPolicy.TYPE_SUBDOCUMENT]: "subdocument", + [Ci.nsIContentPolicy.TYPE_REFRESH]: "refresh", + [Ci.nsIContentPolicy.TYPE_XBL]: "xbl", + [Ci.nsIContentPolicy.TYPE_PING]: "ping", + [Ci.nsIContentPolicy.TYPE_XMLHTTPREQUEST]: "xhr", + [Ci.nsIContentPolicy.TYPE_OBJECT_SUBREQUEST]: "objectSubdoc", + [Ci.nsIContentPolicy.TYPE_DTD]: "dtd", + [Ci.nsIContentPolicy.TYPE_FONT]: "font", + [Ci.nsIContentPolicy.TYPE_MEDIA]: "media", + [Ci.nsIContentPolicy.TYPE_WEBSOCKET]: "websocket", + [Ci.nsIContentPolicy.TYPE_CSP_REPORT]: "csp", + [Ci.nsIContentPolicy.TYPE_XSLT]: "xslt", + [Ci.nsIContentPolicy.TYPE_BEACON]: "beacon", + [Ci.nsIContentPolicy.TYPE_FETCH]: "fetch", + [Ci.nsIContentPolicy.TYPE_IMAGESET]: "imageset", + [Ci.nsIContentPolicy.TYPE_WEB_MANIFEST]: "webManifest" +}; + +exports.loadCauseString = function (causeType) { + return LOAD_CAUSE_STRINGS[causeType] || "unknown"; +}; |