Bug 966209 - Add a context menu for images in the Response panel. r?rickychien
MozReview-Commit-ID: B3aNoGxVBNQ
--- a/devtools/client/locales/en-US/netmonitor.properties
+++ b/devtools/client/locales/en-US/netmonitor.properties
@@ -715,16 +715,25 @@ netmonitor.context.copyResponse.accesske
# LOCALIZATION NOTE (netmonitor.context.copyImageAsDataUri): This is the label displayed
# on the context menu that copies the selected image as data uri
netmonitor.context.copyImageAsDataUri=Copy Image as Data URI
# LOCALIZATION NOTE (netmonitor.context.copyImageAsDataUri.accesskey): This is the access key
# for the Copy Image As Data URI menu item displayed in the context menu for a request
netmonitor.context.copyImageAsDataUri.accesskey=I
+# LOCALIZATION NOTE (netmonitor.context.saveImageAs): This is the label displayed
+# on the context menu that save the Image
+netmonitor.context.saveImageAs=Save Image As
+
+# LOCALIZATION NOTE (netmonitor.context.copyImageAsDataUri.accesskey): This is the access key
+# for the Copy Image As Data URI menu item displayed in the context menu for a request
+netmonitor.context.saveImageAs.accesskey=V
+
+
# LOCALIZATION NOTE (netmonitor.context.copyAllAsHar): This is the label displayed
# on the context menu that copies all as HAR format
netmonitor.context.copyAllAsHar=Copy All As HAR
# LOCALIZATION NOTE (netmonitor.context.copyAllAsHar.accesskey): This is the access key
# for the Copy All As HAR menu item displayed in the context menu for a network panel
netmonitor.context.copyAllAsHar.accesskey=O
--- a/devtools/client/netmonitor/src/request-list-context-menu.js
+++ b/devtools/client/netmonitor/src/request-list-context-menu.js
@@ -4,16 +4,17 @@
"use strict";
const Services = require("Services");
const { Curl } = require("devtools/client/shared/curl");
const { gDevTools } = require("devtools/client/framework/devtools");
const Menu = require("devtools/client/framework/menu");
const MenuItem = require("devtools/client/framework/menu-item");
+const FileSaver = require("devtools/client/shared/file-saver");
const clipboardHelper = require("devtools/shared/platform/clipboard");
const { HarExporter } = require("./har/har-exporter");
const { getLongString } = require("./utils/client");
const { L10N } = require("./utils/l10n");
const {
formDataURI,
getFormDataSections,
getUrlQuery,
@@ -150,16 +151,26 @@ RequestListContextMenu.prototype = {
id: "request-list-context-save-all-as-har",
label: L10N.getStr("netmonitor.context.saveAllAsHar"),
accesskey: L10N.getStr("netmonitor.context.saveAllAsHar.accesskey"),
visible: this.sortedRequests.size > 0,
click: () => this.saveAllAsHar(),
}));
menu.append(new MenuItem({
+ id: "request-list-context-save-image-as",
+ label: L10N.getStr("netmonitor.context.saveImageAs"),
+ accesskey: L10N.getStr("netmonitor.context.saveImageAs.accesskey"),
+ visible: !!(selectedRequest &&
+ selectedRequest.responseContent &&
+ selectedRequest.responseContent.content.mimeType.includes("image/")),
+ click: () => this.saveImageAs(),
+ }));
+
+ menu.append(new MenuItem({
type: "separator",
visible: !!(window.NetMonitorController.supportsCustomRequest &&
selectedRequest && !selectedRequest.isCustom),
}));
menu.append(new MenuItem({
id: "request-list-context-resend",
label: L10N.getStr("netmonitor.context.editAndResend"),
@@ -318,16 +329,36 @@ RequestListContextMenu.prototype = {
getLongString(text).then(string => {
let data = formDataURI(mimeType, encoding, string);
clipboardHelper.copyString(data);
});
},
/**
+ * Save image as.
+ */
+ saveImageAs() {
+ const { encoding, text } = this.selectedRequest.responseContent.content;
+ let fileName = this.selectedRequest.urlDetails.baseNameWithQuery;
+ let data;
+ if (encoding === "base64") {
+ let decoded = atob(text);
+ data = new Uint8Array(decoded.length);
+ for (let i = 0; i < decoded.length; ++i) {
+ data[i] = decoded.charCodeAt(i);
+ }
+ } else {
+ data = text;
+ }
+ let blob = new Blob([data]);
+ FileSaver.saveAs(blob, fileName, document);
+ },
+
+ /**
* Copy response data as a string.
*/
copyResponse() {
const { text } = this.selectedRequest.responseContent.content;
getLongString(text).then(string => {
clipboardHelper.copyString(string);
});