blob: 639c596da80a384ec2d9ffadf7552fd1631918da [file] [log] [blame]
// Copyright 2020 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/policy_container_host.h"
#include "base/run_loop.h"
#include "content/public/test/browser_task_environment.h"
#include "services/network/public/mojom/content_security_policy.mojom.h"
#include "services/network/public/mojom/ip_address_space.mojom-shared.h"
#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
using ::testing::ByRef;
using ::testing::Eq;
using ::testing::Pointee;
namespace {
struct SameSizeAsPolicyContainerPolicies {
network::mojom::ReferrerPolicy referrer_policy;
network::mojom::IPAddressSpace ip_address_space;
bool is_web_secure_context;
std::vector<network::mojom::ContentSecurityPolicyPtr>
content_security_policies;
network::CrossOriginOpenerPolicy cross_origin_opener_policy;
network::CrossOriginEmbedderPolicy cross_origin_embedder_policy;
network::mojom::WebSandboxFlags sandbox_flags;
bool is_credentialless;
bool can_navigate_top_without_user_gesture;
};
} // namespace
// Asserts size of PolicyContainerPolicies, so that whenever a new element is
// added to PolicyContainerPolicies, the assert will fail. When hitting this
// assert failure, please ensure that the attribute is
// - added to the PolicyContainerPolicies constructor
// - copied correctly in PolicyContainerPolicies::Clone()
// - checked correctly in PolicyContainerPolicies::operator==
// - handled correctly in PolicyContainerPolicies::operator<<
// - tested correctly in PolicyContainerHostTest.PolicyContainerPolicies below.
static_assert(sizeof(PolicyContainerPolicies) ==
sizeof(SameSizeAsPolicyContainerPolicies),
"PolicyContainerPolicies have been modified");
TEST(PolicyContainerPoliciesTest, CloneIsEqual) {
std::vector<network::mojom::ContentSecurityPolicyPtr> csps;
auto csp = network::mojom::ContentSecurityPolicy::New();
csp->treat_as_public_address = true;
csps.push_back(std::move(csp));
network::CrossOriginOpenerPolicy coop;
network::mojom::WebSandboxFlags sandbox_flags =
network::mojom::WebSandboxFlags::kOrientationLock |
network::mojom::WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts;
coop.value = network::mojom::CrossOriginOpenerPolicyValue::kSameOrigin;
coop.report_only_value =
network::mojom::CrossOriginOpenerPolicyValue::kSameOriginAllowPopups;
coop.reporting_endpoint = "endpoint 1";
coop.report_only_reporting_endpoint = "endpoint 2";
network::CrossOriginEmbedderPolicy coep;
coep.value = network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
coep.report_only_value =
network::mojom::CrossOriginEmbedderPolicyValue::kCredentialless;
coep.reporting_endpoint = "endpoint 1";
coep.report_only_reporting_endpoint = "endpoint 2";
PolicyContainerPolicies policies(
network::mojom::ReferrerPolicy::kAlways,
network::mojom::IPAddressSpace::kUnknown,
/*is_web_secure_context=*/true, std::move(csps), coop, coep,
sandbox_flags,
/*is_credentialless=*/true,
/*can_navigate_top_without_user_gesture=*/true);
EXPECT_THAT(policies.Clone(), Eq(ByRef(policies)));
}
TEST(PolicyContainerHostTest, ReferrerPolicy) {
scoped_refptr<PolicyContainerHost> policy_container =
base::MakeRefCounted<PolicyContainerHost>();
EXPECT_EQ(network::mojom::ReferrerPolicy::kDefault,
policy_container->referrer_policy());
static_cast<blink::mojom::PolicyContainerHost*>(policy_container.get())
->SetReferrerPolicy(network::mojom::ReferrerPolicy::kAlways);
EXPECT_EQ(network::mojom::ReferrerPolicy::kAlways,
policy_container->referrer_policy());
}
TEST(PolicyContainerHostTest, AssociateWithFrameToken) {
// We need to satisfy DCHECK_CURRENTLY_ON(BrowserThread::UI).
content::BrowserTaskEnvironment task_environment;
scoped_refptr<PolicyContainerHost> policy_container_host =
base::MakeRefCounted<PolicyContainerHost>();
blink::LocalFrameToken token;
policy_container_host->AssociateWithFrameToken(token);
EXPECT_EQ(policy_container_host.get(),
PolicyContainerHost::FromFrameToken(token));
// Check that we can associate a new PolicyContainerHost to the same frame
// token and everything works correctly.
scoped_refptr<PolicyContainerHost> policy_container_host_2 =
base::MakeRefCounted<PolicyContainerHost>();
policy_container_host_2->AssociateWithFrameToken(token);
EXPECT_EQ(policy_container_host_2.get(),
PolicyContainerHost::FromFrameToken(token));
}
TEST(PolicyContainerHostTest, KeepAliveThroughBlinkPolicyContainerRemote) {
// Enable tasks and RunLoop on the main thread and satisfy
// DCHECK_CURRENTLY_ON(BrowserThread::UI).
content::BrowserTaskEnvironment task_environment;
scoped_refptr<PolicyContainerHost> policy_container_host =
base::MakeRefCounted<PolicyContainerHost>();
blink::LocalFrameToken token;
policy_container_host->AssociateWithFrameToken(token);
blink::mojom::PolicyContainerPtr blink_policy_container =
policy_container_host->CreatePolicyContainerForBlink();
PolicyContainerHost* raw_pointer = policy_container_host.get();
EXPECT_EQ(raw_pointer, PolicyContainerHost::FromFrameToken(token));
policy_container_host.reset();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(raw_pointer, PolicyContainerHost::FromFrameToken(token));
blink_policy_container->remote.reset();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(PolicyContainerHost::FromFrameToken(token));
}
// Test that the disconnect handler is called when all keep alive handles
// disconnect.
TEST(PolicyContainerHostTest, KeepAliveThroughKeepAlives) {
// Enable tasks and RunLoop on the main thread and satisfy
// DCHECK_CURRENTLY_ON(BrowserThread::UI).
content::BrowserTaskEnvironment task_environment;
scoped_refptr<PolicyContainerHost> policy_container_host =
base::MakeRefCounted<PolicyContainerHost>();
blink::LocalFrameToken token;
policy_container_host->AssociateWithFrameToken(token);
mojo::PendingRemote<blink::mojom::PolicyContainerHostKeepAliveHandle>
keep_alive;
policy_container_host->IssueKeepAliveHandle(
keep_alive.InitWithNewPipeAndPassReceiver());
PolicyContainerHost* raw_pointer = policy_container_host.get();
EXPECT_EQ(raw_pointer, PolicyContainerHost::FromFrameToken(token));
policy_container_host.reset();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(raw_pointer, PolicyContainerHost::FromFrameToken(token));
keep_alive.reset();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(PolicyContainerHost::FromFrameToken(token));
}
} // namespace content