tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

recording-utils.sys.mjs (2750B)


      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 // @ts-check
      5 
      6 /**
      7 * @typedef {import("perf").GetActiveBrowserID} GetActiveBrowserID
      8 * @typedef {import("perf").ProfileCaptureResult} ProfileCaptureResult
      9 */
     10 
     11 /**
     12 * Gets the ID of active tab from the browser.
     13 *
     14 * @type {GetActiveBrowserID}
     15 */
     16 export function getActiveBrowserID() {
     17  const win = Services.wm.getMostRecentBrowserWindow();
     18 
     19  const browserId = win?.gBrowser?.selectedBrowser?.browsingContext?.browserId;
     20  if (browserId) {
     21    return browserId;
     22  }
     23 
     24  console.error(
     25    "Failed to get the active browserId while starting the profiler."
     26  );
     27  // `0` mean that we failed to ge the active browserId, and it's
     28  // treated as null value in the platform.
     29  return 0;
     30 }
     31 
     32 /**
     33 * @typedef {object} ProfileCaptureResultAndAdditionalInformation
     34 * @property {ProfileCaptureResult} profileCaptureResult
     35 * @property {MockedExports.ProfileGenerationAdditionalInformation} [additionalInformation]
     36 */
     37 /**
     38 * Fetch the profile data from Firefox, then stop the profiler.
     39 *
     40 * @returns {Promise<ProfileCaptureResultAndAdditionalInformation>}
     41 */
     42 export async function getProfileDataAsGzippedArrayBufferThenStop() {
     43  if (!Services.profiler.IsActive()) {
     44    // The profiler is not active, ignore.
     45    return {
     46      profileCaptureResult: {
     47        type: "ERROR",
     48        error: new Error("The profiler is not active."),
     49      },
     50    };
     51  }
     52  if (Services.profiler.IsPaused()) {
     53    // The profiler is already paused for capture, ignore.
     54    return {
     55      profileCaptureResult: {
     56        type: "ERROR",
     57        error: new Error("The profiler is already paused."),
     58      },
     59    };
     60  }
     61 
     62  // Pause profiler before we collect the profile, so that we don't capture
     63  // more samples while the parent process waits for subprocess profiles.
     64  Services.profiler.Pause();
     65 
     66  try {
     67    const { profile, additionalInformation } =
     68      await Services.profiler.getProfileDataAsGzippedArrayBuffer();
     69 
     70    return {
     71      profileCaptureResult: { type: "SUCCESS", profile },
     72      additionalInformation,
     73    };
     74  } catch (unknownError) {
     75    const error = /** @type {Error} */ (unknownError);
     76    return { profileCaptureResult: { type: "ERROR", error } };
     77  } finally {
     78    // We're purposefully not using `await`, to minimize the time the user has
     79    // to wait until the result is returned.
     80    Services.profiler.StopProfiler();
     81  }
     82 }
     83 
     84 // This file also exports a named object containing other exports to play well
     85 // with defineESModuleGetters.
     86 export const RecordingUtils = {
     87  getActiveBrowserID,
     88  getProfileDataAsGzippedArrayBufferThenStop,
     89 };