DevTools: Remove _pendingPerformanceModel

Change-Id: Id6c781b5f3d113d6575f314b301f923c4221b83d
Reviewed-on: https://chromium-review.googlesource.com/998675
Commit-Queue: Alexei Filippov <alph@chromium.org>
Reviewed-by: Dmitry Gozman <dgozman@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#548666}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 001da8df2a9ba65969eb552fcf491c1a17ca9aff
diff --git a/front_end/performance_test_runner/TimelineTestRunner.js b/front_end/performance_test_runner/TimelineTestRunner.js
index b3a0ad6..ee79361 100644
--- a/front_end/performance_test_runner/TimelineTestRunner.js
+++ b/front_end/performance_test_runner/TimelineTestRunner.js
@@ -89,7 +89,7 @@
     categories += ',' + additionalCategories;
 
   const timelinePanel = UI.panels.timeline;
-  const timelineController = PerformanceTestRunner.timelineController();
+  const timelineController = PerformanceTestRunner.createTimelineController();
   timelinePanel._timelineController = timelineController;
   timelineController._startRecordingWithCategories(categories, enableJSSampling).then(tracingStarted);
 
@@ -126,10 +126,10 @@
   return performanceModel;
 };
 
-PerformanceTestRunner.timelineController = function() {
-  const performanceModel = new Timeline.PerformanceModel();
-  UI.panels.timeline._pendingPerformanceModel = performanceModel;
-  return new Timeline.TimelineController(TestRunner.tracingManager, performanceModel, UI.panels.timeline);
+PerformanceTestRunner.createTimelineController = function() {
+  const controller = new Timeline.TimelineController(SDK.targetManager.mainTarget(), UI.panels.timeline);
+  controller._tracingManager = TestRunner.tracingManager;
+  return controller;
 };
 
 PerformanceTestRunner.runWhenTimelineIsReady = function(callback) {
diff --git a/front_end/timeline/TimelineController.js b/front_end/timeline/TimelineController.js
index 6b46dac..7a01424 100644
--- a/front_end/timeline/TimelineController.js
+++ b/front_end/timeline/TimelineController.js
@@ -9,20 +9,18 @@
  */
 Timeline.TimelineController = class {
   /**
-   * @param {!SDK.TracingManager} tracingManager
-   * @param {!Timeline.PerformanceModel} performanceModel
+   * @param {!SDK.Target} target
    * @param {!Timeline.TimelineController.Client} client
    */
-  constructor(tracingManager, performanceModel, client) {
-    this._tracingManager = tracingManager;
-    this._performanceModel = performanceModel;
+  constructor(target, client) {
+    this._tracingManager = target.model(SDK.TracingManager);
+    this._performanceModel = new Timeline.PerformanceModel();
+    this._performanceModel.setMainTarget(target);
     this._client = client;
 
     const backingStorage = new Bindings.TempFileBackingStorage();
     this._tracingModel = new SDK.TracingModel(backingStorage);
 
-    this._performanceModel.setMainTarget(tracingManager.target());
-
     /** @type {!Array<!Timeline.ExtensionTracingSession>} */
     this._extensionSessions = [];
     SDK.targetManager.observeModels(SDK.CPUProfilerModel, this);
@@ -86,7 +84,10 @@
     return startPromise;
   }
 
-  stopRecording() {
+  /**
+   * @return {!Promise<!Timeline.PerformanceModel>}
+   */
+  async stopRecording() {
     const tracingStoppedPromises = [];
     tracingStoppedPromises.push(new Promise(resolve => this._tracingCompleteCallback = resolve));
     tracingStoppedPromises.push(this._stopProfilingOnAllModels());
@@ -97,12 +98,12 @@
 
     const extensionCompletionPromises = this._extensionSessions.map(session => session.stop());
     if (extensionCompletionPromises.length) {
-      let timerId;
-      const timeoutPromise = new Promise(fulfill => timerId = setTimeout(fulfill, 5000));
       tracingStoppedPromises.push(
-          Promise.race([Promise.all(extensionCompletionPromises).then(() => clearTimeout(timerId)), timeoutPromise]));
+          Promise.race([Promise.all(extensionCompletionPromises), new Promise(r => setTimeout(r, 5000))]));
     }
-    Promise.all(tracingStoppedPromises).then(() => this._allSourcesFinished());
+    await Promise.all(tracingStoppedPromises);
+    this._allSourcesFinished();
+    return this._performanceModel;
   }
 
   /**
diff --git a/front_end/timeline/TimelineLoader.js b/front_end/timeline/TimelineLoader.js
index 6bb573a..fb7920a 100644
--- a/front_end/timeline/TimelineLoader.js
+++ b/front_end/timeline/TimelineLoader.js
@@ -55,17 +55,15 @@
 
     setTimeout(async () => {
       const eventsPerChunk = 5000;
-      const yieldEventLoopToPaint = () => new Promise(res => setTimeout(res, 0));
-
       client.loadingStarted();
       for (let i = 0; i < events.length; i += eventsPerChunk) {
         const chunk = events.slice(i, i + eventsPerChunk);
         loader._tracingModel.addEvents(chunk);
         client.loadingProgress((i + chunk.length) / events.length);
-        await yieldEventLoopToPaint();
+        await new Promise(r => setTimeout(r));  // Yield event loop to paint.
       }
       loader.close();
-    }, 0);
+    });
 
     return loader;
   }
diff --git a/front_end/timeline/TimelinePanel.js b/front_end/timeline/TimelinePanel.js
index b0a521f..3ad001e 100644
--- a/front_end/timeline/TimelinePanel.js
+++ b/front_end/timeline/TimelinePanel.js
@@ -64,8 +64,6 @@
 
     /** @type {?Timeline.PerformanceModel} */
     this._performanceModel = null;
-    /** @type {?Timeline.PerformanceModel} */
-    this._pendingPerformanceModel = null;
 
     this._viewModeSetting =
         Common.settings.createSetting('timelineViewMode', Timeline.TimelinePanel.ViewMode.FlameChart);
@@ -331,7 +329,10 @@
   _prepareToLoadTimeline() {
     console.assert(this._state === Timeline.TimelinePanel.State.Idle);
     this._setState(Timeline.TimelinePanel.State.Loading);
-    this._pendingPerformanceModel = new Timeline.PerformanceModel();
+    if (this._performanceModel) {
+      this._performanceModel.dispose();
+      this._performanceModel = null;
+    }
   }
 
   _createFileSelector() {
@@ -479,11 +480,7 @@
   /**
    * @return {!Promise}
    */
-  _startRecording() {
-    const tracingManagers = SDK.targetManager.models(SDK.TracingManager);
-    if (!tracingManagers.length)
-      return Promise.resolve();
-
+  async _startRecording() {
     console.assert(!this._statusPane, 'Status pane is already opened.');
     this._setState(Timeline.TimelinePanel.State.StartPending);
     this._showRecordingStarted();
@@ -497,24 +494,24 @@
       captureFilmStrip: this._showScreenshotsSetting.get()
     };
 
-    this._pendingPerformanceModel = new Timeline.PerformanceModel();
-    this._controller = new Timeline.TimelineController(tracingManagers[0], this._pendingPerformanceModel, this);
+    const mainTarget = /** @type {!SDK.Target} */ (SDK.targetManager.mainTarget());
+    this._controller = new Timeline.TimelineController(mainTarget, this);
     this._setUIControlsEnabled(false);
     this._hideLandingPage();
-    return this._controller.startRecording(recordingOptions, enabledTraceProviders)
-        .then(() => this._recordingStarted());
+    await this._controller.startRecording(recordingOptions, enabledTraceProviders);
+    this._recordingStarted();
   }
 
-  _stopRecording() {
+  async _stopRecording() {
     if (this._statusPane) {
       this._statusPane.finish();
       this._statusPane.updateStatus(Common.UIString('Stopping timeline\u2026'));
       this._statusPane.updateProgressBar(Common.UIString('Received'), 0);
     }
     this._setState(Timeline.TimelinePanel.State.StopPending);
-    this._controller.stopRecording();
-    this._controller = null;
+    this._performanceModel = await this._controller.stopRecording();
     this._setUIControlsEnabled(true);
+    this._controller = null;
   }
 
   _onSuspendStateChanged() {
@@ -720,22 +717,21 @@
   loadingComplete(tracingModel) {
     delete this._loader;
     this._setState(Timeline.TimelinePanel.State.Idle);
-    const performanceModel = this._pendingPerformanceModel;
-    this._pendingPerformanceModel = null;
 
     if (this._statusPane)
       this._statusPane.hide();
     delete this._statusPane;
 
     if (!tracingModel) {
-      performanceModel.dispose();
       this._clear();
       return;
     }
 
-    performanceModel.setTracingModel(tracingModel);
-    this._setModel(performanceModel);
-    this._historyManager.addRecording(performanceModel);
+    if (!this._performanceModel)
+      this._performanceModel = new Timeline.PerformanceModel();
+    this._performanceModel.setTracingModel(tracingModel);
+    this._setModel(this._performanceModel);
+    this._historyManager.addRecording(this._performanceModel);
   }
 
   _showRecordingStarted() {
@@ -772,23 +768,18 @@
   /**
    * @param {!Common.Event} event
    */
-  _loadEventFired(event) {
+  async _loadEventFired(event) {
     if (this._state !== Timeline.TimelinePanel.State.Recording || !this._recordingPageReload ||
         this._controller.mainTarget() !== event.data.resourceTreeModel.target())
       return;
-    setTimeout(stopRecordingOnReload.bind(this, this._controller), this._millisecondsToRecordAfterLoadEvent);
+    const controller = this._controller;
+    await new Promise(r => setTimeout(r, this._millisecondsToRecordAfterLoadEvent));
 
-    /**
-     * @param {!Timeline.TimelineController} controller
-     * @this {Timeline.TimelinePanel}
-     */
-    function stopRecordingOnReload(controller) {
-      // Check if we're still in the same recording session.
-      if (controller !== this._controller)
-        return;
-      this._recordingPageReload = false;
-      this._stopRecording();
-    }
+    // Check if we're still in the same recording session.
+    if (controller !== this._controller)
+      return;
+    this._recordingPageReload = false;
+    this._stopRecording();
   }
 
   /**