// Copyright (c) 2009 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 "build/build_config.h"

#include "ipc/ipc_tests.h"

#if defined(OS_MACOSX)
extern "C" {
#include <sandbox.h>
}
#endif
#include <fcntl.h>
#include <sys/stat.h>

#include "base/eintr_wrapper.h"
#include "base/message_loop.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_message_utils.h"
#include "testing/multiprocess_func_list.h"

#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"

namespace {

const unsigned kNumFDsToSend = 20;
const char* kDevZeroPath = "/dev/zero";

static void VerifyAndCloseDescriptor(int fd, ino_t inode_num) {
  // Check that we can read from the FD.
  char buf;
  ssize_t amt_read = read(fd, &buf, 1);
  ASSERT_EQ(amt_read, 1);
  ASSERT_EQ(buf, 0);  // /dev/zero always reads NUL bytes.

  struct stat st;
  ASSERT_EQ(fstat(fd, &st), 0);

  ASSERT_EQ(close(fd), 0);

  // We compare iNode numbers to check that the file sent over the wire
  // was actually the same physical file as the one we were expecting.
  ASSERT_EQ(inode_num, st.st_ino);
}

class MyChannelDescriptorListener : public IPC::Channel::Listener {
 public:
  MyChannelDescriptorListener(ino_t expected_inode_num)
      : expected_inode_num_(expected_inode_num),
        num_fds_received_(0) {}

  virtual bool OnMessageReceived(const IPC::Message& message) {
    void* iter = NULL;

    ++num_fds_received_;
    base::FileDescriptor descriptor;

    IPC::ParamTraits<base::FileDescriptor>::Read(
            &message, &iter, &descriptor);

    VerifyAndCloseDescriptor(descriptor.fd, expected_inode_num_);
    if (num_fds_received_ == kNumFDsToSend) {
      MessageLoop::current()->Quit();
    }
    return true;
  }

  virtual void OnChannelError() {
    MessageLoop::current()->Quit();
  }

  bool GotExpectedNumberOfDescriptors() {
    return kNumFDsToSend == num_fds_received_;
  }

 private:
  ino_t expected_inode_num_;
  unsigned num_fds_received_;
};

void TestDescriptorServer(IPC::Channel &chan,
                          base::ProcessHandle process_handle) {
  ASSERT_TRUE(process_handle);

  for (unsigned i = 0; i < kNumFDsToSend; ++i) {
    base::FileDescriptor descriptor;
    const int fd = open(kDevZeroPath, O_RDONLY);
    ASSERT_GE(fd, 0);
    descriptor.auto_close = true;
    descriptor.fd = fd;

    IPC::Message* message = new IPC::Message(0, // routing_id
                                             3, // message type
                                             IPC::Message::PRIORITY_NORMAL);
    IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor);
    ASSERT_TRUE(chan.Send(message));
  }

  // Run message loop.
  MessageLoop::current()->Run();

  // Close Channel so client gets its OnChannelError() callback fired.
  chan.Close();

  // Cleanup child process.
  EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000));
}

int TestDescriptorClient(ino_t expected_inode_num) {
  MessageLoopForIO main_message_loop;
  MyChannelDescriptorListener listener(expected_inode_num);

  // Setup IPC channel.
  IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT,
                    &listener);
  CHECK(chan.Connect());

  // Run message loop so IPC Channel can handle message IO.
  MessageLoop::current()->Run();

  // Verify that the message loop was exited due to getting the correct
  // number of descriptors, and not because the channel closing unexpectedly.
  CHECK(listener.GotExpectedNumberOfDescriptors());

  return 0;
}

}  // namespace

// ---------------------------------------------------------------------------
#if defined(OS_MACOSX)
// TODO(port): Make this test cross-platform.
MULTIPROCESS_TEST_MAIN(RunTestDescriptorClientSandboxed) {
  struct stat st;
  const int fd = open(kDevZeroPath, O_RDONLY);
  fstat(fd, &st);
  if (HANDLE_EINTR(close(fd)) < 0) {
    return -1;
  }

  // Enable the Sandbox.
  char* error_buff = NULL;
  int error = sandbox_init(kSBXProfilePureComputation, SANDBOX_NAMED,
                           &error_buff);
  bool success = (error == 0 && error_buff == NULL);
  if (!success) {
    return -1;
  }

  sandbox_free_error(error_buff);

  // Make sure Sandbox is really enabled.
  if (open(kDevZeroPath, O_RDONLY) != -1) {
    LOG(ERROR) << "Sandbox wasn't properly enabled";
    return -1;
  }

  // See if we can receive a file descriptor.
  return TestDescriptorClient(st.st_ino);
}

// Test that FDs are correctly sent to a sandboxed process.
TEST_F(IPCChannelTest, DescriptorTestSandboxed) {
    // Setup IPC channel.
  MyChannelDescriptorListener listener(-1);

  IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
                    &listener);
  ASSERT_TRUE(chan.Connect());

  base::ProcessHandle process_handle = SpawnChild(
      TEST_DESCRIPTOR_CLIENT_SANDBOXED,
      &chan);
  TestDescriptorServer(chan, process_handle);
}
#endif  // defined(OS_MACOSX)

MULTIPROCESS_TEST_MAIN(RunTestDescriptorClient) {
  struct stat st;
  const int fd = open(kDevZeroPath, O_RDONLY);
  fstat(fd, &st);
  EXPECT_GE(HANDLE_EINTR(close(fd)), 0);

  return TestDescriptorClient(st.st_ino);
}

TEST_F(IPCChannelTest, DescriptorTest) {
    // Setup IPC channel.
  MyChannelDescriptorListener listener(-1);

  IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
                    &listener);
  ASSERT_TRUE(chan.Connect());

  base::ProcessHandle process_handle = SpawnChild(TEST_DESCRIPTOR_CLIENT,
                                                  &chan);
  TestDescriptorServer(chan, process_handle);
}

#endif  // defined(OS_POSIX)
