HeapSnapshotFileUtils.js (3021B)
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 // Heap snapshots are always saved in the temp directory, and have a regular 6 // naming convention. This module provides helpers for working with heap 7 // snapshot files in a safe manner. Because we attempt to avoid unnecessary 8 // copies of the heap snapshot files by checking the local filesystem for a heap 9 // snapshot file with the given snapshot id, we want to ensure that we are only 10 // attempting to open heap snapshot files and not `~/.ssh/id_rsa`, for 11 // example. Therefore, the RDP only talks about snapshot ids, or transfering the 12 // bulk file data. A file path can be recovered from a snapshot id, which allows 13 // one to check for the presence of the heap snapshot file on the local file 14 // system, but we don't have to worry about opening arbitrary files. 15 // 16 // The heap snapshot file path conventions permits the following forms: 17 // 18 // $TEMP_DIRECTORY/XXXXXXXXXX.fxsnapshot 19 // $TEMP_DIRECTORY/XXXXXXXXXX-XXXXX.fxsnapshot 20 // 21 // Where the strings of "X" are zero or more digits. 22 23 "use strict"; 24 25 const lazy = {}; 26 ChromeUtils.defineESModuleGetters( 27 lazy, 28 { 29 FileUtils: "resource://gre/modules/FileUtils.sys.mjs", 30 }, 31 { global: "contextual" } 32 ); 33 34 function getHeapSnapshotFileTemplate() { 35 return PathUtils.join(PathUtils.tempDir, `${Date.now()}.fxsnapshot`); 36 } 37 38 /** 39 * Get a unique temp file path for a new heap snapshot. The file is guaranteed 40 * not to exist before this call. 41 * 42 * @returns String 43 */ 44 exports.getNewUniqueHeapSnapshotTempFilePath = function () { 45 const file = new lazy.FileUtils.File(getHeapSnapshotFileTemplate()); 46 // The call to createUnique will append "-N" after the leaf name (but before 47 // the extension) until a new file is found and create it. This guarantees we 48 // won't accidentally choose the same file twice. 49 file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666); 50 return file.path; 51 }; 52 53 function isValidSnapshotFileId(snapshotId) { 54 return /^\d+(\-\d+)?$/.test(snapshotId); 55 } 56 57 /** 58 * Get the file path for the given snapshot id. 59 * 60 * @param {string} snapshotId 61 * 62 * @returns String | null 63 */ 64 exports.getHeapSnapshotTempFilePath = function (snapshotId) { 65 // Don't want anyone sneaking "../../../.." strings into the snapshot id and 66 // trying to make us open arbitrary files. 67 if (!isValidSnapshotFileId(snapshotId)) { 68 return null; 69 } 70 return PathUtils.join(PathUtils.tempDir, snapshotId + ".fxsnapshot"); 71 }; 72 73 /** 74 * Return true if we have the heap snapshot file for the given snapshot id on 75 * the local file system. False is returned otherwise. 76 * 77 * @returns Promise<Boolean> 78 */ 79 exports.haveHeapSnapshotTempFile = function (snapshotId) { 80 const path = exports.getHeapSnapshotTempFilePath(snapshotId); 81 if (!path) { 82 return Promise.resolve(false); 83 } 84 85 return IOUtils.stat(path).then( 86 () => true, 87 () => false 88 ); 89 };