From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Mon, 29 Aug 2022 11:44:57 +0200
Subject: fix: crash loading non-standard schemes in iframes

This fixes a crash that occurs when loading non-standard schemes from
iframes or webviews. This was happening because
ChildProcessSecurityPolicyImpl::CanAccessDataForOrigin contains explicit
exceptions to allow built-in non-standard schemes, but does not check
for non-standard schemes registered by the embedder.

This patch adjusts the origin calculation for subframe non-standard schemes in
 - browser process at `NavigationRequest::GetOriginForURLLoaderFactoryUncheckedWithDebugInfo`
 - render process at `DocumentLoader::CalculateOrigin`

When top level frame navigates to non-standard scheme url, the origin is calculated
as `null` without any derivation. It is only in cases where there is a `initiator_origin`
then the origin is derived from it, which is usually the case for renderer initiated
navigations and iframes are no exceptions from this rule.

The patch should be removed in favor of either:
  - Remove support for non-standard custom schemes
  - Register non-standard custom schemes as websafe schemes and update
  CPSPI::CanAccessDataForOrigin to allow them for any navigation.
  - Update the callsite to use RFHI::CanCommitOriginAndUrl in upstream, previous
  effort to do this can be found at https://chromium-review.googlesource.com/c/chromium/src/+/3856266.

Upstream bug https://bugs.chromium.org/p/chromium/issues/detail?id=1081397.

diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 7d101d40116bf743f940f32ba4c9b507aa9a235b..2aa1584fd451fb15ec6084fb0c19724e6c63e0e3 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -11666,6 +11666,11 @@ url::Origin NavigationRequest::GetOriginForURLLoaderFactoryUnchecked() {
             target_rph_id);
   }
 
+  if (!common_params().url.IsStandard() && !common_params().url.IsAboutBlank()) {
+    return url::Origin::Resolve(common_params().url,
+                                url::Origin());
+  }
+
   // In cases not covered above, URLLoaderFactory should be associated with the
   // origin of |common_params.url| and/or |common_params.initiator_origin|.
   url::Origin resolved_origin = url::Origin::Resolve(
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 521e3d6ef9d818c6b3d91ff1483b058c43d405a7..bcfe3223ee2789b7239c6106c19e98cbafcf0782 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -2323,6 +2323,7 @@ Frame* DocumentLoader::CalculateOwnerFrame() {
 scoped_refptr<SecurityOrigin> DocumentLoader::CalculateOrigin(
     Document* owner_document) {
   scoped_refptr<SecurityOrigin> origin;
+  bool is_standard = url::IsStandard(url_.Protocol().Ascii().data());
   // Whether the origin is newly created within this call, instead of copied
   // from an existing document's origin or from `origin_to_commit_`. If this is
   // true, we won't try to compare the nonce of this origin (if it's opaque) to
@@ -2359,6 +2360,9 @@ scoped_refptr<SecurityOrigin> DocumentLoader::CalculateOrigin(
     // non-renderer only origin bits will be the same, which will be asserted at
     // the end of this function.
     origin = origin_to_commit_;
+  } else if (!SecurityOrigin::ShouldUseInnerURL(url_) &&
+             !is_standard) {
+    origin = SecurityOrigin::Create(url_);
   } else {
     // Otherwise, create an origin that propagates precursor information
     // as needed. For non-opaque origins, this creates a standard tuple
