har-utils.js (4727B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 ChromeUtils.defineLazyGetter(this, "ZipWriter", function () { 8 return Components.Constructor("@mozilla.org/zipwriter;1", "nsIZipWriter"); 9 }); 10 11 const OPEN_FLAGS = { 12 RDONLY: parseInt("0x01", 16), 13 WRONLY: parseInt("0x02", 16), 14 CREATE_FILE: parseInt("0x08", 16), 15 APPEND: parseInt("0x10", 16), 16 TRUNCATE: parseInt("0x20", 16), 17 EXCL: parseInt("0x80", 16), 18 }; 19 20 function formatDate(date) { 21 const year = String(date.getFullYear() % 100).padStart(2, "0"); 22 const month = String(date.getMonth() + 1).padStart(2, "0"); 23 const day = String(date.getDate()).padStart(2, "0"); 24 const hour = String(date.getHours()).padStart(2, "0"); 25 const minutes = String(date.getMinutes()).padStart(2, "0"); 26 const seconds = String(date.getSeconds()).padStart(2, "0"); 27 28 return `${year}-${month}-${day} ${hour}-${minutes}-${seconds}`; 29 } 30 31 /** 32 * Helper API for HAR export features. 33 */ 34 var HarUtils = { 35 getHarFileName(defaultFileName, jsonp, compress, hostname, pathname = "") { 36 const extension = jsonp ? ".harp" : ".har"; 37 38 const now = new Date(); 39 let name = defaultFileName.replace(/%date/g, formatDate(now)); 40 name = name.replace(/%hostname/g, hostname + pathname); 41 name = name.replace(/\:/gm, "-", ""); 42 name = name.replace(/\//gm, "_", ""); 43 44 let fileName = name + extension; 45 46 // Default file extension is zip if compressing is on. 47 if (compress) { 48 fileName += ".zip"; 49 } 50 51 return fileName; 52 }, 53 54 /** 55 * Save HAR string into a given file. The file might be compressed 56 * if specified in the options. 57 * 58 * @param {File} file Target file where the HAR string (JSON) 59 * should be stored. 60 * @param {string} jsonString HAR data (JSON or JSONP) 61 * @param {boolean} compress The result file is zipped if set to true. 62 */ 63 saveToFile(file, jsonString, compress) { 64 const openFlags = 65 OPEN_FLAGS.WRONLY | OPEN_FLAGS.CREATE_FILE | OPEN_FLAGS.TRUNCATE; 66 67 try { 68 const foStream = Cc[ 69 "@mozilla.org/network/file-output-stream;1" 70 ].createInstance(Ci.nsIFileOutputStream); 71 72 const permFlags = parseInt("0666", 8); 73 foStream.init(file, openFlags, permFlags, 0); 74 75 const convertor = Cc[ 76 "@mozilla.org/intl/converter-output-stream;1" 77 ].createInstance(Ci.nsIConverterOutputStream); 78 convertor.init(foStream, "UTF-8"); 79 80 // The entire jsonString can be huge so, write the data in chunks. 81 const chunkLength = 1024 * 1024; 82 for (let i = 0; i <= jsonString.length; i++) { 83 const data = jsonString.substr(i, chunkLength + 1); 84 if (data) { 85 convertor.writeString(data); 86 } 87 88 i = i + chunkLength; 89 } 90 91 // this closes foStream 92 convertor.close(); 93 } catch (err) { 94 console.error(err); 95 return false; 96 } 97 98 // If no compressing then bail out. 99 if (!compress) { 100 return true; 101 } 102 103 // Remember name of the original file, it'll be replaced by a zip file. 104 const originalFilePath = file.path; 105 const originalFileName = file.leafName; 106 107 try { 108 // Rename using unique name (the file is going to be removed). 109 file.moveTo(null, "temp" + new Date().getTime() + "temphar"); 110 111 // Create compressed file with the original file path name. 112 const zipFile = Cc["@mozilla.org/file/local;1"].createInstance( 113 Ci.nsIFile 114 ); 115 zipFile.initWithPath(originalFilePath); 116 117 // The file within the zipped file doesn't use .zip extension. 118 let fileName = originalFileName; 119 if (fileName.indexOf(".zip") == fileName.length - 4) { 120 fileName = fileName.substr(0, fileName.indexOf(".zip")); 121 } 122 123 const zip = new ZipWriter(); 124 zip.open(zipFile, openFlags); 125 zip.addEntryFile( 126 fileName, 127 Ci.nsIZipWriter.COMPRESSION_DEFAULT, 128 file, 129 false 130 ); 131 zip.close(); 132 133 // Remove the original file (now zipped). 134 file.remove(true); 135 return true; 136 } catch (err) { 137 console.error(err); 138 139 // Something went wrong (disk space?) rename the original file back. 140 file.moveTo(null, originalFileName); 141 } 142 143 return false; 144 }, 145 146 getLocalDirectory(path) { 147 let dir; 148 149 if (!path) { 150 dir = Services.dirsvc.get("ProfD", Ci.nsIFile); 151 dir.append("har"); 152 dir.append("logs"); 153 } else { 154 dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); 155 dir.initWithPath(path); 156 } 157 158 return dir; 159 }, 160 }; 161 162 // Exports from this module 163 exports.HarUtils = HarUtils;