summaryrefslogtreecommitdiffstats
path: root/devtools/client/fronts/descriptors/descriptor-mixin.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/fronts/descriptors/descriptor-mixin.js')
-rw-r--r--devtools/client/fronts/descriptors/descriptor-mixin.js60
1 files changed, 60 insertions, 0 deletions
diff --git a/devtools/client/fronts/descriptors/descriptor-mixin.js b/devtools/client/fronts/descriptors/descriptor-mixin.js
new file mode 100644
index 0000000000..ac38e104b5
--- /dev/null
+++ b/devtools/client/fronts/descriptors/descriptor-mixin.js
@@ -0,0 +1,60 @@
+/* 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";
+
+/**
+ * A Descriptor represents a debuggable context. It can be a browser tab, a tab on
+ * a remote device, like a tab on Firefox for Android. But it can also be an add-on,
+ * as well as firefox parent process, or just one of its content process.
+ * It can be very similar to a Target. The key difference is the lifecycle of these two classes.
+ * The descriptor is meant to be always alive and meaningful/usable until the end of the RDP connection.
+ * Typically a Tab Descriptor will describe the tab and not the one document currently loaded in this tab,
+ * while the Target, will describe this one document and a new Target may be created on each navigation.
+ */
+function DescriptorMixin(parentClass) {
+ class Descriptor extends parentClass {
+ constructor(client, targetFront, parentFront) {
+ super(client, targetFront, parentFront);
+
+ this._client = client;
+
+ // Pass a true value in order to distinguish this event reception
+ // from any manual destroy caused by the frontend
+ this.on(
+ "descriptor-destroyed",
+ this.destroy.bind(this, { isServerDestroyEvent: true })
+ );
+ }
+
+ get client() {
+ return this._client;
+ }
+
+ async destroy({ isServerDestroyEvent } = {}) {
+ if (this.isDestroyed()) {
+ return;
+ }
+ // This workaround is mostly done for Workers, as WorkerDescriptor
+ // extends the Target class, which causes some issue down the road:
+ // In Target.destroy, we call WorkerDescriptorActor.detach *before* calling super.destroy(),
+ // and so hold on before calling Front.destroy() which would reject all pending requests, including detach().
+ // When calling detach, the server will emit "descriptor-destroyed", which will call Target.destroy again,
+ // but will still be blocked on detach resolution and won't call Front.destroy, and won't reject pending requests either.
+ //
+ // So call Front.baseFrontClassDestroyed manually from here, so that we ensure rejecting the pending detach request
+ // and unblock Target.destroy resolution.
+ //
+ // Here is the inheritance chain for WorkerDescriptor:
+ // WorkerDescriptor -> Descriptor (from descriptor-mixin.js) -> Target (from target-mixin.js) -> Front (protocol.js) -> Pool (protocol.js) -> EventEmitter
+ if (isServerDestroyEvent) {
+ this.baseFrontClassDestroy();
+ }
+
+ await super.destroy();
+ }
+ }
+ return Descriptor;
+}
+exports.DescriptorMixin = DescriptorMixin;