ng = "?implementation=js"; } } else if (profilerViewMode !== undefined && profilerViewMode !== "full") { viewModeQueryString = `?view=${profilerViewMode}`; } const urlToLoad = `${baseUrl}${baseUrlPath}${additionalPath}${viewModeQueryString}`; // Find the most recently used window, as the DevTools client could be in a variety // of hosts. // Note that when running from the browser toolbox, there won't be the browser window, // but only the browser toolbox document. const win = Services.wm.getMostRecentBrowserWindow() || Services.wm.getMostRecentWindow("devtools:toolbox"); if (!win) { throw new Error("No browser window"); } win.focus(); // The profiler frontend currently doesn't support being loaded in a private // window, because it does some storage writes in IndexedDB. That's why we // force the opening of the tab in a non-private window. This might open a new // non-private window if the only currently opened window is a private window. const contentBrowser = await new Promise(resolveOnContentBrowserCreated => win.openWebLinkIn(urlToLoad, "tab", { forceNonPrivate: true, resolveOnContentBrowserCreated, userContextId: win.gBrowser?.contentPrincipal.userContextId, relatedToCurrent: true, }) ); return contentBrowser; } /** * Restarts the browser with a given environment variable set to a value. * * @param {Record} env */ function restartBrowserWithEnvironmentVariable(env) { for (const [envName, envValue] of Object.entries(env)) { Services.env.set(envName, envValue); } Services.startup.quit( Services.startup.eForceQuit | Services.startup.eRestart ); } /** * @param {Window} window * @param {string[]} objdirs * @param {(objdirs: string[]) => unknown} changeObjdirs */ function openFilePickerForObjdir(window, objdirs, changeObjdirs) { const FilePicker = Cc["@mozilla.org/filepicker;1"].createInstance( Ci.nsIFilePicker ); FilePicker.init( window.browsingContext, "Pick build directory", FilePicker.modeGetFolder ); FilePicker.open(rv => { if (rv == FilePicker.returnOK) { const path = FilePicker.file.path; if (path && !objdirs.includes(path)) { const newObjdirs = [...objdirs, path]; changeObjdirs(newObjdirs); } } }); } /** * Try to open the given script with line and column in the tab. * * If the profiled tab is not alive anymore, returns without doing anything. * * @param {number} tabId * @param {string} scriptUrl * @param {number} line * @param {number} columnOneBased */ async function openScriptInDebugger(tabId, scriptUrl, line, columnOneBased) { const win = Services.wm.getMostRecentBrowserWindow(); // Iterate through all tabs in the current window and find the tab that we want. const foundTab = win.gBrowser.tabs.find( tab => tab.linkedBrowser.browserId === tabId ); if (!foundTab) { console.log(`No tab found with the tab id: ${tabId}`); return; } // If a matching tab was found, switch to it. win.gBrowser.selectedTab = foundTab; // And open the devtools debugger with script. const toolbox = await gDevTools.showToolboxForTab(foundTab, { toolId: "jsdebugger", }); toolbox.win.focus(); // In case profiler backend can't retrieve the column number, it can return zero. const columnZeroBased = columnOneBased > 0 ? columnOneBased - 1 : 0; await toolbox.viewSourceInDebugger( scriptUrl, line, columnZeroBased, /* sourceId = */ null, "ProfilerOpenScript" ); } module.exports = { openProfilerTab, restartBrowserWithEnvironmentVariable, openFilePickerForObjdir, openScriptInDebugger, }; PK