From a2f0af32b2814968f7670546f4804a8716843ec2 Mon Sep 17 00:00:00 2001 From: yulia Date: Fri, 14 Jun 2019 00:18:25 +0000 Subject: [PATCH] Bug 1494796 - maintain backwards compatibility r=jdescottes Introduce a flag to maintain backwards compatibility with old servers Differential Revision: https://phabricator.services.mozilla.com/D34184 --HG-- extra : moz-landing-system : lando --- devtools/server/actors/root.js | 2 + devtools/shared/client/debugger-client.js | 76 ++++++++++++++----- .../shared/client/deprecated-thread-client.js | 18 +++-- .../shared/fronts/targets/target-mixin.js | 12 ++- 4 files changed, 82 insertions(+), 26 deletions(-) diff --git a/devtools/server/actors/root.js b/devtools/server/actors/root.js index fea1e9a7cf8b..99bb26f391a5 100644 --- a/devtools/server/actors/root.js +++ b/devtools/server/actors/root.js @@ -173,6 +173,8 @@ RootActor.prototype = { // Supports native log points and modifying the condition/log of an existing // breakpoints. Fx66+ nativeLogpoints: true, + // support older browsers for Fx69+ + hasThreadFront: true, }, /** diff --git a/devtools/shared/client/debugger-client.js b/devtools/shared/client/debugger-client.js index b81bf47baf6a..d3a4ede32f19 100644 --- a/devtools/shared/client/debugger-client.js +++ b/devtools/shared/client/debugger-client.js @@ -550,6 +550,13 @@ DebuggerClient.prototype = { return; } + // support older browsers for Fx69+ for using the old thread client + if (!this.traits.hasThreadFront && + packet.from.includes("context")) { + this.sendToDeprecatedThreadClient(packet); + return; + } + // If we have a registered Front for this actor, let it handle the packet // and skip all the rest of this unpleasantness. const front = this.getActor(packet.from); @@ -558,24 +565,12 @@ DebuggerClient.prototype = { return; } - if (this._clients.has(packet.from) && packet.type) { - const client = this._clients.get(packet.from); - const type = packet.type; - if (client.events.includes(type)) { - client.emit(type, packet); - // we ignore the rest, as the client is expected to handle this packet. - return; - } - } - let activeRequest; // See if we have a handler function waiting for a reply from this // actor. (Don't count unsolicited notifications or pauses as // replies.) if (this._activeRequests.has(packet.from) && - !(packet.type in UnsolicitedNotifications) && - !(packet.type == ThreadStateTypes.paused && - packet.why.type in UnsolicitedPauses)) { + !(packet.type in UnsolicitedNotifications)) { activeRequest = this._activeRequests.get(packet.from); this._activeRequests.delete(packet.from); } @@ -585,13 +580,6 @@ DebuggerClient.prototype = { // in the local transport case. this._attemptNextRequest(packet.from); - // Packets that indicate thread state changes get special treatment. - if (packet.type in ThreadStateTypes && - this._clients.has(packet.from) && - typeof this._clients.get(packet.from)._onThreadState == "function") { - this._clients.get(packet.from)._onThreadState(packet); - } - // Only try to notify listeners on events, not responses to requests // that lack a packet type. if (packet.type) { @@ -609,6 +597,54 @@ DebuggerClient.prototype = { } }, + // support older browsers for Fx69+ + // The code duplication here is intentional until we drop support for + // these versions. Once that happens this code can be deleted. + sendToDeprecatedThreadClient(packet) { + const deprecatedThreadClient = this.getActor(packet.from); + if (deprecatedThreadClient && packet.type) { + const type = packet.type; + if (deprecatedThreadClient.events.includes(type)) { + deprecatedThreadClient.emit(type, packet); + // we ignore the rest, as the client is expected to handle this packet. + return; + } + } + + let activeRequest; + // See if we have a handler function waiting for a reply from this + // actor. (Don't count unsolicited notifications or pauses as + // replies.) + if (this._activeRequests.has(packet.from) && + !(packet.type == ThreadStateTypes.paused && + packet.why.type in UnsolicitedPauses)) { + activeRequest = this._activeRequests.get(packet.from); + this._activeRequests.delete(packet.from); + } + + // If there is a subsequent request for the same actor, hand it off to the + // transport. Delivery of packets on the other end is always async, even + // in the local transport case. + this._attemptNextRequest(packet.from); + + // Packets that indicate thread state changes get special treatment. + if (packet.type in ThreadStateTypes && + deprecatedThreadClient && + typeof deprecatedThreadClient._onThreadState == "function") { + deprecatedThreadClient._onThreadState(packet); + } + + // Only try to notify listeners on events, not responses to requests + // that lack a packet type. + if (packet.type) { + this.emit(packet.type, packet); + } + + if (activeRequest) { + activeRequest.emit("json-reply", packet); + } + }, + /** * Called by the DebuggerTransport to dispatch incoming bulk packets as * appropriate. diff --git a/devtools/shared/client/deprecated-thread-client.js b/devtools/shared/client/deprecated-thread-client.js index ec30a0a298e5..2bb54a7c0f06 100644 --- a/devtools/shared/client/deprecated-thread-client.js +++ b/devtools/shared/client/deprecated-thread-client.js @@ -227,10 +227,18 @@ ThreadClient.prototype = { */ detach: DebuggerClient.requester({ type: "detach", - }, { - after: function(response) { - return response; - }, + }), + + destroy: function() { + return this.detach(); + }, + + /** + * attach to the thread actor. + */ + attach: DebuggerClient.requester({ + type: "attach", + options: arg(0), }), /** @@ -341,7 +349,7 @@ ThreadClient.prototype = { // The debugger UI may not be initialized yet so we want to keep // the packet around so it knows what to pause state to display // when it's initialized - this._lastPausePacket = packet; + this._lastPausePacket = packet.type === "resumed" ? null : packet; this._clearPauseGrips(); packet.type === ThreadStateTypes.detached && this._clearThreadGrips(); this.client._eventsEnabled && this.emit(packet.type, packet); diff --git a/devtools/shared/fronts/targets/target-mixin.js b/devtools/shared/fronts/targets/target-mixin.js index f5ba2d1941fe..384146db795b 100644 --- a/devtools/shared/fronts/targets/target-mixin.js +++ b/devtools/shared/fronts/targets/target-mixin.js @@ -10,6 +10,7 @@ // used by a subclass, specific to local tabs. loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true); loader.lazyRequireGetter(this, "TargetFactory", "devtools/client/framework/target", true); +loader.lazyRequireGetter(this, "ThreadClient", "devtools/shared/client/deprecated-thread-client"); loader.lazyRequireGetter(this, "getFront", "devtools/shared/protocol", true); /** @@ -404,7 +405,16 @@ function TargetMixin(parentClass) { "TargetMixin sub class should set _threadActor before calling " + "attachThread" ); } - this.threadClient = await this.getFront("context"); + if (this.getTrait("hasThreadFront")) { + this.threadClient = await this.getFront("context"); + } else { + // Backwards compat for Firefox 68 + // mimics behavior of a front + this.threadClient = new ThreadClient(this._client, this._threadActor); + this.fronts.set("context", this.threadClient); + this.threadClient.actorID = this._threadActor; + this.manage(this.threadClient); + } const result = await this.threadClient.attach(options); this.threadClient.on("newSource", this._onNewSource);