| Index: base/memory/shared_memory_mac_unittest.cc
 | 
| diff --git a/base/memory/shared_memory_mac_unittest.cc b/base/memory/shared_memory_mac_unittest.cc
 | 
| index e4c5e8b19b8d0dd6b426a77c895b16324ee9b5e1..c29302f490b4bf5d5e8d151a7a603a375d9d8192 100644
 | 
| --- a/base/memory/shared_memory_mac_unittest.cc
 | 
| +++ b/base/memory/shared_memory_mac_unittest.cc
 | 
| @@ -7,6 +7,7 @@
 | 
|  #include <servers/bootstrap.h>
 | 
|  
 | 
|  #include "base/command_line.h"
 | 
| +#include "base/mac/mac_util.h"
 | 
|  #include "base/mac/mach_logging.h"
 | 
|  #include "base/mac/scoped_mach_port.h"
 | 
|  #include "base/memory/shared_memory.h"
 | 
| @@ -22,6 +23,46 @@ namespace base {
 | 
|  
 | 
|  namespace {
 | 
|  
 | 
| +// Gets the current and maximum protection levels of the memory region.
 | 
| +// Returns whether the operation was successful.
 | 
| +// |current| and |max| are output variables only populated on success.
 | 
| +bool GetProtections(void* address, size_t size, int* current, int* max) {
 | 
| +  vm_region_info_t region_info;
 | 
| +  mach_vm_address_t mem_address = reinterpret_cast<mach_vm_address_t>(address);
 | 
| +  mach_vm_size_t mem_size = size;
 | 
| +  vm_region_basic_info_64 basic_info;
 | 
| +
 | 
| +  region_info = reinterpret_cast<vm_region_recurse_info_t>(&basic_info);
 | 
| +  vm_region_flavor_t flavor = VM_REGION_BASIC_INFO_64;
 | 
| +  memory_object_name_t memory_object;
 | 
| +  mach_port_t ctype;
 | 
| +
 | 
| +  kern_return_t kr =
 | 
| +      mach_vm_region(mach_task_self(), &mem_address, &mem_size, flavor,
 | 
| +                     region_info, &memory_object, &ctype);
 | 
| +  if (kr != KERN_SUCCESS) {
 | 
| +    LOG(ERROR) << "Failed to get region info.";
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
| +  *current = basic_info.protection;
 | 
| +  *max = basic_info.max_protection;
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +// Creates a new SharedMemory with the given |size|, filled with 'a'.
 | 
| +scoped_ptr<SharedMemory> CreateSharedMemory(int size) {
 | 
| +  SharedMemoryHandle shm(size);
 | 
| +  if (!shm.IsValid()) {
 | 
| +    LOG(ERROR) << "Failed to make SharedMemoryHandle";
 | 
| +    return nullptr;
 | 
| +  }
 | 
| +  scoped_ptr<SharedMemory> shared_memory(new SharedMemory(shm, false));
 | 
| +  shared_memory->Map(size);
 | 
| +  memset(shared_memory->memory(), 'a', size);
 | 
| +  return shared_memory;
 | 
| +}
 | 
| +
 | 
|  static const std::string g_service_switch_name = "service_name";
 | 
|  
 | 
|  // Structs used to pass a mach port from client to server.
 | 
| @@ -184,17 +225,18 @@ class SharedMemoryMacMultiProcessTest : public MultiProcessTest {
 | 
|  // Tests that content written to shared memory in the server process can be read
 | 
|  // by the child process.
 | 
|  TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemory) {
 | 
| +  // Mach-based SharedMemory isn't support on OSX 10.6.
 | 
| +  if (mac::IsOSSnowLeopard())
 | 
| +    return;
 | 
| +
 | 
|    SetUpChild("MachBasedSharedMemoryClient");
 | 
|  
 | 
| -  SharedMemoryHandle shm(s_memory_size);
 | 
| -  ASSERT_TRUE(shm.IsValid());
 | 
| -  SharedMemory shared_memory(shm, false);
 | 
| -  shared_memory.Map(s_memory_size);
 | 
| -  memset(shared_memory.memory(), 'a', s_memory_size);
 | 
| +  scoped_ptr<SharedMemory> shared_memory(
 | 
| +      CreateSharedMemory(s_memory_size).Pass());
 | 
|  
 | 
|    // Send the underlying memory object to the client process.
 | 
| -  SendMachPort(
 | 
| -      client_port_.get(), shm.GetMemoryObject(), MACH_MSG_TYPE_COPY_SEND);
 | 
| +  SendMachPort(client_port_.get(), shared_memory->handle().GetMemoryObject(),
 | 
| +               MACH_MSG_TYPE_COPY_SEND);
 | 
|    int rv = -1;
 | 
|    ASSERT_TRUE(child_process_.WaitForExitWithTimeout(
 | 
|        TestTimeouts::action_timeout(), &rv));
 | 
| @@ -219,6 +261,10 @@ MULTIPROCESS_TEST_MAIN(MachBasedSharedMemoryClient) {
 | 
|  
 | 
|  // Tests that mapping shared memory with an offset works correctly.
 | 
|  TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemoryWithOffset) {
 | 
| +  // Mach-based SharedMemory isn't support on OSX 10.6.
 | 
| +  if (mac::IsOSSnowLeopard())
 | 
| +    return;
 | 
| +
 | 
|    SetUpChild("MachBasedSharedMemoryWithOffsetClient");
 | 
|  
 | 
|    SharedMemoryHandle shm(s_memory_size);
 | 
| @@ -264,6 +310,10 @@ MULTIPROCESS_TEST_MAIN(MachBasedSharedMemoryWithOffsetClient) {
 | 
|  // Tests that duplication and closing has the right effect on Mach reference
 | 
|  // counts.
 | 
|  TEST_F(SharedMemoryMacMultiProcessTest, MachDuplicateAndClose) {
 | 
| +  // Mach-based SharedMemory isn't support on OSX 10.6.
 | 
| +  if (mac::IsOSSnowLeopard())
 | 
| +    return;
 | 
| +
 | 
|    mach_msg_type_number_t active_name_count = GetActiveNameCount();
 | 
|  
 | 
|    // Making a new SharedMemoryHandle increments the name count.
 | 
| @@ -291,6 +341,10 @@ TEST_F(SharedMemoryMacMultiProcessTest, MachDuplicateAndClose) {
 | 
|  // ownership, and that destroying the SharedMemory closes the SharedMemoryHandle
 | 
|  // as well.
 | 
|  TEST_F(SharedMemoryMacMultiProcessTest, MachSharedMemoryTakesOwnership) {
 | 
| +  // Mach-based SharedMemory isn't support on OSX 10.6.
 | 
| +  if (mac::IsOSSnowLeopard())
 | 
| +    return;
 | 
| +
 | 
|    mach_msg_type_number_t active_name_count = GetActiveNameCount();
 | 
|  
 | 
|    // Making a new SharedMemoryHandle increments the name count.
 | 
| @@ -310,17 +364,113 @@ TEST_F(SharedMemoryMacMultiProcessTest, MachSharedMemoryTakesOwnership) {
 | 
|  
 | 
|  // Tests that the read-only flag works.
 | 
|  TEST_F(SharedMemoryMacMultiProcessTest, MachReadOnly) {
 | 
| -  SharedMemoryHandle shm(s_memory_size);
 | 
| -  ASSERT_TRUE(shm.IsValid());
 | 
| -  SharedMemory shared_memory(shm, false);
 | 
| -  shared_memory.Map(s_memory_size);
 | 
| -  memset(shared_memory.memory(), 'a', s_memory_size);
 | 
| +  // Mach-based SharedMemory isn't support on OSX 10.6.
 | 
| +  if (mac::IsOSSnowLeopard())
 | 
| +    return;
 | 
| +
 | 
| +  scoped_ptr<SharedMemory> shared_memory(
 | 
| +      CreateSharedMemory(s_memory_size).Pass());
 | 
|  
 | 
| -  SharedMemoryHandle shm2 = shm.Duplicate();
 | 
| +  SharedMemoryHandle shm2 = shared_memory->handle().Duplicate();
 | 
|    ASSERT_TRUE(shm2.IsValid());
 | 
| -  SharedMemory shared_memory2(shm, true);
 | 
| +  SharedMemory shared_memory2(shm2, true);
 | 
|    shared_memory2.Map(s_memory_size);
 | 
|    ASSERT_DEATH(memset(shared_memory2.memory(), 'b', s_memory_size), "");
 | 
|  }
 | 
|  
 | 
| +// Tests that the method ShareToProcess() works.
 | 
| +TEST_F(SharedMemoryMacMultiProcessTest, MachShareToProcess) {
 | 
| +  // Mach-based SharedMemory isn't support on OSX 10.6.
 | 
| +  if (mac::IsOSSnowLeopard())
 | 
| +    return;
 | 
| +
 | 
| +  mach_msg_type_number_t active_name_count = GetActiveNameCount();
 | 
| +
 | 
| +  {
 | 
| +    scoped_ptr<SharedMemory> shared_memory(
 | 
| +        CreateSharedMemory(s_memory_size).Pass());
 | 
| +
 | 
| +    SharedMemoryHandle shm2;
 | 
| +    ASSERT_TRUE(shared_memory->ShareToProcess(GetCurrentProcId(), &shm2));
 | 
| +    ASSERT_TRUE(shm2.IsValid());
 | 
| +    SharedMemory shared_memory2(shm2, true);
 | 
| +    shared_memory2.Map(s_memory_size);
 | 
| +
 | 
| +    ASSERT_EQ(0, memcmp(shared_memory->memory(), shared_memory2.memory(),
 | 
| +                        s_memory_size));
 | 
| +  }
 | 
| +
 | 
| +  EXPECT_EQ(active_name_count, GetActiveNameCount());
 | 
| +}
 | 
| +
 | 
| +// Tests that the method ShareReadOnlyToProcess() creates a memory object that
 | 
| +// is read only.
 | 
| +TEST_F(SharedMemoryMacMultiProcessTest, MachShareToProcessReadonly) {
 | 
| +  // Mach-based SharedMemory isn't support on OSX 10.6.
 | 
| +  if (mac::IsOSSnowLeopard())
 | 
| +    return;
 | 
| +
 | 
| +  scoped_ptr<SharedMemory> shared_memory(
 | 
| +      CreateSharedMemory(s_memory_size).Pass());
 | 
| +
 | 
| +  // Check the protection levels.
 | 
| +  int current_prot, max_prot;
 | 
| +  ASSERT_TRUE(GetProtections(shared_memory->memory(),
 | 
| +                             shared_memory->mapped_size(), ¤t_prot,
 | 
| +                             &max_prot));
 | 
| +  ASSERT_EQ(VM_PROT_READ | VM_PROT_WRITE, current_prot);
 | 
| +  ASSERT_EQ(VM_PROT_READ | VM_PROT_WRITE, max_prot);
 | 
| +
 | 
| +  // Make a new memory object.
 | 
| +  SharedMemoryHandle shm2;
 | 
| +  ASSERT_TRUE(shared_memory->ShareReadOnlyToProcess(GetCurrentProcId(), &shm2));
 | 
| +  ASSERT_TRUE(shm2.IsValid());
 | 
| +
 | 
| +  // Mapping with |readonly| set to |false| should fail.
 | 
| +  SharedMemory shared_memory2(shm2, false);
 | 
| +  shared_memory2.Map(s_memory_size);
 | 
| +  ASSERT_EQ(nullptr, shared_memory2.memory());
 | 
| +
 | 
| +  // Now trying mapping with |readonly| set to |true|.
 | 
| +  SharedMemory shared_memory3(shm2.Duplicate(), true);
 | 
| +  shared_memory3.Map(s_memory_size);
 | 
| +  ASSERT_NE(nullptr, shared_memory3.memory());
 | 
| +
 | 
| +  // Check the protection levels.
 | 
| +  ASSERT_TRUE(GetProtections(shared_memory3.memory(),
 | 
| +                             shared_memory3.mapped_size(), ¤t_prot,
 | 
| +                             &max_prot));
 | 
| +  ASSERT_EQ(VM_PROT_READ, current_prot);
 | 
| +  ASSERT_EQ(VM_PROT_READ, max_prot);
 | 
| +
 | 
| +  // The memory should still be readonly, since the underlying memory object
 | 
| +  // is readonly.
 | 
| +  ASSERT_DEATH(memset(shared_memory2.memory(), 'b', s_memory_size), "");
 | 
| +}
 | 
| +
 | 
| +// Tests that the method ShareReadOnlyToProcess() doesn't leak.
 | 
| +TEST_F(SharedMemoryMacMultiProcessTest, MachShareToProcessReadonlyLeak) {
 | 
| +  // Mach-based SharedMemory isn't support on OSX 10.6.
 | 
| +  if (mac::IsOSSnowLeopard())
 | 
| +    return;
 | 
| +
 | 
| +  mach_msg_type_number_t active_name_count = GetActiveNameCount();
 | 
| +
 | 
| +  {
 | 
| +    scoped_ptr<SharedMemory> shared_memory(
 | 
| +        CreateSharedMemory(s_memory_size).Pass());
 | 
| +
 | 
| +    SharedMemoryHandle shm2;
 | 
| +    ASSERT_TRUE(
 | 
| +        shared_memory->ShareReadOnlyToProcess(GetCurrentProcId(), &shm2));
 | 
| +    ASSERT_TRUE(shm2.IsValid());
 | 
| +
 | 
| +    // Intentionally map with |readonly| set to |false|.
 | 
| +    SharedMemory shared_memory2(shm2, false);
 | 
| +    shared_memory2.Map(s_memory_size);
 | 
| +  }
 | 
| +
 | 
| +  EXPECT_EQ(active_name_count, GetActiveNameCount());
 | 
| +}
 | 
| +
 | 
|  }  //  namespace base
 | 
| 
 |