From 0404498fbfe3e99ba69a4e99f09715baceecd99d Mon Sep 17 00:00:00 2001 From: Sigurd Schneider Date: Mon, 17 May 2021 09:21:12 +0200 Subject: [PATCH] Add issues for CORS same-origin problems This CL adds issues for the CORS error codes DisallowedByMode Screenshot: https://imgur.com/a/XBVhWCs Bug: chromium:1141824 Change-Id: If2292961beaba23e18b41b580c2d20f453b5faf3 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2897282 Commit-Queue: Sigurd Schneider Reviewed-by: Wolfgang Beyer --- config/gni/all_devtools_files.gni | 1 + config/gni/devtools_grd_files.gni | 1 + front_end/core/i18n/locales/en-US.json | 3 ++ front_end/core/i18n/locales/en-XL.json | 3 ++ front_end/models/issues_manager/BUILD.gn | 1 + front_end/models/issues_manager/CorsIssue.ts | 8 ++++- .../descriptions/corsDisallowedByMode.md | 7 ++++ .../panels/issues/AffectedResourcesView.ts | 3 +- .../panels/issues/CorsIssueDetailsView.ts | 16 +++++++-- test/e2e/issues/cors-issues_test.ts | 36 +++++++++++++++++++ 10 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 front_end/models/issues_manager/descriptions/corsDisallowedByMode.md diff --git a/config/gni/all_devtools_files.gni b/config/gni/all_devtools_files.gni index 3d482a2516..b16b95c6aa 100644 --- a/config/gni/all_devtools_files.gni +++ b/config/gni/all_devtools_files.gni @@ -212,6 +212,7 @@ all_devtools_files = [ "front_end/models/issues_manager/descriptions/cspTrustedTypesPolicyViolation.md", "front_end/models/issues_manager/descriptions/heavyAd.md", "front_end/models/issues_manager/descriptions/corsAllowCredentialsRequired.md", + "front_end/models/issues_manager/descriptions/corsDisallowedByMode.md", "front_end/models/issues_manager/descriptions/corsHeaderDisallowedByPreflightResponse.md", "front_end/models/issues_manager/descriptions/corsInvalidHeaderValues.md", "front_end/models/issues_manager/descriptions/corsMethodDisallowedByPreflightResponse.md", diff --git a/config/gni/devtools_grd_files.gni b/config/gni/devtools_grd_files.gni index 557b56e74b..c3508abebd 100644 --- a/config/gni/devtools_grd_files.gni +++ b/config/gni/devtools_grd_files.gni @@ -246,6 +246,7 @@ grd_files_release_sources = [ "front_end/models/issues_manager/descriptions/TwaHttpError.md", "front_end/models/issues_manager/descriptions/TwaPageUnavailableOffline.md", "front_end/models/issues_manager/descriptions/corsAllowCredentialsRequired.md", + "front_end/models/issues_manager/descriptions/corsDisallowedByMode.md", "front_end/models/issues_manager/descriptions/corsHeaderDisallowedByPreflightResponse.md", "front_end/models/issues_manager/descriptions/corsInsecurePrivateNetwork.md", "front_end/models/issues_manager/descriptions/corsInsecurePrivateNetworkPreflight.md", diff --git a/front_end/core/i18n/locales/en-US.json b/front_end/core/i18n/locales/en-US.json index c8caa93aa0..530c552fe8 100644 --- a/front_end/core/i18n/locales/en-US.json +++ b/front_end/core/i18n/locales/en-US.json @@ -4976,6 +4976,9 @@ "panels/issues/CorsIssueDetailsView.ts | secure": { "message": "secure" }, + "panels/issues/CorsIssueDetailsView.ts | sourceLocation": { + "message": "Source Location" + }, "panels/issues/CorsIssueDetailsView.ts | status": { "message": "Status" }, diff --git a/front_end/core/i18n/locales/en-XL.json b/front_end/core/i18n/locales/en-XL.json index d5b56db65f..418efdfb24 100644 --- a/front_end/core/i18n/locales/en-XL.json +++ b/front_end/core/i18n/locales/en-XL.json @@ -4976,6 +4976,9 @@ "panels/issues/CorsIssueDetailsView.ts | secure": { "message": "ŝéĉúr̂é" }, + "panels/issues/CorsIssueDetailsView.ts | sourceLocation": { + "message": "Ŝóûŕĉé L̂óĉát̂íôń" + }, "panels/issues/CorsIssueDetailsView.ts | status": { "message": "Ŝt́ât́ûś" }, diff --git a/front_end/models/issues_manager/BUILD.gn b/front_end/models/issues_manager/BUILD.gn index 5773227bfa..837c62b51d 100644 --- a/front_end/models/issues_manager/BUILD.gn +++ b/front_end/models/issues_manager/BUILD.gn @@ -45,6 +45,7 @@ devtools_issue_description_files = [ "CoepCorpNotSameSite.md", "CoepFrameResourceNeedsCoepHeader.md", "corsAllowCredentialsRequired.md", + "corsDisallowedByMode.md", "corsHeaderDisallowedByPreflightResponse.md", "corsInsecurePrivateNetwork.md", "corsInsecurePrivateNetworkPreflight.md", diff --git a/front_end/models/issues_manager/CorsIssue.ts b/front_end/models/issues_manager/CorsIssue.ts index 0d017ba67d..f8b89d440b 100644 --- a/front_end/models/issues_manager/CorsIssue.ts +++ b/front_end/models/issues_manager/CorsIssue.ts @@ -120,7 +120,6 @@ export class CorsIssue extends Issue { case IssueCode.InsecurePrivateNetworkPreflight: return { file: 'corsInsecurePrivateNetworkPreflight.md', - substitutions: undefined, links: [{ link: 'https://developer.chrome.com/blog/private-network-access-update', linkTitle: i18nString(UIStrings.corsForPrivateNetworksRfc), @@ -191,6 +190,13 @@ export class CorsIssue extends Issue { }], }; case IssueCode.DisallowedByMode: + return { + file: 'corsDisallowedByMode.md', + links: [{ + link: 'https://web.dev/cross-origin-resource-sharing', + linkTitle: i18nString(UIStrings.CORS), + }], + }; case IssueCode.CorsDisabledScheme: case IssueCode.PreflightMissingAllowExternal: case IssueCode.PreflightInvalidAllowExternal: diff --git a/front_end/models/issues_manager/descriptions/corsDisallowedByMode.md b/front_end/models/issues_manager/descriptions/corsDisallowedByMode.md new file mode 100644 index 0000000000..141a7d1590 --- /dev/null +++ b/front_end/models/issues_manager/descriptions/corsDisallowedByMode.md @@ -0,0 +1,7 @@ +# Ensure only same-origin resources are fetched with same-origin request mode + +A cross-origin resource sharing (CORS) request to a cross-origin resource was blocked because the request mode was set to `same-origin`. + +To fix this issue, ensure that only same-origin resources are fetched with the `same-origin` request mode. If you need to fetch a cross-origin resource, use a request mode such as `cors`. + +Note that if an opaque response is sufficient, the request's mode can be set to `no-cors` to fetch the resource with CORS disabled; that way CORS headers are not required but the response content is inaccessible (opaque). diff --git a/front_end/panels/issues/AffectedResourcesView.ts b/front_end/panels/issues/AffectedResourcesView.ts index bdab310fe6..4f2bc37037 100644 --- a/front_end/panels/issues/AffectedResourcesView.ts +++ b/front_end/panels/issues/AffectedResourcesView.ts @@ -275,8 +275,7 @@ export abstract class AffectedResourcesView extends UI.TreeOutline.TreeElement { protected appendSourceLocation( element: HTMLElement, - sourceLocation: {url: string, scriptId: string|undefined, lineNumber: number, columnNumber: number|undefined}| - undefined, + sourceLocation: {url: string, scriptId?: string, lineNumber: number, columnNumber?: number}|undefined, target: SDK.SDKModel.Target|null|undefined): void { const sourceCodeLocation = document.createElement('td'); sourceCodeLocation.classList.add('affected-source-location'); diff --git a/front_end/panels/issues/CorsIssueDetailsView.ts b/front_end/panels/issues/CorsIssueDetailsView.ts index 7c5f18483c..de42db40a7 100644 --- a/front_end/panels/issues/CorsIssueDetailsView.ts +++ b/front_end/panels/issues/CorsIssueDetailsView.ts @@ -108,6 +108,10 @@ const UIStrings = { *@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', }; const str_ = i18n.i18n.registerUIStrings('panels/issues/CorsIssueDetailsView.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); @@ -182,9 +186,12 @@ export class CorsIssueDetailsView extends AffectedResourcesView { 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; default: Platform.assertUnhandled { 'blocked', ]); }); + + it('should display CORS issues that are disallowed by the mode', async () => { + await goToResource('empty.html'); + const {target} = getBrowserAndPages(); + await target.evaluate(async () => { + try { + const url = new URL('/', document.location.toString()).toString().replace('localhost', 'devtools.oopif.test'); + await fetch(url, {mode: 'same-origin'}); + } catch (e) { + } + }); + await navigateToIssuesTab(); + await expandIssue(); + const issueElement = + await getIssueByTitle('Ensure only same-origin resources are fetched with same-origin request mode'); + assertNotNull(issueElement); + const section = await getResourcesElement('request', issueElement, '.cors-issue-affected-resource-label'); + const text = await section.label.evaluate(el => el.textContent); + assert.strictEqual(text, '1 request'); + await ensureResourceSectionIsExpanded(section); + const table = await extractTableFromResourceSection(section.content); + assertNotNull(table); + assert.strictEqual(table.length, 2); + assert.deepEqual(table[0], [ + 'Request', + 'Status', + 'Initiator Context', + 'Source Location', + ]); + assertMatchArray(table[1], [ + /^devtools.oopif.test.*\//, + 'blocked', + /^https:\/\/localhost.*/, + /.*:\d+/, + ]); + }); });