Mypal/devtools/client/netmonitor/request-list-context-menu.js

357 lines
11 KiB
JavaScript

/* 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 NetMonitorController, NetMonitorView, gNetwork */
"use strict";
const Services = require("Services");
const { Task } = require("devtools/shared/task");
const { Curl } = require("devtools/client/shared/curl");
const { gDevTools } = require("devtools/client/framework/devtools");
const { openRequestInTab } = require("devtools/client/netmonitor/open-request-in-tab");
const Menu = require("devtools/client/framework/menu");
const MenuItem = require("devtools/client/framework/menu-item");
const { L10N } = require("./l10n");
const { formDataURI, getFormDataSections } = require("./request-utils");
loader.lazyRequireGetter(this, "HarExporter",
"devtools/client/netmonitor/har/har-exporter", true);
loader.lazyServiceGetter(this, "clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper");
loader.lazyRequireGetter(this, "NetworkHelper",
"devtools/shared/webconsole/network-helper");
function RequestListContextMenu() {}
RequestListContextMenu.prototype = {
get selectedItem() {
return NetMonitorView.RequestsMenu.selectedItem;
},
get items() {
return NetMonitorView.RequestsMenu.items;
},
/**
* Handle the context menu opening. Hide items if no request is selected.
* Since visible attribute only accept boolean value but the method call may
* return undefined, we use !! to force convert any object to boolean
*/
open({ screenX = 0, screenY = 0 } = {}) {
let selectedItem = this.selectedItem;
let menu = new Menu();
menu.append(new MenuItem({
id: "request-menu-context-copy-url",
label: L10N.getStr("netmonitor.context.copyUrl"),
accesskey: L10N.getStr("netmonitor.context.copyUrl.accesskey"),
visible: !!selectedItem,
click: () => this.copyUrl(),
}));
menu.append(new MenuItem({
id: "request-menu-context-copy-url-params",
label: L10N.getStr("netmonitor.context.copyUrlParams"),
accesskey: L10N.getStr("netmonitor.context.copyUrlParams.accesskey"),
visible: !!(selectedItem &&
NetworkHelper.nsIURL(selectedItem.attachment.url).query),
click: () => this.copyUrlParams(),
}));
menu.append(new MenuItem({
id: "request-menu-context-copy-post-data",
label: L10N.getStr("netmonitor.context.copyPostData"),
accesskey: L10N.getStr("netmonitor.context.copyPostData.accesskey"),
visible: !!(selectedItem && selectedItem.attachment.requestPostData),
click: () => this.copyPostData(),
}));
menu.append(new MenuItem({
id: "request-menu-context-copy-as-curl",
label: L10N.getStr("netmonitor.context.copyAsCurl"),
accesskey: L10N.getStr("netmonitor.context.copyAsCurl.accesskey"),
visible: !!(selectedItem && selectedItem.attachment),
click: () => this.copyAsCurl(),
}));
menu.append(new MenuItem({
type: "separator",
visible: !!selectedItem,
}));
menu.append(new MenuItem({
id: "request-menu-context-copy-request-headers",
label: L10N.getStr("netmonitor.context.copyRequestHeaders"),
accesskey: L10N.getStr("netmonitor.context.copyRequestHeaders.accesskey"),
visible: !!(selectedItem && selectedItem.attachment.requestHeaders),
click: () => this.copyRequestHeaders(),
}));
menu.append(new MenuItem({
id: "response-menu-context-copy-response-headers",
label: L10N.getStr("netmonitor.context.copyResponseHeaders"),
accesskey: L10N.getStr("netmonitor.context.copyResponseHeaders.accesskey"),
visible: !!(selectedItem && selectedItem.attachment.responseHeaders),
click: () => this.copyResponseHeaders(),
}));
menu.append(new MenuItem({
id: "request-menu-context-copy-response",
label: L10N.getStr("netmonitor.context.copyResponse"),
accesskey: L10N.getStr("netmonitor.context.copyResponse.accesskey"),
visible: !!(selectedItem &&
selectedItem.attachment.responseContent &&
selectedItem.attachment.responseContent.content.text &&
selectedItem.attachment.responseContent.content.text.length !== 0),
click: () => this.copyResponse(),
}));
menu.append(new MenuItem({
id: "request-menu-context-copy-image-as-data-uri",
label: L10N.getStr("netmonitor.context.copyImageAsDataUri"),
accesskey: L10N.getStr("netmonitor.context.copyImageAsDataUri.accesskey"),
visible: !!(selectedItem &&
selectedItem.attachment.responseContent &&
selectedItem.attachment.responseContent.content
.mimeType.includes("image/")),
click: () => this.copyImageAsDataUri(),
}));
menu.append(new MenuItem({
type: "separator",
visible: !!selectedItem,
}));
menu.append(new MenuItem({
id: "request-menu-context-copy-all-as-har",
label: L10N.getStr("netmonitor.context.copyAllAsHar"),
accesskey: L10N.getStr("netmonitor.context.copyAllAsHar.accesskey"),
visible: !!this.items.length,
click: () => this.copyAllAsHar(),
}));
menu.append(new MenuItem({
id: "request-menu-context-save-all-as-har",
label: L10N.getStr("netmonitor.context.saveAllAsHar"),
accesskey: L10N.getStr("netmonitor.context.saveAllAsHar.accesskey"),
visible: !!this.items.length,
click: () => this.saveAllAsHar(),
}));
menu.append(new MenuItem({
type: "separator",
visible: !!selectedItem,
}));
menu.append(new MenuItem({
id: "request-menu-context-resend",
label: L10N.getStr("netmonitor.context.editAndResend"),
accesskey: L10N.getStr("netmonitor.context.editAndResend.accesskey"),
visible: !!(NetMonitorController.supportsCustomRequest &&
selectedItem &&
!selectedItem.attachment.isCustom),
click: () => NetMonitorView.RequestsMenu.cloneSelectedRequest(),
}));
menu.append(new MenuItem({
type: "separator",
visible: !!selectedItem,
}));
menu.append(new MenuItem({
id: "request-menu-context-newtab",
label: L10N.getStr("netmonitor.context.newTab"),
accesskey: L10N.getStr("netmonitor.context.newTab.accesskey"),
visible: !!selectedItem,
click: () => this.openRequestInTab()
}));
menu.append(new MenuItem({
id: "request-menu-context-perf",
label: L10N.getStr("netmonitor.context.perfTools"),
accesskey: L10N.getStr("netmonitor.context.perfTools.accesskey"),
visible: !!NetMonitorController.supportsPerfStats,
click: () => NetMonitorView.toggleFrontendMode()
}));
menu.popup(screenX, screenY, NetMonitorController._toolbox);
return menu;
},
/**
* Opens selected item in a new tab.
*/
openRequestInTab() {
openRequestInTab(this.selectedItem.attachment);
},
/**
* Copy the request url from the currently selected item.
*/
copyUrl() {
clipboardHelper.copyString(this.selectedItem.attachment.url);
},
/**
* Copy the request url query string parameters from the currently
* selected item.
*/
copyUrlParams() {
let { url } = this.selectedItem.attachment;
let params = NetworkHelper.nsIURL(url).query.split("&");
let string = params.join(Services.appinfo.OS === "WINNT" ? "\r\n" : "\n");
clipboardHelper.copyString(string);
},
/**
* Copy the request form data parameters (or raw payload) from
* the currently selected item.
*/
copyPostData: Task.async(function* () {
let selected = this.selectedItem.attachment;
// Try to extract any form data parameters.
let formDataSections = yield getFormDataSections(
selected.requestHeaders,
selected.requestHeadersFromUploadStream,
selected.requestPostData,
gNetwork.getString.bind(gNetwork));
let params = [];
formDataSections.forEach(section => {
let paramsArray = NetworkHelper.parseQueryString(section);
if (paramsArray) {
params = [...params, ...paramsArray];
}
});
let string = params
.map(param => param.name + (param.value ? "=" + param.value : ""))
.join(Services.appinfo.OS === "WINNT" ? "\r\n" : "\n");
// Fall back to raw payload.
if (!string) {
let postData = selected.requestPostData.postData.text;
string = yield gNetwork.getString(postData);
if (Services.appinfo.OS !== "WINNT") {
string = string.replace(/\r/g, "");
}
}
clipboardHelper.copyString(string);
}),
/**
* Copy a cURL command from the currently selected item.
*/
copyAsCurl: Task.async(function* () {
let selected = this.selectedItem.attachment;
// Create a sanitized object for the Curl command generator.
let data = {
url: selected.url,
method: selected.method,
headers: [],
httpVersion: selected.httpVersion,
postDataText: null
};
// Fetch header values.
for (let { name, value } of selected.requestHeaders.headers) {
let text = yield gNetwork.getString(value);
data.headers.push({ name: name, value: text });
}
// Fetch the request payload.
if (selected.requestPostData) {
let postData = selected.requestPostData.postData.text;
data.postDataText = yield gNetwork.getString(postData);
}
clipboardHelper.copyString(Curl.generateCommand(data));
}),
/**
* Copy the raw request headers from the currently selected item.
*/
copyRequestHeaders() {
let selected = this.selectedItem.attachment;
let rawHeaders = selected.requestHeaders.rawHeaders.trim();
if (Services.appinfo.OS !== "WINNT") {
rawHeaders = rawHeaders.replace(/\r/g, "");
}
clipboardHelper.copyString(rawHeaders);
},
/**
* Copy the raw response headers from the currently selected item.
*/
copyResponseHeaders() {
let selected = this.selectedItem.attachment;
let rawHeaders = selected.responseHeaders.rawHeaders.trim();
if (Services.appinfo.OS !== "WINNT") {
rawHeaders = rawHeaders.replace(/\r/g, "");
}
clipboardHelper.copyString(rawHeaders);
},
/**
* Copy image as data uri.
*/
copyImageAsDataUri() {
let selected = this.selectedItem.attachment;
let { mimeType, text, encoding } = selected.responseContent.content;
gNetwork.getString(text).then(string => {
let data = formDataURI(mimeType, encoding, string);
clipboardHelper.copyString(data);
});
},
/**
* Copy response data as a string.
*/
copyResponse() {
let selected = this.selectedItem.attachment;
let text = selected.responseContent.content.text;
gNetwork.getString(text).then(string => {
clipboardHelper.copyString(string);
});
},
/**
* Copy HAR from the network panel content to the clipboard.
*/
copyAllAsHar() {
let options = this.getDefaultHarOptions();
return HarExporter.copy(options);
},
/**
* Save HAR from the network panel content to a file.
*/
saveAllAsHar() {
let options = this.getDefaultHarOptions();
return HarExporter.save(options);
},
getDefaultHarOptions() {
let form = NetMonitorController._target.form;
let title = form.title || form.url;
return {
getString: gNetwork.getString.bind(gNetwork),
view: NetMonitorView.RequestsMenu,
items: NetMonitorView.RequestsMenu.items,
title: title
};
}
};
module.exports = RequestListContextMenu;