#include "mojo/public/cpp/bindings/tests/feature_unittest.test-mojom-features.h"
#include "mojo/public/cpp/bindings/tests/feature_unittest.test-mojom-forward.h"
#include "mojo/public/cpp/bindings/tests/feature_unittest.test-mojom-shared.h"
#include "mojo/public/cpp/bindings/tests/feature_unittest.test-mojom.h"
#include <utility>
#include "base/dcheck_is_on.h"
#include "base/feature_list.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/generic_pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "mojo/public/cpp/bindings/service_factory.h"
#include "mojo/public/cpp/bindings/shared_associated_remote.h"
#include "mojo/public/cpp/bindings/shared_remote.h"
#include "mojo/public/cpp/bindings/tests/bindings_test_base.h"
#include "mojo/public/cpp/system/functions.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo::test::feature_unittest {
namespace {
class DefaultDeniedImpl : public mojom::DefaultDenied {
public:
explicit DefaultDeniedImpl(
mojo::PendingReceiver<mojom::DefaultDenied> receiver)
: receiver_(this, std::move(receiver)) {}
DefaultDeniedImpl() : receiver_(this) {}
~DefaultDeniedImpl() override = default;
DefaultDeniedImpl(const DefaultDeniedImpl&) = delete;
DefaultDeniedImpl& operator=(const DefaultDeniedImpl&) = delete;
void GetInt(GetIntCallback callback) override { std::move(callback).Run(1); }
mojo::Receiver<mojom::DefaultDenied>& receiver() { return receiver_; }
static auto RunService(PendingReceiver<mojom::DefaultDenied> receiver) {
return std::make_unique<DefaultDeniedImpl>(std::move(receiver));
}
private:
mojo::Receiver<mojom::DefaultDenied> receiver_;
};
class OtherDeniedImpl : public mojom::OtherDenied {
public:
explicit OtherDeniedImpl(mojo::PendingReceiver<mojom::OtherDenied> receiver)
: receiver_(this, std::move(receiver)) {}
OtherDeniedImpl() : receiver_(this) {}
~OtherDeniedImpl() override = default;
OtherDeniedImpl(const OtherDeniedImpl&) = delete;
OtherDeniedImpl& operator=(const OtherDeniedImpl&) = delete;
void GetInt(GetIntCallback callback) override { std::move(callback).Run(1); }
mojo::Receiver<mojom::OtherDenied>& receiver() { return receiver_; }
private:
mojo::Receiver<mojom::OtherDenied> receiver_;
};
class OtherAllowedImpl : public mojom::OtherAllowed {
public:
explicit OtherAllowedImpl(mojo::PendingReceiver<mojom::OtherAllowed> receiver)
: receiver_(this, std::move(receiver)) {}
OtherAllowedImpl() : receiver_(this) {}
~OtherAllowedImpl() override = default;
OtherAllowedImpl(const OtherAllowedImpl&) = delete;
OtherAllowedImpl& operator=(const OtherAllowedImpl&) = delete;
void GetInt(GetIntCallback callback) override { std::move(callback).Run(1); }
mojo::Receiver<mojom::OtherAllowed>& receiver() { return receiver_; }
private:
mojo::Receiver<mojom::OtherAllowed> receiver_;
};
class DefaultDeniedSelfOwnedImpl : public mojom::DefaultDenied {
public:
DefaultDeniedSelfOwnedImpl() = default;
~DefaultDeniedSelfOwnedImpl() override = default;
DefaultDeniedSelfOwnedImpl(const DefaultDeniedSelfOwnedImpl&) = delete;
DefaultDeniedSelfOwnedImpl& operator=(const DefaultDeniedSelfOwnedImpl&) =
delete;
void GetInt(GetIntCallback callback) override { std::move(callback).Run(1); }
};
class DefaultAllowedSelfOwnedImpl : public mojom::DefaultAllowed {
public:
DefaultAllowedSelfOwnedImpl() = default;
~DefaultAllowedSelfOwnedImpl() override = default;
DefaultAllowedSelfOwnedImpl(const DefaultAllowedSelfOwnedImpl&) = delete;
DefaultAllowedSelfOwnedImpl& operator=(const DefaultAllowedSelfOwnedImpl&) =
delete;
void GetInt(GetIntCallback callback) override { std::move(callback).Run(1); }
};
class DefaultAllowedImpl : mojom::DefaultAllowed {
public:
explicit DefaultAllowedImpl(
mojo::PendingReceiver<mojom::DefaultAllowed> receiver)
: receiver_(this, std::move(receiver)) {}
~DefaultAllowedImpl() override = default;
DefaultAllowedImpl(const DefaultAllowedImpl&) = delete;
DefaultAllowedImpl& operator=(const DefaultAllowedImpl&) = delete;
void GetInt(GetIntCallback callback) override { std::move(callback).Run(1); }
mojo::Receiver<mojom::DefaultAllowed>& receiver() { return receiver_; }
static auto RunService(PendingReceiver<mojom::DefaultAllowed> receiver) {
return std::make_unique<DefaultAllowedImpl>(std::move(receiver));
}
private:
mojo::Receiver<mojom::DefaultAllowed> receiver_;
};
class FeaturesOnMethodsImpl : public mojom::FeaturesOnMethods {
public:
explicit FeaturesOnMethodsImpl(
mojo::PendingReceiver<mojom::FeaturesOnMethods> receiver)
: receiver_(this, std::move(receiver)), assoc_receiver_(nullptr) {}
explicit FeaturesOnMethodsImpl(
mojo::PendingAssociatedReceiver<mojom::FeaturesOnMethods> receiver)
: receiver_(nullptr), assoc_receiver_(this, std::move(receiver)) {}
~FeaturesOnMethodsImpl() override = default;
FeaturesOnMethodsImpl(const FeaturesOnMethodsImpl&) = delete;
FeaturesOnMethodsImpl& operator=(const FeaturesOnMethodsImpl&) = delete;
void DefaultDenied(DefaultDeniedCallback callback) override {
std::move(callback).Run(1);
}
void DefaultDeniedSync(DefaultDeniedCallback callback) override {
std::move(callback).Run(1);
}
void DefaultAllowed(DefaultAllowedCallback callback) override {
std::move(callback).Run(1);
}
void Normal(NormalCallback callback) override { std::move(callback).Run(1); }
private:
mojo::Receiver<mojom::FeaturesOnMethods> receiver_;
mojo::AssociatedReceiver<mojom::FeaturesOnMethods> assoc_receiver_;
};
class PassesInterfacesImpl : public mojom::PassesInterfaces {
public:
explicit PassesInterfacesImpl(
mojo::PendingReceiver<mojom::PassesInterfaces> receiver)
: receiver_(this, std::move(receiver)) {}
~PassesInterfacesImpl() override = default;
PassesInterfacesImpl(const PassesInterfacesImpl&) = delete;
PassesInterfacesImpl& operator=(const PassesInterfacesImpl&) = delete;
void OnGetInt(PassPendingOptionalRemoteAllowedCallback callback, int val) {
std::move(callback).Run(val == 1);
}
void PassPendingOptionalRemoteAllowed(
mojo::PendingRemote<mojom::DefaultAllowed> iface,
PassPendingOptionalRemoteAllowedCallback callback) override {
allowed_remote_.Bind(std::move(iface));
ASSERT_TRUE(allowed_remote_);
allowed_remote_->GetInt(base::BindOnce(&PassesInterfacesImpl::OnGetInt,
base::Unretained(this),
std::move(callback)));
}
void PassPendingOptionalRemoteDisabled(
mojo::PendingRemote<mojom::DefaultDenied> iface,
PassPendingOptionalRemoteDisabledCallback callback) override {
ASSERT_FALSE(iface.is_valid());
std::move(callback).Run(true);
}
void PassPendingOptionalReceiverAllowed(
mojo::PendingReceiver<mojom::DefaultAllowed> iface) override {
allowed_impl_ = std::make_unique<DefaultAllowedImpl>(std::move(iface));
ASSERT_TRUE(allowed_impl_->receiver().is_bound());
}
void PassPendingOptionalReceiverDisabled(
mojo::PendingReceiver<mojom::DefaultDenied> iface,
PassPendingOptionalReceiverDisabledCallback callback) override {
denied_impl_ = std::make_unique<DefaultDeniedImpl>(std::move(iface));
ASSERT_FALSE(denied_impl_->receiver().is_bound());
std::move(callback).Run(true);
}
private:
mojo::Receiver<mojom::PassesInterfaces> receiver_;
mojo::Remote<mojom::DefaultAllowed> allowed_remote_;
mojo::Remote<mojom::DefaultDenied> denied_remote_;
std::unique_ptr<DefaultAllowedImpl> allowed_impl_;
std::unique_ptr<DefaultDeniedImpl> denied_impl_;
};
}
class FeatureBindingsTest : public BindingsTestBase {
public:
void SetUp() override {
mojo::SetDefaultProcessErrorHandler(base::BindRepeating(
&FeatureBindingsTest::OnProcessError, base::Unretained(this)));
}
void TearDown() override {
mojo::SetDefaultProcessErrorHandler(base::NullCallback());
}
void SetErrorHandler(base::OnceClosure handler) {
error_handler_ = std::move(handler);
}
private:
void OnProcessError(const std::string& error) {
if (error_handler_) {
std::move(error_handler_).Run();
}
}
base::OnceClosure error_handler_;
};
TEST(FeatureTest, FeatureBasics) {
EXPECT_TRUE(base::FeatureList::IsEnabled(
mojo::test::feature_unittest::mojom::TestFeatureOn));
EXPECT_FALSE(base::FeatureList::IsEnabled(
mojo::test::feature_unittest::mojom::TestFeatureOff));
}
TEST(FeatureTest, ScopedFeatures) {
base::test::ScopedFeatureList feature_list1;
feature_list1.InitFromCommandLine("TestFeatureOff", "TestFeatureOn");
EXPECT_FALSE(base::FeatureList::IsEnabled(
mojo::test::feature_unittest::mojom::TestFeatureOn));
EXPECT_TRUE(base::FeatureList::IsEnabled(
mojo::test::feature_unittest::mojom::TestFeatureOff));
}
TEST_P(FeatureBindingsTest, DefaultAllowed) {
bool error = false;
SetErrorHandler(base::BindLambdaForTesting([&] { error = true; }));
Remote<mojom::DefaultAllowed> remote;
DefaultAllowedImpl impl(remote.BindNewPipeAndPassReceiver());
EXPECT_TRUE(remote);
base::RunLoop run_loop;
remote->GetInt(base::BindLambdaForTesting([&](int) { run_loop.Quit(); }));
run_loop.Run();
EXPECT_FALSE(error);
}
TEST_P(FeatureBindingsTest, OtherAllowed) {
bool error = false;
SetErrorHandler(base::BindLambdaForTesting([&] { error = true; }));
Remote<mojom::OtherAllowed> remote;
OtherAllowedImpl impl(remote.BindNewPipeAndPassReceiver());
EXPECT_TRUE(remote);
base::RunLoop run_loop;
remote->GetInt(base::BindLambdaForTesting([&](int) { run_loop.Quit(); }));
run_loop.Run();
EXPECT_FALSE(error);
}
TEST_P(FeatureBindingsTest, FeaturesOnMethodsAllowed) {
bool error = false;
SetErrorHandler(base::BindLambdaForTesting([&] { error = true; }));
Remote<mojom::FeaturesOnMethods> remote;
EXPECT_FALSE(remote);
FeaturesOnMethodsImpl impl(remote.BindNewPipeAndPassReceiver());
EXPECT_TRUE(remote);
base::RunLoop run_loop;
remote->DefaultAllowed(
base::BindLambdaForTesting([&](int) { run_loop.Quit(); }));
run_loop.Run();
base::RunLoop run_loop2;
remote->Normal(base::BindLambdaForTesting([&](int) { run_loop2.Quit(); }));
run_loop2.Run();
EXPECT_FALSE(error);
}
TEST_P(FeatureBindingsTest, FeaturesOnReceiverDenied) {
if (GetParam() == mojo::BindingsTestSerializationMode::kNeverSerialize) {
return;
}
bool called = false;
bool called_disconnect = false;
base::RunLoop run_loop;
Remote<mojom::FeaturesOnMethods> remote;
auto pending_receiver = remote.BindNewPipeAndPassReceiver();
remote.set_disconnect_handler(base::BindLambdaForTesting([&] {
called_disconnect = true;
run_loop.Quit();
}));
{
base::test::ScopedFeatureList feature_list;
feature_list.InitFromCommandLine("TestFeatureOff", "");
remote->DefaultDenied(
base::BindLambdaForTesting([&](int) { called = true; }));
}
FeaturesOnMethodsImpl impl(std::move(pending_receiver));
run_loop.Run();
EXPECT_FALSE(called);
EXPECT_TRUE(called_disconnect);
}
TEST_P(FeatureBindingsTest, PassesInterfacesAllowed) {
bool error = false;
SetErrorHandler(base::BindLambdaForTesting([&] { error = true; }));
Remote<mojom::PassesInterfaces> remote;
EXPECT_FALSE(remote);
PassesInterfacesImpl impl(remote.BindNewPipeAndPassReceiver());
EXPECT_TRUE(remote);
{
base::RunLoop run_loop;
MessagePipe pipe;
PendingRemote<mojom::DefaultAllowed> allowed_pending_remote(
std::move(pipe.handle0), 0);
PendingReceiver<mojom::DefaultAllowed> allowed_pending_receiver(
std::move(pipe.handle1));
bool cb_val = false;
remote->PassPendingOptionalRemoteAllowed(
std::move(allowed_pending_remote),
base::BindLambdaForTesting([&](bool val) {
cb_val = val;
run_loop.Quit();
}));
DefaultAllowedImpl allowed_impl(std::move(allowed_pending_receiver));
run_loop.Run();
ASSERT_TRUE(cb_val);
}
{
base::RunLoop run_loop;
MessagePipe pipe;
PendingRemote<mojom::DefaultAllowed> allowed_pending_remote(
std::move(pipe.handle0), 0);
PendingReceiver<mojom::DefaultAllowed> allowed_pending_receiver(
std::move(pipe.handle1));
bool cb_val = false;
remote->PassPendingOptionalReceiverAllowed(
std::move(allowed_pending_receiver));
Remote<mojom::DefaultAllowed> allowed(std::move(allowed_pending_remote));
allowed->GetInt(base::BindLambdaForTesting([&](int val) {
cb_val = val == 1;
run_loop.Quit();
}));
run_loop.Run();
ASSERT_TRUE(cb_val);
}
}
TEST_P(FeatureBindingsTest, SetsAllowed) {
Remote<mojom::DefaultAllowed> remote_a;
Remote<mojom::DefaultAllowed> remote_b;
DefaultAllowedImpl impl_a(remote_a.BindNewPipeAndPassReceiver());
DefaultAllowedImpl impl_b(remote_b.BindNewPipeAndPassReceiver());
PendingRemote<mojom::DefaultAllowed> pending_remote_c;
auto pending_receiver_c = pending_remote_c.InitWithNewPipeAndPassReceiver();
PendingRemote<mojom::DefaultAllowed> pending_remote_d;
auto pending_receiver_d = pending_remote_d.InitWithNewPipeAndPassReceiver();
auto impl_c = std::make_unique<DefaultAllowedSelfOwnedImpl>();
auto impl_d = std::make_unique<DefaultAllowedSelfOwnedImpl>();
ReceiverSet<mojom::DefaultAllowed> receiver_set;
receiver_set.Add(impl_c.get(), std::move(pending_receiver_c));
receiver_set.Add(impl_d.get(), std::move(pending_receiver_d));
RemoteSet<mojom::DefaultAllowed> remote_set;
remote_set.Add(std::move(remote_a));
remote_set.Add(std::move(remote_b));
remote_set.Add(std::move(pending_remote_c));
remote_set.Add(std::move(pending_remote_d));
}
TEST_P(FeatureBindingsTest, ServiceFactory) {
ServiceFactory services;
MessagePipe pipe_allowed;
MessagePipe pipe_denied;
services.Add(DefaultAllowedImpl::RunService);
services.Add(DefaultDeniedImpl::RunService);
GenericPendingReceiver gpr_allowed(mojom::DefaultAllowed::Name_,
std::move(pipe_allowed.handle0));
GenericPendingReceiver gpr_denied(mojom::DefaultDenied::Name_,
std::move(pipe_denied.handle0));
EXPECT_TRUE(services.CanRunService(gpr_allowed));
EXPECT_FALSE(services.CanRunService(gpr_denied));
}
#if !DCHECK_IS_ON()
TEST_P(FeatureBindingsTest, InertPendingRemoteWontInit) {
PendingRemote<mojom::DefaultDenied> pending_remote;
EXPECT_FALSE(pending_remote);
PendingReceiver<mojom::DefaultDenied> pending_receiver =
pending_remote.InitWithNewPipeAndPassReceiver();
EXPECT_FALSE(pending_receiver);
EXPECT_FALSE(pending_remote);
}
TEST_P(FeatureBindingsTest, InertPendingReceiverWontInit) {
PendingReceiver<mojom::DefaultDenied> pending_receiver;
EXPECT_FALSE(pending_receiver);
PendingRemote<mojom::DefaultDenied> pending_remote =
pending_receiver.InitWithNewPipeAndPassRemote();
EXPECT_FALSE(pending_receiver);
EXPECT_FALSE(pending_remote);
}
TEST_P(FeatureBindingsTest, InertPendingAssociatedRemoteWontInit) {
PendingAssociatedRemote<mojom::DefaultDenied> pending_remote;
EXPECT_FALSE(pending_remote);
PendingAssociatedReceiver<mojom::DefaultDenied> pending_receiver =
pending_remote.InitWithNewEndpointAndPassReceiver();
EXPECT_FALSE(pending_receiver);
EXPECT_FALSE(pending_remote);
}
TEST_P(FeatureBindingsTest, InertPendingAssociatedReceiverWontInit) {
PendingAssociatedReceiver<mojom::DefaultDenied> pending_receiver;
EXPECT_FALSE(pending_receiver);
PendingAssociatedRemote<mojom::DefaultDenied> pending_remote =
pending_receiver.InitWithNewEndpointAndPassRemote();
EXPECT_FALSE(pending_receiver);
EXPECT_FALSE(pending_remote);
}
TEST_P(FeatureBindingsTest, RemoteWontBindNewPipe) {
Remote<mojom::DefaultDenied> remote;
EXPECT_FALSE(remote);
PendingReceiver<mojom::DefaultDenied> pending_receiver =
remote.BindNewPipeAndPassReceiver();
EXPECT_FALSE(pending_receiver);
}
TEST_P(FeatureBindingsTest, RemoteWontBindPendingRemote) {
MessagePipe pipe;
PendingRemote<mojom::DefaultDenied> pending_remote(std::move(pipe.handle0),
0);
Remote<mojom::DefaultDenied> remote;
EXPECT_FALSE(remote);
remote.Bind(std::move(pending_remote));
EXPECT_FALSE(remote);
}
TEST_P(FeatureBindingsTest, AssociatedRemoteWontBind) {
PendingAssociatedRemote<mojom::DefaultDenied> pa_remote;
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver;
{
base::test::ScopedFeatureList feature_list1;
feature_list1.InitFromCommandLine("TestFeatureOff", "");
pa_receiver = pa_remote.InitWithNewEndpointAndPassReceiver();
}
EXPECT_TRUE(pa_remote);
AssociatedRemote<mojom::DefaultDenied> a_remote;
a_remote.Bind(std::move(pa_remote));
EXPECT_FALSE(a_remote);
}
TEST_P(FeatureBindingsTest, AssociatedRemoteWontBindNewEndpoint) {
AssociatedRemote<mojom::DefaultDenied> a_remote;
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver =
a_remote.BindNewEndpointAndPassReceiver();
EXPECT_FALSE(a_remote);
EXPECT_FALSE(pa_receiver);
}
TEST_P(FeatureBindingsTest, AssociatedRemoteWontBindDedicated) {
AssociatedRemote<mojom::DefaultDenied> a_remote;
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver =
a_remote.BindNewEndpointAndPassDedicatedReceiver();
EXPECT_FALSE(a_remote);
EXPECT_FALSE(pa_receiver);
}
TEST_P(FeatureBindingsTest, ReceiverWontBindNewPipe) {
DefaultDeniedImpl impl;
PendingRemote<mojom::DefaultDenied> pending_remote =
impl.receiver().BindNewPipeAndPassRemote();
EXPECT_FALSE(pending_remote);
}
TEST_P(FeatureBindingsTest, ReceiverWontBindPendingReceiver) {
MessagePipe pipe;
PendingReceiver<mojom::DefaultDenied> pending_receiver(
std::move(pipe.handle0));
EXPECT_TRUE(pending_receiver);
DefaultDeniedImpl impl(std::move(pending_receiver));
EXPECT_FALSE(impl.receiver().is_bound());
}
TEST_P(FeatureBindingsTest, AssociatedReceiverWontBind) {
PendingAssociatedRemote<mojom::DefaultDenied> pa_remote;
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver =
pa_remote.InitWithNewEndpointAndPassReceiver();
DefaultDeniedSelfOwnedImpl impl;
AssociatedReceiver<mojom::DefaultDenied> a_receiver(&impl);
a_receiver.Bind(std::move(pa_receiver), nullptr);
EXPECT_FALSE(a_receiver.is_bound());
}
TEST_P(FeatureBindingsTest, AssociatedReceiverWontBindNewEndpoint) {
DefaultDeniedSelfOwnedImpl impl;
AssociatedReceiver<mojom::DefaultDenied> a_receiver(&impl);
auto a_remote = a_receiver.BindNewEndpointAndPassRemote(nullptr);
EXPECT_FALSE(a_receiver);
EXPECT_FALSE(a_remote);
}
TEST_P(FeatureBindingsTest, AssociatedReceiverWontBindDedicated) {
DefaultDeniedSelfOwnedImpl impl;
AssociatedReceiver<mojom::DefaultDenied> a_receiver(&impl);
auto a_remote = a_receiver.BindNewEndpointAndPassDedicatedRemote();
EXPECT_FALSE(a_receiver);
EXPECT_FALSE(a_remote);
}
TEST_P(FeatureBindingsTest, SelfOwnedReceiver) {
MessagePipe pipe;
PendingReceiver<mojom::DefaultDenied> pending_receiver(
std::move(pipe.handle0));
auto impl = std::make_unique<DefaultDeniedSelfOwnedImpl>();
auto weak_ref =
MakeSelfOwnedReceiver(std::move(impl), std::move(pending_receiver));
EXPECT_FALSE(weak_ref);
}
TEST_P(FeatureBindingsTest, SelfOwnedAssociatedReceiver) {
PendingAssociatedRemote<mojom::DefaultDenied> pa_remote;
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver =
pa_remote.InitWithNewEndpointAndPassReceiver();
auto impl = std::make_unique<DefaultDeniedSelfOwnedImpl>();
auto weak_ref =
MakeSelfOwnedAssociatedReceiver(std::move(impl), std::move(pa_receiver));
EXPECT_FALSE(weak_ref);
}
TEST_P(FeatureBindingsTest, SharedRemoteWontBindNewPipe) {
SharedRemote<mojom::DefaultDenied> s_remote;
EXPECT_FALSE(s_remote);
PendingReceiver<mojom::DefaultDenied> p_receiver =
s_remote.BindNewPipeAndPassReceiver();
EXPECT_FALSE(s_remote);
EXPECT_FALSE(p_receiver);
}
TEST_P(FeatureBindingsTest, SharedRemoteWontBind) {
PendingRemote<mojom::DefaultDenied> pa_remote;
PendingReceiver<mojom::DefaultDenied> pa_receiver;
{
base::test::ScopedFeatureList feature_list1;
feature_list1.InitFromCommandLine("TestFeatureOff", "");
pa_receiver = pa_remote.InitWithNewPipeAndPassReceiver();
}
EXPECT_TRUE(pa_remote);
SharedRemote<mojom::DefaultDenied> s_remote;
s_remote.Bind(std::move(pa_remote), nullptr);
EXPECT_FALSE(s_remote);
}
TEST_P(FeatureBindingsTest, SharedAssociatedRemoteWontBindNewEndpoint) {
SharedAssociatedRemote<mojom::DefaultDenied> sa_remote;
EXPECT_FALSE(sa_remote);
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver =
sa_remote.BindNewEndpointAndPassReceiver();
EXPECT_FALSE(sa_remote);
EXPECT_FALSE(pa_receiver);
}
TEST_P(FeatureBindingsTest, SharedAssociatedRemoteWontBind) {
PendingAssociatedRemote<mojom::DefaultDenied> pa_remote;
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver;
{
base::test::ScopedFeatureList feature_list1;
feature_list1.InitFromCommandLine("TestFeatureOff", "");
pa_receiver = pa_remote.InitWithNewEndpointAndPassReceiver();
}
EXPECT_TRUE(pa_remote);
SharedAssociatedRemote<mojom::DefaultDenied> sa_remote;
sa_remote.Bind(std::move(pa_remote), nullptr);
EXPECT_FALSE(sa_remote);
}
TEST_P(FeatureBindingsTest, GenericPendingReceivers) {
MessagePipe pipe_a;
ScopedInterfaceEndpointHandle end_a;
ScopedInterfaceEndpointHandle end_b;
ScopedInterfaceEndpointHandle::CreatePairPendingAssociation(&end_a, &end_b);
GenericPendingReceiver gpr_allowed(mojom::DefaultAllowed::Name_,
std::move(pipe_a.handle0));
GenericPendingReceiver gpr_denied(mojom::DefaultDenied::Name_,
std::move(pipe_a.handle1));
GenericPendingAssociatedReceiver gpar_allowed(mojom::DefaultAllowed::Name_,
std::move(end_a));
GenericPendingAssociatedReceiver gpar_denied(mojom::DefaultDenied::Name_,
std::move(end_b));
auto p_allowed = gpr_allowed.As<mojom::DefaultAllowed>();
auto p_denied = gpr_denied.As<mojom::DefaultDenied>();
auto pa_allowed = gpar_allowed.As<mojom::DefaultAllowed>();
auto pa_denied = gpar_denied.As<mojom::DefaultDenied>();
EXPECT_TRUE(p_allowed);
EXPECT_TRUE(pa_allowed);
EXPECT_FALSE(p_denied);
EXPECT_FALSE(pa_denied);
}
TEST_P(FeatureBindingsTest, PassesOptionalInterfacesRemoteDenied) {
if (GetParam() == BindingsTestSerializationMode::kNeverSerialize) {
return;
}
Remote<mojom::PassesInterfaces> remote;
PassesInterfacesImpl impl(remote.BindNewPipeAndPassReceiver());
base::RunLoop run_loop;
MessagePipe pipe;
PendingRemote<mojom::DefaultDenied> denied_pending_remote(
std::move(pipe.handle0), 0);
bool error = false;
SetErrorHandler(base::BindLambdaForTesting([&] {
error = true;
run_loop.Quit();
}));
bool called_empty = false;
remote->PassPendingOptionalRemoteDisabled(
std::move(denied_pending_remote),
base::BindLambdaForTesting([&](bool val) {
called_empty = val;
run_loop.Quit();
}));
run_loop.Run();
ASSERT_FALSE(error);
ASSERT_TRUE(called_empty);
}
TEST_P(FeatureBindingsTest, PassesOptionalInterfacesReceiverDenied) {
if (GetParam() == mojo::BindingsTestSerializationMode::kNeverSerialize) {
return;
}
Remote<mojom::PassesInterfaces> remote;
PassesInterfacesImpl impl(remote.BindNewPipeAndPassReceiver());
base::RunLoop run_loop;
MessagePipe pipe;
PendingReceiver<mojom::DefaultDenied> denied_pending_receiver(
std::move(pipe.handle1));
bool error = false;
SetErrorHandler(base::BindLambdaForTesting([&] {
error = true;
run_loop.Quit();
}));
bool called_empty = false;
remote->PassPendingOptionalReceiverDisabled(
std::move(denied_pending_receiver),
base::BindLambdaForTesting([&](bool val) {
called_empty = val;
run_loop.Quit();
}));
run_loop.Run();
ASSERT_FALSE(error);
ASSERT_TRUE(called_empty);
}
TEST_P(FeatureBindingsTest, RemoteWontBindNewPipeImported) {
Remote<mojom::OtherDenied> remote;
PendingReceiver<mojom::OtherDenied> pending_receiver =
remote.BindNewPipeAndPassReceiver();
EXPECT_FALSE(pending_receiver);
}
TEST_P(FeatureBindingsTest, ReceiverWontBindPendingReceiverImported) {
MessagePipe pipe;
PendingReceiver<mojom::OtherDenied> pending_receiver(std::move(pipe.handle0));
OtherDeniedImpl impl(std::move(pending_receiver));
EXPECT_FALSE(impl.receiver().is_bound());
}
TEST_P(FeatureBindingsTest, ReceiverSetDenied) {
MessagePipe pipe_a;
PendingReceiver<mojom::DefaultDenied> pending_receiver_a(
std::move(pipe_a.handle0));
auto impl = std::make_unique<DefaultDeniedSelfOwnedImpl>();
ReceiverSet<mojom::DefaultDenied> receiver_set;
EXPECT_EQ(receiver_set.Add(impl.get(), std::move(pending_receiver_a)),
std::nullopt);
}
TEST_P(FeatureBindingsTest, RemoteSetDenied) {
PendingRemote<mojom::DefaultDenied> pending_remote;
auto pending_receiver = pending_remote.InitWithNewPipeAndPassReceiver();
RemoteSet<mojom::DefaultDenied> remote_set;
EXPECT_EQ(remote_set.Add(std::move(pending_remote)), std::nullopt);
}
#endif
#if defined(GTEST_HAS_DEATH_TEST) && !BUILDFLAG(IS_ANDROID)
using FeatureBindingsDeathTest = FeatureBindingsTest;
TEST_P(FeatureBindingsDeathTest, MethodsOnRemoteDenied) {
bool called = false;
Remote<mojom::FeaturesOnMethods> remote;
FeaturesOnMethodsImpl impl(remote.BindNewPipeAndPassReceiver());
EXPECT_DEATH(remote->DefaultDenied(
base::BindLambdaForTesting([&](int) { called = true; })),
"");
EXPECT_FALSE(called);
}
TEST_P(FeatureBindingsDeathTest, MethodsOnRemoteDeniedSync) {
int result = 0;
Remote<mojom::FeaturesOnMethods> remote;
FeaturesOnMethodsImpl impl(remote.BindNewPipeAndPassReceiver());
EXPECT_DEATH(remote->DefaultDeniedSync(&result), "");
EXPECT_EQ(result, 0);
}
TEST_P(FeatureBindingsDeathTest, MethodsOnAssociatedRemoteDenied) {
bool called = false;
AssociatedRemote<mojom::FeaturesOnMethods> remote;
FeaturesOnMethodsImpl impl(remote.BindNewEndpointAndPassDedicatedReceiver());
EXPECT_DEATH(remote->DefaultDenied(
base::BindLambdaForTesting([&](int) { called = true; })),
"");
EXPECT_FALSE(called);
}
INSTANTIATE_TEST_SUITE_P(
,
FeatureBindingsDeathTest,
testing::Values(mojo::BindingsTestSerializationMode::kNeverSerialize));
#endif
INSTANTIATE_TEST_SUITE_P(
,
FeatureBindingsTest,
testing::Values(
mojo::BindingsTestSerializationMode::kSerializeBeforeSend,
mojo::BindingsTestSerializationMode::kSerializeBeforeDispatch,
mojo::BindingsTestSerializationMode::kNeverSerialize));
}