async disconnect() {
    this.actions.batchReset();

    // The timeline front wasn't initialized and started if the server wasn't
    // recent enough to emit the markers we were interested in.
    if (this.tabTarget.getTrait("documentLoadingMarkers") && this.timelineFront) {
      this.timelineFront.off("doc-loading", this.onDocLoadingMarker);
      await this.timelineFront.destroy();
    }

    this.tabTarget.off("will-navigate");
    this.tabTarget.off("close");
    this.tabTarget = null;
    this.webConsoleClient.off("networkEvent");
    this.webConsoleClient.off("networkEventUpdate");
    this.webConsoleClient = null;
    this.timelineFront = null;
  }
  async connect(connection, actions, getState) {
    this.actions = actions;
    this.getState = getState;
    this.tabTarget = connection.tabConnection.tabTarget;

    this.webConsoleClient = this.tabTarget.activeConsole;

    this.tabTarget.on("will-navigate", this.willNavigate);
    this.tabTarget.on("close", this.disconnect);
    this.webConsoleClient.on("networkEvent", this.onNetworkEvent);
    this.webConsoleClient.on("networkEventUpdate", this.onNetworkEventUpdate);

    // Don't start up waiting for timeline markers if the server isn't
    // recent enough to emit the markers we're interested in.
    if (this.tabTarget.getTrait("documentLoadingMarkers")) {
      this.timelineFront = new TimelineFront(this.tabTarget.client, this.tabTarget.form);
      this.timelineFront.on("doc-loading", this.onDocLoadingMarker);
      await this.timelineFront.start({ withDocLoadingEvents: true });
    }

    this.displayCachedEvents();
  }