chrome-devtools-frontend 1.0.1581449 → 1.0.1582745
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/prompts/merging-devtools-module.md +144 -0
- package/agents/prompts/ui-widgets.md +351 -0
- package/agents/prompts/verification.md +2 -1
- package/docs/contributing/README.md +5 -6
- package/docs/contributing/changes.md +1 -2
- package/docs/styleguide/ux/README.md +1 -1
- package/front_end/core/sdk/OverlayModel.ts +4 -2
- package/front_end/core/sdk/RemoteObject.ts +7 -1
- package/front_end/core/sdk/StorageKeyManager.ts +6 -1
- package/front_end/core/sdk/Target.ts +4 -2
- package/front_end/entrypoint_template.html +5 -1
- package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +31 -40
- package/front_end/entrypoints/greendev_floaty/floaty.css +41 -1
- package/front_end/entrypoints/greendev_floaty/floaty.html +8 -1
- package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +5 -5
- package/front_end/entrypoints/node_app/app/NodeMain.ts +19 -1
- package/front_end/entrypoints/node_app/node_app.ts +34 -0
- package/front_end/generated/InspectorBackendCommands.ts +1 -1
- package/front_end/generated/SupportedCSSProperties.js +2 -0
- package/front_end/generated/protocol.ts +0 -6
- package/front_end/models/ai_assistance/AiConversation.ts +10 -0
- package/front_end/models/ai_assistance/agents/AiAgent.ts +2 -0
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +26 -4
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +85 -7
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +2 -6
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +66 -2
- package/front_end/models/computed_style/ComputedStyleModel.ts +26 -0
- package/front_end/models/greendev/Prototypes.ts +1 -10
- package/front_end/models/issues_manager/ConnectionAllowlistIssue.ts +75 -0
- package/front_end/models/issues_manager/CookieIssue.ts +0 -28
- package/front_end/models/issues_manager/FederatedAuthRequestIssue.ts +0 -30
- package/front_end/models/issues_manager/IssuesManager.ts +5 -0
- package/front_end/models/issues_manager/descriptions/connectionAllowlistInvalidAllowlistItemType.md +12 -0
- package/front_end/models/issues_manager/descriptions/connectionAllowlistInvalidHeader.md +12 -0
- package/front_end/models/issues_manager/descriptions/connectionAllowlistInvalidUrlPattern.md +8 -0
- package/front_end/models/issues_manager/descriptions/connectionAllowlistItemNotInnerList.md +12 -0
- package/front_end/models/issues_manager/descriptions/connectionAllowlistMoreThanOneList.md +7 -0
- package/front_end/models/issues_manager/descriptions/connectionAllowlistReportingEndpointNotToken.md +10 -0
- package/front_end/models/issues_manager/issues_manager.ts +2 -0
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +93 -6
- package/front_end/panels/ai_assistance/components/ChatInput.ts +8 -4
- package/front_end/panels/application/ApplicationPanelSidebar.ts +13 -11
- package/front_end/panels/application/DOMStorageModel.ts +1 -1
- package/front_end/panels/application/ResourcesPanel.ts +10 -5
- package/front_end/panels/application/preloading/PreloadingView.ts +8 -1
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +4 -1
- package/front_end/panels/application/preloading/components/PreloadingGrid.ts +2 -1
- package/front_end/panels/application/preloading/components/PreloadingString.ts +12 -3
- package/front_end/panels/application/preloading/helper/PreloadingForward.ts +14 -0
- package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +37 -3
- package/front_end/panels/changes/ChangesSidebar.ts +2 -6
- package/front_end/panels/common/AiCodeCompletionTeaser.ts +13 -3
- package/front_end/panels/common/aiCodeCompletionTeaser.css +6 -0
- package/front_end/panels/console/ConsoleSidebar.ts +3 -11
- package/front_end/panels/console_counters/WarningErrorCounter.ts +16 -10
- package/front_end/panels/elements/ComputedStyleWidget.ts +55 -37
- package/front_end/panels/elements/PlatformFontsWidget.ts +23 -10
- package/front_end/panels/greendev/GreenDevPanel.css +42 -1
- package/front_end/panels/greendev/GreenDevPanel.ts +30 -1
- package/front_end/panels/lighthouse/LighthouseStartView.ts +3 -5
- package/front_end/panels/lighthouse/lighthouseStartView.css +6 -0
- package/front_end/panels/network/NetworkLogView.ts +6 -6
- package/front_end/panels/network/RequestInitiatorView.ts +27 -19
- package/front_end/panels/network/RequestTimingView.ts +1 -1
- package/front_end/panels/settings/AISettingsTab.ts +1 -5
- package/front_end/panels/settings/KeybindsSettingsTab.ts +4 -3
- package/front_end/panels/settings/SettingsScreen.ts +0 -51
- package/front_end/panels/sources/OutlineQuickOpen.ts +19 -0
- package/front_end/panels/timeline/AnimationsTrackAppender.ts +4 -1
- package/front_end/panels/timeline/InteractionsTrackAppender.ts +1 -1
- package/front_end/panels/timeline/TimelinePanel.ts +25 -0
- package/front_end/panels/timeline/TimelineUIUtils.ts +13 -16
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/lighthouse/README.chromium +2 -2
- package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +145 -144
- package/front_end/third_party/lighthouse/report/bundle.js +12 -5
- package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +2 -2
- package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +5 -1
- package/front_end/ui/legacy/ListControl.ts +28 -1
- package/front_end/ui/legacy/Toolbar.ts +4 -4
- package/front_end/ui/legacy/Treeoutline.ts +5 -5
- package/front_end/ui/legacy/UIUtils.ts +26 -10
- package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +10 -13
- package/front_end/ui/legacy/components/utils/Linkifier.ts +4 -7
- package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
- package/inspector_overlay/main.ts +18 -3
- package/inspector_overlay/tool_green_dev_anchors.css +54 -0
- package/inspector_overlay/tool_green_dev_anchors.ts +164 -0
- package/inspector_overlay/tool_persistent.ts +14 -0
- package/package.json +1 -1
- package/docs/contributing/design.md +0 -166
- package/docs/design_guidelines.md +0 -1
- package/front_end/models/issues_manager/descriptions/federatedAuthRequestClientMetadataHttpNotFound.md +0 -1
- package/front_end/models/issues_manager/descriptions/federatedAuthRequestClientMetadataInvalidResponse.md +0 -1
- package/front_end/models/issues_manager/descriptions/federatedAuthRequestClientMetadataNoResponse.md +0 -1
|
@@ -9,7 +9,9 @@ import * as Platform from '../../../core/platform/platform.js';
|
|
|
9
9
|
import * as Root from '../../../core/root/root.js';
|
|
10
10
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
11
11
|
import * as Logs from '../../logs/logs.js';
|
|
12
|
+
import type * as Trace from '../../trace/trace.js';
|
|
12
13
|
import * as Workspace from '../../workspace/workspace.js';
|
|
14
|
+
import {AgentFocus} from '../performance/AIContext.js';
|
|
13
15
|
|
|
14
16
|
import {
|
|
15
17
|
type AgentOptions,
|
|
@@ -30,7 +32,7 @@ You aim to help developers of all levels, prioritizing teaching web concepts as
|
|
|
30
32
|
|
|
31
33
|
# Considerations
|
|
32
34
|
* Determine what the question the domain of the question is - styling, network, sources, performance or other part of DevTools.
|
|
33
|
-
*
|
|
35
|
+
* Proactively try to gather additional data. If a select specific data can be selected, select one.
|
|
34
36
|
* Avoid making assumptions without sufficient evidence, and always seek further clarification if needed.
|
|
35
37
|
* Always explore multiple possible explanations for the observed behavior before settling on a conclusion.
|
|
36
38
|
* When presenting solutions, clearly distinguish between the primary cause and contributing factors.
|
|
@@ -71,11 +73,19 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
71
73
|
};
|
|
72
74
|
}
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
readonly #performanceRecordAndReload?: () => Promise<Trace.TraceModel.ParsedTrace>;
|
|
77
|
+
readonly #onInspectElement?: () => Promise<SDK.DOMModel.DOMNode|null>;
|
|
78
|
+
|
|
79
|
+
constructor(opts: AgentOptions&{
|
|
80
|
+
performanceRecordAndReload?: () => Promise<Trace.TraceModel.ParsedTrace>,
|
|
81
|
+
onInspectElement?: () => Promise<SDK.DOMModel.DOMNode|null>,
|
|
82
|
+
}) {
|
|
75
83
|
super(opts);
|
|
84
|
+
this.#performanceRecordAndReload = opts.performanceRecordAndReload;
|
|
85
|
+
this.#onInspectElement = opts.onInspectElement;
|
|
76
86
|
|
|
77
87
|
this.declareFunction<Record<string, never>>('listNetworkRequests', {
|
|
78
|
-
description: `Gives a list of network requests including URL, status code, and duration in ms
|
|
88
|
+
description: `Gives a list of network requests including URL, status code, and duration in ms.`,
|
|
79
89
|
parameters: {
|
|
80
90
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
81
91
|
description: '',
|
|
@@ -106,6 +116,12 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
106
116
|
});
|
|
107
117
|
}
|
|
108
118
|
|
|
119
|
+
if (requests.length === 0) {
|
|
120
|
+
return {
|
|
121
|
+
error: 'No requests recorded by DevTools',
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
109
125
|
return {
|
|
110
126
|
result: requests,
|
|
111
127
|
};
|
|
@@ -113,7 +129,8 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
113
129
|
});
|
|
114
130
|
|
|
115
131
|
this.declareFunction<{url: string}>('selectNetworkRequest', {
|
|
116
|
-
description:
|
|
132
|
+
description:
|
|
133
|
+
`Selects a specific network request to further provide information about. Use this when asked about network requests issues.`,
|
|
117
134
|
parameters: {
|
|
118
135
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
119
136
|
description: '',
|
|
@@ -181,7 +198,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
181
198
|
});
|
|
182
199
|
|
|
183
200
|
this.declareFunction<{name: string}>('selectSourceFile', {
|
|
184
|
-
description: `
|
|
201
|
+
description: `Selects a source file. Use this when asked about files on the page.`,
|
|
185
202
|
parameters: {
|
|
186
203
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
187
204
|
description: '',
|
|
@@ -190,14 +207,14 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
190
207
|
properties: {
|
|
191
208
|
name: {
|
|
192
209
|
type: Host.AidaClient.ParametersTypes.STRING,
|
|
193
|
-
description: 'The name of the file',
|
|
210
|
+
description: 'The name of the file you want to select.',
|
|
194
211
|
nullable: false,
|
|
195
212
|
},
|
|
196
213
|
},
|
|
197
214
|
},
|
|
198
215
|
displayInfoFromArgs: args => {
|
|
199
216
|
return {
|
|
200
|
-
title: lockedString('Getting source file'),
|
|
217
|
+
title: lockedString('Getting source file…'),
|
|
201
218
|
action: `selectSourceFile(${args.name})`,
|
|
202
219
|
};
|
|
203
220
|
},
|
|
@@ -213,6 +230,67 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
213
230
|
return {error: 'Unable to find file.'};
|
|
214
231
|
},
|
|
215
232
|
});
|
|
233
|
+
|
|
234
|
+
this.declareFunction('performanceRecordAndReload', {
|
|
235
|
+
description: 'Records a new performance trace, to help debug performance issue.',
|
|
236
|
+
parameters: {
|
|
237
|
+
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
238
|
+
description: '',
|
|
239
|
+
nullable: true,
|
|
240
|
+
required: [],
|
|
241
|
+
properties: {},
|
|
242
|
+
},
|
|
243
|
+
displayInfoFromArgs: () => {
|
|
244
|
+
return {
|
|
245
|
+
title: 'Recording a performance trace…',
|
|
246
|
+
action: 'performanceRecordAndReload()',
|
|
247
|
+
};
|
|
248
|
+
},
|
|
249
|
+
handler: async () => {
|
|
250
|
+
if (!this.#performanceRecordAndReload) {
|
|
251
|
+
return {
|
|
252
|
+
error: 'Performance recording is not available.',
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
const result = await this.#performanceRecordAndReload();
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
context: AgentFocus.fromParsedTrace(result),
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
this.declareFunction<Record<string, never>>('inspectDom', {
|
|
264
|
+
description:
|
|
265
|
+
`Prompts user to select a DOM element from the page. Use this when you don't know which element is selected.`,
|
|
266
|
+
parameters: {
|
|
267
|
+
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
268
|
+
description: '',
|
|
269
|
+
nullable: true,
|
|
270
|
+
required: [],
|
|
271
|
+
properties: {},
|
|
272
|
+
},
|
|
273
|
+
displayInfoFromArgs: () => {
|
|
274
|
+
return {
|
|
275
|
+
title: lockedString('Please select an element on the page…'),
|
|
276
|
+
action: 'selectElement()',
|
|
277
|
+
};
|
|
278
|
+
},
|
|
279
|
+
handler: async () => {
|
|
280
|
+
if (!this.#onInspectElement) {
|
|
281
|
+
return {error: 'The inspect element action is not available.'};
|
|
282
|
+
}
|
|
283
|
+
const node = await this.#onInspectElement();
|
|
284
|
+
if (node) {
|
|
285
|
+
return {
|
|
286
|
+
context: node,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
error: 'Unable to select element.',
|
|
291
|
+
};
|
|
292
|
+
},
|
|
293
|
+
});
|
|
216
294
|
}
|
|
217
295
|
|
|
218
296
|
#getUISourceCodes = (): Iterable<Workspace.UISourceCode.UISourceCode> => {
|
|
@@ -80,10 +80,6 @@ const UIStringsNotTranslate = {
|
|
|
80
80
|
* @description Title text for request timing details.
|
|
81
81
|
*/
|
|
82
82
|
timing: 'Timing',
|
|
83
|
-
/**
|
|
84
|
-
* @description Prefix text for response status.
|
|
85
|
-
*/
|
|
86
|
-
responseStatus: 'Response Status',
|
|
87
83
|
/**
|
|
88
84
|
* @description Title text for request initiator chain.
|
|
89
85
|
*/
|
|
@@ -178,8 +174,8 @@ async function createContextDetailsForNetworkAgent(
|
|
|
178
174
|
|
|
179
175
|
const responseContextDetail: ContextDetail = {
|
|
180
176
|
title: lockedString(UIStringsNotTranslate.response),
|
|
181
|
-
text:
|
|
182
|
-
`\n\n${formatter.
|
|
177
|
+
text: formatter.formatResponseHeaders() + responseBodyString +
|
|
178
|
+
`\n\n${formatter.formatStatus()}${formatter.formatFailureReasons()}`,
|
|
183
179
|
};
|
|
184
180
|
const timingContextDetail: ContextDetail = {
|
|
185
181
|
title: lockedString(UIStringsNotTranslate.timing),
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import type * as SDK from '../../../core/sdk/sdk.js';
|
|
6
|
+
import type * as Protocol from '../../../generated/protocol.js';
|
|
6
7
|
import * as Annotations from '../../annotations/annotations.js';
|
|
7
8
|
import * as Logs from '../../logs/logs.js';
|
|
8
9
|
import * as NetworkTimeCalculator from '../../network_time_calculator/network_time_calculator.js';
|
|
@@ -75,6 +76,51 @@ export class NetworkRequestFormatter {
|
|
|
75
76
|
return '<redacted cross-origin initiator URL>';
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
static formatStatus(status: {
|
|
80
|
+
statusCode: number,
|
|
81
|
+
statusText: string,
|
|
82
|
+
failed: boolean,
|
|
83
|
+
canceled: boolean,
|
|
84
|
+
preserved: boolean,
|
|
85
|
+
finished: boolean,
|
|
86
|
+
}): string {
|
|
87
|
+
let responseStatus = '';
|
|
88
|
+
if (status.statusCode) {
|
|
89
|
+
responseStatus = `Response status: ${status.statusCode} ${status.statusText}\n`;
|
|
90
|
+
}
|
|
91
|
+
const flags = [];
|
|
92
|
+
flags.push(status.finished ? 'finished' : 'pending');
|
|
93
|
+
if (status.failed) {
|
|
94
|
+
flags.push('failed');
|
|
95
|
+
}
|
|
96
|
+
if (status.canceled) {
|
|
97
|
+
flags.push('canceled');
|
|
98
|
+
}
|
|
99
|
+
if (status.preserved) {
|
|
100
|
+
flags.push('preserved');
|
|
101
|
+
}
|
|
102
|
+
const requestStatus = flags.length > 0 ? `Network request status: ${flags.join(', ')}\n` : '';
|
|
103
|
+
return `${responseStatus}${requestStatus}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static formatFailureReasons(reasons: {
|
|
107
|
+
blockedReason?: Protocol.Network.BlockedReason,
|
|
108
|
+
corsErrorStatus?: Protocol.Network.CorsErrorStatus,
|
|
109
|
+
localizedFailDescription?: string|null,
|
|
110
|
+
}): string {
|
|
111
|
+
const lines = [];
|
|
112
|
+
if (reasons.blockedReason) {
|
|
113
|
+
lines.push(`Blocked reason: ${reasons.blockedReason}`);
|
|
114
|
+
}
|
|
115
|
+
if (reasons.corsErrorStatus) {
|
|
116
|
+
lines.push(`CORS error: ${reasons.corsErrorStatus.corsError} ${reasons.corsErrorStatus.failedParameter}`);
|
|
117
|
+
}
|
|
118
|
+
if (reasons.localizedFailDescription) {
|
|
119
|
+
lines.push(`Fail description: ${reasons.localizedFailDescription}`);
|
|
120
|
+
}
|
|
121
|
+
return lines.length > 0 ? `${lines.join('\n')}\n` : '';
|
|
122
|
+
}
|
|
123
|
+
|
|
78
124
|
constructor(
|
|
79
125
|
request: SDK.NetworkRequest.NetworkRequest, calculator: NetworkTimeCalculator.NetworkTransferTimeCalculator) {
|
|
80
126
|
this.#request = request;
|
|
@@ -111,13 +157,31 @@ ${this.formatRequestHeaders()}
|
|
|
111
157
|
|
|
112
158
|
${this.formatResponseHeaders()}${responseBody}
|
|
113
159
|
|
|
114
|
-
|
|
115
|
-
|
|
160
|
+
${this.formatStatus()}${this.formatFailureReasons()}
|
|
116
161
|
Request timing:\n${this.formatNetworkRequestTiming()}
|
|
117
162
|
|
|
118
163
|
Request initiator chain:\n${this.formatRequestInitiatorChain()}`;
|
|
119
164
|
}
|
|
120
165
|
|
|
166
|
+
formatStatus(): string {
|
|
167
|
+
return NetworkRequestFormatter.formatStatus({
|
|
168
|
+
statusCode: this.#request.statusCode,
|
|
169
|
+
statusText: this.#request.statusText,
|
|
170
|
+
failed: this.#request.failed,
|
|
171
|
+
canceled: this.#request.canceled,
|
|
172
|
+
preserved: this.#request.preserved,
|
|
173
|
+
finished: this.#request.finished,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
formatFailureReasons(): string {
|
|
178
|
+
return NetworkRequestFormatter.formatFailureReasons({
|
|
179
|
+
blockedReason: this.#request.blockedReason(),
|
|
180
|
+
corsErrorStatus: this.#request.corsErrorStatus(),
|
|
181
|
+
localizedFailDescription: this.#request.localizedFailDescription,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
121
185
|
/**
|
|
122
186
|
* Note: nothing here should include information from origins other than
|
|
123
187
|
* the request's origin.
|
|
@@ -137,6 +137,32 @@ export class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper<Event
|
|
|
137
137
|
null as ComputedStyle | null;
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
+
|
|
141
|
+
private async fetchMatchedCascade(): Promise<SDK.CSSMatchedStyles.CSSMatchedStyles|null> {
|
|
142
|
+
const node = this.node;
|
|
143
|
+
if (!node || !this.cssModel()) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const cssModel = this.cssModel();
|
|
148
|
+
if (!cssModel) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const matchedStyles = await cssModel.cachedMatchedCascadeForNode(node);
|
|
153
|
+
if (!matchedStyles) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
return matchedStyles.node() === this.node ? matchedStyles : null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async fetchAllComputedStyleInfo(): Promise<{
|
|
160
|
+
computedStyle: ComputedStyle | null,
|
|
161
|
+
matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null,
|
|
162
|
+
}> {
|
|
163
|
+
const [computedStyle, matchedStyles] = await Promise.all([this.fetchComputedStyle(), this.fetchMatchedCascade()]);
|
|
164
|
+
return {computedStyle, matchedStyles};
|
|
165
|
+
}
|
|
140
166
|
}
|
|
141
167
|
|
|
142
168
|
export const enum Events {
|
|
@@ -9,8 +9,6 @@ let instance: Prototypes|null = null;
|
|
|
9
9
|
|
|
10
10
|
export interface GreenDevSettings {
|
|
11
11
|
inDevToolsFloaty: Common.Settings.Setting<boolean>;
|
|
12
|
-
inlineWidgets: Common.Settings.Setting<boolean>;
|
|
13
|
-
artifactViewer: Common.Settings.Setting<boolean>;
|
|
14
12
|
aiAnnotations: Common.Settings.Setting<boolean>;
|
|
15
13
|
copyToGemini: Common.Settings.Setting<boolean>;
|
|
16
14
|
}
|
|
@@ -41,21 +39,14 @@ export class Prototypes {
|
|
|
41
39
|
const inDevToolsFloaty =
|
|
42
40
|
settings.createSetting('greendev-in-devtools-floaty-enabled', false, Common.Settings.SettingStorageType.LOCAL);
|
|
43
41
|
|
|
44
|
-
const inlineWidgets =
|
|
45
|
-
settings.createSetting('greendev-inline-widgets-enabled', false, Common.Settings.SettingStorageType.LOCAL);
|
|
46
|
-
|
|
47
42
|
const aiAnnotations = settings.createSetting(
|
|
48
43
|
'greendev-ai-annotations-enabled',
|
|
49
44
|
false,
|
|
50
45
|
Common.Settings.SettingStorageType.LOCAL,
|
|
51
46
|
);
|
|
52
|
-
|
|
53
|
-
const artifactViewer =
|
|
54
|
-
settings.createSetting('greendev-artifact-viewer-enabled', false, Common.Settings.SettingStorageType.LOCAL);
|
|
55
|
-
|
|
56
47
|
const copyToGemini =
|
|
57
48
|
settings.createSetting('greendev-copy-to-gemini-enabled', false, Common.Settings.SettingStorageType.LOCAL);
|
|
58
49
|
|
|
59
|
-
return {inDevToolsFloaty,
|
|
50
|
+
return {inDevToolsFloaty, aiAnnotations, copyToGemini};
|
|
60
51
|
}
|
|
61
52
|
}
|
|
@@ -0,0 +1,75 @@
|
|
|
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 i18n from '../../core/i18n/i18n.js';
|
|
6
|
+
import type * as SDK from '../../core/sdk/sdk.js';
|
|
7
|
+
import * as Protocol from '../../generated/protocol.js';
|
|
8
|
+
|
|
9
|
+
import {Issue, IssueCategory, IssueKind} from './Issue.js';
|
|
10
|
+
import {
|
|
11
|
+
type LazyMarkdownIssueDescription,
|
|
12
|
+
type MarkdownIssueDescription,
|
|
13
|
+
resolveLazyDescription,
|
|
14
|
+
} from './MarkdownIssueDescription.js';
|
|
15
|
+
|
|
16
|
+
const UIStrings = {
|
|
17
|
+
/**
|
|
18
|
+
*@description Title for Connection-Allowlist specification url
|
|
19
|
+
*/
|
|
20
|
+
connectionAllowlistHeader: 'Connection-Allowlist specification',
|
|
21
|
+
} as const;
|
|
22
|
+
const str_ = i18n.i18n.registerUIStrings('models/issues_manager/ConnectionAllowlistIssue.ts', UIStrings);
|
|
23
|
+
const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
|
|
24
|
+
|
|
25
|
+
export class ConnectionAllowlistIssue extends Issue<Protocol.Audits.ConnectionAllowlistIssueDetails> {
|
|
26
|
+
constructor(
|
|
27
|
+
issueDetails: Protocol.Audits.ConnectionAllowlistIssueDetails, issuesModel: SDK.IssuesModel.IssuesModel|null) {
|
|
28
|
+
super(
|
|
29
|
+
{
|
|
30
|
+
code: `${Protocol.Audits.InspectorIssueCode.ConnectionAllowlistIssue}::${issueDetails.error}`,
|
|
31
|
+
umaCode: `${Protocol.Audits.InspectorIssueCode.ConnectionAllowlistIssue}::${issueDetails.error}`,
|
|
32
|
+
},
|
|
33
|
+
issueDetails, issuesModel);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
override primaryKey(): string {
|
|
37
|
+
return JSON.stringify(this.details());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
override getDescription(): MarkdownIssueDescription|null {
|
|
41
|
+
const description: LazyMarkdownIssueDescription = {
|
|
42
|
+
file: `connectionAllowlist${this.details().error}.md`,
|
|
43
|
+
links: [
|
|
44
|
+
{
|
|
45
|
+
link: 'https://wicg.github.io/private-network-access/#connection-allowlist',
|
|
46
|
+
linkTitle: i18nLazyString(UIStrings.connectionAllowlistHeader),
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
return resolveLazyDescription(description);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
override getCategory(): IssueCategory {
|
|
54
|
+
return IssueCategory.OTHER;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
override getKind(): IssueKind {
|
|
58
|
+
return IssueKind.PAGE_ERROR;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
override requests(): Iterable<Protocol.Audits.AffectedRequest> {
|
|
62
|
+
return this.details().request ? [this.details().request] : [];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static fromInspectorIssue(
|
|
66
|
+
issuesModel: SDK.IssuesModel.IssuesModel|null,
|
|
67
|
+
inspectorIssue: Protocol.Audits.InspectorIssue): ConnectionAllowlistIssue[] {
|
|
68
|
+
const details = inspectorIssue.details.connectionAllowlistIssueDetails;
|
|
69
|
+
if (!details) {
|
|
70
|
+
console.warn('Connection-Allowlist issue without details received.');
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
return [new ConnectionAllowlistIssue(details, issuesModel)];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -8,7 +8,6 @@ import * as i18n from '../../core/i18n/i18n.js';
|
|
|
8
8
|
import type * as Platform from '../../core/platform/platform.js';
|
|
9
9
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
10
10
|
import * as Protocol from '../../generated/protocol.js';
|
|
11
|
-
import * as ThirdPartyWeb from '../../third_party/third-party-web/third-party-web.js';
|
|
12
11
|
|
|
13
12
|
import {Issue, IssueCategory, IssueKind} from './Issue.js';
|
|
14
13
|
import {
|
|
@@ -55,15 +54,6 @@ export const enum CookieStatus {
|
|
|
55
54
|
ALLOWED_BY_HEURISTICS = 3,
|
|
56
55
|
}
|
|
57
56
|
|
|
58
|
-
export interface CookieReportInfo {
|
|
59
|
-
name: string;
|
|
60
|
-
domain: string;
|
|
61
|
-
type?: string;
|
|
62
|
-
platform?: string;
|
|
63
|
-
status: CookieStatus;
|
|
64
|
-
insight?: Protocol.Audits.CookieIssueInsight;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
57
|
export class CookieIssue extends Issue<Protocol.Audits.CookieIssueDetails> {
|
|
68
58
|
cookieId(): string {
|
|
69
59
|
const details = this.details();
|
|
@@ -246,24 +236,6 @@ export class CookieIssue extends Issue<Protocol.Audits.CookieIssueDetails> {
|
|
|
246
236
|
return IssueKind.BREAKING_CHANGE;
|
|
247
237
|
}
|
|
248
238
|
|
|
249
|
-
makeCookieReportEntry(): CookieReportInfo|undefined {
|
|
250
|
-
const status = CookieIssue.getCookieStatus(this.details());
|
|
251
|
-
const details = this.details();
|
|
252
|
-
if (details.cookie && details.cookieUrl && status !== undefined) {
|
|
253
|
-
const entity = ThirdPartyWeb.ThirdPartyWeb.getEntity(details.cookieUrl);
|
|
254
|
-
return {
|
|
255
|
-
name: details.cookie.name,
|
|
256
|
-
domain: details.cookie.domain,
|
|
257
|
-
type: entity?.category,
|
|
258
|
-
platform: entity?.name,
|
|
259
|
-
status,
|
|
260
|
-
insight: this.details().insight,
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
239
|
static getCookieStatus(cookieIssueDetails: Protocol.Audits.CookieIssueDetails): CookieStatus|undefined {
|
|
268
240
|
if (cookieIssueDetails.cookieExclusionReasons.includes(
|
|
269
241
|
Protocol.Audits.CookieExclusionReason.ExcludeThirdPartyPhaseout)) {
|
|
@@ -109,36 +109,6 @@ const issueDescriptions = new Map<Protocol.Audits.FederatedAuthRequestIssueReaso
|
|
|
109
109
|
}],
|
|
110
110
|
},
|
|
111
111
|
],
|
|
112
|
-
[
|
|
113
|
-
Protocol.Audits.FederatedAuthRequestIssueReason.ClientMetadataHttpNotFound,
|
|
114
|
-
{
|
|
115
|
-
file: 'federatedAuthRequestClientMetadataHttpNotFound.md',
|
|
116
|
-
links: [{
|
|
117
|
-
link: 'https://fedidcg.github.io/FedCM/',
|
|
118
|
-
linkTitle: i18nLazyString(UIStrings.fedCm),
|
|
119
|
-
}],
|
|
120
|
-
},
|
|
121
|
-
],
|
|
122
|
-
[
|
|
123
|
-
Protocol.Audits.FederatedAuthRequestIssueReason.ClientMetadataNoResponse,
|
|
124
|
-
{
|
|
125
|
-
file: 'federatedAuthRequestClientMetadataNoResponse.md',
|
|
126
|
-
links: [{
|
|
127
|
-
link: 'https://fedidcg.github.io/FedCM/',
|
|
128
|
-
linkTitle: i18nLazyString(UIStrings.fedCm),
|
|
129
|
-
}],
|
|
130
|
-
},
|
|
131
|
-
],
|
|
132
|
-
[
|
|
133
|
-
Protocol.Audits.FederatedAuthRequestIssueReason.ClientMetadataInvalidResponse,
|
|
134
|
-
{
|
|
135
|
-
file: 'federatedAuthRequestClientMetadataInvalidResponse.md',
|
|
136
|
-
links: [{
|
|
137
|
-
link: 'https://fedidcg.github.io/FedCM/',
|
|
138
|
-
linkTitle: i18nLazyString(UIStrings.fedCm),
|
|
139
|
-
}],
|
|
140
|
-
},
|
|
141
|
-
],
|
|
142
112
|
[
|
|
143
113
|
Protocol.Audits.FederatedAuthRequestIssueReason.ErrorFetchingSignin,
|
|
144
114
|
{
|
|
@@ -9,6 +9,7 @@ import * as Protocol from '../../generated/protocol.js';
|
|
|
9
9
|
import {AttributionReportingIssue} from './AttributionReportingIssue.js';
|
|
10
10
|
import {BounceTrackingIssue} from './BounceTrackingIssue.js';
|
|
11
11
|
import {ClientHintIssue} from './ClientHintIssue.js';
|
|
12
|
+
import {ConnectionAllowlistIssue} from './ConnectionAllowlistIssue.js';
|
|
12
13
|
import {ContentSecurityPolicyIssue} from './ContentSecurityPolicyIssue.js';
|
|
13
14
|
import {CookieDeprecationMetadataIssue} from './CookieDeprecationMetadataIssue.js';
|
|
14
15
|
import {CookieIssue} from './CookieIssue.js';
|
|
@@ -144,6 +145,10 @@ const issueCodeHandlers = new Map<
|
|
|
144
145
|
Protocol.Audits.InspectorIssueCode.UnencodedDigestIssue,
|
|
145
146
|
UnencodedDigestIssue.fromInspectorIssue,
|
|
146
147
|
],
|
|
148
|
+
[
|
|
149
|
+
Protocol.Audits.InspectorIssueCode.ConnectionAllowlistIssue,
|
|
150
|
+
ConnectionAllowlistIssue.fromInspectorIssue,
|
|
151
|
+
],
|
|
147
152
|
[
|
|
148
153
|
Protocol.Audits.InspectorIssueCode.PermissionElementIssue,
|
|
149
154
|
PermissionElementIssue.fromInspectorIssue,
|
package/front_end/models/issues_manager/descriptions/connectionAllowlistInvalidAllowlistItemType.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# An item in the `Connection-Allowlist` header is invalid.
|
|
2
|
+
|
|
3
|
+
Each item in the `Connection-Allowlist`'s header's [Inner List](sfInnerList)
|
|
4
|
+
must be a [String](sfString) representing a [URL Pattern](urlPatternSpec), or
|
|
5
|
+
the [Token](sfToken) `response-origin`.
|
|
6
|
+
|
|
7
|
+
For example, the following header allows connections to (only)
|
|
8
|
+
`https://example.com/` and the origin from which the response was delivered:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
Connection-Allowlist: ("https://example.com" response-origin)
|
|
12
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# The `Connection-Allowlist` header is not formatted as a Structured Field List.
|
|
2
|
+
|
|
3
|
+
Responses' `Connection-Allowlist` header should be formatted as a [List](sfList)
|
|
4
|
+
containing a single [Inner List](sfInnerList) that declares the allowed set of
|
|
5
|
+
[URL Patterns](urlPatternSpec) for a given context.
|
|
6
|
+
|
|
7
|
+
For example, the following header allows connections to (only)
|
|
8
|
+
`https://example.com/`:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
Connection-Allowlist: ("https://example.com")
|
|
12
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# An item in the `Connection-Allowlist` header is not a valid URL pattern.
|
|
2
|
+
|
|
3
|
+
Each item in the `Connection-Allowlist` header must be a valid
|
|
4
|
+
[URL Pattern](urlPatternSpec) that can be used to match against the request's
|
|
5
|
+
origin.
|
|
6
|
+
|
|
7
|
+
Note that our current implementation does not allow regular expressions to be
|
|
8
|
+
used as part of the pattern.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# An item in the `Connection-Allowlist` header is not an Inner List.
|
|
2
|
+
|
|
3
|
+
Responses' `Connection-Allowlist` header should be formatted as a [List](sfList)
|
|
4
|
+
containing a single [Inner List](sfInnerList) that declares the allowed set of
|
|
5
|
+
[URL Patterns](urlPatternSpec) for a given context.
|
|
6
|
+
|
|
7
|
+
For example, the following header allows connections to (only)
|
|
8
|
+
`https://example.com/`:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
Connection-Allowlist: ("https://example.com")
|
|
12
|
+
```
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# `Connection-Allowlist` has multiple items.
|
|
2
|
+
|
|
3
|
+
Responses' `Connection-Allowlist` header should be formatted as a [List](sfList)
|
|
4
|
+
containing a single [Inner List](sfInnerList) that declares the allowed set of
|
|
5
|
+
[URL Patterns](urlPatternSpec) for a given context. This response was a
|
|
6
|
+
[List](sfList) containing more than one item: all but the first have been
|
|
7
|
+
ignored.
|
package/front_end/models/issues_manager/descriptions/connectionAllowlistReportingEndpointNotToken.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# The `report-to` parameter in the `Connection-Allowlist` header is not a token.
|
|
2
|
+
|
|
3
|
+
If provided, the `report-to` parameter must be a [Token](sfToken)
|
|
4
|
+
naming a reporting endpoint.
|
|
5
|
+
|
|
6
|
+
For example:
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
Connection-Allowlist: ("https://example.com");report-to=endpoint
|
|
10
|
+
```
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import * as AttributionReportingIssue from './AttributionReportingIssue.js';
|
|
6
6
|
import * as CheckFormsIssuesTrigger from './CheckFormsIssuesTrigger.js';
|
|
7
7
|
import * as ClientHintIssue from './ClientHintIssue.js';
|
|
8
|
+
import * as ConnectionAllowlistIssue from './ConnectionAllowlistIssue.js';
|
|
8
9
|
import * as ContentSecurityPolicyIssue from './ContentSecurityPolicyIssue.js';
|
|
9
10
|
import * as ContrastCheckTrigger from './ContrastCheckTrigger.js';
|
|
10
11
|
import * as CookieDeprecationMetadataIssue from './CookieDeprecationMetadataIssue.js';
|
|
@@ -39,6 +40,7 @@ export {
|
|
|
39
40
|
AttributionReportingIssue,
|
|
40
41
|
CheckFormsIssuesTrigger,
|
|
41
42
|
ClientHintIssue,
|
|
43
|
+
ConnectionAllowlistIssue,
|
|
42
44
|
ContentSecurityPolicyIssue,
|
|
43
45
|
ContrastCheckTrigger,
|
|
44
46
|
CookieDeprecationMetadataIssue,
|