import*as Bindings from"../bindings/bindings.js";import*as Common from"../common/common.js";import*as LitHtml from"../third_party/lit-html/lit-html.js";import*as Network from"../network/network.js";import*as Root from"../root/root.js";import*as SDK from"../sdk/sdk.js";import*as UI from"../ui/ui.js";import*as Workspace from"../workspace/workspace.js";import*as i18n from"../i18n/i18n.js";const UIStrings={additionalInformation:"Additional Information",thisAdditionalDebugging:"This additional (debugging) information is shown because the 'Protocol Monitor' experiment is enabled.",frameId:"Frame ID",document:"Document",url:"URL",clickToRevealInSourcesPanel:"Click to reveal in Sources panel",clickToRevealInNetworkPanel:"Click to reveal in Network panel",unreachableUrl:"Unreachable URL",clickToRevealInNetworkPanelMight:"Click to reveal in Network panel (might require page reload)",origin:"Origin",ownerElement:"Owner Element",clickToRevealInElementsPanel:"Click to reveal in Elements panel",adStatus:"Ad Status",thisFrameHasBeenIdentifiedAsThe:"This frame has been identified as the root frame of an ad",root:"root",thisFrameHasBeenIdentifiedAsTheA:"This frame has been identified as a child frame of an ad",child:"child",securityIsolation:"Security & Isolation",secureContext:"Secure Context",yes:"Yes",no:"No",crossoriginIsolated:"Cross-Origin Isolated",localhostIsAlwaysASecureContext:"Localhost is always a secure context",aFrameAncestorIsAnInsecure:"A frame ancestor is an insecure context",theFramesSchemeIsInsecure:"The frame's scheme is insecure",crossoriginEmbedderPolicy:"Cross-Origin Embedder Policy",crossoriginOpenerPolicy:"Cross-Origin Opener Policy",reportingTo:"reporting to",apiAvailability:"API availability",availabilityOfCertainApisDepends:"Availability of certain APIs depends on the document being cross-origin isolated.",availableTransferable:"available, transferable",availableNotTransferable:"available, not transferable",unavailable:"unavailable",sharedarraybufferConstructorIs:"SharedArrayBuffer constructor is available and SABs can be transferred via postMessage",sharedarraybufferConstructorIsAvailable:"SharedArrayBuffer constructor is available but SABs cannot be transferred via postMessage",WillRequireCrossoriginIsolated:"\u26a0\ufe0f will require cross-origin isolated context in the future",requiresCrossoriginIsolated:"requires cross-origin isolated context",available:"available",thePerformanceAPI:"The performance.measureUserAgentSpecificMemory() API is available",thePerformancemeasureuseragentspecificmemory:"The performance.measureUserAgentSpecificMemory() API is not available",measureMemory:"Measure Memory",learnMore:"Learn more"},str_=i18n.i18n.registerUIStrings("resources/FrameDetailsView.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);export class FrameDetailsView extends UI.ThrottledWidget.ThrottledWidget{constructor(e){super(),this.reportView=new FrameDetailsReportView,this.frame=e,this.contentElement.classList.add("overflow-auto"),this.contentElement.appendChild(this.reportView),this.update()}async doUpdate(){this.reportView.data={frame:this.frame}}}export class FrameDetailsReportView extends HTMLElement{constructor(){super(...arguments),this.shadow=this.attachShadow({mode:"open"}),this.protocolMonitorExperimentEnabled=!1}connectedCallback(){this.protocolMonitorExperimentEnabled=Root.Runtime.experiments.isEnabled("protocolMonitor")}set data(e){this.frame=e.frame,this.render()}async render(){this.frame&&LitHtml.render(LitHtml.html`
      <style>
        .text-ellipsis {
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }

        button ~ .text-ellipsis {
          padding-left: 2px;
        }

        .link {
          color: var(--color-link);
          text-decoration: underline;
          cursor: pointer;
          padding: 2px 0; /* adjust focus ring size */
        }

        button.link {
          border: none;
          background: none;
          font-family: inherit;
          font-size: inherit;
        }

        .inline-comment {
          padding-left: 1ex;
          white-space: pre-line;
        }

        .inline-comment::before {
          content: "(";
        }

        .inline-comment::after {
          content: ")";
        }

        .inline-name {
          color: var(--color-text-secondary);
          padding-left: 2ex;
          user-select: none;
          white-space: pre-line;
        }

        .inline-name::after {
          content: ':\u00a0';
        }

        .inline-items {
          display: flex;
        }
      </style>
      <devtools-report .data=${{reportTitle:this.frame.displayName()}}>
        ${this.renderDocumentSection()}
        ${this.renderIsolationSection()}
        ${this.renderApiAvailabilitySection()}
        ${LitHtml.Directives.until(this.renderPermissionPolicy(),LitHtml.nothing)}
        ${this.protocolMonitorExperimentEnabled?this.renderAdditionalInfoSection():LitHtml.nothing}
      </devtools-report>
    `,this.shadow)}async renderPermissionPolicy(){const e=await(this.frame&&this.frame.getPermissionsPolicyState());if(!e)return LitHtml.nothing;const t=e.filter((e=>e.allowed)).map((e=>e.feature)).sort(),r=e.filter((e=>!e.allowed)).map((e=>e.feature)).sort();return LitHtml.html`<devtools-report-section-header>Permissions Policy</devtools-report-section-header>
    ${t.length?LitHtml.html`<devtools-report-key>Allowed Features</devtools-report-key>
    <devtools-report-value>${t.join(", ")}</devtools-report-value>`:LitHtml.nothing}
    ${r.length?LitHtml.html`<devtools-report-key>Disallowed Features</devtools-report-key>
    <devtools-report-value>${r.join(", ")}</devtools-report-value>`:LitHtml.nothing}
    `}renderDocumentSection(){return this.frame?LitHtml.html`
      <devtools-report-section-header>${i18nString(UIStrings.document)}</devtools-report-section-header>
      <devtools-report-key>${i18nString(UIStrings.url)}</devtools-report-key>
      <devtools-report-value>
        <div class="inline-items">
          ${this.maybeRenderSourcesLinkForURL()}
          ${this.maybeRenderNetworkLinkForURL()}
          <div class="text-ellipsis" title=${this.frame.url}>${this.frame.url}</div>
        </div>
      </devtools-report-value>
      ${this.maybeRenderUnreachableURL()}
      ${this.maybeRenderOrigin()}
      ${LitHtml.Directives.until(this.renderOwnerElement(),LitHtml.nothing)}
      ${this.maybeRenderAdStatus()}
      <devtools-report-divider></devtools-report-divider>
    `:LitHtml.nothing}maybeRenderSourcesLinkForURL(){if(!this.frame||this.frame.unreachableUrl())return LitHtml.nothing;const e=this.uiSourceCodeForFrame(this.frame);return this.renderIconLink("sources_panel_icon",i18nString(UIStrings.clickToRevealInSourcesPanel),(()=>Common.Revealer.reveal(e)))}maybeRenderNetworkLinkForURL(){if(this.frame){const e=this.frame.resourceForURL(this.frame.url);if(e&&e.request){const t=e.request;return this.renderIconLink("network_panel_icon",i18nString(UIStrings.clickToRevealInNetworkPanel),(()=>Network.NetworkPanel.NetworkPanel.selectAndShowRequest(t,Network.NetworkItemView.Tabs.Headers)))}}return LitHtml.nothing}renderIconLink(e,t,r){return LitHtml.html`
      <button class="link" role="link" tabindex=0 @click=${r} title=${t}>
        <devtools-icon .data=${{iconName:e,color:"var(--color-primary)",width:"16px",height:"16px"}}>
      </button>
    `}uiSourceCodeForFrame(e){for(const t of Workspace.Workspace.WorkspaceImpl.instance().projects()){const r=Bindings.NetworkProject.NetworkProject.getTargetForProject(t);if(r&&r===e.resourceTreeModel().target()){const r=t.uiSourceCodeForURL(e.url);if(r)return r}}return null}maybeRenderUnreachableURL(){return this.frame&&this.frame.unreachableUrl()?LitHtml.html`
      <devtools-report-key>${i18nString(UIStrings.unreachableUrl)}</devtools-report-key>
      <devtools-report-value>
        <div class="inline-items">
          ${this.renderNetworkLinkForUnreachableURL()}
          <div class="text-ellipsis" title=${this.frame.unreachableUrl()}>${this.frame.unreachableUrl()}</div>
        </div>
      </devtools-report-value>
    `:LitHtml.nothing}renderNetworkLinkForUnreachableURL(){if(this.frame){const e=Common.ParsedURL.ParsedURL.fromString(this.frame.unreachableUrl());if(e)return this.renderIconLink("network_panel_icon",i18nString(UIStrings.clickToRevealInNetworkPanelMight),(()=>{Network.NetworkPanel.NetworkPanel.revealAndFilter([{filterType:"domain",filterValue:e.domain()},{filterType:null,filterValue:e.path}])}))}return LitHtml.nothing}maybeRenderOrigin(){return this.frame&&this.frame.securityOrigin&&"://"!==this.frame.securityOrigin?LitHtml.html`
        <devtools-report-key>${i18nString(UIStrings.origin)}</devtools-report-key>
        <devtools-report-value>
          <div class="text-ellipsis" title=${this.frame.securityOrigin}>${this.frame.securityOrigin}</div>
        </devtools-report-value>
      `:LitHtml.nothing}async renderOwnerElement(){if(this.frame){const e=await this.frame.getOwnerDOMNodeOrDocument();if(e)return LitHtml.html`
          <style>
            .button-icon-with-text {
              vertical-align: sub;
            }

            .without-min-width {
              min-width: auto;
            }
          </style>
            <devtools-report-key>${i18nString(UIStrings.ownerElement)}</devtools-report-key>
          <devtools-report-value class="without-min-width">
              <button class="link" role="link" tabindex=0 title=${i18nString(UIStrings.clickToRevealInElementsPanel)}
              @mouseenter=${()=>this.frame?.highlight()}
              @mouseleave=${()=>SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight()}
              @click=${()=>Common.Revealer.reveal(e)}
            >
              <devtools-icon class="button-icon-with-text" .data=${{iconName:"elements_panel_icon",color:"var(--color-primary)",width:"16px",height:"16px"}}></devtools-icon>
              <${e.nodeName().toLocaleLowerCase()}>
            </button>
          </devtools-report-value>
        `}return LitHtml.nothing}maybeRenderAdStatus(){if(this.frame){if(this.frame.adFrameType()===Protocol.Page.AdFrameType.Root)return LitHtml.html`
          <devtools-report-key>${i18nString(UIStrings.adStatus)}</devtools-report-key>
          <devtools-report-value title=${i18nString(UIStrings.thisFrameHasBeenIdentifiedAsThe)}>${i18nString(UIStrings.root)}</devtools-report-value>
        `;if(this.frame.adFrameType()===Protocol.Page.AdFrameType.Child)return LitHtml.html`
          <devtools-report-key>${i18nString(UIStrings.adStatus)}</devtools-report-key>
          <devtools-report-value title=${i18nString(UIStrings.thisFrameHasBeenIdentifiedAsTheA)}>${i18nString(UIStrings.child)}</devtools-report-value>
        `}return LitHtml.nothing}renderIsolationSection(){return this.frame?LitHtml.html`
      <devtools-report-section-header>${i18nString(UIStrings.securityIsolation)}</devtools-report-section-header>
      <devtools-report-key>${i18nString(UIStrings.secureContext)}</devtools-report-key>
      <devtools-report-value>
        ${this.frame.isSecureContext()?i18nString(UIStrings.yes):i18nString(UIStrings.no)}
        ${this.maybeRenderSecureContextExplanation()}
      </devtools-report-value>
      <devtools-report-key>${i18nString(UIStrings.crossoriginIsolated)}</devtools-report-key>
      <devtools-report-value>
        ${this.frame.isCrossOriginIsolated()?i18nString(UIStrings.yes):i18nString(UIStrings.no)}
      </devtools-report-value>
      ${LitHtml.Directives.until(this.maybeRenderCoopCoepStatus(),LitHtml.nothing)}
      <devtools-report-divider></devtools-report-divider>
    `:LitHtml.nothing}maybeRenderSecureContextExplanation(){const e=this.getSecureContextExplanation();return e?LitHtml.html`
        <span class="inline-comment">${e}</span>
      `:LitHtml.nothing}getSecureContextExplanation(){switch(this.frame?.getSecureContextType()){case Protocol.Page.SecureContextType.Secure:return null;case Protocol.Page.SecureContextType.SecureLocalhost:return i18nString(UIStrings.localhostIsAlwaysASecureContext);case Protocol.Page.SecureContextType.InsecureAncestor:return i18nString(UIStrings.aFrameAncestorIsAnInsecure);case Protocol.Page.SecureContextType.InsecureScheme:return i18nString(UIStrings.theFramesSchemeIsInsecure)}return null}async maybeRenderCoopCoepStatus(){if(this.frame){const e=this.frame.resourceTreeModel().target().model(SDK.NetworkManager.NetworkManager),t=e&&await e.getSecurityIsolationStatus(this.frame.id);if(t)return LitHtml.html`
          ${this.maybeRenderCrossOriginStatus(t.coep,i18nString(UIStrings.crossoriginEmbedderPolicy),Protocol.Network.CrossOriginEmbedderPolicyValue.None)}
          ${this.maybeRenderCrossOriginStatus(t.coop,i18nString(UIStrings.crossoriginOpenerPolicy),Protocol.Network.CrossOriginOpenerPolicyValue.UnsafeNone)}
        `}return LitHtml.nothing}maybeRenderCrossOriginStatus(e,t,r){if(!e)return LitHtml.nothing;const i=e.value!==r,o=!i&&e.reportOnlyValue!==r,n=i?e.reportingEndpoint:e.reportOnlyReportingEndpoint;return LitHtml.html`
      <devtools-report-key>${t}</devtools-report-key>
      <devtools-report-value>
        ${i?e.value:e.reportOnlyValue}
        ${o?LitHtml.html`<span class="inline-comment">report-only</span>`:LitHtml.nothing}
        ${n?LitHtml.html`<span class="inline-name">${i18nString(UIStrings.reportingTo)}</span>${n}`:LitHtml.nothing}
      </devtools-report-value>
    `}renderApiAvailabilitySection(){return this.frame?LitHtml.html`
      <style>
        .span-cols {
          grid-column-start: span 2;
          margin: 0 0 8px 30px;
          line-height: 28px;
        }
      </style>
      <devtools-report-section-header>${i18nString(UIStrings.apiAvailability)}</devtools-report-section-header>
      <div class="span-cols">
        ${i18nString(UIStrings.availabilityOfCertainApisDepends)}
        <x-link href="https://web.dev/why-coop-coep/" class="link">Learn more</x-link>
      </div>
      ${this.renderSharedArrayBufferAvailability()}
      ${this.renderMeasureMemoryAvailability()}
      <devtools-report-divider></devtools-report-divider>
    `:LitHtml.nothing}renderSharedArrayBufferAvailability(){if(this.frame){const e=this.frame.getGatedAPIFeatures();if(e){const t=e.includes(Protocol.Page.GatedAPIFeatures.SharedArrayBuffers),r=t&&e.includes(Protocol.Page.GatedAPIFeatures.SharedArrayBuffersTransferAllowed),i=i18nString(r?UIStrings.availableTransferable:t?UIStrings.availableNotTransferable:UIStrings.unavailable),o=r?i18nString(UIStrings.sharedarraybufferConstructorIs):t?i18nString(UIStrings.sharedarraybufferConstructorIsAvailable):"";return LitHtml.html`
          <devtools-report-key>SharedArrayBuffers</devtools-report-key>
          <devtools-report-value title=${o}>
            ${i}
            ${this.frame.isCrossOriginIsolated()?LitHtml.nothing:t?LitHtml.html`<span class="inline-comment">${i18nString(UIStrings.WillRequireCrossoriginIsolated)}</span>`:LitHtml.html`<span class="inline-comment">${i18nString(UIStrings.requiresCrossoriginIsolated)}</span>`}
          </devtools-report-value>
        `}}return LitHtml.nothing}renderMeasureMemoryAvailability(){if(this.frame){const e=this.frame.isCrossOriginIsolated(),t=i18nString(e?UIStrings.available:UIStrings.unavailable),r=i18nString(e?UIStrings.thePerformanceAPI:UIStrings.thePerformancemeasureuseragentspecificmemory);return LitHtml.html`
        <devtools-report-key>${i18nString(UIStrings.measureMemory)}</devtools-report-key>
        <devtools-report-value>
          <span title=${r}>${t}</span>
          <x-link class="link" href="https://web.dev/monitor-total-page-memory-usage/">${i18nString(UIStrings.learnMore)}</x-link>
        </devtools-report-value>
      `}return LitHtml.nothing}renderAdditionalInfoSection(){return this.frame?LitHtml.html`
      <devtools-report-section-header
        title=${i18nString(UIStrings.thisAdditionalDebugging)}
      >${i18nString(UIStrings.additionalInformation)}</devtools-report-section-header>
      <devtools-report-key>${i18nString(UIStrings.frameId)}</devtools-report-key>
      <devtools-report-value>
        <div class="text-ellipsis" title=${this.frame.id}>${this.frame.id}</div>
      </devtools-report-value>
      <devtools-report-divider></devtools-report-divider>
    `:LitHtml.nothing}}customElements.define("devtools-resources-frame-details-view",FrameDetailsReportView);