chrome-devtools-frontend 1.0.1021582 → 1.0.1022475
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/.eslintignore +14 -1
- package/extension-api/ExtensionAPI.d.ts +54 -4
- package/front_end/.eslintrc.js +3 -1
- package/front_end/core/host/InspectorFrontendHostAPI.ts +1 -0
- package/front_end/core/host/UserMetrics.ts +18 -0
- package/front_end/core/i18n/locales/en-US.json +60 -0
- package/front_end/core/i18n/locales/en-XL.json +60 -0
- package/front_end/core/sdk/DebuggerModel.ts +10 -0
- package/front_end/devtools_compatibility.js +1 -0
- package/front_end/legacy_test_runner/sources_test_runner/DebuggerTestRunner.js +4 -3
- package/front_end/models/bindings/DebuggerLanguagePlugins.ts +166 -117
- package/front_end/models/bindings/ResourceScriptMapping.ts +12 -1
- package/front_end/models/extensions/ExtensionAPI.ts +101 -13
- package/front_end/models/extensions/ExtensionServer.ts +63 -1
- package/front_end/models/extensions/LanguageExtensionEndpoint.ts +16 -3
- package/front_end/models/issues_manager/RelatedIssue.ts +1 -1
- package/front_end/models/issues_manager/descriptions/federatedAuthRequestErrorIdToken.md +1 -1
- package/front_end/models/issues_manager/descriptions/federatedAuthRequestIdTokenInvalidRequest.md +1 -1
- package/front_end/models/issues_manager/descriptions/federatedAuthRequestIdTokenInvalidResponse.md +1 -1
- package/front_end/models/issues_manager/descriptions/federatedAuthRequestIdTokenNoResponse.md +1 -1
- package/front_end/models/timeline_model/TimelineModel.ts +164 -7
- package/front_end/panels/application/AppManifestView.ts +13 -2
- package/front_end/panels/application/ApplicationPanelSidebar.ts +67 -5
- package/front_end/panels/elements/ElementsTreeOutline.ts +41 -7
- package/front_end/panels/elements/TopLayerContainer.ts +9 -1
- package/front_end/panels/elements/components/AdornerManager.ts +7 -0
- package/front_end/panels/elements/elementsTreeOutline.css +4 -0
- package/front_end/panels/network/components/RequestHeadersView.css +55 -0
- package/front_end/panels/network/components/RequestHeadersView.ts +278 -14
- package/front_end/panels/sources/AddSourceMapURLDialog.ts +17 -3
- package/front_end/panels/sources/CallStackSidebarPane.ts +7 -0
- package/front_end/panels/sources/DebuggerPlugin.ts +29 -3
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +8 -0
- package/front_end/panels/sources/SourcesPanel.ts +14 -0
- package/front_end/third_party/acorn/acorn.ts +1 -1
- package/front_end/third_party/chromium/client-variations/client-variations.ts +1 -1
- package/front_end/third_party/diff/DiffWrapper.ts +2 -0
- package/front_end/third_party/i18n/i18n-impl.ts +5 -1
- package/front_end/third_party/i18n/i18n.ts +1 -1
- package/front_end/third_party/i18n/locales.ts +1 -1
- package/front_end/third_party/marked/marked.ts +1 -1
- package/front_end/third_party/puppeteer/puppeteer.ts +6 -6
- package/front_end/ui/components/linear_memory_inspector/LinearMemoryInspectorController.ts +23 -1
- package/front_end/ui/legacy/ReportView.ts +8 -0
- package/package.json +1 -1
- package/scripts/eslint_rules/lib/custom_element_definitions_location.js +29 -14
- package/scripts/eslint_rules/lib/es_modules_import.js +5 -1
- package/scripts/eslint_rules/tests/custom_element_definitions_location_test.js +14 -2
- package/scripts/eslint_rules/tests/es_modules_import_test.js +5 -0
@@ -35,10 +35,12 @@
|
|
35
35
|
import * as Common from '../../core/common/common.js';
|
36
36
|
import * as i18n from '../../core/i18n/i18n.js';
|
37
37
|
import * as SDK from '../../core/sdk/sdk.js';
|
38
|
+
import * as Adorners from '../../ui/components/adorners/adorners.js';
|
38
39
|
import * as CodeHighlighter from '../../ui/components/code_highlighter/code_highlighter.js';
|
40
|
+
import * as IconButton from '../../ui/components/icon_button/icon_button.js';
|
39
41
|
import * as UI from '../../ui/legacy/legacy.js';
|
40
42
|
|
41
|
-
import
|
43
|
+
import * as ElementsComponents from './components/components.js';
|
42
44
|
import {ElementsPanel} from './ElementsPanel.js';
|
43
45
|
import {ElementsTreeElement, InitialChildrenLimit} from './ElementsTreeElement.js';
|
44
46
|
import elementsTreeOutlineStyles from './elementsTreeOutline.css.js';
|
@@ -1629,13 +1631,45 @@ export class ShortcutTreeElement extends UI.TreeOutline.TreeElement {
|
|
1629
1631
|
text = '<' + text + '>';
|
1630
1632
|
}
|
1631
1633
|
title.textContent = '\u21AA ' + text;
|
1632
|
-
|
1633
|
-
const link = (linkifyDeferredNodeReference(nodeShortcut.deferredNode) as Element);
|
1634
|
-
UI.UIUtils.createTextChild(this.listItemElement, ' ');
|
1635
|
-
link.classList.add('elements-tree-shortcut-link');
|
1636
|
-
link.textContent = i18nString(UIStrings.reveal);
|
1637
|
-
this.listItemElement.appendChild(link);
|
1638
1634
|
this.nodeShortcut = nodeShortcut;
|
1635
|
+
this.addRevealAdorner();
|
1636
|
+
}
|
1637
|
+
|
1638
|
+
addRevealAdorner(): void {
|
1639
|
+
const adorner = new Adorners.Adorner.Adorner();
|
1640
|
+
adorner.classList.add('adorner-reveal');
|
1641
|
+
const config = ElementsComponents.AdornerManager.getRegisteredAdorner(
|
1642
|
+
ElementsComponents.AdornerManager.RegisteredAdorners.REVEAL);
|
1643
|
+
const name = config.name;
|
1644
|
+
const adornerContent = document.createElement('span');
|
1645
|
+
const linkIcon = new IconButton.Icon.Icon();
|
1646
|
+
linkIcon
|
1647
|
+
.data = {iconName: 'ic_show_node_16x16', color: 'var(--color-text-disabled)', width: '12px', height: '12px'};
|
1648
|
+
const slotText = document.createElement('span');
|
1649
|
+
slotText.textContent = name;
|
1650
|
+
adornerContent.append(linkIcon);
|
1651
|
+
adornerContent.append(slotText);
|
1652
|
+
adornerContent.classList.add('adorner-with-icon');
|
1653
|
+
adorner.data = {
|
1654
|
+
name,
|
1655
|
+
content: adornerContent,
|
1656
|
+
};
|
1657
|
+
this.listItemElement.appendChild(adorner);
|
1658
|
+
const onClick = (((): void => {
|
1659
|
+
this.nodeShortcut.deferredNode.resolve(
|
1660
|
+
node => {
|
1661
|
+
void Common.Revealer.reveal(node);
|
1662
|
+
},
|
1663
|
+
);
|
1664
|
+
}) as EventListener);
|
1665
|
+
adorner.addInteraction(onClick, {
|
1666
|
+
isToggle: false,
|
1667
|
+
shouldPropagateOnKeydown: false,
|
1668
|
+
ariaLabelDefault: i18nString(UIStrings.reveal),
|
1669
|
+
ariaLabelActive: i18nString(UIStrings.reveal),
|
1670
|
+
});
|
1671
|
+
adorner.addEventListener('mousedown', e => e.consume(), false);
|
1672
|
+
ElementsPanel.instance().registerAdorner(adorner);
|
1639
1673
|
}
|
1640
1674
|
|
1641
1675
|
get hovered(): boolean {
|
@@ -3,6 +3,7 @@
|
|
3
3
|
// found in the LICENSE file.
|
4
4
|
import * as i18n from '../../core/i18n/i18n.js';
|
5
5
|
import * as SDK from '../../core/sdk/sdk.js';
|
6
|
+
import * as IconButton from '../../ui/components/icon_button/icon_button.js';
|
6
7
|
import * as UI from '../../ui/legacy/legacy.js';
|
7
8
|
|
8
9
|
import * as ElementsComponents from './components/components.js';
|
@@ -79,7 +80,14 @@ export class TopLayerContainer extends UI.TreeOutline.TreeElement {
|
|
79
80
|
const config = ElementsComponents.AdornerManager.getRegisteredAdorner(
|
80
81
|
ElementsComponents.AdornerManager.RegisteredAdorners.TOP_LAYER);
|
81
82
|
const adornerContent = document.createElement('span');
|
82
|
-
adornerContent.
|
83
|
+
adornerContent.classList.add('adorner-with-icon');
|
84
|
+
const linkIcon = new IconButton.Icon.Icon();
|
85
|
+
linkIcon
|
86
|
+
.data = {iconName: 'ic_show_node_16x16', color: 'var(--color-text-disabled)', width: '12px', height: '12px'};
|
87
|
+
const adornerText = document.createElement('span');
|
88
|
+
adornerText.textContent = ` top-layer (${topLayerElementIndex}) `;
|
89
|
+
adornerContent.append(linkIcon);
|
90
|
+
adornerContent.append(adornerText);
|
83
91
|
const adorner = element?.adorn(config, adornerContent);
|
84
92
|
if (adorner) {
|
85
93
|
const onClick = (((): void => {
|
@@ -31,6 +31,7 @@ export enum RegisteredAdorners {
|
|
31
31
|
CONTAINER = 'container',
|
32
32
|
SLOT = 'slot',
|
33
33
|
TOP_LAYER = 'top-layer',
|
34
|
+
REVEAL = 'reveal',
|
34
35
|
}
|
35
36
|
|
36
37
|
// This enum-like const object serves as the authoritative registry for all the
|
@@ -79,6 +80,12 @@ export function getRegisteredAdorner(which: RegisteredAdorners): RegisteredAdorn
|
|
79
80
|
category: AdornerCategories.LAYOUT,
|
80
81
|
enabledByDefault: true,
|
81
82
|
};
|
83
|
+
case RegisteredAdorners.REVEAL:
|
84
|
+
return {
|
85
|
+
name: 'reveal',
|
86
|
+
category: AdornerCategories.DEFAULT,
|
87
|
+
enabledByDefault: true,
|
88
|
+
};
|
82
89
|
}
|
83
90
|
}
|
84
91
|
|
@@ -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
|
-
${
|
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
|
-
${
|
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
|
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(
|
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 =
|
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 {
|
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 =
|
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
|
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
|
}
|