| // Copyright 2016 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/renderer_host/ancestor_throttle.h" |
| |
| #include "base/functional/bind.h" |
| #include "base/functional/callback_helpers.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "content/browser/renderer_host/frame_tree_node.h" |
| #include "content/browser/renderer_host/render_frame_host_impl.h" |
| #include "content/common/features.h" |
| #include "content/public/browser/navigation_handle.h" |
| #include "content/public/browser/navigation_throttle.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/test_renderer_host.h" |
| #include "content/test/navigation_simulator_impl.h" |
| #include "content/test/test_navigation_url_loader.h" |
| #include "net/http/http_response_headers.h" |
| #include "services/network/public/cpp/content_security_policy/content_security_policy.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace content { |
| |
| class AncestorThrottleNavigationTest : public RenderViewHostTestHarness { |
| public: |
| AncestorThrottleNavigationTest() { |
| scoped_feature_list.InitAndEnableFeature(features::kEmbeddingRequiresOptIn); |
| } |
| ~AncestorThrottleNavigationTest() override = default; |
| |
| AncestorThrottleNavigationTest(const AncestorThrottleNavigationTest& other) = |
| delete; |
| AncestorThrottleNavigationTest& operator=( |
| const AncestorThrottleNavigationTest& other) = delete; |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list; |
| }; |
| |
| TEST_F(AncestorThrottleNavigationTest, EmbeddingOptInRequirement) { |
| // Set up the main frame. We'll add nested frames to it in the tests below. |
| NavigateAndCommit(GURL("https://www.example.org")); |
| auto* main_frame = static_cast<TestRenderFrameHost*>(main_rfh()); |
| |
| struct TestCase { |
| const char* name; |
| const char* frame_url; |
| const char* xfo; |
| const char* csp; |
| NavigationThrottle::ThrottleAction expected_result; |
| } cases[] = {{ |
| "Same-origin, no XFO, no CSP", |
| "https://www.example.org", |
| nullptr, |
| nullptr, |
| NavigationThrottle::PROCEED, |
| }, |
| { |
| "Same-site, no XFO, no CSP", |
| "https://not.example.org", |
| nullptr, |
| nullptr, |
| NavigationThrottle::BLOCK_RESPONSE, |
| }, |
| { |
| "Same-site, XFO: ALLOWALL, no CSP", |
| "https://not.example.org", |
| "ALLOWALL", |
| nullptr, |
| NavigationThrottle::PROCEED, |
| }, |
| { |
| "Same-site, XFO: INVALID, no CSP", |
| "https://not.example.org", |
| "INVALID", |
| nullptr, |
| NavigationThrottle::PROCEED, |
| }, |
| { |
| "Same-site, no XFO, CSP: frame-ancestors *", |
| "https://not.example.org", |
| nullptr, |
| "frame-ancestors *", |
| NavigationThrottle::PROCEED, |
| }, |
| { |
| "Same-site, no XFO, CSP without frame-ancestors", |
| "https://not.example.org", |
| nullptr, |
| "img-src 'self'", |
| NavigationThrottle::BLOCK_RESPONSE, |
| }, |
| { |
| "Cross-origin, no XFO, no CSP", |
| "https://www.not-example.org", |
| nullptr, |
| nullptr, |
| NavigationThrottle::BLOCK_RESPONSE, |
| }, |
| { |
| "Cross-origin, XFO: ALLOWALL, no CSP", |
| "https://www.not-example.org", |
| "ALLOWALL", |
| nullptr, |
| NavigationThrottle::PROCEED, |
| }, |
| { |
| "Cross-origin, XFO: INVALID, no CSP", |
| "https://www.not-example.org", |
| "INVALID", |
| nullptr, |
| NavigationThrottle::PROCEED, |
| }, |
| { |
| "Cross-origin, no XFO, CSP: frame-ancestors *", |
| "https://www.not-example.org", |
| nullptr, |
| "frame-ancestors *", |
| NavigationThrottle::PROCEED, |
| }, |
| { |
| "Cross-origin, no XFO, CSP without frame-ancestors", |
| "https://www.not-example.org", |
| nullptr, |
| "img-src 'self'", |
| NavigationThrottle::BLOCK_RESPONSE, |
| }}; |
| |
| for (auto test : cases) { |
| SCOPED_TRACE(test.name); |
| auto* frame = static_cast<TestRenderFrameHost*>( |
| content::RenderFrameHostTester::For(main_frame) |
| ->AppendChild(test.name)); |
| std::unique_ptr<NavigationSimulator> simulator = |
| content::NavigationSimulator::CreateRendererInitiated( |
| GURL(test.frame_url), frame); |
| |
| auto response_headers = |
| base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK"); |
| if (test.xfo) |
| response_headers->SetHeader("X-Frame-Options", test.xfo); |
| if (test.csp) |
| response_headers->SetHeader("Content-Security-Policy", test.csp); |
| |
| simulator->SetResponseHeaders(response_headers); |
| simulator->ReadyToCommit(); |
| |
| EXPECT_EQ(test.expected_result, simulator->GetLastThrottleCheckResult()); |
| } |
| } |
| |
| } // namespace content |