| Index: ipc/attachment_broker_privileged_mac_unittest.cc
 | 
| diff --git a/ipc/attachment_broker_privileged_mac_unittest.cc b/ipc/attachment_broker_privileged_mac_unittest.cc
 | 
| deleted file mode 100644
 | 
| index 330db03af9618d2842b90ed7b5ef1b11d64f8a80..0000000000000000000000000000000000000000
 | 
| --- a/ipc/attachment_broker_privileged_mac_unittest.cc
 | 
| +++ /dev/null
 | 
| @@ -1,428 +0,0 @@
 | 
| -// Copyright 2015 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 "ipc/attachment_broker_privileged_mac.h"
 | 
| -
 | 
| -#include <mach/mach.h>
 | 
| -#include <mach/mach_vm.h>
 | 
| -#include <stddef.h>
 | 
| -#include <stdint.h>
 | 
| -
 | 
| -#include <map>
 | 
| -#include <memory>
 | 
| -
 | 
| -#include "base/command_line.h"
 | 
| -#include "base/mac/mac_util.h"
 | 
| -#include "base/mac/mach_logging.h"
 | 
| -#include "base/mac/mach_port_util.h"
 | 
| -#include "base/mac/scoped_mach_port.h"
 | 
| -#include "base/macros.h"
 | 
| -#include "base/memory/shared_memory.h"
 | 
| -#include "base/process/port_provider_mac.h"
 | 
| -#include "base/process/process_handle.h"
 | 
| -#include "base/sys_info.h"
 | 
| -#include "base/test/multiprocess_test.h"
 | 
| -#include "base/test/test_timeouts.h"
 | 
| -#include "ipc/test_util_mac.h"
 | 
| -#include "testing/multiprocess_func_list.h"
 | 
| -
 | 
| -namespace IPC {
 | 
| -
 | 
| -namespace {
 | 
| -
 | 
| -static const std::string g_service_switch_name = "service_name";
 | 
| -
 | 
| -// Sends a uint32_t to a mach port.
 | 
| -void SendUInt32(mach_port_t port, uint32_t message) {
 | 
| -  int message_size = sizeof(uint32_t);
 | 
| -  int total_size = message_size + sizeof(mach_msg_header_t);
 | 
| -  void* buffer = malloc(total_size);
 | 
| -  mach_msg_header_t* header = (mach_msg_header_t*)buffer;
 | 
| -  header->msgh_remote_port = port;
 | 
| -  header->msgh_local_port = MACH_PORT_NULL;
 | 
| -  header->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
 | 
| -  header->msgh_reserved = 0;
 | 
| -  header->msgh_id = 0;
 | 
| -  header->msgh_size = total_size;
 | 
| -  memcpy(static_cast<char*>(buffer) + sizeof(mach_msg_header_t), &message,
 | 
| -         message_size);
 | 
| -
 | 
| -  kern_return_t kr;
 | 
| -  kr = mach_msg(static_cast<mach_msg_header_t*>(buffer), MACH_SEND_MSG,
 | 
| -                total_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
 | 
| -                MACH_PORT_NULL);
 | 
| -  MACH_CHECK(kr == KERN_SUCCESS, kr) << "SendUInt32";
 | 
| -  free(buffer);
 | 
| -}
 | 
| -
 | 
| -// Receives a uint32_t from a mach port.
 | 
| -uint32_t ReceiveUInt32(mach_port_t listening_port) {
 | 
| -  int message_size = sizeof(uint32_t);
 | 
| -  int total_size =
 | 
| -      message_size + sizeof(mach_msg_header_t) + sizeof(mach_msg_trailer_t);
 | 
| -  int options = MACH_RCV_MSG;
 | 
| -  void* buffer = malloc(total_size);
 | 
| -
 | 
| -  int kr =
 | 
| -      mach_msg(static_cast<mach_msg_header_t*>(buffer), options, 0, total_size,
 | 
| -               listening_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
 | 
| -  MACH_CHECK(kr == KERN_SUCCESS, kr) << "ReceiveUInt32";
 | 
| -
 | 
| -  uint32_t response;
 | 
| -  memcpy(&response, static_cast<char*>(buffer) + sizeof(mach_msg_header_t),
 | 
| -         message_size);
 | 
| -
 | 
| -  free(buffer);
 | 
| -  return response;
 | 
| -}
 | 
| -
 | 
| -// Sets up the mach communication ports with the server. Returns a port to which
 | 
| -// the server will send mach objects.
 | 
| -// |original_name_count| is an output variable that describes the number of
 | 
| -// active names in this task before the task port is shared with the server.
 | 
| -base::mac::ScopedMachReceiveRight CommonChildProcessSetUp(
 | 
| -    mach_msg_type_number_t* original_name_count) {
 | 
| -  base::CommandLine cmd_line = *base::CommandLine::ForCurrentProcess();
 | 
| -  std::string service_name =
 | 
| -      cmd_line.GetSwitchValueASCII(g_service_switch_name);
 | 
| -  base::mac::ScopedMachSendRight server_port(
 | 
| -      LookupServer(service_name.c_str()));
 | 
| -  base::mac::ScopedMachReceiveRight client_port(MakeReceivingPort());
 | 
| -
 | 
| -  // |server_port| is a newly allocated right which will be deallocated once
 | 
| -  // this method returns.
 | 
| -  *original_name_count = GetActiveNameCount() - 1;
 | 
| -
 | 
| -  // Send the port that this process is listening on to the server.
 | 
| -  SendMachPort(server_port.get(), client_port.get(), MACH_MSG_TYPE_MAKE_SEND);
 | 
| -
 | 
| -  // Send the task port for this process.
 | 
| -  SendMachPort(server_port.get(), mach_task_self(), MACH_MSG_TYPE_COPY_SEND);
 | 
| -  return client_port;
 | 
| -}
 | 
| -
 | 
| -// Creates a new shared memory region populated with 'a'.
 | 
| -std::unique_ptr<base::SharedMemory> CreateAndPopulateSharedMemoryHandle(
 | 
| -    size_t size) {
 | 
| -  base::SharedMemoryHandle shm(size);
 | 
| -  std::unique_ptr<base::SharedMemory> shared_memory(
 | 
| -      new base::SharedMemory(shm, false));
 | 
| -  shared_memory->Map(size);
 | 
| -  memset(shared_memory->memory(), 'a', size);
 | 
| -  return shared_memory;
 | 
| -}
 | 
| -
 | 
| -// Create a shared memory region from a memory object. The returned object takes
 | 
| -// ownership of |memory_object|.
 | 
| -std::unique_ptr<base::SharedMemory> MapMemoryObject(mach_port_t memory_object,
 | 
| -                                                    size_t size) {
 | 
| -  base::SharedMemoryHandle shm(memory_object, size, base::GetCurrentProcId());
 | 
| -  std::unique_ptr<base::SharedMemory> shared_memory(
 | 
| -      new base::SharedMemory(shm, false));
 | 
| -  shared_memory->Map(size);
 | 
| -  return shared_memory;
 | 
| -}
 | 
| -
 | 
| -class MockPortProvider : public base::PortProvider {
 | 
| - public:
 | 
| -  MockPortProvider() {}
 | 
| -  ~MockPortProvider() override {}
 | 
| -  mach_port_t TaskForPid(base::ProcessHandle process) const override {
 | 
| -    return MACH_PORT_NULL;
 | 
| -  }
 | 
| -};
 | 
| -
 | 
| -}  // namespace
 | 
| -
 | 
| -class AttachmentBrokerPrivilegedMacMultiProcessTest
 | 
| -    : public base::MultiProcessTest {
 | 
| - public:
 | 
| -  AttachmentBrokerPrivilegedMacMultiProcessTest() {}
 | 
| -
 | 
| -  base::CommandLine MakeCmdLine(const std::string& procname) override {
 | 
| -    base::CommandLine command_line = MultiProcessTest::MakeCmdLine(procname);
 | 
| -    // Pass the service name to the child process.
 | 
| -    command_line.AppendSwitchASCII(g_service_switch_name, service_name_);
 | 
| -    return command_line;
 | 
| -  }
 | 
| -
 | 
| -  void SetUpChild(const std::string& name) {
 | 
| -    // Make a random service name so that this test doesn't conflict with other
 | 
| -    // similar tests.
 | 
| -    service_name_ = CreateRandomServiceName();
 | 
| -    server_port_.reset(BecomeMachServer(service_name_.c_str()).release());
 | 
| -    child_process_ = SpawnChild(name);
 | 
| -    client_port_.reset(ReceiveMachPort(server_port_.get()).release());
 | 
| -    client_task_port_.reset(ReceiveMachPort(server_port_.get()).release());
 | 
| -  }
 | 
| -
 | 
| -  static const int s_memory_size = 99999;
 | 
| -
 | 
| - protected:
 | 
| -  std::string service_name_;
 | 
| -
 | 
| -  // A port on which the main process listens for mach messages from the child
 | 
| -  // process.
 | 
| -  base::mac::ScopedMachReceiveRight server_port_;
 | 
| -
 | 
| -  // A port on which the child process listens for mach messages from the main
 | 
| -  // process.
 | 
| -  base::mac::ScopedMachSendRight client_port_;
 | 
| -
 | 
| -  // Child process's task port.
 | 
| -  base::mac::ScopedMachSendRight client_task_port_;
 | 
| -
 | 
| -  // Dummy port provider.
 | 
| -  MockPortProvider port_provider_;
 | 
| -
 | 
| -  base::Process child_process_;
 | 
| -  DISALLOW_COPY_AND_ASSIGN(AttachmentBrokerPrivilegedMacMultiProcessTest);
 | 
| -};
 | 
| -
 | 
| -// The attachment broker inserts a right for a memory object into the
 | 
| -// destination task.
 | 
| -TEST_F(AttachmentBrokerPrivilegedMacMultiProcessTest, InsertRight) {
 | 
| -  SetUpChild("InsertRightClient");
 | 
| -  mach_msg_type_number_t original_name_count = GetActiveNameCount();
 | 
| -  IPC::AttachmentBrokerPrivilegedMac broker(&port_provider_);
 | 
| -
 | 
| -  // Create some shared memory.
 | 
| -  std::unique_ptr<base::SharedMemory> shared_memory =
 | 
| -      CreateAndPopulateSharedMemoryHandle(s_memory_size);
 | 
| -  ASSERT_TRUE(shared_memory->handle().IsValid());
 | 
| -
 | 
| -  // Insert the memory object into the destination task, via an intermediate
 | 
| -  // port.
 | 
| -  IncrementMachRefCount(shared_memory->handle().GetMemoryObject(),
 | 
| -                        MACH_PORT_RIGHT_SEND);
 | 
| -  mach_port_name_t inserted_memory_object = base::CreateIntermediateMachPort(
 | 
| -      client_task_port_.get(),
 | 
| -      base::mac::ScopedMachSendRight(shared_memory->handle().GetMemoryObject()),
 | 
| -      nullptr);
 | 
| -  EXPECT_NE(inserted_memory_object,
 | 
| -            static_cast<mach_port_name_t>(MACH_PORT_NULL));
 | 
| -  SendUInt32(client_port_.get(), inserted_memory_object);
 | 
| -
 | 
| -  // Check that no names have been leaked.
 | 
| -  shared_memory.reset();
 | 
| -  EXPECT_EQ(original_name_count, GetActiveNameCount());
 | 
| -
 | 
| -  int rv = -1;
 | 
| -  ASSERT_TRUE(child_process_.WaitForExitWithTimeout(
 | 
| -      TestTimeouts::action_timeout(), &rv));
 | 
| -  EXPECT_EQ(0, rv);
 | 
| -}
 | 
| -
 | 
| -MULTIPROCESS_TEST_MAIN(InsertRightClient) {
 | 
| -  mach_msg_type_number_t original_name_count = 0;
 | 
| -  base::mac::ScopedMachReceiveRight client_port(
 | 
| -      CommonChildProcessSetUp(&original_name_count).release());
 | 
| -  base::mac::ScopedMachReceiveRight inserted_port(
 | 
| -      ReceiveUInt32(client_port.get()));
 | 
| -  base::mac::ScopedMachSendRight memory_object(
 | 
| -      ReceiveMachPort(inserted_port.get()));
 | 
| -  inserted_port.reset();
 | 
| -
 | 
| -  // The server should have inserted a right into this process.
 | 
| -  EXPECT_EQ(original_name_count + 1, GetActiveNameCount());
 | 
| -
 | 
| -  // Map the memory object and check its contents.
 | 
| -  std::unique_ptr<base::SharedMemory> shared_memory(MapMemoryObject(
 | 
| -      memory_object.release(),
 | 
| -      AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size));
 | 
| -  const char* start = static_cast<const char*>(shared_memory->memory());
 | 
| -  for (int i = 0;
 | 
| -       i < AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size; ++i) {
 | 
| -    DCHECK_EQ(start[i], 'a');
 | 
| -  }
 | 
| -
 | 
| -  // Check that no names have been leaked.
 | 
| -  shared_memory.reset();
 | 
| -  EXPECT_EQ(original_name_count, GetActiveNameCount());
 | 
| -
 | 
| -  return 0;
 | 
| -}
 | 
| -
 | 
| -// The attachment broker inserts the right for a memory object into the
 | 
| -// destination task twice.
 | 
| -TEST_F(AttachmentBrokerPrivilegedMacMultiProcessTest, InsertSameRightTwice) {
 | 
| -  SetUpChild("InsertSameRightTwiceClient");
 | 
| -  mach_msg_type_number_t original_name_count = GetActiveNameCount();
 | 
| -  IPC::AttachmentBrokerPrivilegedMac broker(&port_provider_);
 | 
| -
 | 
| -  // Create some shared memory.
 | 
| -  std::unique_ptr<base::SharedMemory> shared_memory =
 | 
| -      CreateAndPopulateSharedMemoryHandle(s_memory_size);
 | 
| -  ASSERT_TRUE(shared_memory->handle().IsValid());
 | 
| -
 | 
| -  // Insert the memory object into the destination task, via an intermediate
 | 
| -  // port, twice.
 | 
| -  for (int i = 0; i < 2; ++i) {
 | 
| -    IncrementMachRefCount(shared_memory->handle().GetMemoryObject(),
 | 
| -                          MACH_PORT_RIGHT_SEND);
 | 
| -    mach_port_name_t inserted_memory_object = base::CreateIntermediateMachPort(
 | 
| -        client_task_port_.get(),
 | 
| -        base::mac::ScopedMachSendRight(
 | 
| -            shared_memory->handle().GetMemoryObject()),
 | 
| -        nullptr);
 | 
| -    EXPECT_NE(inserted_memory_object,
 | 
| -              static_cast<mach_port_name_t>(MACH_PORT_NULL));
 | 
| -    SendUInt32(client_port_.get(), inserted_memory_object);
 | 
| -  }
 | 
| -
 | 
| -  // Check that no names have been leaked.
 | 
| -  shared_memory.reset();
 | 
| -  EXPECT_EQ(original_name_count, GetActiveNameCount());
 | 
| -
 | 
| -  int rv = -1;
 | 
| -  ASSERT_TRUE(child_process_.WaitForExitWithTimeout(
 | 
| -      TestTimeouts::action_timeout(), &rv));
 | 
| -  EXPECT_EQ(0, rv);
 | 
| -}
 | 
| -
 | 
| -MULTIPROCESS_TEST_MAIN(InsertSameRightTwiceClient) {
 | 
| -  mach_msg_type_number_t original_name_count = 0;
 | 
| -  base::mac::ScopedMachReceiveRight client_port(
 | 
| -      CommonChildProcessSetUp(&original_name_count).release());
 | 
| -
 | 
| -  // Receive two memory objects.
 | 
| -  base::mac::ScopedMachReceiveRight inserted_port(
 | 
| -      ReceiveUInt32(client_port.get()));
 | 
| -  base::mac::ScopedMachReceiveRight inserted_port2(
 | 
| -      ReceiveUInt32(client_port.get()));
 | 
| -  base::mac::ScopedMachSendRight memory_object(
 | 
| -      ReceiveMachPort(inserted_port.get()));
 | 
| -  base::mac::ScopedMachSendRight memory_object2(
 | 
| -      ReceiveMachPort(inserted_port2.get()));
 | 
| -  inserted_port.reset();
 | 
| -  inserted_port2.reset();
 | 
| -
 | 
| -  // Both rights are for the same Mach port, so only one new name should appear.
 | 
| -  EXPECT_EQ(original_name_count + 1, GetActiveNameCount());
 | 
| -
 | 
| -  // Map both memory objects and check their contents.
 | 
| -  std::unique_ptr<base::SharedMemory> shared_memory(MapMemoryObject(
 | 
| -      memory_object.release(),
 | 
| -      AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size));
 | 
| -  char* start = static_cast<char*>(shared_memory->memory());
 | 
| -  for (int i = 0;
 | 
| -       i < AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size; ++i) {
 | 
| -    DCHECK_EQ(start[i], 'a');
 | 
| -  }
 | 
| -
 | 
| -  std::unique_ptr<base::SharedMemory> shared_memory2(MapMemoryObject(
 | 
| -      memory_object2.release(),
 | 
| -      AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size));
 | 
| -  char* start2 = static_cast<char*>(shared_memory2->memory());
 | 
| -  for (int i = 0;
 | 
| -       i < AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size; ++i) {
 | 
| -    DCHECK_EQ(start2[i], 'a');
 | 
| -  }
 | 
| -
 | 
| -  // Check that the contents of both regions are shared.
 | 
| -  start[0] = 'b';
 | 
| -  DCHECK_EQ(start2[0], 'b');
 | 
| -
 | 
| -  // After releasing one shared memory region, the name count shouldn't change,
 | 
| -  // since another reference exists.
 | 
| -  shared_memory.reset();
 | 
| -  EXPECT_EQ(original_name_count + 1, GetActiveNameCount());
 | 
| -
 | 
| -  // After releasing the second shared memory region, the name count should be
 | 
| -  // as if no names were ever inserted
 | 
| -  shared_memory2.reset();
 | 
| -  EXPECT_EQ(original_name_count, GetActiveNameCount());
 | 
| -
 | 
| -  return 0;
 | 
| -}
 | 
| -
 | 
| -// The attachment broker inserts the rights for two memory objects into the
 | 
| -// destination task.
 | 
| -TEST_F(AttachmentBrokerPrivilegedMacMultiProcessTest, InsertTwoRights) {
 | 
| -  SetUpChild("InsertTwoRightsClient");
 | 
| -  mach_msg_type_number_t original_name_count = GetActiveNameCount();
 | 
| -  IPC::AttachmentBrokerPrivilegedMac broker(&port_provider_);
 | 
| -
 | 
| -  for (int i = 0; i < 2; ++i) {
 | 
| -    // Create some shared memory.
 | 
| -    std::unique_ptr<base::SharedMemory> shared_memory =
 | 
| -        CreateAndPopulateSharedMemoryHandle(s_memory_size);
 | 
| -    ASSERT_TRUE(shared_memory->handle().IsValid());
 | 
| -
 | 
| -    // Insert the memory object into the destination task, via an intermediate
 | 
| -    // port.
 | 
| -    IncrementMachRefCount(shared_memory->handle().GetMemoryObject(),
 | 
| -                          MACH_PORT_RIGHT_SEND);
 | 
| -    mach_port_name_t inserted_memory_object = base::CreateIntermediateMachPort(
 | 
| -        client_task_port_.get(),
 | 
| -        base::mac::ScopedMachSendRight(
 | 
| -            shared_memory->handle().GetMemoryObject()),
 | 
| -        nullptr);
 | 
| -    EXPECT_NE(inserted_memory_object,
 | 
| -              static_cast<mach_port_name_t>(MACH_PORT_NULL));
 | 
| -    SendUInt32(client_port_.get(), inserted_memory_object);
 | 
| -  }
 | 
| -
 | 
| -  // Check that no names have been leaked.
 | 
| -  EXPECT_EQ(original_name_count, GetActiveNameCount());
 | 
| -
 | 
| -  int rv = -1;
 | 
| -  ASSERT_TRUE(child_process_.WaitForExitWithTimeout(
 | 
| -      TestTimeouts::action_timeout(), &rv));
 | 
| -  EXPECT_EQ(0, rv);
 | 
| -}
 | 
| -
 | 
| -MULTIPROCESS_TEST_MAIN(InsertTwoRightsClient) {
 | 
| -  mach_msg_type_number_t original_name_count = 0;
 | 
| -  base::mac::ScopedMachReceiveRight client_port(
 | 
| -      CommonChildProcessSetUp(&original_name_count).release());
 | 
| -
 | 
| -  // Receive two memory objects.
 | 
| -  base::mac::ScopedMachReceiveRight inserted_port(
 | 
| -      ReceiveUInt32(client_port.get()));
 | 
| -  base::mac::ScopedMachReceiveRight inserted_port2(
 | 
| -      ReceiveUInt32(client_port.get()));
 | 
| -  base::mac::ScopedMachSendRight memory_object(
 | 
| -      ReceiveMachPort(inserted_port.get()));
 | 
| -  base::mac::ScopedMachSendRight memory_object2(
 | 
| -      ReceiveMachPort(inserted_port2.get()));
 | 
| -  inserted_port.reset();
 | 
| -  inserted_port2.reset();
 | 
| -
 | 
| -  // There should be two new names to reflect the two new shared memory regions.
 | 
| -  EXPECT_EQ(original_name_count + 2, GetActiveNameCount());
 | 
| -
 | 
| -  // Map both memory objects and check their contents.
 | 
| -  std::unique_ptr<base::SharedMemory> shared_memory(MapMemoryObject(
 | 
| -      memory_object.release(),
 | 
| -      AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size));
 | 
| -  char* start = static_cast<char*>(shared_memory->memory());
 | 
| -  for (int i = 0;
 | 
| -       i < AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size; ++i) {
 | 
| -    DCHECK_EQ(start[i], 'a');
 | 
| -  }
 | 
| -
 | 
| -  std::unique_ptr<base::SharedMemory> shared_memory2(MapMemoryObject(
 | 
| -      memory_object2.release(),
 | 
| -      AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size));
 | 
| -  char* start2 = static_cast<char*>(shared_memory2->memory());
 | 
| -  for (int i = 0;
 | 
| -       i < AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size; ++i) {
 | 
| -    DCHECK_EQ(start2[i], 'a');
 | 
| -  }
 | 
| -
 | 
| -  // Check that the contents of both regions are not shared.
 | 
| -  start[0] = 'b';
 | 
| -  DCHECK_EQ(start2[0], 'a');
 | 
| -
 | 
| -  // After releasing one shared memory region, the name count should decrement.
 | 
| -  shared_memory.reset();
 | 
| -  EXPECT_EQ(original_name_count + 1, GetActiveNameCount());
 | 
| -  shared_memory2.reset();
 | 
| -  EXPECT_EQ(original_name_count, GetActiveNameCount());
 | 
| -
 | 
| -  return 0;
 | 
| -}
 | 
| -
 | 
| -}  //  namespace IPC
 | 
| 
 |