/* 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"; /** * The following functions are used in testing to control and inspect * the nsIProfiler in child process content. These should be called from * the parent process. */ const { Cc, Ci } = require("chrome"); const { Task } = require("devtools/shared/task"); const FRAME_SCRIPT_UTILS_URL = "chrome://devtools/content/shared/frame-script-utils.js"; let gMM = null; /** * Loads the relevant frame scripts into the provided browser's message manager. */ exports.pmmLoadFrameScripts = (gBrowser) => { gMM = gBrowser.selectedBrowser.messageManager; gMM.loadFrameScript(FRAME_SCRIPT_UTILS_URL, false); }; /** * Clears the cached message manager. */ exports.pmmClearFrameScripts = () => { gMM = null; }; /** * Sends a message to the message listener, attaching an id to the payload data. * Resolves a returned promise when the response is received from the message * listener, with the same id as part of the response payload data. */ exports.pmmUniqueMessage = function (message, payload) { if (!gMM) { throw new Error("`pmmLoadFrameScripts()` must be called when using MessageManager."); } let { generateUUID } = Cc["@mozilla.org/uuid-generator;1"] .getService(Ci.nsIUUIDGenerator); payload.id = generateUUID().toString(); return new Promise(resolve => { gMM.addMessageListener(message + ":response", function onHandler({ data }) { if (payload.id == data.id) { gMM.removeMessageListener(message + ":response", onHandler); resolve(data.data); } }); gMM.sendAsyncMessage(message, payload); }); }; /** * Checks if the nsProfiler module is active. */ exports.pmmIsProfilerActive = () => { return exports.pmmSendProfilerCommand("IsActive"); }; /** * Starts the nsProfiler module. */ exports.pmmStartProfiler = Task.async(function* ({ entries, interval, features }) { let isActive = (yield exports.pmmSendProfilerCommand("IsActive")).isActive; if (!isActive) { return exports.pmmSendProfilerCommand("StartProfiler", [entries, interval, features, features.length]); } return null; }); /** * Stops the nsProfiler module. */ exports.pmmStopProfiler = Task.async(function* () { let isActive = (yield exports.pmmSendProfilerCommand("IsActive")).isActive; if (isActive) { return exports.pmmSendProfilerCommand("StopProfiler"); } return null; }); /** * Calls a method on the nsProfiler module. */ exports.pmmSendProfilerCommand = (method, args = []) => { return exports.pmmUniqueMessage("devtools:test:profiler", { method, args }); }; /** * Evaluates a script in content, returning a promise resolved with the * returned result. */ exports.pmmEvalInDebuggee = (script) => { return exports.pmmUniqueMessage("devtools:test:eval", { script }); }; /** * Evaluates a console method in content. */ exports.pmmConsoleMethod = function (method, ...args) { // Terrible ugly hack -- this gets stringified when it uses the // message manager, so an undefined arg in `console.profileEnd()` // turns into a stringified "null", which is terrible. This method // is only used for test helpers, so swap out the argument if its undefined // with an empty string. Differences between empty string and undefined are // tested on the front itself. if (args[0] == null) { args[0] = ""; } return exports.pmmUniqueMessage("devtools:test:console", { method, args }); };