Origin Policy: Apply CSP of an active origin policy.

Gated on --enable-features=OriginPolicy (via the test in OriginPolicyThrottle).

Bug: 751996
Change-Id: I433e406fe400f86f0b677752908839da7d3d9345
Reviewed-on: https://chromium-review.googlesource.com/1111960
Reviewed-by: Mike West <mkwst@chromium.org>
Reviewed-by: Andy Paicu <andypaicu@chromium.org>
Commit-Queue: Daniel Vogelheim <vogelheim@chromium.org>
Cr-Commit-Position: refs/heads/master@{#576875}
diff --git a/third_party/blink/public/platform/web_content_security_policy.h b/third_party/blink/public/platform/web_content_security_policy.h
index 3089f56..4d94b01 100644
--- a/third_party/blink/public/platform/web_content_security_policy.h
+++ b/third_party/blink/public/platform/web_content_security_policy.h
@@ -44,7 +44,9 @@
 enum WebContentSecurityPolicySource {
   kWebContentSecurityPolicySourceHTTP,
   kWebContentSecurityPolicySourceMeta,
-  kWebContentSecurityPolicySourceLast = kWebContentSecurityPolicySourceMeta
+  kWebContentSecurityPolicySourceOriginPolicy,
+  kWebContentSecurityPolicySourceLast =
+      kWebContentSecurityPolicySourceOriginPolicy
 };
 
 enum WebContentSecurityPolicyDisposition {
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
index 2401b6f..c103e02 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -1895,4 +1895,13 @@
   return list;
 }
 
+bool ContentSecurityPolicy::HasPolicyFromSource(
+    ContentSecurityPolicyHeaderSource source) const {
+  for (const auto& policy : policies_) {
+    if (policy->HeaderSource() == source)
+      return true;
+  }
+  return false;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.h b/third_party/blink/renderer/core/frame/csp/content_security_policy.h
index d97eb51..783a241 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy.h
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.h
@@ -461,6 +461,8 @@
   // there is no execution context to enforce the sandbox flags.
   SandboxFlags GetSandboxMask() const { return sandbox_mask_; }
 
+  bool HasPolicyFromSource(ContentSecurityPolicyHeaderSource) const;
+
  private:
   FRIEND_TEST_ALL_PREFIXES(ContentSecurityPolicyTest, NonceInline);
   FRIEND_TEST_ALL_PREFIXES(ContentSecurityPolicyTest, NonceSinglePolicy);
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc
index ad5c35a..f5e347f 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc
@@ -29,13 +29,24 @@
   String header = String::FromUTF8(data, size);
   unsigned hash = header.IsNull() ? 0 : header.Impl()->GetHash();
 
+  // Use the 'hash' value to pick header_type and header_source input.
+  // 1st bit: header type.
+  // 2nd bit: header source: HTTP (or other)
+  // 3rd bit: header source: Meta or OriginPolicy (if not HTTP)
+  ContentSecurityPolicyHeaderType header_type =
+      hash & 0x01 ? kContentSecurityPolicyHeaderTypeEnforce
+                  : kContentSecurityPolicyHeaderTypeReport;
+  ContentSecurityPolicyHeaderSource header_source =
+      kContentSecurityPolicyHeaderSourceHTTP;
+  if (hash & 0x02) {
+    header_source = (hash & 0x04)
+                        ? kContentSecurityPolicyHeaderSourceMeta
+                        : kContentSecurityPolicyHeaderSourceOriginPolicy;
+  }
+
   // Construct and initialize a policy from the string.
   ContentSecurityPolicy* csp = ContentSecurityPolicy::Create();
-  csp->DidReceiveHeader(header,
-                        hash & 0x01 ? kContentSecurityPolicyHeaderTypeEnforce
-                                    : kContentSecurityPolicyHeaderTypeReport,
-                        hash & 0x02 ? kContentSecurityPolicyHeaderSourceHTTP
-                                    : kContentSecurityPolicyHeaderSourceMeta);
+  csp->DidReceiveHeader(header, header_type, header_source);
   g_page_holder->GetDocument().InitContentSecurityPolicy(csp);
 
   // Force a garbage collection.
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 0b35e877..df1354d 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -31,6 +31,7 @@
 
 #include <memory>
 #include "base/auto_reset.h"
+#include "third_party/blink/public/common/origin_policy/origin_policy.h"
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url_request.h"
@@ -97,6 +98,7 @@
 #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
 #include "third_party/blink/renderer/platform/weborigin/security_policy.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
@@ -608,6 +610,23 @@
   if (!frame_->GetSettings()->BypassCSP()) {
     content_security_policy_->DidReceiveHeaders(
         ContentSecurityPolicyResponseHeaders(response));
+
+    // Handle OriginPolicy. We can skip the entire block if the OP policies have
+    // already been passed down.
+    if (!content_security_policy_->HasPolicyFromSource(
+            kContentSecurityPolicyHeaderSourceOriginPolicy)) {
+      std::unique_ptr<OriginPolicy> origin_policy = OriginPolicy::From(
+          StringUTF8Adaptor(request_.GetOriginPolicy()).AsStringPiece());
+      if (origin_policy) {
+        for (auto csp : origin_policy->GetContentSecurityPolicies()) {
+          content_security_policy_->DidReceiveHeader(
+              WTF::String::FromUTF8(csp.policy.data(), csp.policy.length()),
+              csp.report_only ? kContentSecurityPolicyHeaderTypeReport
+                              : kContentSecurityPolicyHeaderTypeEnforce,
+              kContentSecurityPolicyHeaderSourceOriginPolicy);
+        }
+      }
+    }
   }
   if (!content_security_policy_->AllowAncestors(frame_, response.Url())) {
     CancelLoadAfterCSPDenied(response);
diff --git a/third_party/blink/renderer/platform/network/content_security_policy_parsers.cc b/third_party/blink/renderer/platform/network/content_security_policy_parsers.cc
index 50b795f..2107d3c 100644
--- a/third_party/blink/renderer/platform/network/content_security_policy_parsers.cc
+++ b/third_party/blink/renderer/platform/network/content_security_policy_parsers.cc
@@ -66,4 +66,7 @@
                    kContentSecurityPolicyHeaderSourceHTTP);
 STATIC_ASSERT_ENUM(kWebContentSecurityPolicySourceMeta,
                    kContentSecurityPolicyHeaderSourceMeta);
+STATIC_ASSERT_ENUM(kWebContentSecurityPolicySourceOriginPolicy,
+                   kContentSecurityPolicyHeaderSourceOriginPolicy);
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/network/content_security_policy_parsers.h b/third_party/blink/renderer/platform/network/content_security_policy_parsers.h
index 0fb0dc5..e352fa9 100644
--- a/third_party/blink/renderer/platform/network/content_security_policy_parsers.h
+++ b/third_party/blink/renderer/platform/network/content_security_policy_parsers.h
@@ -20,7 +20,8 @@
 
 enum ContentSecurityPolicyHeaderSource {
   kContentSecurityPolicyHeaderSourceHTTP,
-  kContentSecurityPolicyHeaderSourceMeta
+  kContentSecurityPolicyHeaderSourceMeta,
+  kContentSecurityPolicyHeaderSourceOriginPolicy
 };
 
 enum ContentSecurityPolicyHashAlgorithm {