diff options
Diffstat (limited to 'devtools/client/netmonitor/har/har-utils.js')
-rw-r--r-- | devtools/client/netmonitor/har/har-utils.js | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/devtools/client/netmonitor/har/har-utils.js b/devtools/client/netmonitor/har/har-utils.js new file mode 100644 index 000000000..aa9bd3811 --- /dev/null +++ b/devtools/client/netmonitor/har/har-utils.js @@ -0,0 +1,189 @@ +/* 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/. */ + +"use strict"; +/* eslint-disable mozilla/reject-some-requires */ +const { Ci, Cc, CC } = require("chrome"); +/* eslint-disable mozilla/reject-some-requires */ +const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyGetter(this, "dirService", function () { + return Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties); +}); + +XPCOMUtils.defineLazyGetter(this, "ZipWriter", function () { + return CC("@mozilla.org/zipwriter;1", "nsIZipWriter"); +}); + +XPCOMUtils.defineLazyGetter(this, "LocalFile", function () { + return new CC("@mozilla.org/file/local;1", "nsILocalFile", "initWithPath"); +}); + +XPCOMUtils.defineLazyGetter(this, "getMostRecentBrowserWindow", function () { + return require("sdk/window/utils").getMostRecentBrowserWindow; +}); + +const nsIFilePicker = Ci.nsIFilePicker; + +const OPEN_FLAGS = { + RDONLY: parseInt("0x01", 16), + WRONLY: parseInt("0x02", 16), + CREATE_FILE: parseInt("0x08", 16), + APPEND: parseInt("0x10", 16), + TRUNCATE: parseInt("0x20", 16), + EXCL: parseInt("0x80", 16) +}; + +/** + * Helper API for HAR export features. + */ +var HarUtils = { + /** + * Open File Save As dialog and let the user pick the proper file + * location for generated HAR log. + */ + getTargetFile: function (fileName, jsonp, compress) { + let browser = getMostRecentBrowserWindow(); + + let fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker); + fp.init(browser, null, nsIFilePicker.modeSave); + fp.appendFilter( + "HTTP Archive Files", "*.har; *.harp; *.json; *.jsonp; *.zip"); + fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText); + fp.filterIndex = 1; + + fp.defaultString = this.getHarFileName(fileName, jsonp, compress); + + let rv = fp.show(); + if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { + return fp.file; + } + + return null; + }, + + getHarFileName: function (defaultFileName, jsonp, compress) { + let extension = jsonp ? ".harp" : ".har"; + + // Read more about toLocaleFormat & format string. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleFormat + let now = new Date(); + let name = now.toLocaleFormat(defaultFileName); + name = name.replace(/\:/gm, "-", ""); + name = name.replace(/\//gm, "_", ""); + + let fileName = name + extension; + + // Default file extension is zip if compressing is on. + if (compress) { + fileName += ".zip"; + } + + return fileName; + }, + + /** + * Save HAR string into a given file. The file might be compressed + * if specified in the options. + * + * @param {File} file Target file where the HAR string (JSON) + * should be stored. + * @param {String} jsonString HAR data (JSON or JSONP) + * @param {Boolean} compress The result file is zipped if set to true. + */ + saveToFile: function (file, jsonString, compress) { + let openFlags = OPEN_FLAGS.WRONLY | OPEN_FLAGS.CREATE_FILE | + OPEN_FLAGS.TRUNCATE; + + try { + let foStream = Cc["@mozilla.org/network/file-output-stream;1"] + .createInstance(Ci.nsIFileOutputStream); + + let permFlags = parseInt("0666", 8); + foStream.init(file, openFlags, permFlags, 0); + + let convertor = Cc["@mozilla.org/intl/converter-output-stream;1"] + .createInstance(Ci.nsIConverterOutputStream); + convertor.init(foStream, "UTF-8", 0, 0); + + // The entire jsonString can be huge so, write the data in chunks. + let chunkLength = 1024 * 1024; + for (let i = 0; i <= jsonString.length; i++) { + let data = jsonString.substr(i, chunkLength + 1); + if (data) { + convertor.writeString(data); + } + + i = i + chunkLength; + } + + // this closes foStream + convertor.close(); + } catch (err) { + console.error(err); + return false; + } + + // If no compressing then bail out. + if (!compress) { + return true; + } + + // Remember name of the original file, it'll be replaced by a zip file. + let originalFilePath = file.path; + let originalFileName = file.leafName; + + try { + // Rename using unique name (the file is going to be removed). + file.moveTo(null, "temp" + (new Date()).getTime() + "temphar"); + + // Create compressed file with the original file path name. + let zipFile = Cc["@mozilla.org/file/local;1"] + .createInstance(Ci.nsILocalFile); + zipFile.initWithPath(originalFilePath); + + // The file within the zipped file doesn't use .zip extension. + let fileName = originalFileName; + if (fileName.indexOf(".zip") == fileName.length - 4) { + fileName = fileName.substr(0, fileName.indexOf(".zip")); + } + + let zip = new ZipWriter(); + zip.open(zipFile, openFlags); + zip.addEntryFile(fileName, Ci.nsIZipWriter.COMPRESSION_DEFAULT, + file, false); + zip.close(); + + // Remove the original file (now zipped). + file.remove(true); + return true; + } catch (err) { + console.error(err); + + // Something went wrong (disk space?) rename the original file back. + file.moveTo(null, originalFileName); + } + + return false; + }, + + getLocalDirectory: function (path) { + let dir; + + if (!path) { + dir = dirService.get("ProfD", Ci.nsILocalFile); + dir.append("har"); + dir.append("logs"); + } else { + dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); + dir.initWithPath(path); + } + + return dir; + }, +}; + +// Exports from this module +exports.HarUtils = HarUtils; |