[ui]: Add a debug track for a thread's critical path automatically

Added a 'critical path' button to the thread_state_tab that will
automatically generate the critical path for the entire thread
and create a debug track with that info.

The first click in a trace is a bit slow since it imports the
experimental.thread_executing_span stdlib module. But subsequent
clicks are instant.

Test: Manual

Change-Id: I803052606d46187ea6d80061735053cdb11c8743
diff --git a/ui/src/frontend/thread_state_tab.ts b/ui/src/frontend/thread_state_tab.ts
index 485b402..2768393 100644
--- a/ui/src/frontend/thread_state_tab.ts
+++ b/ui/src/frontend/thread_state_tab.ts
@@ -14,8 +14,10 @@
 
 import m from 'mithril';
 
+import {runQuery} from '../common/queries';
 import {Duration, time} from '../common/time';
 import {raf} from '../core/raf_scheduler';
+import {addDebugTrack} from '../tracks/debug/slice_track';
 
 import {Anchor} from './anchor';
 import {BottomTab, bottomTabRegistry, NewBottomTabArgs} from './bottom_tab';
@@ -33,6 +35,7 @@
   ThreadState,
   ThreadStateRef,
 } from './thread_state';
+import {Button} from './widgets/button';
 import {DetailsShell} from './widgets/details_shell';
 import {DurationWidget} from './widgets/duration';
 import {GridLayout} from './widgets/grid_layout';
@@ -226,10 +229,11 @@
       utid: state.thread!.utid,
       name,
     });
+    const sliceColumns = {ts: 'ts', dur: 'dur', name: 'thread_name'};
 
     const nameForNextOrPrev = (state: ThreadState) =>
         `${state.state} for ${Duration.humanise(state.dur)}`;
-    return m(
+    return [m(
         Tree,
         this.relatedStates.waker && m(TreeNode, {
           left: 'Waker',
@@ -263,8 +267,27 @@
                                  }),
                                  right: renderRef(
                                      state, getFullThreadName(state.thread)),
-                               })))),
-    );
+                  })))),
+      ), m(Button,
+           {
+          label: 'Critical path',
+          onclick: () => runQuery(`SELECT IMPORT('experimental.thread_executing_span');`, this.engine)
+              .then(() => addDebugTrack(
+              this.engine,
+                  {
+                    sqlSource:
+                  `
+                     SELECT ts, dur, thread_name, process_name, height
+                     FROM experimental_thread_executing_span_critical_path(
+                       NULL, ${this.state?.thread?.utid})
+                  `,
+                  columns: ['ts', 'dur', 'thread_name', 'process_name', 'height']
+                  },
+               `${this.state?.thread?.name}`,
+                  sliceColumns,
+                  ['ts', 'dur', 'thread_name', 'process_name', 'height'])),
+      }
+      )];
   }