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

#include "base/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/test/test_mojo_binder_policy_applier_unittest.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", MojoBinderPolicy::kDefer},
       {"content.mojom.TestInterfaceForGrant", MojoBinderPolicy::kGrant},
       {"content.mojom.TestInterfaceForCancel", MojoBinderPolicy::kCancel},
       {"content.mojom.TestInterfaceForUnexpected",
        MojoBinderPolicy::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_.ApplyPolicyToBinder(
      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_.ApplyPolicyToBinder(
      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_.ApplyPolicyToBinder(
      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_.ApplyPolicyToBinder(
      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_.ApplyPolicyToBinder(
      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_.ApplyPolicyToBinder(
      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_.ApplyPolicyToBinder(
      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_.ApplyPolicyToBinder(
      defer_interface_name,
      base::BindOnce(&TestReceiverCollector::BindDeferInterface,
                     base::Unretained(&collector_),
                     defer_receiver.As<mojom::TestInterfaceForDefer>()));
  policy_applier_.ApplyPolicyToBinder(
      grant_interface_name,
      base::BindOnce(&TestReceiverCollector::BindGrantInterface,
                     base::Unretained(&collector_),
                     grant_receiver.As<mojom::TestInterfaceForGrant>()));
  policy_applier_.ApplyPolicyToBinder(
      cancel_interface_name,
      base::BindOnce(&TestReceiverCollector::BindCancelInterface,
                     base::Unretained(&collector_),
                     cancel_receiver.As<mojom::TestInterfaceForCancel>()));
  policy_applier_.ApplyPolicyToBinder(
      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_.ApplyPolicyToBinder(
      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
