Bug 1362800 - Expose geckoProfiler.getProfileAsArrayBuffer. r?kmag
MozReview-Commit-ID: 7uFPWAhh25L
--- a/browser/components/extensions/ext-geckoProfiler.js
+++ b/browser/components/extensions/ext-geckoProfiler.js
@@ -10,16 +10,20 @@ XPCOMUtils.defineLazyModuleGetter(this,
XPCOMUtils.defineLazyModuleGetter(this, "Subprocess", "resource://gre/modules/Subprocess.jsm");
const PREF_ASYNC_STACK = "javascript.options.asyncstack";
const PREF_SYMBOLS_URL = "extensions.geckoProfiler.symbols.url";
const PREF_GET_SYMBOL_RULES = "extensions.geckoProfiler.getSymbolRules";
const ASYNC_STACKS_ENABLED = Services.prefs.getBoolPref(PREF_ASYNC_STACK, false);
+var {
+ ExtensionError,
+} = ExtensionUtils;
+
function parseSym(data) {
const worker = new ChromeWorker("resource://app/modules/ParseSymbols-worker.js");
const promise = new Promise((resolve, reject) => {
worker.onmessage = (e) => {
if (e.data.error) {
reject(e.data.error);
} else {
resolve(e.data.result);
@@ -290,23 +294,32 @@ this.geckoProfiler = class extends Exten
},
async resume() {
Services.profiler.ResumeSampling();
},
async getProfile() {
if (!Services.profiler.IsActive()) {
- throw new Error("The profiler is stopped. " +
+ throw new ExtensionError("The profiler is stopped. " +
"You need to start the profiler before you can capture a profile.");
}
return Services.profiler.getProfileDataAsync();
},
+ async getProfileAsArrayBuffer() {
+ if (!Services.profiler.IsActive()) {
+ throw new ExtensionError("The profiler is stopped. " +
+ "You need to start the profiler before you can capture a profile.");
+ }
+
+ return Services.profiler.getProfileDataAsArrayBuffer();
+ },
+
async getSymbols(debugName, breakpadId) {
if (symbolCache.size === 0) {
primeSymbolStore(Services.profiler.sharedLibraries);
}
const cachedLibInfo = symbolCache.get(urlForSymFile(debugName, breakpadId));
const symbolRules = Services.prefs.getCharPref(PREF_GET_SYMBOL_RULES, "localBreakpad,remoteBreakpad");
--- a/browser/components/extensions/schemas/geckoProfiler.json
+++ b/browser/components/extensions/schemas/geckoProfiler.json
@@ -88,16 +88,23 @@
{
"name": "getProfile",
"type": "function",
"description": "Gathers the profile data from the current profiling session.",
"async": true,
"parameters": []
},
{
+ "name": "getProfileAsArrayBuffer",
+ "type": "function",
+ "description": "Gathers the profile data from the current profiling session. The returned promise resolves to an array buffer that contains a JSON string.",
+ "async": true,
+ "parameters": []
+ },
+ {
"name": "getSymbols",
"type": "function",
"description": "Gets the debug symbols for a particular library.",
"async": true,
"parameters": [
{
"type": "string",
"name": "debugName",
--- a/browser/components/extensions/test/xpcshell/test_ext_geckoProfiler_control.js
+++ b/browser/components/extensions/test/xpcshell/test_ext_geckoProfiler_control.js
@@ -43,16 +43,28 @@ let getExtension = () => {
result = await browser.geckoProfiler.getProfile();
browser.test.assertTrue("libs" in result, "The profile contains libs.");
browser.test.assertTrue("meta" in result, "The profile contains meta.");
browser.test.assertTrue("threads" in result, "The profile contains threads.");
browser.test.assertTrue(result.threads.some(t => t.name == "GeckoMain"),
"The profile contains a GeckoMain thread.");
browser.test.sendMessage("tested profile");
break;
+ case "test profile as array buffer":
+ let arrayBuffer = await browser.geckoProfiler.getProfileAsArrayBuffer();
+ browser.test.assertTrue(arrayBuffer.byteLength >= 2, "The profile array buffer contains data.");
+ let textDecoder = new TextDecoder();
+ let profile = JSON.parse(textDecoder.decode(arrayBuffer));
+ browser.test.assertTrue("libs" in profile, "The profile contains libs.");
+ browser.test.assertTrue("meta" in profile, "The profile contains meta.");
+ browser.test.assertTrue("threads" in profile, "The profile contains threads.");
+ browser.test.assertTrue(profile.threads.some(t => t.name == "GeckoMain"),
+ "The profile contains a GeckoMain thread.");
+ browser.test.sendMessage("tested profile as array buffer");
+ break;
case "remove runningListener":
browser.geckoProfiler.onRunning.removeListener(runningListener);
browser.test.sendMessage("removed runningListener");
break;
}
});
browser.test.sendMessage("ready");
@@ -81,16 +93,19 @@ add_task(async function testProfilerCont
await extension.awaitMessage("stopped");
extension.sendMessage("start");
await extension.awaitMessage("started");
extension.sendMessage("test profile");
await extension.awaitMessage("tested profile");
+ extension.sendMessage("test profile as array buffer");
+ await extension.awaitMessage("tested profile as array buffer");
+
extension.sendMessage("pause");
await extension.awaitMessage("paused");
extension.sendMessage("resume");
await extension.awaitMessage("resumed");
extension.sendMessage("stop");
await extension.awaitMessage("stopped");