1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "mojo/public/cpp/system/platform_handle.h"
6
7 #if defined(OS_MACOSX) && !defined(OS_IOS)
8 #include <mach/mach.h>
9 #include "base/mac/mach_logging.h"
10 #endif
11
12 namespace mojo {
13
14 namespace {
15
PlatformHandleValueFromPlatformFile(base::PlatformFile file)16 uint64_t PlatformHandleValueFromPlatformFile(base::PlatformFile file) {
17 #if defined(OS_WIN)
18 return reinterpret_cast<uint64_t>(file);
19 #else
20 return static_cast<uint64_t>(file);
21 #endif
22 }
23
PlatformFileFromPlatformHandleValue(uint64_t value)24 base::PlatformFile PlatformFileFromPlatformHandleValue(uint64_t value) {
25 #if defined(OS_WIN)
26 return reinterpret_cast<base::PlatformFile>(value);
27 #else
28 return static_cast<base::PlatformFile>(value);
29 #endif
30 }
31
32 } // namespace
33
WrapPlatformFile(base::PlatformFile platform_file)34 ScopedHandle WrapPlatformFile(base::PlatformFile platform_file) {
35 MojoPlatformHandle platform_handle;
36 platform_handle.struct_size = sizeof(MojoPlatformHandle);
37 platform_handle.type = kPlatformFileHandleType;
38 platform_handle.value = PlatformHandleValueFromPlatformFile(platform_file);
39
40 MojoHandle mojo_handle;
41 MojoResult result = MojoWrapPlatformHandle(&platform_handle, &mojo_handle);
42 CHECK_EQ(result, MOJO_RESULT_OK);
43
44 return ScopedHandle(Handle(mojo_handle));
45 }
46
UnwrapPlatformFile(ScopedHandle handle,base::PlatformFile * file)47 MojoResult UnwrapPlatformFile(ScopedHandle handle, base::PlatformFile* file) {
48 MojoPlatformHandle platform_handle;
49 platform_handle.struct_size = sizeof(MojoPlatformHandle);
50 MojoResult result = MojoUnwrapPlatformHandle(handle.release().value(),
51 &platform_handle);
52 if (result != MOJO_RESULT_OK)
53 return result;
54
55 if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) {
56 *file = base::kInvalidPlatformFile;
57 } else {
58 CHECK_EQ(platform_handle.type, kPlatformFileHandleType);
59 *file = PlatformFileFromPlatformHandleValue(platform_handle.value);
60 }
61
62 return MOJO_RESULT_OK;
63 }
64
WrapSharedMemoryHandle(const base::SharedMemoryHandle & memory_handle,size_t size,bool read_only)65 ScopedSharedBufferHandle WrapSharedMemoryHandle(
66 const base::SharedMemoryHandle& memory_handle,
67 size_t size,
68 bool read_only) {
69 #if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
70 if (memory_handle.fd == base::kInvalidPlatformFile)
71 return ScopedSharedBufferHandle();
72 #else
73 if (!memory_handle.IsValid())
74 return ScopedSharedBufferHandle();
75 #endif
76 MojoPlatformHandle platform_handle;
77 platform_handle.struct_size = sizeof(MojoPlatformHandle);
78 platform_handle.type = kPlatformSharedBufferHandleType;
79 #if defined(OS_MACOSX) && !defined(OS_IOS)
80 platform_handle.value =
81 static_cast<uint64_t>(memory_handle.GetMemoryObject());
82 #elif defined(OS_POSIX)
83 platform_handle.value = PlatformHandleValueFromPlatformFile(memory_handle.fd);
84 #elif defined(OS_WIN)
85 platform_handle.value =
86 PlatformHandleValueFromPlatformFile(memory_handle.GetHandle());
87 #endif
88
89 MojoPlatformSharedBufferHandleFlags flags =
90 MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE;
91 if (read_only)
92 flags |= MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY;
93
94 MojoHandle mojo_handle;
95 MojoResult result = MojoWrapPlatformSharedBufferHandle(
96 &platform_handle, size, flags, &mojo_handle);
97 CHECK_EQ(result, MOJO_RESULT_OK);
98
99 return ScopedSharedBufferHandle(SharedBufferHandle(mojo_handle));
100 }
101
UnwrapSharedMemoryHandle(ScopedSharedBufferHandle handle,base::SharedMemoryHandle * memory_handle,size_t * size,bool * read_only)102 MojoResult UnwrapSharedMemoryHandle(ScopedSharedBufferHandle handle,
103 base::SharedMemoryHandle* memory_handle,
104 size_t* size,
105 bool* read_only) {
106 if (!handle.is_valid())
107 return MOJO_RESULT_INVALID_ARGUMENT;
108 MojoPlatformHandle platform_handle;
109 platform_handle.struct_size = sizeof(MojoPlatformHandle);
110
111 MojoPlatformSharedBufferHandleFlags flags;
112 size_t num_bytes;
113 MojoResult result = MojoUnwrapPlatformSharedBufferHandle(
114 handle.release().value(), &platform_handle, &num_bytes, &flags);
115 if (result != MOJO_RESULT_OK)
116 return result;
117
118 if (size)
119 *size = num_bytes;
120
121 if (read_only)
122 *read_only = flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY;
123
124 #if defined(OS_MACOSX) && !defined(OS_IOS)
125 CHECK_EQ(platform_handle.type, MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT);
126 *memory_handle = base::SharedMemoryHandle(
127 static_cast<mach_port_t>(platform_handle.value), num_bytes,
128 base::GetCurrentProcId());
129 #elif defined(OS_POSIX)
130 CHECK_EQ(platform_handle.type, MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR);
131 *memory_handle = base::SharedMemoryHandle(
132 static_cast<int>(platform_handle.value), false);
133 #elif defined(OS_WIN)
134 CHECK_EQ(platform_handle.type, MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE);
135 *memory_handle = base::SharedMemoryHandle(
136 reinterpret_cast<HANDLE>(platform_handle.value),
137 base::GetCurrentProcId());
138 #endif
139
140 return MOJO_RESULT_OK;
141 }
142
143 #if defined(OS_MACOSX) && !defined(OS_IOS)
WrapMachPort(mach_port_t port)144 ScopedHandle WrapMachPort(mach_port_t port) {
145 kern_return_t kr =
146 mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, 1);
147 MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr)
148 << "MachPortAttachmentMac mach_port_mod_refs";
149 if (kr != KERN_SUCCESS)
150 return ScopedHandle();
151
152 MojoPlatformHandle platform_handle;
153 platform_handle.struct_size = sizeof(MojoPlatformHandle);
154 platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT;
155 platform_handle.value = static_cast<uint64_t>(port);
156
157 MojoHandle mojo_handle;
158 MojoResult result = MojoWrapPlatformHandle(&platform_handle, &mojo_handle);
159 CHECK_EQ(result, MOJO_RESULT_OK);
160
161 return ScopedHandle(Handle(mojo_handle));
162 }
163
UnwrapMachPort(ScopedHandle handle,mach_port_t * port)164 MojoResult UnwrapMachPort(ScopedHandle handle, mach_port_t* port) {
165 MojoPlatformHandle platform_handle;
166 platform_handle.struct_size = sizeof(MojoPlatformHandle);
167 MojoResult result =
168 MojoUnwrapPlatformHandle(handle.release().value(), &platform_handle);
169 if (result != MOJO_RESULT_OK)
170 return result;
171
172 CHECK_EQ(platform_handle.type, MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT);
173 *port = static_cast<mach_port_t>(platform_handle.value);
174 return MOJO_RESULT_OK;
175 }
176 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
177
178 } // namespace mojo
179