chrome-devtools-frontend 1.0.1581708 → 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/front_end/core/sdk/RemoteObject.ts +7 -1
- package/front_end/entrypoint_template.html +5 -1
- package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +9 -24
- package/front_end/entrypoints/greendev_floaty/floaty.css +1 -1
- package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +1 -1
- 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/agents/ContextSelectionAgent.snapshot.txt +6 -6
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +17 -9
- 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/greendev/Prototypes.ts +1 -10
- package/front_end/models/issues_manager/ConnectionAllowlistIssue.ts +75 -0
- 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 +7 -1
- package/front_end/panels/ai_assistance/components/ChatInput.ts +7 -3
- 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/console/ConsoleSidebar.ts +3 -11
- 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 +19 -8
- package/front_end/panels/settings/AISettingsTab.ts +1 -5
- package/front_end/panels/settings/SettingsScreen.ts +0 -51
- package/front_end/panels/timeline/AnimationsTrackAppender.ts +4 -1
- package/front_end/panels/timeline/InteractionsTrackAppender.ts +1 -1
- package/front_end/panels/timeline/TimelineUIUtils.ts +13 -16
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +5 -1
- package/front_end/ui/legacy/Toolbar.ts +4 -4
- package/front_end/ui/legacy/Treeoutline.ts +4 -4
- package/front_end/ui/legacy/UIUtils.ts +9 -3
- package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +6 -11
- package/front_end/ui/legacy/components/utils/Linkifier.ts +4 -7
- package/package.json +1 -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
|
@@ -66,6 +66,11 @@ export abstract class RemoteObject {
|
|
|
66
66
|
return matches ? parseInt(matches[1], 10) : 0;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
static isEmptyArray(object: RemoteObject|Protocol.Runtime.RemoteObject|Protocol.Runtime.ObjectPreview): boolean {
|
|
70
|
+
const matches = object.description?.match(descriptionLengthParenRegex);
|
|
71
|
+
return Boolean(matches?.[1] === '0');
|
|
72
|
+
}
|
|
73
|
+
|
|
69
74
|
static unserializableDescription(object: unknown): string|null {
|
|
70
75
|
if (typeof object === 'number') {
|
|
71
76
|
const description = String(object);
|
|
@@ -582,7 +587,8 @@ export class RemoteObjectImpl extends RemoteObject {
|
|
|
582
587
|
|
|
583
588
|
override isLinearMemoryInspectable(): boolean {
|
|
584
589
|
return this.type === 'object' && this.subtype !== undefined &&
|
|
585
|
-
['webassemblymemory', 'typedarray', 'dataview', 'arraybuffer'].includes(this.subtype)
|
|
590
|
+
['webassemblymemory', 'typedarray', 'dataview', 'arraybuffer'].includes(this.subtype) &&
|
|
591
|
+
!RemoteObject.isEmptyArray(this);
|
|
586
592
|
}
|
|
587
593
|
}
|
|
588
594
|
|
|
@@ -14,7 +14,11 @@
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
</style>
|
|
17
|
-
<meta
|
|
17
|
+
<meta
|
|
18
|
+
http-equiv="Content-Security-Policy"
|
|
19
|
+
content="default-src 'self' devtools: data:; style-src 'self' 'unsafe-inline' devtools:; object-src 'none'; script-src
|
|
20
|
+
'self' https://chrome-devtools-frontend.appspot.com; img-src 'self' data:; frame-src * data:; connect-src data:
|
|
21
|
+
https://chromeuxreport.googleapis.com 'self' devtools:;">
|
|
18
22
|
<meta name="referrer" content="no-referrer">
|
|
19
23
|
<script type="module" src="./entrypoints/%ENTRYPOINT_NAME%/%ENTRYPOINT_NAME%.js"></script>
|
|
20
24
|
<link href="./application_tokens.css" rel="stylesheet">
|
|
@@ -254,6 +254,10 @@ class GreenDevFloaty {
|
|
|
254
254
|
return messages;
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
#formatError(errorMessage: string): string {
|
|
258
|
+
return `Error: '${errorMessage}' - Protip: to use AI features you need to be signed in.`;
|
|
259
|
+
}
|
|
260
|
+
|
|
257
261
|
runConversation = async(): Promise<void> => {
|
|
258
262
|
if (!this.#textField || !this.#node) {
|
|
259
263
|
return;
|
|
@@ -276,7 +280,7 @@ class GreenDevFloaty {
|
|
|
276
280
|
nodeDescription: document.querySelector('.green-dev-floaty-dialog-node-description')?.textContent,
|
|
277
281
|
});
|
|
278
282
|
|
|
279
|
-
const
|
|
283
|
+
const aiContent = this.#addMessageInternal('Thinking...', false);
|
|
280
284
|
this.#syncChannel.postMessage({
|
|
281
285
|
type: 'new-message',
|
|
282
286
|
text: 'Thinking...',
|
|
@@ -297,9 +301,9 @@ class GreenDevFloaty {
|
|
|
297
301
|
{type: 'update-last-message', text: result.text, sessionId: this.#backendNodeId});
|
|
298
302
|
break;
|
|
299
303
|
case ResponseType.ERROR:
|
|
300
|
-
aiContent.textContent =
|
|
304
|
+
aiContent.textContent = this.#formatError(result.error);
|
|
301
305
|
this.#syncChannel.postMessage(
|
|
302
|
-
{type: 'update-last-message', text:
|
|
306
|
+
{type: 'update-last-message', text: this.#formatError(result.error), sessionId: this.#backendNodeId});
|
|
303
307
|
break;
|
|
304
308
|
case ResponseType.SIDE_EFFECT:
|
|
305
309
|
result.confirm(true);
|
|
@@ -316,7 +320,7 @@ class GreenDevFloaty {
|
|
|
316
320
|
}
|
|
317
321
|
};
|
|
318
322
|
|
|
319
|
-
#addMessageInternal(text: string, isUser: boolean):
|
|
323
|
+
#addMessageInternal(text: string, isUser: boolean): HTMLDivElement {
|
|
320
324
|
const messageElement = document.createElement('div');
|
|
321
325
|
messageElement.className = `message ${isUser ? 'user-message' : 'ai-message'}`;
|
|
322
326
|
|
|
@@ -325,30 +329,11 @@ class GreenDevFloaty {
|
|
|
325
329
|
content.textContent = text;
|
|
326
330
|
messageElement.appendChild(content);
|
|
327
331
|
|
|
328
|
-
let details: HTMLDivElement|undefined;
|
|
329
|
-
if (!isUser) {
|
|
330
|
-
details = document.createElement('div');
|
|
331
|
-
details.className = 'message-details';
|
|
332
|
-
details.style.display = 'none';
|
|
333
|
-
messageElement.appendChild(details);
|
|
334
|
-
|
|
335
|
-
const toggle = document.createElement('div');
|
|
336
|
-
toggle.className = 'message-details-toggle';
|
|
337
|
-
toggle.textContent = 'Show details';
|
|
338
|
-
toggle.onclick = () => {
|
|
339
|
-
if (details) {
|
|
340
|
-
const isHidden = details.style.display === 'none';
|
|
341
|
-
details.style.display = isHidden ? 'block' : 'none';
|
|
342
|
-
toggle.textContent = isHidden ? 'Hide details' : 'Show details';
|
|
343
|
-
}
|
|
344
|
-
};
|
|
345
|
-
messageElement.appendChild(toggle);
|
|
346
|
-
}
|
|
347
332
|
if (this.#chatContainer) {
|
|
348
333
|
this.#chatContainer.appendChild(messageElement);
|
|
349
334
|
this.#chatContainer.scrollTop = this.#chatContainer.scrollHeight;
|
|
350
335
|
}
|
|
351
|
-
return
|
|
336
|
+
return content;
|
|
352
337
|
}
|
|
353
338
|
}
|
|
354
339
|
|
|
@@ -186,7 +186,7 @@ class GreenDevFloaty {
|
|
|
186
186
|
aiContent.textContent = result.text;
|
|
187
187
|
break;
|
|
188
188
|
case ResponseType.ERROR:
|
|
189
|
-
aiContent.textContent = `Error: ${result.error}
|
|
189
|
+
aiContent.textContent = `Error: '${result.error}' - Protip: to use AI features you need to be signed in.`;
|
|
190
190
|
break;
|
|
191
191
|
case ResponseType.THOUGHT:
|
|
192
192
|
if (aiDetails) {
|
|
@@ -84,7 +84,7 @@ inspectorBackend.registerEnum("Audits.UnencodedDigestError", {MalformedDictionar
|
|
|
84
84
|
inspectorBackend.registerEnum("Audits.ConnectionAllowlistError", {InvalidHeader: "InvalidHeader", MoreThanOneList: "MoreThanOneList", ItemNotInnerList: "ItemNotInnerList", InvalidAllowlistItemType: "InvalidAllowlistItemType", ReportingEndpointNotToken: "ReportingEndpointNotToken", InvalidUrlPattern: "InvalidUrlPattern"});
|
|
85
85
|
inspectorBackend.registerEnum("Audits.GenericIssueErrorType", {FormLabelForNameError: "FormLabelForNameError", FormDuplicateIdForInputError: "FormDuplicateIdForInputError", FormInputWithNoLabelError: "FormInputWithNoLabelError", FormAutocompleteAttributeEmptyError: "FormAutocompleteAttributeEmptyError", FormEmptyIdAndNameAttributesForInputError: "FormEmptyIdAndNameAttributesForInputError", FormAriaLabelledByToNonExistingIdError: "FormAriaLabelledByToNonExistingIdError", FormInputAssignedAutocompleteValueToIdOrNameAttributeError: "FormInputAssignedAutocompleteValueToIdOrNameAttributeError", FormLabelHasNeitherForNorNestedInputError: "FormLabelHasNeitherForNorNestedInputError", FormLabelForMatchesNonExistingIdError: "FormLabelForMatchesNonExistingIdError", FormInputHasWrongButWellIntendedAutocompleteValueError: "FormInputHasWrongButWellIntendedAutocompleteValueError", ResponseWasBlockedByORB: "ResponseWasBlockedByORB", NavigationEntryMarkedSkippable: "NavigationEntryMarkedSkippable", AutofillAndManualTextPolicyControlledFeaturesInfo: "AutofillAndManualTextPolicyControlledFeaturesInfo", AutofillPolicyControlledFeatureInfo: "AutofillPolicyControlledFeatureInfo", ManualTextPolicyControlledFeatureInfo: "ManualTextPolicyControlledFeatureInfo"});
|
|
86
86
|
inspectorBackend.registerEnum("Audits.ClientHintIssueReason", {MetaTagAllowListInvalidOrigin: "MetaTagAllowListInvalidOrigin", MetaTagModifiedHTML: "MetaTagModifiedHTML"});
|
|
87
|
-
inspectorBackend.registerEnum("Audits.FederatedAuthRequestIssueReason", {ShouldEmbargo: "ShouldEmbargo", TooManyRequests: "TooManyRequests", WellKnownHttpNotFound: "WellKnownHttpNotFound", WellKnownNoResponse: "WellKnownNoResponse", WellKnownInvalidResponse: "WellKnownInvalidResponse", WellKnownListEmpty: "WellKnownListEmpty", WellKnownInvalidContentType: "WellKnownInvalidContentType", ConfigNotInWellKnown: "ConfigNotInWellKnown", WellKnownTooBig: "WellKnownTooBig", ConfigHttpNotFound: "ConfigHttpNotFound", ConfigNoResponse: "ConfigNoResponse", ConfigInvalidResponse: "ConfigInvalidResponse", ConfigInvalidContentType: "ConfigInvalidContentType",
|
|
87
|
+
inspectorBackend.registerEnum("Audits.FederatedAuthRequestIssueReason", {ShouldEmbargo: "ShouldEmbargo", TooManyRequests: "TooManyRequests", WellKnownHttpNotFound: "WellKnownHttpNotFound", WellKnownNoResponse: "WellKnownNoResponse", WellKnownInvalidResponse: "WellKnownInvalidResponse", WellKnownListEmpty: "WellKnownListEmpty", WellKnownInvalidContentType: "WellKnownInvalidContentType", ConfigNotInWellKnown: "ConfigNotInWellKnown", WellKnownTooBig: "WellKnownTooBig", ConfigHttpNotFound: "ConfigHttpNotFound", ConfigNoResponse: "ConfigNoResponse", ConfigInvalidResponse: "ConfigInvalidResponse", ConfigInvalidContentType: "ConfigInvalidContentType", IdpNotPotentiallyTrustworthy: "IdpNotPotentiallyTrustworthy", DisabledInSettings: "DisabledInSettings", DisabledInFlags: "DisabledInFlags", ErrorFetchingSignin: "ErrorFetchingSignin", InvalidSigninResponse: "InvalidSigninResponse", AccountsHttpNotFound: "AccountsHttpNotFound", AccountsNoResponse: "AccountsNoResponse", AccountsInvalidResponse: "AccountsInvalidResponse", AccountsListEmpty: "AccountsListEmpty", AccountsInvalidContentType: "AccountsInvalidContentType", IdTokenHttpNotFound: "IdTokenHttpNotFound", IdTokenNoResponse: "IdTokenNoResponse", IdTokenInvalidResponse: "IdTokenInvalidResponse", IdTokenIdpErrorResponse: "IdTokenIdpErrorResponse", IdTokenCrossSiteIdpErrorResponse: "IdTokenCrossSiteIdpErrorResponse", IdTokenInvalidRequest: "IdTokenInvalidRequest", IdTokenInvalidContentType: "IdTokenInvalidContentType", ErrorIdToken: "ErrorIdToken", Canceled: "Canceled", RpPageNotVisible: "RpPageNotVisible", SilentMediationFailure: "SilentMediationFailure", NotSignedInWithIdp: "NotSignedInWithIdp", MissingTransientUserActivation: "MissingTransientUserActivation", ReplacedByActiveMode: "ReplacedByActiveMode", RelyingPartyOriginIsOpaque: "RelyingPartyOriginIsOpaque", TypeNotMatching: "TypeNotMatching", UiDismissedNoEmbargo: "UiDismissedNoEmbargo", CorsError: "CorsError", SuppressedBySegmentationPlatform: "SuppressedBySegmentationPlatform"});
|
|
88
88
|
inspectorBackend.registerEnum("Audits.FederatedAuthUserInfoRequestIssueReason", {NotSameOrigin: "NotSameOrigin", NotIframe: "NotIframe", NotPotentiallyTrustworthy: "NotPotentiallyTrustworthy", NoAPIPermission: "NoApiPermission", NotSignedInWithIdp: "NotSignedInWithIdp", NoAccountSharingPermission: "NoAccountSharingPermission", InvalidConfigOrWellKnown: "InvalidConfigOrWellKnown", InvalidAccountsResponse: "InvalidAccountsResponse", NoReturningUserFromFetchedAccounts: "NoReturningUserFromFetchedAccounts"});
|
|
89
89
|
inspectorBackend.registerEnum("Audits.PartitioningBlobURLInfo", {BlockedCrossPartitionFetching: "BlockedCrossPartitionFetching", EnforceNoopenerForNavigation: "EnforceNoopenerForNavigation"});
|
|
90
90
|
inspectorBackend.registerEnum("Audits.ElementAccessibilityIssueReason", {DisallowedSelectChild: "DisallowedSelectChild", DisallowedOptGroupChild: "DisallowedOptGroupChild", NonPhrasingContentOptionChild: "NonPhrasingContentOptionChild", InteractiveContentOptionChild: "InteractiveContentOptionChild", InteractiveContentLegendChild: "InteractiveContentLegendChild", InteractiveContentSummaryDescendant: "InteractiveContentSummaryDescendant"});
|
|
@@ -4552,6 +4552,7 @@ export const generatedProperties = [
|
|
|
4552
4552
|
"uppercase",
|
|
4553
4553
|
"lowercase",
|
|
4554
4554
|
"full-width",
|
|
4555
|
+
"full-size-kana",
|
|
4555
4556
|
"none",
|
|
4556
4557
|
"math-auto"
|
|
4557
4558
|
],
|
|
@@ -7048,6 +7049,7 @@ export const generatedPropertyValues = {
|
|
|
7048
7049
|
"uppercase",
|
|
7049
7050
|
"lowercase",
|
|
7050
7051
|
"full-width",
|
|
7052
|
+
"full-size-kana",
|
|
7051
7053
|
"none",
|
|
7052
7054
|
"math-auto"
|
|
7053
7055
|
]
|
|
@@ -1292,10 +1292,6 @@ export namespace Audits {
|
|
|
1292
1292
|
ConfigNoResponse = 'ConfigNoResponse',
|
|
1293
1293
|
ConfigInvalidResponse = 'ConfigInvalidResponse',
|
|
1294
1294
|
ConfigInvalidContentType = 'ConfigInvalidContentType',
|
|
1295
|
-
ClientMetadataHttpNotFound = 'ClientMetadataHttpNotFound',
|
|
1296
|
-
ClientMetadataNoResponse = 'ClientMetadataNoResponse',
|
|
1297
|
-
ClientMetadataInvalidResponse = 'ClientMetadataInvalidResponse',
|
|
1298
|
-
ClientMetadataInvalidContentType = 'ClientMetadataInvalidContentType',
|
|
1299
1295
|
IdpNotPotentiallyTrustworthy = 'IdpNotPotentiallyTrustworthy',
|
|
1300
1296
|
DisabledInSettings = 'DisabledInSettings',
|
|
1301
1297
|
DisabledInFlags = 'DisabledInFlags',
|
|
@@ -1317,11 +1313,9 @@ export namespace Audits {
|
|
|
1317
1313
|
Canceled = 'Canceled',
|
|
1318
1314
|
RpPageNotVisible = 'RpPageNotVisible',
|
|
1319
1315
|
SilentMediationFailure = 'SilentMediationFailure',
|
|
1320
|
-
ThirdPartyCookiesBlocked = 'ThirdPartyCookiesBlocked',
|
|
1321
1316
|
NotSignedInWithIdp = 'NotSignedInWithIdp',
|
|
1322
1317
|
MissingTransientUserActivation = 'MissingTransientUserActivation',
|
|
1323
1318
|
ReplacedByActiveMode = 'ReplacedByActiveMode',
|
|
1324
|
-
InvalidFieldsSpecified = 'InvalidFieldsSpecified',
|
|
1325
1319
|
RelyingPartyOriginIsOpaque = 'RelyingPartyOriginIsOpaque',
|
|
1326
1320
|
TypeNotMatching = 'TypeNotMatching',
|
|
1327
1321
|
UiDismissedNoEmbargo = 'UiDismissedNoEmbargo',
|
|
@@ -31,7 +31,7 @@ Content:
|
|
|
31
31
|
"function_declarations": [
|
|
32
32
|
{
|
|
33
33
|
"name": "listNetworkRequests",
|
|
34
|
-
"description": "Gives a list of network requests including URL, status code, and duration in ms",
|
|
34
|
+
"description": "Gives a list of network requests including URL, status code, and duration in ms.",
|
|
35
35
|
"parameters": {
|
|
36
36
|
"type": 6,
|
|
37
37
|
"description": "",
|
|
@@ -42,7 +42,7 @@ Content:
|
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
"name": "selectNetworkRequest",
|
|
45
|
-
"description": "
|
|
45
|
+
"description": "Selects a specific network request to further provide information about. Use this when asked about network requests issues.",
|
|
46
46
|
"parameters": {
|
|
47
47
|
"type": 6,
|
|
48
48
|
"description": "",
|
|
@@ -72,7 +72,7 @@ Content:
|
|
|
72
72
|
},
|
|
73
73
|
{
|
|
74
74
|
"name": "selectSourceFile",
|
|
75
|
-
"description": "
|
|
75
|
+
"description": "Selects a source file. Use this when asked about files on the page.",
|
|
76
76
|
"parameters": {
|
|
77
77
|
"type": 6,
|
|
78
78
|
"description": "",
|
|
@@ -83,7 +83,7 @@ Content:
|
|
|
83
83
|
"properties": {
|
|
84
84
|
"name": {
|
|
85
85
|
"type": 1,
|
|
86
|
-
"description": "The name of the file",
|
|
86
|
+
"description": "The name of the file you want to select.",
|
|
87
87
|
"nullable": false
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -91,7 +91,7 @@ Content:
|
|
|
91
91
|
},
|
|
92
92
|
{
|
|
93
93
|
"name": "performanceRecordAndReload",
|
|
94
|
-
"description": "
|
|
94
|
+
"description": "Records a new performance trace, to help debug performance issue.",
|
|
95
95
|
"parameters": {
|
|
96
96
|
"type": 6,
|
|
97
97
|
"description": "",
|
|
@@ -102,7 +102,7 @@ Content:
|
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
104
|
"name": "inspectDom",
|
|
105
|
-
"description": "Prompts user to select a DOM element from the page.",
|
|
105
|
+
"description": "Prompts user to select a DOM element from the page. Use this when you don't know which element is selected.",
|
|
106
106
|
"parameters": {
|
|
107
107
|
"type": 6,
|
|
108
108
|
"description": "",
|
|
@@ -32,7 +32,7 @@ You aim to help developers of all levels, prioritizing teaching web concepts as
|
|
|
32
32
|
|
|
33
33
|
# Considerations
|
|
34
34
|
* Determine what the question the domain of the question is - styling, network, sources, performance or other part of DevTools.
|
|
35
|
-
*
|
|
35
|
+
* Proactively try to gather additional data. If a select specific data can be selected, select one.
|
|
36
36
|
* Avoid making assumptions without sufficient evidence, and always seek further clarification if needed.
|
|
37
37
|
* Always explore multiple possible explanations for the observed behavior before settling on a conclusion.
|
|
38
38
|
* When presenting solutions, clearly distinguish between the primary cause and contributing factors.
|
|
@@ -85,7 +85,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
85
85
|
this.#onInspectElement = opts.onInspectElement;
|
|
86
86
|
|
|
87
87
|
this.declareFunction<Record<string, never>>('listNetworkRequests', {
|
|
88
|
-
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.`,
|
|
89
89
|
parameters: {
|
|
90
90
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
91
91
|
description: '',
|
|
@@ -116,6 +116,12 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
if (requests.length === 0) {
|
|
120
|
+
return {
|
|
121
|
+
error: 'No requests recorded by DevTools',
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
119
125
|
return {
|
|
120
126
|
result: requests,
|
|
121
127
|
};
|
|
@@ -123,7 +129,8 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
123
129
|
});
|
|
124
130
|
|
|
125
131
|
this.declareFunction<{url: string}>('selectNetworkRequest', {
|
|
126
|
-
description:
|
|
132
|
+
description:
|
|
133
|
+
`Selects a specific network request to further provide information about. Use this when asked about network requests issues.`,
|
|
127
134
|
parameters: {
|
|
128
135
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
129
136
|
description: '',
|
|
@@ -191,7 +198,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
191
198
|
});
|
|
192
199
|
|
|
193
200
|
this.declareFunction<{name: string}>('selectSourceFile', {
|
|
194
|
-
description: `
|
|
201
|
+
description: `Selects a source file. Use this when asked about files on the page.`,
|
|
195
202
|
parameters: {
|
|
196
203
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
197
204
|
description: '',
|
|
@@ -200,14 +207,14 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
200
207
|
properties: {
|
|
201
208
|
name: {
|
|
202
209
|
type: Host.AidaClient.ParametersTypes.STRING,
|
|
203
|
-
description: 'The name of the file',
|
|
210
|
+
description: 'The name of the file you want to select.',
|
|
204
211
|
nullable: false,
|
|
205
212
|
},
|
|
206
213
|
},
|
|
207
214
|
},
|
|
208
215
|
displayInfoFromArgs: args => {
|
|
209
216
|
return {
|
|
210
|
-
title: lockedString('Getting source file'),
|
|
217
|
+
title: lockedString('Getting source file…'),
|
|
211
218
|
action: `selectSourceFile(${args.name})`,
|
|
212
219
|
};
|
|
213
220
|
},
|
|
@@ -225,7 +232,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
225
232
|
});
|
|
226
233
|
|
|
227
234
|
this.declareFunction('performanceRecordAndReload', {
|
|
228
|
-
description: '
|
|
235
|
+
description: 'Records a new performance trace, to help debug performance issue.',
|
|
229
236
|
parameters: {
|
|
230
237
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
231
238
|
description: '',
|
|
@@ -254,7 +261,8 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
254
261
|
});
|
|
255
262
|
|
|
256
263
|
this.declareFunction<Record<string, never>>('inspectDom', {
|
|
257
|
-
description:
|
|
264
|
+
description:
|
|
265
|
+
`Prompts user to select a DOM element from the page. Use this when you don't know which element is selected.`,
|
|
258
266
|
parameters: {
|
|
259
267
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
260
268
|
description: '',
|
|
@@ -264,7 +272,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
264
272
|
},
|
|
265
273
|
displayInfoFromArgs: () => {
|
|
266
274
|
return {
|
|
267
|
-
title: lockedString('Please select an element on the page
|
|
275
|
+
title: lockedString('Please select an element on the page…'),
|
|
268
276
|
action: 'selectElement()',
|
|
269
277
|
};
|
|
270
278
|
},
|
|
@@ -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.
|
|
@@ -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
|
+
}
|
|
@@ -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.
|