1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/frame_host/frame_tree_node.h"
6 #include "content/browser/frame_host/navigation_request.h"
7 #include "content/public/browser/navigation_throttle.h"
8 #include "content/test/navigation_simulator_impl.h"
9 #include "content/test/test_render_frame_host.h"
10 #include "content/test/test_render_view_host.h"
11 
12 namespace content {
13 
14 class FormSubmissionTest : public RenderViewHostImplTestHarness {
15  public:
PreventFormSubmission()16   void PreventFormSubmission() {
17     auto source_none = network::mojom::CSPSourceList::New(
18         std::vector<network::mojom::CSPSourcePtr>(), false, false, false);
19     auto policy = network::mojom::ContentSecurityPolicy::New();
20     policy->header = network::mojom::ContentSecurityPolicyHeader::New();
21     policy->directives[network::mojom::CSPDirectiveName::FormAction] =
22         std::move(source_none);
23     main_test_rfh()->AddContentSecurityPolicy(std::move(policy));
24   }
25 };
26 
27 // Tests that form submissions are allowed by default when there is no CSP.
TEST_F(FormSubmissionTest,ContentSecurityPolicyFormActionNoCSP)28 TEST_F(FormSubmissionTest, ContentSecurityPolicyFormActionNoCSP) {
29   const GURL kUrl("https://chromium.org");
30   const GURL kFormUrl("https://foo.com");
31   const GURL kRedirectUrl("https://bar.com");
32 
33   // Load a page.
34   NavigateAndCommit(kUrl);
35 
36   // Try to submit a form.
37   auto form_submission =
38       NavigationSimulatorImpl::CreateRendererInitiated(kFormUrl, main_rfh());
39   form_submission->SetIsFormSubmission(true);
40   form_submission->set_should_check_main_world_csp(
41       network::mojom::CSPDisposition::CHECK);
42   form_submission->Start();
43   EXPECT_EQ(NavigationThrottle::PROCEED,
44             form_submission->GetLastThrottleCheckResult());
45   form_submission->Redirect(kRedirectUrl);
46   EXPECT_EQ(NavigationThrottle::PROCEED,
47             form_submission->GetLastThrottleCheckResult());
48 }
49 
50 // Tests that no form submission is allowed when the calling RenderFrameHost's
51 // CSP is "form-action 'none'".
TEST_F(FormSubmissionTest,ContentSecurityPolicyFormActionNone)52 TEST_F(FormSubmissionTest, ContentSecurityPolicyFormActionNone) {
53   const GURL kUrl("https://chromium.org");
54   const GURL kFormUrl("https://foo.com");
55   const GURL kRedirectUrl("https://bar.com");
56 
57   // Load a page.
58   NavigateAndCommit(kUrl);
59   PreventFormSubmission();
60 
61   // Try to submit a form.
62   auto form_submission =
63       NavigationSimulatorImpl::CreateRendererInitiated(kFormUrl, main_rfh());
64   form_submission->SetIsFormSubmission(true);
65   form_submission->set_should_check_main_world_csp(
66       network::mojom::CSPDisposition::CHECK);
67 
68   // Browser side checks have been disabled on the initial load. Only the
69   // renderer side checks occurs. Related issue: https://crbug.com/798698.
70   form_submission->Start();
71   EXPECT_EQ(NavigationThrottle::PROCEED,
72             form_submission->GetLastThrottleCheckResult());
73 
74   form_submission->Redirect(kRedirectUrl);
75   EXPECT_EQ(NavigationThrottle::CANCEL,
76             form_submission->GetLastThrottleCheckResult());
77 }
78 
79 // Tests that the navigation is allowed because "should_by_pass_main_world_csp"
80 // is true, even if it is a form submission and the policy is
81 // "form-action 'none'".
TEST_F(FormSubmissionTest,ContentSecurityPolicyFormActionBypassCSP)82 TEST_F(FormSubmissionTest, ContentSecurityPolicyFormActionBypassCSP) {
83   const GURL kUrl("https://chromium.org");
84   const GURL kFormUrl("https://foo.com");
85   const GURL kRedirectUrl("https://bar.com");
86 
87   // Load a page.
88   NavigateAndCommit(kUrl);
89   PreventFormSubmission();
90 
91   // Try to submit a form.
92   auto form_submission =
93       NavigationSimulatorImpl::CreateRendererInitiated(kFormUrl, main_rfh());
94   form_submission->SetIsFormSubmission(true);
95   form_submission->set_should_check_main_world_csp(
96       network::mojom::CSPDisposition::DO_NOT_CHECK);
97   form_submission->Start();
98   EXPECT_EQ(NavigationThrottle::PROCEED,
99             form_submission->GetLastThrottleCheckResult());
100 
101   form_submission->Redirect(kRedirectUrl);
102   EXPECT_EQ(NavigationThrottle::PROCEED,
103             form_submission->GetLastThrottleCheckResult());
104 }
105 
106 }  // namespace content
107