/* 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/. */ /* globals window, dumpn, gNetwork, $, EVENTS, NetMonitorView */ "use strict"; const {Task} = require("devtools/shared/task"); const {writeHeaderText, getKeyWithEvent} = require("./request-utils"); loader.lazyRequireGetter(this, "NetworkHelper", "devtools/shared/webconsole/network-helper"); /** * Functions handling the custom request view. */ function CustomRequestView() { dumpn("CustomRequestView was instantiated"); } CustomRequestView.prototype = { /** * Initialization function, called when the network monitor is started. */ initialize: function () { dumpn("Initializing the CustomRequestView"); this.updateCustomRequestEvent = getKeyWithEvent(this.onUpdate.bind(this)); $("#custom-pane").addEventListener("input", this.updateCustomRequestEvent, false); }, /** * Destruction function, called when the network monitor is closed. */ destroy: function () { dumpn("Destroying the CustomRequestView"); $("#custom-pane").removeEventListener("input", this.updateCustomRequestEvent, false); }, /** * Populates this view with the specified data. * * @param object data * The data source (this should be the attachment of a request item). * @return object * Returns a promise that resolves upon population the view. */ populate: Task.async(function* (data) { $("#custom-url-value").value = data.url; $("#custom-method-value").value = data.method; this.updateCustomQuery(data.url); if (data.requestHeaders) { let headers = data.requestHeaders.headers; $("#custom-headers-value").value = writeHeaderText(headers); } if (data.requestPostData) { let postData = data.requestPostData.postData.text; $("#custom-postdata-value").value = yield gNetwork.getString(postData); } window.emit(EVENTS.CUSTOMREQUESTVIEW_POPULATED); }), /** * Handle user input in the custom request form. * * @param object field * the field that the user updated. */ onUpdate: function (field) { let selectedItem = NetMonitorView.RequestsMenu.selectedItem; let value; switch (field) { case "method": value = $("#custom-method-value").value.trim(); selectedItem.attachment.method = value; break; case "url": value = $("#custom-url-value").value; this.updateCustomQuery(value); selectedItem.attachment.url = value; break; case "query": let query = $("#custom-query-value").value; this.updateCustomUrl(query); field = "url"; value = $("#custom-url-value").value; selectedItem.attachment.url = value; break; case "body": value = $("#custom-postdata-value").value; selectedItem.attachment.requestPostData = { postData: { text: value } }; break; case "headers": let headersText = $("#custom-headers-value").value; value = parseHeadersText(headersText); selectedItem.attachment.requestHeaders = { headers: value }; break; } NetMonitorView.RequestsMenu.updateMenuView(selectedItem, field, value); }, /** * Update the query string field based on the url. * * @param object url * The URL to extract query string from. */ updateCustomQuery: function (url) { let paramsArray = NetworkHelper.parseQueryString( NetworkHelper.nsIURL(url).query); if (!paramsArray) { $("#custom-query").hidden = true; return; } $("#custom-query").hidden = false; $("#custom-query-value").value = writeQueryText(paramsArray); }, /** * Update the url based on the query string field. * * @param object queryText * The contents of the query string field. */ updateCustomUrl: function (queryText) { let params = parseQueryText(queryText); let queryString = writeQueryString(params); let url = $("#custom-url-value").value; let oldQuery = NetworkHelper.nsIURL(url).query; let path = url.replace(oldQuery, queryString); $("#custom-url-value").value = path; } }; /** * Parse text representation of multiple HTTP headers. * * @param string text * Text of headers * @return array * Array of headers info {name, value} */ function parseHeadersText(text) { return parseRequestText(text, "\\S+?", ":"); } /** * Parse readable text list of a query string. * * @param string text * Text of query string represetation * @return array * Array of query params {name, value} */ function parseQueryText(text) { return parseRequestText(text, ".+?", "="); } /** * Parse a text representation of a name[divider]value list with * the given name regex and divider character. * * @param string text * Text of list * @return array * Array of headers info {name, value} */ function parseRequestText(text, namereg, divider) { let regex = new RegExp("(" + namereg + ")\\" + divider + "\\s*(.+)"); let pairs = []; for (let line of text.split("\n")) { let matches; if (matches = regex.exec(line)) { // eslint-disable-line let [, name, value] = matches; pairs.push({name: name, value: value}); } } return pairs; } /** * Write out a list of query params into a chunk of text * * @param array params * Array of query params {name, value} * @return string * List of query params in text format */ function writeQueryText(params) { return params.map(({name, value}) => name + "=" + value).join("\n"); } /** * Write out a list of query params into a query string * * @param array params * Array of query params {name, value} * @return string * Query string that can be appended to a url. */ function writeQueryString(params) { return params.map(({name, value}) => name + "=" + value).join("&"); } exports.CustomRequestView = CustomRequestView;