Index: content/browser/frame_host/form_submission_throttle_browsertest.cc |
diff --git a/content/browser/frame_host/form_submission_throttle_browsertest.cc b/content/browser/frame_host/form_submission_throttle_browsertest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b3aec7225055d8b04b83afde0973479facceb265 |
--- /dev/null |
+++ b/content/browser/frame_host/form_submission_throttle_browsertest.cc |
@@ -0,0 +1,146 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+#include "content/browser/frame_host/form_submission_throttle.h" |
+ |
+#include "content/browser/frame_host/frame_tree_node.h" |
+#include "content/browser/frame_host/navigation_handle_impl.h" |
+#include "content/browser/web_contents/web_contents_impl.h" |
+#include "content/public/common/browser_side_navigation_policy.h" |
+#include "content/public/test/content_browser_test.h" |
+#include "content/public/test/content_browser_test_utils.h" |
+#include "content/shell/browser/shell.h" |
+#include "net/dns/mock_host_resolver.h" |
+#include "net/test/embedded_test_server/embedded_test_server.h" |
+#include "url/url_constants.h" |
+#include "url/url_util.h" |
+ |
+namespace content { |
+ |
+class FormSubmissionBrowserTest : public ContentBrowserTest { |
+ void SetUpOnMainThread() override { |
+ host_resolver()->AddRule("*", "127.0.0.1"); |
+ ASSERT_TRUE(embedded_test_server()->Start()); |
+ } |
+}; |
+ |
+IN_PROC_BROWSER_TEST_F(FormSubmissionBrowserTest, |
+ CheckContentSecurityPolicyFormAction) { |
+ // The FormSubmissionThrottle isn't used without PlzNavigate. |
+ if (!IsBrowserSideNavigationEnabled()) |
+ return; |
+ |
+ const struct { |
+ GURL main_page_url; |
+ GURL form_page_url; |
+ NavigationThrottle::ThrottleCheckResult start_expectation; |
+ NavigationThrottle::ThrottleCheckResult redirect_expectation; |
+ } kTestCases[] = { |
+ // Form submissions is allowed by default when there is no CSP. |
+ { |
+ embedded_test_server()->GetURL( |
+ "/form_submission_throttle/no_csp.html"), |
+ embedded_test_server()->GetURL("/simple_page.html"), |
+ NavigationThrottle::PROCEED, // start expectation. |
+ NavigationThrottle::PROCEED // redirect expectation. |
+ }, |
+ |
+ // No form submission is allowed when the calling RenderFrameHost's CSP |
+ // is "form-action 'none'". |
+ { |
+ embedded_test_server()->GetURL( |
+ "/form_submission_throttle/form_action_none.html"), |
+ embedded_test_server()->GetURL("/simple_page.html"), |
+ NavigationThrottle::CANCEL, // start expectation. |
+ NavigationThrottle::CANCEL // redirect expectation. |
+ }, |
+ |
+ // The path of the source-expression is only enforced when there is no |
+ // redirection. By using this behavior, this test can check a case where |
+ // the request is canceled in WillStartRequest() but not in |
+ // WillRedirectRequest(). |
+ // See https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects for |
+ // details. |
+ { |
+ embedded_test_server()->GetURL( |
+ "/form_submission_throttle/form_action_with_path.html"), |
+ embedded_test_server()->GetURL("/not_the_file.html"), |
+ NavigationThrottle::CANCEL, // start expectation. |
+ NavigationThrottle::PROCEED // redirect expectation. |
+ }, |
+ }; |
+ |
+ for (const auto& test : kTestCases) { |
+ SCOPED_TRACE(testing::Message() |
+ << std::endl |
+ << "main_page_url = " << test.main_page_url << std::endl |
+ << "form_page_url = " << test.form_page_url << std::endl); |
+ |
+ // Load the main page. |
+ EXPECT_TRUE(NavigateToURL(shell(), test.main_page_url)); |
+ |
+ // Build a new form submission navigation. |
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
+ ->GetFrameTree() |
+ ->root(); |
+ std::unique_ptr<NavigationHandle> handle = NavigationHandleImpl::Create( |
+ test.form_page_url, // url |
+ std::vector<GURL>(), // redirect chain |
+ root, // frame_tree_node |
+ true, // is_renderer_initiated |
+ false, // is_same_page |
+ base::TimeTicks::Now(), // navigation_start |
+ 0, // pending_nav_entry_id |
+ false, // started_from_context_menu |
+ CSPDisposition::CHECK, // should_check_main_world_csp |
+ true); // is_form_submission |
+ |
+ // Test the expectations with a FormSubmissionThrottle. |
+ std::unique_ptr<NavigationThrottle> throttle = |
+ FormSubmissionThrottle::MaybeCreateThrottleFor(handle.get()); |
+ ASSERT_TRUE(throttle); |
+ EXPECT_EQ(test.start_expectation, throttle->WillStartRequest()); |
+ EXPECT_EQ(test.redirect_expectation, throttle->WillRedirectRequest()); |
+ } |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(FormSubmissionBrowserTest, |
+ CheckContentSecurityPolicyFormActionBypassCSP) { |
+ // The FormSubmissionThrottle isn't used without PlzNavigate. |
+ if (!IsBrowserSideNavigationEnabled()) |
+ return; |
+ |
+ GURL main_url = embedded_test_server()->GetURL( |
+ "/form_submission_throttle/form_action_none.html"); |
+ GURL form_url = embedded_test_server()->GetURL("/simple_page.html"); |
+ |
+ // Load the main page. |
+ EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
+ |
+ // Build a new form submission navigation. |
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
+ ->GetFrameTree() |
+ ->root(); |
+ std::unique_ptr<NavigationHandle> handle = NavigationHandleImpl::Create( |
+ form_url, // url |
+ std::vector<GURL>(), // redirect chain |
+ root, // frame_tree_node |
+ true, // is_renderer_initiated |
+ false, // is_same_page |
+ base::TimeTicks::Now(), // navigation_start |
+ 0, // pending_nav_entry_id |
+ false, // started_from_context_menu |
+ CSPDisposition::DO_NOT_CHECK, // should_check_main_world_csp |
+ true); // is_form_submission |
+ |
+ // Test that the navigation is allowed because "should_by_pass_main_world_csp" |
+ // is true, even if it is a form submission and the policy is |
+ // "form-action 'none'". |
+ std::unique_ptr<NavigationThrottle> throttle = |
+ FormSubmissionThrottle::MaybeCreateThrottleFor(handle.get()); |
+ ASSERT_TRUE(throttle); |
+ EXPECT_EQ(NavigationThrottle::PROCEED, throttle->WillStartRequest()); |
+ EXPECT_EQ(NavigationThrottle::PROCEED, throttle->WillRedirectRequest()); |
+} |
+ |
+} // namespace content |