UNPKG

@dcloudio/uni-debugger

Version:

uni-app debugger

772 lines (682 loc) 26.6 kB
/* * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org> * Copyright (C) 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @implements {UI.ContextMenu.Provider} * @implements {UI.ViewLocationResolver} */ Network.NetworkPanel = class extends UI.Panel { constructor() { super('network'); this.registerRequiredCSS('network/networkPanel.css'); this._networkLogShowOverviewSetting = Common.settings.createSetting('networkLogShowOverview', true); this._networkLogLargeRowsSetting = Common.settings.createSetting('networkLogLargeRows', false); this._networkRecordFilmStripSetting = Common.settings.createSetting('networkRecordFilmStripSetting', false); this._toggleRecordAction = /** @type {!UI.Action }*/ (UI.actionRegistry.action('network.toggle-recording')); /** @type {number|undefined} */ this._pendingStopTimer; /** @type {?Network.NetworkItemView} */ this._networkItemView = null; /** @type {?PerfUI.FilmStripView} */ this._filmStripView = null; /** @type {?Network.NetworkPanel.FilmStripRecorder} */ this._filmStripRecorder = null; const panel = new UI.VBox(); this._panelToolbar = new UI.Toolbar('', panel.contentElement); this._filterBar = new UI.FilterBar('networkPanel', true); this._filterBar.show(panel.contentElement); this._filmStripPlaceholderElement = panel.contentElement.createChild('div', 'network-film-strip-placeholder'); // Create top overview component. this._overviewPane = new PerfUI.TimelineOverviewPane('network'); this._overviewPane.addEventListener( PerfUI.TimelineOverviewPane.Events.WindowChanged, this._onWindowChanged.bind(this)); this._overviewPane.element.id = 'network-overview-panel'; this._networkOverview = new Network.NetworkOverview(); this._overviewPane.setOverviewControls([this._networkOverview]); this._overviewPlaceholderElement = panel.contentElement.createChild('div'); this._calculator = new Network.NetworkTransferTimeCalculator(); this._splitWidget = new UI.SplitWidget(true, false, 'networkPanelSplitViewState'); this._splitWidget.hideMain(); this._splitWidget.show(panel.contentElement); panel.setDefaultFocusedChild(this._filterBar); const initialSidebarWidth = 225; const splitWidget = new UI.SplitWidget(true, false, 'networkPanelSidebarState', initialSidebarWidth); splitWidget.hideSidebar(); splitWidget.enableShowModeSaving(); splitWidget.element.tabIndex = 0; splitWidget.show(this.element); this._sidebarLocation = UI.viewManager.createTabbedLocation(async () => { UI.viewManager.showView('network'); splitWidget.showBoth(); }, 'network-sidebar', true); const tabbedPane = this._sidebarLocation.tabbedPane(); tabbedPane.setMinimumSize(100, 25); tabbedPane.element.classList.add('network-tabbed-pane'); tabbedPane.element.addEventListener('keydown', event => { if (event.key !== 'Escape') return; splitWidget.hideSidebar(); event.consume(); }); const closeSidebar = new UI.ToolbarButton(Common.UIString('Close'), 'largeicon-delete'); closeSidebar.addEventListener(UI.ToolbarButton.Events.Click, () => splitWidget.hideSidebar()); tabbedPane.rightToolbar().appendToolbarItem(closeSidebar); splitWidget.setSidebarWidget(tabbedPane); splitWidget.setMainWidget(panel); splitWidget.setDefaultFocusedChild(panel); this.setDefaultFocusedChild(splitWidget); this._progressBarContainer = createElement('div'); /** @type {!Network.NetworkLogView} */ this._networkLogView = new Network.NetworkLogView(this._filterBar, this._progressBarContainer, this._networkLogLargeRowsSetting); this._splitWidget.setSidebarWidget(this._networkLogView); this._detailsWidget = new UI.VBox(); this._detailsWidget.element.classList.add('network-details-view'); this._splitWidget.setMainWidget(this._detailsWidget); this._closeButtonElement = createElement('div', 'dt-close-button'); this._closeButtonElement.addEventListener('click', this._showRequest.bind(this, null), false); this._closeButtonElement.style.margin = '0 5px'; this._networkLogShowOverviewSetting.addChangeListener(this._toggleShowOverview, this); this._networkLogLargeRowsSetting.addChangeListener(this._toggleLargerRequests, this); this._networkRecordFilmStripSetting.addChangeListener(this._toggleRecordFilmStrip, this); this._preserveLogSetting = Common.moduleSetting('network_log.preserve-log'); this._offlineCheckbox = MobileThrottling.throttlingManager().createOfflineToolbarCheckbox(); this._throttlingSelect = this._createThrottlingConditionsSelect(); this._setupToolbarButtons(splitWidget); this._toggleRecord(true); this._toggleShowOverview(); this._toggleLargerRequests(); this._toggleRecordFilmStrip(); this._updateUI(); SDK.targetManager.addModelListener( SDK.ResourceTreeModel, SDK.ResourceTreeModel.Events.WillReloadPage, this._willReloadPage, this); SDK.targetManager.addModelListener(SDK.ResourceTreeModel, SDK.ResourceTreeModel.Events.Load, this._load, this); this._networkLogView.addEventListener(Network.NetworkLogView.Events.RequestSelected, this._onRequestSelected, this); BrowserSDK.networkLog.addEventListener(BrowserSDK.NetworkLog.Events.RequestAdded, this._onUpdateRequest, this); BrowserSDK.networkLog.addEventListener(BrowserSDK.NetworkLog.Events.RequestUpdated, this._onUpdateRequest, this); BrowserSDK.networkLog.addEventListener(BrowserSDK.NetworkLog.Events.Reset, this._onNetworkLogReset, this); } /** * @param {!Array<{filterType: !Network.NetworkLogView.FilterType, filterValue: string}>} filters */ static revealAndFilter(filters) { const panel = Network.NetworkPanel._instance(); let filterString = ''; for (const filter of filters) filterString += `${filter.filterType}:${filter.filterValue} `; panel._networkLogView.setTextFilterValue(filterString); UI.viewManager.showView('network'); } /** * @return {!Network.NetworkPanel} */ static _instance() { return /** @type {!Network.NetworkPanel} */ (self.runtime.sharedInstance(Network.NetworkPanel)); } /** * @return {!UI.ToolbarCheckbox} */ offlineCheckboxForTest() { return this._offlineCheckbox; } /** * @return {!UI.ToolbarComboBox} */ throttlingSelectForTest() { return this._throttlingSelect; } /** * @param {!Common.Event} event */ _onWindowChanged(event) { const startTime = Math.max(this._calculator.minimumBoundary(), event.data.startTime / 1000); const endTime = Math.min(this._calculator.maximumBoundary(), event.data.endTime / 1000); this._networkLogView.setWindow(startTime, endTime); } _setupToolbarButtons(splitWidget) { const searchToggle = new UI.ToolbarToggle('Search', 'largeicon-search'); function updateSidebarToggle() { searchToggle.setToggled(splitWidget.showMode() !== UI.SplitWidget.ShowMode.OnlyMain); } this._panelToolbar.appendToolbarItem(UI.Toolbar.createActionButton(this._toggleRecordAction)); const clearButton = new UI.ToolbarButton(Common.UIString('Clear'), 'largeicon-clear'); clearButton.addEventListener(UI.ToolbarButton.Events.Click, () => BrowserSDK.networkLog.reset(), this); this._panelToolbar.appendToolbarItem(clearButton); this._panelToolbar.appendSeparator(); const recordFilmStripButton = new UI.ToolbarSettingToggle( this._networkRecordFilmStripSetting, 'largeicon-camera', Common.UIString('Capture screenshots')); this._panelToolbar.appendToolbarItem(recordFilmStripButton); this._panelToolbar.appendToolbarItem(this._filterBar.filterButton()); updateSidebarToggle(); splitWidget.addEventListener(UI.SplitWidget.Events.ShowModeChanged, updateSidebarToggle); searchToggle.addEventListener(UI.ToolbarButton.Events.Click, () => { if (splitWidget.showMode() === UI.SplitWidget.ShowMode.OnlyMain) splitWidget.showBoth(); else splitWidget.hideSidebar(); }); this._panelToolbar.appendToolbarItem(searchToggle); this._panelToolbar.appendSeparator(); this._panelToolbar.appendText(Common.UIString('View:')); const largerRequestsButton = new UI.ToolbarSettingToggle( this._networkLogLargeRowsSetting, 'largeicon-large-list', Common.UIString('Use large request rows'), Common.UIString('Use small request rows')); this._panelToolbar.appendToolbarItem(largerRequestsButton); const showOverviewButton = new UI.ToolbarSettingToggle( this._networkLogShowOverviewSetting, 'largeicon-waterfall', Common.UIString('Show overview'), Common.UIString('Hide overview')); this._panelToolbar.appendToolbarItem(showOverviewButton); this._panelToolbar.appendToolbarItem(new UI.ToolbarSettingCheckbox( Common.moduleSetting('network.group-by-frame'), '', Common.UIString('Group by frame'))); this._panelToolbar.appendSeparator(); this._panelToolbar.appendToolbarItem(new UI.ToolbarSettingCheckbox( this._preserveLogSetting, Common.UIString('Do not clear log on page reload / navigation'), Common.UIString('Preserve log'))); const disableCacheCheckbox = new UI.ToolbarSettingCheckbox( Common.moduleSetting('cacheDisabled'), Common.UIString('Disable cache (while DevTools is open)'), Common.UIString('Disable cache')); this._panelToolbar.appendToolbarItem(disableCacheCheckbox); this._panelToolbar.appendSeparator(); this._panelToolbar.appendToolbarItem(this._offlineCheckbox); this._panelToolbar.appendToolbarItem(this._throttlingSelect); this._panelToolbar.appendToolbarItem(new UI.ToolbarItem(this._progressBarContainer)); } /** * @return {!UI.ToolbarComboBox} */ _createThrottlingConditionsSelect() { const toolbarItem = new UI.ToolbarComboBox(null); toolbarItem.setTitle(ls`Throttling`); toolbarItem.setMaxWidth(160); MobileThrottling.throttlingManager().decorateSelectWithNetworkThrottling(toolbarItem.selectElement()); return toolbarItem; } _toggleRecording() { if (!this._preserveLogSetting.get() && !this._toggleRecordAction.toggled()) BrowserSDK.networkLog.reset(); this._toggleRecord(!this._toggleRecordAction.toggled()); } /** * @param {boolean} toggled */ _toggleRecord(toggled) { this._toggleRecordAction.setToggled(toggled); this._networkLogView.setRecording(toggled); if (!toggled && this._filmStripRecorder) this._filmStripRecorder.stopRecording(this._filmStripAvailable.bind(this)); // TODO(einbinder) This should be moved to a setting/action that NetworkLog owns but NetworkPanel controls, but // always be present in the command menu. BrowserSDK.networkLog.setIsRecording(toggled); } /** * @param {?SDK.FilmStripModel} filmStripModel */ _filmStripAvailable(filmStripModel) { if (!filmStripModel) return; const calculator = this._networkLogView.timeCalculator(); this._filmStripView.setModel(filmStripModel, calculator.minimumBoundary() * 1000, calculator.boundarySpan() * 1000); this._networkOverview.setFilmStripModel(filmStripModel); const timestamps = filmStripModel.frames().map(mapTimestamp); /** * @param {!SDK.FilmStripModel.Frame} frame * @return {number} */ function mapTimestamp(frame) { return frame.timestamp / 1000; } this._networkLogView.addFilmStripFrames(timestamps); } _onNetworkLogReset() { Network.BlockedURLsPane.reset(); if (!this._preserveLogSetting.get()) { this._calculator.reset(); this._overviewPane.reset(); } if (this._filmStripView) this._resetFilmStripView(); } /** * @param {!Common.Event} event */ _willReloadPage(event) { this._toggleRecord(true); if (this._pendingStopTimer) { clearTimeout(this._pendingStopTimer); delete this._pendingStopTimer; } if (this.isShowing() && this._filmStripRecorder) this._filmStripRecorder.startRecording(); } /** * @param {!Common.Event} event */ _load(event) { if (this._filmStripRecorder && this._filmStripRecorder.isRecording()) { this._pendingStopTimer = setTimeout(this._stopFilmStripRecording.bind(this), Network.NetworkPanel.displayScreenshotDelay); } } _stopFilmStripRecording() { this._filmStripRecorder.stopRecording(this._filmStripAvailable.bind(this)); delete this._pendingStopTimer; } _toggleLargerRequests() { this._updateUI(); } _toggleShowOverview() { const toggled = this._networkLogShowOverviewSetting.get(); if (toggled) this._overviewPane.show(this._overviewPlaceholderElement); else this._overviewPane.detach(); this.doResize(); } _toggleRecordFilmStrip() { const toggled = this._networkRecordFilmStripSetting.get(); if (toggled && !this._filmStripRecorder) { this._filmStripView = new PerfUI.FilmStripView(); this._filmStripView.setMode(PerfUI.FilmStripView.Modes.FrameBased); this._filmStripView.element.classList.add('network-film-strip'); this._filmStripRecorder = new Network.NetworkPanel.FilmStripRecorder(this._networkLogView.timeCalculator(), this._filmStripView); this._filmStripView.show(this._filmStripPlaceholderElement); this._filmStripView.addEventListener(PerfUI.FilmStripView.Events.FrameSelected, this._onFilmFrameSelected, this); this._filmStripView.addEventListener(PerfUI.FilmStripView.Events.FrameEnter, this._onFilmFrameEnter, this); this._filmStripView.addEventListener(PerfUI.FilmStripView.Events.FrameExit, this._onFilmFrameExit, this); this._resetFilmStripView(); } if (!toggled && this._filmStripRecorder) { this._filmStripView.detach(); this._filmStripView = null; this._filmStripRecorder = null; } } _resetFilmStripView() { this._filmStripView.reset(); this._filmStripView.setStatusText(Common.UIString( 'Hit %s to reload and capture filmstrip.', UI.shortcutRegistry.shortcutDescriptorsForAction('inspector_main.reload')[0].name)); } /** * @override * @return {!Array.<!Element>} */ elementsToRestoreScrollPositionsFor() { return this._networkLogView.elementsToRestoreScrollPositionsFor(); } /** * @override */ wasShown() { UI.context.setFlavor(Network.NetworkPanel, this); } /** * @override */ willHide() { UI.context.setFlavor(Network.NetworkPanel, null); } /** * @param {!SDK.NetworkRequest} request */ revealAndHighlightRequest(request) { this._showRequest(null); if (request) this._networkLogView.revealAndHighlightRequest(request); } /** * @param {!SDK.NetworkRequest} request * @return {!Promise<?Network.NetworkItemView>} */ async selectRequest(request) { await UI.viewManager.showView('network'); this._networkLogView.selectRequest(request); return this._networkItemView; } /** * @param {!Common.Event} event */ _onRowSizeChanged(event) { this._updateUI(); } /** * @param {!Common.Event} event */ _onRequestSelected(event) { const request = /** @type {?SDK.NetworkRequest} */ (event.data); this._showRequest(request); } /** * @param {?SDK.NetworkRequest} request */ _showRequest(request) { if (this._networkItemView) { this._networkItemView.detach(); this._networkItemView = null; } if (request) { this._networkItemView = new Network.NetworkItemView(request, this._networkLogView.timeCalculator()); this._networkItemView.leftToolbar().appendToolbarItem(new UI.ToolbarItem(this._closeButtonElement)); this._networkItemView.show(this._detailsWidget.element); this._splitWidget.showBoth(); } else { this._splitWidget.hideMain(); this._networkLogView.clearSelection(); } this._updateUI(); } _updateUI() { this._detailsWidget.element.classList.toggle( 'network-details-view-tall-header', this._networkLogLargeRowsSetting.get()); this._networkLogView.switchViewMode(!this._splitWidget.isResizable()); } /** * @override * @param {!Event} event * @param {!UI.ContextMenu} contextMenu * @param {!Object} target * @this {Network.NetworkPanel} */ appendApplicableItems(event, contextMenu, target) { /** * @this {Network.NetworkPanel} */ function reveal(request) { UI.viewManager.showView('network').then(this.revealAndHighlightRequest.bind(this, request)); } /** * @this {Network.NetworkPanel} */ function appendRevealItem(request) { contextMenu.revealSection().appendItem(Common.UIString('Reveal in Network panel'), reveal.bind(this, request)); } if (event.target.isSelfOrDescendant(this.element)) return; if (target instanceof SDK.Resource) { const resource = /** @type {!SDK.Resource} */ (target); if (resource.request) appendRevealItem.call(this, resource.request); return; } if (target instanceof Workspace.UISourceCode) { const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (target); const resource = Bindings.resourceForURL(uiSourceCode.url()); if (resource && resource.request) appendRevealItem.call(this, resource.request); return; } if (!(target instanceof SDK.NetworkRequest)) return; const request = /** @type {!SDK.NetworkRequest} */ (target); if (this._networkItemView && this._networkItemView.isShowing() && this._networkItemView.request() === request) return; appendRevealItem.call(this, request); } /** * @param {!Common.Event} event */ _onFilmFrameSelected(event) { const timestamp = /** @type {number} */ (event.data); this._overviewPane.setWindowTimes(0, timestamp); } /** * @param {!Common.Event} event */ _onFilmFrameEnter(event) { const timestamp = /** @type {number} */ (event.data); this._networkOverview.selectFilmStripFrame(timestamp); this._networkLogView.selectFilmStripFrame(timestamp / 1000); } /** * @param {!Common.Event} event */ _onFilmFrameExit(event) { this._networkOverview.clearFilmStripFrame(); this._networkLogView.clearFilmStripFrame(); } /** * @param {!Common.Event} event */ _onUpdateRequest(event) { const request = /** @type {!SDK.NetworkRequest} */ (event.data); this._calculator.updateBoundaries(request); // FIXME: Unify all time units across the frontend! this._overviewPane.setBounds(this._calculator.minimumBoundary() * 1000, this._calculator.maximumBoundary() * 1000); this._networkOverview.updateRequest(request); this._overviewPane.scheduleUpdate(); } /** * @override * @param {string} locationName * @return {?UI.ViewLocation} */ resolveLocation(locationName) { if (locationName === 'network-sidebar') return this._sidebarLocation; return null; } }; Network.NetworkPanel.displayScreenshotDelay = 1000; /** * @implements {UI.ContextMenu.Provider} * @unrestricted */ Network.NetworkPanel.ContextMenuProvider = class { /** * @override * @param {!Event} event * @param {!UI.ContextMenu} contextMenu * @param {!Object} target */ appendApplicableItems(event, contextMenu, target) { Network.NetworkPanel._instance().appendApplicableItems(event, contextMenu, target); } }; /** * @implements {Common.Revealer} * @unrestricted */ Network.NetworkPanel.RequestRevealer = class { /** * @override * @param {!Object} request * @return {!Promise} */ reveal(request) { if (!(request instanceof SDK.NetworkRequest)) return Promise.reject(new Error('Internal error: not a network request')); const panel = Network.NetworkPanel._instance(); return UI.viewManager.showView('network').then(panel.revealAndHighlightRequest.bind(panel, request)); } }; /** * @implements {SDK.TracingManagerClient} */ Network.NetworkPanel.FilmStripRecorder = class { /** * @param {!Network.NetworkTimeCalculator} timeCalculator * @param {!PerfUI.FilmStripView} filmStripView */ constructor(timeCalculator, filmStripView) { /** @type {?SDK.TracingManager} */ this._tracingManager = null; /** @type {?SDK.ResourceTreeModel} */ this._resourceTreeModel = null; this._timeCalculator = timeCalculator; this._filmStripView = filmStripView; /** @type {?SDK.TracingModel} */ this._tracingModel = null; /** @type {?function(?SDK.FilmStripModel)} */ this._callback = null; } /** * @override * @param {!Array.<!SDK.TracingManager.EventPayload>} events */ traceEventsCollected(events) { if (this._tracingModel) this._tracingModel.addEvents(events); } /** * @override */ tracingComplete() { if (!this._tracingModel || !this._tracingManager) return; this._tracingModel.tracingComplete(); this._tracingManager = null; this._callback(new SDK.FilmStripModel(this._tracingModel, this._timeCalculator.minimumBoundary() * 1000)); this._callback = null; if (this._resourceTreeModel) this._resourceTreeModel.resumeReload(); this._resourceTreeModel = null; } /** * @override */ tracingBufferUsage() { } /** * @override * @param {number} progress */ eventsRetrievalProgress(progress) { } startRecording() { this._filmStripView.reset(); this._filmStripView.setStatusText(Common.UIString('Recording frames...')); const tracingManagers = SDK.targetManager.models(SDK.TracingManager); if (this._tracingManager || !tracingManagers.length) return; this._tracingManager = tracingManagers[0]; this._resourceTreeModel = this._tracingManager.target().model(SDK.ResourceTreeModel); if (this._tracingModel) this._tracingModel.dispose(); this._tracingModel = new SDK.TracingModel(new Bindings.TempFileBackingStorage()); this._tracingManager.start(this, '-*,disabled-by-default-devtools.screenshot', ''); } /** * @return {boolean} */ isRecording() { return !!this._tracingManager; } /** * @param {function(?SDK.FilmStripModel)} callback */ stopRecording(callback) { if (!this._tracingManager) return; this._tracingManager.stop(); if (this._resourceTreeModel) this._resourceTreeModel.suspendReload(); this._callback = callback; this._filmStripView.setStatusText(Common.UIString('Fetching frames...')); } }; /** * @implements {UI.ActionDelegate} */ Network.NetworkPanel.ActionDelegate = class { /** * @override * @param {!UI.Context} context * @param {string} actionId * @return {boolean} */ handleAction(context, actionId) { const panel = UI.context.flavor(Network.NetworkPanel); console.assert(panel && panel instanceof Network.NetworkPanel); switch (actionId) { case 'network.toggle-recording': panel._toggleRecording(); return true; case 'network.hide-request-details': if (!panel._networkItemView) return false; panel._showRequest(null); return true; case 'network.search': const selection = UI.inspectorView.element.window().getSelection(); let queryCandidate = ''; if (selection.rangeCount) queryCandidate = selection.toString().replace(/\r?\n.*/, ''); Network.SearchNetworkView.openSearch(queryCandidate); return true; } return false; } }; /** * @implements {Common.Revealer} */ Network.NetworkPanel.RequestLocationRevealer = class { /** * @override * @param {!Object} match * @return {!Promise} */ async reveal(match) { const location = /** @type {!Network.UIRequestLocation} */ (match); const view = await Network.NetworkPanel._instance().selectRequest(location.request); if (!view) return; if (location.searchMatch) await view.revealResponseBody(location.searchMatch.lineNumber); if (location.requestHeader) view.revealRequestHeader(location.requestHeader.name); if (location.responseHeader) view.revealResponseHeader(location.responseHeader.name); } }; Network.SearchNetworkView = class extends Search.SearchView { constructor() { super('network'); } /** * @param {string} query * @param {boolean=} searchImmediately * @return {!Promise<!Search.SearchView>} */ static async openSearch(query, searchImmediately) { await UI.viewManager.showView('network.search-network-tab'); const searchView = /** @type {!Network.SearchNetworkView} */ (self.runtime.sharedInstance(Network.SearchNetworkView)); searchView.toggle(query, !!searchImmediately); return searchView; } /** * @override * @return {!Search.SearchScope} */ createScope() { return new Network.NetworkSearchScope(); } };