worker.js (4693B)
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 5 "use strict"; 6 7 /* 8 * Target actor for any of the various kinds of workers. 9 * 10 * See devtools/docs/backend/actor-hierarchy.md for more details. 11 */ 12 13 // protocol.js uses objects as exceptions in order to define 14 // error packets. 15 /* eslint-disable no-throw-literal */ 16 17 const { Actor } = require("resource://devtools/shared/protocol.js"); 18 const { 19 workerDescriptorSpec, 20 } = require("resource://devtools/shared/specs/descriptors/worker.js"); 21 22 const { 23 DevToolsServer, 24 } = require("resource://devtools/server/devtools-server.js"); 25 const { XPCOMUtils } = ChromeUtils.importESModule( 26 "resource://gre/modules/XPCOMUtils.sys.mjs", 27 { global: "contextual" } 28 ); 29 const { 30 createWorkerSessionContext, 31 } = require("resource://devtools/server/actors/watcher/session-context.js"); 32 33 loader.lazyRequireGetter( 34 this, 35 "connectToWorker", 36 "resource://devtools/server/connectors/worker-connector.js", 37 true 38 ); 39 40 XPCOMUtils.defineLazyServiceGetter( 41 this, 42 "swm", 43 "@mozilla.org/serviceworkers/manager;1", 44 Ci.nsIServiceWorkerManager 45 ); 46 47 class WorkerDescriptorActor extends Actor { 48 constructor(conn, dbg) { 49 super(conn, workerDescriptorSpec); 50 this._dbg = dbg; 51 52 this._threadActor = null; 53 this._transport = null; 54 55 this._dbgListener = { 56 onClose: this._onWorkerClose.bind(this), 57 onError: this._onWorkerError.bind(this), 58 }; 59 60 this._dbg.addListener(this._dbgListener); 61 this._attached = true; 62 } 63 64 form() { 65 const form = { 66 actor: this.actorID, 67 68 consoleActor: this._consoleActor, 69 threadActor: this._threadActor, 70 tracerActor: this._tracerActor, 71 72 targetType: this._targetType, 73 74 id: this._dbg.id, 75 url: this._dbg.url, 76 origin: this._dbg.principal.origin, 77 traits: {}, 78 type: this._dbg.type, 79 }; 80 if (this._dbg.type === Ci.nsIWorkerDebugger.TYPE_SERVICE) { 81 /** 82 * The ServiceWorkerManager in content processes don't maintain 83 * ServiceWorkerRegistrations; record the ServiceWorker's ID, and 84 * this data will be merged with the corresponding registration in 85 * the parent process. 86 */ 87 if (!DevToolsServer.isInChildProcess) { 88 const registration = this._getServiceWorkerRegistrationInfo(); 89 form.scope = registration.scope; 90 const newestWorker = 91 registration.activeWorker || 92 registration.waitingWorker || 93 registration.installingWorker; 94 form.fetch = newestWorker?.handlesFetchEvents; 95 } 96 } 97 return form; 98 } 99 100 detach() { 101 if (!this._attached) { 102 throw { error: "wrongState" }; 103 } 104 105 this.destroy(); 106 } 107 108 destroy() { 109 if (this._attached) { 110 this._detach(); 111 } 112 113 this.emit("descriptor-destroyed"); 114 super.destroy(); 115 } 116 117 async getTarget() { 118 if (!this._attached) { 119 return { error: "wrongState" }; 120 } 121 122 if (this._threadActor !== null) { 123 return { 124 type: "connected", 125 126 consoleActor: this._consoleActor, 127 threadActor: this._threadActor, 128 tracerActor: this._tracerActor, 129 130 targetType: this._targetType, 131 }; 132 } 133 134 try { 135 const { transport, workerTargetForm } = await connectToWorker( 136 this.conn, 137 this._dbg, 138 this.actorID, 139 { 140 sessionContext: createWorkerSessionContext(), 141 } 142 ); 143 144 this._consoleActor = workerTargetForm.consoleActor; 145 this._threadActor = workerTargetForm.threadActor; 146 this._tracerActor = workerTargetForm.tracerActor; 147 148 this._targetType = workerTargetForm.targetType; 149 150 this._transport = transport; 151 152 return { 153 type: "connected", 154 155 consoleActor: this._consoleActor, 156 threadActor: this._threadActor, 157 tracerActor: this._tracerActor, 158 159 targetType: this._targetType, 160 161 url: this._dbg.url, 162 }; 163 } catch (error) { 164 return { error: error.toString() }; 165 } 166 } 167 168 _onWorkerClose() { 169 this.destroy(); 170 } 171 172 _onWorkerError(filename, lineno, message) { 173 console.error("ERROR:", filename, ":", lineno, ":", message); 174 } 175 176 _getServiceWorkerRegistrationInfo() { 177 return swm.getRegistrationByPrincipal(this._dbg.principal, this._dbg.url); 178 } 179 180 _detach() { 181 if (this._threadActor !== null) { 182 this._transport.close(); 183 this._transport = null; 184 this._threadActor = null; 185 } 186 187 this._dbg.removeListener(this._dbgListener); 188 this._attached = false; 189 } 190 } 191 192 exports.WorkerDescriptorActor = WorkerDescriptorActor;