chrome-devtools-frontend
Version:
Chrome DevTools UI
502 lines (483 loc) • 26.4 kB
text/typescript
// 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.
/* eslint-disable rulesdir/no-imperative-dom-api */
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 Protocol from '../../generated/protocol.js';
import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
import * as NetworkForward from '../../panels/network/forward/forward.js';
import {AffectedItem, AffectedResourcesView} from './AffectedResourcesView.js';
import type {AggregatedIssue} from './IssueAggregator.js';
import type {IssueView} from './IssueView.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',
} as const;
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: IssueView, issue: AggregatedIssue, jslogContext: string) {
super(parent, issue, jslogContext);
this.affectedResourcesCountElement.classList.add('cors-issue-affected-resource-label');
}
#appendStatus(element: HTMLElement, isWarning: boolean): void {
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);
}
protected getResourceNameWithCount(count: number): Platform.UIString.LocalizedString {
return i18nString(UIStrings.nRequests, {n: count});
}
#appendDetails(issueCode: IssuesManager.CorsIssue.IssueCode, issues: Iterable<IssuesManager.CorsIssue.CorsIssue>):
void {
const header = document.createElement('tr');
this.appendColumnTitle(header, i18nString(UIStrings.request));
this.appendColumnTitle(header, i18nString(UIStrings.status));
switch (issueCode) {
case IssuesManager.CorsIssue.IssueCode.INVALID_HEADER_VALUES:
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.WILDCARD_ORIGN_NOT_ALLOWED:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequestIfProblematic));
break;
case IssuesManager.CorsIssue.IssueCode.PREFLIGHT_RESPONSE_INVALID:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequest));
this.appendColumnTitle(header, i18nString(UIStrings.problem));
break;
case IssuesManager.CorsIssue.IssueCode.ORIGIN_MISMATCH:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequestIfProblematic));
this.appendColumnTitle(header, i18nString(UIStrings.initiatorContext));
this.appendColumnTitle(header, i18nString(UIStrings.allowedOrigin));
break;
case IssuesManager.CorsIssue.IssueCode.ALLOW_CREDENTIALS_REQUIRED:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequestIfProblematic));
this.appendColumnTitle(header, i18nString(UIStrings.allowCredentialsValueFromHeader));
break;
case IssuesManager.CorsIssue.IssueCode.INSECURE_PRIVATE_NETWORK:
this.appendColumnTitle(header, i18nString(UIStrings.resourceAddressSpace));
this.appendColumnTitle(header, i18nString(UIStrings.initiatorAddressSpace));
this.appendColumnTitle(header, i18nString(UIStrings.initiatorContext));
break;
case IssuesManager.CorsIssue.IssueCode.PREFLIGHT_ALLOW_PRIVATE_NETWORK_ERROR:
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.PREFLIGHT_MISSING_PRIVATE_NETWORK_ACCESS_ID:
case IssuesManager.CorsIssue.IssueCode.PREFLIGHT_MISSING_PRIVATE_NETWORK_ACCESS_NAME:
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.METHOD_DISALLOWED_BY_PREFLIGHT_RESPONSE:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequest));
this.appendColumnTitle(header, i18nString(UIStrings.disallowedRequestMethod));
break;
case IssuesManager.CorsIssue.IssueCode.HEADER_DISALLOWED_BY_PREFLIGHT_RESPONSE:
this.appendColumnTitle(header, i18nString(UIStrings.preflightRequest));
this.appendColumnTitle(header, i18nString(UIStrings.disallowedRequestHeader));
break;
case IssuesManager.CorsIssue.IssueCode.REDIRECT_CONTAINS_CREDENTIALS:
// The default columns suffice.
break;
case IssuesManager.CorsIssue.IssueCode.DISALLOWED_BY_MODE:
this.appendColumnTitle(header, i18nString(UIStrings.initiatorContext));
this.appendColumnTitle(header, i18nString(UIStrings.sourceLocation));
break;
case IssuesManager.CorsIssue.IssueCode.CORS_DISABLED_SCHEME:
this.appendColumnTitle(header, i18nString(UIStrings.initiatorContext));
this.appendColumnTitle(header, i18nString(UIStrings.sourceLocation));
this.appendColumnTitle(header, i18nString(UIStrings.unsupportedScheme));
break;
case IssuesManager.CorsIssue.IssueCode.NO_CORS_REDIRECT_MODE_NOT_FOLLOW:
this.appendColumnTitle(header, i18nString(UIStrings.sourceLocation));
break;
default:
Platform.assertUnhandled<IssuesManager.CorsIssue.IssueCode.PREFLIGHT_MISSING_ALLOW_EXTERNAL|
IssuesManager.CorsIssue.IssueCode.PREFLIGHT_INVALID_ALLOW_EXTERNAL|
IssuesManager.CorsIssue.IssueCode.INVALID_PRIVATE_NETWORK_ACCESS|
IssuesManager.CorsIssue.IssueCode.UNEXPECTED_PRIVATE_NETWORK_ACCESS|IssuesManager
.CorsIssue.IssueCode.PRIVATE_NETWORK_ACCESS_PERMISSION_UNAVAILABLE|IssuesManager
.CorsIssue.IssueCode.PRIVATE_NETWORK_ACCESS_PERMISSION_DENIED|
IssuesManager.CorsIssue.IssueCode.LOCAL_NETWORK_ACCESS_PERMISSION_DENIED>(issueCode);
}
this.affectedResources.appendChild(header);
let count = 0;
for (const issue of issues) {
count++;
this.#appendDetail(issueCode, issue);
}
this.updateAffectedResourceCount(count);
}
#appendSecureContextCell(element: HTMLElement, isSecureContext: boolean|undefined): void {
if (isSecureContext === undefined) {
this.appendIssueDetailCell(element, '');
return;
}
this.appendIssueDetailCell(
element, isSecureContext ? i18nString(UIStrings.secure) : i18nString(UIStrings.insecure));
}
private static getHeaderFromError(corsError: Protocol.Network.CorsError): string {
switch (corsError) {
case Protocol.Network.CorsError.InvalidAllowHeadersPreflightResponse:
return 'Access-Control-Allow-Headers';
case Protocol.Network.CorsError.InvalidAllowMethodsPreflightResponse:
case Protocol.Network.CorsError.MethodDisallowedByPreflightResponse:
return 'Access-Control-Allow-Methods';
case Protocol.Network.CorsError.PreflightMissingAllowOriginHeader:
case Protocol.Network.CorsError.PreflightMultipleAllowOriginValues:
case Protocol.Network.CorsError.PreflightInvalidAllowOriginValue:
case Protocol.Network.CorsError.MissingAllowOriginHeader:
case Protocol.Network.CorsError.MultipleAllowOriginValues:
case Protocol.Network.CorsError.InvalidAllowOriginValue:
case Protocol.Network.CorsError.WildcardOriginNotAllowed:
case Protocol.Network.CorsError.PreflightWildcardOriginNotAllowed:
case Protocol.Network.CorsError.AllowOriginMismatch:
case Protocol.Network.CorsError.PreflightAllowOriginMismatch:
return 'Access-Control-Allow-Origin';
case Protocol.Network.CorsError.InvalidAllowCredentials:
case Protocol.Network.CorsError.PreflightInvalidAllowCredentials:
return 'Access-Control-Allow-Credentials';
case Protocol.Network.CorsError.PreflightMissingAllowPrivateNetwork:
case Protocol.Network.CorsError.PreflightInvalidAllowPrivateNetwork:
return 'Access-Control-Allow-Private-Network';
case Protocol.Network.CorsError.RedirectContainsCredentials:
case Protocol.Network.CorsError.PreflightDisallowedRedirect:
return 'Location';
case Protocol.Network.CorsError.PreflightInvalidStatus:
return 'Status-Code';
case Protocol.Network.CorsError.PreflightMissingPrivateNetworkAccessId:
return 'Private-Network-Access-Id';
case Protocol.Network.CorsError.PreflightMissingPrivateNetworkAccessName:
return 'Private-Network-Access-Name';
}
return '';
}
private static getProblemFromError(corsErrorStatus: Protocol.Network.CorsErrorStatus): string {
switch (corsErrorStatus.corsError) {
case Protocol.Network.CorsError.InvalidAllowHeadersPreflightResponse:
case Protocol.Network.CorsError.InvalidAllowMethodsPreflightResponse:
case Protocol.Network.CorsError.PreflightInvalidAllowOriginValue:
case Protocol.Network.CorsError.InvalidAllowOriginValue:
return i18nString(UIStrings.problemInvalidValue);
case Protocol.Network.CorsError.PreflightMultipleAllowOriginValues:
case Protocol.Network.CorsError.MultipleAllowOriginValues:
return i18nString(UIStrings.problemMultipleValues);
case Protocol.Network.CorsError.MissingAllowOriginHeader:
case Protocol.Network.CorsError.PreflightMissingAllowOriginHeader:
return i18nString(UIStrings.problemMissingHeader);
case Protocol.Network.CorsError.PreflightInvalidStatus:
return i18nString(UIStrings.preflightInvalidStatus);
case Protocol.Network.CorsError.PreflightDisallowedRedirect:
return i18nString(UIStrings.preflightDisallowedRedirect);
case Protocol.Network.CorsError.InvalidResponse:
return i18nString(UIStrings.failedRequest);
}
throw new Error('Invalid Argument');
}
#appendDetail(issueCode: IssuesManager.CorsIssue.IssueCode, issue: IssuesManager.CorsIssue.CorsIssue): void {
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(): void {
Host.userMetrics.issuesPanelResourceOpened(IssuesManager.Issue.IssueCategory.CORS, AffectedItem.REQUEST);
},
};
switch (issueCode) {
case IssuesManager.CorsIssue.IssueCode.INVALID_HEADER_VALUES:
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.WILDCARD_ORIGN_NOT_ALLOWED:
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.PREFLIGHT_RESPONSE_INVALID: {
element.appendChild(this.createRequestCell(details.request, opts));
this.#appendStatus(element, details.isWarning);
const specialHighlightHeader = corsError === 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.ORIGIN_MISMATCH:
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.ALLOW_CREDENTIALS_REQUIRED:
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.INSECURE_PRIVATE_NETWORK:
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.PREFLIGHT_ALLOW_PRIVATE_NETWORK_ERROR: {
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.METHOD_DISALLOWED_BY_PREFLIGHT_RESPONSE:
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.HEADER_DISALLOWED_BY_PREFLIGHT_RESPONSE:
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.REDIRECT_CONTAINS_CREDENTIALS:
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.DISALLOWED_BY_MODE:
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.CORS_DISABLED_SCHEME:
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.NO_CORS_REDIRECT_MODE_NOT_FOLLOW:
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.PREFLIGHT_MISSING_PRIVATE_NETWORK_ACCESS_ID:
case IssuesManager.CorsIssue.IssueCode.PREFLIGHT_MISSING_PRIVATE_NETWORK_ACCESS_NAME:
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<IssuesManager.CorsIssue.IssueCode.PREFLIGHT_MISSING_ALLOW_EXTERNAL|
IssuesManager.CorsIssue.IssueCode.PREFLIGHT_INVALID_ALLOW_EXTERNAL|
IssuesManager.CorsIssue.IssueCode.INVALID_PRIVATE_NETWORK_ACCESS|
IssuesManager.CorsIssue.IssueCode.UNEXPECTED_PRIVATE_NETWORK_ACCESS|IssuesManager
.CorsIssue.IssueCode.PRIVATE_NETWORK_ACCESS_PERMISSION_UNAVAILABLE|IssuesManager
.CorsIssue.IssueCode.PRIVATE_NETWORK_ACCESS_PERMISSION_DENIED|
IssuesManager.CorsIssue.IssueCode.LOCAL_NETWORK_ACCESS_PERMISSION_DENIED>(issueCode);
break;
}
this.affectedResources.appendChild(element);
}
update(): void {
this.clear();
const issues = this.issue.getCorsIssues();
const issue = issues.values().next();
if (issue.done) {
this.updateAffectedResourceCount(0);
} else {
this.#appendDetails(issue.value.code(), issues);
}
}
}