summaryrefslogtreecommitdiffstats
path: root/devtools/server/actors/watcher/target-helpers/worker-helper.js
blob: 671d1dc7066b7c0dcea1512f13bd2158318ec2fa (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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* 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 DEVTOOLS_WORKER_JS_WINDOW_ACTOR_NAME = "DevToolsWorker";

/**
 * Force creating targets for all existing workers for a given Watcher Actor.
 *
 * @param WatcherActor watcher
 *        The Watcher Actor requesting to watch for new targets.
 */
async function createTargets(watcher) {
  // Go over all existing BrowsingContext in order to:
  // - Force the instantiation of a DevToolsWorkerChild
  // - Have the DevToolsWorkerChild to spawn the WorkerTargetActors
  const browsingContexts = watcher.getAllBrowsingContexts({
    acceptSameProcessIframes: true,
    forceAcceptTopLevelTarget: true,
  });
  const promises = [];
  for (const browsingContext of browsingContexts) {
    const promise = browsingContext.currentWindowGlobal
      .getActor(DEVTOOLS_WORKER_JS_WINDOW_ACTOR_NAME)
      .instantiateWorkerTargets({
        watcherActorID: watcher.actorID,
        connectionPrefix: watcher.conn.prefix,
        sessionContext: watcher.sessionContext,
        sessionData: watcher.sessionData,
      });
    promises.push(promise);
  }

  // Await for the different queries in order to try to resolve only *after* we received
  // the already available worker targets.
  return Promise.all(promises);
}

/**
 * Force destroying all worker targets which were related to a given watcher.
 *
 * @param WatcherActor watcher
 *        The Watcher Actor requesting to stop watching for new targets.
 */
async function destroyTargets(watcher) {
  // Go over all existing BrowsingContext in order to destroy all targets
  const browsingContexts = watcher.getAllBrowsingContexts({
    acceptSameProcessIframes: true,
    forceAcceptTopLevelTarget: true,
  });
  for (const browsingContext of browsingContexts) {
    let windowActor;
    try {
      windowActor = browsingContext.currentWindowGlobal.getActor(
        DEVTOOLS_WORKER_JS_WINDOW_ACTOR_NAME
      );
    } catch (e) {
      continue;
    }

    windowActor.destroyWorkerTargets({
      watcherActorID: watcher.actorID,
      sessionContext: watcher.sessionContext,
    });
  }
}

/**
 * Go over all existing BrowsingContext in order to communicate about new data entries
 *
 * @param WatcherActor watcher
 *        The Watcher Actor requesting to stop watching for new targets.
 * @param string type
 *        The type of data to be added
 * @param Array<Object> entries
 *        The values to be added to this type of data
 * @param String updateType
 *        "add" will only add the new entries in the existing data set.
 *        "set" will update the data set with the new entries.
 */
async function addOrSetSessionDataEntry({
  watcher,
  type,
  entries,
  updateType,
}) {
  const browsingContexts = watcher.getAllBrowsingContexts({
    acceptSameProcessIframes: true,
    forceAcceptTopLevelTarget: true,
  });
  const promises = [];
  for (const browsingContext of browsingContexts) {
    const promise = browsingContext.currentWindowGlobal
      .getActor(DEVTOOLS_WORKER_JS_WINDOW_ACTOR_NAME)
      .addOrSetSessionDataEntry({
        watcherActorID: watcher.actorID,
        sessionContext: watcher.sessionContext,
        type,
        entries,
        updateType,
      });
    promises.push(promise);
  }
  // Await for the queries in order to try to resolve only *after* the remote code processed the new data
  return Promise.all(promises);
}

/**
 * Notify all existing frame targets that some data entries have been removed
 *
 * See addOrSetSessionDataEntry for argument documentation.
 */
function removeSessionDataEntry({ watcher, type, entries }) {
  const browsingContexts = watcher.getAllBrowsingContexts({
    acceptSameProcessIframes: true,
    forceAcceptTopLevelTarget: true,
  });
  for (const browsingContext of browsingContexts) {
    browsingContext.currentWindowGlobal
      .getActor(DEVTOOLS_WORKER_JS_WINDOW_ACTOR_NAME)
      .removeSessionDataEntry({
        watcherActorID: watcher.actorID,
        sessionContext: watcher.sessionContext,
        type,
        entries,
      });
  }
}

module.exports = {
  createTargets,
  destroyTargets,
  addOrSetSessionDataEntry,
  removeSessionDataEntry,
};