// 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/mojo_binder_policy_applier.h"

#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "content/browser/mojo_binder_policy_map_impl.h"
#include "content/public/test/mojo_capability_control_test_interfaces.mojom.h"
#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {

// A test class that implements test interfaces and provides verification
// methods.
class TestReceiverCollector : public mojom::TestInterfaceForDefer,
                              public mojom::TestInterfaceForGrant,
                              public mojom::TestInterfaceForCancel,
                              public mojom::TestInterfaceForUnexpected {
 public:
  TestReceiverCollector() = default;

  ~TestReceiverCollector() override = default;

  // Deletes copy and move operations.
  TestReceiverCollector(const TestReceiverCollector& other) = delete;
  TestReceiverCollector& operator=(const TestReceiverCollector& other) = delete;
  TestReceiverCollector(TestReceiverCollector&&) = delete;
  TestReceiverCollector& operator=(TestReceiverCollector&&) = delete;

  void BindDeferInterface(
      mojo::PendingReceiver<mojom::TestInterfaceForDefer> receiver) {
    ASSERT_FALSE(defer_receiver_.is_bound());
    defer_receiver_.Bind(std::move(receiver));
  }

  void BindGrantInterface(
      mojo::PendingReceiver<mojom::TestInterfaceForGrant> receiver) {
    ASSERT_FALSE(grant_receiver_.is_bound());
    grant_receiver_.Bind(std::move(receiver));
  }

  void BindCancelInterface(
      mojo::PendingReceiver<mojom::TestInterfaceForCancel> receiver) {
    ASSERT_FALSE(cancel_receiver_.is_bound());
    cancel_receiver_.Bind(std::move(receiver));
  }

  void BindUnexpectedInterface(
      mojo::PendingReceiver<mojom::TestInterfaceForUnexpected> receiver) {
    ASSERT_FALSE(unexpected_receiver_.is_bound());
    unexpected_receiver_.Bind(std::move(receiver));
  }

  // mojom::TestInterfaceForDefer implementation.
  void Ping(PingCallback callback) override { NOTREACHED(); }

  // Will be called when MojoBinderPolicyApplier::ApplyPolicyToBinder()
  // handles a kCancel binding request.
  void Cancel(const std::string& interface_name) {
    is_cancelled_ = true;
    cancelled_interface_ = interface_name;
  }

  // Used to check if the cancel_closure of MojoBinderPolicyApplier was
  // executed.
  bool IsCancelled() { return is_cancelled_; }

  const std::string& cancelled_interface() const {
    return cancelled_interface_;
  }

  bool IsDeferReceiverBound() const { return defer_receiver_.is_bound(); }

  bool IsGrantReceiverBound() const { return grant_receiver_.is_bound(); }

  bool IsCancelReceiverBound() const { return cancel_receiver_.is_bound(); }

  bool IsUnexpectedReceiverBound() const {
    return unexpected_receiver_.is_bound();
  }

 private:
  mojo::Receiver<mojom::TestInterfaceForDefer> defer_receiver_{this};
  mojo::Receiver<mojom::TestInterfaceForGrant> grant_receiver_{this};
  mojo::Receiver<mojom::TestInterfaceForCancel> cancel_receiver_{this};
  mojo::Receiver<mojom::TestInterfaceForUnexpected> unexpected_receiver_{this};
  bool is_cancelled_ = false;
  std::string cancelled_interface_;
};

class MojoBinderPolicyApplierTest : public testing::Test,
                                    mojom::MojoContextProvider {
 public:
  MojoBinderPolicyApplierTest() = default;

  // mojom::MojoContextProvider
  void GrantAll() override { policy_applier_.GrantAll(); }

 protected:
  std::vector<base::OnceClosure>& deferred_binders() {
    return policy_applier_.deferred_binders_;
  }

  // Calls MojoBinderPolicyApplier::GrantAll() inside a Mojo message dispatch
  // stack.
  void RunGrantAll() {
    DCHECK(!receiver_.is_bound());
    receiver_.Bind(remote_.BindNewPipeAndPassReceiver());
    remote_->GrantAll();
    remote_.FlushForTesting();
  }

  const MojoBinderPolicyMapImpl policy_map_{
      {{"content.mojom.TestInterfaceForDefer",
        MojoBinderNonAssociatedPolicy::kDefer},
       {"content.mojom.TestInterfaceForGrant",
        MojoBinderNonAssociatedPolicy::kGrant},
       {"content.mojom.TestInterfaceForCancel",
        MojoBinderNonAssociatedPolicy::kCancel},
       {"content.mojom.TestInterfaceForUnexpected",
        MojoBinderNonAssociatedPolicy::kUnexpected}}};
  TestReceiverCollector collector_{};
  MojoBinderPolicyApplier policy_applier_{
      &policy_map_, base::BindOnce(&TestReceiverCollector::Cancel,
                                   base::Unretained(&collector_))};

 private:
  base::test::TaskEnvironment task_environment_;
  mojo::Remote<mojom::MojoContextProvider> remote_;
  mojo::Receiver<mojom::MojoContextProvider> receiver_{this};
};

// Verifies that interfaces whose policies are kGrant can be bound immediately.
TEST_F(MojoBinderPolicyApplierTest, GrantInEnforce) {
  // Initialize Mojo interfaces.
  mojo::Remote<mojom::TestInterfaceForGrant> grant_remote;
  mojo::GenericPendingReceiver grant_receiver(
      grant_remote.BindNewPipeAndPassReceiver());

  // Bind the interface immediately if the policy is kGrant.
  const std::string interface_name = grant_receiver.interface_name().value();
  EXPECT_FALSE(collector_.IsCancelled());
  EXPECT_FALSE(collector_.IsGrantReceiverBound());
  policy_applier_.ApplyPolicyToNonAssociatedBinder(
      interface_name,
      base::BindOnce(&TestReceiverCollector::BindGrantInterface,
                     base::Unretained(&collector_),
                     grant_receiver.As<mojom::TestInterfaceForGrant>()));
  EXPECT_TRUE(collector_.IsGrantReceiverBound());
  EXPECT_FALSE(collector_.IsCancelled());
}

// Verifies that interfaces whose policies are kDefer cannot be bound until
// GrantAll() is called.
TEST_F(MojoBinderPolicyApplierTest, DeferInEnforce) {
  // Initialize Mojo interfaces.
  mojo::Remote<mojom::TestInterfaceForDefer> defer_remote;
  mojo::GenericPendingReceiver defer_receiver(
      defer_remote.BindNewPipeAndPassReceiver());

  // Delay binding the interface until GrantAll() is called.
  const std::string interface_name = defer_receiver.interface_name().value();
  EXPECT_FALSE(collector_.IsCancelled());
  policy_applier_.ApplyPolicyToNonAssociatedBinder(
      interface_name,
      base::BindOnce(&TestReceiverCollector::BindDeferInterface,
                     base::Unretained(&collector_),
                     defer_receiver.As<mojom::TestInterfaceForDefer>()));
  EXPECT_FALSE(collector_.IsDeferReceiverBound());
  EXPECT_EQ(1U, deferred_binders().size());

  RunGrantAll();
  EXPECT_EQ(0U, deferred_binders().size());
  EXPECT_TRUE(collector_.IsDeferReceiverBound());
  EXPECT_FALSE(collector_.IsCancelled());
}

// Verifies that MojoBinderPolicyApplier will run `cancel_closure` when running
// in the kEnforce mode and receiving an interface whose policy is kCancel,
TEST_F(MojoBinderPolicyApplierTest, CancelInEnforce) {
  // Initialize Mojo interfaces.
  mojo::Remote<mojom::TestInterfaceForCancel> cancel_remote;
  mojo::GenericPendingReceiver cancel_receiver(
      cancel_remote.BindNewPipeAndPassReceiver());

  const std::string interface_name = cancel_receiver.interface_name().value();
  EXPECT_FALSE(collector_.IsCancelled());
  EXPECT_FALSE(collector_.IsCancelReceiverBound());
  policy_applier_.ApplyPolicyToNonAssociatedBinder(
      interface_name,
      base::BindOnce(&TestReceiverCollector::BindCancelInterface,
                     base::Unretained(&collector_),
                     cancel_receiver.As<mojom::TestInterfaceForCancel>()));
  EXPECT_TRUE(collector_.IsCancelled());
  EXPECT_EQ(collector_.cancelled_interface(),
            "content.mojom.TestInterfaceForCancel");
  EXPECT_FALSE(collector_.IsCancelReceiverBound());
}

// When MojoBinderPolicyApplier runs in the kPrepareToGrantAll mode, verifies it
// applies kGrant for kGrant interfaces.
TEST_F(MojoBinderPolicyApplierTest, GrantInPrepareToGrantAll) {
  // Initialize Mojo interfaces.
  mojo::Remote<mojom::TestInterfaceForGrant> grant_remote;
  mojo::GenericPendingReceiver grant_receiver(
      grant_remote.BindNewPipeAndPassReceiver());

  policy_applier_.PrepareToGrantAll();
  const std::string grant_interface_name =
      grant_receiver.interface_name().value();
  policy_applier_.ApplyPolicyToNonAssociatedBinder(
      grant_interface_name,
      base::BindOnce(&TestReceiverCollector::BindGrantInterface,
                     base::Unretained(&collector_),
                     grant_receiver.As<mojom::TestInterfaceForGrant>()));
  EXPECT_TRUE(collector_.IsGrantReceiverBound());
}

// When MojoBinderPolicyApplier runs in the kPrepareToGrantAll mode, verifies it
// applies kDefer for kDefer interfaces.
TEST_F(MojoBinderPolicyApplierTest, DeferInPrepareToGrantAll) {
  // Initialize Mojo interfaces.
  mojo::Remote<mojom::TestInterfaceForDefer> defer_remote;
  mojo::GenericPendingReceiver defer_receiver(
      defer_remote.BindNewPipeAndPassReceiver());

  policy_applier_.PrepareToGrantAll();
  const std::string defer_interface_name =
      defer_receiver.interface_name().value();
  policy_applier_.ApplyPolicyToNonAssociatedBinder(
      defer_interface_name,
      base::BindOnce(&TestReceiverCollector::BindDeferInterface,
                     base::Unretained(&collector_),
                     defer_receiver.As<mojom::TestInterfaceForDefer>()));
  EXPECT_FALSE(collector_.IsDeferReceiverBound());
  EXPECT_EQ(1U, deferred_binders().size());

  RunGrantAll();
  EXPECT_TRUE(collector_.IsDeferReceiverBound());
  EXPECT_EQ(0U, deferred_binders().size());
}

// When MojoBinderPolicyApplier runs in the kPrepareToGrantAll mode, verifies it
// applies kGrant rather than kCancel policy when receiving a kCancel interface
// binding request.
TEST_F(MojoBinderPolicyApplierTest, CancelInPrepareToGrantAll) {
  // Initialize Mojo interfaces.
  mojo::Remote<mojom::TestInterfaceForCancel> cancel_remote;
  mojo::GenericPendingReceiver cancel_receiver(
      cancel_remote.BindNewPipeAndPassReceiver());

  policy_applier_.PrepareToGrantAll();
  const std::string cancel_interface_name =
      cancel_receiver.interface_name().value();
  policy_applier_.ApplyPolicyToNonAssociatedBinder(
      cancel_interface_name,
      base::BindOnce(&TestReceiverCollector::BindCancelInterface,
                     base::Unretained(&collector_),
                     cancel_receiver.As<mojom::TestInterfaceForCancel>()));
  EXPECT_FALSE(collector_.IsCancelled());
  EXPECT_TRUE(collector_.IsCancelReceiverBound());
}

TEST_F(MojoBinderPolicyApplierTest, UnexpectedInPrepareToGrantAll) {
  // Initialize Mojo interfaces.
  mojo::Remote<mojom::TestInterfaceForUnexpected> unexpected_remote;
  mojo::GenericPendingReceiver unexpected_receiver(
      unexpected_remote.BindNewPipeAndPassReceiver());

  policy_applier_.PrepareToGrantAll();
  const std::string interface_name =
      unexpected_receiver.interface_name().value();
  policy_applier_.ApplyPolicyToNonAssociatedBinder(
      interface_name,
      base::BindOnce(
          &TestReceiverCollector::BindUnexpectedInterface,
          base::Unretained(&collector_),
          unexpected_receiver.As<mojom::TestInterfaceForUnexpected>()));
  EXPECT_FALSE(collector_.IsCancelled());
  EXPECT_TRUE(collector_.IsUnexpectedReceiverBound());
}

// Verifies that all interfaces are bound immediately if GrantAll() is called,
// regardless of policies.
TEST_F(MojoBinderPolicyApplierTest, BindInterfacesAfterResolving) {
  // Initialize Mojo interfaces.
  mojo::Remote<mojom::TestInterfaceForDefer> defer_remote;
  mojo::GenericPendingReceiver defer_receiver(
      defer_remote.BindNewPipeAndPassReceiver());
  mojo::Remote<mojom::TestInterfaceForGrant> grant_remote;
  mojo::GenericPendingReceiver grant_receiver(
      grant_remote.BindNewPipeAndPassReceiver());
  mojo::Remote<mojom::TestInterfaceForCancel> cancel_remote;
  mojo::GenericPendingReceiver cancel_receiver(
      cancel_remote.BindNewPipeAndPassReceiver());
  mojo::Remote<mojom::TestInterfaceForUnexpected> unexpected_remote;
  mojo::GenericPendingReceiver unexpected_receiver(
      unexpected_remote.BindNewPipeAndPassReceiver());

  RunGrantAll();

  // All interfaces should be bound immediately.
  const std::string defer_interface_name =
      defer_receiver.interface_name().value();
  const std::string grant_interface_name =
      grant_receiver.interface_name().value();
  const std::string cancel_interface_name =
      cancel_receiver.interface_name().value();
  const std::string unexpected_interface_name =
      unexpected_receiver.interface_name().value();
  EXPECT_FALSE(collector_.IsCancelled());
  EXPECT_FALSE(collector_.IsGrantReceiverBound());
  EXPECT_FALSE(collector_.IsDeferReceiverBound());
  EXPECT_FALSE(collector_.IsCancelReceiverBound());
  EXPECT_FALSE(collector_.IsUnexpectedReceiverBound());
  policy_applier_.ApplyPolicyToNonAssociatedBinder(
      defer_interface_name,
      base::BindOnce(&TestReceiverCollector::BindDeferInterface,
                     base::Unretained(&collector_),
                     defer_receiver.As<mojom::TestInterfaceForDefer>()));
  policy_applier_.ApplyPolicyToNonAssociatedBinder(
      grant_interface_name,
      base::BindOnce(&TestReceiverCollector::BindGrantInterface,
                     base::Unretained(&collector_),
                     grant_receiver.As<mojom::TestInterfaceForGrant>()));
  policy_applier_.ApplyPolicyToNonAssociatedBinder(
      cancel_interface_name,
      base::BindOnce(&TestReceiverCollector::BindCancelInterface,
                     base::Unretained(&collector_),
                     cancel_receiver.As<mojom::TestInterfaceForCancel>()));
  policy_applier_.ApplyPolicyToNonAssociatedBinder(
      unexpected_interface_name,
      base::BindOnce(
          &TestReceiverCollector::BindUnexpectedInterface,
          base::Unretained(&collector_),
          unexpected_receiver.As<mojom::TestInterfaceForUnexpected>()));
  EXPECT_TRUE(collector_.IsGrantReceiverBound());
  EXPECT_TRUE(collector_.IsDeferReceiverBound());
  EXPECT_TRUE(collector_.IsCancelReceiverBound());
  EXPECT_TRUE(collector_.IsUnexpectedReceiverBound());
  EXPECT_FALSE(collector_.IsCancelled());
  EXPECT_EQ(0U, deferred_binders().size());
}

// Verifies that DropDeferredBinders() deletes all deferred binders.
TEST_F(MojoBinderPolicyApplierTest, DropDeferredBinders) {
  // Initialize Mojo interfaces.
  mojo::Remote<mojom::TestInterfaceForDefer> defer_remote;
  mojo::GenericPendingReceiver defer_receiver(
      defer_remote.BindNewPipeAndPassReceiver());

  const std::string interface_name = defer_receiver.interface_name().value();
  EXPECT_FALSE(collector_.IsCancelled());
  policy_applier_.ApplyPolicyToNonAssociatedBinder(
      interface_name,
      base::BindOnce(&TestReceiverCollector::BindDeferInterface,
                     base::Unretained(&collector_),
                     defer_receiver.As<mojom::TestInterfaceForDefer>()));
  EXPECT_FALSE(collector_.IsDeferReceiverBound());
  EXPECT_EQ(1U, deferred_binders().size());
  policy_applier_.DropDeferredBinders();
  EXPECT_EQ(0U, deferred_binders().size());
  RunGrantAll();
  EXPECT_FALSE(collector_.IsDeferReceiverBound());
}

}  // namespace content
