blob: e4959f1fd7dfa7251d24dfc6ba446018f5968034 [file] [log] [blame]
Wolfgang Beyer760462e2020-07-13 15:01:351// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Wolfgang Beyer309863f2021-01-21 09:01:215/* eslint-disable rulesdir/no_underscored_properties */
6
Wolfgang Beyer92395c92021-02-02 10:43:237import type * as Components from '../ui/components/components.js';
8
Wolfgang Beyer2ed11a42020-09-30 07:24:549import * as Bindings from '../bindings/bindings.js';
Sigurd Schneider1e5ad282020-07-17 11:52:0810import * as Common from '../common/common.js';
Wolfgang Beyer92395c92021-02-02 10:43:2311import * as LitHtml from '../third_party/lit-html/lit-html.js';
Sigurd Schneiderfc2bd212020-08-12 12:58:4112import * as Network from '../network/network.js';
Wolfgang Beyer1525b1f2021-02-02 14:12:3013import * as Platform from '../platform/platform.js';
Wolfgang Beyer95951c4d2020-10-23 08:00:0614import * as Root from '../root/root.js';
Wolfgang Beyer760462e2020-07-13 15:01:3515import * as SDK from '../sdk/sdk.js'; // eslint-disable-line no-unused-vars
16import * as UI from '../ui/ui.js';
Sigurd Schneider1e5ad282020-07-17 11:52:0817import * as Workspace from '../workspace/workspace.js';
Wolfgang Beyer1525b1f2021-02-02 14:12:3018import {ls} from '../platform/platform.js';
Wolfgang Beyer760462e2020-07-13 15:01:3519
Wolfgang Beyer309863f2021-01-21 09:01:2120const booleanToYesNo = (b: boolean): Common.UIString.LocalizedString => b ? ls`Yes` : ls`No`;
Sigurd Schneideraef29822020-08-20 14:01:1321
Sigurd Schneider1e5ad282020-07-17 11:52:0822export class FrameDetailsView extends UI.ThrottledWidget.ThrottledWidget {
Wolfgang Beyer92395c92021-02-02 10:43:2323 private readonly reportView = new FrameDetailsReportView();
24
Wolfgang Beyer309863f2021-01-21 09:01:2125 _protocolMonitorExperimentEnabled: boolean;
26 _frame: SDK.ResourceTreeModel.ResourceTreeFrame;
27 _reportView: UI.ReportView.ReportView;
Wolfgang Beyer309863f2021-01-21 09:01:2128 _isolationSection: UI.ReportView.Section;
29 _secureContext: HTMLElement;
30 _crossOriginIsolatedContext: HTMLElement;
31 _coepPolicy: HTMLElement;
32 _coopPolicy: HTMLElement;
33 _apiAvailability: UI.ReportView.Section;
34 _apiSharedArrayBuffer: HTMLElement;
35 _apiMeasureMemory: HTMLElement;
36 _additionalInfo: UI.ReportView.Section|undefined;
Wolfgang Beyer92395c92021-02-02 10:43:2337
Wolfgang Beyer309863f2021-01-21 09:01:2138 constructor(frame: SDK.ResourceTreeModel.ResourceTreeFrame) {
Wolfgang Beyer760462e2020-07-13 15:01:3539 super();
Wolfgang Beyer95951c4d2020-10-23 08:00:0640 this._protocolMonitorExperimentEnabled = Root.Runtime.experiments.isEnabled('protocolMonitor');
Wolfgang Beyer31b60b12020-11-27 13:16:0341 this.registerRequiredCSS('resources/frameDetailsReportView.css', {enableLegacyPatching: false});
Sigurd Schneider1e5ad282020-07-17 11:52:0842 this._frame = frame;
Wolfgang Beyer5ac564d2020-09-28 13:49:3543 this.contentElement.classList.add('frame-details-container');
44
Wolfgang Beyer92395c92021-02-02 10:43:2345 this.contentElement.appendChild(this.reportView);
46
Simon Zünd1edfa262020-12-09 08:30:0547 // TODO(crbug.com/1156978): Replace UI.ReportView.ReportView with ReportView.ts web component.
Wolfgang Beyer92395c92021-02-02 10:43:2348 this._reportView = new UI.ReportView.ReportView();
Wolfgang Beyer31b60b12020-11-27 13:16:0349 this._reportView.registerRequiredCSS('resources/frameDetailsReportView.css', {enableLegacyPatching: false});
Wolfgang Beyer760462e2020-07-13 15:01:3550 this._reportView.show(this.contentElement);
Wolfgang Beyer5ac564d2020-09-28 13:49:3551 this._reportView.element.classList.add('frame-details-report-container');
Wolfgang Beyer760462e2020-07-13 15:01:3552
Sigurd Schneider680531a2020-08-19 08:08:5153 this._isolationSection = this._reportView.appendSection(ls`Security & Isolation`);
Sigurd Schneideraef29822020-08-20 14:01:1354 this._secureContext = this._isolationSection.appendField(ls`Secure Context`);
Sigurd Schneidercea65762020-10-19 09:47:5055 this._crossOriginIsolatedContext = this._isolationSection.appendField(ls`Cross-Origin Isolated`);
Sigurd Schneider680531a2020-08-19 08:08:5156 this._coepPolicy = this._isolationSection.appendField(ls`Cross-Origin Embedder Policy`);
57 this._coopPolicy = this._isolationSection.appendField(ls`Cross-Origin Opener Policy`);
Sigurd Schneider3fa2f7f2020-10-19 14:36:0258
59 this._apiAvailability = this._reportView.appendSection(ls`API availablity`);
60 const summaryRow = this._apiAvailability.appendRow();
61 const summaryText = ls`Availability of certain APIs depends on the document being cross-origin isolated.`;
62 const link = 'https://web.dev/why-coop-coep/';
63 summaryRow.appendChild(UI.Fragment.html`<div>${summaryText} ${UI.XLink.XLink.create(link, ls`Learn more`)}</div>`);
Sigurd Schneidereabef962020-11-05 10:51:4964 this._apiSharedArrayBuffer = this._apiAvailability.appendField(ls`Shared Array Buffers`);
Sigurd Schneider12cf8692021-01-11 15:21:0065 this._apiMeasureMemory = this._apiAvailability.appendField(ls`Measure Memory`);
Wolfgang Beyer95951c4d2020-10-23 08:00:0666
67 if (this._protocolMonitorExperimentEnabled) {
68 this._additionalInfo = this._reportView.appendSection(ls`Additional Information`);
69 this._additionalInfo.setTitle(
70 ls`Additional Information`,
71 ls`This additional (debugging) information is shown because the 'Protocol Monitor' experiment is enabled.`);
72 const frameIDField = this._additionalInfo.appendField(ls`Frame ID`);
73 frameIDField.textContent = frame.id;
74 }
Sigurd Schneider1e5ad282020-07-17 11:52:0875 this.update();
76 }
77
Wolfgang Beyer309863f2021-01-21 09:01:2178 async doUpdate(): Promise<void> {
Wolfgang Beyer92395c92021-02-02 10:43:2379 this.reportView.data = {frame: this._frame};
Sigurd Schneider680531a2020-08-19 08:08:5180 await this._updateCoopCoepStatus();
Sigurd Schneideraef29822020-08-20 14:01:1381 this._updateContextStatus();
Sigurd Schneidereabef962020-11-05 10:51:4982 this._updateApiAvailability();
Sigurd Schneider680531a2020-08-19 08:08:5183 }
84
Wolfgang Beyer309863f2021-01-21 09:01:2185 static fillCrossOriginPolicy(
86 field: HTMLElement,
87 isEnabled: (value: Protocol.Network.CrossOriginEmbedderPolicyValue|
88 Protocol.Network.CrossOriginOpenerPolicyValue) => boolean,
89 info: Protocol.Network.CrossOriginEmbedderPolicyStatus|Protocol.Network.CrossOriginOpenerPolicyStatus|null|
90 undefined): void {
Sigurd Schneidera36cca52020-10-29 15:36:0091 if (!info) {
92 field.textContent = '';
93 return;
94 }
Sigurd Schneider3cc78e22020-09-18 10:44:1395 const enabled = isEnabled(info.value);
96 field.textContent = enabled ? info.value : info.reportOnlyValue;
97 if (!enabled && isEnabled(info.reportOnlyValue)) {
98 const reportOnly = document.createElement('span');
99 reportOnly.classList.add('inline-comment');
100 reportOnly.textContent = 'report-only';
101 field.appendChild(reportOnly);
102 }
103 const endpoint = enabled ? info.reportingEndpoint : info.reportOnlyReportingEndpoint;
104 if (endpoint) {
105 const reportingEndpointPrefix = field.createChild('span', 'inline-name');
106 reportingEndpointPrefix.textContent = ls`reporting to`;
Wolfgang Beyer9a64fc62020-10-06 14:54:43107 const reportingEndpointName = field.createChild('span');
Sigurd Schneider3cc78e22020-09-18 10:44:13108 reportingEndpointName.textContent = endpoint;
109 }
110 }
111
Wolfgang Beyer309863f2021-01-21 09:01:21112 async _updateCoopCoepStatus(): Promise<void> {
Sigurd Schneider5a5b7352020-10-05 11:13:05113 const model = this._frame.resourceTreeModel().target().model(SDK.NetworkManager.NetworkManager);
114 const info = model && await model.getSecurityIsolationStatus(this._frame.id);
Sigurd Schneider3cc78e22020-09-18 10:44:13115 if (!info) {
116 return;
117 }
Wolfgang Beyer309863f2021-01-21 09:01:21118 const coepIsEnabled =
119 (value: Protocol.Network.CrossOriginEmbedderPolicyValue|Protocol.Network.CrossOriginOpenerPolicyValue):
120 boolean => value !== Protocol.Network.CrossOriginEmbedderPolicyValue.None;
Sigurd Schneider3cc78e22020-09-18 10:44:13121 FrameDetailsView.fillCrossOriginPolicy(this._coepPolicy, coepIsEnabled, info.coep);
Tim van der Lipped7cfd142021-01-07 12:17:24122 this._isolationSection.setFieldVisible(ls`Cross-Origin Embedder Policy`, Boolean(info.coep));
Sigurd Schneidera36cca52020-10-29 15:36:00123
Wolfgang Beyer309863f2021-01-21 09:01:21124 const coopIsEnabled =
125 (value: Protocol.Network.CrossOriginEmbedderPolicyValue|Protocol.Network.CrossOriginOpenerPolicyValue):
126 boolean => value !== Protocol.Network.CrossOriginOpenerPolicyValue.UnsafeNone;
Sigurd Schneider3cc78e22020-09-18 10:44:13127 FrameDetailsView.fillCrossOriginPolicy(this._coopPolicy, coopIsEnabled, info.coop);
Tim van der Lipped7cfd142021-01-07 12:17:24128 this._isolationSection.setFieldVisible(ls`Cross-Origin Opener Policy`, Boolean(info.coop));
Wolfgang Beyer760462e2020-07-13 15:01:35129 }
Sigurd Schneiderf1aba722020-07-20 09:03:19130
Wolfgang Beyer309863f2021-01-21 09:01:21131 _explanationFromSecureContextType(type: Protocol.Page.SecureContextType|null): string|null {
Sigurd Schneideraef29822020-08-20 14:01:13132 switch (type) {
133 case Protocol.Page.SecureContextType.Secure:
134 return null;
135 case Protocol.Page.SecureContextType.SecureLocalhost:
136 return ls`Localhost is always a secure context`;
137 case Protocol.Page.SecureContextType.InsecureAncestor:
138 return ls`A frame ancestor is an insecure context`;
139 case Protocol.Page.SecureContextType.InsecureScheme:
140 return ls`The frame's scheme is insecure`;
141 }
142 return null;
143 }
144
Wolfgang Beyer309863f2021-01-21 09:01:21145 _updateContextStatus(): void {
Sigurd Schneideraef29822020-08-20 14:01:13146 if (this._frame.unreachableUrl()) {
147 this._isolationSection.setFieldVisible(ls`Secure Context`, false);
Sigurd Schneidercea65762020-10-19 09:47:50148 this._isolationSection.setFieldVisible(ls`Cross-Origin Isolated`, false);
Sigurd Schneideraef29822020-08-20 14:01:13149 return;
150 }
151 this._isolationSection.setFieldVisible(ls`Secure Context`, true);
Sigurd Schneidercea65762020-10-19 09:47:50152 this._isolationSection.setFieldVisible(ls`Cross-Origin Isolated`, true);
153
Sigurd Schneideraef29822020-08-20 14:01:13154 this._secureContext.textContent = booleanToYesNo(this._frame.isSecureContext());
155 const secureContextExplanation = this._explanationFromSecureContextType(this._frame.getSecureContextType());
156 if (secureContextExplanation) {
Sigurd Schneidercea65762020-10-19 09:47:50157 const secureContextType = this._secureContext.createChild('span', 'inline-comment');
Sigurd Schneideraef29822020-08-20 14:01:13158 secureContextType.textContent = secureContextExplanation;
159 }
Sigurd Schneidercea65762020-10-19 09:47:50160 this._crossOriginIsolatedContext.textContent = booleanToYesNo(this._frame.isCrossOriginIsolated());
Sigurd Schneideraef29822020-08-20 14:01:13161 }
162
Wolfgang Beyer309863f2021-01-21 09:01:21163 _updateApiAvailability(): void {
Sigurd Schneidereabef962020-11-05 10:51:49164 const features = this._frame.getGatedAPIFeatures();
Tim van der Lipped7cfd142021-01-07 12:17:24165 this._apiAvailability.setFieldVisible(ls`Shared Array Buffers`, Boolean(features));
Sigurd Schneidereabef962020-11-05 10:51:49166
167 if (!features) {
168 return;
169 }
170 const sabAvailable = features.includes(Protocol.Page.GatedAPIFeatures.SharedArrayBuffers);
171 if (sabAvailable) {
172 const sabTransferAvailable = features.includes(Protocol.Page.GatedAPIFeatures.SharedArrayBuffersTransferAllowed);
173 this._apiSharedArrayBuffer.textContent =
174 sabTransferAvailable ? ls`available, transferable` : ls`available, not transferable`;
Tim van der Lippe420e5e32020-11-23 16:58:46175 UI.Tooltip.Tooltip.install(
176 this._apiSharedArrayBuffer,
177 sabTransferAvailable ?
178 ls`SharedArrayBuffer constructor is available and SABs can be transferred via postMessage` :
179 ls`SharedArrayBuffer constructor is available but SABs cannot be transferred via postMessage`);
Sigurd Schneidereabef962020-11-05 10:51:49180 if (!this._frame.isCrossOriginIsolated()) {
181 const reasonHint = this._apiSharedArrayBuffer.createChild('span', 'inline-span');
182 reasonHint.textContent = ls`⚠️ will require cross-origin isolated context in the future`;
183 }
184 } else {
185 this._apiSharedArrayBuffer.textContent = ls`unavailable`;
186 if (!this._frame.isCrossOriginIsolated()) {
187 const reasonHint = this._apiSharedArrayBuffer.createChild('span', 'inline-comment');
188 reasonHint.textContent = ls`requires cross-origin isolated context`;
189 }
190 }
Sigurd Schneider12cf8692021-01-11 15:21:00191
192 const measureMemoryAvailable = this._frame.isCrossOriginIsolated();
193 UI.Tooltip.Tooltip.install(
194 this._apiMeasureMemory,
Sigurd Schneiderbf1327b2021-01-22 14:25:48195 measureMemoryAvailable ? ls`The performance.measureUserAgentSpecificMemory() API is available` :
196 ls`The performance.measureUserAgentSpecificMemory() API is not available`);
Sigurd Schneider12cf8692021-01-11 15:21:00197 this._apiMeasureMemory.textContent = '';
Sigurd Schneider2d4d9af2021-01-25 12:12:27198 const status = measureMemoryAvailable ? ls`available` : ls`unavailable`;
Sigurd Schneider12cf8692021-01-11 15:21:00199 const link = 'https://web.dev/monitor-total-page-memory-usage/';
200 this._apiMeasureMemory.appendChild(
201 UI.Fragment.html`<div>${status} ${UI.XLink.XLink.create(link, ls`Learn more`)}</div>`);
Sigurd Schneidereabef962020-11-05 10:51:49202 }
Wolfgang Beyer760462e2020-07-13 15:01:35203}
Wolfgang Beyer3b4747f2020-08-12 07:30:46204
Wolfgang Beyer92395c92021-02-02 10:43:23205export interface FrameDetailsReportViewData {
206 frame: SDK.ResourceTreeModel.ResourceTreeFrame;
207}
208
209export class FrameDetailsReportView extends HTMLElement {
210 private readonly shadow = this.attachShadow({mode: 'open'});
211 private frame?: SDK.ResourceTreeModel.ResourceTreeFrame;
212
213 set data(data: FrameDetailsReportViewData) {
214 this.frame = data.frame;
215 this.render();
216 }
217
218 private async render(): Promise<void> {
219 if (!this.frame) {
220 return;
221 }
222
223 // Disabled until https://crbug.com/1079231 is fixed.
224 // clang-format off
225 LitHtml.render(LitHtml.html`
Wolfgang Beyer1525b1f2021-02-02 14:12:30226 <style>
227 .text-ellipsis {
228 overflow: hidden;
229 text-overflow: ellipsis;
230 white-space: nowrap;
231 }
232
233 button ~ .text-ellipsis {
234 padding-left: 2px;
235 }
236
237 .link {
238 color: var(--color-link);
239 text-decoration: underline;
240 cursor: pointer;
241 padding: 2px 0; /* adjust focus ring size */
242 }
243
244 button.link {
245 border: none;
246 background: none;
247 font-family: inherit;
248 font-size: inherit;
249 }
250
251 .inline-items {
252 display: flex;
253 }
254 </style>
Wolfgang Beyer92395c92021-02-02 10:43:23255 <devtools-report .data=${{reportTitle: this.frame.displayName()} as Components.ReportView.ReportData}>
Wolfgang Beyer1525b1f2021-02-02 14:12:30256 ${this.renderDocumentSection()}
Wolfgang Beyer92395c92021-02-02 10:43:23257 </devtools-report>
258 `, this.shadow);
259 // clang-format on
260 }
Wolfgang Beyer1525b1f2021-02-02 14:12:30261
262 private renderDocumentSection(): LitHtml.TemplateResult|{} {
263 if (!this.frame) {
264 return LitHtml.nothing;
265 }
266
267 return LitHtml.html`
268 <devtools-report-section-header>${ls`Document`}</devtools-report-section-header>
269 <devtools-report-key>${ls`URL`}</devtools-report-key>
270 <devtools-report-value>
271 <div class="inline-items">
272 ${this.maybeRenderSourcesLinkForURL()}
273 ${this.maybeRenderNetworkLinkForURL()}
274 <div class="text-ellipsis" title=${this.frame.url}>${this.frame.url}</div>
275 </div>
276 </devtools-report-value>
277 ${this.maybeRenderUnreachableURL()}
278 ${this.maybeRenderOrigin()}
279 ${LitHtml.Directives.until(this.renderOwnerElement(), LitHtml.nothing)}
280 ${this.maybeRenderAdStatus()}
281 <devtools-report-divider></devtools-report-divider>
282 `;
283 }
284
285 private maybeRenderSourcesLinkForURL(): LitHtml.TemplateResult|{} {
286 if (!this.frame || this.frame.unreachableUrl()) {
287 return LitHtml.nothing;
288 }
289 const sourceCode = this.uiSourceCodeForFrame(this.frame);
290 return this.renderIconLink(
291 'sources_panel_icon',
292 ls`Click to reveal in Sources panel`,
293 (): Promise<void> => Common.Revealer.reveal(sourceCode),
294 );
295 }
296
297 private maybeRenderNetworkLinkForURL(): LitHtml.TemplateResult|{} {
298 if (this.frame) {
299 const resource = this.frame.resourceForURL(this.frame.url);
300 if (resource && resource.request) {
301 const request = resource.request;
302 return this.renderIconLink(
303 'network_panel_icon',
304 ls`Click to reveal in Network panel`,
305 (): Promise<void> =>
306 Network.NetworkPanel.NetworkPanel.selectAndShowRequest(request, Network.NetworkItemView.Tabs.Headers),
307 );
308 }
309 }
310 return LitHtml.nothing;
311 }
312
313 private renderIconLink(
314 iconName: string, title: Platform.UIString.LocalizedString,
315 clickHandler: (() => void)|(() => Promise<void>)): LitHtml.TemplateResult {
316 // Disabled until https://crbug.com/1079231 is fixed.
317 // clang-format off
318 return LitHtml.html`
319 <button class="link" role="link" tabindex=0 @click=${clickHandler} title=${title}>
320 <devtools-icon .data=${{
321 iconName: iconName,
322 color: 'var(--color-primary)',
323 width: '16px',
324 height: '16px',
325 } as Components.Icon.IconData}>
326 </button>
327 `;
328 // clang-format on
329 }
330
331 private uiSourceCodeForFrame(frame: SDK.ResourceTreeModel.ResourceTreeFrame): Workspace.UISourceCode.UISourceCode
332 |null {
333 for (const project of Workspace.Workspace.WorkspaceImpl.instance().projects()) {
334 const projectTarget = Bindings.NetworkProject.NetworkProject.getTargetForProject(project);
335 if (projectTarget && projectTarget === frame.resourceTreeModel().target()) {
336 const uiSourceCode = project.uiSourceCodeForURL(frame.url);
337 if (uiSourceCode) {
338 return uiSourceCode;
339 }
340 }
341 }
342 return null;
343 }
344
345 private maybeRenderUnreachableURL(): LitHtml.TemplateResult|{} {
346 if (!this.frame || !this.frame.unreachableUrl()) {
347 return LitHtml.nothing;
348 }
349 return LitHtml.html`
350 <devtools-report-key>${ls`Unreachable URL`}</devtools-report-key>
351 <devtools-report-value>
352 <div class="inline-items">
353 ${this.renderNetworkLinkForUnreachableURL()}
354 <div class="text-ellipsis" title=${this.frame.unreachableUrl()}>${this.frame.unreachableUrl()}</div>
355 </div>
356 </devtools-report-value>
357 `;
358 }
359
360 private renderNetworkLinkForUnreachableURL(): LitHtml.TemplateResult|{} {
361 if (this.frame) {
362 const unreachableUrl = Common.ParsedURL.ParsedURL.fromString(this.frame.unreachableUrl());
363 if (unreachableUrl) {
364 return this.renderIconLink(
365 'network_panel_icon',
366 ls`Click to reveal in Network panel (might require page reload)`,
367 ():
368 void => {
369 Network.NetworkPanel.NetworkPanel.revealAndFilter([
370 {
371 filterType: 'domain',
372 filterValue: unreachableUrl.domain(),
373 },
374 {
375 filterType: null,
376 filterValue: unreachableUrl.path,
377 },
378 ]);
379 },
380 );
381 }
382 }
383 return LitHtml.nothing;
384 }
385
386 private maybeRenderOrigin(): LitHtml.TemplateResult|{} {
387 if (this.frame && this.frame.securityOrigin && this.frame.securityOrigin !== '://') {
388 return LitHtml.html`
389 <devtools-report-key>${ls`Origin`}</devtools-report-key>
390 <devtools-report-value>
391 <div class="text-ellipsis" title=${this.frame.securityOrigin}>${this.frame.securityOrigin}</div>
392 </devtools-report-value>
393 `;
394 }
395 return LitHtml.nothing;
396 }
397
398 private async renderOwnerElement(): Promise<LitHtml.TemplateResult|{}> {
399 if (this.frame) {
400 const openerFrame = this.frame instanceof SDK.ResourceTreeModel.ResourceTreeFrame ?
401 this.frame :
402 SDK.FrameManager.FrameManager.instance().getFrame(this.frame);
403 if (openerFrame) {
404 const linkTargetDOMNode = await openerFrame.getOwnerDOMNodeOrDocument();
405 if (linkTargetDOMNode) {
406 // Disabled until https://crbug.com/1079231 is fixed.
407 // clang-format off
408 return LitHtml.html`
409 <style>
410 .button-icon-with-text {
411 vertical-align: sub;
412 }
413 </style>
414 <devtools-report-key>${ls`Owner Element`}</devtools-report-key>
415 <devtools-report-value>
416 <button class="link" role="link" tabindex=0 title=${ls`Click to reveal in Elements panel`}
417 @mouseenter=${(): Promise<void> => openerFrame.highlight()}
418 @mouseleave=${(): void => SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight()}
419 @click=${(): Promise<void> => Common.Revealer.reveal(linkTargetDOMNode)}
420 >
421 <devtools-icon class="button-icon-with-text" .data=${{
422 iconName: 'elements_panel_icon',
423 color: 'var(--color-primary)',
424 width: '16px',
425 height: '16px',
426 } as Components.Icon.IconData}></devtools-icon>
427 <${linkTargetDOMNode.nodeName().toLocaleLowerCase()}>
428 </a>
429 </devtools-report-value>
430 `;
431 // clang-format on
432 }
433 }
434 }
435 return LitHtml.nothing;
436 }
437
438 private maybeRenderAdStatus(): LitHtml.TemplateResult|{} {
439 if (this.frame) {
440 if (this.frame.adFrameType() === Protocol.Page.AdFrameType.Root) {
441 return LitHtml.html`
442 <devtools-report-key>${ls`Ad Status`}</devtools-report-key>
443 <devtools-report-value title=${ls`This frame has been identified as the root frame of an ad`}>${
444 ls`root`}</devtools-report-value>
445 `;
446 }
447 if (this.frame.adFrameType() === Protocol.Page.AdFrameType.Child) {
448 return LitHtml.html`
449 <devtools-report-key>${ls`Ad Status`}</devtools-report-key>
450 <devtools-report-value title=${ls`This frame has been identified as the a child frame of an ad`}>${
451 ls`child`}</devtools-report-value>
452 `;
453 }
454 }
455 return LitHtml.nothing;
456 }
Wolfgang Beyer92395c92021-02-02 10:43:23457}
458
459customElements.define('devtools-resources-frame-details-view', FrameDetailsReportView);
460
461declare global {
462 // eslint-disable-next-line @typescript-eslint/no-unused-vars
463 interface HTMLElementTagNameMap {
464 'devtools-resources-frame-details-view': FrameDetailsReportView;
465 }
466}