memory.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. "use strict";
  5. const { memorySpec } = require("devtools/shared/specs/memory");
  6. const { Task } = require("devtools/shared/task");
  7. const protocol = require("devtools/shared/protocol");
  8. loader.lazyRequireGetter(this, "FileUtils",
  9. "resource://gre/modules/FileUtils.jsm", true);
  10. loader.lazyRequireGetter(this, "HeapSnapshotFileUtils",
  11. "devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
  12. const MemoryFront = protocol.FrontClassWithSpec(memorySpec, {
  13. initialize: function (client, form, rootForm = null) {
  14. protocol.Front.prototype.initialize.call(this, client, form);
  15. this._client = client;
  16. this.actorID = form.memoryActor;
  17. this.heapSnapshotFileActorID = rootForm
  18. ? rootForm.heapSnapshotFileActor
  19. : null;
  20. this.manage(this);
  21. },
  22. /**
  23. * Save a heap snapshot, transfer it from the server to the client if the
  24. * server and client do not share a file system, and return the local file
  25. * path to the heap snapshot.
  26. *
  27. * Note that this is safe to call for actors inside sandoxed child processes,
  28. * as we jump through the correct IPDL hoops.
  29. *
  30. * @params Boolean options.forceCopy
  31. * Always force a bulk data copy of the saved heap snapshot, even when
  32. * the server and client share a file system.
  33. *
  34. * @params {Object|undefined} options.boundaries
  35. * The boundaries for the heap snapshot. See
  36. * ThreadSafeChromeUtils.webidl for more details.
  37. *
  38. * @returns Promise<String>
  39. */
  40. saveHeapSnapshot: protocol.custom(Task.async(function* (options = {}) {
  41. const snapshotId = yield this._saveHeapSnapshotImpl(options.boundaries);
  42. if (!options.forceCopy &&
  43. (yield HeapSnapshotFileUtils.haveHeapSnapshotTempFile(snapshotId))) {
  44. return HeapSnapshotFileUtils.getHeapSnapshotTempFilePath(snapshotId);
  45. }
  46. return yield this.transferHeapSnapshot(snapshotId);
  47. }), {
  48. impl: "_saveHeapSnapshotImpl"
  49. }),
  50. /**
  51. * Given that we have taken a heap snapshot with the given id, transfer the
  52. * heap snapshot file to the client. The path to the client's local file is
  53. * returned.
  54. *
  55. * @param {String} snapshotId
  56. *
  57. * @returns Promise<String>
  58. */
  59. transferHeapSnapshot: protocol.custom(function (snapshotId) {
  60. if (!this.heapSnapshotFileActorID) {
  61. throw new Error("MemoryFront initialized without a rootForm");
  62. }
  63. const request = this._client.request({
  64. to: this.heapSnapshotFileActorID,
  65. type: "transferHeapSnapshot",
  66. snapshotId
  67. });
  68. return new Promise((resolve, reject) => {
  69. const outFilePath =
  70. HeapSnapshotFileUtils.getNewUniqueHeapSnapshotTempFilePath();
  71. const outFile = new FileUtils.File(outFilePath);
  72. const outFileStream = FileUtils.openSafeFileOutputStream(outFile);
  73. request.on("bulk-reply", Task.async(function* ({ copyTo }) {
  74. yield copyTo(outFileStream);
  75. FileUtils.closeSafeFileOutputStream(outFileStream);
  76. resolve(outFilePath);
  77. }));
  78. });
  79. })
  80. });
  81. exports.MemoryFront = MemoryFront;