summaryrefslogtreecommitdiffstats
path: root/devtools/shared/fronts/memory.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/shared/fronts/memory.js')
-rw-r--r--devtools/shared/fronts/memory.js92
1 files changed, 92 insertions, 0 deletions
diff --git a/devtools/shared/fronts/memory.js b/devtools/shared/fronts/memory.js
new file mode 100644
index 000000000..d7a6a3108
--- /dev/null
+++ b/devtools/shared/fronts/memory.js
@@ -0,0 +1,92 @@
+/* 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";
+
+const { memorySpec } = require("devtools/shared/specs/memory");
+const { Task } = require("devtools/shared/task");
+const protocol = require("devtools/shared/protocol");
+
+loader.lazyRequireGetter(this, "FileUtils",
+ "resource://gre/modules/FileUtils.jsm", true);
+loader.lazyRequireGetter(this, "HeapSnapshotFileUtils",
+ "devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
+
+const MemoryFront = protocol.FrontClassWithSpec(memorySpec, {
+ initialize: function (client, form, rootForm = null) {
+ protocol.Front.prototype.initialize.call(this, client, form);
+ this._client = client;
+ this.actorID = form.memoryActor;
+ this.heapSnapshotFileActorID = rootForm
+ ? rootForm.heapSnapshotFileActor
+ : null;
+ this.manage(this);
+ },
+
+ /**
+ * Save a heap snapshot, transfer it from the server to the client if the
+ * server and client do not share a file system, and return the local file
+ * path to the heap snapshot.
+ *
+ * Note that this is safe to call for actors inside sandoxed child processes,
+ * as we jump through the correct IPDL hoops.
+ *
+ * @params Boolean options.forceCopy
+ * Always force a bulk data copy of the saved heap snapshot, even when
+ * the server and client share a file system.
+ *
+ * @params {Object|undefined} options.boundaries
+ * The boundaries for the heap snapshot. See
+ * ThreadSafeChromeUtils.webidl for more details.
+ *
+ * @returns Promise<String>
+ */
+ saveHeapSnapshot: protocol.custom(Task.async(function* (options = {}) {
+ const snapshotId = yield this._saveHeapSnapshotImpl(options.boundaries);
+
+ if (!options.forceCopy &&
+ (yield HeapSnapshotFileUtils.haveHeapSnapshotTempFile(snapshotId))) {
+ return HeapSnapshotFileUtils.getHeapSnapshotTempFilePath(snapshotId);
+ }
+
+ return yield this.transferHeapSnapshot(snapshotId);
+ }), {
+ impl: "_saveHeapSnapshotImpl"
+ }),
+
+ /**
+ * Given that we have taken a heap snapshot with the given id, transfer the
+ * heap snapshot file to the client. The path to the client's local file is
+ * returned.
+ *
+ * @param {String} snapshotId
+ *
+ * @returns Promise<String>
+ */
+ transferHeapSnapshot: protocol.custom(function (snapshotId) {
+ if (!this.heapSnapshotFileActorID) {
+ throw new Error("MemoryFront initialized without a rootForm");
+ }
+
+ const request = this._client.request({
+ to: this.heapSnapshotFileActorID,
+ type: "transferHeapSnapshot",
+ snapshotId
+ });
+
+ return new Promise((resolve, reject) => {
+ const outFilePath =
+ HeapSnapshotFileUtils.getNewUniqueHeapSnapshotTempFilePath();
+ const outFile = new FileUtils.File(outFilePath);
+
+ const outFileStream = FileUtils.openSafeFileOutputStream(outFile);
+ request.on("bulk-reply", Task.async(function* ({ copyTo }) {
+ yield copyTo(outFileStream);
+ FileUtils.closeSafeFileOutputStream(outFileStream);
+ resolve(outFilePath);
+ }));
+ });
+ })
+});
+
+exports.MemoryFront = MemoryFront;