HeapSnapshotFileUtils.js 3.3 KB

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