import{SortableDataGrid,DataGrid}from'../data_grid/data_grid.js';import{InspectorFrontendHost}from'../host/host.js';import{InspectorBackend}from'../protocol_client/protocol_client.js';import{SDKModel,RemoteObject}from'../sdk/sdk.js';import{JSONView}from'../source_frame/source_frame.js';import{TextUtils}from'../text_utils/text_utils.js';import{Widget,Toolbar,SplitWidget,FilterSuggestionBuilder,TabbedPane,EmptyWidget}from'../ui/ui.js';class ProtocolMonitorImpl extends Widget.VBox{constructor(){super(true);this._nodes=[];this._started=false;this._startTime=0;this._nodeForId={};this._filter=node=>true;this._columns=[{id:'method',title:ls`Method`,visible:true,sortable:true,weight:60},{id:'direction',title:ls`Direction`,visible:false,sortable:true,hideable:true,weight:30},{id:'request',title:ls`Request`,visible:true,hideable:true,weight:60},{id:'response',title:ls`Response`,visible:true,hideable:true,weight:60},{id:'timestamp',title:ls`Timestamp`,visible:false,sortable:true,hideable:true,weight:30},{id:'target',title:ls`Target`,visible:false,sortable:true,hideable:true,weight:30}];this.registerRequiredCSS('protocol_monitor/protocolMonitor.css');const topToolbar=new Toolbar.Toolbar('protocol-monitor-toolbar',this.contentElement);const recordButton=new Toolbar.ToolbarToggle(ls`Record`,'largeicon-start-recording','largeicon-stop-recording');recordButton.addEventListener(Toolbar.ToolbarButton.Events.Click,()=>{recordButton.setToggled(!recordButton.toggled());this._setRecording(recordButton.toggled());});recordButton.setToggleWithRedColor(true);topToolbar.appendToolbarItem(recordButton);recordButton.setToggled(true);const clearButton=new Toolbar.ToolbarButton(ls`Clear all`,'largeicon-clear');clearButton.addEventListener(Toolbar.ToolbarButton.Events.Click,()=>{this._dataGrid.rootNode().removeChildren();this._nodes=[];this._nodeForId={};});topToolbar.appendToolbarItem(clearButton);const split=new SplitWidget.SplitWidget(true,true,'protocol-monitor-panel-split',250);split.show(this.contentElement);this._dataGrid=new SortableDataGrid.SortableDataGrid({displayName:ls`Protocol Monitor`,columns:this._columns});this._dataGrid.element.style.flex='1';this._infoWidget=new InfoWidget();split.setMainWidget(this._dataGrid.asWidget());split.setSidebarWidget(this._infoWidget);this._dataGrid.addEventListener(DataGrid.Events.SelectedNode,event=>this._infoWidget.render(event.data.data));this._dataGrid.addEventListener(DataGrid.Events.DeselectedNode,event=>this._infoWidget.render(null));this._dataGrid.setHeaderContextMenuCallback(this._innerHeaderContextMenu.bind(this));this._dataGrid.setRowContextMenuCallback(this._innerRowContextMenu.bind(this));this._dataGrid.addEventListener(DataGrid.Events.SortingChanged,this._sortDataGrid.bind(this));this._dataGrid.setStickToBottom(true);this._dataGrid.sortNodes(SortableDataGrid.SortableDataGrid.NumericComparator.bind(null,'timestamp'),false);this._updateColumnVisibility();const keys=['method','request','response','direction'];this._filterParser=new TextUtils.FilterParser(keys);this._suggestionBuilder=new FilterSuggestionBuilder.FilterSuggestionBuilder(keys);this._textFilterUI=new Toolbar.ToolbarInput(ls`Filter`,'',1,.2,'',this._suggestionBuilder.completions.bind(this._suggestionBuilder));this._textFilterUI.addEventListener(Toolbar.ToolbarInput.Event.TextChanged,event=>{const query=(event.data);const filters=this._filterParser.parse(query);this._filter=node=>{for(const{key,text,negative}of filters){if(!text){continue;}
const data=key?node.data[key]:node.data;if(!data){continue;}
const found=JSON.stringify(data).toLowerCase().indexOf(text.toLowerCase())!==-1;if(found===negative){return false;}}
return true;};this._filterNodes();});topToolbar.appendToolbarItem(this._textFilterUI);}
_filterNodes(){for(const node of this._nodes){if(this._filter(node)){if(!node.parent){this._dataGrid.insertChild(node);}}else{node.remove();}}}
_innerHeaderContextMenu(contextMenu){const columnConfigs=this._columns.filter(columnConfig=>columnConfig.hideable);for(const columnConfig of columnConfigs){contextMenu.headerSection().appendCheckboxItem(columnConfig.title,this._toggleColumnVisibility.bind(this,columnConfig),columnConfig.visible);}}
_innerRowContextMenu(contextMenu,node){contextMenu.defaultSection().appendItem(ls`Filter`,()=>{this._textFilterUI.setValue(`method:${node.data.method}`,true);});contextMenu.defaultSection().appendItem(ls`Documentation`,()=>{const[domain,method]=node.data.method.split('.');const type=node.data.direction==='sent'?'method':'event';InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(`https://chromedevtools.github.io/devtools-protocol/tot/${domain}#${type}-${method}`);});}
_toggleColumnVisibility(columnConfig){columnConfig.visible=!columnConfig.visible;this._updateColumnVisibility();}
_updateColumnVisibility(){const visibleColumns=({});for(const columnConfig of this._columns){visibleColumns[columnConfig.id]=columnConfig.visible;}
this._dataGrid.setColumnsVisiblity(visibleColumns);}
_sortDataGrid(){const sortColumnId=this._dataGrid.sortColumnId();if(!sortColumnId){return;}
let columnIsNumeric=true;switch(sortColumnId){case'method':case'direction':columnIsNumeric=false;break;}
const comparator=columnIsNumeric?SortableDataGrid.SortableDataGrid.NumericComparator:SortableDataGrid.SortableDataGrid.StringComparator;this._dataGrid.sortNodes(comparator.bind(null,sortColumnId),!this._dataGrid.isSortOrderAscending());}
wasShown(){if(this._started){return;}
this._started=true;this._startTime=Date.now();this._setRecording(true);}
_setRecording(recording){if(recording){InspectorBackend.test.onMessageSent=this._messageSent.bind(this);InspectorBackend.test.onMessageReceived=this._messageReceived.bind(this);}else{InspectorBackend.test.onMessageSent=null;InspectorBackend.test.onMessageReceived=null;}}
_targetToString(target){if(!target){return'';}
return target.decorateLabel(`${target.name()} ${target === SDKModel.TargetManager.instance().mainTarget() ? '' : target.id()}`);}
_messageReceived(message,target){if('id'in message){const node=this._nodeForId[message.id];if(!node){return;}
node.data.response=message.result||message.error;node.hasError=!!message.error;node.refresh();if(this._dataGrid.selectedNode===node){this._infoWidget.render(node.data);}
return;}
const sdkTarget=(target);const node=new ProtocolNode({method:message.method,direction:'received',response:message.params,timestamp:Date.now()-this._startTime,request:'',target:this._targetToString(sdkTarget)});this._nodes.push(node);if(this._filter(node)){this._dataGrid.insertChild(node);}}
_messageSent(message,target){const sdkTarget=(target);const node=new ProtocolNode({method:message.method,direction:'sent',request:message.params,timestamp:Date.now()-this._startTime,response:'(pending)',id:message.id,target:this._targetToString(sdkTarget)});this._nodeForId[message.id]=node;this._nodes.push(node);if(this._filter(node)){this._dataGrid.insertChild(node);}}}
class ProtocolNode extends SortableDataGrid.SortableDataGridNode{constructor(data){super(data);this.hasError=false;}
createCell(columnId){switch(columnId){case'response':if(!this.data[columnId]&&this.data.direction==='send'){const cell=this.createTD(columnId);cell.textContent='(pending)';return cell;}
case'request':{const cell=this.createTD(columnId);const obj=RemoteObject.RemoteObject.fromLocalObject(this.data[columnId]);cell.textContent=obj.description.trimEndWithMaxLength(50);cell.classList.add('source-code');return cell;}
case'timestamp':{const cell=this.createTD(columnId);cell.textContent=ls`${this.data[columnId]} ms`;return cell;}}
return super.createCell(columnId);}
element(){const element=super.element();element.classList.toggle('protocol-message-sent',this.data.direction==='sent');element.classList.toggle('protocol-message-received',this.data.direction!=='sent');element.classList.toggle('error',this.hasError);return element;}}
class InfoWidget extends Widget.VBox{constructor(){super();this._tabbedPane=new TabbedPane.TabbedPane();this._tabbedPane.appendTab('request','Request',new Widget.Widget());this._tabbedPane.appendTab('response','Response',new Widget.Widget());this._tabbedPane.show(this.contentElement);this._tabbedPane.selectTab('response');this.render(null);}
render(data){const requestEnabled=data&&data.direction==='sent';this._tabbedPane.setTabEnabled('request',!!requestEnabled);if(!data){this._tabbedPane.changeTabView('request',new EmptyWidget.EmptyWidget(ls`No message selected`));this._tabbedPane.changeTabView('response',new EmptyWidget.EmptyWidget(ls`No message selected`));return;}
if(!requestEnabled){this._tabbedPane.selectTab('response');}
this._tabbedPane.changeTabView('request',JSONView.JSONView.createViewSync(data.request));this._tabbedPane.changeTabView('response',JSONView.JSONView.createViewSync(data.response));}}
var ProtocolMonitor=Object.freeze({__proto__:null,ProtocolMonitorImpl:ProtocolMonitorImpl,ProtocolNode:ProtocolNode,InfoWidget:InfoWidget});export{ProtocolMonitor};