1// Copyright (C) 2023 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// Copyright (C) 2023 The Android Open Source Project 16// 17// Licensed under the Apache License, Version 2.0 (the "License"); 18// you may not use this file except in compliance with the License. 19// You may obtain a copy of the License at 20// 21// http://www.apache.org/licenses/LICENSE-2.0 22// 23// Unless required by applicable law or agreed to in writing, software 24// distributed under the License is distributed on an "AS IS" BASIS, 25// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26// See the License for the specific language governing permissions and 27// limitations under the License. 28 29import m from 'mithril'; 30import {duration, Time, time} from '../../base/time'; 31import {asUpid, Upid} from '../../components/sql_utils/core_types'; 32import {DurationWidget} from '../../components/widgets/duration'; 33import {Timestamp} from '../../components/widgets/timestamp'; 34import {LONG, NUM, STR} from '../../trace_processor/query_result'; 35import {DetailsShell} from '../../widgets/details_shell'; 36import {GridLayout, GridLayoutColumn} from '../../widgets/grid_layout'; 37import {Section} from '../../widgets/section'; 38import {SqlRef} from '../../widgets/sql_ref'; 39import {dictToTreeNodes, Tree} from '../../widgets/tree'; 40import {TrackEventDetailsPanel} from '../../public/details_panel'; 41import {Trace} from '../../public/trace'; 42 43interface Data { 44 ts: time; 45 dur: duration; 46 interactionType: string; 47 totalDurationMs: duration; 48 upid: Upid; 49} 50 51export class WebContentInteractionPanel implements TrackEventDetailsPanel { 52 private data?: Data; 53 54 constructor( 55 private readonly trace: Trace, 56 private readonly id: number, 57 ) {} 58 59 async load() { 60 const queryResult = await this.trace.engine.query(` 61 SELECT 62 ts, 63 dur, 64 interaction_type AS interactionType, 65 total_duration_ms AS totalDurationMs, 66 renderer_upid AS upid 67 FROM chrome_web_content_interactions 68 WHERE id = ${this.id}; 69 `); 70 71 const iter = queryResult.firstRow({ 72 ts: LONG, 73 dur: LONG, 74 interactionType: STR, 75 totalDurationMs: LONG, 76 upid: NUM, 77 }); 78 79 this.data = { 80 ts: Time.fromRaw(iter.ts), 81 dur: iter.ts, 82 interactionType: iter.interactionType, 83 totalDurationMs: iter.totalDurationMs, 84 upid: asUpid(iter.upid), 85 }; 86 } 87 88 private getDetailsDictionary() { 89 const details: {[key: string]: m.Child} = {}; 90 if (this.data === undefined) return details; 91 details['Interaction'] = this.data.interactionType; 92 details['Timestamp'] = m(Timestamp, {ts: this.data.ts}); 93 details['Duration'] = m(DurationWidget, {dur: this.data.dur}); 94 details['Renderer Upid'] = this.data.upid; 95 details['Total duration of all events'] = m(DurationWidget, { 96 dur: this.data.totalDurationMs, 97 }); 98 details['SQL ID'] = m(SqlRef, { 99 table: 'chrome_web_content_interactions', 100 id: this.id, 101 }); 102 return details; 103 } 104 105 render() { 106 if (!this.data) { 107 return m('h2', 'Loading'); 108 } 109 110 return m( 111 DetailsShell, 112 { 113 title: 'Chrome Web Content Interaction', 114 }, 115 m( 116 GridLayout, 117 m( 118 GridLayoutColumn, 119 m( 120 Section, 121 {title: 'Details'}, 122 m(Tree, dictToTreeNodes(this.getDetailsDictionary())), 123 ), 124 ), 125 ), 126 ); 127 } 128} 129