Bug 1574156 - implement FrameDescriptor; r=ochameau
authoryulia <ystartsev@mozilla.com>
Tue, 27 Aug 2019 09:07:45 +0000
changeset 553773 5c69342869b413c4249304f8fd016603652fc809
parent 553772 c0535352f1201b8274a30fd7943d44e8a84ca9ed
child 553774 9a85c28fd033545e63ac5851f71c4d34a9436d28
push id2165
push userffxbld-merge
push dateMon, 14 Oct 2019 16:30:58 +0000
treeherdermozilla-release@0eae18af659f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau
bugs1574156
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1574156 - implement FrameDescriptor; r=ochameau Differential Revision: https://phabricator.services.mozilla.com/D42305
devtools/server/actors/descriptors/frame.js
devtools/server/actors/descriptors/moz.build
devtools/shared/fronts/descriptors/frame.js
devtools/shared/fronts/descriptors/moz.build
devtools/shared/specs/descriptors/frame.js
devtools/shared/specs/descriptors/moz.build
devtools/shared/specs/index.js
new file mode 100644
--- /dev/null
+++ b/devtools/server/actors/descriptors/frame.js
@@ -0,0 +1,91 @@
+/* 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 { ActorClassWithSpec, Actor } = require("devtools/shared/protocol");
+const {
+  frameDescriptorSpec,
+} = require("devtools/shared/specs/descriptors/frame");
+
+loader.lazyRequireGetter(
+  this,
+  "FrameConnector",
+  "devtools/server/connectors/frame-connector",
+  true
+);
+
+const FrameDescriptorActor = ActorClassWithSpec(frameDescriptorSpec, {
+  initialize(connection, browsingContext) {
+    if (typeof browsingContext.id != "number") {
+      throw Error("Frame Descriptor Connect requires a valid browsingContext.");
+    }
+    Actor.prototype.initialize.call(this, connection);
+    this.destroy = this.destroy.bind(this);
+    this.id = browsingContext.id;
+    this._browsingContext = browsingContext;
+    this._embedderElement = browsingContext.embedderElement;
+  },
+
+  /**
+   * Connect to a remote process actor, always a Frame target.
+   */
+  async _connectMessageManager() {
+    return FrameConnector.startServer(
+      this.conn,
+      this._embedderElement,
+      this.destroy
+    );
+  },
+
+  async _connectBrowsingContext() {
+    const id = this.id;
+    return {
+      error: "NoJSWindowAPISupport",
+      message: `The browsingContext '${id}' can only be accessed via JSWindowAPI`,
+    };
+  },
+
+  get _mm() {
+    // Get messageManager from XUL browser (which might be a specialized tunnel for RDM)
+    // or else fallback to asking the frameLoader itself.
+    return (
+      this._embedderElement &&
+      (this._embedderElement.messageManager ||
+        this._embedderElement.frameLoader.messageManager)
+    );
+  },
+
+  /**
+   * Connect the a frame actor.
+   */
+  async getTarget() {
+    let form;
+    if (this._mm) {
+      form = await this._connectMessageManager();
+    } else {
+      form = await this._connectBrowsingContext();
+    }
+
+    return form;
+  },
+
+  form() {
+    return {
+      actor: this.actorID,
+      id: this.id,
+      parentId: this._browsingContext.parent
+        ? this._browsingContext.parent.id
+        : null,
+    };
+  },
+
+  destroy() {
+    this._browsingContext = null;
+    this._embedderElement = null;
+    Actor.prototype.destroy.call(this);
+  },
+});
+
+exports.FrameDescriptorActor = FrameDescriptorActor;
--- a/devtools/server/actors/descriptors/moz.build
+++ b/devtools/server/actors/descriptors/moz.build
@@ -1,10 +1,11 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
+    'frame.js',
     'process.js',
 )
 
new file mode 100644
--- /dev/null
+++ b/devtools/shared/fronts/descriptors/frame.js
@@ -0,0 +1,83 @@
+/* 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 {
+  frameDescriptorSpec,
+} = require("devtools/shared/specs/descriptors/frame");
+
+loader.lazyRequireGetter(
+  this,
+  "BrowsingContextTargetFront",
+  "devtools/shared/fronts/targets/browsing-context",
+  true
+);
+
+const {
+  FrontClassWithSpec,
+  registerFront,
+} = require("devtools/shared/protocol");
+
+class FrameDescriptorFront extends FrontClassWithSpec(frameDescriptorSpec) {
+  constructor(client) {
+    super(client);
+    this._frameDescriptorFront = null;
+    this._targetFrontPromise = null;
+    this._client = client;
+  }
+
+  form(json) {
+    this.id = json.id;
+  }
+
+  async _createFrameTarget(form) {
+    let front = null;
+    front = new BrowsingContextTargetFront(this._client);
+    front.actorID = form.actor;
+    front.form(form);
+    this.manage(front);
+    return front;
+  }
+
+  async getTarget() {
+    if (this._frameTargetFront && this._frameTargetFront.actorID) {
+      return this._frameTargetFront;
+    }
+    if (this._targetFrontPromise) {
+      return this._targetFrontPromise;
+    }
+    this._targetFrontPromise = (async () => {
+      try {
+        const targetForm = await super.getTarget();
+        if (targetForm.error) {
+          this._targetFrontPromise = null;
+          return null;
+        }
+        this._frameTargetFront = await this._createFrameTarget(targetForm);
+        await this._frameTargetFront.attach();
+        // clear the promise if we are finished so that we can re-connect if
+        // necessary
+        this._targetFrontPromise = null;
+        return this._frameTargetFront;
+      } catch (e) {
+        // This is likely to happen if we get a lot of events which drop previous
+        // frames.
+        console.log(
+          `Request to connect to frameDescriptor "${this.id}" failed: ${e}`
+        );
+        return null;
+      }
+    })();
+    return this._targetFrontPromise;
+  }
+
+  destroy() {
+    this._frameTargetFront = null;
+    this._targetFrontPromise = null;
+    super.destroy();
+  }
+}
+
+exports.FrameDescriptorFront = FrameDescriptorFront;
+registerFront(FrameDescriptorFront);
--- a/devtools/shared/fronts/descriptors/moz.build
+++ b/devtools/shared/fronts/descriptors/moz.build
@@ -1,10 +1,11 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
+    'frame.js',
     'process.js',
 )
 
new file mode 100644
--- /dev/null
+++ b/devtools/shared/specs/descriptors/frame.js
@@ -0,0 +1,19 @@
+/* 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 { generateActorSpec, RetVal } = require("devtools/shared/protocol");
+
+const frameDescriptorSpec = generateActorSpec({
+  typeName: "frameDescriptor",
+
+  methods: {
+    getTarget: {
+      request: {},
+      response: { process: RetVal("json") },
+    },
+  },
+});
+
+exports.frameDescriptorSpec = frameDescriptorSpec;
--- a/devtools/shared/specs/descriptors/moz.build
+++ b/devtools/shared/specs/descriptors/moz.build
@@ -1,10 +1,11 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
+    'frame.js',
     'process.js',
 )
 
--- a/devtools/shared/specs/index.js
+++ b/devtools/shared/specs/index.js
@@ -53,16 +53,21 @@ const Types = (exports.__TypesForTests =
     front: "devtools/shared/fronts/changes",
   },
   {
     types: ["cssProperties"],
     spec: "devtools/shared/specs/css-properties",
     front: "devtools/shared/fronts/css-properties",
   },
   {
+    types: ["frameDescriptor"],
+    spec: "devtools/shared/specs/descriptors/frame",
+    front: "devtools/shared/fronts/descriptors/frame",
+  },
+  {
     types: ["processDescriptor"],
     spec: "devtools/shared/specs/descriptors/process",
     front: "devtools/shared/fronts/descriptors/process",
   },
   {
     types: ["device"],
     spec: "devtools/shared/specs/device",
     front: "devtools/shared/fronts/device",