"navigate-to" remaining work

This patch includes:
The security violation event and CSP report are now sent to the correct
document via an interface ptr sent though the common params
Added 'unsafe-allowed-redirects' keyword tests
Bundled all CSP info into one InitiatorCSPInfo struct
Modified existing tests to test the violation event as well

Bug: 837627, 805886
Change-Id: I03124f29d4205ad4a5c2ac899b15f42e8e23659b
Reviewed-on: https://chromium-review.googlesource.com/c/1124476
Commit-Queue: Andy Paicu <[email protected]>
Reviewed-by: Jochen Eisinger <[email protected]>
Reviewed-by: Alex Moshchuk <[email protected]>
Reviewed-by: Mike West <[email protected]>
Reviewed-by: Arthur Sonzogni <[email protected]>
Cr-Commit-Position: refs/heads/master@{#598336}
diff --git a/content/browser/frame_host/form_submission_throttle.cc b/content/browser/frame_host/form_submission_throttle.cc
index d50a20b..46c737ac 100644
--- a/content/browser/frame_host/form_submission_throttle.cc
+++ b/content/browser/frame_host/form_submission_throttle.cc
@@ -30,12 +30,12 @@
 
 NavigationThrottle::ThrottleCheckResult
 FormSubmissionThrottle::WillStartRequest() {
-  return CheckContentSecurityPolicyFormAction(false /* is_redirect */);
+  return CheckContentSecurityPolicyFormAction(false /* was_server_redirect */);
 }
 
 NavigationThrottle::ThrottleCheckResult
 FormSubmissionThrottle::WillRedirectRequest() {
-  return CheckContentSecurityPolicyFormAction(true /* is_redirect */);
+  return CheckContentSecurityPolicyFormAction(true /* was_server_redirect */);
 }
 
 const char* FormSubmissionThrottle::GetNameForLogging() {
@@ -43,7 +43,8 @@
 }
 
 NavigationThrottle::ThrottleCheckResult
-FormSubmissionThrottle::CheckContentSecurityPolicyFormAction(bool is_redirect) {
+FormSubmissionThrottle::CheckContentSecurityPolicyFormAction(
+    bool was_server_redirect) {
   // TODO(arthursonzogni): form-action is enforced on the wrong RenderFrameHost.
   // The navigating one is used instead of the one that has initiated the form
   // submission. The renderer side checks are still in place and are used for
@@ -59,7 +60,7 @@
   // compromised) renderer being responsible for enforcing the CSP of another
   // (victim) renderer. Therefore it is okay to return early and do no further
   // browser-side checks.
-  if (!is_redirect)
+  if (!was_server_redirect)
     return NavigationThrottle::PROCEED;
 
   NavigationHandleImpl* handle =
@@ -80,7 +81,7 @@
   // check report-only CSP, (2) upgrade request if needed, (3) check enforced
   // CSP to match how frame-src works. https://crbug.com/713388
   if (render_frame->IsAllowedByCsp(
-          CSPDirective::FormAction, url, is_redirect,
+          CSPDirective::FormAction, url, was_server_redirect,
           false /* is_response_check */, handle->source_location(),
           CSPContext::CHECK_ALL_CSP, true /* is_form_submission */)) {
     return NavigationThrottle::PROCEED;
diff --git a/content/browser/frame_host/form_submission_throttle.h b/content/browser/frame_host/form_submission_throttle.h
index 9c11df3..eb95c84 100644
--- a/content/browser/frame_host/form_submission_throttle.h
+++ b/content/browser/frame_host/form_submission_throttle.h
@@ -36,7 +36,7 @@
  private:
   explicit FormSubmissionThrottle(NavigationHandle* handle);
   NavigationThrottle::ThrottleCheckResult CheckContentSecurityPolicyFormAction(
-      bool is_redirect);
+      bool was_server_redirect);
 
   DISALLOW_COPY_AND_ASSIGN(FormSubmissionThrottle);
 };
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc
index ff776ee..bece944 100644
--- a/content/browser/frame_host/navigation_entry_impl.cc
+++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -692,11 +692,8 @@
       !IsViewSourceMode(), should_replace_entry(), GetBaseURLForDataURL(),
       GetHistoryURLForDataURL(), previews_state, navigation_start,
       frame_entry.method(), post_body ? post_body : post_data_,
-      base::Optional<SourceLocation>(),
-      CSPDisposition::CHECK /* should_check_main_world_csp */,
-      has_started_from_context_menu(), has_user_gesture(),
-      std::vector<ContentSecurityPolicy>() /* initiator_csp */,
-      CSPSource() /* initiator_self_source */, input_start);
+      base::Optional<SourceLocation>(), has_started_from_context_menu(),
+      has_user_gesture(), InitiatorCSPInfo(), input_start);
 }
 
 RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams(
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index bdb0819..b86fa9fc 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -353,7 +353,7 @@
           GURL() /* client_side_redirect_url */,
           base::nullopt /* devtools_initiator_info */),
       request_params, browser_initiated, false /* from_begin_navigation */,
-      &frame_entry, &entry, std::move(navigation_ui_data), nullptr));
+      &frame_entry, &entry, std::move(navigation_ui_data), nullptr, nullptr));
   navigation_request->blob_url_loader_factory_ =
       frame_entry.blob_url_loader_factory();
   return navigation_request;
@@ -369,7 +369,8 @@
     int current_history_list_length,
     bool override_user_agent,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-    mojom::NavigationClientAssociatedPtrInfo navigation_client) {
+    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator) {
   // Only normal navigations to a different document or reloads are expected.
   // - Renderer-initiated fragment-navigations never take place in the browser,
   //   even with PlzNavigate.
@@ -404,7 +405,7 @@
       true,   // from_begin_navigation
       nullptr, entry,
       nullptr,  // navigation_ui_data
-      std::move(navigation_client)));
+      std::move(navigation_client), std::move(navigation_initiator)));
   navigation_request->blob_url_loader_factory_ =
       std::move(blob_url_loader_factory);
   return navigation_request;
@@ -420,7 +421,8 @@
     const FrameNavigationEntry* frame_entry,
     const NavigationEntryImpl* entry,
     std::unique_ptr<NavigationUIData> navigation_ui_data,
-    mojom::NavigationClientAssociatedPtrInfo navigation_client)
+    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator)
     : frame_tree_node_(frame_tree_node),
       common_params_(common_params),
       begin_params_(std::move(begin_params)),
@@ -541,7 +543,9 @@
   begin_params_->headers = headers.ToString();
 
   initiator_csp_context_.reset(new InitiatorCSPContext(
-      common_params_.initiator_csp, common_params_.initiator_self_source));
+      common_params_.initiator_csp_info.initiator_csp,
+      common_params_.initiator_csp_info.initiator_self_source,
+      std::move(navigation_initiator)));
 }
 
 NavigationRequest::~NavigationRequest() {
@@ -599,8 +603,8 @@
   // otherwise block. Similarly, the NavigationHandle is created afterwards, so
   // that it gets the request URL after potentially being modified by CSP.
   net::Error net_error = CheckContentSecurityPolicy(
-      false /* is redirect */, false /* url_upgraded_after_redirect */,
-      false /* is_response_check */);
+      false /* has_followed redirect */,
+      false /* url_upgraded_after_redirect */, false /* is_response_check */);
   if (net_error != net::OK) {
     // Create a navigation handle so that the correct error code can be set on
     // it by OnRequestFailedInternal().
@@ -693,7 +697,7 @@
               common_params_.navigation_type),
           common_params_.navigation_start, nav_entry_id_,
           common_params_.started_from_context_menu,
-          common_params_.should_check_main_world_csp,
+          common_params_.initiator_csp_info.should_check_main_world_csp,
           begin_params_->is_form_submission, std::move(navigation_ui_data_),
           common_params_.method, std::move(headers), common_params_.post_data,
           Referrer::SanitizeForRequest(common_params_.url,
@@ -859,9 +863,10 @@
   // Check Content Security Policy before the NavigationThrottles run. This
   // gives CSP a chance to modify requests that NavigationThrottles would
   // otherwise block.
-  net::Error net_error = CheckContentSecurityPolicy(
-      true /* is redirect */, redirect_info.insecure_scheme_was_upgraded,
-      false /* is_response_check */);
+  net::Error net_error =
+      CheckContentSecurityPolicy(true /* has_followed_redirect */,
+                                 redirect_info.insecure_scheme_was_upgraded,
+                                 false /* is_response_check */);
   if (net_error != net::OK) {
     OnRequestFailedInternal(
         network::URLLoaderCompletionStatus(net_error), false /*skip_throttles*/,
@@ -1110,7 +1115,7 @@
   // redirect or not in order to perform its checks. This is the reason
   // why we need to check the CSP both on request and response.
   net::Error net_error = CheckContentSecurityPolicy(
-      navigation_handle_->WasServerRedirect(),
+      navigation_handle_->WasServerRedirect() /* has_followed_redirect */,
       false /* url_upgraded_after_redirect */, true /* is_response_check */);
   if (net_error != net::OK) {
     OnRequestFailedInternal(network::URLLoaderCompletionStatus(net_error),
@@ -1685,7 +1690,7 @@
 bool NavigationRequest::IsAllowedByCSPDirective(
     CSPContext* context,
     CSPDirective::Name directive,
-    bool is_redirect,
+    bool has_followed_redirect,
     bool url_upgraded_after_redirect,
     bool is_response_check,
     CSPContext::CheckCSPDisposition disposition) {
@@ -1702,25 +1707,26 @@
     url = common_params_.url;
   }
   return context->IsAllowedByCsp(
-      directive, url, is_redirect, is_response_check,
+      directive, url, has_followed_redirect, is_response_check,
       common_params_.source_location.value_or(SourceLocation()), disposition,
       begin_params_->is_form_submission);
 }
 
 net::Error NavigationRequest::CheckCSPDirectives(
     RenderFrameHostImpl* parent,
-    bool is_redirect,
+    bool has_followed_redirect,
     bool url_upgraded_after_redirect,
     bool is_response_check,
     CSPContext::CheckCSPDisposition disposition) {
   bool navigate_to_allowed = IsAllowedByCSPDirective(
-      initiator_csp_context_.get(), CSPDirective::NavigateTo, is_redirect,
-      url_upgraded_after_redirect, is_response_check, disposition);
+      initiator_csp_context_.get(), CSPDirective::NavigateTo,
+      has_followed_redirect, url_upgraded_after_redirect, is_response_check,
+      disposition);
 
   bool frame_src_allowed = true;
   if (parent) {
     frame_src_allowed = IsAllowedByCSPDirective(
-        parent, CSPDirective::FrameSrc, is_redirect,
+        parent, CSPDirective::FrameSrc, has_followed_redirect,
         url_upgraded_after_redirect, is_response_check, disposition);
   }
 
@@ -1740,13 +1746,13 @@
 }
 
 net::Error NavigationRequest::CheckContentSecurityPolicy(
-    bool is_redirect,
+    bool has_followed_redirect,
     bool url_upgraded_after_redirect,
     bool is_response_check) {
   if (common_params_.url.SchemeIs(url::kAboutScheme))
     return net::OK;
 
-  if (common_params_.should_check_main_world_csp ==
+  if (common_params_.initiator_csp_info.should_check_main_world_csp ==
       CSPDisposition::DO_NOT_CHECK) {
     return net::OK;
   }
@@ -1772,13 +1778,13 @@
   // This sequence of events allows site owners to learn about (via step 1) any
   // requests that are upgraded in step 2.
 
-  net::Error report_only_csp_status =
-      CheckCSPDirectives(parent, is_redirect, url_upgraded_after_redirect,
-                         is_response_check, CSPContext::CHECK_REPORT_ONLY_CSP);
+  net::Error report_only_csp_status = CheckCSPDirectives(
+      parent, has_followed_redirect, url_upgraded_after_redirect,
+      is_response_check, CSPContext::CHECK_REPORT_ONLY_CSP);
 
   // upgrade-insecure-requests is handled in the network code for redirects,
   // only do the upgrade here if this is not a redirect.
-  if (!is_redirect && !frame_tree_node()->IsMainFrame()) {
+  if (!has_followed_redirect && !frame_tree_node()->IsMainFrame()) {
     if (parent &&
         parent->ShouldModifyRequestUrlForCsp(true /* is subresource */)) {
       upgrade_if_insecure_ = true;
@@ -1787,9 +1793,9 @@
     }
   }
 
-  net::Error enforced_csp_status =
-      CheckCSPDirectives(parent, is_redirect, url_upgraded_after_redirect,
-                         is_response_check, CSPContext::CHECK_ENFORCED_CSP);
+  net::Error enforced_csp_status = CheckCSPDirectives(
+      parent, has_followed_redirect, url_upgraded_after_redirect,
+      is_response_check, CSPContext::CHECK_ENFORCED_CSP);
   if (enforced_csp_status != net::OK)
     return enforced_csp_status;
   return report_only_csp_status;
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h
index 44fae3f..7d37652 100644
--- a/content/browser/frame_host/navigation_request.h
+++ b/content/browser/frame_host/navigation_request.h
@@ -111,7 +111,8 @@
       int current_history_list_length,
       bool override_user_agent,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-      mojom::NavigationClientAssociatedPtrInfo navigation_client);
+      mojom::NavigationClientAssociatedPtrInfo navigation_client,
+      blink::mojom::NavigationInitiatorPtr navigation_initiator);
 
   ~NavigationRequest() override;
 
@@ -226,7 +227,8 @@
                     const FrameNavigationEntry* frame_navigation_entry,
                     const NavigationEntryImpl* navitation_entry,
                     std::unique_ptr<NavigationUIData> navigation_ui_data,
-                    mojom::NavigationClientAssociatedPtrInfo navigation_client);
+                    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+                    blink::mojom::NavigationInitiatorPtr navigation_initiator);
 
   // NavigationURLLoaderDelegate implementation.
   void OnRequestRedirected(
@@ -286,7 +288,7 @@
   // and navigate-to checks.
   bool IsAllowedByCSPDirective(CSPContext* context,
                                CSPDirective::Name directive,
-                               bool is_redirect,
+                               bool has_followed_redirect,
                                bool url_upgraded_after_redirect,
                                bool is_response_check,
                                CSPContext::CheckCSPDisposition disposition);
@@ -296,7 +298,7 @@
   // Returns net::OK if the checks pass, and net::ERR_ABORTED or
   // net::ERR_BLOCKED_BY_CLIENT depending on which checks fail.
   net::Error CheckCSPDirectives(RenderFrameHostImpl* parent,
-                                bool is_redirect,
+                                bool has_followed_redirect,
                                 bool url_upgraded_after_redirect,
                                 bool is_response_check,
                                 CSPContext::CheckCSPDisposition disposition);
@@ -307,7 +309,7 @@
   //   a report will be sent.
   // - The navigation request may be upgraded from HTTP to HTTPS if a CSP is
   //   configured to upgrade insecure requests.
-  net::Error CheckContentSecurityPolicy(bool is_redirect,
+  net::Error CheckContentSecurityPolicy(bool has_followed_redirect,
                                         bool url_upgraded_after_redirect,
                                         bool is_response_check);
 
diff --git a/content/browser/frame_host/navigator.cc b/content/browser/frame_host/navigator.cc
index 59cea6f..7cce6d2 100644
--- a/content/browser/frame_host/navigator.cc
+++ b/content/browser/frame_host/navigator.cc
@@ -32,6 +32,7 @@
     const CommonNavigationParams& common_params,
     mojom::BeginNavigationParamsPtr begin_params,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-    mojom::NavigationClientAssociatedPtrInfo navigation_client) {}
+    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator) {}
 
 }  // namespace content
diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h
index a57db61..a02d2e9 100644
--- a/content/browser/frame_host/navigator.h
+++ b/content/browser/frame_host/navigator.h
@@ -144,7 +144,8 @@
       const CommonNavigationParams& common_params,
       mojom::BeginNavigationParamsPtr begin_params,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-      mojom::NavigationClientAssociatedPtrInfo navigation_client);
+      mojom::NavigationClientAssociatedPtrInfo navigation_client,
+      blink::mojom::NavigationInitiatorPtr navigation_initiator);
 
   // Used to restart a navigation that was thought to be same-document in
   // cross-document mode.
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index 201a8526..7d7544d 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -582,7 +582,8 @@
     const CommonNavigationParams& common_params,
     mojom::BeginNavigationParamsPtr begin_params,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-    mojom::NavigationClientAssociatedPtrInfo navigation_client) {
+    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator) {
   // TODO(clamy): the url sent by the renderer should be validated with
   // FilterURL.
   // This is a renderer-initiated navigation.
@@ -645,7 +646,8 @@
           frame_tree_node, pending_entry, common_params,
           std::move(begin_params), controller_->GetLastCommittedEntryIndex(),
           controller_->GetEntryCount(), override_user_agent,
-          std::move(blob_url_loader_factory), std::move(navigation_client)));
+          std::move(blob_url_loader_factory), std::move(navigation_client),
+          std::move(navigation_initiator)));
   NavigationRequest* navigation_request = frame_tree_node->navigation_request();
 
   // This frame has already run beforeunload before it sent this IPC.  See if
diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h
index 5efb8da..cfc5634 100644
--- a/content/browser/frame_host/navigator_impl.h
+++ b/content/browser/frame_host/navigator_impl.h
@@ -90,7 +90,8 @@
       const CommonNavigationParams& common_params,
       mojom::BeginNavigationParamsPtr begin_params,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-      mojom::NavigationClientAssociatedPtrInfo navigation_client) override;
+      mojom::NavigationClientAssociatedPtrInfo navigation_client,
+      blink::mojom::NavigationInitiatorPtr navigation_initiator) override;
   void RestartNavigationAsCrossDocument(
       std::unique_ptr<NavigationRequest> navigation_request) override;
   void OnAbortNavigation(FrameTreeNode* frame_tree_node) override;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 9d82fe28..b71ff538 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -487,23 +487,27 @@
   mojom::BeginNavigationParamsPtr begin_navigation_params;
   scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
   mojom::NavigationClientAssociatedPtrInfo navigation_client;
+  blink::mojom::NavigationInitiatorPtr navigation_initiator;
 
   PendingNavigation(
       CommonNavigationParams common_params,
       mojom::BeginNavigationParamsPtr begin_navigation_params,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-      mojom::NavigationClientAssociatedPtrInfo navigation_client);
+      mojom::NavigationClientAssociatedPtrInfo navigation_client,
+      blink::mojom::NavigationInitiatorPtr navigation_initiator);
 };
 
 PendingNavigation::PendingNavigation(
     CommonNavigationParams common_params,
     mojom::BeginNavigationParamsPtr begin_navigation_params,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-    mojom::NavigationClientAssociatedPtrInfo navigation_client)
+    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator)
     : common_params(common_params),
       begin_navigation_params(std::move(begin_navigation_params)),
       blob_url_loader_factory(std::move(blob_url_loader_factory)),
-      navigation_client(std::move(navigation_client)) {}
+      navigation_client(std::move(navigation_client)),
+      navigation_initiator(std::move(navigation_initiator)) {}
 
 class FileChooserImpl : public content::FileSelectListener,
                         private content::WebContentsObserver {
@@ -1594,7 +1598,8 @@
         frame_tree_node(), pending_navigate_->common_params,
         std::move(pending_navigate_->begin_navigation_params),
         std::move(pending_navigate_->blob_url_loader_factory),
-        std::move(pending_navigate_->navigation_client));
+        std::move(pending_navigate_->navigation_client),
+        std::move(pending_navigate_->navigation_initiator));
     pending_navigate_.reset();
   }
 }
@@ -3483,7 +3488,8 @@
     const CommonNavigationParams& common_params,
     mojom::BeginNavigationParamsPtr begin_params,
     blink::mojom::BlobURLTokenPtr blob_url_token,
-    mojom::NavigationClientAssociatedPtrInfo navigation_client) {
+    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator) {
   if (!is_active())
     return;
 
@@ -3547,13 +3553,15 @@
   if (waiting_for_init_) {
     pending_navigate_ = std::make_unique<PendingNavigation>(
         validated_params, std::move(begin_params),
-        std::move(blob_url_loader_factory), std::move(navigation_client));
+        std::move(blob_url_loader_factory), std::move(navigation_client),
+        std::move(navigation_initiator));
     return;
   }
 
   frame_tree_node()->navigator()->OnBeginNavigation(
       frame_tree_node(), validated_params, std::move(begin_params),
-      std::move(blob_url_loader_factory), std::move(navigation_client));
+      std::move(blob_url_loader_factory), std::move(navigation_client),
+      std::move(navigation_initiator));
 }
 
 void RenderFrameHostImpl::SubresourceResponseStarted(
@@ -3833,13 +3841,10 @@
   DCHECK(data_url.SchemeIs(url::kDataScheme));
   CommonNavigationParams common_params(
       data_url, Referrer(), ui::PAGE_TRANSITION_LINK,
-      FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, false, false,
-      GURL(), GURL(), PREVIEWS_OFF, base::TimeTicks::Now(), "GET", nullptr,
-      base::Optional<SourceLocation>(),
-      CSPDisposition::CHECK /* should_check_main_world_csp */,
-      false /* started_from_context_menu */, false /* has_user_gesture */,
-      std::vector<ContentSecurityPolicy>() /* initiator_csp */,
-      CSPSource() /* initiator_self_source */);
+      FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, false, false, GURL(), GURL(),
+      PREVIEWS_OFF, base::TimeTicks::Now(), "GET", nullptr,
+      base::Optional<SourceLocation>(), false /* started_from_context_menu */,
+      false /* has_user_gesture */, InitiatorCSPInfo());
   CommitNavigation(0, nullptr, network::mojom::URLLoaderClientEndpointsPtr(),
                    common_params, RequestNavigationParams(), false,
                    base::nullopt, base::nullopt /* subresource_overrides */,
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 00563fa..b75cf70 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -67,6 +67,7 @@
 #include "third_party/blink/public/common/frame/user_activation_update_type.h"
 #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
 #include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
+#include "third_party/blink/public/mojom/frame/navigation_initiator.mojom.h"
 #include "third_party/blink/public/mojom/presentation/presentation.mojom.h"
 #include "third_party/blink/public/platform/dedicated_worker_factory.mojom.h"
 #include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
@@ -996,7 +997,8 @@
       const CommonNavigationParams& common_params,
       mojom::BeginNavigationParamsPtr begin_params,
       blink::mojom::BlobURLTokenPtr blob_url_token,
-      mojom::NavigationClientAssociatedPtrInfo navigation_client) override;
+      mojom::NavigationClientAssociatedPtrInfo navigation_client,
+      blink::mojom::NavigationInitiatorPtr navigation_initiator) override;
   void SubresourceResponseStarted(const GURL& url,
                                   net::CertStatus cert_status) override;
   void ResourceLoadComplete(
diff --git a/content/browser/initiator_csp_context.cc b/content/browser/initiator_csp_context.cc
index a29e02d..2529f9e 100644
--- a/content/browser/initiator_csp_context.cc
+++ b/content/browser/initiator_csp_context.cc
@@ -8,8 +8,10 @@
 
 InitiatorCSPContext::InitiatorCSPContext(
     const std::vector<ContentSecurityPolicy>& policies,
-    base::Optional<CSPSource>& self_source)
-    : reporting_render_frame_host_impl_(nullptr) {
+    base::Optional<CSPSource>& self_source,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator)
+    : reporting_render_frame_host_impl_(nullptr),
+      initiator_ptr(std::move(navigation_initiator)) {
   for (const auto& policy : policies)
     AddContentSecurityPolicy(policy);
 
@@ -17,6 +19,8 @@
     SetSelf(self_source.value());
 }
 
+InitiatorCSPContext::~InitiatorCSPContext() {}
+
 void InitiatorCSPContext::SetReportingRenderFrameHost(
     RenderFrameHostImpl* rfh) {
   reporting_render_frame_host_impl_ = rfh;
@@ -24,9 +28,19 @@
 
 void InitiatorCSPContext::ReportContentSecurityPolicyViolation(
     const CSPViolationParams& violation_params) {
-  if (reporting_render_frame_host_impl_) {
-    reporting_render_frame_host_impl_->ReportContentSecurityPolicyViolation(
-        violation_params);
+  if (initiator_ptr.is_bound()) {
+    initiator_ptr->SendViolationReport(blink::mojom::CSPViolationParams::New(
+        violation_params.directive, violation_params.effective_directive,
+        violation_params.console_message, violation_params.blocked_url.spec(),
+        violation_params.report_endpoints, violation_params.use_reporting_api,
+        violation_params.header,
+        (blink::mojom::WebContentSecurityPolicyType)
+            violation_params.disposition,
+        violation_params.after_redirect,
+        blink::mojom::SourceLocation::New(
+            violation_params.source_location.url,
+            violation_params.source_location.column_number,
+            violation_params.source_location.line_number)));
   }
 }
 
diff --git a/content/browser/initiator_csp_context.h b/content/browser/initiator_csp_context.h
index e370eee3..097e228 100644
--- a/content/browser/initiator_csp_context.h
+++ b/content/browser/initiator_csp_context.h
@@ -20,8 +20,11 @@
 // `navigate-to` and `form-action` (in the case of form submissions).
 class InitiatorCSPContext : public CSPContext {
  public:
-  InitiatorCSPContext(const std::vector<ContentSecurityPolicy>& policies,
-                      base::Optional<CSPSource>& self_source);
+  InitiatorCSPContext(
+      const std::vector<ContentSecurityPolicy>& policies,
+      base::Optional<CSPSource>& self_source,
+      blink::mojom::NavigationInitiatorPtr navigation_initiator);
+  ~InitiatorCSPContext() override;
 
   void ReportContentSecurityPolicyViolation(
       const CSPViolationParams& violation_params) override;
@@ -35,6 +38,9 @@
 
  private:
   RenderFrameHostImpl* reporting_render_frame_host_impl_;
+  blink::mojom::NavigationInitiatorPtr initiator_ptr;
+
+  DISALLOW_COPY_AND_ASSIGN(InitiatorCSPContext);
 };
 
 }  // namespace content
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc
index c101d5f..64be3e15 100644
--- a/content/browser/navigation_browsertest.cc
+++ b/content/browser/navigation_browsertest.cc
@@ -585,10 +585,8 @@
       GURL() /* history_url_for_data_url */, PREVIEWS_UNSPECIFIED,
       base::TimeTicks::Now() /* navigation_start */, "GET",
       nullptr /* post_data */, base::Optional<SourceLocation>(),
-      CSPDisposition::CHECK, false /* started_from_context_menu */,
-      false /* has_user_gesture */,
-      std::vector<ContentSecurityPolicy>() /* initiator_csp */,
-      CSPSource() /* initiator_self_source */);
+      false /* started_from_context_menu */, false /* has_user_gesture */,
+      InitiatorCSPInfo());
   mojom::BeginNavigationParamsPtr begin_params =
       mojom::BeginNavigationParams::New(
           std::string() /* headers */, net::LOAD_NORMAL,
@@ -610,10 +608,10 @@
         mojo::MakeRequestAssociatedWithDedicatedPipe(&navigation_client);
     rfh->frame_host_binding_for_testing().impl()->BeginNavigation(
         common_params, std::move(begin_params), nullptr,
-        navigation_client.PassInterface());
+        navigation_client.PassInterface(), nullptr);
   } else {
     rfh->frame_host_binding_for_testing().impl()->BeginNavigation(
-        common_params, std::move(begin_params), nullptr, nullptr);
+        common_params, std::move(begin_params), nullptr, nullptr, nullptr);
   }
   EXPECT_EQ(bad_message::RFH_BASE_URL_FOR_DATA_URL_SPECIFIED,
             process_kill_waiter.Wait());
diff --git a/content/common/content_security_policy/content_security_policy.cc b/content/common/content_security_policy/content_security_policy.cc
index 0a5565c5..d024d30 100644
--- a/content/common/content_security_policy/content_security_policy.cc
+++ b/content/common/content_security_policy/content_security_policy.cc
@@ -57,7 +57,7 @@
                      const CSPDirective& directive,
                      const CSPDirective::Name directive_name,
                      const GURL& url,
-                     bool is_redirect,
+                     bool has_followed_redirect,
                      const SourceLocation& source_location) {
   // We should never have a violation against `child-src` or `default-src`
   // directly; the effective directive should always be one of the explicit
@@ -71,8 +71,8 @@
   // renderers.
   GURL safe_url = url;
   SourceLocation safe_source_location = source_location;
-  context->SanitizeDataForUseInCspViolation(is_redirect, directive_name,
-                                            &safe_url, &safe_source_location);
+  context->SanitizeDataForUseInCspViolation(
+      has_followed_redirect, directive_name, &safe_url, &safe_source_location);
 
   std::stringstream message;
 
@@ -103,7 +103,7 @@
       CSPDirective::NameToString(directive.name),
       CSPDirective::NameToString(directive_name), message.str(), safe_url,
       policy.report_endpoints, policy.use_reporting_api,
-      policy.header.header_value, policy.header.type, is_redirect,
+      policy.header.header_value, policy.header.type, has_followed_redirect,
       safe_source_location));
 }
 
@@ -112,16 +112,16 @@
                     const CSPDirective& directive,
                     CSPDirective::Name directive_name,
                     const GURL& url,
-                    bool is_redirect,
+                    bool has_followed_redirect,
                     bool is_response_check,
                     const SourceLocation& source_location) {
-  if (CSPSourceList::Allow(directive.source_list, url, context, is_redirect,
-                           is_response_check)) {
+  if (CSPSourceList::Allow(directive.source_list, url, context,
+                           has_followed_redirect, is_response_check)) {
     return true;
   }
 
-  ReportViolation(context, policy, directive, directive_name, url, is_redirect,
-                  source_location);
+  ReportViolation(context, policy, directive, directive_name, url,
+                  has_followed_redirect, source_location);
   return false;
 }
 
@@ -164,7 +164,7 @@
 bool ContentSecurityPolicy::Allow(const ContentSecurityPolicy& policy,
                                   CSPDirective::Name directive_name,
                                   const GURL& url,
-                                  bool is_redirect,
+                                  bool has_followed_redirect,
                                   bool is_response_check,
                                   CSPContext* context,
                                   const SourceLocation& source_location,
@@ -184,9 +184,9 @@
     const CSPDirective* current_directive =
         FindDirective(current_directive_name, policy.directives);
     if (current_directive) {
-      bool allowed =
-          AllowDirective(context, policy, *current_directive, directive_name,
-                         url, is_redirect, is_response_check, source_location);
+      bool allowed = AllowDirective(context, policy, *current_directive,
+                                    directive_name, url, has_followed_redirect,
+                                    is_response_check, source_location);
       return allowed ||
              policy.header.type == blink::kWebContentSecurityPolicyTypeReport;
     }
diff --git a/content/common/content_security_policy/content_security_policy.h b/content/common/content_security_policy/content_security_policy.h
index abac1de..70113da 100644
--- a/content/common/content_security_policy/content_security_policy.h
+++ b/content/common/content_security_policy/content_security_policy.h
@@ -44,7 +44,7 @@
   static bool Allow(const ContentSecurityPolicy& policy,
                     CSPDirective::Name directive,
                     const GURL& url,
-                    bool is_redirect,
+                    bool has_followed_redirect,
                     bool is_response_check,
                     CSPContext* context,
                     const SourceLocation& source_location,
diff --git a/content/common/content_security_policy/content_security_policy_unittest.cc b/content/common/content_security_policy/content_security_policy_unittest.cc
index a7e57115..a8b5be93 100644
--- a/content/common/content_security_policy/content_security_policy_unittest.cc
+++ b/content/common/content_security_policy/content_security_policy_unittest.cc
@@ -269,7 +269,6 @@
   struct TestCase {
     const CSPSourceList& navigate_to_list;
     const GURL& url;
-    bool is_redirect;
     bool is_response_check;
     bool expected;
     bool is_form_submission;
@@ -277,48 +276,45 @@
   } cases[] = {
       // Basic source matching.
       {none_source_list, GURL("https://example.test"), false, false, false,
-       false, nullptr},
-      {example_source_list, GURL("https://example.test"), false, false, true,
-       false, nullptr},
+       nullptr},
+      {example_source_list, GURL("https://example.test"), false, true, false,
+       nullptr},
       {example_source_list, GURL("https://not-example.test"), false, false,
-       false, false, nullptr},
-      {self_source_list, GURL("https://example.test"), false, false, true,
        false, nullptr},
+      {self_source_list, GURL("https://example.test"), false, true, false,
+       nullptr},
 
       // Checking allow_redirect flag interactions.
-      {redirects_source_list, GURL("https://example.test"), false, false, true,
-       false, nullptr},
-      {redirects_source_list, GURL("https://example.test"), true, false, true,
-       false, nullptr},
-      {redirects_source_list, GURL("https://example.test"), true, true, true,
-       false, nullptr},
       {redirects_source_list, GURL("https://example.test"), false, true, false,
-       false, nullptr},
+       nullptr},
+      {redirects_source_list, GURL("https://example.test"), true, false, false,
+       nullptr},
       {redirects_example_source_list, GURL("https://example.test"), false, true,
-       true, false, nullptr},
+       false, nullptr},
+      {redirects_example_source_list, GURL("https://example.test"), true, true,
+       false, nullptr},
 
       // Interaction with form-action
 
       // Form submission without form-action present
-      {none_source_list, GURL("https://example.test"), false, false, false,
-       true, nullptr},
-      {example_source_list, GURL("https://example.test"), false, false, true,
-       true, nullptr},
+      {none_source_list, GURL("https://example.test"), false, false, true,
+       nullptr},
+      {example_source_list, GURL("https://example.test"), false, true, true,
+       nullptr},
       {example_source_list, GURL("https://not-example.test"), false, false,
-       false, true, nullptr},
-      {self_source_list, GURL("https://example.test"), false, false, true, true,
+       true, nullptr},
+      {self_source_list, GURL("https://example.test"), false, true, true,
        nullptr},
 
       // Form submission with form-action present
-      {none_source_list, GURL("https://example.test"), false, false, true, true,
+      {none_source_list, GURL("https://example.test"), false, true, true,
        &example_source_list},
-      {example_source_list, GURL("https://example.test"), false, false, true,
-       true, &example_source_list},
-      {example_source_list, GURL("https://not-example.test"), false, false,
-       true, true, &example_source_list},
-      {self_source_list, GURL("https://example.test"), false, false, true, true,
+      {example_source_list, GURL("https://example.test"), false, true, true,
        &example_source_list},
-
+      {example_source_list, GURL("https://not-example.test"), false, true, true,
+       &example_source_list},
+      {self_source_list, GURL("https://example.test"), false, true, true,
+       &example_source_list},
   };
 
   for (const auto& test : cases) {
@@ -333,11 +329,14 @@
     ContentSecurityPolicy policy(EmptyCspHeader(), directives,
                                  report_end_points, false);
 
-    EXPECT_EQ(test.expected,
-              ContentSecurityPolicy::Allow(
-                  policy, CSPDirective::NavigateTo, test.url, test.is_redirect,
-                  test.is_response_check, &context, SourceLocation(),
-                  test.is_form_submission));
+    EXPECT_EQ(test.expected, ContentSecurityPolicy::Allow(
+                                 policy, CSPDirective::NavigateTo, test.url,
+                                 true, test.is_response_check, &context,
+                                 SourceLocation(), test.is_form_submission));
+    EXPECT_EQ(test.expected, ContentSecurityPolicy::Allow(
+                                 policy, CSPDirective::NavigateTo, test.url,
+                                 false, test.is_response_check, &context,
+                                 SourceLocation(), test.is_form_submission));
   }
 }
 
diff --git a/content/common/content_security_policy/csp_context.cc b/content/common/content_security_policy/csp_context.cc
index 5e52b72..f83e316 100644
--- a/content/common/content_security_policy/csp_context.cc
+++ b/content/common/content_security_policy/csp_context.cc
@@ -32,7 +32,7 @@
 
 bool CSPContext::IsAllowedByCsp(CSPDirective::Name directive_name,
                                 const GURL& url,
-                                bool is_redirect,
+                                bool has_followed_redirect,
                                 bool is_response_check,
                                 const SourceLocation& source_location,
                                 CheckCSPDisposition check_csp_disposition,
@@ -44,8 +44,8 @@
   for (const auto& policy : policies_) {
     if (ShouldCheckPolicy(policy, check_csp_disposition)) {
       allow &= ContentSecurityPolicy::Allow(
-          policy, directive_name, url, is_redirect, is_response_check, this,
-          source_location, is_form_submission);
+          policy, directive_name, url, has_followed_redirect, is_response_check,
+          this, source_location, is_form_submission);
     }
   }
 
@@ -105,7 +105,7 @@
 }
 
 void CSPContext::SanitizeDataForUseInCspViolation(
-    bool is_redirect,
+    bool has_followed_redirect,
     CSPDirective::Name directive,
     GURL* blocked_url,
     SourceLocation* source_location) const {
diff --git a/content/common/content_security_policy/csp_context.h b/content/common/content_security_policy/csp_context.h
index e7f1cee..fb86c02 100644
--- a/content/common/content_security_policy/csp_context.h
+++ b/content/common/content_security_policy/csp_context.h
@@ -48,7 +48,7 @@
   // Returns true when the request can proceed, false otherwise.
   bool IsAllowedByCsp(CSPDirective::Name directive_name,
                       const GURL& url,
-                      bool is_redirect,
+                      bool has_followed_redirect,
                       bool is_response_check,
                       const SourceLocation& source_location,
                       CheckCSPDisposition check_csp_disposition,
@@ -92,7 +92,7 @@
   // without the round trip in the renderer process.
   // See https://crbug.com/721329
   virtual void SanitizeDataForUseInCspViolation(
-      bool is_redirect,
+      bool has_followed_redirect,
       CSPDirective::Name directive,
       GURL* blocked_url,
       SourceLocation* source_location) const;
diff --git a/content/common/content_security_policy/csp_source.cc b/content/common/content_security_policy/csp_source.cc
index 69b7db2..9ada01e 100644
--- a/content/common/content_security_policy/csp_source.cc
+++ b/content/common/content_security_policy/csp_source.cc
@@ -103,8 +103,8 @@
 
 bool SourceAllowPath(const CSPSource& source,
                      const GURL& url,
-                     bool is_redirect) {
-  if (is_redirect)
+                     bool has_followed_redirect) {
+  if (has_followed_redirect)
     return true;
 
   if (source.path.empty() || url.path().empty())
@@ -174,7 +174,7 @@
 bool CSPSource::Allow(const CSPSource& source,
                       const GURL& url,
                       CSPContext* context,
-                      bool is_redirect) {
+                      bool has_followed_redirect) {
   if (source.IsSchemeOnly())
     return SourceAllowScheme(source, url, context) !=
            SchemeMatchingResult::NotMatching;
@@ -190,7 +190,7 @@
   return schemeResult != SchemeMatchingResult::NotMatching &&
          SourceAllowHost(source, url) &&
          portResult != PortMatchingResult::NotMatching &&
-         SourceAllowPath(source, url, is_redirect);
+         SourceAllowPath(source, url, has_followed_redirect);
 }
 
 std::string CSPSource::ToString() const {
diff --git a/content/common/content_security_policy/csp_source.h b/content/common/content_security_policy/csp_source.h
index 62670ed..de2c051 100644
--- a/content/common/content_security_policy/csp_source.h
+++ b/content/common/content_security_policy/csp_source.h
@@ -59,7 +59,7 @@
   static bool Allow(const CSPSource& source,
                     const GURL& url,
                     CSPContext* context,
-                    bool is_redirect = false);
+                    bool has_followed_redirect = false);
 };
 
 }  // namespace content
diff --git a/content/common/content_security_policy/csp_source_list.cc b/content/common/content_security_policy/csp_source_list.cc
index 4bf358daa1..343c4c1b 100644
--- a/content/common/content_security_policy/csp_source_list.cc
+++ b/content/common/content_security_policy/csp_source_list.cc
@@ -11,9 +11,9 @@
 bool AllowFromSources(const GURL& url,
                       const std::vector<CSPSource>& sources,
                       CSPContext* context,
-                      bool is_redirect) {
+                      bool has_followed_redirect) {
   for (const CSPSource& source : sources) {
-    if (CSPSource::Allow(source, url, context, is_redirect))
+    if (CSPSource::Allow(source, url, context, has_followed_redirect))
       return true;
   }
   return false;
@@ -22,15 +22,18 @@
 };  // namespace
 
 CSPSourceList::CSPSourceList()
-    : allow_self(false), allow_star(false), allow_redirects(false), sources() {}
+    : allow_self(false),
+      allow_star(false),
+      allow_response_redirects(false),
+      sources() {}
 
 CSPSourceList::CSPSourceList(bool allow_self,
                              bool allow_star,
-                             bool allow_redirects,
+                             bool allow_response_redirects,
                              std::vector<CSPSource> sources)
     : allow_self(allow_self),
       allow_star(allow_star),
-      allow_redirects(allow_redirects),
+      allow_response_redirects(allow_response_redirects),
       sources(sources) {}
 
 CSPSourceList::CSPSourceList(const CSPSourceList&) = default;
@@ -40,21 +43,16 @@
 bool CSPSourceList::Allow(const CSPSourceList& source_list,
                           const GURL& url,
                           CSPContext* context,
-                          bool is_redirect,
+                          bool has_followed_redirect,
                           bool is_response_check) {
   // If the source list allows all redirects, the decision can't be made until
   // the response is received.
-  if (source_list.allow_redirects && !is_response_check)
+  if (source_list.allow_response_redirects && !is_response_check)
     return true;
 
   // If the source list does not allow all redirects, the decision has already
   // been made when checking the request.
-  if (!source_list.allow_redirects && is_response_check)
-    return true;
-
-  // If the source list allows all redirects, all responses that are a redirect
-  // are allowed.
-  if (source_list.allow_redirects && is_response_check && is_redirect)
+  if (!source_list.allow_response_redirects && is_response_check)
     return true;
 
   // Wildcards match network schemes ('http', 'https', 'ftp', 'ws', 'wss'), and
@@ -73,11 +71,12 @@
 
   if (source_list.allow_self && context->self_source() &&
       CSPSource::Allow(context->self_source().value(), url, context,
-                       is_redirect)) {
+                       has_followed_redirect)) {
     return true;
   }
 
-  return AllowFromSources(url, source_list.sources, context, is_redirect);
+  return AllowFromSources(url, source_list.sources, context,
+                          has_followed_redirect);
 }
 
 std::string CSPSourceList::ToString() const {
diff --git a/content/common/content_security_policy/csp_source_list.h b/content/common/content_security_policy/csp_source_list.h
index 94af7755..a1ce31f 100644
--- a/content/common/content_security_policy/csp_source_list.h
+++ b/content/common/content_security_policy/csp_source_list.h
@@ -18,7 +18,7 @@
   CSPSourceList();
   CSPSourceList(bool allow_self,
                 bool allow_star,
-                bool allow_redirects,
+                bool allow_response_redirects,
                 std::vector<CSPSource> source_list);
   CSPSourceList(const CSPSourceList&);
   ~CSPSourceList();
@@ -27,7 +27,7 @@
   // on the source list itself.
   bool allow_self;
   bool allow_star;
-  bool allow_redirects;
+  bool allow_response_redirects;
   std::vector<CSPSource> sources;
 
   std::string ToString() const;
@@ -39,7 +39,7 @@
   static bool Allow(const CSPSourceList& source_list,
                     const GURL& url,
                     CSPContext* context,
-                    bool is_redirect = false,
+                    bool has_followed_redirect = false,
                     bool is_response_check = false);
 };
 
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index 0cd83ad..f598bf8a2 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -20,6 +20,7 @@
 import "services/viz/public/interfaces/compositing/surface_id.mojom";
 import "third_party/blink/public/mojom/blob/blob_url_store.mojom";
 import "third_party/blink/public/mojom/feature_policy/feature_policy.mojom";
+import "third_party/blink/public/mojom/frame/navigation_initiator.mojom";
 import "third_party/blink/public/platform/referrer.mojom";
 import "third_party/blink/public/web/commit_result.mojom";
 import "third_party/blink/public/web/window_features.mojom";
@@ -306,7 +307,8 @@
       CommonNavigationParams common_params,
       BeginNavigationParams begin_params,
       blink.mojom.BlobURLToken? blob_url_token,
-      associated NavigationClient? navigation_client);
+      associated NavigationClient? navigation_client,
+      blink.mojom.NavigationInitiator? navigation_initiator);
 
   // Sent when a subresource response has started.
   // |cert_status| is the bitmask of status info of the SSL certificate. (see
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 6bfafce..eee8d28e 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -460,6 +460,12 @@
   IPC_STRUCT_TRAITS_MEMBER(column_number)
 IPC_STRUCT_TRAITS_END()
 
+IPC_STRUCT_TRAITS_BEGIN(content::InitiatorCSPInfo)
+  IPC_STRUCT_TRAITS_MEMBER(should_check_main_world_csp)
+  IPC_STRUCT_TRAITS_MEMBER(initiator_csp)
+  IPC_STRUCT_TRAITS_MEMBER(initiator_self_source)
+IPC_STRUCT_TRAITS_END()
+
 IPC_STRUCT_TRAITS_BEGIN(content::CommonNavigationParams)
   IPC_STRUCT_TRAITS_MEMBER(url)
   IPC_STRUCT_TRAITS_MEMBER(referrer)
@@ -474,11 +480,9 @@
   IPC_STRUCT_TRAITS_MEMBER(method)
   IPC_STRUCT_TRAITS_MEMBER(post_data)
   IPC_STRUCT_TRAITS_MEMBER(source_location)
-  IPC_STRUCT_TRAITS_MEMBER(should_check_main_world_csp)
   IPC_STRUCT_TRAITS_MEMBER(has_user_gesture)
   IPC_STRUCT_TRAITS_MEMBER(started_from_context_menu)
-  IPC_STRUCT_TRAITS_MEMBER(initiator_csp)
-  IPC_STRUCT_TRAITS_MEMBER(initiator_self_source)
+  IPC_STRUCT_TRAITS_MEMBER(initiator_csp_info)
   IPC_STRUCT_TRAITS_MEMBER(origin_policy)
   IPC_STRUCT_TRAITS_MEMBER(input_start)
 IPC_STRUCT_TRAITS_END()
@@ -672,6 +676,7 @@
 IPC_STRUCT_TRAITS_BEGIN(content::CSPSourceList)
   IPC_STRUCT_TRAITS_MEMBER(allow_self)
   IPC_STRUCT_TRAITS_MEMBER(allow_star)
+  IPC_STRUCT_TRAITS_MEMBER(allow_response_redirects)
   IPC_STRUCT_TRAITS_MEMBER(sources)
 IPC_STRUCT_TRAITS_END()
 
diff --git a/content/common/navigation_params.cc b/content/common/navigation_params.cc
index 04cf967..e3d07f56 100644
--- a/content/common/navigation_params.cc
+++ b/content/common/navigation_params.cc
@@ -24,6 +24,18 @@
 
 SourceLocation::~SourceLocation() = default;
 
+InitiatorCSPInfo::InitiatorCSPInfo() = default;
+InitiatorCSPInfo::InitiatorCSPInfo(
+    CSPDisposition should_check_main_world_csp,
+    const std::vector<ContentSecurityPolicy>& initiator_csp,
+    const base::Optional<CSPSource>& initiator_self_source)
+    : should_check_main_world_csp(should_check_main_world_csp),
+      initiator_csp(initiator_csp),
+      initiator_self_source(initiator_self_source) {}
+InitiatorCSPInfo::InitiatorCSPInfo(const InitiatorCSPInfo& other) = default;
+
+InitiatorCSPInfo::~InitiatorCSPInfo() = default;
+
 CommonNavigationParams::CommonNavigationParams() = default;
 
 CommonNavigationParams::CommonNavigationParams(
@@ -40,11 +52,9 @@
     std::string method,
     const scoped_refptr<network::ResourceRequestBody>& post_data,
     base::Optional<SourceLocation> source_location,
-    CSPDisposition should_check_main_world_csp,
     bool started_from_context_menu,
     bool has_user_gesture,
-    const std::vector<ContentSecurityPolicy>& initiator_csp,
-    const base::Optional<CSPSource>& initiator_self_source,
+    const InitiatorCSPInfo& initiator_csp_info,
     base::TimeTicks input_start)
     : url(url),
       referrer(referrer),
@@ -59,11 +69,9 @@
       method(method),
       post_data(post_data),
       source_location(source_location),
-      should_check_main_world_csp(should_check_main_world_csp),
       started_from_context_menu(started_from_context_menu),
       has_user_gesture(has_user_gesture),
-      initiator_csp(initiator_csp),
-      initiator_self_source(initiator_self_source),
+      initiator_csp_info(initiator_csp_info),
       input_start(input_start) {
   // |method != "POST"| should imply absence of |post_data|.
   if (method != "POST" && post_data) {
diff --git a/content/common/navigation_params.h b/content/common/navigation_params.h
index f3641715..08655e4 100644
--- a/content/common/navigation_params.h
+++ b/content/common/navigation_params.h
@@ -57,6 +57,28 @@
 
 // Provided by the browser or the renderer -------------------------------------
 
+// Represents the Content Security Policy of the initator of the navigation.
+struct CONTENT_EXPORT InitiatorCSPInfo {
+  InitiatorCSPInfo();
+  InitiatorCSPInfo(CSPDisposition should_check_main_world_csp,
+                   const std::vector<ContentSecurityPolicy>& initiator_csp,
+                   const base::Optional<CSPSource>& initiator_self_source);
+  InitiatorCSPInfo(const InitiatorCSPInfo& other);
+  ~InitiatorCSPInfo();
+
+  // Whether or not the CSP of the main world should apply. When the navigation
+  // is initiated from a content script in an isolated world, the CSP defined
+  // in the main world should not apply.
+  // TODO(arthursonzogni): Instead of this boolean, the origin of the isolated
+  // world which has initiated the navigation should be passed.
+  // See https://crbug.com/702540
+  CSPDisposition should_check_main_world_csp = CSPDisposition::CHECK;
+
+  // The relevant CSP policies and the initiator 'self' source to be used.
+  std::vector<ContentSecurityPolicy> initiator_csp;
+  base::Optional<CSPSource> initiator_self_source;
+};
+
 // Used by all navigation IPCs.
 struct CONTENT_EXPORT CommonNavigationParams {
   CommonNavigationParams();
@@ -74,11 +96,9 @@
       std::string method,
       const scoped_refptr<network::ResourceRequestBody>& post_data,
       base::Optional<SourceLocation> source_location,
-      CSPDisposition should_check_main_world_csp,
       bool started_from_context_menu,
       bool has_user_gesture,
-      const std::vector<ContentSecurityPolicy>& initiator_csp,
-      const base::Optional<CSPSource>& initiator_self_source,
+      const InitiatorCSPInfo& initiator_csp_info,
       base::TimeTicks input_start = base::TimeTicks());
   CommonNavigationParams(const CommonNavigationParams& other);
   ~CommonNavigationParams();
@@ -141,14 +161,6 @@
   // not be set.
   base::Optional<SourceLocation> source_location;
 
-  // Whether or not the CSP of the main world should apply. When the navigation
-  // is initiated from a content script in an isolated world, the CSP defined
-  // in the main world should not apply.
-  // TODO(arthursonzogni): Instead of this boolean, the origin of the isolated
-  // world which has initiated the navigation should be passed.
-  // See https://crbug.com/702540
-  CSPDisposition should_check_main_world_csp = CSPDisposition::CHECK;
-
   // Whether or not this navigation was started from a context menu.
   bool started_from_context_menu = false;
 
@@ -156,8 +168,7 @@
   bool has_user_gesture = false;
 
   // We require a copy of the relevant CSP to perform navigation checks.
-  std::vector<ContentSecurityPolicy> initiator_csp;
-  base::Optional<CSPSource> initiator_self_source;
+  InitiatorCSPInfo initiator_csp_info;
 
   // The current origin policy for this request's origin.
   // (Empty if none applies.)
diff --git a/content/public/test/navigation_simulator.cc b/content/public/test/navigation_simulator.cc
index 5872f8bb..9fc6892 100644
--- a/content/public/test/navigation_simulator.cc
+++ b/content/public/test/navigation_simulator.cc
@@ -967,12 +967,12 @@
     render_frame_host_->frame_host_binding_for_testing()
         .impl()
         ->BeginNavigation(common_params, std::move(begin_params), nullptr,
-                          navigation_client_ptr.PassInterface());
+                          navigation_client_ptr.PassInterface(), nullptr);
   } else {
     render_frame_host_->frame_host_binding_for_testing()
         .impl()
         ->BeginNavigation(common_params, std::move(begin_params), nullptr,
-                          nullptr);
+                          nullptr, nullptr);
   }
 
   NavigationRequest* request =
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index e06bc5c..0a22468f 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -567,10 +567,8 @@
       url, Referrer(), ui::PAGE_TRANSITION_LINK, FrameMsg_Navigate_Type::RELOAD,
       true, false, GURL(), GURL(), PREVIEWS_UNSPECIFIED, base::TimeTicks::Now(),
       "GET", nullptr, base::Optional<SourceLocation>(),
-      CSPDisposition::CHECK /* should_check_main_world_csp */,
       false /* started_from_context_menu */, false /* has_user_gesture */,
-      std::vector<ContentSecurityPolicy>() /* initiator_csp */,
-      CSPSource() /* initiator_self_source */);
+      InitiatorCSPInfo());
   RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_);
   TestRenderFrame* frame =
       static_cast<TestRenderFrame*>(impl->GetMainRenderFrame());
@@ -711,11 +709,8 @@
       url, Referrer(), ui::PAGE_TRANSITION_FORWARD_BACK,
       FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT, true, false, GURL(),
       GURL(), PREVIEWS_UNSPECIFIED, base::TimeTicks::Now(), "GET", nullptr,
-      base::Optional<SourceLocation>(),
-      CSPDisposition::CHECK /* should_check_main_world_csp */,
-      false /* started_from_context_menu */, false /* has_user_gesture */,
-      std::vector<ContentSecurityPolicy>() /* initiator_csp */,
-      CSPSource() /* initiator_self_source */);
+      base::Optional<SourceLocation>(), false /* started_from_context_menu */,
+      false /* has_user_gesture */, InitiatorCSPInfo());
   RequestNavigationParams request_params;
   request_params.page_state = state;
   request_params.nav_entry_id = pending_offset + 1;
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 1ed2844..fa9f391 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -194,9 +194,11 @@
 
 namespace {
 
+#ifndef STATIC_ASSERT_ENUM
 #define STATIC_ASSERT_ENUM(a, b)                            \
   static_assert(static_cast<int>(a) == static_cast<int>(b), \
                 "mismatching enums: " #a)
+#endif
 
 // Check PP_TextInput_Type and ui::TextInputType are kept in sync.
 STATIC_ASSERT_ENUM(ui::TEXT_INPUT_TYPE_NONE, PP_TEXTINPUT_TYPE_NONE);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 20539cd..c9b6d0f 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -537,13 +537,14 @@
       static_cast<PreviewsState>(info.url_request.GetPreviewsState()),
       base::TimeTicks::Now(), info.url_request.HttpMethod().Latin1(),
       GetRequestBodyForWebURLRequest(info.url_request), source_location,
-      should_check_main_world_csp, false /* started_from_context_menu */,
-      info.url_request.HasUserGesture(),
-      BuildContentSecurityPolicyList(info.url_request.GetNavigationCSP()),
-      info.url_request.GetNavigationCSP().self_source.has_value()
-          ? base::Optional<CSPSource>(BuildCSPSource(
-                info.url_request.GetNavigationCSP().self_source.value()))
-          : base::nullopt,
+      false /* started_from_context_menu */, info.url_request.HasUserGesture(),
+      InitiatorCSPInfo(
+          should_check_main_world_csp,
+          BuildContentSecurityPolicyList(info.url_request.GetInitiatorCSP()),
+          info.url_request.GetInitiatorCSP().self_source.has_value()
+              ? base::Optional<CSPSource>(BuildCSPSource(
+                    info.url_request.GetInitiatorCSP().self_source.value()))
+              : base::nullopt),
       input_start);
 }
 
@@ -4195,7 +4196,8 @@
 
 void RenderFrameImpl::DidStartProvisionalLoad(
     blink::WebDocumentLoader* document_loader,
-    blink::WebURLRequest& request) {
+    blink::WebURLRequest& request,
+    mojo::ScopedMessagePipeHandle navigation_initiator_handle) {
   // In fast/loader/stop-provisional-loads.html, we abort the load before this
   // callback is invoked.
   if (!document_loader)
@@ -4226,7 +4228,7 @@
     info.input_start = pending_navigation_info_->input_start;
 
     pending_navigation_info_.reset(nullptr);
-    BeginNavigation(info);
+    BeginNavigation(info, std::move(navigation_initiator_handle));
   }
 
   NavigationState* navigation_state =
@@ -6306,10 +6308,12 @@
       main_thread_use_time));
 }
 
+#ifndef STATIC_ASSERT_ENUM
 #define STATIC_ASSERT_ENUM(a, b)                            \
   static_assert(static_cast<int>(a) == static_cast<int>(b), \
                 "mismatching enums: " #a)
 #undef STATIC_ASSERT_ENUM
+#endif
 
 void RenderFrameImpl::OnEnableViewSourceMode() {
   DCHECK(frame_);
@@ -6721,7 +6725,9 @@
 }
 }  // namespace
 
-void RenderFrameImpl::BeginNavigation(const NavigationPolicyInfo& info) {
+void RenderFrameImpl::BeginNavigation(
+    const NavigationPolicyInfo& info,
+    mojo::ScopedMessagePipeHandle navigation_initiator_handle) {
   browser_side_navigation_pending_ = true;
   browser_side_navigation_pending_url_ = info.url_request.Url();
 
@@ -6820,10 +6826,15 @@
     BindNavigationClient(mojo::MakeRequest(&navigation_client_info));
     navigation_state->set_navigation_client(std::move(navigation_client_impl_));
   }
+
+  blink::mojom::NavigationInitiatorPtr initiator_ptr(
+      blink::mojom::NavigationInitiatorPtrInfo(
+          std::move(navigation_initiator_handle), 0));
+
   GetFrameHost()->BeginNavigation(
       MakeCommonNavigationParams(info, load_flags, info.input_start),
       std::move(begin_navigation_params), std::move(blob_url_token),
-      std::move(navigation_client_info));
+      std::move(navigation_client_info), std::move(initiator_ptr));
 }
 
 void RenderFrameImpl::LoadDataURL(
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index e993cf33..b4fe35c6 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -649,8 +649,10 @@
   void WillSendSubmitEvent(const blink::WebFormElement& form) override;
   void DidCreateDocumentLoader(
       blink::WebDocumentLoader* document_loader) override;
-  void DidStartProvisionalLoad(blink::WebDocumentLoader* document_loader,
-                               blink::WebURLRequest& request) override;
+  void DidStartProvisionalLoad(
+      blink::WebDocumentLoader* document_loader,
+      blink::WebURLRequest& request,
+      mojo::ScopedMessagePipeHandle navigation_initiator_handle) override;
   void DidFailProvisionalLoad(const blink::WebURLError& error,
                               blink::WebHistoryCommitType commit_type) override;
   void DidCommitProvisionalLoad(
@@ -1181,7 +1183,9 @@
       const RequestNavigationParams& request_params);
 
   // Sends a FrameHostMsg_BeginNavigation to the browser
-  void BeginNavigation(const NavigationPolicyInfo& info);
+  void BeginNavigation(
+      const NavigationPolicyInfo& info,
+      mojo::ScopedMessagePipeHandle navigation_initiator_handle);
 
   // Loads a data url.
   void LoadDataURL(
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index 6be7d66..4be7db30 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -85,7 +85,8 @@
   void BeginNavigation(const CommonNavigationParams& common_params,
                        mojom::BeginNavigationParamsPtr begin_params,
                        blink::mojom::BlobURLTokenPtr blob_url_token,
-                       mojom::NavigationClientAssociatedPtrInfo) override {}
+                       mojom::NavigationClientAssociatedPtrInfo,
+                       blink::mojom::NavigationInitiatorPtr) override {}
 
   void SubresourceResponseStarted(const GURL& url,
                                   net::CertStatus cert_status) override {}
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index 6c427b77..d309cf4 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -455,9 +455,10 @@
   if (IsPerNavigationMojoInterfaceEnabled()) {
     GetRemoteAssociatedInterfaces()->GetInterface(&navigation_client_ptr);
     BeginNavigation(common_params, std::move(begin_params), nullptr,
-                    navigation_client_ptr.PassInterface());
+                    navigation_client_ptr.PassInterface(), nullptr);
   } else {
-    BeginNavigation(common_params, std::move(begin_params), nullptr, nullptr);
+    BeginNavigation(common_params, std::move(begin_params), nullptr, nullptr,
+                    nullptr);
   }
 }