Commit 341261cd authored by Julian Descottes's avatar Julian Descottes
Browse files

Bug 1833656 - [devtools] Support multiple pages in HAR with filtered requests...

Bug 1833656 - [devtools] Support multiple pages in HAR with filtered requests r=bomsy,ochameau,devtools-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D178336
parent 4ad4deab
Loading
Loading
Loading
Loading
+97 −0
Original line number Diff line number Diff line
/* 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 {
  TYPES,
} = require("resource://devtools/shared/commands/resource/resource-command.js");

/**
 * This collector class is dedicated to recording additional metadata necessary
 * to build HAR files. The actual request data will be provided by the
 * netmonitor which is already monitoring for requests.
 *
 * The only purpose of this class is to record additional document and network
 * events, which will help to assign requests to individual pages.
 *
 * It should be created and destroyed by the main netmonitor data collector.
 */
class HarMetadataCollector {
  #commands;
  #initialTargetTitle;
  #navigationRequests;
  #targetTitlesPerURL;

  constructor(commands) {
    this.#commands = commands;
  }

  /**
   * Stop recording and clear the state.
   */
  destroy() {
    this.clear();

    this.#commands.resourceCommand.unwatchResources(
      [TYPES.DOCUMENT_EVENT, TYPES.NETWORK_EVENT],
      {
        onAvailable: this.#onResourceAvailable,
      }
    );
  }

  /**
   * Reset the current state.
   */
  clear() {
    this.#navigationRequests = [];
    this.#targetTitlesPerURL = new Map();
    this.#initialTargetTitle = this.#commands.targetCommand.targetFront.title;
  }

  /**
   * Start recording additional events for HAR files building.
   */
  async connect() {
    this.clear();

    await this.#commands.resourceCommand.watchResources(
      [TYPES.DOCUMENT_EVENT, TYPES.NETWORK_EVENT],
      {
        onAvailable: this.#onResourceAvailable,
      }
    );
  }

  getHarData() {
    return {
      initialTargetTitle: this.#initialTargetTitle,
      navigationRequests: this.#navigationRequests,
      targetTitlesPerURL: this.#targetTitlesPerURL,
    };
  }

  #onResourceAvailable = resources => {
    for (const resource of resources) {
      if (resource.resourceType === TYPES.DOCUMENT_EVENT) {
        if (
          resource.name === "dom-complete" &&
          resource.targetFront.isTopLevel
        ) {
          this.#targetTitlesPerURL.set(
            resource.targetFront.url,
            resource.targetFront.title
          );
        }
      } else if (resource.resourceType === TYPES.NETWORK_EVENT) {
        if (resource.isNavigationRequest) {
          this.#navigationRequests.push(resource);
        }
      }
    }
  };
}

exports.HarMetadataCollector = HarMetadataCollector;
+13 −19
Original line number Diff line number Diff line
@@ -25,6 +25,13 @@ loader.lazyRequireGetter(
  "resource://devtools/client/shared/components/throttling/profiles.js"
);

loader.lazyRequireGetter(
  this,
  "HarMetadataCollector",
  "resource://devtools/client/netmonitor/src/connector/har-metadata-collector.js",
  true
);

const DEVTOOLS_ENABLE_PERSISTENT_LOG_PREF = "devtools.netmonitor.persistlog";

/**
@@ -89,8 +96,8 @@ class Connector {
      owner: this.owner,
    });

    this._initialTargetTitle = this.currentTarget.title;
    this._targetTitlesPerURL = new Map();
    this._harMetadataCollector = new HarMetadataCollector(this.commands);
    await this._harMetadataCollector.connect();

    await this.commands.resourceCommand.watchResources([TYPES.DOCUMENT_EVENT], {
      onAvailable: this.onResourceAvailable,
@@ -134,16 +141,14 @@ class Connector {

    this.dataProvider.destroy();
    this.dataProvider = null;

    this._targetTitlesPerURL = new Map();
    this._harMetadataCollector.destroy();
  }

  clear() {
    // Clear all the caches in the data provider
    this.dataProvider.clear();

    this._initialTargetTitle = this.currentTarget.title;
    this._targetTitlesPerURL = new Map();
    this._harMetadataCollector.clear();

    this.commands.resourceCommand.clearResources(Connector.NETWORK_RESOURCES);
    this.emitForTests("clear-network-resources");
@@ -347,10 +352,6 @@ class Connector {
    }

    if (resource.name === "dom-complete") {
      this._targetTitlesPerURL.set(
        resource.targetFront.url,
        resource.targetFront.title
      );
      this.navigate();
    }

@@ -466,15 +467,8 @@ class Connector {
  /**
   * Used for HAR generation.
   */
  getTargetTitlesPerURL() {
    return this._targetTitlesPerURL;
  }

  /**
   * Used for HAR generation.
   */
  getInitialTargetTitle() {
    return this._initialTargetTitle;
  getHarData() {
    return this._harMetadataCollector.getHarData();
  }

  /**
+1 −0
Original line number Diff line number Diff line
@@ -4,5 +4,6 @@

DevToolsModules(
    "firefox-data-provider.js",
    "har-metadata-collector.js",
    "index.js",
)
+151 −171

File changed.

Preview size limit exceeded, changes collapsed.

+2 −14
Original line number Diff line number Diff line
@@ -196,27 +196,15 @@ const HarExporter = {
   * long strings).
   */
  async buildHarData(options) {
    const { connector } = options;

    // Disconnect from redux actions/store.
    connector.enableActions(false);

    options = {
      ...options,
      getString: connector.getLongString,
      getTimingMarker: connector.getTimingMarker,
      initialTargetTitle: connector.getInitialTargetTitle(),
      requestData: connector.requestData,
      targetTitlesPerURL: connector.getTargetTitlesPerURL(),
      title: connector.currentTarget.title,
    };
    options.connector.enableActions(false);

    // Build HAR object from collected data.
    const builder = new HarBuilder(options);
    const result = await builder.build();

    // Connect to redux actions again.
    connector.enableActions(true);
    options.connector.enableActions(true);

    return result;
  },
Loading