chrome-devtools-frontend 1.0.1660788 → 1.0.1662289
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/evaluate-ai-css-completion/SKILL.md +143 -0
- package/.agents/skills/evaluate-ai-css-completion/scripts/evaluate.js +104 -0
- package/.agents/skills/migrate-chromium-test/SKILL.md +7 -2
- package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +7 -1
- package/docs/ui_engineering.md +75 -42
- package/eslint.config.mjs +7 -0
- package/extension-api/ExtensionAPI.d.ts +88 -0
- package/front_end/core/common/SettingRegistration.ts +0 -5
- package/front_end/core/host/InspectorFrontendHost.ts +1 -0
- package/front_end/core/host/InspectorFrontendHostStub.ts +2 -0
- package/front_end/core/platform/ArrayUtilities.ts +10 -0
- package/front_end/core/platform/StringUtilities.ts +20 -4
- package/front_end/core/sdk/CPUThrottlingManager.ts +2 -0
- package/front_end/core/sdk/DOMDebuggerModel.ts +2 -0
- package/front_end/core/sdk/DOMModel.ts +1 -0
- package/front_end/core/sdk/DebuggerModel.ts +4 -4
- package/front_end/core/sdk/EventBreakpointsModel.ts +2 -0
- package/front_end/core/sdk/FrameManager.ts +1 -0
- package/front_end/core/sdk/IsolateManager.ts +1 -0
- package/front_end/core/sdk/NetworkManager.ts +2 -0
- package/front_end/core/sdk/NetworkRequest.ts +1 -0
- package/front_end/core/sdk/PageResourceLoader.ts +2 -0
- package/front_end/core/sdk/SourceMap.ts +5 -5
- package/front_end/core/sdk/SourceMapManager.ts +3 -2
- package/front_end/core/sdk/TargetManager.ts +4 -0
- package/front_end/entrypoints/main/MainImpl.ts +2 -1
- package/front_end/foundation/README.md +86 -0
- package/front_end/generated/InspectorBackendCommands.ts +4 -5
- package/front_end/generated/protocol.ts +20 -38
- package/front_end/models/bindings/CompilerScriptMapping.ts +5 -5
- package/front_end/models/bindings/ContentProviderBasedProject.ts +2 -3
- package/front_end/models/bindings/DebuggerLanguagePlugins.ts +3 -3
- package/front_end/models/bindings/DefaultScriptMapping.ts +3 -3
- package/front_end/models/bindings/ResourceMapping.ts +3 -3
- package/front_end/models/bindings/ResourceScriptMapping.ts +2 -2
- package/front_end/models/bindings/SASSSourceMapping.ts +3 -3
- package/front_end/models/bindings/TempFile.ts +8 -3
- package/front_end/models/extensions/ExtensionAPI.ts +110 -46
- package/front_end/models/extensions/RecorderExtensionEndpoint.ts +7 -5
- package/front_end/models/formatter/ScriptFormatter.ts +8 -11
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +14 -5
- package/front_end/models/issues_manager/CheckFormsIssuesTrigger.ts +8 -9
- package/front_end/models/issues_manager/CookieIssue.ts +21 -9
- package/front_end/models/issues_manager/Issue.ts +3 -4
- package/front_end/models/issues_manager/IssueAggregator.ts +0 -9
- package/front_end/models/issues_manager/IssueResolver.ts +2 -2
- package/front_end/models/issues_manager/IssuesManager.ts +136 -137
- package/front_end/models/issues_manager/RelatedIssue.ts +10 -8
- package/front_end/models/issues_manager/issues_manager.ts +0 -2
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
- package/front_end/models/logs/RequestResolver.ts +2 -2
- package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +12 -9
- package/front_end/models/trace/handlers/FramesHandler.ts +4 -7
- package/front_end/models/trace/handlers/ModelHandlers.ts +0 -1
- package/front_end/models/trace/handlers/RendererHandler.ts +2 -15
- package/front_end/models/trace/handlers/Threads.ts +4 -11
- package/front_end/models/trace/insights/DOMSize.ts +1 -1
- package/front_end/models/workspace_diff/WorkspaceDiff.ts +10 -4
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +2 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +0 -44
- package/front_end/panels/application/CookieItemsView.ts +1 -1
- package/front_end/panels/application/ServiceWorkersView.ts +494 -411
- package/front_end/panels/application/WebMCPView.ts +38 -43
- package/front_end/panels/application/application.ts +0 -6
- package/front_end/panels/application/components/AdsView.ts +201 -30
- package/front_end/panels/application/components/adsView.css +25 -0
- package/front_end/panels/application/components/components.ts +0 -2
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +1 -1
- package/front_end/panels/application/preloading/components/RuleSetDetailsView.ts +2 -2
- package/front_end/panels/application/serviceWorkersView.css +40 -4
- package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +147 -123
- package/front_end/panels/common/ExtensionServer.ts +3 -3
- package/front_end/panels/console/ConsoleView.ts +3 -2
- package/front_end/panels/console/PromptBuilder.ts +2 -1
- package/front_end/panels/emulation/DeviceModeView.ts +164 -113
- package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
- package/front_end/panels/issues/IssueView.ts +0 -2
- package/front_end/panels/issues/IssuesPane.ts +1 -8
- package/front_end/panels/js_timeline/js_timeline-meta.ts +3 -2
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +53 -12
- package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +3 -3
- package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +5 -5
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryHighlightChipList.ts +4 -4
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +2 -2
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryNavigator.ts +6 -6
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +3 -3
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplay.ts +8 -9
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplayUtils.ts +2 -2
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterSettings.ts +1 -1
- package/front_end/panels/linear_memory_inspector/linear_memory_inspector-meta.ts +2 -2
- package/front_end/panels/network/RequestPayloadView.ts +92 -52
- package/front_end/panels/network/RequestTimingView.ts +95 -127
- package/front_end/panels/network/components/ResponseHeaderSection.ts +5 -3
- package/front_end/panels/profiler/HeapSnapshotView.ts +3 -3
- package/front_end/panels/profiler/WritableProfileHeader.ts +2 -2
- package/front_end/panels/recorder/{components/ControlButton.ts → ControlButton.ts} +9 -10
- package/front_end/panels/recorder/{components/CreateRecordingView.ts → CreateRecordingView.ts} +48 -47
- package/front_end/panels/recorder/{components/ExtensionView.ts → ExtensionView.ts} +8 -8
- package/front_end/panels/recorder/RecorderController.ts +302 -127
- package/front_end/panels/recorder/RecorderPanel.ts +1 -1
- package/front_end/panels/recorder/{components/RecordingListView.ts → RecordingListView.ts} +19 -20
- package/front_end/panels/recorder/{components/RecordingView.ts → RecordingView.ts} +88 -88
- package/front_end/panels/recorder/{components/ReplaySection.ts → ReplaySection.ts} +11 -11
- package/front_end/panels/recorder/{components/SelectorPicker.ts → SelectorPicker.ts} +13 -13
- package/front_end/panels/recorder/{components/StepEditor.ts → StepEditor.ts} +15 -15
- package/front_end/panels/recorder/{components/StepView.ts → StepView.ts} +10 -10
- package/front_end/panels/recorder/{components/TimelineSection.ts → TimelineSection.ts} +2 -2
- package/front_end/panels/recorder/recorder.ts +23 -1
- package/front_end/panels/recorder/util/util.ts +113 -0
- package/front_end/panels/sources/SourcesView.ts +0 -17
- package/front_end/panels/sources/TabbedEditorContainer.ts +1 -1
- package/front_end/panels/sources/UISourceCodeFrame.ts +42 -0
- package/front_end/panels/sources/sources.ts +0 -2
- package/front_end/panels/timeline/CompatibilityTracksAppender.ts +0 -17
- package/front_end/panels/timeline/IsolateSelector.ts +10 -8
- package/front_end/panels/timeline/ThreadAppender.ts +0 -106
- package/front_end/panels/timeline/TimelinePanel.ts +18 -7
- package/front_end/panels/timeline/TimelineUIUtils.ts +144 -129
- package/front_end/panels/timeline/timeline-meta.ts +3 -2
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/report_view/ReportView.ts +11 -5
- package/front_end/ui/components/report_view/report.css +4 -1
- package/front_end/ui/legacy/TextPrompt.ts +49 -1
- package/front_end/ui/legacy/Treeoutline.ts +3 -0
- package/front_end/ui/legacy/UIUtils.ts +11 -1
- package/front_end/ui/legacy/Widget.ts +14 -15
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +2 -2
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +11 -7
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +2 -1
- package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +10 -1
- package/front_end/ui/legacy/textPrompt.css +10 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +1 -1
- package/front_end/models/issues_manager/AttributionReportingIssue.ts +0 -247
- package/front_end/models/issues_manager/descriptions/arInsecureContext.md +0 -7
- package/front_end/models/issues_manager/descriptions/arInvalidInfoHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsSourceHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsTriggerHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arInvalidRegisterSourceHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arInvalidRegisterTriggerHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +0 -6
- package/front_end/models/issues_manager/descriptions/arNoRegisterOsSourceHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNoRegisterOsTriggerHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNoRegisterSourceHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNoRegisterTriggerHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNoWebOrOsSupport.md +0 -4
- package/front_end/models/issues_manager/descriptions/arOsSourceIgnored.md +0 -18
- package/front_end/models/issues_manager/descriptions/arOsTriggerIgnored.md +0 -19
- package/front_end/models/issues_manager/descriptions/arPermissionPolicyDisabled.md +0 -8
- package/front_end/models/issues_manager/descriptions/arSourceAndTriggerHeaders.md +0 -9
- package/front_end/models/issues_manager/descriptions/arSourceIgnored.md +0 -13
- package/front_end/models/issues_manager/descriptions/arTriggerIgnored.md +0 -12
- package/front_end/models/issues_manager/descriptions/arUntrustworthyReportingOrigin.md +0 -10
- package/front_end/models/issues_manager/descriptions/arWebAndOsHeaders.md +0 -11
- package/front_end/models/trace/handlers/AuctionWorkletsHandler.ts +0 -183
- package/front_end/panels/application/InterestGroupStorageModel.ts +0 -81
- package/front_end/panels/application/InterestGroupStorageView.ts +0 -151
- package/front_end/panels/application/InterestGroupTreeElement.ts +0 -65
- package/front_end/panels/application/components/InterestGroupAccessGrid.ts +0 -135
- package/front_end/panels/application/components/interestGroupAccessGrid.css +0 -27
- package/front_end/panels/application/interestGroupStorageView.css +0 -9
- package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +0 -182
- package/front_end/panels/recorder/components/components.ts +0 -25
- package/front_end/panels/recorder/components/util.ts +0 -116
- package/front_end/panels/sources/InplaceFormatterEditorAction.ts +0 -149
- /package/front_end/panels/recorder/{components/controlButton.css → controlButton.css} +0 -0
- /package/front_end/panels/recorder/{components/createRecordingView.css → createRecordingView.css} +0 -0
- /package/front_end/panels/recorder/{components/extensionView.css → extensionView.css} +0 -0
- /package/front_end/panels/recorder/{components/recordingListView.css → recordingListView.css} +0 -0
- /package/front_end/panels/recorder/{components/recordingView.css → recordingView.css} +0 -0
- /package/front_end/panels/recorder/{components/replaySection.css → replaySection.css} +0 -0
- /package/front_end/panels/recorder/{components/selectorPicker.css → selectorPicker.css} +0 -0
- /package/front_end/panels/recorder/{components/startView.css → startView.css} +0 -0
- /package/front_end/panels/recorder/{components/stepEditor.css → stepEditor.css} +0 -0
- /package/front_end/panels/recorder/{components/stepView.css → stepView.css} +0 -0
- /package/front_end/panels/recorder/{components/timelineSection.css → timelineSection.css} +0 -0
|
@@ -252,8 +252,8 @@ export interface ViewInput {
|
|
|
252
252
|
onPaste: () => void;
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
export function filterToolCalls(
|
|
256
|
-
|
|
255
|
+
export function filterToolCalls(toolCalls: WebMCP.WebMCPModel.Call[],
|
|
256
|
+
filterState: FilterState): WebMCP.WebMCPModel.Call[] {
|
|
257
257
|
let filtered = [...toolCalls];
|
|
258
258
|
|
|
259
259
|
const statusTypes = filterState.statusTypes;
|
|
@@ -734,35 +734,32 @@ export class WebMCPView extends UI.Widget.VBox {
|
|
|
734
734
|
|
|
735
735
|
#filterButtons: FilterMenuButtons;
|
|
736
736
|
|
|
737
|
-
static createFilterButtons(
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
return {button, setCount};
|
|
765
|
-
};
|
|
737
|
+
static createFilterButtons(onToolTypesClick: (contextMenu: UI.ContextMenu.ContextMenu) => void,
|
|
738
|
+
onStatusTypesClick: (contextMenu: UI.ContextMenu.ContextMenu) => void): FilterMenuButtons {
|
|
739
|
+
const createButton = (label: string, onContextMenu: (contextMenu: UI.ContextMenu.ContextMenu) => void,
|
|
740
|
+
jsLogContext: string): FilterMenuButton => {
|
|
741
|
+
const button = new UI.Toolbar.ToolbarMenuButton(onContextMenu,
|
|
742
|
+
/* isIconDropdown=*/ false, /* useSoftMenu=*/ true, jsLogContext,
|
|
743
|
+
/* iconName=*/ undefined,
|
|
744
|
+
/* keepOpen=*/ true);
|
|
745
|
+
button.setText(label);
|
|
746
|
+
|
|
747
|
+
/* eslint-disable-next-line @devtools/no-imperative-dom-api */
|
|
748
|
+
const adorner = new Adorners.Adorner.Adorner();
|
|
749
|
+
adorner.name = 'countWrapper';
|
|
750
|
+
const countElement = document.createElement('span');
|
|
751
|
+
adorner.append(countElement);
|
|
752
|
+
adorner.classList.add('active-filters-count');
|
|
753
|
+
adorner.classList.add('hidden');
|
|
754
|
+
button.setAdorner(adorner);
|
|
755
|
+
|
|
756
|
+
const setCount = (count: number): void => {
|
|
757
|
+
countElement.textContent = `${count}`;
|
|
758
|
+
count === 0 ? adorner.hide() : adorner.show();
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
return {button, setCount};
|
|
762
|
+
};
|
|
766
763
|
|
|
767
764
|
return {
|
|
768
765
|
toolTypes: createButton(i18nString(UIStrings.toolTypes), onToolTypesClick, 'webmcp.tool-types'),
|
|
@@ -968,20 +965,18 @@ export const PAYLOAD_DEFAULT_VIEW = (input: PayloadViewInput, output: object, ta
|
|
|
968
965
|
|
|
969
966
|
const createPayload = (parsedInput: unknown): TemplateResult => {
|
|
970
967
|
const object = new SDK.RemoteObject.LocalJSONObject(parsedInput);
|
|
971
|
-
const
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
}));
|
|
976
|
-
section.title = document.createTextNode(object.description);
|
|
977
|
-
section.listItemElement.classList.add('source-code', 'object-properties-section');
|
|
978
|
-
section.childrenListElement.classList.add('source-code', 'object-properties-section');
|
|
979
|
-
section.expand();
|
|
968
|
+
const objectTree = new ObjectUI.ObjectPropertiesSection.ObjectTree(object, {
|
|
969
|
+
readOnly: true,
|
|
970
|
+
propertiesMode: ObjectUI.ObjectPropertiesSection.ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
|
|
971
|
+
});
|
|
980
972
|
return html`<devtools-tree .template=${html`
|
|
981
973
|
<style>${ObjectUI.ObjectPropertiesSection.objectValueStyles}</style>
|
|
982
974
|
<style>${ObjectUI.ObjectPropertiesSection.objectPropertiesSectionStyles}</style>
|
|
983
975
|
<ul role="tree">
|
|
984
|
-
<
|
|
976
|
+
<li role=treeitem class="object-properties-section-root-element object-properties-section source-code" open>
|
|
977
|
+
${object.description}
|
|
978
|
+
${object.hasChildren ? ObjectUI.ObjectPropertiesSection.renderObjectTree(objectTree) : nothing}
|
|
979
|
+
</li>
|
|
985
980
|
</ul>
|
|
986
981
|
`}></devtools-tree>`;
|
|
987
982
|
};
|
|
@@ -1351,8 +1346,8 @@ export function parseToolSchema(schema: JSONSchema7): ParsedToolSchema {
|
|
|
1351
1346
|
}
|
|
1352
1347
|
}
|
|
1353
1348
|
|
|
1354
|
-
function parseProperty(
|
|
1355
|
-
|
|
1349
|
+
function parseProperty(name: string, propDef: JSONSchema7Definition,
|
|
1350
|
+
optional: boolean): ProtocolMonitor.JSONEditor.Parameter {
|
|
1356
1351
|
if (typeof propDef === 'boolean') {
|
|
1357
1352
|
return {
|
|
1358
1353
|
name,
|
|
@@ -18,9 +18,6 @@ import * as ExtensionStorageModel from './ExtensionStorageModel.js';
|
|
|
18
18
|
import * as FrameDetailsView from './FrameDetailsView.js';
|
|
19
19
|
import * as IndexedDBModel from './IndexedDBModel.js';
|
|
20
20
|
import * as IndexedDBViews from './IndexedDBViews.js';
|
|
21
|
-
import * as InterestGroupStorageModel from './InterestGroupStorageModel.js';
|
|
22
|
-
import * as InterestGroupStorageView from './InterestGroupStorageView.js';
|
|
23
|
-
import * as InterestGroupTreeElement from './InterestGroupTreeElement.js';
|
|
24
21
|
import * as KeyValueStorageItemsView from './KeyValueStorageItemsView.js';
|
|
25
22
|
import * as OpenedWindowDetailsView from './OpenedWindowDetailsView.js';
|
|
26
23
|
import * as OriginTrialTreeView from './OriginTrialTreeView.js';
|
|
@@ -62,9 +59,6 @@ export {
|
|
|
62
59
|
FrameDetailsView,
|
|
63
60
|
IndexedDBModel,
|
|
64
61
|
IndexedDBViews,
|
|
65
|
-
InterestGroupStorageModel,
|
|
66
|
-
InterestGroupStorageView,
|
|
67
|
-
InterestGroupTreeElement,
|
|
68
62
|
KeyValueStorageItemsView,
|
|
69
63
|
OpenedWindowDetailsView,
|
|
70
64
|
OriginTrialTreeView,
|
|
@@ -2,6 +2,8 @@
|
|
|
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
|
|
|
5
|
+
import '../../../ui/legacy/components/data_grid/data_grid.js';
|
|
6
|
+
|
|
5
7
|
import * as i18n from '../../../core/i18n/i18n.js';
|
|
6
8
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
7
9
|
import type * as Protocol from '../../../generated/protocol.js';
|
|
@@ -14,6 +16,10 @@ import adsViewStyles from './adsView.css.js';
|
|
|
14
16
|
const {html} = Lit;
|
|
15
17
|
|
|
16
18
|
const UIStrings = {
|
|
19
|
+
/**
|
|
20
|
+
* @description Title for the metrics table.
|
|
21
|
+
*/
|
|
22
|
+
metrics: 'Metrics',
|
|
17
23
|
/**
|
|
18
24
|
* @description Title for a metric showing the percentage of the viewport covered by ads.
|
|
19
25
|
*/
|
|
@@ -35,75 +41,135 @@ const UIStrings = {
|
|
|
35
41
|
* @example {5.00%} PH1
|
|
36
42
|
*/
|
|
37
43
|
average: '(Average: {PH1})',
|
|
44
|
+
/**
|
|
45
|
+
* @description Title for the ad iframes table.
|
|
46
|
+
* @example {3} PH1
|
|
47
|
+
*/
|
|
48
|
+
adIframesTitle: 'Ad iframes (total {PH1})',
|
|
49
|
+
/**
|
|
50
|
+
* @description Text to display when a value is not available.
|
|
51
|
+
*/
|
|
52
|
+
notAvailable: 'N/A',
|
|
53
|
+
/**
|
|
54
|
+
* @description Text to display when a frame has no name/id.
|
|
55
|
+
*/
|
|
56
|
+
unnamed: '<unnamed>',
|
|
57
|
+
/**
|
|
58
|
+
* @description Title for the Element Id column in the ad iframes table.
|
|
59
|
+
*/
|
|
60
|
+
elementId: 'Element ID',
|
|
61
|
+
/**
|
|
62
|
+
* @description Title for the Initial origin column in the ad iframes table.
|
|
63
|
+
*/
|
|
64
|
+
initialOrigin: 'Initial origin',
|
|
65
|
+
/**
|
|
66
|
+
* @description Title for the CPU column in the ad iframes table.
|
|
67
|
+
*/
|
|
68
|
+
cpu: 'CPU',
|
|
69
|
+
/**
|
|
70
|
+
* @description Title for the Network column in the ad iframes table.
|
|
71
|
+
*/
|
|
72
|
+
network: 'Network',
|
|
73
|
+
/**
|
|
74
|
+
* @description Accessible name for the ad iframes table.
|
|
75
|
+
*/
|
|
76
|
+
adIframes: 'Ad iframes',
|
|
38
77
|
} as const;
|
|
39
78
|
|
|
40
79
|
const str_ = i18n.i18n.registerUIStrings('panels/application/components/AdsView.ts', UIStrings);
|
|
41
80
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
42
81
|
|
|
82
|
+
/**
|
|
83
|
+
* @description Data for a single row in the ad iframes table.
|
|
84
|
+
*/
|
|
85
|
+
interface AdFrameNodeData {
|
|
86
|
+
elementId: string;
|
|
87
|
+
initialOrigin: string;
|
|
88
|
+
networkBytes: string;
|
|
89
|
+
cpuTime: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
43
92
|
export interface ViewInput {
|
|
44
93
|
metrics: Protocol.Ads.AdMetrics;
|
|
94
|
+
adFrames: AdFrameNodeData[];
|
|
45
95
|
}
|
|
46
96
|
|
|
47
97
|
export type View = (input: ViewInput, output: undefined, target: HTMLElement|DocumentFragment) => void;
|
|
48
98
|
|
|
99
|
+
const formatMetric = (val: number|undefined, formatter: (val: number) => string): string => {
|
|
100
|
+
if (val === undefined || val === -1) {
|
|
101
|
+
return i18nString(UIStrings.notAvailable);
|
|
102
|
+
}
|
|
103
|
+
return formatter(val);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const formatCpu = (val: number|undefined): string => {
|
|
107
|
+
return formatMetric(val, (v: number): string => i18n.TimeUtilities.millisToString(v));
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const formatNetwork = (val: number|undefined): string => {
|
|
111
|
+
return formatMetric(val, (v: number): string => i18n.ByteUtilities.bytesToString(v));
|
|
112
|
+
};
|
|
113
|
+
|
|
49
114
|
const DEFAULT_VIEW: View = (input, output, target) => {
|
|
50
115
|
const metrics = input.metrics;
|
|
51
116
|
|
|
52
117
|
const formatValue = (val: number, isPercentage: boolean): string => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
118
|
+
return formatMetric(val, (v: number): string => {
|
|
119
|
+
if (isPercentage) {
|
|
120
|
+
return new Intl
|
|
121
|
+
.NumberFormat(i18n.DevToolsLocale.DevToolsLocale.instance().locale, {
|
|
122
|
+
style: 'percent',
|
|
123
|
+
maximumFractionDigits: 0,
|
|
124
|
+
})
|
|
125
|
+
.format(v / 100);
|
|
126
|
+
}
|
|
127
|
+
return new Intl.NumberFormat(i18n.DevToolsLocale.DevToolsLocale.instance().locale).format(v);
|
|
128
|
+
});
|
|
62
129
|
};
|
|
63
130
|
|
|
64
|
-
const formatAverage = (val: number, isPercentage: boolean): string => {
|
|
65
|
-
|
|
131
|
+
const formatAverage = (val: number|undefined, isPercentage: boolean): string => {
|
|
132
|
+
return formatMetric(val, (v: number): string => {
|
|
133
|
+
if (isPercentage) {
|
|
134
|
+
return new Intl
|
|
135
|
+
.NumberFormat(i18n.DevToolsLocale.DevToolsLocale.instance().locale, {
|
|
136
|
+
style: 'percent',
|
|
137
|
+
minimumFractionDigits: 2,
|
|
138
|
+
maximumFractionDigits: 2,
|
|
139
|
+
})
|
|
140
|
+
.format(v / 100);
|
|
141
|
+
}
|
|
66
142
|
return new Intl
|
|
67
143
|
.NumberFormat(i18n.DevToolsLocale.DevToolsLocale.instance().locale, {
|
|
68
|
-
style: 'percent',
|
|
69
144
|
minimumFractionDigits: 2,
|
|
70
145
|
maximumFractionDigits: 2,
|
|
71
146
|
})
|
|
72
|
-
.format(
|
|
73
|
-
}
|
|
74
|
-
return new Intl
|
|
75
|
-
.NumberFormat(i18n.DevToolsLocale.DevToolsLocale.instance().locale, {
|
|
76
|
-
minimumFractionDigits: 2,
|
|
77
|
-
maximumFractionDigits: 2,
|
|
78
|
-
})
|
|
79
|
-
.format(val);
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const formatCpu = (val: number): string => {
|
|
83
|
-
return i18n.TimeUtilities.millisToString(val);
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const formatNetwork = (val: number): string => {
|
|
87
|
-
return i18n.ByteUtilities.bytesToString(val);
|
|
147
|
+
.format(v);
|
|
148
|
+
});
|
|
88
149
|
};
|
|
89
150
|
|
|
90
151
|
// clang-format off
|
|
91
152
|
Lit.render(html`
|
|
92
153
|
<style>${adsViewStyles}</style>
|
|
93
154
|
<div class="ads-view-container" jslog=${VisualLogging.pane('ads')}>
|
|
155
|
+
<div class="metrics-title">${i18nString(UIStrings.metrics)}</div>
|
|
94
156
|
<dl class="metrics-container">
|
|
95
157
|
<div class="metric-box">
|
|
96
158
|
<dt class="metric-title">${i18nString(UIStrings.viewportAdDensity)}</dt>
|
|
97
159
|
<dd class="metric-value">
|
|
98
160
|
<span>${formatValue(metrics.viewportAdDensityByArea, true)}</span>
|
|
99
|
-
<span class="metric-average">${i18nString(UIStrings.average, {
|
|
161
|
+
<span class="metric-average">${i18nString(UIStrings.average, {
|
|
162
|
+
PH1: formatAverage(metrics.averageViewportAdDensityByArea, true),
|
|
163
|
+
})}</span>
|
|
100
164
|
</dd>
|
|
101
165
|
</div>
|
|
102
166
|
<div class="metric-box">
|
|
103
167
|
<dt class="metric-title">${i18nString(UIStrings.viewportAdCount)}</dt>
|
|
104
168
|
<dd class="metric-value">
|
|
105
169
|
<span>${formatValue(metrics.viewportAdCount, false)}</span>
|
|
106
|
-
<span class="metric-average">${i18nString(UIStrings.average, {
|
|
170
|
+
<span class="metric-average">${i18nString(UIStrings.average, {
|
|
171
|
+
PH1: formatAverage(metrics.averageViewportAdCount, false),
|
|
172
|
+
})}</span>
|
|
107
173
|
</dd>
|
|
108
174
|
</div>
|
|
109
175
|
<div class="metric-box">
|
|
@@ -119,6 +185,27 @@ const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
119
185
|
</dd>
|
|
120
186
|
</div>
|
|
121
187
|
</dl>
|
|
188
|
+
<div class="ad-frames-title">${i18nString(UIStrings.adIframesTitle, {PH1: input.adFrames.length})}</div>
|
|
189
|
+
<div class="ad-frames-container">
|
|
190
|
+
<devtools-data-grid striped resize="last" class="ad-frames-data-grid" name=${i18nString(UIStrings.adIframes)}>
|
|
191
|
+
<table>
|
|
192
|
+
<tr>
|
|
193
|
+
<th id="elementId" weight="1">${i18nString(UIStrings.elementId)}</th>
|
|
194
|
+
<th id="initialOrigin" weight="2">${i18nString(UIStrings.initialOrigin)}</th>
|
|
195
|
+
<th id="cpuTime" weight="1">${i18nString(UIStrings.cpu)}</th>
|
|
196
|
+
<th id="networkBytes" weight="1">${i18nString(UIStrings.network)}</th>
|
|
197
|
+
</tr>
|
|
198
|
+
${input.adFrames.map(frame => html`
|
|
199
|
+
<tr>
|
|
200
|
+
<td title=${frame.elementId}>${frame.elementId}</td>
|
|
201
|
+
<td title=${frame.initialOrigin}>${frame.initialOrigin}</td>
|
|
202
|
+
<td title=${frame.cpuTime}>${frame.cpuTime}</td>
|
|
203
|
+
<td title=${frame.networkBytes}>${frame.networkBytes}</td>
|
|
204
|
+
</tr>
|
|
205
|
+
`)}
|
|
206
|
+
</table>
|
|
207
|
+
</devtools-data-grid>
|
|
208
|
+
</div>
|
|
122
209
|
</div>
|
|
123
210
|
`, target);
|
|
124
211
|
// clang-format on
|
|
@@ -131,6 +218,10 @@ export class AdsView extends UI.Widget.Widget {
|
|
|
131
218
|
#pollSessionId = 0;
|
|
132
219
|
#view: View;
|
|
133
220
|
|
|
221
|
+
readonly #adFrames = new Map<Protocol.Page.FrameId, Protocol.Ads.AdFrameData>();
|
|
222
|
+
readonly #adIframeElementIds = new Map<Protocol.Page.FrameId, string|null>();
|
|
223
|
+
readonly #fetchingElementIds = new Set<Protocol.Page.FrameId>();
|
|
224
|
+
|
|
134
225
|
constructor(view: View = DEFAULT_VIEW) {
|
|
135
226
|
super({useShadowDom: true});
|
|
136
227
|
this.#view = view;
|
|
@@ -194,6 +285,7 @@ export class AdsView extends UI.Widget.Widget {
|
|
|
194
285
|
}
|
|
195
286
|
if (!response.getError()) {
|
|
196
287
|
this.#currentMetrics = response.metrics;
|
|
288
|
+
this.#processAdFrames(response.metrics);
|
|
197
289
|
this.requestUpdate();
|
|
198
290
|
}
|
|
199
291
|
}
|
|
@@ -203,6 +295,65 @@ export class AdsView extends UI.Widget.Widget {
|
|
|
203
295
|
}
|
|
204
296
|
}
|
|
205
297
|
|
|
298
|
+
#processAdFrames(metrics: Protocol.Ads.AdMetrics): void {
|
|
299
|
+
// Drop removed frames from the local cache.
|
|
300
|
+
for (const frameId of metrics.removeAdFrames || []) {
|
|
301
|
+
this.#adFrames.delete(frameId);
|
|
302
|
+
this.#adIframeElementIds.delete(frameId);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Merge partial updates into the local cache.
|
|
306
|
+
for (const frame of metrics.updateAdFrames || []) {
|
|
307
|
+
const frameId = frame.frameId;
|
|
308
|
+
const existingFrame = this.#adFrames.get(frameId) || {} as Protocol.Ads.AdFrameData;
|
|
309
|
+
|
|
310
|
+
// Object Spread / Protocol Undefined Behavior
|
|
311
|
+
// To reduce the payload size, the C++ backend only sends the 'initialOrigin' field
|
|
312
|
+
// when it changes since the last sent message for the same frame. Because
|
|
313
|
+
// the parsed JSON frame won't have the 'initialOrigin' key if it hasn't changed,
|
|
314
|
+
// spreading it over existingFrame won't overwrite existingFrame.initialOrigin with
|
|
315
|
+
// undefined.
|
|
316
|
+
const newFrame = {...existingFrame, ...frame} as Protocol.Ads.AdFrameData;
|
|
317
|
+
this.#adFrames.set(frameId, newFrame);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Asynchronously fetch Element IDs for newly tracked frames.
|
|
321
|
+
// Duplicate requests are prevented by #fetchingElementIds.
|
|
322
|
+
for (const frameId of this.#adFrames.keys()) {
|
|
323
|
+
if (!this.#adIframeElementIds.has(frameId) && !this.#fetchingElementIds.has(frameId)) {
|
|
324
|
+
this.#fetchingElementIds.add(frameId);
|
|
325
|
+
void this.#fetchIframeElementId(frameId)
|
|
326
|
+
.then(elementId => {
|
|
327
|
+
if (this.#adFrames.has(frameId) && elementId !== undefined) {
|
|
328
|
+
this.#adIframeElementIds.set(frameId, elementId);
|
|
329
|
+
}
|
|
330
|
+
})
|
|
331
|
+
.catch(() => {})
|
|
332
|
+
.finally(() => {
|
|
333
|
+
this.#fetchingElementIds.delete(frameId);
|
|
334
|
+
this.requestUpdate();
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
async #fetchIframeElementId(frameId: Protocol.Page.FrameId): Promise<string|null|undefined> {
|
|
341
|
+
const frame = SDK.FrameManager.FrameManager.instance().getFrame(frameId);
|
|
342
|
+
if (!frame) {
|
|
343
|
+
return undefined;
|
|
344
|
+
}
|
|
345
|
+
const domModel = frame.resourceTreeModel().target().model(SDK.DOMModel.DOMModel);
|
|
346
|
+
if (!domModel) {
|
|
347
|
+
return undefined;
|
|
348
|
+
}
|
|
349
|
+
const deferredNode = await domModel.getOwnerNodeForFrame(frameId);
|
|
350
|
+
if (deferredNode) {
|
|
351
|
+
const node = await deferredNode.resolvePromise();
|
|
352
|
+
return node?.getAttribute('id') || null;
|
|
353
|
+
}
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
|
|
206
357
|
#onPrimaryPageChanged(): void {
|
|
207
358
|
this.#currentMetrics = {
|
|
208
359
|
viewportAdDensityByArea: 0,
|
|
@@ -214,12 +365,32 @@ export class AdsView extends UI.Widget.Widget {
|
|
|
214
365
|
updateAdFrames: [],
|
|
215
366
|
removeAdFrames: [],
|
|
216
367
|
};
|
|
368
|
+
this.#adFrames.clear();
|
|
369
|
+
this.#adIframeElementIds.clear();
|
|
370
|
+
this.#fetchingElementIds.clear();
|
|
217
371
|
this.requestUpdate();
|
|
218
372
|
}
|
|
219
373
|
|
|
220
374
|
override performUpdate(): void {
|
|
375
|
+
const adFramesArray: AdFrameNodeData[] = [];
|
|
376
|
+
for (const [frameId, frame] of this.#adFrames) {
|
|
377
|
+
// The table displays the resolved ID, or an <unnamed> placeholder if the
|
|
378
|
+
// element lacks an ID attribute, or an empty string while pending.
|
|
379
|
+
const elementIdText = this.#adIframeElementIds.has(frameId) ?
|
|
380
|
+
(this.#adIframeElementIds.get(frameId) || i18nString(UIStrings.unnamed)) :
|
|
381
|
+
'';
|
|
382
|
+
|
|
383
|
+
adFramesArray.push({
|
|
384
|
+
elementId: elementIdText,
|
|
385
|
+
initialOrigin: frame.initialOrigin || '',
|
|
386
|
+
cpuTime: formatCpu(frame.cpuTime),
|
|
387
|
+
networkBytes: formatNetwork(frame.networkBytes),
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
|
|
221
391
|
const viewInput: ViewInput = {
|
|
222
392
|
metrics: this.#currentMetrics,
|
|
393
|
+
adFrames: adFramesArray,
|
|
223
394
|
};
|
|
224
395
|
this.#view(viewInput, undefined, this.contentElement);
|
|
225
396
|
}
|
|
@@ -58,3 +58,28 @@
|
|
|
58
58
|
font-weight: normal;
|
|
59
59
|
color: var(--sys-color-on-surface-subtle);
|
|
60
60
|
}
|
|
61
|
+
|
|
62
|
+
.metrics-title,
|
|
63
|
+
.ad-frames-title {
|
|
64
|
+
color: var(--sys-color-on-surface);
|
|
65
|
+
flex: 0 0 auto;
|
|
66
|
+
font-weight: bold;
|
|
67
|
+
margin-bottom: 8px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.ad-frames-data-grid {
|
|
71
|
+
flex: auto;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.ad-frames-container {
|
|
75
|
+
border: 1px solid var(--sys-color-divider);
|
|
76
|
+
display: flex;
|
|
77
|
+
flex: auto;
|
|
78
|
+
flex-direction: column;
|
|
79
|
+
margin-bottom: 24px;
|
|
80
|
+
height: 300px;
|
|
81
|
+
min-height: 150px;
|
|
82
|
+
position: relative;
|
|
83
|
+
resize: vertical;
|
|
84
|
+
overflow: hidden;
|
|
85
|
+
}
|
|
@@ -7,7 +7,6 @@ import * as BackForwardCacheView from './BackForwardCacheView.js';
|
|
|
7
7
|
import * as BounceTrackingMitigationsView from './BounceTrackingMitigationsView.js';
|
|
8
8
|
import * as CrashReportContextGrid from './CrashReportContextGrid.js';
|
|
9
9
|
import * as EndpointsGrid from './EndpointsGrid.js';
|
|
10
|
-
import * as InterestGroupAccessGrid from './InterestGroupAccessGrid.js';
|
|
11
10
|
import * as PermissionsPolicySection from './PermissionsPolicySection.js';
|
|
12
11
|
import * as ProtocolHandlersView from './ProtocolHandlersView.js';
|
|
13
12
|
import * as ReportsGrid from './ReportsGrid.js';
|
|
@@ -23,7 +22,6 @@ export {
|
|
|
23
22
|
BounceTrackingMitigationsView,
|
|
24
23
|
CrashReportContextGrid,
|
|
25
24
|
EndpointsGrid,
|
|
26
|
-
InterestGroupAccessGrid,
|
|
27
25
|
PermissionsPolicySection,
|
|
28
26
|
ProtocolHandlersView,
|
|
29
27
|
ReportsGrid,
|
|
@@ -243,7 +243,7 @@ export class PreloadingDetailsReportView extends LegacyWrapper.LegacyWrapper.Wra
|
|
|
243
243
|
.data=${
|
|
244
244
|
{
|
|
245
245
|
affectedRequest,
|
|
246
|
-
requestResolver: this.#data.requestResolver || new Logs.RequestResolver.RequestResolver(),
|
|
246
|
+
requestResolver: this.#data.requestResolver || new Logs.RequestResolver.RequestResolver(Logs.NetworkLog.NetworkLog.instance()),
|
|
247
247
|
displayURL: true,
|
|
248
248
|
urlToDisplay: url,
|
|
249
249
|
}
|
|
@@ -129,8 +129,8 @@ export class RuleSetDetailsView extends UI.Widget.VBox {
|
|
|
129
129
|
|
|
130
130
|
async #getSourceText(): Promise<string> {
|
|
131
131
|
if (this.#shouldPrettyPrint && this.#ruleSet?.sourceText !== undefined) {
|
|
132
|
-
const formattedResult =
|
|
133
|
-
|
|
132
|
+
const formattedResult = await Formatter.ScriptFormatter.formatScriptContent(
|
|
133
|
+
SDK.TargetManager.TargetManager.instance().settings, 'application/json', this.#ruleSet.sourceText);
|
|
134
134
|
return formattedResult.formattedContent;
|
|
135
135
|
}
|
|
136
136
|
|
|
@@ -96,10 +96,6 @@
|
|
|
96
96
|
min-width: 80px;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
.report-field-value {
|
|
100
|
-
white-space: normal;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
99
|
.report-field-value-filename,
|
|
104
100
|
.service-worker-client-string {
|
|
105
101
|
max-width: 400px;
|
|
@@ -162,3 +158,43 @@ devtools-icon.error-icon {
|
|
|
162
158
|
vertical-align: bottom;
|
|
163
159
|
width: var(--sys-size-7);
|
|
164
160
|
}
|
|
161
|
+
|
|
162
|
+
.service-worker-toolbar {
|
|
163
|
+
margin-left: var(--sys-size-4);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.report-field {
|
|
167
|
+
display: flex;
|
|
168
|
+
padding: var(--sys-size-3) 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.report-field-name {
|
|
172
|
+
font: var(--sys-typescale-body5-medium);
|
|
173
|
+
color: var(--sys-color-on-surface-subtle);
|
|
174
|
+
flex: 0 0 128px;
|
|
175
|
+
text-align: left;
|
|
176
|
+
white-space: pre-wrap;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.report-field-value {
|
|
180
|
+
font: var(--sys-typescale-body4-regular);
|
|
181
|
+
flex: auto;
|
|
182
|
+
padding: 0 var(--sys-size-6);
|
|
183
|
+
white-space: normal;
|
|
184
|
+
user-select: text;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.service-worker-section {
|
|
188
|
+
border-bottom: 1px solid var(--sys-color-divider);
|
|
189
|
+
grid-column: 1 / 3;
|
|
190
|
+
padding: 0 var(--sys-size-9) 11px var(--sys-size-9);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.service-worker-section-container {
|
|
194
|
+
display: contents;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
devtools-widget {
|
|
198
|
+
display: block;
|
|
199
|
+
}
|
|
200
|
+
|