Bug 1625942: Introduce ResourceWatcher into network monitor to fetch DocumentEvents. r=ochameau
☠☠ backed out by 84a01c8388d5 ☠ ☠
authorDaisuke Akatsuka <daisuke@birchill.co.jp>
Fri, 17 Apr 2020 08:13:23 +0000
changeset 524562 743e1ce65e061403c0fca63f0b76301c08b480a4
parent 524561 141e29d9f70a1b63f49b5e8e2ea5d49415039ee7
child 524563 4255bd054e34fcaf2a5e5d2c9b1dba9f2fe4e2d8
push id37323
push userdluca@mozilla.com
push dateFri, 17 Apr 2020 16:25:55 +0000
treeherdermozilla-central@b4b1d6f91ef0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau
bugs1625942
milestone77.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 1625942: Introduce ResourceWatcher into network monitor to fetch DocumentEvents. r=ochameau Differential Revision: https://phabricator.services.mozilla.com/D69329
devtools/client/netmonitor/src/connector/firefox-connector.js
devtools/server/actors/webconsole/listeners/document-events.js
devtools/shared/resources/resource-watcher.js
--- a/devtools/client/netmonitor/src/connector/firefox-connector.js
+++ b/devtools/client/netmonitor/src/connector/firefox-connector.js
@@ -28,30 +28,30 @@ loader.lazyRequireGetter(
 class FirefoxConnector {
   constructor() {
     // Public methods
     this.connect = this.connect.bind(this);
     this.disconnect = this.disconnect.bind(this);
     this.willNavigate = this.willNavigate.bind(this);
     this.navigate = this.navigate.bind(this);
     this.displayCachedEvents = this.displayCachedEvents.bind(this);
-    this.onDocEvent = this.onDocEvent.bind(this);
     this.sendHTTPRequest = this.sendHTTPRequest.bind(this);
     this.setPreferences = this.setPreferences.bind(this);
     this.triggerActivity = this.triggerActivity.bind(this);
     this.getTabTarget = this.getTabTarget.bind(this);
     this.viewSourceInDebugger = this.viewSourceInDebugger.bind(this);
     this.requestData = this.requestData.bind(this);
     this.getTimingMarker = this.getTimingMarker.bind(this);
     this.updateNetworkThrottling = this.updateNetworkThrottling.bind(this);
 
     // Internals
     this.getLongString = this.getLongString.bind(this);
     this.getNetworkRequest = this.getNetworkRequest.bind(this);
     this.onTargetAvailable = this.onTargetAvailable.bind(this);
+    this.onResourceAvailable = this.onResourceAvailable.bind(this);
   }
 
   get currentTarget() {
     return this.toolbox.targetList.targetFront;
   }
 
   /**
    * Connect to the backend.
@@ -67,31 +67,41 @@ class FirefoxConnector {
 
     // The owner object (NetMonitorAPI) received all events.
     this.owner = connection.owner;
 
     await this.toolbox.targetList.watchTargets(
       [this.toolbox.targetList.TYPES.FRAME],
       this.onTargetAvailable
     );
+
+    await this.toolbox.resourceWatcher.watch(
+      [this.toolbox.resourceWatcher.TYPES.DOCUMENT_EVENTS],
+      this.onResourceAvailable
+    );
   }
 
   disconnect() {
     // As this function might be called twice, we need to guard if already called.
     if (this._destroyed) {
       return;
     }
 
     this._destroyed = true;
 
     this.toolbox.targetList.unwatchTargets(
       [this.toolbox.targetList.TYPES.FRAME],
       this.onTargetAvailable
     );
 
+    this.toolbox.resourceWatcher.unwatch(
+      [this.toolbox.resourceWatcher.TYPES.DOCUMENT_EVENTS],
+      this.onResourceAvailable
+    );
+
     if (this.actions) {
       this.actions.batchReset();
     }
 
     this.removeListeners();
 
     this.currentTarget.off("will-navigate", this.willNavigate);
     this.currentTarget.off("navigate", this.navigate);
@@ -140,23 +150,28 @@ class FirefoxConnector {
     this.responsiveFront = await this.currentTarget.getFront("responsive");
 
     // Displaying cache events is only intended for the UI panel.
     if (this.actions) {
       this.displayCachedEvents();
     }
   }
 
+  async onResourceAvailable({ resourceType, targetFront, resource }) {
+    if (resourceType === this.toolbox.resourceWatcher.TYPES.DOCUMENT_EVENTS) {
+      this.onDocEvent(resource);
+    }
+  }
+
   async addListeners() {
     this.webConsoleFront.on("networkEvent", this.dataProvider.onNetworkEvent);
     this.webConsoleFront.on(
       "networkEventUpdate",
       this.dataProvider.onNetworkEventUpdate
     );
-    this.webConsoleFront.on("documentEvent", this.onDocEvent);
 
     // Support for WebSocket monitoring is currently hidden behind this pref.
     if (Services.prefs.getBoolPref("devtools.netmonitor.features.webSockets")) {
       try {
         // Initialize WebSocket front to intercept websocket traffic.
         const webSocketFront = await this.currentTarget.getFront("webSocket");
         webSocketFront.startListening();
 
@@ -169,20 +184,16 @@ class FirefoxConnector {
           this.dataProvider.onWebSocketClosed
         );
         webSocketFront.on("frameReceived", this.dataProvider.onFrameReceived);
         webSocketFront.on("frameSent", this.dataProvider.onFrameSent);
       } catch (e) {
         // Support for FF68 or older
       }
     }
-
-    // The console actor supports listening to document events like
-    // DOMContentLoaded and load.
-    await this.webConsoleFront.startListeners(["DocumentEvents"]);
   }
 
   removeListeners() {
     const webSocketFront = this.currentTarget.getCachedFront("webSocket");
     if (webSocketFront) {
       webSocketFront.off(
         "webSocketOpened",
         this.dataProvider.onWebSocketOpened
@@ -199,17 +210,16 @@ class FirefoxConnector {
       this.webConsoleFront.off(
         "networkEvent",
         this.dataProvider.onNetworkEvent
       );
       this.webConsoleFront.off(
         "networkEventUpdate",
         this.dataProvider.onNetworkEventUpdate
       );
-      this.webConsoleFront.off("docEvent", this.onDocEvent);
     }
   }
 
   enableActions(enable) {
     this.dataProvider.enableActions(enable);
   }
 
   willNavigate() {
--- a/devtools/server/actors/webconsole/listeners/document-events.js
+++ b/devtools/server/actors/webconsole/listeners/document-events.js
@@ -41,16 +41,24 @@ DocumentEventsListener.prototype = {
       return;
     }
 
     // Ignore iframes
     if (!isTopLevel) {
       return;
     }
 
+    const packet = {
+      from: this.console.actorID,
+      type: "documentEvent",
+      name: "dom-loading",
+      time: window.performance.timing.navigationStart,
+    };
+    this.console.conn.send(packet);
+
     const { readyState } = window.document;
     if (readyState != "interactive" && readyState != "complete") {
       window.addEventListener("DOMContentLoaded", this.onContentLoaded, {
         once: true,
       });
     } else {
       this.onContentLoaded({ target: window.document });
     }
--- a/devtools/shared/resources/resource-watcher.js
+++ b/devtools/shared/resources/resource-watcher.js
@@ -296,16 +296,17 @@ class ResourceWatcher {
     // We are aware of one case where that might be useful.
     // When a panel is disabled via the options panel, after it has been opened.
     // Would that justify doing this? Is there another usecase?
   }
 }
 
 ResourceWatcher.TYPES = ResourceWatcher.prototype.TYPES = {
   CONSOLE_MESSAGES: "console-messages",
+  DOCUMENT_EVENTS: "document-events",
 };
 module.exports = { ResourceWatcher };
 
 // Backward compat code for each type of resource.
 // Each section added here should eventually be removed once the equivalent server
 // code is implement in Firefox, in its release channel.
 const LegacyListeners = {
   // Bug 1620243 aims at implementing this from the actor and will eventually replace
@@ -346,9 +347,25 @@ const LegacyListeners = {
       "ConsoleAPI",
     ]);
     // Wrap the message into a `message` attribute, to match `consoleAPICall` behavior
     messages.map(message => ({ message })).forEach(onAvailable);
 
     // Forward new message events
     webConsoleFront.on("consoleAPICall", onAvailable);
   },
+  async [ResourceWatcher.TYPES.DOCUMENT_EVENTS]({
+    targetList,
+    targetType,
+    targetFront,
+    isTopLevel,
+    onAvailable,
+  }) {
+    // DocumentEventsListener of webconsole handles only top level document.
+    if (!isTopLevel) {
+      return;
+    }
+
+    const webConsoleFront = await targetFront.getFront("console");
+    webConsoleFront.on("documentEvent", onAvailable);
+    await webConsoleFront.startListeners(["DocumentEvents"]);
+  },
 };