chrome-devtools-frontend 1.0.939144 → 1.0.940714

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.
Files changed (53) hide show
  1. package/.stylelintrc.json +1 -7
  2. package/config/gni/all_devtools_files.gni +0 -1
  3. package/config/gni/devtools_grd_files.gni +2 -0
  4. package/docs/triage_guidelines.md +13 -11
  5. package/front_end/Tests.js +33 -0
  6. package/front_end/core/host/InspectorFrontendHostAPI.ts +5 -0
  7. package/front_end/core/host/UserMetrics.ts +72 -0
  8. package/front_end/core/i18n/locales/en-US.json +30 -9
  9. package/front_end/core/i18n/locales/en-XL.json +30 -9
  10. package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
  11. package/front_end/core/root/Runtime.ts +4 -0
  12. package/front_end/core/sdk/CSSModel.ts +64 -50
  13. package/front_end/core/sdk/CategorizedBreakpoint.ts +35 -0
  14. package/front_end/core/sdk/DOMDebuggerModel.ts +28 -42
  15. package/front_end/core/sdk/EventBreakpointsModel.ts +178 -0
  16. package/front_end/core/sdk/Target.ts +2 -1
  17. package/front_end/core/sdk/sdk.ts +4 -0
  18. package/front_end/devtools_compatibility.js +5 -0
  19. package/front_end/entrypoints/main/MainImpl.ts +6 -3
  20. package/front_end/entrypoints/main/main-meta.ts +1 -2
  21. package/front_end/entrypoints/shell/shell.js +1 -0
  22. package/front_end/entrypoints/shell/shell.json +0 -1
  23. package/front_end/models/logs/LogManager.ts +1 -0
  24. package/front_end/panels/accessibility/AXBreadcrumbsPane.ts +1 -1
  25. package/front_end/panels/accessibility/AccessibilityNodeView.ts +1 -1
  26. package/front_end/panels/application/ApplicationPanelCacheSection.ts +1 -1
  27. package/front_end/panels/application/BackForwardCacheView.ts +24 -24
  28. package/front_end/panels/browser_debugger/CSPViolationBreakpointsSidebarPane.ts +2 -2
  29. package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +7 -7
  30. package/front_end/panels/browser_debugger/EventListenerBreakpointsSidebarPane.ts +14 -6
  31. package/front_end/panels/css_overview/components/CSSOverviewStartView.ts +6 -8
  32. package/front_end/panels/css_overview/components/cssOverviewStartView.css +7 -1
  33. package/front_end/panels/elements/StylesSidebarPane.ts +2 -1
  34. package/front_end/panels/issues/IssueKindView.ts +22 -4
  35. package/front_end/panels/lighthouse/LighthouseController.ts +10 -33
  36. package/front_end/panels/lighthouse/LighthousePanel.ts +2 -1
  37. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +2 -1
  38. package/front_end/panels/network/NetworkLogView.ts +16 -0
  39. package/front_end/panels/network/RequestPayloadView.ts +2 -0
  40. package/front_end/panels/network/requestPayloadTree.css +5 -0
  41. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +1 -0
  42. package/front_end/panels/settings/components/SyncSection.ts +25 -4
  43. package/front_end/panels/sources/DebuggerPausedMessage.ts +14 -7
  44. package/front_end/third_party/codemirror.next/bundle-tsconfig.json +1 -1
  45. package/front_end/ui/components/buttons/Button.ts +11 -0
  46. package/front_end/ui/components/buttons/button.css +4 -0
  47. package/front_end/ui/components/docs/button/basic.ts +10 -0
  48. package/package.json +2 -2
  49. package/scripts/eslint_rules/lib/check_component_naming.js +1 -1
  50. package/scripts/eslint_rules/lib/enforce_custom_event_names.js +1 -1
  51. package/scripts/eslint_rules/lib/l10n_no_i18nString_calls_module_instantiation.js +1 -1
  52. package/scripts/eslint_rules/lib/no_underscored_properties.js +1 -1
  53. package/front_end/entrypoints/main/module.json +0 -5
@@ -11,6 +11,7 @@ import './NetworkManager.js';
11
11
  import './RuntimeModel.js';
12
12
 
13
13
  import * as AccessibilityModel from './AccessibilityModel.js';
14
+ import * as CategorizedBreakpoint from './CategorizedBreakpoint.js';
14
15
  import * as ChildTargetManager from './ChildTargetManager.js';
15
16
  import * as CompilerSourceMappingContentProvider from './CompilerSourceMappingContentProvider.js';
16
17
  import * as Connections from './Connections.js';
@@ -37,6 +38,7 @@ import * as DebuggerModel from './DebuggerModel.js';
37
38
  import * as DOMDebuggerModel from './DOMDebuggerModel.js';
38
39
  import * as DOMModel from './DOMModel.js';
39
40
  import * as EmulationModel from './EmulationModel.js';
41
+ import * as EventBreakpointsModel from './EventBreakpointsModel.js';
40
42
  import * as FilmStripModel from './FilmStripModel.js';
41
43
  import * as FrameManager from './FrameManager.js';
42
44
  import * as HeapProfilerModel from './HeapProfilerModel.js';
@@ -76,6 +78,7 @@ import * as WebAuthnModel from './WebAuthnModel.js';
76
78
 
77
79
  export {
78
80
  AccessibilityModel,
81
+ CategorizedBreakpoint,
79
82
  ChildTargetManager,
80
83
  CompilerSourceMappingContentProvider,
81
84
  Connections,
@@ -102,6 +105,7 @@ export {
102
105
  DOMDebuggerModel,
103
106
  DOMModel,
104
107
  EmulationModel,
108
+ EventBreakpointsModel,
105
109
  FilmStripModel,
106
110
  FrameManager,
107
111
  HeapProfilerModel,
@@ -396,6 +396,11 @@
396
396
  LinearMemoryInspectorTarget: 'DevTools.LinearMemoryInspector.Target',
397
397
  Language: 'DevTools.Language',
398
398
  ConsoleShowsCorsErrors: 'DevTools.ConsoleShowsCorsErrors',
399
+ RecordingEdited: 'DevTools.RecordingEdited',
400
+ RecordingExported: 'DevTools.RecordingExported',
401
+ RecordingReplayFinished: 'DevTools.RecordingReplayFinished',
402
+ RecordingReplayStarted: 'DevTools.RecordingReplayStarted',
403
+ RecordingToggled: 'DevTools.RecordingToggled',
399
404
  };
400
405
 
401
406
  /**
@@ -149,7 +149,10 @@ export class MainImpl {
149
149
  this.createSettings(prefs);
150
150
  await this.requestAndRegisterLocaleData();
151
151
 
152
- Host.userMetrics.syncSetting(Common.Settings.Settings.instance().moduleSetting<boolean>('sync_preferences').get());
152
+ if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.SYNC_SETTINGS)) {
153
+ Host.userMetrics.syncSetting(
154
+ Common.Settings.Settings.instance().moduleSetting<boolean>('sync_preferences').get());
155
+ }
153
156
 
154
157
  this.createAppUI();
155
158
  }
@@ -270,8 +273,8 @@ export class MainImpl {
270
273
  'keyboardShortcutEditor', 'Enable keyboard shortcut editor', true,
271
274
  'https://developer.chrome.com/blog/new-in-devtools-88/#keyboard-shortcuts');
272
275
 
273
- // Back-forward cache
274
- Root.Runtime.experiments.register('bfcacheDebugging', 'Enable back-forward cache debugging support');
276
+ // Back-Forward Cache
277
+ Root.Runtime.experiments.register('bfcacheDebugging', 'Enable Back-Forward Cache debugging support');
275
278
 
276
279
  // Timeline
277
280
  Root.Runtime.experiments.register('timelineEventInitiators', 'Timeline: event initiators');
@@ -223,8 +223,6 @@ let loadedInspectorMainModule: (typeof InspectorMain|undefined);
223
223
 
224
224
  async function loadMainModule(): Promise<typeof Main> {
225
225
  if (!loadedMainModule) {
226
- // Side-effect import resources in module.json
227
- await Root.Runtime.Runtime.instance().loadModulePromise('entrypoints/main');
228
226
  loadedMainModule = await import('./main.js');
229
227
  }
230
228
  return loadedMainModule;
@@ -754,6 +752,7 @@ function filterLocalesForSettings(): string[] {
754
752
 
755
753
  Common.Settings.registerSettingExtension({
756
754
  category: Common.Settings.SettingCategory.APPEARANCE,
755
+ storageType: Common.Settings.SettingStorageType.Synced,
757
756
  settingName: 'language',
758
757
  settingType: Common.Settings.SettingType.ENUM,
759
758
  title: i18nLazyString(UIStrings.language),
@@ -20,4 +20,5 @@ import '../../models/persistence/persistence-legacy.js';
20
20
  import '../../models/extensions/extensions-legacy.js';
21
21
 
22
22
  import './shell-meta-files.js';
23
+ import '../main/main.js';
23
24
  // We generate the descriptors in this file, which depend on the runtime.
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "modules": [
3
- { "name": "entrypoints/main", "type": "autostart" },
4
3
  { "name": "ui/legacy", "type": "autostart" },
5
4
  { "name": "ui/legacy/components/text_editor", "type": "autostart" },
6
5
  { "name": "ui/legacy/components/source_frame", "type": "autostart" },
@@ -49,6 +49,7 @@ export class LogManager implements SDK.TargetManager.SDKModelObserver<SDK.LogMod
49
49
  timestamp: entry.timestamp,
50
50
  workerId: entry.workerId,
51
51
  category: entry.category,
52
+ affectedResources: entry.networkRequestId ? {requestId: entry.networkRequestId} : undefined,
52
53
  };
53
54
  const consoleMessage = new SDK.ConsoleModel.ConsoleMessage(
54
55
  target.model(SDK.RuntimeModel.RuntimeModel), entry.source, entry.level, entry.text, details);
@@ -446,7 +446,7 @@ export class AXBreadcrumb {
446
446
  }
447
447
  }
448
448
 
449
- if (this.axNodeInternal.hasOnlyUnloadedChildren()) {
449
+ if (!this.axNodeInternal.ignored() && this.axNodeInternal.hasOnlyUnloadedChildren()) {
450
450
  this.nodeElementInternal.classList.add('children-unloaded');
451
451
  UI.ARIAUtils.setExpanded(this.nodeElementInternal, false);
452
452
  }
@@ -673,7 +673,7 @@ export class AXNodeIgnoredReasonTreeElement extends AXNodePropertyTreeElement {
673
673
  reasonElement = i18n.i18n.getFormatLocalizedString(str_, UIStrings.elementIsNotVisible, {});
674
674
  break;
675
675
  case 'presentationalRole': {
676
- const role = axNode && axNode.role() || '';
676
+ const role = axNode && axNode.role()?.value || '';
677
677
  const rolePresentationSpan = document.createElement('span', {is: 'source-code'}).textContent = 'role=' + role;
678
678
  reasonElement =
679
679
  i18n.i18n.getFormatLocalizedString(str_, UIStrings.elementHasPlaceholder, {PH1: rolePresentationSpan});
@@ -20,7 +20,7 @@ const UIStrings = {
20
20
  /**
21
21
  *@description Text in Application Panel Sidebar of the Application panel
22
22
  */
23
- backForwardCache: 'Back-forward Cache',
23
+ backForwardCache: 'Back-Forward Cache',
24
24
  /**
25
25
  *@description A context menu item in the Application Panel Sidebar of the Application panel
26
26
  */
@@ -17,67 +17,67 @@ import backForwardCacheViewStyles from './backForwardCacheView.css.js';
17
17
 
18
18
  const UIStrings = {
19
19
  /**
20
- * @description Title text in Back-forward Cache view of the Application panel
20
+ * @description Title text in Back-Forward Cache view of the Application panel
21
21
  */
22
22
  mainFrame: 'Main Frame',
23
23
  /**
24
- * @description Title text in Back-forward Cache view of the Application panel
24
+ * @description Title text in Back-Forward Cache view of the Application panel
25
25
  */
26
- backForwardCacheTitle: 'Back-forward Cache',
26
+ backForwardCacheTitle: 'Back-Forward Cache',
27
27
  /**
28
28
  * @description Status text for the status of the main frame
29
29
  */
30
30
  unavailable: 'unavailable',
31
31
  /**
32
- * @description Entry name text in the Back-forward Cache view of the Application panel
32
+ * @description Entry name text in the Back-Forward Cache view of the Application panel
33
33
  */
34
34
  url: 'URL',
35
35
  /**
36
- * @description Entry name text in the Back-forward Cache view of the Application panel
36
+ * @description Entry name text in the Back-Forward Cache view of the Application panel
37
37
  */
38
- bfcacheStatus: 'Back-forward Cache Status',
38
+ bfcacheStatus: 'Back-Forward Cache Status',
39
39
  /**
40
- * @description Status text for the status of the back-forward cache status
40
+ * @description Status text for the status of the Back-Forward Cache status
41
41
  */
42
42
  unknown: 'unknown',
43
43
  /**
44
- * @description Status text for the status of the back-forward cache status indicating that
45
- * the back-forward cache was not used and a normal navigation occured instead.
44
+ * @description Status text for the status of the Back-Forward Cache status indicating that
45
+ * the Back-Forward Cache was not used and a normal navigation occured instead.
46
46
  */
47
- normalNavigation: 'Normal navigation (Not restored from back-forward cache)',
47
+ normalNavigation: 'Normal navigation (Not restored from Back-Forward Cache)',
48
48
  /**
49
- * @description Status text for the status of the back-forward cache status indicating that
50
- * the back-forward cache was used to restore the page instead of reloading it.
49
+ * @description Status text for the status of the Back-Forward Cache status indicating that
50
+ * the Back-Forward Cache was used to restore the page instead of reloading it.
51
51
  */
52
- restoredFromBFCache: 'Restored from back-forward cache',
52
+ restoredFromBFCache: 'Restored from Back-Forward Cache',
53
53
  /**
54
54
  * @description Label for a list of reasons which prevent the page from being eligible for
55
- * back-forward cache. These reasons are actionable i.e. they can be cleaned up to make the
56
- * page eligible for back-forward cache.
55
+ * Back-Forward Cache. These reasons are actionable i.e. they can be cleaned up to make the
56
+ * page eligible for Back-Forward Cache.
57
57
  */
58
58
  pageSupportNeeded: 'Actionable',
59
59
  /**
60
60
  * @description Explanation for actionable items which prevent the page from being eligible
61
- * for back-forward cache.
61
+ * for Back-Forward Cache.
62
62
  */
63
63
  pageSupportNeededExplanation:
64
- 'These reasons are actionable i.e. they can be cleaned up to make the page eligible for back-forward cache.',
64
+ 'These reasons are actionable i.e. they can be cleaned up to make the page eligible for Back-Forward Cache.',
65
65
  /**
66
66
  * @description Label for a list of reasons which prevent the page from being eligible for
67
- * back-forward cache. These reasons are circumstantial / not actionable i.e. they cannot be
68
- * cleaned up by developers to make the page eligible for back-forward cache.
67
+ * Back-Forward Cache. These reasons are circumstantial / not actionable i.e. they cannot be
68
+ * cleaned up by developers to make the page eligible for Back-Forward Cache.
69
69
  */
70
70
  circumstantial: 'Not Actionable',
71
71
  /**
72
72
  * @description Explanation for circumstantial/non-actionable items which prevent the page from being eligible
73
- * for back-forward cache.
73
+ * for Back-Forward Cache.
74
74
  */
75
75
  circumstantialExplanation:
76
76
  'These reasons are not actionable i.e. caching was prevented by something outside of the direct control of the page.',
77
77
  /**
78
78
  * @description Label for a list of reasons which prevent the page from being eligible for
79
- * back-forward cache. These reasons are pending support by chrome i.e. in a future version
80
- * of chrome they will not prevent back-forward cache usage anymore.
79
+ * Back-Forward Cache. These reasons are pending support by chrome i.e. in a future version
80
+ * of chrome they will not prevent Back-Forward Cache usage anymore.
81
81
  */
82
82
  supportPending: 'Pending Support',
83
83
  /**
@@ -86,10 +86,10 @@ const UIStrings = {
86
86
  runTest: 'Run Test',
87
87
  /**
88
88
  * @description Explanation for 'pending support' items which prevent the page from being eligible
89
- * for back-forward cache.
89
+ * for Back-Forward Cache.
90
90
  */
91
91
  supportPendingExplanation:
92
- 'Chrome support for these reasons is pending i.e. they will not prevent the page from being eligible for back-forward cache in a future version of Chrome.',
92
+ 'Chrome support for these reasons is pending i.e. they will not prevent the page from being eligible for Back-Forward Cache in a future version of Chrome.',
93
93
  };
94
94
  const str_ = i18n.i18n.registerUIStrings('panels/application/BackForwardCacheView.ts', UIStrings);
95
95
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -26,14 +26,14 @@ export class CSPViolationBreakpointsSidebarPane extends CategorizedBreakpointsSi
26
26
  }
27
27
 
28
28
  protected getBreakpointFromPausedDetails(details: SDK.DebuggerModel.DebuggerPausedDetails):
29
- SDK.DOMDebuggerModel.CategorizedBreakpoint|null {
29
+ SDK.CategorizedBreakpoint.CategorizedBreakpoint|null {
30
30
  const breakpointType = details.auxData && details.auxData['violationType'] ? details.auxData['violationType'] : '';
31
31
  const breakpoints = SDK.DOMDebuggerModel.DOMDebuggerManager.instance().cspViolationBreakpoints();
32
32
  const breakpoint = breakpoints.find(x => x.type() === breakpointType);
33
33
  return breakpoint ? breakpoint : null;
34
34
  }
35
35
 
36
- protected toggleBreakpoint(breakpoint: SDK.DOMDebuggerModel.CategorizedBreakpoint, enabled: boolean): void {
36
+ protected toggleBreakpoint(breakpoint: SDK.CategorizedBreakpoint.CategorizedBreakpoint, enabled: boolean): void {
37
37
  breakpoint.setEnabled(enabled);
38
38
  SDK.DOMDebuggerModel.DOMDebuggerManager.instance().updateCSPViolationBreakpoints();
39
39
  }
@@ -24,10 +24,10 @@ export abstract class CategorizedBreakpointsSidebarPane extends UI.Widget.VBox {
24
24
  readonly #viewId: string;
25
25
  readonly #detailsPausedReason: Protocol.Debugger.PausedEventReason;
26
26
  readonly #categories: Map<string, Item>;
27
- readonly #breakpoints: Map<SDK.DOMDebuggerModel.CategorizedBreakpoint, Item>;
27
+ readonly #breakpoints: Map<SDK.CategorizedBreakpoint.CategorizedBreakpoint, Item>;
28
28
  #highlightedElement?: HTMLLIElement;
29
29
  constructor(
30
- categories: string[], breakpoints: SDK.DOMDebuggerModel.CategorizedBreakpoint[], viewId: string,
30
+ categories: string[], breakpoints: SDK.CategorizedBreakpoint.CategorizedBreakpoint[], viewId: string,
31
31
  detailsPausedReason: Protocol.Debugger.PausedEventReason) {
32
32
  super(true);
33
33
  this.#categoriesTreeOutline = new UI.TreeOutline.TreeOutlineInShadow();
@@ -66,7 +66,7 @@ export abstract class CategorizedBreakpointsSidebarPane extends UI.Widget.VBox {
66
66
  return this.#categories;
67
67
  }
68
68
 
69
- get breakpoints(): Map<SDK.DOMDebuggerModel.CategorizedBreakpoint, Item> {
69
+ get breakpoints(): Map<SDK.CategorizedBreakpoint.CategorizedBreakpoint, Item> {
70
70
  return this.#breakpoints;
71
71
  }
72
72
 
@@ -96,7 +96,7 @@ export abstract class CategorizedBreakpointsSidebarPane extends UI.Widget.VBox {
96
96
  this.#categories.set(name, {element: treeElement, checkbox: labelNode.checkboxElement});
97
97
  }
98
98
 
99
- protected createBreakpoint(breakpoint: SDK.DOMDebuggerModel.CategorizedBreakpoint): void {
99
+ protected createBreakpoint(breakpoint: SDK.CategorizedBreakpoint.CategorizedBreakpoint): void {
100
100
  const labelNode = UI.UIUtils.CheckboxLabel.create(breakpoint.title());
101
101
  labelNode.classList.add('source-code');
102
102
  labelNode.checkboxElement.addEventListener('click', this.breakpointCheckboxClicked.bind(this, breakpoint), true);
@@ -124,7 +124,7 @@ export abstract class CategorizedBreakpointsSidebarPane extends UI.Widget.VBox {
124
124
  }
125
125
 
126
126
  protected getBreakpointFromPausedDetails(_details: SDK.DebuggerModel.DebuggerPausedDetails):
127
- SDK.DOMDebuggerModel.CategorizedBreakpoint|null {
127
+ SDK.CategorizedBreakpoint.CategorizedBreakpoint|null {
128
128
  return null;
129
129
  }
130
130
 
@@ -180,11 +180,11 @@ export abstract class CategorizedBreakpointsSidebarPane extends UI.Widget.VBox {
180
180
  }
181
181
  }
182
182
 
183
- protected toggleBreakpoint(breakpoint: SDK.DOMDebuggerModel.CategorizedBreakpoint, enabled: boolean): void {
183
+ protected toggleBreakpoint(breakpoint: SDK.CategorizedBreakpoint.CategorizedBreakpoint, enabled: boolean): void {
184
184
  breakpoint.setEnabled(enabled);
185
185
  }
186
186
 
187
- private breakpointCheckboxClicked(breakpoint: SDK.DOMDebuggerModel.CategorizedBreakpoint): void {
187
+ private breakpointCheckboxClicked(breakpoint: SDK.CategorizedBreakpoint.CategorizedBreakpoint): void {
188
188
  const item = this.#breakpoints.get(breakpoint);
189
189
  if (!item) {
190
190
  return;
@@ -11,10 +11,13 @@ let eventListenerBreakpointsSidebarPaneInstance: EventListenerBreakpointsSidebar
11
11
 
12
12
  export class EventListenerBreakpointsSidebarPane extends CategorizedBreakpointsSidebarPane {
13
13
  private constructor() {
14
- const categories = SDK.DOMDebuggerModel.DOMDebuggerManager.instance().eventListenerBreakpoints().map(
15
- breakpoint => breakpoint.category());
14
+ let breakpoints: SDK.CategorizedBreakpoint.CategorizedBreakpoint[] =
15
+ SDK.DOMDebuggerModel.DOMDebuggerManager.instance().eventListenerBreakpoints();
16
+ const nonDomBreakpoints = SDK.EventBreakpointsModel.EventBreakpointsManager.instance().eventListenerBreakpoints();
17
+ breakpoints = breakpoints.concat(nonDomBreakpoints);
18
+
19
+ const categories = breakpoints.map(breakpoint => breakpoint.category());
16
20
  categories.sort();
17
- const breakpoints = SDK.DOMDebuggerModel.DOMDebuggerManager.instance().eventListenerBreakpoints();
18
21
  super(
19
22
  categories, breakpoints, 'sources.eventListenerBreakpoints', Protocol.Debugger.PausedEventReason.EventListener);
20
23
  }
@@ -27,10 +30,15 @@ export class EventListenerBreakpointsSidebarPane extends CategorizedBreakpointsS
27
30
  }
28
31
 
29
32
  getBreakpointFromPausedDetails(details: SDK.DebuggerModel.DebuggerPausedDetails):
30
- SDK.DOMDebuggerModel.CategorizedBreakpoint|null {
31
- return SDK.DOMDebuggerModel.DOMDebuggerManager.instance().resolveEventListenerBreakpoint(details.auxData as {
33
+ SDK.CategorizedBreakpoint.CategorizedBreakpoint|null {
34
+ const auxData = details.auxData as {
32
35
  eventName: string,
33
36
  targetName: string,
34
- });
37
+ };
38
+ const domBreakpoint = SDK.DOMDebuggerModel.DOMDebuggerManager.instance().resolveEventListenerBreakpoint(auxData);
39
+ if (domBreakpoint) {
40
+ return domBreakpoint;
41
+ }
42
+ return SDK.EventBreakpointsModel.EventBreakpointsManager.instance().resolveEventListenerBreakpoint(auxData);
35
43
  }
36
44
  }
@@ -6,6 +6,7 @@ import * as i18n from '../../../core/i18n/i18n.js';
6
6
  import * as Buttons from '../../../ui/components/buttons/buttons.js';
7
7
  import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
8
8
  import * as IconButton from '../../../ui/components/icon_button/icon_button.js';
9
+ import * as Legacy from '../../../ui/legacy/legacy.js';
9
10
  import * as LitHtml from '../../../ui/lit-html/lit-html.js';
10
11
 
11
12
  import cssOverviewStartViewStyles from './cssOverviewStartView.css.js';
@@ -76,14 +77,12 @@ export class OverviewStartRequestedEvent extends Event {
76
77
  export class CSSOverviewStartView extends HTMLElement {
77
78
  static readonly litTagName = LitHtml.literal`devtools-css-overview-start-view`;
78
79
  readonly #shadow = this.attachShadow({mode: 'open'});
79
- #feedbackLink: HTMLAnchorElement;
80
+ #feedbackLink: HTMLElement;
80
81
 
81
82
  constructor() {
82
83
  super();
83
- this.#feedbackLink = document.createElement('a');
84
- this.#feedbackLink.href = FEEDBACK_LINK;
85
- this.#feedbackLink.target = '_blank';
86
- this.#feedbackLink.innerText = i18nString(UIStrings.feedbackInline);
84
+ this.#feedbackLink =
85
+ Legacy.XLink.XLink.create(FEEDBACK_LINK, i18nString(UIStrings.feedbackInline), 'devtools-link');
87
86
  }
88
87
 
89
88
  connectedCallback(): void {
@@ -106,7 +105,6 @@ export class CSSOverviewStartView extends HTMLElement {
106
105
  private render(): void {
107
106
  // Disabled until https://crbug.com/1079231 is fixed.
108
107
  // clang-format off
109
- // eslint-disable-next-line rulesdir/ban_a_tags_in_lit_html
110
108
  render(html`
111
109
  <div class="css-overview-start-view">
112
110
  <h1 class="summary-header">${i18nString(UIStrings.identifyCSSImprovements)}</h1>
@@ -144,11 +142,11 @@ export class CSSOverviewStartView extends HTMLElement {
144
142
  </div>
145
143
  <div>
146
144
  <h1 class="video-doc-header">${i18nString(UIStrings.videoAndDocumentation)}</h1>
147
- <a href=${DOC_LINK} target="_blank">${i18nString(UIStrings.quickStartWithCSSOverview)}</a>
145
+ <x-link class="devtools-link" href=${DOC_LINK}>${i18nString(UIStrings.quickStartWithCSSOverview)}</x-link>
148
146
  </div>
149
147
  </div>
150
148
  </section>
151
- <a class="feedback-standalone" href=${FEEDBACK_LINK} target="_blank">${i18nString(UIStrings.feedbackStandalone)}</a>
149
+ <x-link class="feedback-standalone" href=${FEEDBACK_LINK}>${i18nString(UIStrings.feedbackStandalone)}</x-link>
152
150
  </div>
153
151
  `, this.#shadow, {
154
152
  host: this,
@@ -95,6 +95,12 @@ h1 {
95
95
  margin-bottom: 24px;
96
96
  }
97
97
 
98
+ .feedback-prompt .devtools-link {
99
+ color: -webkit-link;
100
+ cursor: pointer;
101
+ text-decoration: underline;
102
+ }
103
+
98
104
  .resources {
99
105
  display: flex;
100
106
  flex-direction: row;
@@ -125,7 +131,7 @@ h1 {
125
131
  font-weight: bold;
126
132
  }
127
133
 
128
- .resources a {
134
+ .resources .devtools-link {
129
135
  font-size: 14px;
130
136
  line-height: 22px;
131
137
  letter-spacing: 0.04em;
@@ -1827,7 +1827,8 @@ export class StylePropertiesSection {
1827
1827
  containerElement.data = {
1828
1828
  container: ElementsComponents.Helper.legacyNodeToElementsComponentsNode(container.containerNode),
1829
1829
  queryName: containerQuery.name,
1830
- onContainerLinkClick: (): void => {
1830
+ onContainerLinkClick: (event): void => {
1831
+ event.preventDefault();
1831
1832
  ElementsPanel.instance().revealAndSelectNode(container.containerNode, true, true);
1832
1833
  container.containerNode.scrollIntoView();
1833
1834
  },
@@ -14,10 +14,17 @@ import * as Components from './components/components.js';
14
14
 
15
15
  const UIStrings = {
16
16
  /**
17
- * @description Menu entry for hiding all current issues belonging to a particular kind.
18
- * @example {Page Errors} PH1
17
+ * @description Menu entry for hiding all current Page Errors.
19
18
  */
20
- hideAllCurrent: 'Hide all current {PH1}',
19
+ hideAllCurrentPageErrors: 'Hide all current Page Errors',
20
+ /**
21
+ * @description Menu entry for hiding all current Breaking Changes.
22
+ */
23
+ hideAllCurrentBreakingChanges: 'Hide all current Breaking Changes',
24
+ /**
25
+ * @description Menu entry for hiding all current Page Errors.
26
+ */
27
+ hideAllCurrentImprovements: 'Hide all current Improvements',
21
28
  };
22
29
  const str_ = i18n.i18n.registerUIStrings('panels/issues/IssueKindView.ts', UIStrings);
23
30
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -70,6 +77,17 @@ export class IssueKindView extends UI.TreeOutline.TreeElement {
70
77
  return this.kind;
71
78
  }
72
79
 
80
+ getHideAllCurrentKindString(): Common.UIString.LocalizedString {
81
+ switch (this.kind) {
82
+ case IssuesManager.Issue.IssueKind.PageError:
83
+ return i18nString(UIStrings.hideAllCurrentPageErrors);
84
+ case IssuesManager.Issue.IssueKind.Improvement:
85
+ return i18nString(UIStrings.hideAllCurrentImprovements);
86
+ case IssuesManager.Issue.IssueKind.BreakingChange:
87
+ return i18nString(UIStrings.hideAllCurrentBreakingChanges);
88
+ }
89
+ }
90
+
73
91
  private appendHeader(): void {
74
92
  const header = document.createElement('div');
75
93
  header.classList.add('header');
@@ -93,7 +111,7 @@ export class IssueKindView extends UI.TreeOutline.TreeElement {
93
111
  const hideAvailableIssuesBtn = new Components.HideIssuesMenu.HideIssuesMenu();
94
112
  hideAvailableIssuesBtn.classList.add('hide-available-issues');
95
113
  hideAvailableIssuesBtn.data = {
96
- menuItemLabel: i18nString(UIStrings.hideAllCurrent, {PH1: IssuesManager.Issue.getIssueKindName(this.kind)}),
114
+ menuItemLabel: this.getHideAllCurrentKindString(),
97
115
  menuItemAction: (): void => {
98
116
  const setting = IssuesManager.IssuesManager.getHideIssueByCodeSetting();
99
117
  const values = setting.get();
@@ -262,42 +262,19 @@ export class LighthouseController extends Common.ObjectWrapper.ObjectWrapper<Eve
262
262
  return '';
263
263
  }
264
264
  const mainTarget = this.manager.target();
265
- const runtimeModel = mainTarget.model(SDK.RuntimeModel.RuntimeModel);
266
- const executionContext = runtimeModel && runtimeModel.defaultExecutionContext();
267
- let inspectedURL = mainTarget.inspectedURL();
268
- if (!executionContext) {
269
- return inspectedURL;
270
- }
265
+ // target.inspectedURL is reliably populated, however it lacks any url #hash
266
+ const inspectedURL = mainTarget.inspectedURL();
271
267
 
272
- // Evaluate location.href for a more specific URL than inspectedURL provides so that SPA hash navigation routes
273
- // will be respected and audited.
274
- try {
275
- const result = await executionContext.evaluate(
276
- {
277
- expression: 'window.location.href',
278
- objectGroup: 'lighthouse',
279
- includeCommandLineAPI: false,
280
- silent: false,
281
- returnByValue: true,
282
- generatePreview: false,
283
- allowUnsafeEvalBlockedByCSP: undefined,
284
- disableBreaks: undefined,
285
- replMode: undefined,
286
- throwOnSideEffect: undefined,
287
- timeout: undefined,
288
- },
289
- /* userGesture */ false, /* awaitPromise */ false);
290
- if ((!('exceptionDetails' in result) || !result.exceptionDetails) && 'object' in result && result.object) {
291
- if (result.object.value) {
292
- inspectedURL = result.object.value;
293
- }
294
- result.object.release();
295
- }
296
- } catch (err) {
297
- console.error(err);
268
+ // We'll use the navigationHistory to acquire the current URL including hash
269
+ const resourceTreeModel = mainTarget.model(SDK.ResourceTreeModel.ResourceTreeModel);
270
+ const navHistory = resourceTreeModel && await resourceTreeModel.navigationHistory();
271
+ if (!resourceTreeModel || !navHistory) {
272
+ return inspectedURL;
298
273
  }
299
274
 
300
- return inspectedURL;
275
+ const {currentIndex, entries} = navHistory;
276
+ const navigationEntry = entries[currentIndex];
277
+ return navigationEntry.url;
301
278
  }
302
279
 
303
280
  getFlags(): {internalDisableDeviceScreenEmulation: boolean, emulatedFormFactor: (string|undefined)} {
@@ -263,7 +263,8 @@ export class LighthousePanel extends UI.Panel.Panel {
263
263
 
264
264
  const reportContainer = this.auditResultsElement.createChild('div', 'lh-vars lh-root lh-devtools');
265
265
 
266
- const dom = new LighthouseReport.DOM(this.auditResultsElement.ownerDocument as Document);
266
+ // @ts-ignore: Second argument will soon be required.
267
+ const dom = new LighthouseReport.DOM(this.auditResultsElement.ownerDocument as Document, reportContainer);
267
268
  const renderer = new LighthouseReportRenderer(dom) as LighthouseReport.ReportRenderer;
268
269
 
269
270
  const el = renderer.renderReport(lighthouseResult, reportContainer);
@@ -221,8 +221,9 @@ export class LighthouseReportUIFeatures extends LighthouseReport.ReportUIFeature
221
221
  }
222
222
 
223
223
  getDocument(): Document {
224
- return this._document;
224
+ return this._dom.document();
225
225
  }
226
+
226
227
  resetUIState(): void {
227
228
  this._resetUIState();
228
229
  }
@@ -958,11 +958,24 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
958
958
  (initiatorLink as HTMLElement).focus();
959
959
  }
960
960
  }
961
+
961
962
  if (isEnterOrSpaceKey(event)) {
962
963
  this.dispatchEventToListeners(Events.RequestActivated, {showPanel: true, takeFocus: true});
963
964
  event.consume(true);
964
965
  }
965
966
  });
967
+ this.dataGrid.element.addEventListener('keyup', event => {
968
+ if ((event.key === 'r' || event.key === 'R') && this.dataGrid.selectedNode) {
969
+ const request = (this.dataGrid.selectedNode as NetworkNode).request();
970
+ if (!request) {
971
+ return;
972
+ }
973
+
974
+ if (SDK.NetworkManager.NetworkManager.canReplayRequest(request)) {
975
+ SDK.NetworkManager.NetworkManager.replayRequest(request);
976
+ }
977
+ }
978
+ });
966
979
  this.dataGrid.element.addEventListener('focus', this.onDataGridFocus.bind(this), true);
967
980
  this.dataGrid.element.addEventListener('blur', this.onDataGridBlur.bind(this), true);
968
981
  return this.dataGrid;
@@ -1535,6 +1548,8 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
1535
1548
  footerSection.appendItem(i18nString(UIStrings.copyAllAsCurlCmd), this.copyAllCurlCommand.bind(this, 'win'));
1536
1549
  footerSection.appendItem(i18nString(UIStrings.copyAllAsCurlBash), this.copyAllCurlCommand.bind(this, 'unix'));
1537
1550
  } else {
1551
+ footerSection.appendItem(
1552
+ i18nString(UIStrings.copyAsPowershell), this.copyPowerShellCommand.bind(this, request), disableIfBlob);
1538
1553
  footerSection.appendItem(
1539
1554
  i18nString(UIStrings.copyAsFetch), this.copyFetchCall.bind(this, request, FetchStyle.Browser),
1540
1555
  disableIfBlob);
@@ -1543,6 +1558,7 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
1543
1558
  disableIfBlob);
1544
1559
  footerSection.appendItem(
1545
1560
  i18nString(UIStrings.copyAsCurl), this.copyCurlCommand.bind(this, request, 'unix'), disableIfBlob);
1561
+ footerSection.appendItem(i18nString(UIStrings.copyAllAsPowershell), this.copyAllPowerShellCommand.bind(this));
1546
1562
  footerSection.appendItem(
1547
1563
  i18nString(UIStrings.copyAllAsFetch), this.copyAllFetchCall.bind(this, FetchStyle.Browser));
1548
1564
  footerSection.appendItem(
@@ -491,6 +491,8 @@ export class RequestPayloadView extends UI.Widget.VBox {
491
491
  private createToggleButton(title: string): Element {
492
492
  const button = document.createElement('span');
493
493
  button.classList.add('payload-toggle');
494
+ button.tabIndex = 0;
495
+ button.setAttribute('role', 'button');
494
496
  button.textContent = title;
495
497
  return button;
496
498
  }
@@ -64,6 +64,11 @@
64
64
  color: var(--color-text-primary);
65
65
  }
66
66
 
67
+ .tree-outline li.expanded .payload-toggle:focus-visible {
68
+ border: 2px solid var(--color-button-outline-focus);
69
+ border-radius: 5px;
70
+ }
71
+
67
72
  .tree-outline li .header-toggle:hover {
68
73
  color: var(--color-text-secondary);
69
74
  cursor: pointer;
@@ -142,6 +142,7 @@ export class ProtocolMonitorImpl extends UI.Widget.VBox {
142
142
  clearButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, () => {
143
143
  this.messages = [];
144
144
  this.dataGridIntegrator.update({...this.dataGridIntegrator.data(), rows: []});
145
+ this.infoWidget.render(null);
145
146
  });
146
147
  topToolbar.appendToolbarItem(clearButton);
147
148