UNPKG

@yuebai008/cli

Version:

Command line interface for rapid qg-minigame development

16 lines 12.5 kB
import*as Host from"../../../core/host/host.js";import*as i18n from"../../../core/i18n/i18n.js";import*as IssuesManager from"../../../models/issues_manager/issues_manager.js";import*as NetworkForward from"../../../panels/network/forward/forward.js";import*as ComponentHelpers from"../../../ui/components/helpers/helpers.js";import*as LitHtml from"../../../ui/lit-html/lit-html.js";import*as Sources from"../../../panels/sources/sources.js";import*as UI from"../../../ui/legacy/legacy.js";import{compareHeaders,HeaderSectionRow}from"./HeaderSectionRow.js";import*as Persistence from"../../../models/persistence/persistence.js";import*as Platform from"../../../core/platform/platform.js";import*as Common from"../../../core/common/common.js";import*as Buttons from"../../../ui/components/buttons/buttons.js";import*as Root from"../../../core/root/root.js";import responseHeaderSectionStyles from"./ResponseHeaderSection.css.js";const{render:render,html:html}=LitHtml,UIStrings={addHeader:"Add header",chooseThisOptionIfTheResourceAnd:"Choose this option if the resource and the document are served from the same site.",onlyChooseThisOptionIfAn:"Only choose this option if an arbitrary website including this resource does not impose a security risk.",thisDocumentWasBlockedFrom:"The document was blocked from loading in a popup opened by a sandboxed iframe because this document specified a cross-origin opener policy.",toEmbedThisFrameInYourDocument:"To embed this frame in your document, the response needs to enable the cross-origin embedder policy by specifying the following response header:",toUseThisResourceFromADifferent:"To use this resource from a different origin, the server needs to specify a cross-origin resource policy in the response headers:",toUseThisResourceFromADifferentOrigin:"To use this resource from a different origin, the server may relax the cross-origin resource policy response header:",toUseThisResourceFromADifferentSite:"To use this resource from a different site, the server may relax the cross-origin resource policy response header:"},str_=i18n.i18n.registerUIStrings("panels/network/components/ResponseHeaderSection.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_),i18nLazyString=i18n.i18n.getLazilyComputedLocalizedString.bind(void 0,str_),plusIconUrl=new URL("../../../Images/plus.svg",import.meta.url).toString();export const RESPONSE_HEADER_SECTION_DATA_KEY="ResponseHeaderSection";export class ResponseHeaderSection extends HTMLElement{static litTagName=LitHtml.literal`devtools-response-header-section`;#e=this.attachShadow({mode:"open"});#r;#s=[];#t=[];#o=null;#i=[];#a=!1;connectedCallback(){this.#e.adoptedStyleSheets=[responseHeaderSectionStyles]}set data(e){this.#r=e.request;const r=this.#r.sortedResponseHeaders.concat(this.#r.setCookieHeaders);r.sort((function(e,r){return Platform.StringUtilities.compare(e.name.toLowerCase(),r.name.toLowerCase())})),this.#s=r.map((e=>({name:Platform.StringUtilities.toLowerCaseString(e.name),value:e.value.replace(/\s/g," ")})));const s=[];if(this.#r.wasBlocked()){const e=BlockedReasonDetails.get(this.#r.blockedReason());if(e){if(IssuesManager.RelatedIssue.hasIssueOfCategory(this.#r,IssuesManager.Issue.IssueCategory.CrossOriginEmbedderPolicy)){const r=()=>{Host.userMetrics.issuesPanelOpenedFrom(Host.UserMetrics.IssueOpener.LearnMoreLinkCOEP),this.#r&&IssuesManager.RelatedIssue.reveal(this.#r,IssuesManager.Issue.IssueCategory.CrossOriginEmbedderPolicy)};e.blockedDetails&&(e.blockedDetails.reveal=r)}s.push(e)}}this.#s=function(e,r){let s=0,t=0;const o=[];for(;s<e.length&&t<r.length;)e[s].name<r[t].name?o.push({...e[s++],headerNotSet:!1}):e[s].name>r[t].name?o.push({...r[t++],headerNotSet:!0}):o.push({...r[t++],...e[s++],headerNotSet:!1});for(;s<e.length;)o.push({...e[s++],headerNotSet:!1});for(;t<r.length;)o.push({...r[t++],headerNotSet:!0});return o}(this.#s,s);const t=this.#r.blockedResponseCookies(),o=new Map(t?.map((e=>[e.cookieLine.replace(/\s/g," "),e.blockedReasons])));for(const e of this.#s)if("set-cookie"===e.name&&e.value){const r=o.get(e.value);r&&(e.setCookieBlockedReasons=r)}e.toReveal?.section===NetworkForward.UIRequestLocation.UIHeaderSection.Response&&this.#s.filter((r=>compareHeaders(r.name,e.toReveal?.header?.toLowerCase()))).forEach((e=>{e.highlight=!0}));const i=this.#r.getAssociatedData("ResponseHeaderSection");i?this.#t=i:(this.#t=this.#s.map((e=>({name:e.name,value:e.value,originalValue:e.value}))),this.#n()),this.#d(),this.#r.setAssociatedData("ResponseHeaderSection",this.#t),this.#c()}#l(){this.#r&&(this.#a=!1,this.#t=this.#s.map((e=>({name:e.name,value:e.value,originalValue:e.value}))),this.#n(),this.#r.setAssociatedData("ResponseHeaderSection",this.#t))}async#d(){if(this.#r){if(this.#o=Persistence.NetworkPersistenceManager.NetworkPersistenceManager.instance().getHeadersUISourceCodeFromUrl(this.#r.url()),!this.#o)return this.#l(),void this.#c();try{const e=await this.#o.requestContent();if(this.#i=JSON.parse(e.content||"[]"),!this.#i.every(Persistence.NetworkPersistenceManager.isHeaderOverride))throw"Type mismatch after parsing";this.#a=Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.HEADER_OVERRIDES)&&Common.Settings.Settings.instance().moduleSetting("persistenceNetworkOverridesEnabled").get();for(const e of this.#t)e.valueEditable=this.#a}catch(e){console.error("Failed to parse",this.#o?.url()||"source code file","for locally overriding headers."),this.#l()}finally{this.#c()}}}#n(){if(!this.#r||0===this.#r.originalResponseHeaders.length)return;const e=new Map;for(const r of this.#r?.originalResponseHeaders||[]){const s=Platform.StringUtilities.toLowerCaseString(r.name),t=e.get(s);t?t.push(r.value.replace(/\s/g," ")):e.set(s,[r.value.replace(/\s/g," ")])}const r=new Map;for(const e of this.#s){if(e.headerNotSet)continue;const s=r.get(e.name);s?s.push(e.value||""):r.set(e.name,[e.value||""])}const s=(e,r,s)=>{const t=r.get(e),o=s.get(e);if(!t||!o||t.length!==o.length)return!0;t.sort(),o.sort();for(let e=0;e<t.length;e++)if(!compareHeaders(t[e],o[e]))return!0;return!1};for(const t of r.keys())"set-cookie"!==t&&s(t,r,e)&&this.#t.filter((e=>compareHeaders(e.name,t))).forEach((e=>{e.isOverride=!0}));this.#t.filter((e=>"set-cookie"===e.name)).forEach((e=>{void 0===this.#r?.originalResponseHeaders.find((r=>"set-cookie"===Platform.StringUtilities.toLowerCaseString(r.name)&&compareHeaders(r.value,e.value)))&&(e.isOverride=!0)}))}#h(e){const r=e.target;if(void 0===r.dataset.index)return;const s=Number(r.dataset.index);this.#m(e.headerName,e.headerValue,s),Host.userMetrics.actionTaken(Host.UserMetrics.Action.HeaderOverrideHeaderEdited)}#u(e){const r=Persistence.NetworkPersistenceManager.NetworkPersistenceManager.instance().rawPathFromUrl(e,!0),s=r.lastIndexOf("/");return Common.ParsedURL.ParsedURL.substring(r,s+1)}#p(){this.#o?.setWorkingCopy(JSON.stringify(this.#i,null,2)),this.#o?.commitWorkingCopy()}#g(e,r,s){for(let t=this.#i.length-1;t>=0;t--){const o=this.#i[t];if(o.applyTo!==e)continue;const i=o.headers.findIndex((e=>compareHeaders(e.name,r)&&compareHeaders(e.value,s)));if(!(i<0))return o.headers.splice(i,1),void(0===o.headers.length&&this.#i.splice(t,1))}}#f(e){const r=e.target;if(void 0===r.dataset.index||!this.#r)return;const s=Number(r.dataset.index),t=this.#u(this.#r.url());this.#g(t,e.headerName,e.headerValue),this.#p(),this.#t[s].isDeleted=!0,this.#c(),Host.userMetrics.actionTaken(Host.UserMetrics.Action.HeaderOverrideHeaderRemoved)}#m(e,r,s){if(!this.#r)return;0===this.#r.originalResponseHeaders.length&&(this.#r.originalResponseHeaders=this.#r.sortedResponseHeaders.map((e=>({...e}))));const t=this.#t[s].name,o=this.#t[s].value;this.#t[s].name=e,this.#t[s].value=r;let i=[];"set-cookie"===e?i.push({name:e,value:r}):i=this.#t.filter((r=>compareHeaders(r.name,e)&&(!compareHeaders(r.value,r.originalValue)||r.isOverride)));const a=this.#u(this.#r.url());let n=null;const[d]=this.#i.slice(-1);if(d?.applyTo===a?n=d:(n={applyTo:a,headers:[]},this.#i.push(n)),"set-cookie"===e){const e=n.headers.findIndex((e=>compareHeaders(e.name,t)&&compareHeaders(e.value,o)));e>=0&&n.headers.splice(e,1)}else n.headers=n.headers.filter((r=>!compareHeaders(r.name,e)));if(!compareHeaders(this.#t[s].name,t))for(let e=0;e<n.headers.length;++e)if(compareHeaders(n.headers[e].name,t)&&compareHeaders(n.headers[e].value,o)){n.headers.splice(e,1);break}for(const e of i)n.headers.push({name:e.name,value:e.value||""});0===n.headers.length&&this.#i.pop(),this.#p()}#S(){this.#t.push({name:Platform.StringUtilities.toLowerCaseString(i18n.i18n.lockedString("header-name")),value:i18n.i18n.lockedString("header value"),isOverride:!0,nameEditable:!0,valueEditable:!0});const e=this.#t.length-1;this.#m(this.#t[e].name,this.#t[e].value||"",e),this.#c();const r=this.#e.querySelectorAll("devtools-header-section-row"),[s]=Array.from(r).slice(-1);s?.focus(),Host.userMetrics.actionTaken(Host.UserMetrics.Action.HeaderOverrideHeaderAdded)}#c(){if(!this.#r)return;const e=this.#t.map(((e,r)=>({...this.#s[r],...e,isResponseHeader:!0})));render(html` ${e.map(((e,r)=>html` <${HeaderSectionRow.litTagName} .data=${{header:e}} @headeredited=${this.#h} @headerremoved=${this.#f} @enableheaderediting=${this.#v} data-index=${r}></${HeaderSectionRow.litTagName}> `))} ${this.#a?html` <${Buttons.Button.Button.litTagName} class="add-header-button" .variant=${"secondary"} .iconUrl=${plusIconUrl} .iconWidth=${"12px"} .iconHeight=${"12px"} @click=${this.#S}> ${i18nString(UIStrings.addHeader)} </${Buttons.Button.Button.litTagName}> `:LitHtml.nothing} `,this.#e,{host:this})}async#v(){if(!this.#r)return;Host.userMetrics.actionTaken(Host.UserMetrics.Action.HeaderOverrideEnableEditingClicked);const e=this.#r.url(),r=Persistence.NetworkPersistenceManager.NetworkPersistenceManager.instance();r.project()?(Common.Settings.Settings.instance().moduleSetting("persistenceNetworkOverridesEnabled").set(!0),await r.getOrCreateHeadersUISourceCodeFromUrl(e)):UI.InspectorView.InspectorView.instance().displaySelectOverrideFolderInfobar((async()=>{await Sources.SourcesNavigator.OverridesNavigatorView.instance().setupNewWorkspace(),await r.getOrCreateHeadersUISourceCodeFromUrl(e)}))}}ComponentHelpers.CustomElements.defineComponent("devtools-response-header-section",ResponseHeaderSection);const BlockedReasonDetails=new Map([["coep-frame-resource-needs-coep-header",{name:Platform.StringUtilities.toLowerCaseString("cross-origin-embedder-policy"),value:null,blockedDetails:{explanation:i18nLazyString(UIStrings.toEmbedThisFrameInYourDocument),examples:[{codeSnippet:"Cross-Origin-Embedder-Policy: require-corp",comment:void 0}],link:{url:"https://web.dev/coop-coep/"}}}],["corp-not-same-origin-after-defaulted-to-same-origin-by-coep",{name:Platform.StringUtilities.toLowerCaseString("cross-origin-resource-policy"),value:null,blockedDetails:{explanation:i18nLazyString(UIStrings.toUseThisResourceFromADifferent),examples:[{codeSnippet:"Cross-Origin-Resource-Policy: same-site",comment:i18nLazyString(UIStrings.chooseThisOptionIfTheResourceAnd)},{codeSnippet:"Cross-Origin-Resource-Policy: cross-origin",comment:i18nLazyString(UIStrings.onlyChooseThisOptionIfAn)}],link:{url:"https://web.dev/coop-coep/"}}}],["coop-sandboxed-iframe-cannot-navigate-to-coop-page",{name:Platform.StringUtilities.toLowerCaseString("cross-origin-opener-policy"),value:null,headerValueIncorrect:!1,blockedDetails:{explanation:i18nLazyString(UIStrings.thisDocumentWasBlockedFrom),examples:[],link:{url:"https://web.dev/coop-coep/"}}}],["corp-not-same-site",{name:Platform.StringUtilities.toLowerCaseString("cross-origin-resource-policy"),value:null,headerValueIncorrect:!0,blockedDetails:{explanation:i18nLazyString(UIStrings.toUseThisResourceFromADifferentSite),examples:[{codeSnippet:"Cross-Origin-Resource-Policy: cross-origin",comment:i18nLazyString(UIStrings.onlyChooseThisOptionIfAn)}],link:null}}],["corp-not-same-origin",{name:Platform.StringUtilities.toLowerCaseString("cross-origin-resource-policy"),value:null,headerValueIncorrect:!0,blockedDetails:{explanation:i18nLazyString(UIStrings.toUseThisResourceFromADifferentOrigin),examples:[{codeSnippet:"Cross-Origin-Resource-Policy: same-site",comment:i18nLazyString(UIStrings.chooseThisOptionIfTheResourceAnd)},{codeSnippet:"Cross-Origin-Resource-Policy: cross-origin",comment:i18nLazyString(UIStrings.onlyChooseThisOptionIfAn)}],link:null}}]]);