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 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.

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

Upstreamed at https://chromium-review.googlesource.com/c/chromium/src/+/3856266.

diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 5d4f3ab1c8328bce254ede9c3c8dfe9a8c84b8d3..8a9beaf3bfb9fe5eca8ca6675c7c45b4b880db03 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -10396,6 +10396,12 @@ NavigationRequest::GetOriginForURLLoaderFactoryUncheckedWithDebugInfo() {
     return std::make_pair(parent->GetLastCommittedOrigin(), "about_srcdoc");
   }
 
+  if (!common_params().url.IsStandard()) {
+    return std::make_pair(url::Origin::Resolve(common_params().url,
+                                               url::Origin()),
+                          "url_non_standard");
+  }
+
   // 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 15c696731f42b6095e6fff66c3619d5301f807ca..d74a940cdaee0576135e2ceeffa3bdba1583f6be 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -2169,6 +2169,10 @@ Frame* DocumentLoader::CalculateOwnerFrame() {
 scoped_refptr<SecurityOrigin> DocumentLoader::CalculateOrigin(
     Document* owner_document) {
   scoped_refptr<SecurityOrigin> origin;
+  bool is_standard = false;
+  std::string protocol = url_.Protocol().Ascii();
+  is_standard = url::IsStandard(
+      protocol.data(), url::Component(0, static_cast<int>(protocol.size())));
   StringBuilder debug_info_builder;
   if (origin_to_commit_) {
     // Origin to commit is specified by the browser process, it must be taken
@@ -2216,6 +2220,10 @@ scoped_refptr<SecurityOrigin> DocumentLoader::CalculateOrigin(
     debug_info_builder.Append(", url=");
     debug_info_builder.Append(owner_document->Url().BaseAsString());
     debug_info_builder.Append(")");
+  } else if (!SecurityOrigin::ShouldUseInnerURL(url_) &&
+             !is_standard) {
+    debug_info_builder.Append("use_url_with_non_standard_scheme");
+    origin = SecurityOrigin::Create(url_);
   } else if (url_.IsAboutSrcdocURL()) {
     // If there's no owner_document and this is a srcdoc load, then get the
     // origin from the remote parent. A srcdoc navigation with no owner_document
