UNPKG

@quick-game/cli

Version:

Command line interface for rapid qg development

200 lines 10.4 kB
// Copyright 2021 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as i18n from '../../../core/i18n/i18n.js'; import * as SDK from '../../../core/sdk/sdk.js'; import * as NetworkForward from '../../../panels/network/forward/forward.js'; import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js'; import * as IconButton from '../../../ui/components/icon_button/icon_button.js'; import * as Coordinator from '../../../ui/components/render_coordinator/render_coordinator.js'; import * as ReportView from '../../../ui/components/report_view/report_view.js'; import * as LitHtml from '../../../ui/lit-html/lit-html.js'; import permissionsPolicySectionStyles from './permissionsPolicySection.css.js'; import * as Common from '../../../core/common/common.js'; const UIStrings = { /** *@description Label for a button. When clicked more details (for the content this button refers to) will be shown. */ showDetails: 'Show details', /** *@description Label for a button. When clicked some details (for the content this button refers to) will be hidden. */ hideDetails: 'Hide details', /** *@description Label for a list of features which are allowed according to the current Permissions policy *(a mechanism that allows developers to enable/disable browser features and APIs (e.g. camera, geolocation, autoplay)) */ allowedFeatures: 'Allowed Features', /** *@description Label for a list of features which are disabled according to the current Permissions policy *(a mechanism that allows developers to enable/disable browser features and APIs (e.g. camera, geolocation, autoplay)) */ disabledFeatures: 'Disabled Features', /** *@description Tooltip text for a link to a specific request's headers in the Network panel. */ clickToShowHeader: 'Click to reveal the request whose "`Permissions-Policy`" HTTP header disables this feature.', /** *@description Tooltip text for a link to a specific iframe in the Elements panel (Iframes can be nested, the link goes * to the outer-most iframe which blocks a certain feature). */ clickToShowIframe: 'Click to reveal the top-most iframe which does not allow this feature in the elements panel.', /** *@description Text describing that a specific feature is blocked by not being included in the iframe's "allow" attribute. */ disabledByIframe: 'missing in iframe "`allow`" attribute', /** *@description Text describing that a specific feature is blocked by a Permissions Policy specified in a request header. */ disabledByHeader: 'disabled by "`Permissions-Policy`" header', /** *@description Text describing that a specific feature is blocked by virtue of being inside a fenced frame tree. */ disabledByFencedFrame: 'disabled inside a `fencedframe`', }; const str_ = i18n.i18n.registerUIStrings('panels/application/components/PermissionsPolicySection.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); const coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance(); export function renderIconLink(iconName, title, clickHandler) { // Disabled until https://crbug.com/1079231 is fixed. // clang-format off return LitHtml.html ` <button class="link" role="link" tabindex=0 @click=${clickHandler} title=${title}> <${IconButton.Icon.Icon.litTagName} .data=${{ iconName: iconName, color: 'var(--icon-link)', width: '16px', height: '16px', }}> </${IconButton.Icon.Icon.litTagName}> </button> `; // clang-format on } export class PermissionsPolicySection extends HTMLElement { static litTagName = LitHtml.literal `devtools-resources-permissions-policy-section`; #shadow = this.attachShadow({ mode: 'open' }); #permissionsPolicySectionData = { policies: [], showDetails: false }; set data(data) { this.#permissionsPolicySectionData = data; void this.#render(); } connectedCallback() { this.#shadow.adoptedStyleSheets = [permissionsPolicySectionStyles]; } #toggleShowPermissionsDisallowedDetails() { this.#permissionsPolicySectionData.showDetails = !this.#permissionsPolicySectionData.showDetails; void this.#render(); } #renderAllowed() { const allowed = this.#permissionsPolicySectionData.policies.filter(p => p.allowed).map(p => p.feature).sort(); if (!allowed.length) { return LitHtml.nothing; } return LitHtml.html ` <${ReportView.ReportView.ReportKey.litTagName}>${i18nString(UIStrings.allowedFeatures)}</${ReportView.ReportView.ReportKey.litTagName}> <${ReportView.ReportView.ReportValue.litTagName}> ${allowed.join(', ')} </${ReportView.ReportView.ReportValue.litTagName}> `; } async #renderDisallowed() { const disallowed = this.#permissionsPolicySectionData.policies.filter(p => !p.allowed) .sort((a, b) => a.feature.localeCompare(b.feature)); if (!disallowed.length) { return LitHtml.nothing; } if (!this.#permissionsPolicySectionData.showDetails) { return LitHtml.html ` <${ReportView.ReportView.ReportKey.litTagName}>${i18nString(UIStrings.disabledFeatures)}</${ReportView.ReportView.ReportKey.litTagName}> <${ReportView.ReportView.ReportValue.litTagName}> ${disallowed.map(p => p.feature).join(', ')} <button class="link" @click=${() => this.#toggleShowPermissionsDisallowedDetails()}> ${i18nString(UIStrings.showDetails)} </button> </${ReportView.ReportView.ReportValue.litTagName}> `; } const frameManager = SDK.FrameManager.FrameManager.instance(); const featureRows = await Promise.all(disallowed.map(async (policy) => { const frame = policy.locator ? frameManager.getFrame(policy.locator.frameId) : null; const blockReason = policy.locator?.blockReason; const linkTargetDOMNode = await (blockReason === "IframeAttribute" /* Protocol.Page.PermissionsPolicyBlockReason.IframeAttribute */ && frame && frame.getOwnerDOMNodeOrDocument()); const resource = frame && frame.resourceForURL(frame.url); const linkTargetRequest = blockReason === "Header" /* Protocol.Page.PermissionsPolicyBlockReason.Header */ && resource && resource.request; const blockReasonText = (() => { switch (blockReason) { case "IframeAttribute" /* Protocol.Page.PermissionsPolicyBlockReason.IframeAttribute */: return i18nString(UIStrings.disabledByIframe); case "Header" /* Protocol.Page.PermissionsPolicyBlockReason.Header */: return i18nString(UIStrings.disabledByHeader); case "InFencedFrameTree" /* Protocol.Page.PermissionsPolicyBlockReason.InFencedFrameTree */: return i18nString(UIStrings.disabledByFencedFrame); default: return ''; } })(); const revealHeader = async () => { if (!linkTargetRequest) { return; } const headerName = linkTargetRequest.responseHeaderValue('permissions-policy') ? 'permissions-policy' : 'feature-policy'; const requestLocation = NetworkForward.UIRequestLocation.UIRequestLocation.responseHeaderMatch(linkTargetRequest, { name: headerName, value: '' }); await Common.Revealer.reveal(requestLocation); }; // Disabled until https://crbug.com/1079231 is fixed. // clang-format off return LitHtml.html ` <div class="permissions-row"> <div> <${IconButton.Icon.Icon.litTagName} class="allowed-icon" .data=${{ color: 'var(--icon-error)', iconName: 'cross-circle', width: '20px', height: '20px', }}> </${IconButton.Icon.Icon.litTagName}> </div> <div class="feature-name text-ellipsis"> ${policy.feature} </div> <div class="block-reason">${blockReasonText}</div> <div> ${linkTargetDOMNode ? renderIconLink('code-circle', i18nString(UIStrings.clickToShowIframe), () => Common.Revealer.reveal(linkTargetDOMNode)) : LitHtml.nothing} ${linkTargetRequest ? renderIconLink('arrow-up-down-circle', i18nString(UIStrings.clickToShowHeader), revealHeader) : LitHtml.nothing} </div> </div> `; // clang-format on })); return LitHtml.html ` <${ReportView.ReportView.ReportKey.litTagName}>${i18nString(UIStrings.disabledFeatures)}</${ReportView.ReportView.ReportKey.litTagName}> <${ReportView.ReportView.ReportValue.litTagName} class="policies-list"> ${featureRows} <div class="permissions-row"> <button class="link" @click=${() => this.#toggleShowPermissionsDisallowedDetails()}> ${i18nString(UIStrings.hideDetails)} </button> </div> </${ReportView.ReportView.ReportValue.litTagName}> `; } async #render() { await coordinator.write('PermissionsPolicySection render', () => { // Disabled until https://crbug.com/1079231 is fixed. // clang-format off LitHtml.render(LitHtml.html ` <${ReportView.ReportView.ReportSectionHeader.litTagName}>${i18n.i18n.lockedString('Permissions Policy')}</${ReportView.ReportView.ReportSectionHeader.litTagName}> ${this.#renderAllowed()} ${LitHtml.Directives.until(this.#renderDisallowed(), LitHtml.nothing)} <${ReportView.ReportView.ReportSectionDivider.litTagName}></${ReportView.ReportView.ReportSectionDivider.litTagName}> `, this.#shadow, { host: this }); // clang-format on }); } } ComponentHelpers.CustomElements.defineComponent('devtools-resources-permissions-policy-section', PermissionsPolicySection); //# sourceMappingURL=PermissionsPolicySection.js.map