Bug 1571342 - unify save paths for console and netmonitor and fix the latter to not do docshell loads, r=Honza,nchevobbe
Differential Revision: https://phabricator.services.mozilla.com/D41858
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
const FileSaver = require("devtools/client/shared/file-saver");
|
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||||
const JSZip = require("devtools/client/shared/vendor/jszip");
|
const JSZip = require("devtools/client/shared/vendor/jszip");
|
||||||
const clipboardHelper = require("devtools/shared/platform/clipboard");
|
const clipboardHelper = require("devtools/shared/platform/clipboard");
|
||||||
const { HarBuilder } = require("./har-builder");
|
const { HarBuilder } = require("./har-builder");
|
||||||
@@ -86,16 +86,14 @@ const HarExporter = {
|
|||||||
.generateAsync({
|
.generateAsync({
|
||||||
compression: "DEFLATE",
|
compression: "DEFLATE",
|
||||||
platform: Services.appinfo.OS === "WINNT" ? "DOS" : "UNIX",
|
platform: Services.appinfo.OS === "WINNT" ? "DOS" : "UNIX",
|
||||||
type: "blob",
|
type: "uint8array",
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
data = new TextEncoder().encode(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
fileName = `${fileName}${compress ? ".zip" : ""}`;
|
fileName = `${fileName}${compress ? ".zip" : ""}`;
|
||||||
const blob = compress
|
DevToolsUtils.saveAs(window, data, fileName);
|
||||||
? data
|
|
||||||
: new Blob([data], { type: "application/json" });
|
|
||||||
|
|
||||||
FileSaver.saveAs(blob, fileName, document);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
formatDate(date) {
|
formatDate(date) {
|
||||||
|
|||||||
@@ -15,12 +15,7 @@ const {
|
|||||||
} = require("../utils/request-utils");
|
} = require("../utils/request-utils");
|
||||||
|
|
||||||
loader.lazyRequireGetter(this, "Curl", "devtools/client/shared/curl", true);
|
loader.lazyRequireGetter(this, "Curl", "devtools/client/shared/curl", true);
|
||||||
loader.lazyRequireGetter(
|
loader.lazyRequireGetter(this, "saveAs", "devtools/shared/DevToolsUtils", true);
|
||||||
this,
|
|
||||||
"saveAs",
|
|
||||||
"devtools/client/shared/file-saver",
|
|
||||||
true
|
|
||||||
);
|
|
||||||
loader.lazyRequireGetter(
|
loader.lazyRequireGetter(
|
||||||
this,
|
this,
|
||||||
"copyString",
|
"copyString",
|
||||||
@@ -610,9 +605,9 @@ class RequestListContextMenu {
|
|||||||
data[i] = decoded.charCodeAt(i);
|
data[i] = decoded.charCodeAt(i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data = text;
|
data = new TextEncoder().encode(text);
|
||||||
}
|
}
|
||||||
saveAs(new Blob([data]), fileName, document);
|
saveAs(window, data, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
/* 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/. */
|
|
||||||
|
|
||||||
/* eslint-env browser */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTML5 file saver to provide a standard download interface with a "Save As"
|
|
||||||
* dialog
|
|
||||||
*
|
|
||||||
* @param {object} blob - A blob object will be downloaded
|
|
||||||
* @param {string} filename - Given a file name which will display in "Save As" dialog
|
|
||||||
* @param {object} document - Optional. A HTML document for creating a temporary anchor
|
|
||||||
* for triggering a file download.
|
|
||||||
*/
|
|
||||||
function saveAs(blob, filename = "", doc = document) {
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
const a = doc.createElement("a");
|
|
||||||
doc.body.appendChild(a);
|
|
||||||
a.style = "display: none";
|
|
||||||
a.href = url;
|
|
||||||
a.download = filename;
|
|
||||||
a.click();
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
a.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.saveAs = saveAs;
|
|
||||||
@@ -34,7 +34,6 @@ DevToolsModules(
|
|||||||
'DOMHelpers.jsm',
|
'DOMHelpers.jsm',
|
||||||
'enum.js',
|
'enum.js',
|
||||||
'events.js',
|
'events.js',
|
||||||
'file-saver.js',
|
|
||||||
'focus.js',
|
'focus.js',
|
||||||
'getjson.js',
|
'getjson.js',
|
||||||
'inplace-editor.js',
|
'inplace-editor.js',
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ async function exportAllToFile(hud, message) {
|
|||||||
]);
|
]);
|
||||||
MockFilePicker.setFiles([nsiFile]);
|
MockFilePicker.setFiles([nsiFile]);
|
||||||
exportFile.click();
|
exportFile.click();
|
||||||
|
info("Exporting to file");
|
||||||
|
|
||||||
// The file may not be ready yet.
|
// The file may not be ready yet.
|
||||||
await waitFor(() => OS.File.exists(nsiFile.path));
|
await waitFor(() => OS.File.exists(nsiFile.path));
|
||||||
|
|||||||
@@ -14,18 +14,7 @@ const { MESSAGE_SOURCE } = require("devtools/client/webconsole/constants");
|
|||||||
const clipboardHelper = require("devtools/shared/platform/clipboard");
|
const clipboardHelper = require("devtools/shared/platform/clipboard");
|
||||||
const { l10n } = require("devtools/client/webconsole/utils/messages");
|
const { l10n } = require("devtools/client/webconsole/utils/messages");
|
||||||
|
|
||||||
loader.lazyRequireGetter(
|
loader.lazyRequireGetter(this, "saveAs", "devtools/shared/DevToolsUtils", true);
|
||||||
this,
|
|
||||||
"showSaveFileDialog",
|
|
||||||
"devtools/shared/DevToolsUtils",
|
|
||||||
true
|
|
||||||
);
|
|
||||||
loader.lazyRequireGetter(
|
|
||||||
this,
|
|
||||||
"saveFileStream",
|
|
||||||
"devtools/shared/DevToolsUtils",
|
|
||||||
true
|
|
||||||
);
|
|
||||||
loader.lazyRequireGetter(
|
loader.lazyRequireGetter(
|
||||||
this,
|
this,
|
||||||
"openContentLink",
|
"openContentLink",
|
||||||
@@ -255,22 +244,16 @@ function createContextMenu(
|
|||||||
id: "console-menu-export-file",
|
id: "console-menu-export-file",
|
||||||
label: l10n.getStr("webconsole.menu.exportSubmenu.exportFile.label"),
|
label: l10n.getStr("webconsole.menu.exportSubmenu.exportFile.label"),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
click: async () => {
|
// Note: not async, but returns a promise for the actual save.
|
||||||
|
click: () => {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
const suggestedName =
|
const suggestedName =
|
||||||
`console-export-${date.getFullYear()}-` +
|
`console-export-${date.getFullYear()}-` +
|
||||||
`${date.getMonth() + 1}-${date.getDate()}_${date.getHours()}-` +
|
`${date.getMonth() + 1}-${date.getDate()}_${date.getHours()}-` +
|
||||||
`${date.getMinutes()}-${date.getSeconds()}.txt`;
|
`${date.getMinutes()}-${date.getSeconds()}.txt`;
|
||||||
const returnFile = await showSaveFileDialog(win, suggestedName);
|
|
||||||
const converter = Cc[
|
|
||||||
"@mozilla.org/intl/scriptableunicodeconverter"
|
|
||||||
].createInstance(Ci.nsIScriptableUnicodeConverter);
|
|
||||||
converter.charset = "UTF-8";
|
|
||||||
const webconsoleOutput = parentNode.querySelector(".webconsole-output");
|
const webconsoleOutput = parentNode.querySelector(".webconsole-output");
|
||||||
const istream = converter.convertToInputStream(
|
const data = new TextEncoder().encode(getElementText(webconsoleOutput));
|
||||||
getElementText(webconsoleOutput)
|
return saveAs(window, data, suggestedName);
|
||||||
);
|
|
||||||
return saveFileStream(returnFile, istream);
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -781,21 +781,25 @@ exports.openFileStream = function(filePath) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the file at the given path for writing.
|
* Save the given data to disk after asking the user where to do so.
|
||||||
*
|
*
|
||||||
* @param {String} filePath
|
* @param {Window} parentWindow
|
||||||
|
* The parent window to use to display the filepicker.
|
||||||
|
* @param {UInt8Array} dataArray
|
||||||
|
* The data to write to the file.
|
||||||
|
* @param {String} fileName
|
||||||
|
* The suggested filename.
|
||||||
*/
|
*/
|
||||||
exports.saveFileStream = function(filePath, istream) {
|
exports.saveAs = async function(parentWindow, dataArray, fileName = "") {
|
||||||
return new Promise((resolve, reject) => {
|
let returnFile;
|
||||||
const ostream = FileUtils.openSafeFileOutputStream(filePath);
|
try {
|
||||||
NetUtil.asyncCopy(istream, ostream, status => {
|
returnFile = await exports.showSaveFileDialog(parentWindow, fileName);
|
||||||
if (!components.isSuccessCode(status)) {
|
} catch (ex) {
|
||||||
reject(new Error(`Could not save "${filePath}"`));
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
FileUtils.closeSafeFileOutputStream(ostream);
|
await OS.File.writeAtomic(returnFile.path, dataArray, {
|
||||||
resolve();
|
tmpPath: returnFile.path + ".tmp",
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Tests for DevToolsUtils.saveFileStream file:
|
|
||||||
|
|
||||||
const { FileUtils } = ChromeUtils.import(
|
|
||||||
"resource://gre/modules/FileUtils.jsm"
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that a file is properly saved using the saveFileStream function
|
|
||||||
*/
|
|
||||||
add_task(async function test_save_file() {
|
|
||||||
const testText = "This is a text";
|
|
||||||
const fileName = "test_console_save-file-" + Math.random();
|
|
||||||
const file = FileUtils.getFile("TmpD", [fileName]);
|
|
||||||
info("Test creating temporary file: " + file.path);
|
|
||||||
await DevToolsUtils.saveFileStream(file, convertToInputStream(testText));
|
|
||||||
Assert.ok(file.exists(), "Checking if test file exists");
|
|
||||||
const { content } = await DevToolsUtils.fetch(file.path);
|
|
||||||
deepEqual(content, testText, "The content was correct.");
|
|
||||||
cleanup(fileName);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a string to an input stream.
|
|
||||||
* @param String content
|
|
||||||
* @return nsIInputStream
|
|
||||||
*/
|
|
||||||
function convertToInputStream(content) {
|
|
||||||
const converter = Cc[
|
|
||||||
"@mozilla.org/intl/scriptableunicodeconverter"
|
|
||||||
].createInstance(Ci.nsIScriptableUnicodeConverter);
|
|
||||||
converter.charset = "UTF-8";
|
|
||||||
return converter.convertToInputStream(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the temporary file after the test completes.
|
|
||||||
*/
|
|
||||||
function cleanup(fileName) {
|
|
||||||
const file = FileUtils.getFile("TmpD", [fileName]);
|
|
||||||
registerCleanupFunction(() => {
|
|
||||||
file.remove(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -33,7 +33,6 @@ run-if = nightly_build
|
|||||||
[test_safeErrorString.js]
|
[test_safeErrorString.js]
|
||||||
[test_defineLazyPrototypeGetter.js]
|
[test_defineLazyPrototypeGetter.js]
|
||||||
[test_console_filtering.js]
|
[test_console_filtering.js]
|
||||||
[test_console_save-file.js]
|
|
||||||
[test_pluralForm-english.js]
|
[test_pluralForm-english.js]
|
||||||
[test_pluralForm-makeGetter.js]
|
[test_pluralForm-makeGetter.js]
|
||||||
[test_prettifyCSS.js]
|
[test_prettifyCSS.js]
|
||||||
|
|||||||
Reference in New Issue
Block a user