import{BackgroundServiceModel,Events}from'./BackgroundServiceModel.js';export class BackgroundServiceView extends UI.VBox{static getUIString(serviceName){switch(serviceName){case Protocol.BackgroundService.ServiceName.BackgroundFetch:return ls`Background Fetch`;case Protocol.BackgroundService.ServiceName.BackgroundSync:return ls`Background Sync`;case Protocol.BackgroundService.ServiceName.PushMessaging:return ls`Push Messaging`;case Protocol.BackgroundService.ServiceName.Notifications:return ls`Notifications`;case Protocol.BackgroundService.ServiceName.PaymentHandler:return ls`Payment Handler`;case Protocol.BackgroundService.ServiceName.PeriodicBackgroundSync:return ls`Periodic Background Sync`;default:return'';}}
constructor(serviceName,model){super(true);this.registerRequiredCSS('resources/backgroundServiceView.css');this.registerRequiredCSS('ui/emptyWidget.css');this._serviceName=serviceName;this._model=model;this._model.addEventListener(Events.RecordingStateChanged,this._onRecordingStateChanged,this);this._model.addEventListener(Events.BackgroundServiceEventReceived,this._onEventReceived,this);this._model.enable(this._serviceName);this._serviceWorkerManager=this._model.target().model(SDK.ServiceWorkerManager);this._securityOriginManager=this._model.target().model(SDK.SecurityOriginManager);this._securityOriginManager.addEventListener(SDK.SecurityOriginManager.Events.MainSecurityOriginChanged,()=>this._onOriginChanged());this._recordAction=(self.UI.actionRegistry.action('background-service.toggle-recording'));this._recordButton=null;this._originCheckbox=null;this._saveButton=null;this._toolbar=new UI.Toolbar('background-service-toolbar',this.contentElement);this._setupToolbar();this._splitWidget=new UI.SplitWidget(false,true);this._splitWidget.show(this.contentElement);this._dataGrid=this._createDataGrid();this._previewPanel=new UI.VBox();this._selectedEventNode=null;this._preview=null;this._splitWidget.setMainWidget(this._dataGrid.asWidget());this._splitWidget.setSidebarWidget(this._previewPanel);this._showPreview(null);}
async _setupToolbar(){this._recordButton=UI.Toolbar.createActionButton(this._recordAction);this._toolbar.appendToolbarItem(this._recordButton);const clearButton=new UI.ToolbarButton(ls`Clear`,'largeicon-clear');clearButton.addEventListener(UI.ToolbarButton.Events.Click,()=>this._clearEvents());this._toolbar.appendToolbarItem(clearButton);this._toolbar.appendSeparator();this._saveButton=new UI.ToolbarButton(ls`Save events`,'largeicon-download');this._saveButton.addEventListener(UI.ToolbarButton.Events.Click,()=>this._saveToFile());this._saveButton.setEnabled(false);this._toolbar.appendToolbarItem(this._saveButton);this._toolbar.appendSeparator();this._originCheckbox=new UI.ToolbarCheckbox(ls`Show events from other domains`,ls`Show events from other domains`,()=>this._refreshView());this._toolbar.appendToolbarItem(this._originCheckbox);}
_refreshView(){this._clearView();const events=this._model.getEvents(this._serviceName).filter(event=>this._acceptEvent(event));for(const event of events){this._addEvent(event);}}
_clearView(){this._selectedEventNode=null;this._dataGrid.rootNode().removeChildren();this._saveButton.setEnabled(false);this._showPreview(null);}
_toggleRecording(){this._model.setRecording(!this._recordButton.toggled(),this._serviceName);}
_clearEvents(){this._model.clearEvents(this._serviceName);this._clearView();}
_onRecordingStateChanged(event){const state=(event.data);if(state.serviceName!==this._serviceName){return;}
if(state.isRecording===this._recordButton.toggled()){return;}
this._recordButton.setToggled(state.isRecording);this._showPreview(this._selectedEventNode);}
_onEventReceived(event){const serviceEvent=(event.data);if(!this._acceptEvent(serviceEvent)){return;}
this._addEvent(serviceEvent);}
_onOriginChanged(){if(this._originCheckbox.checked()){return;}
this._refreshView();}
_addEvent(serviceEvent){const data=this._createEventData(serviceEvent);const dataNode=new EventDataNode(data,serviceEvent.eventMetadata);this._dataGrid.rootNode().appendChild(dataNode);if(this._dataGrid.rootNode().children.length===1){this._saveButton.setEnabled(true);this._showPreview(this._selectedEventNode);}}
_createDataGrid(){const columns=([{id:'id',title:ls`#`,weight:1},{id:'timestamp',title:ls`Timestamp`,weight:8},{id:'eventName',title:ls`Event`,weight:10},{id:'origin',title:ls`Origin`,weight:10},{id:'swScope',title:ls`SW Scope`,weight:2},{id:'instanceId',title:ls`Instance ID`,weight:10},]);const dataGrid=new DataGrid.DataGrid({displayName:ls`Background Services`,columns});dataGrid.setStriped(true);dataGrid.addEventListener(DataGrid.DataGrid.Events.SelectedNode,event=>this._showPreview((event.data)));return dataGrid;}
_createEventData(serviceEvent){let swScope='';const registration=this._serviceWorkerManager.registrations().get(serviceEvent.serviceWorkerRegistrationId);if(registration){swScope=registration.scopeURL.substr(registration.securityOrigin.length);}
return{id:this._dataGrid.rootNode().children.length+1,timestamp:UI.formatTimestamp(serviceEvent.timestamp*1000,true),origin:serviceEvent.origin,swScope,eventName:serviceEvent.eventName,instanceId:serviceEvent.instanceId,};}
_acceptEvent(event){if(event.service!==this._serviceName){return false;}
if(this._originCheckbox.checked()){return true;}
const origin=event.origin.substr(0,event.origin.length-1);return this._securityOriginManager.securityOrigins().includes(origin);}
_createLearnMoreLink(){let url='https://developers.google.com/web/tools/chrome-devtools/javascript/background-services?utm_source=devtools';switch(this._serviceName){case Protocol.BackgroundService.ServiceName.BackgroundFetch:url+='#fetch';break;case Protocol.BackgroundService.ServiceName.BackgroundSync:url+='#sync';break;case Protocol.BackgroundService.ServiceName.PushMessaging:url+='#push';break;case Protocol.BackgroundService.ServiceName.Notifications:url+='#notifications';break;default:break;}
return UI.XLink.create(url,ls`Learn more`);}
_showPreview(dataNode){if(this._selectedEventNode&&this._selectedEventNode===dataNode){return;}
this._selectedEventNode=dataNode;if(this._preview){this._preview.detach();}
if(this._selectedEventNode){this._preview=this._selectedEventNode.createPreview();this._preview.show(this._previewPanel.contentElement);return;}
this._preview=new UI.VBox();this._preview.contentElement.classList.add('background-service-preview','fill');const centered=this._preview.contentElement.createChild('div');if(this._dataGrid.rootNode().children.length){centered.createChild('p').textContent=ls`Select an entry to view metadata`;}else if(this._recordButton.toggled()){const featureName=BackgroundServiceView.getUIString(this._serviceName);centered.createChild('p').textContent=ls`Recording ${featureName} activity...`;centered.createChild('p').textContent=ls`DevTools will record all ${featureName} activity for up to 3 days, even when closed.`;}else{const landingRecordButton=UI.Toolbar.createActionButton(this._recordAction);const recordKey=createElementWithClass('b','background-service-shortcut');recordKey.textContent=self.UI.shortcutRegistry.shortcutDescriptorsForAction('background-service.toggle-recording')[0].name;const inlineButton=UI.createInlineButton(landingRecordButton);inlineButton.classList.add('background-service-record-inline-button');centered.createChild('p').appendChild(UI.formatLocalized('Click the record button %s or hit %s to start recording.',[inlineButton,recordKey]));centered.appendChild(this._createLearnMoreLink());}
this._preview.show(this._previewPanel.contentElement);}
async _saveToFile(){const fileName=`${this._serviceName}-${new Date().toISO8601Compact()}.json`;const stream=new Bindings.FileOutputStream();const accepted=await stream.open(fileName);if(!accepted){return;}
const events=this._model.getEvents(this._serviceName).filter(event=>this._acceptEvent(event));await stream.write(JSON.stringify(events,undefined,2));stream.close();}}
export class EventDataNode extends DataGrid.DataGridNode{constructor(data,eventMetadata){super(data);this._eventMetadata=eventMetadata.sort((m1,m2)=>m1.key.compareTo(m2.key));}
createPreview(){const preview=new UI.VBox();preview.element.classList.add('background-service-metadata');for(const entry of this._eventMetadata){const div=createElementWithClass('div','background-service-metadata-entry');div.createChild('div','background-service-metadata-name').textContent=entry.key+': ';if(entry.value){div.createChild('div','background-service-metadata-value source-code').textContent=entry.value;}else{div.createChild('div','background-service-metadata-value background-service-empty-value').textContent=ls`empty`;}
preview.element.appendChild(div);}
if(!preview.element.children.length){const div=createElementWithClass('div','background-service-metadata-entry');div.createChild('div','background-service-metadata-name').textContent=ls`No metadata for this event`;preview.element.appendChild(div);}
return preview;}}
export class ActionDelegate{handleAction(context,actionId){const view=context.flavor(BackgroundServiceView);switch(actionId){case'background-service.toggle-recording':view._toggleRecording();return true;}
return false;}}