Backed out 4 changesets (bug 1651522) for causing dt failures on devtools/shared...
[gecko.git] / devtools / server / actors / resources / sources.js
blob6076e333c9d830bd8ca88ebe32766af4e0c5f44c
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/. */
5 "use strict";
7 const {
8   TYPES: { SOURCE },
9 } = require("resource://devtools/server/actors/resources/index.js");
10 const Targets = require("resource://devtools/server/actors/targets/index.js");
12 const {
13   STATES: THREAD_STATES,
14 } = require("resource://devtools/server/actors/thread.js");
16 /**
17  * Start watching for all JS sources related to a given Target Actor.
18  * This will notify about existing sources, but also the ones created in future.
19  *
20  * @param TargetActor targetActor
21  *        The target actor from which we should observe sources
22  * @param Object options
23  *        Dictionary object with following attributes:
24  *        - onAvailable: mandatory function
25  *          This will be called for each resource.
26  */
27 class SourceWatcher {
28   constructor() {
29     this.onNewSource = this.onNewSource.bind(this);
30   }
32   async watch(targetActor, { onAvailable }) {
33     // When debugging the whole browser, we instantiate both content process and browsing context targets.
34     // But sources will only be debugged the content process target, even browsing context sources.
35     if (
36       targetActor.sessionContext.type == "all" &&
37       targetActor.targetType === Targets.TYPES.FRAME &&
38       targetActor.typeName != "parentProcessTarget"
39     ) {
40       return;
41     }
43     const { threadActor } = targetActor;
44     this.sourcesManager = targetActor.sourcesManager;
45     this.onAvailable = onAvailable;
47     // Disable `ThreadActor.newSource` RDP event in order to avoid unnecessary traffic
48     threadActor.disableNewSourceEvents();
50     threadActor.sourcesManager.on("newSource", this.onNewSource);
52     // If the thread actors isn't bootstraped yet,
53     // (this might be the case when this watcher is created on target creation)
54     // attach the thread actor automatically.
55     // Otherwise it would not notify about future sources.
56     // However, do not attach the thread actor for Workers. They use a codepath
57     // which releases the worker on `attach`. For them, the client will call `attach`. (bug 1691986)
58     // Content process targets don't have attach method or sequence.
59     // Instead their thread actor is instantiated immediately, when generating their
60     // form. Which is called immediately when we notify the target actor to the TargetList.
61     const isTargetCreation = threadActor.state == THREAD_STATES.DETACHED;
62     if (isTargetCreation && !targetActor.targetType.endsWith("worker")) {
63       await threadActor.attach({});
64     }
66     // Before fetching all sources, process existing ones.
67     // The ThreadActor is already up and running before this code runs
68     // and have sources already registered and for which newSource event already fired.
69     onAvailable(
70       threadActor.sourcesManager.iter().map(s => {
71         const resource = s.form();
72         resource.resourceType = SOURCE;
73         return resource;
74       })
75     );
77     // Requesting all sources should end up emitting newSource on threadActor.sourcesManager
78     threadActor.addAllSources();
79   }
81   /**
82    * Stop watching for sources
83    */
84   destroy() {
85     if (this.sourcesManager) {
86       this.sourcesManager.off("newSource", this.onNewSource);
87     }
88   }
90   onNewSource(source) {
91     const resource = source.form();
92     resource.resourceType = SOURCE;
93     this.onAvailable([resource]);
94   }
97 module.exports = SourceWatcher;