Fix a DCHECK that can fire if disallowdocumentaccess is enabled.

Agent Clusters can be different even if the origins are the same.

BUG=961448

Change-Id: I1cfc8d7c386735b6c718ba6da5d932d5b459980d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2416263
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: Devlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#808509}
diff --git a/extensions/renderer/script_context.cc b/extensions/renderer/script_context.cc
index 968f4ea..7acfb441 100644
--- a/extensions/renderer/script_context.cc
+++ b/extensions/renderer/script_context.cc
@@ -83,6 +83,12 @@
     return document_url;
   }
 
+  // Note: Just because the frame origin can theoretically access its
+  // precursor origin, there may be more restrictions in practice - such as
+  // if the frame has the disallowdocumentaccess attribute. It's okay to
+  // ignore this case for context classification because it's not meant as an
+  // origin boundary (unlike e.g. a sandboxed frame).
+
   // Looks like the initiator origin is an appropriate fallback!
 
   if (match_origin_as_fallback == MatchOriginAsFallbackBehavior::kAlways) {
@@ -157,6 +163,16 @@
       return document_url;
     }
 
+    // If we don't allow inaccessible parents, the security origin may still
+    // be restricted if the author has prevented same-origin access via the
+    // disallowdocumentaccess attribute on iframe.
+    if (!allow_inaccessible_parents &&
+        !web_frame_origin.CanAccess(
+            blink::WebSecurityOrigin(parent_document.GetSecurityOrigin()))) {
+      // The frame can't access its precursor. Bail.
+      return document_url;
+    }
+
     parent_url = GURL(parent_document.Url());
   } while (parent_url.SchemeIs(url::kAboutScheme));
 
diff --git a/extensions/renderer/script_context_browsertest.cc b/extensions/renderer/script_context_browsertest.cc
index b3a1a08e..b78e8c2 100644
--- a/extensions/renderer/script_context_browsertest.cc
+++ b/extensions/renderer/script_context_browsertest.cc
@@ -8,6 +8,7 @@
 #include "extensions/common/script_constants.h"
 #include "extensions/renderer/script_context.h"
 #include "extensions/renderer/script_context_set.h"
+#include "third_party/blink/public/platform/web_runtime_features.h"
 #include "third_party/blink/public/web/web_document.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "url/gurl.h"
@@ -51,7 +52,8 @@
          <iframe name='frame4' src="data:text/html,<html>Hi</html>"></iframe>
          <iframe name='frame5'
              src="data:text/html,<html>Hi</html>"
-             sandbox=''></iframe>)";
+             sandbox=''></iframe>
+         <iframe disallowdocumentaccess name='frame6'></iframe>)";
 
   const char frame3_html[] =
       R"(<iframe name='frame3_1'></iframe>
@@ -61,6 +63,7 @@
 
   WebLocalFrame* frame = GetMainFrame();
   ASSERT_TRUE(frame);
+  blink::WebRuntimeFeatures::EnableDisallowDocumentAccess(true);
 
   content::RenderFrame::FromWebFrame(frame)->LoadHTMLString(
       frame_html, top_url, "UTF-8", GURL(), false /* replace_current_item */);
@@ -90,6 +93,9 @@
   WebLocalFrame* frame5 = frame4->NextSibling()->ToWebLocalFrame();
   ASSERT_TRUE(frame5);
   ASSERT_EQ("frame5", frame5->AssignedName());
+  WebLocalFrame* frame6 = frame5->NextSibling()->ToWebLocalFrame();
+  ASSERT_TRUE(frame6);
+  ASSERT_EQ("frame6", frame6->AssignedName());
 
   // Load a blank document in a frame from a different origin.
   content::RenderFrame::FromWebFrame(frame3)->LoadHTMLString(
@@ -154,6 +160,11 @@
           frame5,
           MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree));
 
+  // Documents with disallowed access (disallowdocumentaccess) behave much like
+  // sandboxed documents.
+  EXPECT_EQ(blank_url, GetEffectiveDocumentURLForContext(frame6));
+  EXPECT_EQ(top_url, GetEffectiveDocumentURLForInjection(frame6));
+
   // top -> different origin = different origin
   EXPECT_EQ(different_url, GetEffectiveDocumentURLForContext(frame3));
   EXPECT_EQ(different_url, GetEffectiveDocumentURLForInjection(frame3));
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h
index 4d4bd683..3d0b48f2 100644
--- a/third_party/blink/public/platform/web_runtime_features.h
+++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -103,6 +103,7 @@
   BLINK_PLATFORM_EXPORT static void EnableDatabase(bool);
   BLINK_PLATFORM_EXPORT static void EnableDecodeJpeg420ImagesToYUV(bool);
   BLINK_PLATFORM_EXPORT static void EnableDecodeLossyWebPImagesToYUV(bool);
+  BLINK_PLATFORM_EXPORT static void EnableDisallowDocumentAccess(bool);
   BLINK_PLATFORM_EXPORT static void EnableDisplayCutoutAPI(bool);
   BLINK_PLATFORM_EXPORT static void EnableDocumentPolicy(bool);
   BLINK_PLATFORM_EXPORT static void EnableDocumentPolicyNegotiation(bool);
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
index c72609f..8fb1a92 100644
--- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -589,6 +589,10 @@
   RuntimeEnabledFeatures::SetExperimentalProductivityFeaturesEnabled(enable);
 }
 
+void WebRuntimeFeatures::EnableDisallowDocumentAccess(bool enable) {
+  RuntimeEnabledFeatures::SetDisallowDocumentAccessEnabled(enable);
+}
+
 void WebRuntimeFeatures::EnableDisplayCutoutAPI(bool enable) {
   RuntimeEnabledFeatures::SetDisplayCutoutAPIEnabled(enable);
 }