@quick-game/cli
Version:
Command line interface for rapid qg development
466 lines • 28.1 kB
JavaScript
// Copyright 2020 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 Host from '../../core/host/host.js';
import * as i18n from '../../core/i18n/i18n.js';
import * as Platform from '../../core/platform/platform.js';
import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
import * as NetworkForward from '../../panels/network/forward/forward.js';
import { AffectedResourcesView } from './AffectedResourcesView.js';
const UIStrings = {
/**
*@description Label for number of affected resources indication in issue view
*/
nRequests: '{n, plural, =1 {# request} other {# requests}}',
/**
*@description Value for the status column in SharedArrayBuffer issues
*/
warning: 'warning',
/**
*@description The kind of resolution for a mixed content issue
*/
blocked: 'blocked',
/**
*@description Text for the status column in the item list in the CORS issue details view
*/
status: 'Status',
/**
*@description Text for the column showing the associated network request in the item list in the CORS issue details view
*/
request: 'Request',
/**
*@description Text for the column showing the resource's address in the item list in the CORS issue details view
*/
resourceAddressSpace: 'Resource Address',
/**
*@description Text for the column showing the address of the resource load initiator in the item list in the CORS issue details view
*/
initiatorAddressSpace: 'Initiator Address',
/**
*@description Text for the status of the initiator context
*/
secure: 'secure',
/**
*@description Text for the status of the initiator context
*/
insecure: 'insecure',
/**
*@description Title for a column showing the status of the initiator context. The initiator context is either secure or insecure depending on whether it was loaded via HTTP or HTTPS.
*/
initiatorContext: 'Initiator Context',
/**
*@description Title for a column in the affected resources for a CORS issue showing a link to the associated preflight request in case the preflight request caused the issue.
*/
preflightRequestIfProblematic: 'Preflight Request (if problematic)',
/**
*@description Title for a column in the affected resources for a CORS issue showing a link to the associated preflight request.
*/
preflightRequest: 'Preflight Request',
/**
*@description Title for a column in the affected resources for a CORS issue showing the name of the problematic HTTP response header.
*/
header: 'Header',
/**
*@description Title for a column in the affected resources for a CORS issue showing the problem associated with the resource.
*/
problem: 'Problem',
/**
*@description Title for a column in the affected resources for a CORS issue showing the value that was invalid and caused the problem if it is available.
*/
invalidValue: 'Invalid Value (if available)',
/**
*@description Content for the problem column in the affected resources table for a CORS issue that indicates that a response header was missing.
*/
problemMissingHeader: 'Missing Header',
/**
*@description Content for the problem column in the affected resources table for a CORS issue that indicates that a response header contained multiple values.
*/
problemMultipleValues: 'Multiple Values',
/**
*@description Content for the problem column in the affected resources table for a CORS issue that indicates that a response header contained an invalid value.
*/
problemInvalidValue: 'Invalid Value',
/**
*@description Content for the problem column in the affected resources table for a CORS issue that indicates that the response to the preflight request was a redirect.
*/
preflightDisallowedRedirect: 'Response to preflight was a redirect',
/**
*@description Content for the problem column in the affected resources table for a CORS issue that indicates that the HTTP status the preflight request was not successful.
*/
preflightInvalidStatus: 'HTTP status of preflight request didn\'t indicate success',
/**
*@description Title for a column in the affected resources for a CORS issue showing the origin that was allowed according to CORS headers.
*/
allowedOrigin: 'Allowed Origin (from header)',
/**
*@description Title for a column in the affected resources for a CORS issue showing the value of the Access-Control-Allow-Credentials response header.
*/
allowCredentialsValueFromHeader: '`Access-Control-Allow-Credentials` Header Value',
/**
*@description Title for a column in the affected resources for a CORS issue showing the request method that was disallowed.
*/
disallowedRequestMethod: 'Disallowed Request Method',
/**
*@description Title for a column in the affected resources for a CORS issue showing the request header that was disallowed.
*/
disallowedRequestHeader: 'Disallowed Request Header',
/**
*@description Header for the source location column
*/
sourceLocation: 'Source Location',
/**
*@description Header for the column with the URL scheme that is not supported by fetch
*/
unsupportedScheme: 'Unsupported Scheme',
/**
*@description A failed network request.
*/
failedRequest: 'Failed Request',
};
const str_ = i18n.i18n.registerUIStrings('panels/issues/CorsIssueDetailsView.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
export class CorsIssueDetailsView extends AffectedResourcesView {
constructor(parent, issue) {
super(parent, issue);
this.affectedResourcesCountElement.classList.add('cors-issue-affected-resource-label');
}
#appendStatus(element, isWarning) {
const status = document.createElement('td');
if (isWarning) {
status.classList.add('affected-resource-report-only-status');
status.textContent = i18nString(UIStrings.warning);
}
else {
status.classList.add('affected-resource-blocked-status');
status.textContent = i18nString(UIStrings.blocked);
}
element.appendChild(status);
}
getResourceNameWithCount(count) {
return i18nString(UIStrings.nRequests, { n: count });
}
#appendDetails(issueCode, issues) {
const header = document.createElement('tr');
this.appendColumnTitle(header, i18nString(UIStrings.request));
this.appendColumnTitle(header, i18nString(UIStrings.status));
switch (issueCode) {
case IssuesManager.CorsIssue.IssueCode.InvalidHeaderValues:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequestIfProblematic));
this.appendColumnTitle(header, i18nString(UIStrings.header));
this.appendColumnTitle(header, i18nString(UIStrings.problem));
this.appendColumnTitle(header, i18nString(UIStrings.invalidValue));
break;
case IssuesManager.CorsIssue.IssueCode.WildcardOriginNotAllowed:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequestIfProblematic));
break;
case IssuesManager.CorsIssue.IssueCode.PreflightResponseInvalid:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequest));
this.appendColumnTitle(header, i18nString(UIStrings.problem));
break;
case IssuesManager.CorsIssue.IssueCode.OriginMismatch:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequestIfProblematic));
this.appendColumnTitle(header, i18nString(UIStrings.initiatorContext));
this.appendColumnTitle(header, i18nString(UIStrings.allowedOrigin));
break;
case IssuesManager.CorsIssue.IssueCode.AllowCredentialsRequired:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequestIfProblematic));
this.appendColumnTitle(header, i18nString(UIStrings.allowCredentialsValueFromHeader));
break;
case IssuesManager.CorsIssue.IssueCode.InsecurePrivateNetwork:
this.appendColumnTitle(header, i18nString(UIStrings.resourceAddressSpace));
this.appendColumnTitle(header, i18nString(UIStrings.initiatorAddressSpace));
this.appendColumnTitle(header, i18nString(UIStrings.initiatorContext));
break;
case IssuesManager.CorsIssue.IssueCode.PreflightAllowPrivateNetworkError:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequest));
this.appendColumnTitle(header, i18nString(UIStrings.invalidValue));
this.appendColumnTitle(header, i18nString(UIStrings.initiatorAddressSpace));
this.appendColumnTitle(header, i18nString(UIStrings.initiatorContext));
break;
case IssuesManager.CorsIssue.IssueCode.PreflightMissingPrivateNetworkAccessId:
case IssuesManager.CorsIssue.IssueCode.PreflightMissingPrivateNetworkAccessName:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequest));
this.appendColumnTitle(header, i18nString(UIStrings.invalidValue));
this.appendColumnTitle(header, i18nString(UIStrings.resourceAddressSpace));
this.appendColumnTitle(header, i18nString(UIStrings.initiatorAddressSpace));
this.appendColumnTitle(header, i18nString(UIStrings.initiatorContext));
break;
case IssuesManager.CorsIssue.IssueCode.MethodDisallowedByPreflightResponse:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequest));
this.appendColumnTitle(header, i18nString(UIStrings.disallowedRequestMethod));
break;
case IssuesManager.CorsIssue.IssueCode.HeaderDisallowedByPreflightResponse:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequest));
this.appendColumnTitle(header, i18nString(UIStrings.disallowedRequestHeader));
break;
case IssuesManager.CorsIssue.IssueCode.RedirectContainsCredentials:
// The default columns suffice.
break;
case IssuesManager.CorsIssue.IssueCode.DisallowedByMode:
this.appendColumnTitle(header, i18nString(UIStrings.initiatorContext));
this.appendColumnTitle(header, i18nString(UIStrings.sourceLocation));
break;
case IssuesManager.CorsIssue.IssueCode.CorsDisabledScheme:
this.appendColumnTitle(header, i18nString(UIStrings.initiatorContext));
this.appendColumnTitle(header, i18nString(UIStrings.sourceLocation));
this.appendColumnTitle(header, i18nString(UIStrings.unsupportedScheme));
break;
case IssuesManager.CorsIssue.IssueCode.NoCorsRedirectModeNotFollow:
this.appendColumnTitle(header, i18nString(UIStrings.sourceLocation));
break;
default:
Platform.assertUnhandled(issueCode);
}
this.affectedResources.appendChild(header);
let count = 0;
for (const issue of issues) {
count++;
this.#appendDetail(issueCode, issue);
}
this.updateAffectedResourceCount(count);
}
#appendSecureContextCell(element, isSecureContext) {
if (isSecureContext === undefined) {
this.appendIssueDetailCell(element, '');
return;
}
this.appendIssueDetailCell(element, isSecureContext ? i18nString(UIStrings.secure) : i18nString(UIStrings.insecure));
}
static getHeaderFromError(corsError) {
switch (corsError) {
case "InvalidAllowHeadersPreflightResponse" /* Protocol.Network.CorsError.InvalidAllowHeadersPreflightResponse */:
return 'Access-Control-Allow-Headers';
case "InvalidAllowMethodsPreflightResponse" /* Protocol.Network.CorsError.InvalidAllowMethodsPreflightResponse */:
case "MethodDisallowedByPreflightResponse" /* Protocol.Network.CorsError.MethodDisallowedByPreflightResponse */:
return 'Access-Control-Allow-Methods';
case "PreflightMissingAllowOriginHeader" /* Protocol.Network.CorsError.PreflightMissingAllowOriginHeader */:
case "PreflightMultipleAllowOriginValues" /* Protocol.Network.CorsError.PreflightMultipleAllowOriginValues */:
case "PreflightInvalidAllowOriginValue" /* Protocol.Network.CorsError.PreflightInvalidAllowOriginValue */:
case "MissingAllowOriginHeader" /* Protocol.Network.CorsError.MissingAllowOriginHeader */:
case "MultipleAllowOriginValues" /* Protocol.Network.CorsError.MultipleAllowOriginValues */:
case "InvalidAllowOriginValue" /* Protocol.Network.CorsError.InvalidAllowOriginValue */:
case "WildcardOriginNotAllowed" /* Protocol.Network.CorsError.WildcardOriginNotAllowed */:
case "PreflightWildcardOriginNotAllowed" /* Protocol.Network.CorsError.PreflightWildcardOriginNotAllowed */:
case "AllowOriginMismatch" /* Protocol.Network.CorsError.AllowOriginMismatch */:
case "PreflightAllowOriginMismatch" /* Protocol.Network.CorsError.PreflightAllowOriginMismatch */:
return 'Access-Control-Allow-Origin';
case "InvalidAllowCredentials" /* Protocol.Network.CorsError.InvalidAllowCredentials */:
case "PreflightInvalidAllowCredentials" /* Protocol.Network.CorsError.PreflightInvalidAllowCredentials */:
return 'Access-Control-Allow-Credentials';
case "PreflightMissingAllowPrivateNetwork" /* Protocol.Network.CorsError.PreflightMissingAllowPrivateNetwork */:
case "PreflightInvalidAllowPrivateNetwork" /* Protocol.Network.CorsError.PreflightInvalidAllowPrivateNetwork */:
return 'Access-Control-Allow-Private-Network';
case "RedirectContainsCredentials" /* Protocol.Network.CorsError.RedirectContainsCredentials */:
case "PreflightDisallowedRedirect" /* Protocol.Network.CorsError.PreflightDisallowedRedirect */:
return 'Location';
case "PreflightInvalidStatus" /* Protocol.Network.CorsError.PreflightInvalidStatus */:
return 'Status-Code';
case "PreflightMissingPrivateNetworkAccessId" /* Protocol.Network.CorsError.PreflightMissingPrivateNetworkAccessId */:
return 'Private-Network-Access-Id';
case "PreflightMissingPrivateNetworkAccessName" /* Protocol.Network.CorsError.PreflightMissingPrivateNetworkAccessName */:
return 'Private-Network-Access-Name';
}
return '';
}
static getProblemFromError(corsErrorStatus) {
switch (corsErrorStatus.corsError) {
case "InvalidAllowHeadersPreflightResponse" /* Protocol.Network.CorsError.InvalidAllowHeadersPreflightResponse */:
case "InvalidAllowMethodsPreflightResponse" /* Protocol.Network.CorsError.InvalidAllowMethodsPreflightResponse */:
case "PreflightInvalidAllowOriginValue" /* Protocol.Network.CorsError.PreflightInvalidAllowOriginValue */:
case "InvalidAllowOriginValue" /* Protocol.Network.CorsError.InvalidAllowOriginValue */:
return i18nString(UIStrings.problemInvalidValue);
case "PreflightMultipleAllowOriginValues" /* Protocol.Network.CorsError.PreflightMultipleAllowOriginValues */:
case "MultipleAllowOriginValues" /* Protocol.Network.CorsError.MultipleAllowOriginValues */:
return i18nString(UIStrings.problemMultipleValues);
case "MissingAllowOriginHeader" /* Protocol.Network.CorsError.MissingAllowOriginHeader */:
case "PreflightMissingAllowOriginHeader" /* Protocol.Network.CorsError.PreflightMissingAllowOriginHeader */:
return i18nString(UIStrings.problemMissingHeader);
case "PreflightInvalidStatus" /* Protocol.Network.CorsError.PreflightInvalidStatus */:
return i18nString(UIStrings.preflightInvalidStatus);
case "PreflightDisallowedRedirect" /* Protocol.Network.CorsError.PreflightDisallowedRedirect */:
return i18nString(UIStrings.preflightDisallowedRedirect);
case "InvalidResponse" /* Protocol.Network.CorsError.InvalidResponse */:
return i18nString(UIStrings.failedRequest);
}
throw new Error('Invalid Argument');
}
#appendDetail(issueCode, issue) {
const element = document.createElement('tr');
element.classList.add('affected-resource-directive');
const details = issue.details();
const corsErrorStatus = details.corsErrorStatus;
const corsError = details.corsErrorStatus.corsError;
const highlightHeader = {
section: NetworkForward.UIRequestLocation.UIHeaderSection.Response,
name: CorsIssueDetailsView.getHeaderFromError(corsError),
};
const opts = {
additionalOnClickAction() {
Host.userMetrics.issuesPanelResourceOpened(IssuesManager.Issue.IssueCategory.Cors, "Request" /* AffectedItem.Request */);
},
};
switch (issueCode) {
case IssuesManager.CorsIssue.IssueCode.InvalidHeaderValues:
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
if (corsError.includes('Preflight')) {
element.appendChild(this.createRequestCell(details.request, { ...opts, linkToPreflight: true, highlightHeader }));
}
else {
this.appendIssueDetailCell(element, '');
}
this.appendIssueDetailCell(element, CorsIssueDetailsView.getHeaderFromError(corsError), 'code-example');
this.appendIssueDetailCell(element, CorsIssueDetailsView.getProblemFromError(details.corsErrorStatus));
this.appendIssueDetailCell(element, details.corsErrorStatus.failedParameter, 'code-example');
break;
case IssuesManager.CorsIssue.IssueCode.WildcardOriginNotAllowed:
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
if (corsError.includes('Preflight')) {
element.appendChild(this.createRequestCell(details.request, { ...opts, linkToPreflight: true, highlightHeader }));
}
else {
this.appendIssueDetailCell(element, '');
}
break;
case IssuesManager.CorsIssue.IssueCode.PreflightResponseInvalid: {
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
const specialHighlightHeader = corsError === "PreflightInvalidStatus" /* Protocol.Network.CorsError.PreflightInvalidStatus */ ?
{
section: NetworkForward.UIRequestLocation.UIHeaderSection.General,
name: 'Status-Code',
} :
highlightHeader;
element.appendChild(this.createRequestCell(details.request, { ...opts, linkToPreflight: true, highlightHeader: specialHighlightHeader }));
this.appendIssueDetailCell(element, CorsIssueDetailsView.getProblemFromError(details.corsErrorStatus));
break;
}
case IssuesManager.CorsIssue.IssueCode.OriginMismatch:
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
if (corsError.includes('Preflight')) {
element.appendChild(this.createRequestCell(details.request, { ...opts, linkToPreflight: true, highlightHeader }));
}
else {
this.appendIssueDetailCell(element, '');
}
this.appendIssueDetailCell(element, details.initiatorOrigin ?? '', 'code-example');
this.appendIssueDetailCell(element, details.corsErrorStatus.failedParameter, 'code-example');
break;
case IssuesManager.CorsIssue.IssueCode.AllowCredentialsRequired:
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
if (corsError.includes('Preflight')) {
element.appendChild(this.createRequestCell(details.request, { ...opts, linkToPreflight: true, highlightHeader }));
}
else {
this.appendIssueDetailCell(element, '');
}
this.appendIssueDetailCell(element, details.corsErrorStatus.failedParameter, 'code-example');
break;
case IssuesManager.CorsIssue.IssueCode.InsecurePrivateNetwork:
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
this.appendIssueDetailCell(element, details.resourceIPAddressSpace ?? '');
this.appendIssueDetailCell(element, details.clientSecurityState?.initiatorIPAddressSpace ?? '');
this.#appendSecureContextCell(element, details.clientSecurityState?.initiatorIsSecureContext);
break;
case IssuesManager.CorsIssue.IssueCode.PreflightAllowPrivateNetworkError: {
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
element.appendChild(this.createRequestCell(details.request, { ...opts, linkToPreflight: true, highlightHeader }));
this.appendIssueDetailCell(element, details.corsErrorStatus.failedParameter, 'code-example');
this.appendIssueDetailCell(element, details.clientSecurityState?.initiatorIPAddressSpace ?? '');
this.#appendSecureContextCell(element, details.clientSecurityState?.initiatorIsSecureContext);
break;
}
case IssuesManager.CorsIssue.IssueCode.MethodDisallowedByPreflightResponse:
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
element.appendChild(this.createRequestCell(details.request, { ...opts, linkToPreflight: true, highlightHeader }));
this.appendIssueDetailCell(element, details.corsErrorStatus.failedParameter, 'code-example');
break;
case IssuesManager.CorsIssue.IssueCode.HeaderDisallowedByPreflightResponse:
element.appendChild(this.createRequestCell(details.request, {
...opts,
highlightHeader: {
section: NetworkForward.UIRequestLocation.UIHeaderSection.Request,
name: corsErrorStatus.failedParameter,
},
}));
this.#appendStatus(element, details.isWarning);
element.appendChild(this.createRequestCell(details.request, {
...opts,
linkToPreflight: true,
highlightHeader: {
section: NetworkForward.UIRequestLocation.UIHeaderSection.Response,
name: 'Access-Control-Allow-Headers',
},
}));
this.appendIssueDetailCell(element, details.corsErrorStatus.failedParameter, 'code-example');
break;
case IssuesManager.CorsIssue.IssueCode.RedirectContainsCredentials:
element.appendChild(this.createRequestCell(details.request, {
...opts,
highlightHeader: {
section: NetworkForward.UIRequestLocation.UIHeaderSection.Response,
name: CorsIssueDetailsView.getHeaderFromError(corsError),
},
}));
this.#appendStatus(element, details.isWarning);
break;
case IssuesManager.CorsIssue.IssueCode.DisallowedByMode:
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
this.appendIssueDetailCell(element, details.initiatorOrigin ?? '', 'code-example');
this.appendSourceLocation(element, details.location, issue.model()?.getTargetIfNotDisposed());
break;
case IssuesManager.CorsIssue.IssueCode.CorsDisabledScheme:
element.appendChild(this.createRequestCell(details.request, {
...opts,
highlightHeader: {
section: NetworkForward.UIRequestLocation.UIHeaderSection.Response,
name: CorsIssueDetailsView.getHeaderFromError(corsError),
},
}));
this.#appendStatus(element, details.isWarning);
this.appendIssueDetailCell(element, details.initiatorOrigin ?? '', 'code-example');
this.appendSourceLocation(element, details.location, issue.model()?.getTargetIfNotDisposed());
this.appendIssueDetailCell(element, details.corsErrorStatus.failedParameter ?? '', 'code-example');
break;
case IssuesManager.CorsIssue.IssueCode.NoCorsRedirectModeNotFollow:
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
this.appendSourceLocation(element, details.location, issue.model()?.getTargetIfNotDisposed());
break;
case IssuesManager.CorsIssue.IssueCode.PreflightMissingPrivateNetworkAccessId:
case IssuesManager.CorsIssue.IssueCode.PreflightMissingPrivateNetworkAccessName:
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
element.appendChild(this.createRequestCell(details.request, { ...opts, linkToPreflight: true, highlightHeader }));
this.appendIssueDetailCell(element, CorsIssueDetailsView.getHeaderFromError(corsError));
this.appendIssueDetailCell(element, details.resourceIPAddressSpace ?? '');
this.appendIssueDetailCell(element, details.clientSecurityState?.initiatorIPAddressSpace ?? '');
this.#appendSecureContextCell(element, details.clientSecurityState?.initiatorIsSecureContext);
break;
default:
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
Platform.assertUnhandled(issueCode);
break;
}
this.affectedResources.appendChild(element);
}
update() {
this.clear();
const issues = this.issue.getCorsIssues();
if (issues.size > 0) {
this.#appendDetails(issues.values().next().value.code(), issues);
}
else {
this.updateAffectedResourceCount(0);
}
}
}
//# sourceMappingURL=CorsIssueDetailsView.js.map