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
|
@@ -15,6 +15,7 @@ import * as Annotations from '../../models/annotations/annotations.js';
|
|
|
15
15
|
import * as Badges from '../../models/badges/badges.js';
|
|
16
16
|
import * as GreenDev from '../../models/greendev/greendev.js';
|
|
17
17
|
import * as TextUtils from '../../models/text_utils/text_utils.js';
|
|
18
|
+
import type * as Trace from '../../models/trace/trace.js';
|
|
18
19
|
import * as Workspace from '../../models/workspace/workspace.js';
|
|
19
20
|
import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
20
21
|
import * as Snackbars from '../../ui/components/snackbars/snackbars.js';
|
|
@@ -503,6 +504,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
503
504
|
#selectedRequest: AiAssistanceModel.NetworkAgent.RequestContext|null = null;
|
|
504
505
|
// Messages displayed in the `ChatView` component.
|
|
505
506
|
#messages: Message[] = [];
|
|
507
|
+
#isContextAutoSelectionSuspended = false;
|
|
506
508
|
|
|
507
509
|
// Whether the UI should show loading or not.
|
|
508
510
|
#isLoading = false;
|
|
@@ -672,6 +674,10 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
672
674
|
this.requestUpdate();
|
|
673
675
|
}
|
|
674
676
|
|
|
677
|
+
async #handlePerformanceRecordAndReload(): Promise<Trace.TraceModel.ParsedTrace> {
|
|
678
|
+
return await TimelinePanel.TimelinePanel.TimelinePanel.executeRecordAndReload();
|
|
679
|
+
}
|
|
680
|
+
|
|
675
681
|
#getDefaultConversationType(): AiAssistanceModel.AiHistoryStorage.ConversationType|undefined {
|
|
676
682
|
const {hostConfig} = Root.Runtime;
|
|
677
683
|
const viewManager = UI.ViewManager.ViewManager.instance();
|
|
@@ -715,7 +721,8 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
715
721
|
}
|
|
716
722
|
const conversation = targetConversationType ?
|
|
717
723
|
new AiAssistanceModel.AiConversation.AiConversation(
|
|
718
|
-
targetConversationType, [], undefined, false, this.#aidaClient, this.#changeManager
|
|
724
|
+
targetConversationType, [], undefined, false, this.#aidaClient, this.#changeManager, false,
|
|
725
|
+
this.#handlePerformanceRecordAndReload.bind(this), this.#handleInspectElement.bind(this)) :
|
|
719
726
|
undefined;
|
|
720
727
|
|
|
721
728
|
this.#updateConversationState(conversation);
|
|
@@ -735,16 +742,28 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
735
742
|
const conversationType = this.#getDefaultConversationType();
|
|
736
743
|
if (conversationType) {
|
|
737
744
|
conversation = new AiAssistanceModel.AiConversation.AiConversation(
|
|
738
|
-
conversationType,
|
|
745
|
+
conversationType,
|
|
746
|
+
[],
|
|
747
|
+
undefined,
|
|
748
|
+
false,
|
|
749
|
+
this.#aidaClient,
|
|
750
|
+
this.#changeManager,
|
|
751
|
+
false,
|
|
752
|
+
this.#handlePerformanceRecordAndReload.bind(this),
|
|
753
|
+
this.#handleInspectElement.bind(this),
|
|
754
|
+
);
|
|
739
755
|
}
|
|
740
756
|
}
|
|
741
757
|
|
|
742
758
|
this.#conversation = conversation;
|
|
759
|
+
this.#isContextAutoSelectionSuspended = false;
|
|
743
760
|
}
|
|
744
761
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
762
|
+
if (!this.#isContextAutoSelectionSuspended) {
|
|
763
|
+
this.#conversation?.setContext(this.#getConversationContext(
|
|
764
|
+
isAiAssistanceContextSelectionAgentEnabled() ? this.#getDefaultConversationType() :
|
|
765
|
+
(this.#conversation?.type ?? null)));
|
|
766
|
+
}
|
|
748
767
|
|
|
749
768
|
this.requestUpdate();
|
|
750
769
|
}
|
|
@@ -1116,10 +1135,12 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1116
1135
|
|
|
1117
1136
|
#handleContextRemoved(): void {
|
|
1118
1137
|
this.#conversation?.setContext(null);
|
|
1138
|
+
this.#isContextAutoSelectionSuspended = true;
|
|
1119
1139
|
this.requestUpdate();
|
|
1120
1140
|
}
|
|
1121
1141
|
|
|
1122
1142
|
#handleContextAdd(): void {
|
|
1143
|
+
this.#isContextAutoSelectionSuspended = false;
|
|
1123
1144
|
this.#conversation?.setContext(this.#getConversationContext(this.#getDefaultConversationType()));
|
|
1124
1145
|
this.requestUpdate();
|
|
1125
1146
|
}
|
|
@@ -1141,6 +1162,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1141
1162
|
return;
|
|
1142
1163
|
}
|
|
1143
1164
|
|
|
1165
|
+
this.#isContextAutoSelectionSuspended = false;
|
|
1144
1166
|
let targetConversationType: AiAssistanceModel.AiHistoryStorage.ConversationType|undefined;
|
|
1145
1167
|
switch (actionId) {
|
|
1146
1168
|
case 'freestyler.elements-floating-button': {
|
|
@@ -1187,7 +1209,16 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1187
1209
|
let conversation = this.#conversation;
|
|
1188
1210
|
if (!this.#conversation || this.#conversation.type !== targetConversationType || this.#conversation.isEmpty) {
|
|
1189
1211
|
conversation = new AiAssistanceModel.AiConversation.AiConversation(
|
|
1190
|
-
targetConversationType,
|
|
1212
|
+
targetConversationType,
|
|
1213
|
+
[],
|
|
1214
|
+
undefined,
|
|
1215
|
+
false,
|
|
1216
|
+
this.#aidaClient,
|
|
1217
|
+
this.#changeManager,
|
|
1218
|
+
false,
|
|
1219
|
+
this.#handlePerformanceRecordAndReload.bind(this),
|
|
1220
|
+
this.#handleInspectElement.bind(this),
|
|
1221
|
+
);
|
|
1191
1222
|
}
|
|
1192
1223
|
this.#updateConversationState(conversation);
|
|
1193
1224
|
const predefinedPrompt = opts?.['prompt'];
|
|
@@ -1334,11 +1365,67 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1334
1365
|
this.#conversation?.setContext(context);
|
|
1335
1366
|
}
|
|
1336
1367
|
|
|
1368
|
+
this.#isContextAutoSelectionSuspended = false;
|
|
1369
|
+
|
|
1337
1370
|
void VisualLogging.logFunctionCall(`context-change-${this.#conversation?.type}`);
|
|
1338
1371
|
|
|
1339
1372
|
this.requestUpdate();
|
|
1340
1373
|
};
|
|
1341
1374
|
|
|
1375
|
+
async #handleInspectElement(): Promise<SDK.DOMModel.DOMNode|null> {
|
|
1376
|
+
if (!this.#toggleSearchElementAction) {
|
|
1377
|
+
return null;
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
const result = new Promise<SDK.DOMModel.DOMNode|null>(resolve => {
|
|
1381
|
+
// Track the new flavor change for dom node.
|
|
1382
|
+
const handleDOMNodeFlavorChange = (ev: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMNode>): void => {
|
|
1383
|
+
if (!ev.data) {
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
resolve(selectedElementFilter(ev.data));
|
|
1387
|
+
removeListeners();
|
|
1388
|
+
};
|
|
1389
|
+
|
|
1390
|
+
// If the inspect mode is toggled, we want to resolve null.
|
|
1391
|
+
const handleInspectModeToggled = (ev: Common.EventTarget.EventTargetEvent<boolean>): void => {
|
|
1392
|
+
if (!ev.data) {
|
|
1393
|
+
// The inspect element is toggled off
|
|
1394
|
+
// before the flavor change event fires
|
|
1395
|
+
// so we need to wait a bit to see if the flavor changed.
|
|
1396
|
+
window.setTimeout(() => {
|
|
1397
|
+
resolve((selectedElementFilter(UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode))));
|
|
1398
|
+
removeListeners();
|
|
1399
|
+
}, 50);
|
|
1400
|
+
}
|
|
1401
|
+
};
|
|
1402
|
+
|
|
1403
|
+
const removeListeners = (): void => {
|
|
1404
|
+
UI.Context.Context.instance().removeFlavorChangeListener(SDK.DOMModel.DOMNode, handleDOMNodeFlavorChange);
|
|
1405
|
+
this.#toggleSearchElementAction?.removeEventListener(
|
|
1406
|
+
UI.ActionRegistration.Events.TOGGLED, handleInspectModeToggled);
|
|
1407
|
+
};
|
|
1408
|
+
|
|
1409
|
+
UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, handleDOMNodeFlavorChange);
|
|
1410
|
+
this.#toggleSearchElementAction?.addEventListener(UI.ActionRegistration.Events.TOGGLED, handleInspectModeToggled);
|
|
1411
|
+
|
|
1412
|
+
// Clean-up listeners in case of abort.
|
|
1413
|
+
this.#runAbortController.signal.addEventListener('abort', () => {
|
|
1414
|
+
resolve(null);
|
|
1415
|
+
removeListeners();
|
|
1416
|
+
}, {once: true});
|
|
1417
|
+
});
|
|
1418
|
+
|
|
1419
|
+
void this.#toggleSearchElementAction.execute();
|
|
1420
|
+
try {
|
|
1421
|
+
return await result;
|
|
1422
|
+
} finally {
|
|
1423
|
+
if (this.#toggleSearchElementAction.toggled()) {
|
|
1424
|
+
void this.#toggleSearchElementAction.execute();
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1342
1429
|
async #startConversation(
|
|
1343
1430
|
text: string,
|
|
1344
1431
|
imageInput?: Host.AidaClient.Part,
|
|
@@ -42,7 +42,11 @@ const UIStrings = {
|
|
|
42
42
|
/**
|
|
43
43
|
* @description Label added to the button that remove the currently selected context in AI Assistance panel.
|
|
44
44
|
*/
|
|
45
|
-
removeContext: 'Remove
|
|
45
|
+
removeContext: 'Remove from context',
|
|
46
|
+
/**
|
|
47
|
+
* @description Label added to the button that add selected context from the current panel in AI Assistance panel.
|
|
48
|
+
*/
|
|
49
|
+
addContext: 'Add selected item as context',
|
|
46
50
|
} as const;
|
|
47
51
|
|
|
48
52
|
/*
|
|
@@ -387,12 +391,12 @@ export const
|
|
|
387
391
|
:
|
|
388
392
|
input.onContextAdd ? html`
|
|
389
393
|
<devtools-button
|
|
390
|
-
title=${i18nString(UIStrings.
|
|
391
|
-
aria-label=${i18nString(UIStrings.
|
|
394
|
+
title=${i18nString(UIStrings.addContext)}
|
|
395
|
+
aria-label=${i18nString(UIStrings.addContext)}
|
|
392
396
|
class="add-context"
|
|
393
397
|
.iconName=${'plus'}
|
|
394
398
|
.size=${Buttons.Button.Size.SMALL}
|
|
395
|
-
.jslogContext=${'context-
|
|
399
|
+
.jslogContext=${'context-added'}
|
|
396
400
|
.variant=${Buttons.Button.Variant.ICON}
|
|
397
401
|
@click=${input.onContextAdd}></devtools-button>` : Lit.nothing}
|
|
398
402
|
</div>
|
|
@@ -1916,17 +1916,19 @@ export class ResourcesSection implements SDK.TargetManager.Observer {
|
|
|
1916
1916
|
frameManager.addEventListener(
|
|
1917
1917
|
SDK.FrameManager.Events.RESOURCE_ADDED, event => this.resourceAdded(event.data.resource), this);
|
|
1918
1918
|
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1919
|
+
if (this.panel.mode !== 'node') {
|
|
1920
|
+
SDK.TargetManager.TargetManager.instance().addModelListener(
|
|
1921
|
+
SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_CREATED, this.windowOpened,
|
|
1922
|
+
this, {scoped: true});
|
|
1923
|
+
SDK.TargetManager.TargetManager.instance().addModelListener(
|
|
1924
|
+
SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_INFO_CHANGED,
|
|
1925
|
+
this.windowChanged, this, {scoped: true});
|
|
1926
|
+
SDK.TargetManager.TargetManager.instance().addModelListener(
|
|
1927
|
+
SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_DESTROYED,
|
|
1928
|
+
this.windowDestroyed, this, {scoped: true});
|
|
1929
|
+
|
|
1930
|
+
SDK.TargetManager.TargetManager.instance().observeTargets(this, {scoped: true});
|
|
1931
|
+
}
|
|
1930
1932
|
}
|
|
1931
1933
|
|
|
1932
1934
|
private initialize(): void {
|
|
@@ -250,7 +250,7 @@ export class DOMStorageModel extends SDK.SDKModel.SDKModel<EventTypes> {
|
|
|
250
250
|
}
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
-
SDK.SDKModel.SDKModel.register(DOMStorageModel, {capabilities: SDK.Target.Capability.
|
|
253
|
+
SDK.SDKModel.SDKModel.register(DOMStorageModel, {capabilities: SDK.Target.Capability.DOM_STORAGE, autostart: false});
|
|
254
254
|
|
|
255
255
|
export const enum Events {
|
|
256
256
|
DOM_STORAGE_ADDED = 'DOMStorageAdded',
|
|
@@ -37,9 +37,13 @@ export class ResourcesPanel extends UI.Panel.PanelWithSidebar {
|
|
|
37
37
|
private cookieView: CookieItemsView|null;
|
|
38
38
|
private deviceBoundSessionsView: DeviceBoundSessionsView|null;
|
|
39
39
|
private readonly sidebar: ApplicationPanelSidebar;
|
|
40
|
+
mode: 'default'|'node' = 'default';
|
|
40
41
|
|
|
41
|
-
private constructor(
|
|
42
|
+
private constructor(
|
|
43
|
+
mode: 'default'|'node' = 'default',
|
|
44
|
+
) {
|
|
42
45
|
super('resources');
|
|
46
|
+
this.mode = mode;
|
|
43
47
|
this.registerRequiredCSS(resourcesPanelStyles);
|
|
44
48
|
|
|
45
49
|
this.resourcesLastSelectedItemSetting =
|
|
@@ -68,11 +72,12 @@ export class ResourcesPanel extends UI.Panel.PanelWithSidebar {
|
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
static instance(opts: {
|
|
71
|
-
forceNew
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
forceNew?: boolean|null,
|
|
76
|
+
mode?: 'default'|'node',
|
|
77
|
+
} = {forceNew: null, mode: 'default'}): ResourcesPanel {
|
|
78
|
+
const {forceNew, mode} = opts;
|
|
74
79
|
if (!resourcesPanelInstance || forceNew) {
|
|
75
|
-
resourcesPanelInstance = new ResourcesPanel();
|
|
80
|
+
resourcesPanelInstance = new ResourcesPanel(mode);
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
return resourcesPanelInstance;
|
|
@@ -22,7 +22,7 @@ import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
|
|
|
22
22
|
|
|
23
23
|
import * as PreloadingComponents from './components/components.js';
|
|
24
24
|
import {ruleSetTagOrLocationShort} from './components/PreloadingString.js';
|
|
25
|
-
import
|
|
25
|
+
import * as PreloadingHelper from './helper/helper.js';
|
|
26
26
|
import preloadingViewStyles from './preloadingView.css.js';
|
|
27
27
|
import preloadingViewDropDownStyles from './preloadingViewDropDown.css.js';
|
|
28
28
|
|
|
@@ -501,10 +501,17 @@ export class PreloadingAttemptView extends UI.Widget.VBox {
|
|
|
501
501
|
const ruleSet = this.model.getRuleSetById(id);
|
|
502
502
|
return ruleSet === null ? [] : [ruleSet];
|
|
503
503
|
});
|
|
504
|
+
|
|
505
|
+
// Lookup status code for prefetch attempts
|
|
506
|
+
const statusCode = attempt.action === Protocol.Preload.SpeculationAction.Prefetch ?
|
|
507
|
+
PreloadingHelper.PreloadingForward.prefetchStatusCode(attempt.requestId) :
|
|
508
|
+
undefined;
|
|
509
|
+
|
|
504
510
|
return {
|
|
505
511
|
id,
|
|
506
512
|
pipeline,
|
|
507
513
|
ruleSets,
|
|
514
|
+
statusCode,
|
|
508
515
|
};
|
|
509
516
|
});
|
|
510
517
|
this.preloadingGrid.rows = rows;
|
|
@@ -349,7 +349,10 @@ export class PreloadingDetailsReportView extends LegacyWrapper.LegacyWrapper.Wra
|
|
|
349
349
|
return Lit.nothing;
|
|
350
350
|
}
|
|
351
351
|
|
|
352
|
-
|
|
352
|
+
// Lookup status code for Non2XX failures
|
|
353
|
+
const statusCode = PreloadingHelper.PreloadingForward.prefetchStatusCode(attempt.requestId);
|
|
354
|
+
|
|
355
|
+
const failureDescription = prefetchFailureReason(attempt, statusCode);
|
|
353
356
|
if (failureDescription === null) {
|
|
354
357
|
return Lit.nothing;
|
|
355
358
|
}
|
|
@@ -51,6 +51,7 @@ export interface PreloadingGridRow {
|
|
|
51
51
|
id: string;
|
|
52
52
|
pipeline: SDK.PreloadingModel.PreloadPipeline;
|
|
53
53
|
ruleSets: Protocol.Preload.RuleSet[];
|
|
54
|
+
statusCode?: number;
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
export interface ViewInput {
|
|
@@ -107,7 +108,7 @@ export const PRELOADING_GRID_DEFAULT_VIEW: View = (input, _output, target): void
|
|
|
107
108
|
'vertical-align': 'sub',
|
|
108
109
|
})}
|
|
109
110
|
></devtools-icon>` : ''}
|
|
110
|
-
${hasWarning ? i18nString(UIStrings.prefetchFallbackReady) : composedStatus(attempt)}
|
|
111
|
+
${hasWarning ? i18nString(UIStrings.prefetchFallbackReady) : composedStatus(attempt, row.statusCode)}
|
|
111
112
|
</div>
|
|
112
113
|
</td>
|
|
113
114
|
</tr>`;
|
|
@@ -31,6 +31,11 @@ const UIStrings = {
|
|
|
31
31
|
* @description Description text for Prefetch status PrefetchFailedNon2XX.
|
|
32
32
|
*/
|
|
33
33
|
PrefetchFailedNon2XX: 'The prefetch failed because of a non-2xx HTTP response status code.',
|
|
34
|
+
/**
|
|
35
|
+
* @description Description text for Prefetch status PrefetchFailedNon2XX when the HTTP status code is known.
|
|
36
|
+
* @example {404} PH1
|
|
37
|
+
*/
|
|
38
|
+
PrefetchFailedNon2XXWithStatusCode: 'The prefetch failed because of a non-2xx HTTP response status code ({PH1}).',
|
|
34
39
|
/**
|
|
35
40
|
* @description Description text for Prefetch status PrefetchIneligibleRetryAfter.
|
|
36
41
|
*/
|
|
@@ -446,7 +451,8 @@ export const PrefetchReasonDescription: Record<string, {name: () => Platform.UIS
|
|
|
446
451
|
};
|
|
447
452
|
|
|
448
453
|
/** Decoding PrefetchFinalStatus prefetchAttempt to failure description. **/
|
|
449
|
-
export function prefetchFailureReason(
|
|
454
|
+
export function prefetchFailureReason(
|
|
455
|
+
{prefetchStatus}: SDK.PreloadingModel.PrefetchAttempt, statusCode?: number): string|null {
|
|
450
456
|
// If you face an error on rolling CDP changes, see
|
|
451
457
|
// https://docs.google.com/document/d/1PnrfowsZMt62PX1EvvTp2Nqs3ji1zrklrAEe1JYbkTk
|
|
452
458
|
switch (prefetchStatus) {
|
|
@@ -478,6 +484,9 @@ export function prefetchFailureReason({prefetchStatus}: SDK.PreloadingModel.Pref
|
|
|
478
484
|
case Protocol.Preload.PrefetchStatus.PrefetchFailedNetError:
|
|
479
485
|
return PrefetchReasonDescription['PrefetchFailedNetError'].name();
|
|
480
486
|
case Protocol.Preload.PrefetchStatus.PrefetchFailedNon2XX:
|
|
487
|
+
if (statusCode !== undefined) {
|
|
488
|
+
return i18nString(UIStrings.PrefetchFailedNon2XXWithStatusCode, {PH1: String(statusCode)});
|
|
489
|
+
}
|
|
481
490
|
return PrefetchReasonDescription['PrefetchFailedNon2XX'].name();
|
|
482
491
|
case Protocol.Preload.PrefetchStatus.PrefetchIneligibleRetryAfter:
|
|
483
492
|
return PrefetchReasonDescription['PrefetchIneligibleRetryAfter'].name();
|
|
@@ -795,7 +804,7 @@ export function status(status: SDK.PreloadingModel.PreloadingStatus): string {
|
|
|
795
804
|
}
|
|
796
805
|
}
|
|
797
806
|
|
|
798
|
-
export function composedStatus(attempt: SDK.PreloadingModel.PreloadingAttempt): string {
|
|
807
|
+
export function composedStatus(attempt: SDK.PreloadingModel.PreloadingAttempt, statusCode?: number): string {
|
|
799
808
|
const short = status(attempt.status);
|
|
800
809
|
|
|
801
810
|
if (attempt.status !== SDK.PreloadingModel.PreloadingStatus.FAILURE) {
|
|
@@ -804,7 +813,7 @@ export function composedStatus(attempt: SDK.PreloadingModel.PreloadingAttempt):
|
|
|
804
813
|
|
|
805
814
|
switch (attempt.action) {
|
|
806
815
|
case Protocol.Preload.SpeculationAction.Prefetch: {
|
|
807
|
-
const detail = prefetchFailureReason(attempt) ?? i18n.i18n.lockedString('Internal error');
|
|
816
|
+
const detail = prefetchFailureReason(attempt, statusCode) ?? i18n.i18n.lockedString('Internal error');
|
|
808
817
|
return short + ' - ' + detail;
|
|
809
818
|
}
|
|
810
819
|
case Protocol.Preload.SpeculationAction.Prerender:
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import type * as Protocol from '../../../../generated/protocol.js';
|
|
6
|
+
import * as Logs from '../../../../models/logs/logs.js';
|
|
6
7
|
|
|
7
8
|
export class RuleSetView {
|
|
8
9
|
readonly ruleSetId: Protocol.Preload.RuleSetId|null;
|
|
@@ -19,3 +20,16 @@ export class AttemptViewWithFilter {
|
|
|
19
20
|
this.ruleSetId = ruleSetId;
|
|
20
21
|
}
|
|
21
22
|
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Retrieves the HTTP status code for a prefetch attempt by looking up its
|
|
26
|
+
* network request in the network log.
|
|
27
|
+
*/
|
|
28
|
+
export function prefetchStatusCode(requestId: Protocol.Network.RequestId): number|undefined {
|
|
29
|
+
const networkLog = Logs.NetworkLog.NetworkLog.instance();
|
|
30
|
+
const requests = networkLog.requestsForId(requestId);
|
|
31
|
+
if (requests.length > 0) {
|
|
32
|
+
return requests[requests.length - 1].statusCode;
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
@@ -134,6 +134,9 @@ interface ViewOutput {
|
|
|
134
134
|
interface ViewInput {
|
|
135
135
|
onFilterChanged: (filterText: string|null) => void;
|
|
136
136
|
onBreakpointChange: (breakpoint: SDK.CategorizedBreakpoint.CategorizedBreakpoint, enabled: boolean) => void;
|
|
137
|
+
onItemSelected: (item: SDK.CategorizedBreakpoint.Category|SDK.CategorizedBreakpoint.CategorizedBreakpoint|
|
|
138
|
+
null) => void;
|
|
139
|
+
onSpaceKeyDown: () => void;
|
|
137
140
|
|
|
138
141
|
filterText: string|null;
|
|
139
142
|
userExpandedCategories: Set<SDK.CategorizedBreakpoint.Category>;
|
|
@@ -200,6 +203,13 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
200
203
|
}
|
|
201
204
|
};
|
|
202
205
|
|
|
206
|
+
const onKeyDown = (e: KeyboardEvent): void => {
|
|
207
|
+
if (e.key === ' ') {
|
|
208
|
+
input.onSpaceKeyDown();
|
|
209
|
+
e.preventDefault();
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
203
213
|
render(
|
|
204
214
|
// clang-format off
|
|
205
215
|
html`
|
|
@@ -210,10 +220,11 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
210
220
|
style="flex: 1;"
|
|
211
221
|
></devtools-toolbar-input>
|
|
212
222
|
</devtools-toolbar>
|
|
213
|
-
<devtools-tree autofocus .template=${html`
|
|
223
|
+
<devtools-tree autofocus @keydown=${onKeyDown} .template=${html`
|
|
214
224
|
<ul role="tree">
|
|
215
225
|
${filteredCategories.map(([category, breakpoints]) => html`
|
|
216
|
-
<li @
|
|
226
|
+
<li @select=${() => input.onItemSelected(category)}
|
|
227
|
+
@expand=${(e: UI.TreeOutline.TreeViewElement.ExpandEvent) => onExpand(category, e)}
|
|
217
228
|
role="treeitem"
|
|
218
229
|
jslog-context=${category}
|
|
219
230
|
aria-checked=${breakpoints.some(breakpoint => breakpoint.enabled())
|
|
@@ -233,7 +244,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
|
233
244
|
role="group"
|
|
234
245
|
?hidden=${!shouldExpandCategory(breakpoints) && !input.userExpandedCategories.has(category)}>
|
|
235
246
|
${breakpoints.map(breakpoint => html`
|
|
236
|
-
<li
|
|
247
|
+
<li @select=${() => input.onItemSelected(breakpoint)}
|
|
237
248
|
role="treeitem"
|
|
238
249
|
aria-checked=${breakpoint.enabled()}
|
|
239
250
|
jslog-context=${Platform.StringUtilities.toKebabCase(breakpoint.name)}>
|
|
@@ -265,6 +276,7 @@ export abstract class CategorizedBreakpointsSidebarPane extends UI.Widget.VBox {
|
|
|
265
276
|
#filterText: string|null = null;
|
|
266
277
|
#view: View;
|
|
267
278
|
#userExpandedCategories = new Set<SDK.CategorizedBreakpoint.Category>();
|
|
279
|
+
#selectedItem: SDK.CategorizedBreakpoint.Category|SDK.CategorizedBreakpoint.CategorizedBreakpoint|null = null;
|
|
268
280
|
constructor(
|
|
269
281
|
breakpoints: SDK.CategorizedBreakpoint.CategorizedBreakpoint[], jslog: string, viewId: string,
|
|
270
282
|
view = DEFAULT_VIEW) {
|
|
@@ -321,6 +333,26 @@ export abstract class CategorizedBreakpointsSidebarPane extends UI.Widget.VBox {
|
|
|
321
333
|
this.requestUpdate();
|
|
322
334
|
}
|
|
323
335
|
|
|
336
|
+
#onItemSelected(item: SDK.CategorizedBreakpoint.Category|SDK.CategorizedBreakpoint.CategorizedBreakpoint|null): void {
|
|
337
|
+
this.#selectedItem = item;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
#onSpaceKeyDown(): void {
|
|
341
|
+
const selected = this.#selectedItem;
|
|
342
|
+
if (!selected) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
if (selected instanceof SDK.CategorizedBreakpoint.CategorizedBreakpoint) {
|
|
346
|
+
this.onBreakpointChanged(selected, !selected.enabled());
|
|
347
|
+
} else {
|
|
348
|
+
const breakpoints = this.categories.get(selected);
|
|
349
|
+
if (breakpoints) {
|
|
350
|
+
const newEnabled = breakpoints.some(bp => !bp.enabled());
|
|
351
|
+
breakpoints.forEach(bp => this.onBreakpointChanged(bp, newEnabled));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
324
356
|
protected onBreakpointChanged(breakpoint: SDK.CategorizedBreakpoint.CategorizedBreakpoint, enabled: boolean): void {
|
|
325
357
|
breakpoint.setEnabled(enabled);
|
|
326
358
|
this.requestUpdate();
|
|
@@ -331,6 +363,8 @@ export abstract class CategorizedBreakpointsSidebarPane extends UI.Widget.VBox {
|
|
|
331
363
|
filterText: this.#filterText,
|
|
332
364
|
onFilterChanged: this.#onFilterChanged.bind(this),
|
|
333
365
|
onBreakpointChange: this.onBreakpointChanged.bind(this),
|
|
366
|
+
onItemSelected: this.#onItemSelected.bind(this),
|
|
367
|
+
onSpaceKeyDown: this.#onSpaceKeyDown.bind(this),
|
|
334
368
|
sortedCategoryNames: this.#sortedCategories,
|
|
335
369
|
categories: this.categories,
|
|
336
370
|
highlightedItem: this.#highlightedItem,
|
|
@@ -24,7 +24,7 @@ const UIStrings = {
|
|
|
24
24
|
} as const;
|
|
25
25
|
const str_ = i18n.i18n.registerUIStrings('panels/changes/ChangesSidebar.ts', UIStrings);
|
|
26
26
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
27
|
-
const {render, html
|
|
27
|
+
const {render, html} = Lit;
|
|
28
28
|
interface ViewInput {
|
|
29
29
|
selectedSourceCode: Workspace.UISourceCode.UISourceCode|null;
|
|
30
30
|
onSelect: (uiSourceCode: Workspace.UISourceCode.UISourceCode|null) => void;
|
|
@@ -38,20 +38,16 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
38
38
|
uiSourceCode.url();
|
|
39
39
|
const icon = (uiSourceCode: Workspace.UISourceCode.UISourceCode): string =>
|
|
40
40
|
Snippets.ScriptSnippetFileSystem.isSnippetsUISourceCode(uiSourceCode) ? 'snippet' : 'document';
|
|
41
|
-
const configElements = new WeakMap<HTMLLIElement, Workspace.UISourceCode.UISourceCode>();
|
|
42
|
-
const onSelect = (e: UI.TreeOutline.TreeViewElement.SelectEvent): void =>
|
|
43
|
-
input.onSelect(configElements.get(e.detail) ?? null);
|
|
44
41
|
render(
|
|
45
42
|
// clang-format off
|
|
46
43
|
html`<devtools-tree
|
|
47
|
-
@selected=${onSelect}
|
|
48
44
|
navigation-variant
|
|
49
45
|
hide-overflow .template=${html`
|
|
50
46
|
<ul role="tree">
|
|
51
47
|
${input.sourceCodes.values().map(uiSourceCode => html`
|
|
52
48
|
<li
|
|
53
49
|
role="treeitem"
|
|
54
|
-
|
|
50
|
+
@select=${() => input.onSelect(uiSourceCode)}
|
|
55
51
|
?selected=${uiSourceCode === input.selectedSourceCode}>
|
|
56
52
|
<style>${changesSidebarStyles}</style>
|
|
57
53
|
<div class=${'navigator-' + uiSourceCode.contentType().name() + '-tree-item'}>
|
|
@@ -73,12 +73,12 @@ const UIStringsNotTranslate = {
|
|
|
73
73
|
* @description Code generation disclaimer item text for the fre dialog.
|
|
74
74
|
*/
|
|
75
75
|
freDisclaimerDescribeCodeInComment:
|
|
76
|
-
'In Console or Sources, describe the code you need in a comment, then press
|
|
76
|
+
'In Console or Sources, describe the code you need in a comment, then press ctrl+i to generate it.',
|
|
77
77
|
/**
|
|
78
78
|
* @description Code generation disclaimer item text for the fre dialog.
|
|
79
79
|
*/
|
|
80
80
|
freDisclaimerDescribeCodeInCommentForMacOs:
|
|
81
|
-
'In Console or Sources, describe the code you need in a comment, then press
|
|
81
|
+
'In Console or Sources, describe the code you need in a comment, then press cmd+i to generate it.',
|
|
82
82
|
/**
|
|
83
83
|
* @description Privacy disclaimer item text for the fre dialog.
|
|
84
84
|
*/
|
|
@@ -140,7 +140,17 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
|
140
140
|
<span>${lockedString(UIStringsNotTranslate.i)}</span>
|
|
141
141
|
</span>
|
|
142
142
|
</span> ${lockedString(UIStringsNotTranslate.toTurnOnCodeSuggestions)}
|
|
143
|
-
<span role="button" class="ai-code-completion-teaser-dismiss"
|
|
143
|
+
<span role="button" class="ai-code-completion-teaser-dismiss"
|
|
144
|
+
tabindex="0"
|
|
145
|
+
@click=${input.onDismiss}
|
|
146
|
+
@keydown=${(e: KeyboardEvent) => {
|
|
147
|
+
// Handle Enter and Space events to make dismiss button accessible for only keyboard users.
|
|
148
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
149
|
+
input.onDismiss(e);
|
|
150
|
+
e.stopPropagation();
|
|
151
|
+
e.preventDefault();
|
|
152
|
+
}
|
|
153
|
+
}}
|
|
144
154
|
jslog=${VisualLogging.action('ai-code-completion-teaser.dismiss').track({click: true})}>
|
|
145
155
|
${lockedString(UIStringsNotTranslate.dontShowAgain)}
|
|
146
156
|
</span>
|
|
@@ -26,6 +26,12 @@
|
|
|
26
26
|
.ai-code-completion-teaser-dismiss {
|
|
27
27
|
text-decoration: underline;
|
|
28
28
|
cursor: pointer;
|
|
29
|
+
|
|
30
|
+
&:focus-visible {
|
|
31
|
+
border-radius: var(--sys-shape-corner-extra-small);
|
|
32
|
+
outline: var(--sys-size-2) solid var(--sys-color-state-focus-ring);
|
|
33
|
+
outline-offset: 0;
|
|
34
|
+
}
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
.ai-code-completion-teaser-action {
|
|
@@ -50,7 +50,7 @@ const UIStrings = {
|
|
|
50
50
|
} as const;
|
|
51
51
|
const str_ = i18n.i18n.registerUIStrings('panels/console/ConsoleSidebar.ts', UIStrings);
|
|
52
52
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
53
|
-
const {render, html, nothing
|
|
53
|
+
const {render, html, nothing} = Lit;
|
|
54
54
|
|
|
55
55
|
export const enum GroupName {
|
|
56
56
|
CONSOLE_API = 'user message',
|
|
@@ -78,18 +78,10 @@ interface ViewInput {
|
|
|
78
78
|
|
|
79
79
|
export type View = (input: ViewInput, output: object, target: HTMLElement) => void;
|
|
80
80
|
export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
81
|
-
const nodeFilterMap = new WeakMap<Element, ConsoleFilter>();
|
|
82
|
-
const onSelectionChanged = (event: UI.TreeOutline.TreeViewElement.SelectEvent): void => {
|
|
83
|
-
const filter = nodeFilterMap.get(event.detail);
|
|
84
|
-
if (filter) {
|
|
85
|
-
input.onSelectionChanged(filter);
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
81
|
render(
|
|
89
82
|
html`<devtools-tree
|
|
90
83
|
navigation-variant
|
|
91
84
|
hide-overflow
|
|
92
|
-
@select=${onSelectionChanged}
|
|
93
85
|
.template=${
|
|
94
86
|
html`
|
|
95
87
|
<ul role="tree">
|
|
@@ -98,7 +90,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
98
90
|
group => html`
|
|
99
91
|
<li
|
|
100
92
|
role="treeitem"
|
|
101
|
-
|
|
93
|
+
@select=${() => input.onSelectionChanged(group.filter)}
|
|
102
94
|
?selected=${group.filter === input.selectedFilter}>
|
|
103
95
|
<style>${consoleSidebarStyles}</style>
|
|
104
96
|
<devtools-icon name=${GROUP_ICONS[group.name].icon}></devtools-icon>
|
|
@@ -112,7 +104,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
112
104
|
<ul role="group" hidden>
|
|
113
105
|
${group.urlGroups.values().map(urlGroup => html`
|
|
114
106
|
<li
|
|
115
|
-
|
|
107
|
+
@select=${() => input.onSelectionChanged(urlGroup.filter)}
|
|
116
108
|
role="treeitem"
|
|
117
109
|
?selected=${urlGroup.filter === input.selectedFilter}
|
|
118
110
|
title=${urlGroup.url ?? ''}>
|