summaryrefslogtreecommitdiffstats
path: root/devtools/server/actors/resources/jstracer-state.js
blob: 74491a6cedfb148a7b8464717583b9a6185a2150 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/* 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 {
  TYPES: { JSTRACER_STATE },
} = require("resource://devtools/server/actors/resources/index.js");

// Bug 1827382, as this module can be used from the worker thread,
// the following JSM may be loaded by the worker loader until
// we have proper support for ESM from workers.
const {
  addTracingListener,
  removeTracingListener,
} = require("resource://devtools/server/tracer/tracer.jsm");

const { LOG_METHODS } = require("resource://devtools/server/actors/tracer.js");
const Targets = require("resource://devtools/server/actors/targets/index.js");

class TracingStateWatcher {
  /**
   * Start watching for tracing state changes for a given target actor.
   *
   * @param TargetActor targetActor
   *        The target actor from which we should observe
   * @param Object options
   *        Dictionary object with following attributes:
   *        - onAvailable: mandatory function
   *          This will be called for each resource.
   */
  async watch(targetActor, { onAvailable }) {
    // Bug 1874204: tracer doesn't support tracing content process from the browser toolbox just yet
    if (targetActor.targetType == Targets.TYPES.PROCESS) {
      return;
    }

    this.targetActor = targetActor;
    this.onAvailable = onAvailable;

    this.tracingListener = {
      onTracingToggled: this.onTracingToggled.bind(this),
    };
    addTracingListener(this.tracingListener);
  }

  /**
   * Stop watching for tracing state
   */
  destroy() {
    if (!this.tracingListener) {
      return;
    }
    removeTracingListener(this.tracingListener);
  }

  /**
   * Be notified by the underlying JavaScriptTracer class
   * in case it stops by itself, instead of being stopped when the Actor's stopTracing
   * method is called by the user.
   *
   * @param {Boolean} enabled
   *        True if the tracer starts tracing, false it it stops.
   * @param {String} reason
   *        Optional string to justify why the tracer stopped.
   */
  onTracingToggled(enabled, reason) {
    const tracerActor = this.targetActor.getTargetScopedActor("tracer");
    const logMethod = tracerActor?.getLogMethod();

    // JavascriptTracer only supports recording once in the same process/thread.
    // If we open another DevTools, on the same process, we would receive notification
    // about a JavascriptTracer controlled by another toolbox's tracer actor.
    // Ignore them as our current tracer actor didn't start tracing.
    if (!logMethod) {
      return;
    }

    this.onAvailable([
      {
        resourceType: JSTRACER_STATE,
        enabled,
        logMethod,
        profile:
          logMethod == LOG_METHODS.PROFILER && !enabled
            ? tracerActor.getProfile()
            : undefined,
        timeStamp: ChromeUtils.dateNow(),
        reason,
      },
    ]);
  }
}

module.exports = TracingStateWatcher;