chrome-devtools-frontend 1.0.1652307 → 1.0.1656291
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/fixing-skipped-tests/SKILL.md +32 -0
- package/.agents/skills/migrate-chromium-test/SKILL.md +144 -0
- package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +116 -0
- package/.agents/skills/ui-eng-vision-logic-consolidator/SKILL.md +82 -0
- package/.agents/skills/ui-eng-vision-orchestrator/SKILL.md +123 -0
- package/.agents/skills/ui-eng-vision-test-scaffolder/SKILL.md +125 -0
- package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +75 -0
- package/AUTHORS +1 -0
- package/config/owner/COMMON_OWNERS +0 -4
- package/docs/get_the_code.md +1 -2
- package/docs/playbook.md +1 -1
- package/docs/ui_engineering.md +3 -1
- package/eslint.config.mjs +0 -5
- package/front_end/Tests.js +1 -0
- package/front_end/core/common/Settings.ts +47 -30
- package/front_end/core/sdk/CPUThrottlingManager.ts +23 -167
- package/front_end/core/sdk/CSSMetadata.ts +23 -0
- package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +8 -4
- package/front_end/core/sdk/ConsoleModel.ts +13 -11
- package/front_end/core/sdk/DOMDebuggerModel.ts +11 -5
- package/front_end/core/sdk/DOMModel.ts +4 -0
- package/front_end/core/sdk/EmulationModel.ts +4 -0
- package/front_end/core/sdk/EventBreakpointsModel.ts +9 -5
- package/front_end/core/sdk/IsolateManager.ts +6 -6
- package/front_end/core/sdk/ResourceTreeModel.ts +8 -5
- package/front_end/core/sdk/TargetManager.ts +17 -0
- package/front_end/entrypoints/devtools_app/devtools_app.ts +0 -1
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +459 -74
- package/front_end/entrypoints/main/MainImpl.ts +12 -42
- package/front_end/foundation/Universe.ts +116 -3
- package/front_end/generated/InspectorBackendCommands.ts +11 -6
- package/front_end/generated/SupportedCSSProperties.js +124 -34
- package/front_end/generated/protocol-mapping.d.ts +8 -0
- package/front_end/generated/protocol-proxy-api.d.ts +15 -0
- package/front_end/generated/protocol.ts +94 -1
- package/front_end/models/ai_assistance/AiConversation.ts +2 -7
- package/front_end/models/ai_assistance/README.md +4 -3
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +1 -1
- package/front_end/models/ai_assistance/agents/NetworkAgent.snapshot.txt +1 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +13 -320
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +0 -24
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +2 -358
- package/front_end/models/ai_assistance/ai_assistance.ts +6 -8
- package/front_end/models/ai_assistance/contexts/PerformanceTraceContext.ts +295 -0
- package/front_end/models/ai_assistance/contexts/RequestContext.snapshot.txt +0 -1
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +0 -2
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +10 -10
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +12 -11
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +6 -6
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +1 -14
- package/front_end/models/ai_assistance/skills/accessibility.md +4 -2
- package/front_end/models/ai_assistance/tools/GetElementAccessibilityDetails.ts +142 -0
- package/front_end/models/ai_assistance/tools/GetStyles.ts +1 -1
- package/front_end/models/ai_assistance/tools/README.md +21 -1
- package/front_end/models/ai_assistance/tools/{ResolveLighthousePath.ts → ResolveDevtoolsNodePath.ts} +18 -17
- package/front_end/models/ai_assistance/tools/Tool.ts +6 -1
- package/front_end/models/ai_assistance/tools/ToolRegistry.ts +4 -2
- package/front_end/models/autofill_manager/AutofillManager.ts +6 -15
- package/front_end/models/bindings/NetworkProject.ts +4 -8
- package/front_end/models/breakpoints/BreakpointManager.ts +9 -9
- package/front_end/models/emulation/DeviceModeModel.ts +24 -0
- package/front_end/models/emulation/EmulatedDevices.ts +108 -0
- package/front_end/models/heap_snapshot/HeapSnapshotModel.ts +36 -0
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +8 -0
- package/front_end/models/issues_manager/IssuesManager.ts +10 -6
- package/front_end/models/javascript_metadata/JavaScriptMetadata.ts +4 -5
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
- package/front_end/models/live-metrics/LiveMetrics.ts +6 -6
- package/front_end/models/live-metrics/web-vitals-injected/spec/spec.ts +5 -5
- package/front_end/models/live-metrics/web-vitals-injected/web-vitals-injected.ts +3 -3
- package/front_end/models/logs/LogManager.ts +25 -10
- package/front_end/models/logs/NetworkLog.ts +24 -19
- package/front_end/models/persistence/AutomaticFileSystemManager.ts +14 -13
- package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +26 -14
- package/front_end/models/persistence/IsolatedFileSystem.ts +9 -11
- package/front_end/models/persistence/IsolatedFileSystemManager.ts +22 -11
- package/front_end/models/persistence/NetworkPersistenceManager.ts +73 -44
- package/front_end/models/persistence/PersistenceImpl.ts +4 -5
- package/front_end/models/project_settings/ProjectSettingsModel.ts +12 -11
- package/front_end/models/trace/EntityMapper.ts +1 -1
- package/front_end/models/trace/handlers/ScreenshotsHandler.ts +14 -59
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +12 -38
- package/front_end/panels/ai_assistance/ExportConversation.ts +4 -1
- package/front_end/panels/ai_assistance/components/ChatInput.ts +2 -2
- package/front_end/panels/application/DeviceBoundSessionsView.ts +15 -3
- package/front_end/panels/application/FrameDetailsView.ts +2 -1
- package/front_end/panels/application/IndexedDBViews.ts +38 -36
- package/front_end/panels/application/ServiceWorkersView.ts +23 -16
- package/front_end/panels/application/components/AdsView.ts +4 -0
- package/front_end/panels/autofill/AutofillView.ts +1 -1
- package/front_end/panels/autofill/autofill-meta.ts +3 -2
- package/front_end/panels/common/CPUThrottlingOption.ts +142 -0
- package/front_end/panels/common/ThrottlingUtils.ts +9 -4
- package/front_end/panels/common/common.ts +1 -1
- package/front_end/panels/console/ConsoleViewMessage.ts +45 -0
- package/front_end/panels/elements/AccessibilityTreeUtils.ts +26 -15
- package/front_end/panels/elements/AccessibilityTreeView.ts +12 -9
- package/front_end/panels/elements/ElementsPanel.ts +0 -74
- package/front_end/panels/elements/ElementsTreeOutline.ts +5 -4
- package/front_end/panels/emulation/DeviceModeToolbar.ts +46 -45
- package/front_end/panels/layer_viewer/LayerTreeOutline.ts +118 -68
- package/front_end/panels/layer_viewer/Layers3DView.ts +1 -1
- package/front_end/panels/layer_viewer/layerTreeOutline.css +20 -13
- package/front_end/panels/layers/LayersPanel.ts +1 -1
- package/front_end/panels/mobile_throttling/CalibrationController.ts +6 -5
- package/front_end/panels/mobile_throttling/MobileThrottlingSelector.ts +1 -1
- package/front_end/panels/mobile_throttling/ThrottlingManager.ts +40 -13
- package/front_end/panels/mobile_throttling/ThrottlingPresets.ts +13 -17
- package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +79 -30
- package/front_end/panels/mobile_throttling/throttlingSettingsTab.css +5 -0
- package/front_end/panels/network/LinkPreloadGenerator.ts +101 -0
- package/front_end/panels/network/NetworkLogView.ts +28 -9
- package/front_end/panels/network/NetworkPanel.ts +1 -63
- package/front_end/panels/network/RequestInitiatorView.ts +29 -4
- package/front_end/panels/network/components/HeaderSectionRow.css +9 -7
- package/front_end/panels/network/components/HeaderSectionRow.ts +20 -1
- package/front_end/panels/network/components/RequestHeaderSection.css +5 -3
- package/front_end/panels/network/components/RequestHeaderSection.ts +1 -2
- package/front_end/panels/network/components/RequestHeadersView.css +1 -1
- package/front_end/panels/network/network.ts +2 -0
- package/front_end/panels/profiler/HeapSnapshotView.ts +121 -33
- package/front_end/panels/profiler/ModuleUIStrings.ts +4 -0
- package/front_end/panels/security/SecurityPanel.ts +36 -23
- package/front_end/panels/settings/SettingsScreen.ts +18 -103
- package/front_end/panels/settings/settings-meta.ts +0 -24
- package/front_end/panels/timeline/TimelineController.ts +3 -2
- package/front_end/panels/timeline/TimelineHistoryManager.ts +38 -37
- package/front_end/panels/timeline/TimelinePanel.ts +52 -11
- package/front_end/panels/timeline/components/CPUThrottlingSelector.ts +20 -18
- package/front_end/panels/timeline/components/LiveMetricsView.ts +38 -38
- package/front_end/panels/timeline/components/MetricCard.ts +18 -18
- package/front_end/panels/timeline/components/liveMetricsView.css +6 -6
- package/front_end/panels/timeline/components/metricCard.css +4 -4
- package/front_end/panels/timeline/timelineFlamechartPopover.css +2 -0
- package/front_end/panels/utils/utils.ts +25 -24
- package/front_end/panels/whats_new/ReleaseNoteText.ts +3 -3
- package/front_end/panels/whats_new/resources/WNDT.md +1 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +34 -55
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +96 -83
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts +10 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/CDPSession.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/CDPSession.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPResponse.d.ts +3 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPResponse.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPResponse.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Realm.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Realm.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Target.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Target.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPResponse.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPResponse.js +2 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPResponse.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Realm.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Realm.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js +5 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.js +23 -13
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPResponse.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPResponse.js +4 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPResponse.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Input.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/LifecycleWatcher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/LifecycleWatcher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.d.ts +3 -41
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js +4 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/LaunchOptions.d.ts +5 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/LaunchOptions.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/httpUtils.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/httpUtils.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/httpUtils.js +5 -5
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/httpUtils.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/types.d.ts +34 -55
- package/front_end/third_party/puppeteer/package/package.json +4 -4
- package/front_end/third_party/puppeteer/package/src/api/Browser.ts +13 -1
- package/front_end/third_party/puppeteer/package/src/api/BrowserContext.ts +2 -3
- package/front_end/third_party/puppeteer/package/src/api/CDPSession.ts +3 -1
- package/front_end/third_party/puppeteer/package/src/api/HTTPResponse.ts +3 -2
- package/front_end/third_party/puppeteer/package/src/api/Realm.ts +1 -2
- package/front_end/third_party/puppeteer/package/src/api/Target.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/api/locators/locators.ts +1 -2
- package/front_end/third_party/puppeteer/package/src/bidi/HTTPResponse.ts +3 -1
- package/front_end/third_party/puppeteer/package/src/bidi/core/Realm.ts +1 -3
- package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +13 -3
- package/front_end/third_party/puppeteer/package/src/cdp/Frame.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/cdp/FrameManager.ts +24 -13
- package/front_end/third_party/puppeteer/package/src/cdp/HTTPResponse.ts +4 -1
- package/front_end/third_party/puppeteer/package/src/cdp/Input.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/cdp/LifecycleWatcher.ts +1 -4
- package/front_end/third_party/puppeteer/package/src/cdp/Target.ts +2 -4
- package/front_end/third_party/puppeteer/package/src/cdp/WebMCP.ts +7 -76
- package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +1 -4
- package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +4 -1
- package/front_end/third_party/puppeteer/package/src/node/LaunchOptions.ts +5 -0
- package/front_end/third_party/puppeteer/package/src/revisions.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/util/httpUtils.ts +5 -5
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/third_party/puppeteer/third_party/parsel/README.chromium +1 -1
- package/front_end/ui/components/dialogs/Dialog.ts +3 -0
- package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +0 -7
- package/front_end/ui/helpers/OpenInNewTab.ts +15 -7
- package/front_end/ui/legacy/InspectorDrawerView.ts +7 -5
- package/front_end/ui/legacy/ListWidget.ts +12 -0
- package/front_end/ui/legacy/SplitWidget.ts +12 -11
- package/front_end/ui/legacy/TabbedPane.ts +1 -108
- package/front_end/ui/legacy/components/data_grid/DataGrid.ts +9 -0
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +192 -139
- package/front_end/ui/legacy/components/data_grid/DataGridExporter.ts +89 -0
- package/front_end/ui/legacy/components/data_grid/dataGrid.css +10 -0
- package/front_end/ui/legacy/components/data_grid/data_grid.ts +3 -1
- package/front_end/ui/legacy/components/object_ui/CustomPreviewComponent.ts +8 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +110 -17
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +89 -40
- package/front_end/ui/legacy/treeoutline.css +1 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
- package/package.json +4 -3
- package/front_end/Images/navigationControls.png +0 -0
- package/front_end/Images/navigationControls_2x.png +0 -0
- package/front_end/Images/popoverArrows.png +0 -0
- package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +0 -746
- package/front_end/entrypoints/greendev_floaty/floaty.css +0 -301
- package/front_end/entrypoints/greendev_floaty/floaty.html +0 -38
- package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +0 -415
- package/front_end/models/ai_assistance/agents/GreenDevAgent.ts +0 -834
- package/front_end/models/ai_assistance/agents/GreenDevAgentAntigravityCliSocketClient.ts +0 -53
- package/front_end/models/ai_assistance/agents/GreenDevAgentGeminiCliSocketClient.ts +0 -117
- package/front_end/models/annotations/AnnotationRepository.ts +0 -238
- package/front_end/models/annotations/AnnotationType.ts +0 -10
- package/front_end/models/annotations/README.md +0 -7
- package/front_end/models/annotations/annotations.ts +0 -6
- package/front_end/models/greendev/Prototypes.ts +0 -68
- package/front_end/models/greendev/README.md +0 -5
- package/front_end/models/greendev/greendev.ts +0 -5
- package/front_end/panels/common/Annotation.ts +0 -184
- package/front_end/panels/common/AnnotationManager.ts +0 -208
- package/front_end/panels/common/annotation.css +0 -40
- package/front_end/panels/greendev/GreenDevPanel.css +0 -282
- package/front_end/panels/greendev/GreenDevPanel.ts +0 -364
- package/front_end/panels/greendev/GreenDevShared.ts +0 -13
- package/front_end/panels/greendev/greendev-meta.ts +0 -52
- package/front_end/panels/greendev/greendev.ts +0 -9
|
@@ -12,15 +12,21 @@ import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
|
12
12
|
import {type Card, createIcon} from '../../ui/kit/kit.js';
|
|
13
13
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
14
14
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
15
|
+
import * as PanelsCommon from '../common/common.js';
|
|
15
16
|
|
|
16
17
|
import {CalibrationController} from './CalibrationController.js';
|
|
18
|
+
import {ThrottlingPresets} from './ThrottlingPresets.js';
|
|
17
19
|
import throttlingSettingsTabStyles from './throttlingSettingsTab.css.js';
|
|
18
20
|
|
|
19
21
|
const UIStrings = {
|
|
20
22
|
/**
|
|
21
|
-
* @description
|
|
23
|
+
* @description Title for default network throttling profiles card
|
|
24
|
+
*/
|
|
25
|
+
defaultProfiles: 'Default profiles',
|
|
26
|
+
/**
|
|
27
|
+
* @description Title for custom network throttling profiles card
|
|
22
28
|
*/
|
|
23
|
-
|
|
29
|
+
customProfiles: 'Custom profiles',
|
|
24
30
|
/**
|
|
25
31
|
* @description Text of add conditions button in Throttling Settings Tab of the Network panel
|
|
26
32
|
*/
|
|
@@ -209,7 +215,7 @@ function createComputePressurePromise(): Promise<{state: string}> {
|
|
|
209
215
|
export class CPUThrottlingCard {
|
|
210
216
|
element: Card;
|
|
211
217
|
|
|
212
|
-
private readonly setting: Common.Settings.Setting<
|
|
218
|
+
private readonly setting: Common.Settings.Setting<PanelsCommon.CPUThrottlingOption.CalibratedCPUThrottling>;
|
|
213
219
|
private computePressurePromise?: ReturnType<typeof createComputePressurePromise>;
|
|
214
220
|
private controller?: CalibrationController;
|
|
215
221
|
|
|
@@ -225,8 +231,9 @@ export class CPUThrottlingCard {
|
|
|
225
231
|
private warnings: string[] = [];
|
|
226
232
|
|
|
227
233
|
constructor() {
|
|
228
|
-
this.setting =
|
|
229
|
-
|
|
234
|
+
this.setting =
|
|
235
|
+
Common.Settings.Settings.instance().createSetting<PanelsCommon.CPUThrottlingOption.CalibratedCPUThrottling>(
|
|
236
|
+
'calibrated-cpu-throttling', {}, Common.Settings.SettingStorageType.GLOBAL);
|
|
230
237
|
|
|
231
238
|
this.element = document.createElement('devtools-card');
|
|
232
239
|
this.element.heading = i18nString(UIStrings.cpuThrottlingPresets);
|
|
@@ -326,13 +333,13 @@ export class CPUThrottlingCard {
|
|
|
326
333
|
this.progress.style.display = '';
|
|
327
334
|
}
|
|
328
335
|
|
|
329
|
-
const resultToString = (result: number|
|
|
336
|
+
const resultToString = (result: number|PanelsCommon.CPUThrottlingOption.CalibrationError|undefined): string => {
|
|
330
337
|
if (result === undefined) {
|
|
331
338
|
return i18nString(UIStrings.needsCalibration);
|
|
332
339
|
}
|
|
333
340
|
|
|
334
341
|
if (typeof result === 'string') {
|
|
335
|
-
return
|
|
342
|
+
return PanelsCommon.CPUThrottlingOption.calibrationErrorToString(result);
|
|
336
343
|
}
|
|
337
344
|
|
|
338
345
|
// Shouldn't happen, but let's not throw an error (.toFixed) if the setting
|
|
@@ -344,15 +351,15 @@ export class CPUThrottlingCard {
|
|
|
344
351
|
return i18nString(UIStrings.dSlowdown, {PH1: result.toFixed(1)});
|
|
345
352
|
};
|
|
346
353
|
|
|
347
|
-
const setPresetResult =
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
354
|
+
const setPresetResult = (element: HTMLElement|null,
|
|
355
|
+
result: number|PanelsCommon.CPUThrottlingOption.CalibrationError|undefined): void => {
|
|
356
|
+
if (!element) {
|
|
357
|
+
throw new Error('expected HTMLElement');
|
|
358
|
+
}
|
|
352
359
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
360
|
+
element.textContent = resultToString(result);
|
|
361
|
+
element.classList.toggle('not-calibrated', result === undefined);
|
|
362
|
+
};
|
|
356
363
|
|
|
357
364
|
setPresetResult(this.lowTierMobileDeviceEl.querySelector('.cpu-preset-result'), result.low);
|
|
358
365
|
setPresetResult(this.midTierMobileDeviceEl.querySelector('.cpu-preset-result'), result.mid);
|
|
@@ -452,7 +459,10 @@ function extractCustomSettingIndex(key: SDK.NetworkManager.UserDefinedThrottling
|
|
|
452
459
|
|
|
453
460
|
export class ThrottlingSettingsTab extends UI.Widget.VBox implements
|
|
454
461
|
UI.ListWidget.Delegate<SDK.NetworkManager.Conditions> {
|
|
455
|
-
|
|
462
|
+
/** List of default network throttling presets (read-only in UI) */
|
|
463
|
+
private readonly presetsList: UI.ListWidget.ListWidget<SDK.NetworkManager.Conditions>;
|
|
464
|
+
/** List of custom user-defined network throttling profiles */
|
|
465
|
+
private readonly customList: UI.ListWidget.ListWidget<SDK.NetworkManager.Conditions>;
|
|
456
466
|
private readonly customUserConditions: Common.Settings.Setting<SDK.NetworkManager.Conditions[]>;
|
|
457
467
|
private editor?: UI.ListWidget.Editor<SDK.NetworkManager.Conditions>;
|
|
458
468
|
private cpuThrottlingCard: CPUThrottlingCard;
|
|
@@ -489,15 +499,18 @@ export class ThrottlingSettingsTab extends UI.Widget.VBox implements
|
|
|
489
499
|
addButton.textContent = i18nString(UIStrings.addCustomProfile);
|
|
490
500
|
addButton.addEventListener('click', () => this.addButtonClicked());
|
|
491
501
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
502
|
+
this.presetsList = new UI.ListWidget.ListWidget(this);
|
|
503
|
+
this.presetsList.setHeader(createHeaderRow());
|
|
504
|
+
createProfilesCard(i18nString(UIStrings.defaultProfiles), this.presetsList, settingsContent);
|
|
505
|
+
const presets = ThrottlingPresets.networkPresets;
|
|
506
|
+
for (let i = 0; i < presets.length; ++i) {
|
|
507
|
+
this.presetsList.appendItem(presets[i], false);
|
|
508
|
+
}
|
|
495
509
|
|
|
496
|
-
this.
|
|
497
|
-
this.
|
|
498
|
-
this.
|
|
499
|
-
|
|
500
|
-
container.appendChild(addButton);
|
|
510
|
+
this.customList = new UI.ListWidget.ListWidget(this);
|
|
511
|
+
this.customList.setHeader(createHeaderRow());
|
|
512
|
+
const customContainer = createProfilesCard(i18nString(UIStrings.customProfiles), this.customList, settingsContent);
|
|
513
|
+
customContainer.appendChild(addButton);
|
|
501
514
|
|
|
502
515
|
this.customUserConditions = SDK.NetworkManager.customUserNetworkConditionsSetting();
|
|
503
516
|
this.customUserConditions.addChangeListener(this.conditionsUpdated, this);
|
|
@@ -533,19 +546,17 @@ export class ThrottlingSettingsTab extends UI.Widget.VBox implements
|
|
|
533
546
|
}
|
|
534
547
|
|
|
535
548
|
private conditionsUpdated(): void {
|
|
536
|
-
this.
|
|
549
|
+
this.customList.clear();
|
|
537
550
|
|
|
538
551
|
const conditions = this.customUserConditions.get();
|
|
539
552
|
for (let i = 0; i < conditions.length; ++i) {
|
|
540
|
-
this.
|
|
553
|
+
this.customList.appendItem(conditions[i], true);
|
|
541
554
|
}
|
|
542
|
-
|
|
543
|
-
this.list.appendSeparator();
|
|
544
555
|
}
|
|
545
556
|
|
|
546
557
|
private addButtonClicked(): void {
|
|
547
558
|
this.#customUserConditionsCount++;
|
|
548
|
-
this.
|
|
559
|
+
this.customList.addNewItem(this.customList.items.length, {
|
|
549
560
|
key: `USER_CUSTOM_SETTING_${this.#customUserConditionsCount}`,
|
|
550
561
|
title: () => '',
|
|
551
562
|
download: -1,
|
|
@@ -563,7 +574,7 @@ export class ThrottlingSettingsTab extends UI.Widget.VBox implements
|
|
|
563
574
|
const titleText = title.createChild('div', 'conditions-list-title-text');
|
|
564
575
|
const castedTitle = this.retrieveOptionsTitle(conditions);
|
|
565
576
|
titleText.textContent = castedTitle;
|
|
566
|
-
UI.Tooltip.Tooltip.install(
|
|
577
|
+
UI.Tooltip.Tooltip.install(title, castedTitle);
|
|
567
578
|
element.createChild('div', 'conditions-list-separator');
|
|
568
579
|
element.createChild('div', 'conditions-list-text').textContent = throughputText(conditions.download);
|
|
569
580
|
element.createChild('div', 'conditions-list-separator');
|
|
@@ -853,3 +864,41 @@ function percentText(percent: number): string {
|
|
|
853
864
|
}
|
|
854
865
|
return String(percent) + '%';
|
|
855
866
|
}
|
|
867
|
+
|
|
868
|
+
function createProfilesCard(heading: string, list: UI.ListWidget.ListWidget<SDK.NetworkManager.Conditions>,
|
|
869
|
+
parent: Element): HTMLElement {
|
|
870
|
+
const card = parent.createChild('devtools-card');
|
|
871
|
+
card.heading = heading;
|
|
872
|
+
const container = card.createChild('div');
|
|
873
|
+
list.element.classList.add('conditions-list');
|
|
874
|
+
list.registerRequiredCSS(throttlingSettingsTabStyles);
|
|
875
|
+
list.show(container);
|
|
876
|
+
return container;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
function appendHeaderColumn(element: Element, text: string): void {
|
|
880
|
+
element.createChild('div', 'conditions-list-separator');
|
|
881
|
+
const column = element.createChild('div', 'conditions-list-text');
|
|
882
|
+
column.textContent = text;
|
|
883
|
+
UI.Tooltip.Tooltip.install(column, text);
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
function createHeaderRow(): Element {
|
|
887
|
+
const element = document.createElement('div');
|
|
888
|
+
element.classList.add('conditions-list-item', 'conditions-list-header');
|
|
889
|
+
|
|
890
|
+
const title = element.createChild('div', 'conditions-list-text conditions-list-title');
|
|
891
|
+
const titleText = title.createChild('div', 'conditions-list-title-text');
|
|
892
|
+
const profileName = i18nString(UIStrings.profileName);
|
|
893
|
+
titleText.textContent = profileName;
|
|
894
|
+
UI.Tooltip.Tooltip.install(title, profileName);
|
|
895
|
+
|
|
896
|
+
appendHeaderColumn(element, i18nString(UIStrings.download));
|
|
897
|
+
appendHeaderColumn(element, i18nString(UIStrings.upload));
|
|
898
|
+
appendHeaderColumn(element, i18nString(UIStrings.latency));
|
|
899
|
+
appendHeaderColumn(element, i18nString(UIStrings.packetLoss));
|
|
900
|
+
appendHeaderColumn(element, i18nString(UIStrings.packetQueueLength));
|
|
901
|
+
appendHeaderColumn(element, i18nString(UIStrings.packetReordering));
|
|
902
|
+
|
|
903
|
+
return element;
|
|
904
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Copyright 2026 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
import * as Common from '../../core/common/common.js';
|
|
6
|
+
import type * as SDK from '../../core/sdk/sdk.js';
|
|
7
|
+
|
|
8
|
+
const resourceTypeToAsAttribute = new Map<Common.ResourceType.ResourceType, string>([
|
|
9
|
+
[Common.ResourceType.resourceTypes.Document, 'document'],
|
|
10
|
+
[Common.ResourceType.resourceTypes.Stylesheet, 'style'],
|
|
11
|
+
[Common.ResourceType.resourceTypes.Image, 'image'],
|
|
12
|
+
[Common.ResourceType.resourceTypes.Font, 'font'],
|
|
13
|
+
[Common.ResourceType.resourceTypes.Script, 'script'],
|
|
14
|
+
[Common.ResourceType.resourceTypes.TextTrack, 'track'],
|
|
15
|
+
[Common.ResourceType.resourceTypes.Manifest, 'manifest'],
|
|
16
|
+
[Common.ResourceType.resourceTypes.Fetch, 'fetch'],
|
|
17
|
+
[Common.ResourceType.resourceTypes.XHR, 'fetch'],
|
|
18
|
+
[Common.ResourceType.resourceTypes.Wasm, 'fetch'],
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Escapes HTML special characters.
|
|
23
|
+
* Crucial for URLs in href attributes to prevent characters like '&' from being
|
|
24
|
+
* interpreted as HTML entities (e.g., '©' becoming '©').
|
|
25
|
+
*/
|
|
26
|
+
function escapeHTML(str: string): string {
|
|
27
|
+
return str.replace(/&/g, '&')
|
|
28
|
+
.replace(/</g, '<')
|
|
29
|
+
.replace(/>/g, '>')
|
|
30
|
+
.replace(/"/g, '"')
|
|
31
|
+
.replace(/'/g, ''');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function parsePreloadLinkOrigins(request: SDK.NetworkRequest.NetworkRequest):
|
|
35
|
+
{requestOrigin: string|null, documentOrigin: string|null} {
|
|
36
|
+
const requestOrigin = request.parsedURL.securityOrigin();
|
|
37
|
+
const documentURL = request.documentURL;
|
|
38
|
+
const documentOrigin =
|
|
39
|
+
documentURL ? (Common.ParsedURL.ParsedURL.fromString(documentURL)?.securityOrigin() ?? null) : null;
|
|
40
|
+
return {requestOrigin, documentOrigin};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function determinePreloadLinkHref(request: SDK.NetworkRequest.NetworkRequest, isSameOrigin: boolean): string {
|
|
44
|
+
// For same-origin resources, use root-relative URL for environment portability.
|
|
45
|
+
if (isSameOrigin && request.parsedURL.isValid) {
|
|
46
|
+
return request.parsedURL.path + (request.parsedURL.queryParams ? '?' + request.parsedURL.queryParams : '');
|
|
47
|
+
}
|
|
48
|
+
return request.url();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function determinePreloadLinkCrossOrigin(request: SDK.NetworkRequest.NetworkRequest, isCrossOrigin: boolean): string {
|
|
52
|
+
const resourceType = request.resourceType();
|
|
53
|
+
const asValue = resourceTypeToAsAttribute.get(resourceType);
|
|
54
|
+
const isFont = resourceType === Common.ResourceType.resourceTypes.Font;
|
|
55
|
+
const isFetch = asValue === 'fetch';
|
|
56
|
+
const secFetchMode = request.requestHeaderValue('sec-fetch-mode')?.toLowerCase();
|
|
57
|
+
|
|
58
|
+
const needsCrossOrigin = isFont || isFetch || secFetchMode === 'cors';
|
|
59
|
+
|
|
60
|
+
if (!needsCrossOrigin) {
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const hasCredentials = request.includedRequestCookies().length > 0 ||
|
|
65
|
+
Boolean(request.requestHeaderValue('cookie') || request.requestHeaderValue('authorization'));
|
|
66
|
+
|
|
67
|
+
// Only use credentials mode if it is cross-origin AND has credentials.
|
|
68
|
+
// Same-origin CORS (anonymous) automatically sends credentials.
|
|
69
|
+
const useCredentials = isCrossOrigin && hasCredentials;
|
|
70
|
+
return useCredentials ? ' crossorigin="use-credentials"' : ' crossorigin';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Determines whether a network request can be preloaded.
|
|
75
|
+
*/
|
|
76
|
+
export function canPreloadRequest(request: SDK.NetworkRequest.NetworkRequest): boolean {
|
|
77
|
+
return resourceTypeToAsAttribute.has(request.resourceType());
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Generates an HTML `<link rel="preload">` element string for a given network request.
|
|
82
|
+
*/
|
|
83
|
+
export function generatePreloadLink(request: SDK.NetworkRequest.NetworkRequest): string {
|
|
84
|
+
const {requestOrigin, documentOrigin} = parsePreloadLinkOrigins(request);
|
|
85
|
+
const isSameOrigin = Boolean(requestOrigin && documentOrigin && requestOrigin === documentOrigin);
|
|
86
|
+
const isCrossOrigin = Boolean(requestOrigin && documentOrigin && requestOrigin !== documentOrigin);
|
|
87
|
+
|
|
88
|
+
const url = determinePreloadLinkHref(request, isSameOrigin);
|
|
89
|
+
const escapedUrl = escapeHTML(url);
|
|
90
|
+
|
|
91
|
+
const resourceType = request.resourceType();
|
|
92
|
+
const escapedMimeType = request.mimeType ? escapeHTML(request.mimeType) : '';
|
|
93
|
+
|
|
94
|
+
const asValue = resourceTypeToAsAttribute.get(resourceType);
|
|
95
|
+
const asAttr = `as="${asValue ?? 'fetch'}"`;
|
|
96
|
+
|
|
97
|
+
const crossoriginAttr = determinePreloadLinkCrossOrigin(request, isCrossOrigin);
|
|
98
|
+
const typeAttr = escapedMimeType ? ` type="${escapedMimeType}"` : '';
|
|
99
|
+
|
|
100
|
+
return `<link rel="preload" href="${escapedUrl}" ${asAttr}${typeAttr}${crossoriginAttr}>`;
|
|
101
|
+
}
|
|
@@ -41,7 +41,6 @@ import * as i18n from '../../core/i18n/i18n.js';
|
|
|
41
41
|
import * as Platform from '../../core/platform/platform.js';
|
|
42
42
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
43
43
|
import * as Protocol from '../../generated/protocol.js';
|
|
44
|
-
import * as Annotations from '../../models/annotations/annotations.js';
|
|
45
44
|
import * as Bindings from '../../models/bindings/bindings.js';
|
|
46
45
|
import * as HAR from '../../models/har/har.js';
|
|
47
46
|
import * as Logs from '../../models/logs/logs.js';
|
|
@@ -61,6 +60,7 @@ import * as Components from '../../ui/legacy/components/utils/utils.js';
|
|
|
61
60
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
62
61
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
63
62
|
|
|
63
|
+
import {canPreloadRequest, generatePreloadLink} from './LinkPreloadGenerator.js';
|
|
64
64
|
import {
|
|
65
65
|
Events,
|
|
66
66
|
type EventTypes,
|
|
@@ -284,6 +284,11 @@ const UIStrings = {
|
|
|
284
284
|
* refers to the format the data will be copied as, which is compatible with the fetch web API.
|
|
285
285
|
*/
|
|
286
286
|
copyAsFetch: 'Copy as `fetch`',
|
|
287
|
+
/**
|
|
288
|
+
* @description A context menu command in the Network panel, for copying a resource's link element
|
|
289
|
+
* to the clipboard. 'preload' refers to the HTML link relation format the data will be copied as.
|
|
290
|
+
*/
|
|
291
|
+
copyAsPreload: 'Copy as preload element',
|
|
287
292
|
/**
|
|
288
293
|
* @description Text in Network Log View of the Network panel. An action that copies a command to
|
|
289
294
|
* the developer's clipboard. The command allows the developer to replay this specific network
|
|
@@ -992,14 +997,6 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
|
992
997
|
return this.summaryToolbarInternal;
|
|
993
998
|
}
|
|
994
999
|
|
|
995
|
-
getDataGrid(): DataGrid.SortableDataGrid.SortableDataGrid<NetworkNode>|null {
|
|
996
|
-
if (Annotations.AnnotationRepository.annotationsEnabled()) {
|
|
997
|
-
return this.dataGrid;
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
return null;
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
1000
|
modelAdded(networkManager: SDK.NetworkManager.NetworkManager): void {
|
|
1004
1001
|
// TODO(allada) Remove dependency on networkManager and instead use NetworkLog and PageLoad for needed data.
|
|
1005
1002
|
const target = networkManager.target();
|
|
@@ -1812,6 +1809,7 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
|
1812
1809
|
copyMenu.defaultSection().appendItem(
|
|
1813
1810
|
i18nString(UIStrings.copyAsNodejsFetch), this.copyFetchCall.bind(this, request, FetchStyle.NODE_JS),
|
|
1814
1811
|
{disabled: disableIfBlob, jslogContext: 'copy-as-nodejs-fetch'});
|
|
1812
|
+
this.appendCopyAsPreloadItem(copyMenu, request);
|
|
1815
1813
|
|
|
1816
1814
|
if (Host.Platform.isWin()) {
|
|
1817
1815
|
copyMenu.footerSection().appendItem(
|
|
@@ -2011,6 +2009,27 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
|
|
|
2011
2009
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(commands);
|
|
2012
2010
|
}
|
|
2013
2011
|
|
|
2012
|
+
private copyPreloadElement(request: SDK.NetworkRequest.NetworkRequest): void {
|
|
2013
|
+
const preloadLink = generatePreloadLink(request);
|
|
2014
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(preloadLink);
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
private appendCopyAsPreloadItem(copyMenu: UI.ContextMenu.SubMenu, request: SDK.NetworkRequest.NetworkRequest): void {
|
|
2018
|
+
const isHttpOrHttps = request.parsedURL.scheme === 'http' || request.parsedURL.scheme === 'https';
|
|
2019
|
+
const isGetRequest = request.requestMethod === 'GET';
|
|
2020
|
+
|
|
2021
|
+
const networkManager = SDK.NetworkManager.NetworkManager.forRequest(request);
|
|
2022
|
+
const resourceTreeModel = networkManager?.target().model(SDK.ResourceTreeModel.ResourceTreeModel);
|
|
2023
|
+
const isMainDocument = Boolean(resourceTreeModel?.mainFrame && resourceTreeModel.mainFrame.id === request.frameId &&
|
|
2024
|
+
request.resourceType() === Common.ResourceType.resourceTypes.Document);
|
|
2025
|
+
|
|
2026
|
+
const disablePreload =
|
|
2027
|
+
!isHttpOrHttps || request.isBlobRequest() || !isGetRequest || isMainDocument || !canPreloadRequest(request);
|
|
2028
|
+
copyMenu.defaultSection().appendItem(i18nString(UIStrings.copyAsPreload),
|
|
2029
|
+
this.copyPreloadElement.bind(this, request),
|
|
2030
|
+
{disabled: disablePreload, jslogContext: 'copy-as-preload'});
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2014
2033
|
private async copyFetchCall(request: SDK.NetworkRequest.NetworkRequest, style: FetchStyle): Promise<void> {
|
|
2015
2034
|
const command = await this.generateFetchCall(request, style);
|
|
2016
2035
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(command);
|
|
@@ -40,12 +40,11 @@ import * as Host from '../../core/host/host.js';
|
|
|
40
40
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
41
41
|
import * as Platform from '../../core/platform/platform.js';
|
|
42
42
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
43
|
-
import * as Annotations from '../../models/annotations/annotations.js';
|
|
44
43
|
import * as Logs from '../../models/logs/logs.js';
|
|
45
44
|
import * as NetworkTimeCalculator from '../../models/network_time_calculator/network_time_calculator.js';
|
|
46
45
|
import * as Trace from '../../models/trace/trace.js';
|
|
47
46
|
import * as Workspace from '../../models/workspace/workspace.js';
|
|
48
|
-
import * as PanelCommon from '../../panels/common/common.js';
|
|
47
|
+
import type * as PanelCommon from '../../panels/common/common.js';
|
|
49
48
|
import * as NetworkForward from '../../panels/network/forward/forward.js';
|
|
50
49
|
import * as Tracing from '../../services/tracing/tracing.js';
|
|
51
50
|
import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';
|
|
@@ -340,14 +339,6 @@ export class NetworkPanel extends UI.Panel.Panel implements
|
|
|
340
339
|
HTMLElement);
|
|
341
340
|
panel.element.appendChild(this.fileSelectorElement);
|
|
342
341
|
|
|
343
|
-
if (Annotations.AnnotationRepository.annotationsEnabled()) {
|
|
344
|
-
const dataGrid = this.networkLogView.getDataGrid();
|
|
345
|
-
if (dataGrid) {
|
|
346
|
-
PanelCommon.AnnotationManager.instance().initializePlacementForAnnotationType(
|
|
347
|
-
Annotations.AnnotationType.NETWORK_REQUEST, this.resolveInitialState.bind(this), dataGrid.scrollContainer);
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
342
|
this.detailsWidget = new UI.Widget.VBox();
|
|
352
343
|
this.detailsWidget.element.classList.add('network-details-view');
|
|
353
344
|
this.splitWidget.setMainWidget(this.detailsWidget);
|
|
@@ -661,11 +652,6 @@ export class NetworkPanel extends UI.Panel.Panel implements
|
|
|
661
652
|
|
|
662
653
|
// Record the network tool load time after the panel has loaded.
|
|
663
654
|
UI.UIUserMetrics.UIUserMetrics.instance().panelLoaded('network', 'DevTools.Launch.Network');
|
|
664
|
-
|
|
665
|
-
if (Annotations.AnnotationRepository.annotationsEnabled()) {
|
|
666
|
-
void PanelCommon.AnnotationManager.instance().resolveAnnotationsOfType(
|
|
667
|
-
Annotations.AnnotationType.NETWORK_REQUEST);
|
|
668
|
-
}
|
|
669
655
|
}
|
|
670
656
|
|
|
671
657
|
override willHide(): void {
|
|
@@ -765,47 +751,6 @@ export class NetworkPanel extends UI.Panel.Panel implements
|
|
|
765
751
|
return this.networkItemView;
|
|
766
752
|
}
|
|
767
753
|
|
|
768
|
-
async resolveInitialState(
|
|
769
|
-
parentElement: Element, reveal: boolean, lookupId: string,
|
|
770
|
-
anchor?: SDK.DOMModel.DOMNode|SDK.NetworkRequest.NetworkRequest): Promise<{x: number, y: number}|null> {
|
|
771
|
-
let request = anchor as SDK.NetworkRequest.NetworkRequest;
|
|
772
|
-
if (!this.isShowing()) {
|
|
773
|
-
return null;
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
if (!request) {
|
|
777
|
-
const networkManager =
|
|
778
|
-
SDK.TargetManager.TargetManager.instance().scopeTarget()?.model(SDK.NetworkManager.NetworkManager);
|
|
779
|
-
if (!networkManager) {
|
|
780
|
-
return null;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
const requests = Logs.NetworkLog.NetworkLog.instance().requestsForId(lookupId);
|
|
784
|
-
if (requests.length === 0) {
|
|
785
|
-
console.warn('Network Request list is empty');
|
|
786
|
-
return null;
|
|
787
|
-
}
|
|
788
|
-
request = requests[0];
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
if (reveal) {
|
|
792
|
-
await Common.Revealer.reveal(request);
|
|
793
|
-
await this.selectAndActivateRequest(request);
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
const requestNode = this.networkLogView?.nodeForRequest(request);
|
|
797
|
-
if (requestNode?.element()) {
|
|
798
|
-
const targetRect = requestNode.element().getBoundingClientRect();
|
|
799
|
-
const parentRect = parentElement.getBoundingClientRect();
|
|
800
|
-
const relativeX = 4;
|
|
801
|
-
const relativeY = targetRect.y - parentRect.y + parentElement.scrollTop;
|
|
802
|
-
return {x: relativeX, y: relativeY};
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
console.warn('Could not find element for request:', anchor);
|
|
806
|
-
return null;
|
|
807
|
-
}
|
|
808
|
-
|
|
809
754
|
private updateUI(): void {
|
|
810
755
|
if (this.detailsWidget) {
|
|
811
756
|
this.detailsWidget.element.classList.toggle(
|
|
@@ -905,13 +850,6 @@ export class NetworkPanel extends UI.Panel.Panel implements
|
|
|
905
850
|
Trace.Types.Timing.Milli(this.calculator.minimumBoundary() * 1000),
|
|
906
851
|
Trace.Types.Timing.Milli(this.calculator.maximumBoundary() * 1000));
|
|
907
852
|
this.networkOverview.updateRequest(request);
|
|
908
|
-
|
|
909
|
-
if (Annotations.AnnotationRepository.annotationsEnabled()) {
|
|
910
|
-
requestAnimationFrame(() => {
|
|
911
|
-
void PanelCommon.AnnotationManager.instance().resolveAnnotationsOfType(
|
|
912
|
-
Annotations.AnnotationType.NETWORK_REQUEST);
|
|
913
|
-
});
|
|
914
|
-
}
|
|
915
853
|
}
|
|
916
854
|
|
|
917
855
|
resolveLocation(locationName: string): UI.View.ViewLocation|null {
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
/* eslint-disable @devtools/no-imperative-dom-api */
|
|
5
|
-
|
|
6
5
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
7
6
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
8
7
|
import * as Bindings from '../../models/bindings/bindings.js';
|
|
@@ -10,7 +9,7 @@ import * as Logs from '../../models/logs/logs.js';
|
|
|
10
9
|
import type * as StackTrace from '../../models/stack_trace/stack_trace.js';
|
|
11
10
|
import * as Components from '../../ui/legacy/components/utils/utils.js';
|
|
12
11
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
13
|
-
import {html, type LitTemplate, nothing, render, type TemplateResult} from '../../ui/lit/lit.js';
|
|
12
|
+
import {Directives, html, type LitTemplate, nothing, render, type TemplateResult} from '../../ui/lit/lit.js';
|
|
14
13
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
15
14
|
|
|
16
15
|
import requestInitiatorViewStyles from './requestInitiatorView.css.js';
|
|
@@ -34,6 +33,20 @@ const UIStrings = {
|
|
|
34
33
|
} as const;
|
|
35
34
|
const str_ = i18n.i18n.registerUIStrings('panels/network/RequestInitiatorView.ts', UIStrings);
|
|
36
35
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
36
|
+
|
|
37
|
+
const MAX_URL_LENGTH = 150;
|
|
38
|
+
|
|
39
|
+
function trimUrl(url: string): string {
|
|
40
|
+
if (url.length <= MAX_URL_LENGTH) {
|
|
41
|
+
return url;
|
|
42
|
+
}
|
|
43
|
+
// To avoid performance issues with extremely long URLs (e.g. 2MB base64 data URLs),
|
|
44
|
+
// we do a fast O(1) slice instead of using the O(N) Platform.StringUtilities.trimMiddle
|
|
45
|
+
// utility which instantiates Intl.Segmenter and iterates over every grapheme.
|
|
46
|
+
const halfMaxLength = Math.floor(MAX_URL_LENGTH / 2);
|
|
47
|
+
return url.substring(0, halfMaxLength) + '…' + url.substring(url.length - halfMaxLength);
|
|
48
|
+
}
|
|
49
|
+
|
|
37
50
|
export interface ViewInput {
|
|
38
51
|
initiatorGraph: Logs.NetworkLog.InitiatorGraph;
|
|
39
52
|
stackTrace: StackTrace.StackTrace.StackTrace|null;
|
|
@@ -87,11 +100,17 @@ export const DEFAULT_VIEW = (input: ViewInput, _output: undefined, target: HTMLE
|
|
|
87
100
|
const isCurrentRequest = (index === initiators.length - 1);
|
|
88
101
|
const hasFurtherInitiatedNodes = index + 1 < initiators.length;
|
|
89
102
|
const renderedChildren = isCurrentRequest ? renderInitiatedNodes(initiated, request, visited) : nothing;
|
|
103
|
+
const url = request.url();
|
|
104
|
+
// To avoid layout and rendering lag from extremely long URLs (like data: URLs),
|
|
105
|
+
// we only set the title/tooltip attribute if the URL is under 2000 characters.
|
|
106
|
+
const title = url.length < 2000 ? url : undefined;
|
|
90
107
|
|
|
91
108
|
// clang-format off
|
|
92
109
|
return html`
|
|
93
110
|
<li role="treeitem" ?selected=${isCurrentRequest} aria-expanded="true" open>
|
|
94
|
-
<span style=${isCurrentRequest ? 'font-weight: bold' : ''}
|
|
111
|
+
<span style=${isCurrentRequest ? 'font-weight: bold' : ''} title=${Directives.ifDefined(title) as string}>
|
|
112
|
+
${trimUrl(url)}
|
|
113
|
+
</span>
|
|
95
114
|
${hasFurtherInitiatedNodes || renderedChildren !== nothing ? html`
|
|
96
115
|
<ul role="group">
|
|
97
116
|
${renderInitiatorNodes(initiators, index + 1, initiated, visited)}
|
|
@@ -121,9 +140,15 @@ export const DEFAULT_VIEW = (input: ViewInput, _output: undefined, target: HTMLE
|
|
|
121
140
|
visited.add(child);
|
|
122
141
|
}
|
|
123
142
|
const renderedChildren = shouldRecurse ? renderInitiatedNodes(initiated, child, visited) : nothing;
|
|
143
|
+
const url = child.url();
|
|
144
|
+
// To avoid layout and rendering lag from extremely long URLs (like data: URLs),
|
|
145
|
+
// we only set the title/tooltip attribute if the URL is under 2000 characters.
|
|
146
|
+
const title = url.length < 2000 ? url : undefined;
|
|
124
147
|
return html`
|
|
125
148
|
<li role="treeitem" aria-expanded="true" open>
|
|
126
|
-
<span
|
|
149
|
+
<span title=${Directives.ifDefined(title) as string}>
|
|
150
|
+
${trimUrl(url)}
|
|
151
|
+
</span>
|
|
127
152
|
${renderedChildren !== nothing ? html`<ul role="group">${renderedChildren}</ul>` : nothing}
|
|
128
153
|
</li>
|
|
129
154
|
`;
|
|
@@ -17,9 +17,8 @@
|
|
|
17
17
|
margin: var(--sys-size-3) 0;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
.row
|
|
21
|
-
|
|
22
|
-
font-size: var(--monospace-font-size);
|
|
20
|
+
.row:hover {
|
|
21
|
+
background-color: var(--sys-color-state-hover-on-subtle);
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
.header-name {
|
|
@@ -57,7 +56,8 @@
|
|
|
57
56
|
display: flex;
|
|
58
57
|
overflow-wrap: anywhere;
|
|
59
58
|
margin-inline-end: 14px;
|
|
60
|
-
font: var(--
|
|
59
|
+
font-family: var(--monospace-font-family);
|
|
60
|
+
font-size: var(--monospace-font-size);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
.header-badge-text {
|
|
@@ -85,10 +85,12 @@
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
.call-to-action-body {
|
|
88
|
+
display: flex;
|
|
89
|
+
gap: var(--sys-size-4);
|
|
88
90
|
padding: 6px 0;
|
|
89
|
-
margin-left:
|
|
91
|
+
margin-left: var(--sys-size-1);
|
|
90
92
|
border-left: 2px solid var(--issue-color-yellow);
|
|
91
|
-
padding-left:
|
|
93
|
+
padding-left: 11px;
|
|
92
94
|
line-height: 20px;
|
|
93
95
|
}
|
|
94
96
|
|
|
@@ -117,7 +119,7 @@
|
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
.inline-icon {
|
|
120
|
-
|
|
122
|
+
margin-top: var(--sys-size-2);
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
.row-flex-icon {
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
/* eslint-disable @devtools/no-lit-render-outside-of-view */
|
|
5
5
|
|
|
6
6
|
import '../../../ui/kit/kit.js';
|
|
7
|
-
import '../../../ui/legacy/legacy.js';
|
|
8
7
|
|
|
9
8
|
import * as Host from '../../../core/host/host.js';
|
|
10
9
|
import * as i18n from '../../../core/i18n/i18n.js';
|
|
@@ -14,6 +13,7 @@ import type * as Protocol from '../../../generated/protocol.js';
|
|
|
14
13
|
import * as ClientVariations from '../../../third_party/chromium/client-variations/client-variations.js';
|
|
15
14
|
import * as Buttons from '../../../ui/components/buttons/buttons.js';
|
|
16
15
|
import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
|
|
16
|
+
import * as UI from '../../../ui/legacy/legacy.js';
|
|
17
17
|
import * as Lit from '../../../ui/lit/lit.js';
|
|
18
18
|
import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
|
|
19
19
|
|
|
@@ -23,6 +23,10 @@ import headerSectionRowStyles from './HeaderSectionRow.css.js';
|
|
|
23
23
|
const {render, html} = Lit;
|
|
24
24
|
|
|
25
25
|
const UIStrings = {
|
|
26
|
+
/**
|
|
27
|
+
* @description A context menu item to copy the value of a header.
|
|
28
|
+
*/
|
|
29
|
+
copyValue: 'Copy value',
|
|
26
30
|
/**
|
|
27
31
|
* @description Comment used in decoded X-Client-Data HTTP header output in Headers View of the Network panel
|
|
28
32
|
*/
|
|
@@ -197,6 +201,7 @@ export class HeaderSectionRow extends HTMLElement {
|
|
|
197
201
|
<div
|
|
198
202
|
class=${headerValueClasses}
|
|
199
203
|
@copy=${():void => Host.userMetrics.actionTaken(Host.UserMetrics.Action.NetworkPanelCopyValue)}
|
|
204
|
+
@contextmenu=${this.#onContextMenu}
|
|
200
205
|
>
|
|
201
206
|
${this.#renderHeaderValue()}
|
|
202
207
|
</div>
|
|
@@ -483,6 +488,20 @@ export class HeaderSectionRow extends HTMLElement {
|
|
|
483
488
|
}
|
|
484
489
|
event.preventDefault();
|
|
485
490
|
}
|
|
491
|
+
|
|
492
|
+
#onContextMenu(event: Event): void {
|
|
493
|
+
if (!this.#header) {
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
event.stopPropagation();
|
|
497
|
+
event.preventDefault();
|
|
498
|
+
const contextMenu = new UI.ContextMenu.ContextMenu(event);
|
|
499
|
+
contextMenu.clipboardSection().appendItem(i18nString(UIStrings.copyValue), () => {
|
|
500
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(this.#header?.value || '');
|
|
501
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.NetworkPanelCopyValue);
|
|
502
|
+
});
|
|
503
|
+
void contextMenu.show();
|
|
504
|
+
}
|
|
486
505
|
}
|
|
487
506
|
|
|
488
507
|
customElements.define('devtools-header-section-row', HeaderSectionRow);
|