chrome-devtools-frontend 1.0.1022059 → 1.0.1022611

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.
@@ -6797,6 +6797,9 @@
6797
6797
  "panels/network/BlockedURLsPane.ts | textPatternToBlockMatching": {
6798
6798
  "message": "Text pattern to block matching requests; use * for wildcard"
6799
6799
  },
6800
+ "panels/network/components/RequestHeadersView.ts | chooseThisOptionIfTheResourceAnd": {
6801
+ "message": "Choose this option if the resource and the document are served from the same site."
6802
+ },
6800
6803
  "panels/network/components/RequestHeadersView.ts | fromDiskCache": {
6801
6804
  "message": "(from disk cache)"
6802
6805
  },
@@ -6818,6 +6821,15 @@
6818
6821
  "panels/network/components/RequestHeadersView.ts | general": {
6819
6822
  "message": "General"
6820
6823
  },
6824
+ "panels/network/components/RequestHeadersView.ts | learnMore": {
6825
+ "message": "Learn more"
6826
+ },
6827
+ "panels/network/components/RequestHeadersView.ts | learnMoreInTheIssuesTab": {
6828
+ "message": "Learn more in the issues tab"
6829
+ },
6830
+ "panels/network/components/RequestHeadersView.ts | onlyChooseThisOptionIfAn": {
6831
+ "message": "Only choose this option if an arbitrary website including this resource does not impose a security risk."
6832
+ },
6821
6833
  "panels/network/components/RequestHeadersView.ts | raw": {
6822
6834
  "message": "Raw"
6823
6835
  },
@@ -6845,6 +6857,21 @@
6845
6857
  "panels/network/components/RequestHeadersView.ts | statusCode": {
6846
6858
  "message": "Status Code"
6847
6859
  },
6860
+ "panels/network/components/RequestHeadersView.ts | thisDocumentWasBlockedFrom": {
6861
+ "message": "This document was blocked from loading in an iframe with a sandbox attribute because this document specified a cross-origin opener policy."
6862
+ },
6863
+ "panels/network/components/RequestHeadersView.ts | toEmbedThisFrameInYourDocument": {
6864
+ "message": "To embed this frame in your document, the response needs to enable the cross-origin embedder policy by specifying the following response header:"
6865
+ },
6866
+ "panels/network/components/RequestHeadersView.ts | toUseThisResourceFromADifferent": {
6867
+ "message": "To use this resource from a different origin, the server needs to specify a cross-origin resource policy in the response headers:"
6868
+ },
6869
+ "panels/network/components/RequestHeadersView.ts | toUseThisResourceFromADifferentOrigin": {
6870
+ "message": "To use this resource from a different origin, the server may relax the cross-origin resource policy response header:"
6871
+ },
6872
+ "panels/network/components/RequestHeadersView.ts | toUseThisResourceFromADifferentSite": {
6873
+ "message": "To use this resource from a different site, the server may relax the cross-origin resource policy response header:"
6874
+ },
6848
6875
  "panels/network/components/RequestTrustTokensView.ts | aClientprovidedArgumentWas": {
6849
6876
  "message": "A client-provided argument was malformed or otherwise invalid."
6850
6877
  },
@@ -9650,6 +9677,9 @@
9650
9677
  "panels/sources/AddSourceMapURLDialog.ts | add": {
9651
9678
  "message": "Add"
9652
9679
  },
9680
+ "panels/sources/AddSourceMapURLDialog.ts | debugInfoUrl": {
9681
+ "message": "DWARF symbols URL: "
9682
+ },
9653
9683
  "panels/sources/AddSourceMapURLDialog.ts | sourceMapUrl": {
9654
9684
  "message": "Source map URL: "
9655
9685
  },
@@ -9821,6 +9851,9 @@
9821
9851
  "panels/sources/DebuggerPlugin.ts | addSourceMap": {
9822
9852
  "message": "Add source map…"
9823
9853
  },
9854
+ "panels/sources/DebuggerPlugin.ts | addWasmDebugInfo": {
9855
+ "message": "Add DWARF debug info…"
9856
+ },
9824
9857
  "panels/sources/DebuggerPlugin.ts | associatedFilesAreAvailable": {
9825
9858
  "message": "Associated files are available via file tree or {PH1}."
9826
9859
  },
@@ -6797,6 +6797,9 @@
6797
6797
  "panels/network/BlockedURLsPane.ts | textPatternToBlockMatching": {
6798
6798
  "message": "T̂éx̂t́ p̂át̂t́êŕn̂ t́ô b́l̂óĉḱ m̂át̂ćĥín̂ǵ r̂éq̂úêśt̂ś; ûśê * f́ôŕ ŵíl̂d́ĉár̂d́"
6799
6799
  },
6800
+ "panels/network/components/RequestHeadersView.ts | chooseThisOptionIfTheResourceAnd": {
6801
+ "message": "Ĉh́ôóŝé t̂h́îś ôṕt̂íôń îf́ t̂h́ê ŕêśôúr̂ćê án̂d́ t̂h́ê d́ôćûḿêńt̂ ár̂é ŝér̂v́êd́ f̂ŕôḿ t̂h́ê śâḿê śît́ê."
6802
+ },
6800
6803
  "panels/network/components/RequestHeadersView.ts | fromDiskCache": {
6801
6804
  "message": "(f̂ŕôḿ d̂íŝḱ ĉáĉh́ê)"
6802
6805
  },
@@ -6818,6 +6821,15 @@
6818
6821
  "panels/network/components/RequestHeadersView.ts | general": {
6819
6822
  "message": "Ĝén̂ér̂ál̂"
6820
6823
  },
6824
+ "panels/network/components/RequestHeadersView.ts | learnMore": {
6825
+ "message": "L̂éâŕn̂ ḿôŕê"
6826
+ },
6827
+ "panels/network/components/RequestHeadersView.ts | learnMoreInTheIssuesTab": {
6828
+ "message": "L̂éâŕn̂ ḿôŕê ín̂ t́ĥé îśŝúêś t̂áb̂"
6829
+ },
6830
+ "panels/network/components/RequestHeadersView.ts | onlyChooseThisOptionIfAn": {
6831
+ "message": "Ôńl̂ý ĉh́ôóŝé t̂h́îś ôṕt̂íôń îf́ âń âŕb̂ít̂ŕâŕŷ ẃêb́ŝít̂é îńĉĺûd́îńĝ t́ĥíŝ ŕêśôúr̂ćê d́ôéŝ ńôt́ îḿp̂óŝé â śêćûŕît́ŷ ŕîśk̂."
6832
+ },
6821
6833
  "panels/network/components/RequestHeadersView.ts | raw": {
6822
6834
  "message": "R̂áŵ"
6823
6835
  },
@@ -6845,6 +6857,21 @@
6845
6857
  "panels/network/components/RequestHeadersView.ts | statusCode": {
6846
6858
  "message": "Ŝt́ât́ûś Ĉód̂é"
6847
6859
  },
6860
+ "panels/network/components/RequestHeadersView.ts | thisDocumentWasBlockedFrom": {
6861
+ "message": "T̂h́îś d̂óĉúm̂én̂t́ ŵáŝ b́l̂óĉḱêd́ f̂ŕôḿ l̂óâd́îńĝ ín̂ án̂ iframe ẃît́ĥ á sandbox ât́t̂ŕîb́ût́ê b́êćâúŝé t̂h́îś d̂óĉúm̂én̂t́ ŝṕêćîf́îéd̂ á ĉŕôśŝ-ór̂íĝín̂ óp̂én̂ér̂ ṕôĺîćŷ."
6862
+ },
6863
+ "panels/network/components/RequestHeadersView.ts | toEmbedThisFrameInYourDocument": {
6864
+ "message": "T̂ó êḿb̂éd̂ t́ĥíŝ f́r̂ám̂é îń ŷóûŕ d̂óĉúm̂én̂t́, t̂h́ê ŕêśp̂ón̂śê ńêéd̂ś t̂ó êńâb́l̂é t̂h́ê ćr̂óŝś-ôŕîǵîń êḿb̂éd̂d́êŕ p̂ól̂íĉý b̂ý ŝṕêćîf́ŷín̂ǵ t̂h́ê f́ôĺl̂óŵín̂ǵ r̂éŝṕôńŝé ĥéâd́êŕ:"
6865
+ },
6866
+ "panels/network/components/RequestHeadersView.ts | toUseThisResourceFromADifferent": {
6867
+ "message": "T̂ó ûśê t́ĥíŝ ŕêśôúr̂ćê f́r̂óm̂ á d̂íf̂f́êŕêńt̂ ór̂íĝín̂, t́ĥé ŝér̂v́êŕ n̂éêd́ŝ t́ô śp̂éĉíf̂ý â ćr̂óŝś-ôŕîǵîń r̂éŝóûŕĉé p̂ól̂íĉý îń t̂h́ê ŕêśp̂ón̂śê h́êád̂ér̂ś:"
6868
+ },
6869
+ "panels/network/components/RequestHeadersView.ts | toUseThisResourceFromADifferentOrigin": {
6870
+ "message": "T̂ó ûśê t́ĥíŝ ŕêśôúr̂ćê f́r̂óm̂ á d̂íf̂f́êŕêńt̂ ór̂íĝín̂, t́ĥé ŝér̂v́êŕ m̂áŷ ŕêĺâx́ t̂h́ê ćr̂óŝś-ôŕîǵîń r̂éŝóûŕĉé p̂ól̂íĉý r̂éŝṕôńŝé ĥéâd́êŕ:"
6871
+ },
6872
+ "panels/network/components/RequestHeadersView.ts | toUseThisResourceFromADifferentSite": {
6873
+ "message": "T̂ó ûśê t́ĥíŝ ŕêśôúr̂ćê f́r̂óm̂ á d̂íf̂f́êŕêńt̂ śît́ê, t́ĥé ŝér̂v́êŕ m̂áŷ ŕêĺâx́ t̂h́ê ćr̂óŝś-ôŕîǵîń r̂éŝóûŕĉé p̂ól̂íĉý r̂éŝṕôńŝé ĥéâd́êŕ:"
6874
+ },
6848
6875
  "panels/network/components/RequestTrustTokensView.ts | aClientprovidedArgumentWas": {
6849
6876
  "message": "Â ćl̂íêńt̂-ṕr̂óv̂íd̂éd̂ ár̂ǵûḿêńt̂ ẃâś m̂ál̂f́ôŕm̂éd̂ ór̂ ót̂h́êŕŵíŝé îńv̂ál̂íd̂."
6850
6877
  },
@@ -9650,6 +9677,9 @@
9650
9677
  "panels/sources/AddSourceMapURLDialog.ts | add": {
9651
9678
  "message": "Âd́d̂"
9652
9679
  },
9680
+ "panels/sources/AddSourceMapURLDialog.ts | debugInfoUrl": {
9681
+ "message": "D̂ẂÂŔF̂ śŷḿb̂ól̂ś ÛŔL̂: "
9682
+ },
9653
9683
  "panels/sources/AddSourceMapURLDialog.ts | sourceMapUrl": {
9654
9684
  "message": "Ŝóûŕĉé m̂áp̂ ÚR̂Ĺ: "
9655
9685
  },
@@ -9821,6 +9851,9 @@
9821
9851
  "panels/sources/DebuggerPlugin.ts | addSourceMap": {
9822
9852
  "message": "Âd́d̂ śôúr̂ćê ḿâṕ…"
9823
9853
  },
9854
+ "panels/sources/DebuggerPlugin.ts | addWasmDebugInfo": {
9855
+ "message": "Âd́d̂ D́ŴÁR̂F́ d̂éb̂úĝ ín̂f́ô…"
9856
+ },
9824
9857
  "panels/sources/DebuggerPlugin.ts | associatedFilesAreAvailable": {
9825
9858
  "message": "Âśŝóĉíât́êd́ f̂íl̂éŝ ár̂é âv́âíl̂áb̂ĺê v́îá f̂íl̂é t̂ŕêé ôŕ {PH1}."
9826
9859
  },
@@ -737,6 +737,14 @@ export class DebuggerModel extends SDKModel<EventTypes> {
737
737
  this.#sourceMapManagerInternal.attachSourceMap(script, script.sourceURL, script.sourceMapURL);
738
738
  }
739
739
 
740
+ async setDebugInfoURL(script: Script, _externalURL: Platform.DevToolsPath.UrlString): Promise<void> {
741
+ if (this.#expandCallFramesCallback && this.#debuggerPausedDetailsInternal) {
742
+ this.#debuggerPausedDetailsInternal.callFrames =
743
+ await this.#expandCallFramesCallback.call(null, this.#debuggerPausedDetailsInternal.callFrames);
744
+ }
745
+ this.dispatchEventToListeners(Events.DebugInfoAttached, script);
746
+ }
747
+
740
748
  executionContextDestroyed(executionContext: ExecutionContext): void {
741
749
  const sourceMapIds = Array.from(this.#sourceMapIdToScript.keys());
742
750
  for (const sourceMapId of sourceMapIds) {
@@ -968,6 +976,7 @@ export enum Events {
968
976
  DebuggerWasDisabled = 'DebuggerWasDisabled',
969
977
  DebuggerPaused = 'DebuggerPaused',
970
978
  DebuggerResumed = 'DebuggerResumed',
979
+ DebugInfoAttached = 'DebugInfoAttached',
971
980
  ParsedScriptSource = 'ParsedScriptSource',
972
981
  DiscardedAnonymousScriptSource = 'DiscardedAnonymousScriptSource',
973
982
  GlobalObjectCleared = 'GlobalObjectCleared',
@@ -985,6 +994,7 @@ export type EventTypes = {
985
994
  [Events.GlobalObjectCleared]: DebuggerModel,
986
995
  [Events.CallFrameSelected]: DebuggerModel,
987
996
  [Events.DebuggerIsReadyToPause]: DebuggerModel,
997
+ [Events.DebugInfoAttached]: Script,
988
998
  };
989
999
 
990
1000
  class DebuggerDispatcher implements ProtocolProxyApi.DebuggerDispatcher {
@@ -1200,6 +1200,15 @@ export class DebuggerLanguagePluginManager implements
1200
1200
  return [];
1201
1201
  }
1202
1202
 
1203
+ setDebugInfoURL(script: SDK.Script.Script, externalURL: Platform.DevToolsPath.UrlString): void {
1204
+ if (this.hasPluginForScript(script)) {
1205
+ return;
1206
+ }
1207
+ script.debugSymbols = {type: Protocol.Debugger.DebugSymbolsType.ExternalDWARF, externalURL};
1208
+ this.parsedScriptSource({data: script});
1209
+ void script.debuggerModel.setDebugInfoURL(script, externalURL);
1210
+ }
1211
+
1203
1212
  private parsedScriptSource(event: Common.EventTarget.EventTargetEvent<SDK.Script.Script>): void {
1204
1213
  const script = event.data;
1205
1214
  if (!script.sourceURL) {
@@ -38,7 +38,8 @@ import * as Workspace from '../workspace/workspace.js';
38
38
  import type {Breakpoint} from './BreakpointManager.js';
39
39
  import {BreakpointManager} from './BreakpointManager.js';
40
40
  import {ContentProviderBasedProject} from './ContentProviderBasedProject.js';
41
- import type {DebuggerSourceMapping, DebuggerWorkspaceBinding} from './DebuggerWorkspaceBinding.js';
41
+ import type {DebuggerSourceMapping} from './DebuggerWorkspaceBinding.js';
42
+ import {DebuggerWorkspaceBinding} from './DebuggerWorkspaceBinding.js';
42
43
  import {NetworkProject} from './NetworkProject.js';
43
44
  import {metadataForURL} from './ResourceUtils.js';
44
45
 
@@ -455,6 +456,16 @@ export class ResourceScriptFile extends Common.ObjectWrapper.ObjectWrapper<Resou
455
456
  this.scriptInternal.debuggerModel.setSourceMapURL(this.scriptInternal, sourceMapURL);
456
457
  }
457
458
 
459
+ addDebugInfoURL(debugInfoURL: Platform.DevToolsPath.UrlString): void {
460
+ if (!this.scriptInternal) {
461
+ return;
462
+ }
463
+ const {pluginManager} = DebuggerWorkspaceBinding.instance();
464
+ if (pluginManager) {
465
+ pluginManager.setDebugInfoURL(this.scriptInternal, debugInfoURL);
466
+ }
467
+ }
468
+
458
469
  hasSourceMapURL(): boolean {
459
470
  return this.scriptInternal !== undefined && Boolean(this.scriptInternal.sourceMapURL);
460
471
  }
@@ -7,7 +7,7 @@ import * as SDK from '../../core/sdk/sdk.js';
7
7
  import type {Issue, IssueCategory} from './Issue.js';
8
8
  import {IssuesManager} from './IssuesManager.js';
9
9
 
10
- export type IssuesAssociatable = SDK.NetworkRequest.NetworkRequest|SDK.Cookie.Cookie|string;
10
+ export type IssuesAssociatable = Readonly<SDK.NetworkRequest.NetworkRequest>|SDK.Cookie.Cookie|string;
11
11
 
12
12
  function issuesAssociatedWithNetworkRequest(issues: Issue[], request: SDK.NetworkRequest.NetworkRequest): Issue[] {
13
13
  return issues.filter(issue => {
@@ -1 +1 @@
1
- # Error retrieving an id token.
1
+ # Error retrieving a token.
@@ -1 +1 @@
1
- # The id token fetching request is invalid.
1
+ # The token fetching request is invalid.
@@ -1 +1 @@
1
- # Provider's id token is invalid.
1
+ # Provider's token is invalid.
@@ -1 +1 @@
1
- # The response body is empty when fetching the provider's id token.
1
+ # The response body is empty when fetching the provider's token.
@@ -109,3 +109,58 @@ div.raw-headers-row {
109
109
  white-space: pre-wrap;
110
110
  word-break: break-all;
111
111
  }
112
+
113
+ .header-badge-text {
114
+ font-variant: small-caps;
115
+ font-weight: 500;
116
+ white-space: pre-wrap;
117
+ word-break: break-all;
118
+ }
119
+
120
+ .header-badge {
121
+ display: inline;
122
+ margin-right: 0.75em;
123
+ background-color: var(--color-accent-red);
124
+ color: var(--color-background);
125
+ border-radius: 100vh;
126
+ padding-left: 6px;
127
+ padding-right: 6px;
128
+ }
129
+
130
+ .call-to-action {
131
+ background-color: var(--color-background-elevation-1);
132
+ padding: 8px;
133
+ border-radius: 2px;
134
+ }
135
+
136
+ .call-to-action-body {
137
+ padding: 6px 0;
138
+ margin-left: 9.5px;
139
+ border-left: 2px solid var(--issue-color-yellow);
140
+ padding-left: 18px;
141
+ line-height: 20px;
142
+ }
143
+
144
+ .call-to-action .explanation {
145
+ font-weight: bold;
146
+ }
147
+
148
+ .call-to-action code {
149
+ font-size: 90%;
150
+ }
151
+
152
+ .call-to-action .example .comment::before {
153
+ content: " — ";
154
+ }
155
+
156
+ .link,
157
+ .devtools-link {
158
+ color: var(--color-link);
159
+ text-decoration: underline;
160
+ cursor: pointer;
161
+ padding: 2px 0; /* adjust focus ring size */
162
+ }
163
+
164
+ .inline-icon {
165
+ vertical-align: middle;
166
+ }
@@ -3,11 +3,16 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as Common from '../../../core/common/common.js';
6
+ import * as Host from '../../../core/host/host.js';
6
7
  import * as i18n from '../../../core/i18n/i18n.js';
8
+ import * as Platform from '../../../core/platform/platform.js';
7
9
  import {assertNotNullOrUndefined} from '../../../core/platform/platform.js';
8
10
  import * as SDK from '../../../core/sdk/sdk.js';
11
+ import * as Protocol from '../../../generated/protocol.js';
12
+ import * as IssuesManager from '../../../models/issues_manager/issues_manager.js';
9
13
  import * as Buttons from '../../../ui/components/buttons/buttons.js';
10
14
  import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
15
+ import * as IconButton from '../../../ui/components/icon_button/icon_button.js';
11
16
  import * as Input from '../../../ui/components/input/input.js';
12
17
  import * as UI from '../../../ui/legacy/legacy.js';
13
18
  import * as LitHtml from '../../../ui/lit-html/lit-html.js';
@@ -19,6 +24,11 @@ const {render, html} = LitHtml;
19
24
 
20
25
  const UIStrings = {
21
26
  /**
27
+ *@description Text in Headers View of the Network panel
28
+ */
29
+ chooseThisOptionIfTheResourceAnd:
30
+ 'Choose this option if the resource and the document are served from the same site.',
31
+ /**
22
32
  *@description Text in Request Headers View of the Network panel
23
33
  */
24
34
  fromDiskCache: '(from disk cache)',
@@ -47,10 +57,23 @@ const UIStrings = {
47
57
  */
48
58
  general: 'General',
49
59
  /**
60
+ *@description Text that is usually a hyperlink to more documentation
61
+ */
62
+ learnMore: 'Learn more',
63
+ /**
64
+ *@description Text for a link to the issues panel
65
+ */
66
+ learnMoreInTheIssuesTab: 'Learn more in the issues tab',
67
+ /**
50
68
  *@description Label for a checkbox to switch between raw and parsed headers
51
69
  */
52
70
  raw: 'Raw',
53
71
  /**
72
+ *@description Text in Headers View of the Network panel
73
+ */
74
+ onlyChooseThisOptionIfAn:
75
+ 'Only choose this option if an arbitrary website including this resource does not impose a security risk.',
76
+ /**
54
77
  *@description Text in Request Headers View of the Network panel
55
78
  */
56
79
  referrerPolicy: 'Referrer Policy',
@@ -82,9 +105,35 @@ const UIStrings = {
82
105
  *@description HTTP response code
83
106
  */
84
107
  statusCode: 'Status Code',
108
+ /**
109
+ *@description Text in Headers View of the Network panel
110
+ */
111
+ thisDocumentWasBlockedFrom:
112
+ 'This document was blocked from loading in an `iframe` with a `sandbox` attribute because this document specified a cross-origin opener policy.',
113
+ /**
114
+ *@description Text in Headers View of the Network panel
115
+ */
116
+ toEmbedThisFrameInYourDocument:
117
+ 'To embed this frame in your document, the response needs to enable the cross-origin embedder policy by specifying the following response header:',
118
+ /**
119
+ *@description Text in Headers View of the Network panel
120
+ */
121
+ toUseThisResourceFromADifferent:
122
+ 'To use this resource from a different origin, the server needs to specify a cross-origin resource policy in the response headers:',
123
+ /**
124
+ *@description Text in Headers View of the Network panel
125
+ */
126
+ toUseThisResourceFromADifferentOrigin:
127
+ 'To use this resource from a different origin, the server may relax the cross-origin resource policy response header:',
128
+ /**
129
+ *@description Text in Headers View of the Network panel
130
+ */
131
+ toUseThisResourceFromADifferentSite:
132
+ 'To use this resource from a different site, the server may relax the cross-origin resource policy response header:',
85
133
  };
86
134
  const str_ = i18n.i18n.registerUIStrings('panels/network/components/RequestHeadersView.ts', UIStrings);
87
135
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
136
+ const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
88
137
 
89
138
  export class RequestHeadersView extends UI.Widget.VBox {
90
139
  readonly #headersView = new RequestHeadersComponent();
@@ -152,6 +201,39 @@ export class RequestHeadersComponent extends HTMLElement {
152
201
  #renderResponseHeaders(): LitHtml.TemplateResult {
153
202
  assertNotNullOrUndefined(this.#request);
154
203
 
204
+ const headersWithIssues = [];
205
+ if (this.#request.wasBlocked()) {
206
+ const headerWithIssues =
207
+ BlockedReasonDetails.get((this.#request.blockedReason() as Protocol.Network.BlockedReason));
208
+ if (headerWithIssues) {
209
+ headersWithIssues.push(headerWithIssues);
210
+ }
211
+ }
212
+
213
+ function mergeHeadersWithIssues(
214
+ headers: SDK.NetworkRequest.NameValue[], headersWithIssues: HeaderDescriptor[]): HeaderDescriptor[] {
215
+ let i = 0, j = 0;
216
+ const result: HeaderDescriptor[] = [];
217
+ while (i < headers.length && j < headersWithIssues.length) {
218
+ if (headers[i].name < headersWithIssues[j].name) {
219
+ result.push({...headers[i++], headerNotSet: false});
220
+ } else if (headers[i].name > headersWithIssues[j].name) {
221
+ result.push({...headersWithIssues[j++], headerNotSet: true});
222
+ } else {
223
+ result.push({...headersWithIssues[j++], ...headers[i++], headerNotSet: false});
224
+ }
225
+ }
226
+ while (i < headers.length) {
227
+ result.push({...headers[i++], headerNotSet: false});
228
+ }
229
+ while (j < headersWithIssues.length) {
230
+ result.push({...headersWithIssues[j++], headerNotSet: true});
231
+ }
232
+ return result;
233
+ }
234
+
235
+ const mergedHeaders = mergeHeadersWithIssues(this.#request.sortedResponseHeaders.slice(), headersWithIssues);
236
+
155
237
  const toggleShowRaw = (): void => {
156
238
  this.#showResponseHeadersText = !this.#showResponseHeadersText;
157
239
  this.#render();
@@ -172,12 +254,7 @@ export class RequestHeadersComponent extends HTMLElement {
172
254
  >
173
255
  ${this.#showResponseHeadersText ?
174
256
  this.#renderRawHeaders(this.#request.responseHeadersText, true) : html`
175
- ${this.#request.sortedResponseHeaders.map(header => html`
176
- <div class="row">
177
- <div class="header-name">${header.name}:</div>
178
- <div class="header-value">${header.value}</div>
179
- </div>
180
- `)}
257
+ ${mergedHeaders.map(header => this.#renderHeader(header))}
181
258
  `}
182
259
  </${Category.litTagName}>
183
260
  `;
@@ -186,13 +263,17 @@ export class RequestHeadersComponent extends HTMLElement {
186
263
  #renderRequestHeaders(): LitHtml.TemplateResult {
187
264
  assertNotNullOrUndefined(this.#request);
188
265
 
266
+ const headers = this.#request.requestHeaders().slice();
267
+ headers.sort(function(a, b) {
268
+ return Platform.StringUtilities.compare(a.name.toLowerCase(), b.name.toLowerCase());
269
+ });
270
+ const requestHeadersText = this.#request.requestHeadersText();
271
+
189
272
  const toggleShowRaw = (): void => {
190
273
  this.#showRequestHeadersText = !this.#showRequestHeadersText;
191
274
  this.#render();
192
275
  };
193
276
 
194
- const requestHeadersText = this.#request.requestHeadersText();
195
-
196
277
  // Disabled until https://crbug.com/1079231 is fixed.
197
278
  // clang-format off
198
279
  return html`
@@ -208,17 +289,85 @@ export class RequestHeadersComponent extends HTMLElement {
208
289
  >
209
290
  ${(this.#showRequestHeadersText && requestHeadersText) ?
210
291
  this.#renderRawHeaders(requestHeadersText, false) : html`
211
- ${this.#request.requestHeaders().map(header => html`
212
- <div class="row">
213
- <div class="header-name">${header.name}:</div>
214
- <div class="header-value">${header.value}</div>
215
- </div>
216
- `)}
292
+ ${headers.map(header => this.#renderHeader({...header, headerNotSet: false}))}
217
293
  `}
218
294
  </${Category.litTagName}>
219
295
  `;
220
296
  }
221
297
 
298
+ #renderHeader(header: HeaderDescriptor): LitHtml.TemplateResult {
299
+ return html`
300
+ <div class="row">
301
+ <div class="header-name">${header.headerNotSet ? html`<div class="header-badge header-badge-text">not-set</div>` : ''}${header.name}:</div>
302
+ <div class="header-value ${header.headerValueIncorrect ? 'header-warning' : ''}">${header.value?.toString()||''}</div>
303
+ </div>
304
+ ${this.#maybeRenderHeaderDetails(header.details)}
305
+ `;
306
+ }
307
+
308
+ #maybeRenderHeaderDetails(headerDetails?: HeaderDetailsDescriptor): LitHtml.LitTemplate {
309
+ if (!headerDetails) {
310
+ return LitHtml.nothing;
311
+ }
312
+ return html`
313
+ <div class="header-details">
314
+ <div class="call-to-action">
315
+ <div class="call-to-action-body">
316
+ <div class="explanation">${headerDetails.explanation()}</div>
317
+ ${headerDetails.examples.map(example => html`
318
+ <div class="example">
319
+ <code>${example.codeSnippet}</code>
320
+ ${example.comment ? html`
321
+ <span class="comment">${example.comment()}</span>
322
+ ` : ''}
323
+ </div>
324
+ `)}
325
+ ${this.#maybeRenderHeaderDetailsLink(headerDetails)}
326
+ </div>
327
+ </div>
328
+ </div>
329
+ `;
330
+ }
331
+
332
+ #maybeRenderHeaderDetailsLink(headerDetails?: HeaderDetailsDescriptor): LitHtml.LitTemplate {
333
+ if (this.#request && IssuesManager.RelatedIssue.hasIssueOfCategory(this.#request, IssuesManager.Issue.IssueCategory.CrossOriginEmbedderPolicy)) {
334
+ const followLink = (): void => {
335
+ Host.userMetrics.issuesPanelOpenedFrom(Host.UserMetrics.IssueOpener.LearnMoreLinkCOEP);
336
+ if (this.#request) {
337
+ void IssuesManager.RelatedIssue.reveal(
338
+ this.#request, IssuesManager.Issue.IssueCategory.CrossOriginEmbedderPolicy);
339
+ }
340
+ };
341
+ return html`
342
+ <div class="devtools-link" @click=${followLink}>
343
+ <${IconButton.Icon.Icon.litTagName} class="inline-icon" .data=${{
344
+ iconName: 'issue-exclamation-icon',
345
+ color: 'var(--issue-color-yellow)',
346
+ width: '16px',
347
+ height: '16px',
348
+ } as IconButton.Icon.IconData}>
349
+ </${IconButton.Icon.Icon.litTagName}>
350
+ ${i18nString(UIStrings.learnMoreInTheIssuesTab)}
351
+ </div>
352
+ `;
353
+ }
354
+ if (headerDetails?.link) {
355
+ return html`
356
+ <x-link href=${headerDetails.link.url} class="link">
357
+ <${IconButton.Icon.Icon.litTagName} class="inline-icon" .data=${{
358
+ iconName: 'link_icon',
359
+ color: 'var(--color-link)',
360
+ width: '16px',
361
+ height: '16px',
362
+ } as IconButton.Icon.IconData}>
363
+ </${IconButton.Icon.Icon.litTagName}
364
+ >${i18nString(UIStrings.learnMore)}
365
+ </x-link>
366
+ `;
367
+ }
368
+ return LitHtml.nothing;
369
+ }
370
+
222
371
  #renderRawHeaders(rawHeadersText: string, forResponseHeaders: boolean): LitHtml.TemplateResult {
223
372
  const trimmed = rawHeadersText.trim();
224
373
  const showFull = forResponseHeaders ? this.#showResponseHeadersTextFull : this.#showRequestHeadersTextFull;
@@ -434,3 +583,118 @@ declare global {
434
583
  'devtools-request-headers-category': Category;
435
584
  }
436
585
  }
586
+
587
+ interface HeaderDetailsDescriptor {
588
+ explanation: () => string;
589
+ examples: Array<{
590
+ codeSnippet: string,
591
+ comment?: (() => string),
592
+ }>;
593
+ link: {
594
+ url: string,
595
+ }|null;
596
+ }
597
+
598
+ interface HeaderDescriptor {
599
+ name: string;
600
+ value: Object|null;
601
+ headerValueIncorrect?: boolean|null;
602
+ details?: HeaderDetailsDescriptor;
603
+ headerNotSet: boolean|null;
604
+ }
605
+
606
+ const BlockedReasonDetails = new Map<Protocol.Network.BlockedReason, HeaderDescriptor>([
607
+ [
608
+ Protocol.Network.BlockedReason.CoepFrameResourceNeedsCoepHeader,
609
+ {
610
+ name: 'cross-origin-embedder-policy',
611
+ value: null,
612
+ headerValueIncorrect: null,
613
+ details: {
614
+ explanation: i18nLazyString(UIStrings.toEmbedThisFrameInYourDocument),
615
+ examples: [{codeSnippet: 'Cross-Origin-Embedder-Policy: require-corp', comment: undefined}],
616
+ link: {url: 'https://web.dev/coop-coep/'},
617
+ },
618
+ headerNotSet: null,
619
+ },
620
+ ],
621
+ [
622
+ Protocol.Network.BlockedReason.CorpNotSameOriginAfterDefaultedToSameOriginByCoep,
623
+ {
624
+ name: 'cross-origin-resource-policy',
625
+ value: null,
626
+ headerValueIncorrect: null,
627
+ details: {
628
+ explanation: i18nLazyString(UIStrings.toUseThisResourceFromADifferent),
629
+ examples: [
630
+ {
631
+ codeSnippet: 'Cross-Origin-Resource-Policy: same-site',
632
+ comment: i18nLazyString(UIStrings.chooseThisOptionIfTheResourceAnd),
633
+ },
634
+ {
635
+ codeSnippet: 'Cross-Origin-Resource-Policy: cross-origin',
636
+ comment: i18nLazyString(UIStrings.onlyChooseThisOptionIfAn),
637
+ },
638
+ ],
639
+ link: {url: 'https://web.dev/coop-coep/'},
640
+ },
641
+ headerNotSet: null,
642
+ },
643
+ ],
644
+ [
645
+ Protocol.Network.BlockedReason.CoopSandboxedIframeCannotNavigateToCoopPage,
646
+ {
647
+ name: 'cross-origin-opener-policy',
648
+ value: null,
649
+ headerValueIncorrect: false,
650
+ details: {
651
+ explanation: i18nLazyString(UIStrings.thisDocumentWasBlockedFrom),
652
+ examples: [],
653
+ link: {url: 'https://web.dev/coop-coep/'},
654
+ },
655
+ headerNotSet: null,
656
+ },
657
+ ],
658
+ [
659
+ Protocol.Network.BlockedReason.CorpNotSameSite,
660
+ {
661
+ name: 'cross-origin-resource-policy',
662
+ value: null,
663
+ headerValueIncorrect: true,
664
+ details: {
665
+ explanation: i18nLazyString(UIStrings.toUseThisResourceFromADifferentSite),
666
+ examples: [
667
+ {
668
+ codeSnippet: 'Cross-Origin-Resource-Policy: cross-origin',
669
+ comment: i18nLazyString(UIStrings.onlyChooseThisOptionIfAn),
670
+ },
671
+ ],
672
+ link: null,
673
+ },
674
+ headerNotSet: null,
675
+ },
676
+ ],
677
+ [
678
+ Protocol.Network.BlockedReason.CorpNotSameOrigin,
679
+ {
680
+ name: 'cross-origin-resource-policy',
681
+ value: null,
682
+ headerValueIncorrect: true,
683
+ details: {
684
+ explanation: i18nLazyString(UIStrings.toUseThisResourceFromADifferentOrigin),
685
+ examples: [
686
+ {
687
+ codeSnippet: 'Cross-Origin-Resource-Policy: same-site',
688
+ comment: i18nLazyString(UIStrings.chooseThisOptionIfTheResourceAnd),
689
+ },
690
+ {
691
+ codeSnippet: 'Cross-Origin-Resource-Policy: cross-origin',
692
+ comment: i18nLazyString(UIStrings.onlyChooseThisOptionIfAn),
693
+ },
694
+ ],
695
+ link: null,
696
+ },
697
+ headerNotSet: null,
698
+ },
699
+ ],
700
+ ]);
@@ -14,20 +14,25 @@ const UIStrings = {
14
14
  */
15
15
  sourceMapUrl: 'Source map URL: ',
16
16
  /**
17
+ *@description Text in Add Debug Info URL Dialog of the Sources panel
18
+ */
19
+ debugInfoUrl: 'DWARF symbols URL: ',
20
+ /**
17
21
  *@description Text to add something
18
22
  */
19
23
  add: 'Add',
20
24
  };
21
25
  const str_ = i18n.i18n.registerUIStrings('panels/sources/AddSourceMapURLDialog.ts', UIStrings);
22
26
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
23
- export class AddSourceMapURLDialog extends UI.Widget.HBox {
27
+ export class AddDebugInfoURLDialog extends UI.Widget.HBox {
24
28
  private readonly input: HTMLInputElement;
25
29
  private readonly dialog: UI.Dialog.Dialog;
26
30
  private readonly callback: (arg0: Platform.DevToolsPath.UrlString) => void;
27
- constructor(callback: (arg0: Platform.DevToolsPath.UrlString) => void) {
31
+ private constructor(
32
+ label: Platform.UIString.LocalizedString, callback: (arg0: Platform.DevToolsPath.UrlString) => void) {
28
33
  super(/* isWebComponent */ true);
29
34
 
30
- this.contentElement.createChild('label').textContent = i18nString(UIStrings.sourceMapUrl);
35
+ this.contentElement.createChild('label').textContent = label;
31
36
 
32
37
  this.input = UI.UIUtils.createInput('add-source-map', 'text');
33
38
  this.input.addEventListener('keydown', this.onKeyDown.bind(this), false);
@@ -43,6 +48,15 @@ export class AddSourceMapURLDialog extends UI.Widget.HBox {
43
48
  this.callback = callback;
44
49
  }
45
50
 
51
+ static createAddSourceMapURLDialog(callback: (arg0: Platform.DevToolsPath.UrlString) => void): AddDebugInfoURLDialog {
52
+ return new AddDebugInfoURLDialog(i18nString(UIStrings.sourceMapUrl), callback);
53
+ }
54
+
55
+ static createAddDWARFSymbolsURLDialog(callback: (arg0: Platform.DevToolsPath.UrlString) => void):
56
+ AddDebugInfoURLDialog {
57
+ return new AddDebugInfoURLDialog(i18nString(UIStrings.debugInfoUrl), callback);
58
+ }
59
+
46
60
  show(): void {
47
61
  super.show(this.dialog.contentElement);
48
62
  // UI.Dialog extends GlassPane and overrides the `show` method with a wider
@@ -160,6 +160,9 @@ export class CallStackSidebarPane extends UI.View.SimpleView implements UI.Conte
160
160
 
161
161
  this.updateItemThrottler = new Common.Throttler.Throttler(100);
162
162
  this.scheduledForUpdateItems = new Set();
163
+
164
+ SDK.TargetManager.TargetManager.instance().addModelListener(
165
+ SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.DebugInfoAttached, this.debugInfoAttached, this);
163
166
  }
164
167
 
165
168
  static instance(opts: {
@@ -179,6 +182,10 @@ export class CallStackSidebarPane extends UI.View.SimpleView implements UI.Conte
179
182
  this.update();
180
183
  }
181
184
 
185
+ private debugInfoAttached(): void {
186
+ this.update();
187
+ }
188
+
182
189
  private update(): void {
183
190
  void this.updateThrottler.schedule(() => this.doUpdate());
184
191
  }
@@ -45,7 +45,7 @@ import * as SourceFrame from '../../ui/legacy/components/source_frame/source_fra
45
45
  import * as UI from '../../ui/legacy/legacy.js';
46
46
  import type * as TextEditor from '../../ui/components/text_editor/text_editor.js';
47
47
 
48
- import {AddSourceMapURLDialog} from './AddSourceMapURLDialog.js';
48
+ import {AddDebugInfoURLDialog} from './AddSourceMapURLDialog.js';
49
49
  import {BreakpointEditDialog, LogpointPrefix} from './BreakpointEditDialog.js';
50
50
  import {Plugin} from './Plugin.js';
51
51
  import {ScriptFormatterEditorAction} from './ScriptFormatterEditorAction.js';
@@ -112,6 +112,10 @@ const UIStrings = {
112
112
  /**
113
113
  *@description Text in Debugger Plugin of the Sources panel
114
114
  */
115
+ addWasmDebugInfo: 'Add DWARF debug info…',
116
+ /**
117
+ *@description Text in Debugger Plugin of the Sources panel
118
+ */
115
119
  sourceMapDetected: 'Source map detected.',
116
120
  /**
117
121
  *@description Text in Debugger Plugin of the Sources panel
@@ -480,7 +484,8 @@ export class DebuggerPlugin extends Plugin {
480
484
 
481
485
  populateTextAreaContextMenu(contextMenu: UI.ContextMenu.ContextMenu): void {
482
486
  function addSourceMapURL(scriptFile: Bindings.ResourceScriptMapping.ResourceScriptFile): void {
483
- const dialog = new AddSourceMapURLDialog(addSourceMapURLDialogCallback.bind(null, scriptFile));
487
+ const dialog =
488
+ AddDebugInfoURLDialog.createAddSourceMapURLDialog(addSourceMapURLDialogCallback.bind(null, scriptFile));
484
489
  dialog.show();
485
490
  }
486
491
 
@@ -492,13 +497,34 @@ export class DebuggerPlugin extends Plugin {
492
497
  scriptFile.addSourceMapURL(url);
493
498
  }
494
499
 
500
+ function addDebugInfoURL(scriptFile: Bindings.ResourceScriptMapping.ResourceScriptFile): void {
501
+ const dialog =
502
+ AddDebugInfoURLDialog.createAddDWARFSymbolsURLDialog(addDebugInfoURLDialogCallback.bind(null, scriptFile));
503
+ dialog.show();
504
+ }
505
+
506
+ function addDebugInfoURLDialogCallback(
507
+ scriptFile: Bindings.ResourceScriptMapping.ResourceScriptFile, url: Platform.DevToolsPath.UrlString): void {
508
+ if (!url) {
509
+ return;
510
+ }
511
+ scriptFile.addDebugInfoURL(url);
512
+ }
513
+
495
514
  if (this.uiSourceCode.project().type() === Workspace.Workspace.projectTypes.Network &&
496
515
  Common.Settings.Settings.instance().moduleSetting('jsSourceMapsEnabled').get() &&
497
516
  !Bindings.IgnoreListManager.IgnoreListManager.instance().isIgnoreListedUISourceCode(this.uiSourceCode)) {
498
517
  if (this.scriptFileForDebuggerModel.size) {
499
- const scriptFile = this.scriptFileForDebuggerModel.values().next().value;
518
+ const scriptFile: Bindings.ResourceScriptMapping.ResourceScriptFile =
519
+ this.scriptFileForDebuggerModel.values().next().value;
500
520
  const addSourceMapURLLabel = i18nString(UIStrings.addSourceMap);
501
521
  contextMenu.debugSection().appendItem(addSourceMapURLLabel, addSourceMapURL.bind(null, scriptFile));
522
+ if (scriptFile.script?.isWasm() &&
523
+ !Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().pluginManager?.hasPluginForScript(
524
+ scriptFile.script)) {
525
+ contextMenu.debugSection().appendItem(
526
+ i18nString(UIStrings.addWasmDebugInfo), addDebugInfoURL.bind(null, scriptFile));
527
+ }
502
528
  }
503
529
  }
504
530
  }
@@ -99,6 +99,8 @@ export class ScopeChainSidebarPane extends UI.Widget.VBox implements UI.ContextF
99
99
  this.infoElement = document.createElement('div');
100
100
  this.infoElement.className = 'gray-info-message';
101
101
  this.infoElement.tabIndex = -1;
102
+ SDK.TargetManager.TargetManager.instance().addModelListener(
103
+ SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.DebugInfoAttached, this.debugInfoAttached, this);
102
104
  void this.update();
103
105
  }
104
106
 
@@ -151,6 +153,12 @@ export class ScopeChainSidebarPane extends UI.Widget.VBox implements UI.ContextF
151
153
  }
152
154
  }
153
155
 
156
+ private debugInfoAttached(event: Common.EventTarget.EventTargetEvent<SDK.Script.Script>): void {
157
+ if (event.data === this.#scopesScript) {
158
+ void this.update();
159
+ }
160
+ }
161
+
154
162
  private async update(): Promise<void> {
155
163
  // The `resolveThisObject(callFrame)` and `resolveScopeChain(callFrame)` calls
156
164
  // below may take a while to complete, so indicate to the user that something
@@ -314,6 +314,8 @@ export class SourcesPanel extends UI.Panel.Panel implements UI.ContextMenu.Provi
314
314
  SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.DebuggerWasEnabled, this.debuggerWasEnabled, this);
315
315
  SDK.TargetManager.TargetManager.instance().addModelListener(
316
316
  SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this.debuggerPaused, this);
317
+ SDK.TargetManager.TargetManager.instance().addModelListener(
318
+ SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.DebugInfoAttached, this.debugInfoAttached, this);
317
319
  SDK.TargetManager.TargetManager.instance().addModelListener(
318
320
  SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.DebuggerResumed,
319
321
  event => this.debuggerResumed(event.data));
@@ -474,6 +476,18 @@ export class SourcesPanel extends UI.Panel.Panel implements UI.ContextMenu.Provi
474
476
  }
475
477
  }
476
478
 
479
+ private debugInfoAttached(event: Common.EventTarget.EventTargetEvent<SDK.Script.Script>): void {
480
+ const {debuggerModel} = event.data;
481
+ if (!debuggerModel.isPaused()) {
482
+ return;
483
+ }
484
+
485
+ const details = debuggerModel.debuggerPausedDetails();
486
+ if (details && UI.Context.Context.instance().flavor(SDK.Target.Target) === debuggerModel.target()) {
487
+ this.showDebuggerPausedDetails(details);
488
+ }
489
+ }
490
+
477
491
  private showDebuggerPausedDetails(details: SDK.DebuggerModel.DebuggerPausedDetails): void {
478
492
  this.pausedInternal = true;
479
493
  void this.updateDebuggerButtonsAndStatus();
package/package.json CHANGED
@@ -55,5 +55,5 @@
55
55
  "unittest": "scripts/test/run_unittests.py --no-text-coverage",
56
56
  "watch": "vpython third_party/node/node.py --output scripts/watch_build.js"
57
57
  },
58
- "version": "1.0.1022059"
58
+ "version": "1.0.1022611"
59
59
  }
@@ -64,7 +64,7 @@ module.exports = {
64
64
  const filePathWithPanelName = classDefiningFileName.substring(PANELS_DIRECTORY.length + 1);
65
65
  const filePathWithoutPanelName = filePathWithPanelName.substring(filePathWithPanelName.indexOf(path.sep) + 1);
66
66
 
67
- if (filePathWithoutPanelName.startsWith('components' + path.sep)) {
67
+ if (filePathWithoutPanelName.includes(`components${path.sep}`)) {
68
68
  return;
69
69
  }
70
70
  }
@@ -27,6 +27,11 @@ ruleTester.run('custom_element_definitions_location', rule, {
27
27
  filename: 'front_end/panels/issues/components/nested/folder/Foo.ts',
28
28
  options: [{rootFrontendDirectory: path.join(__dirname, '..', '..', '..', 'front_end')}]
29
29
  },
30
+ {
31
+ code: 'class Foo extends HTMLElement {}',
32
+ filename: 'front_end/panels/performance/library/components/metrics/Metric.ts',
33
+ options: [{rootFrontendDirectory: path.join(__dirname, '..', '..', '..', 'front_end')}]
34
+ },
30
35
  {
31
36
  code: 'class Foo extends OtherClass {}',
32
37
  filename: 'front_end/models/some/Model.ts',