Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(426)

Side by Side Diff: content/browser/browser_io_surface_manager_mac.cc

Issue 1137453002: content: Pass IOSurface references using Mach IPC. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase, remove extra DCHECKs and fix reply port typo Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 "content/browser/browser_io_surface_manager_mac.h"
6
7 #include <servers/bootstrap.h>
8
9 #include <string>
10
11 #include "base/logging.h"
12 #include "base/mac/foundation_util.h"
13 #include "base/mac/mach_logging.h"
14 #include "base/strings/stringprintf.h"
15 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
16
17 namespace content {
18 namespace {
19
20 // Returns the Mach port name to use when sending or receiving messages. |pid|
21 // is the process ID of the service.
22 std::string GetMachPortName(pid_t pid) {
23 return base::StringPrintf("%s.iosurfacemgr.%d", base::mac::BaseBundleID(),
24 pid);
25 }
26
27 // Amount of time to wait before giving up when sending a reply message.
28 const int kSendReplyTimeoutMs = 100;
29
30 } // namespace
31
32 // static
33 BrowserIOSurfaceManager* BrowserIOSurfaceManager::GetInstance() {
34 return Singleton<BrowserIOSurfaceManager,
35 LeakySingletonTraits<BrowserIOSurfaceManager>>::get();
36 }
37
38 // static
39 mach_port_t BrowserIOSurfaceManager::LookupServicePort(pid_t pid) {
40 // Look up the named IOSurfaceManager port that's been registered with
41 // the bootstrap server.
42 mach_port_t port;
43 kern_return_t kr =
44 bootstrap_look_up(bootstrap_port, GetMachPortName(pid).c_str(), &port);
45 if (kr != KERN_SUCCESS) {
46 BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up";
47 return MACH_PORT_NULL;
48 }
49
50 return port;
51 }
52
53 bool BrowserIOSurfaceManager::RegisterIOSurface(int io_surface_id,
54 int client_id,
55 IOSurfaceRef io_surface) {
56 base::AutoLock lock(lock_);
57
58 IOSurfaceMapKey key(io_surface_id, client_id);
59 DCHECK(io_surfaces_.find(key) == io_surfaces_.end());
60 io_surfaces_.add(key, make_scoped_ptr(new base::mac::ScopedMachSendRight(
61 IOSurfaceCreateMachPort(io_surface))));
62 return true;
63 }
64
65 void BrowserIOSurfaceManager::UnregisterIOSurface(int io_surface_id,
66 int client_id) {
67 base::AutoLock lock(lock_);
68
69 IOSurfaceMapKey key(io_surface_id, client_id);
70 DCHECK(io_surfaces_.find(key) != io_surfaces_.end());
71 io_surfaces_.erase(key);
72 }
73
74 IOSurfaceRef BrowserIOSurfaceManager::AcquireIOSurface(int io_surface_id) {
75 base::AutoLock lock(lock_);
76
77 IOSurfaceMapKey key(
78 io_surface_id,
79 BrowserGpuChannelHostFactory::instance()->GetGpuChannelId());
80 auto it = io_surfaces_.find(key);
81 if (it == io_surfaces_.end()) {
82 LOG(ERROR) << "Invalid Id for IOSurface " << io_surface_id;
83 return nullptr;
84 }
85
86 return IOSurfaceLookupFromMachPort(it->second->get());
87 }
88
89 void BrowserIOSurfaceManager::EnsureRunning() {
90 base::AutoLock lock(lock_);
91
92 if (initialized_)
93 return;
94
95 // Do not attempt to reinitialize in the event of failure.
96 initialized_ = true;
97
98 if (!Initialize()) {
99 LOG(ERROR) << "Failed to initialize the BrowserIOSurfaceManager";
100 }
101 }
102
103 gpu::Mailbox BrowserIOSurfaceManager::GetGpuProcessMailbox() const {
104 return gpu_process_mailbox_;
105 }
106
107 gpu::Mailbox BrowserIOSurfaceManager::GenerateChildProcessMailbox(
108 int child_process_id) {
109 base::AutoLock lock(lock_);
110
111 gpu::Mailbox mailbox = gpu::Mailbox::Generate();
112 DCHECK(mailbox.Verify());
113 child_process_ids_[mailbox] = child_process_id;
114 return mailbox;
115 }
116
117 void BrowserIOSurfaceManager::InvalidateChildProcessMailbox(
118 const gpu::Mailbox& mailbox) {
119 base::AutoLock lock(lock_);
120
121 DCHECK(child_process_ids_.find(mailbox) != child_process_ids_.end());
122 child_process_ids_.erase(mailbox);
123 }
124
125 BrowserIOSurfaceManager::BrowserIOSurfaceManager()
126 : initialized_(false), gpu_process_mailbox_(gpu::Mailbox::Generate()) {
127 DCHECK(gpu_process_mailbox_.Verify());
128 }
129
130 BrowserIOSurfaceManager::~BrowserIOSurfaceManager() {
131 }
132
133 bool BrowserIOSurfaceManager::Initialize() {
134 lock_.AssertAcquired();
135 DCHECK(server_port_.get() == MACH_PORT_NULL);
136
137 // Check in with launchd and publish the service name.
138 mach_port_t port;
139 kern_return_t kr = bootstrap_check_in(
140 bootstrap_port, GetMachPortName(getpid()).c_str(), &port);
141 if (kr != KERN_SUCCESS) {
142 BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_check_in";
143 return false;
144 }
145 server_port_.reset(port);
146
147 // Start the dispatch source.
148 std::string queue_name =
149 base::StringPrintf("%s.IOSurfaceManager", base::mac::BaseBundleID());
150 dispatch_source_.reset(
151 new base::DispatchSourceMach(queue_name.c_str(), server_port_.get(), ^{
152 HandleRequest();
Robert Sesek 2015/05/19 23:26:23 nit: Chrome indents blocks 4 spaces
reveman 2015/05/27 05:03:18 This is how cl format likes it. I'd rather not mes
153 }));
154 dispatch_source_->Resume();
155
156 return true;
157 }
158
159 void BrowserIOSurfaceManager::HandleRequest() {
160 struct {
161 union {
162 mach_msg_header_t header;
163 IOSurfaceManagerHostMsg_RegisterIOSurface register_io_surface;
164 IOSurfaceManagerHostMsg_UnregisterIOSurface unregister_io_surface;
165 IOSurfaceManagerHostMsg_AcquireIOSurface acquire_io_surface;
166 } msg;
167 mach_msg_trailer_t trailer;
168 } request = {{{0}}};
169 request.msg.header.msgh_size = sizeof(request);
170 request.msg.header.msgh_local_port = server_port_.get();
171
172 kern_return_t kr =
173 mach_msg(&request.msg.header, MACH_RCV_MSG, 0, sizeof(request),
174 server_port_, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
175 if (kr != KERN_SUCCESS) {
176 MACH_LOG(ERROR, kr) << "mach_msg";
177 return;
178 }
179
180 union {
181 mach_msg_header_t header;
182 IOSurfaceManagerMsg_RegisterIOSurfaceReply register_io_surface;
183 IOSurfaceManagerMsg_AcquireIOSurfaceReply acquire_io_surface;
184 } reply = {{0}};
185
186 switch (request.msg.header.msgh_id) {
187 case IOSurfaceManagerHostMsg_RegisterIOSurface::ID:
188 if (!HandleRegisterIOSurfaceRequest(request.msg.register_io_surface,
189 &reply.register_io_surface))
Robert Sesek 2015/05/19 23:26:23 nit: braces required for multi-line body. Same on
reveman 2015/05/27 05:03:18 Done.
190 return;
191 break;
192 case IOSurfaceManagerHostMsg_UnregisterIOSurface::ID:
193 HandleUnregisterIOSurfaceRequest(request.msg.unregister_io_surface);
194 return;
Robert Sesek 2015/05/19 23:26:23 Add a comment here that this is deliberately one-w
reveman 2015/05/27 05:03:18 Done.
195 case IOSurfaceManagerHostMsg_AcquireIOSurface::ID:
196 if (!HandleAcquireIOSurfaceRequest(request.msg.acquire_io_surface,
197 &reply.acquire_io_surface))
198 return;
Robert Sesek 2015/05/19 23:26:23 Won't this leave the remote caller hanging if this
reveman 2015/05/27 05:03:18 Failure is a result of incorrect usage or a reques
Robert Sesek 2015/05/28 18:25:11 I think it's okay then. If there were non-misuse w
199 break;
200 default:
201 LOG(ERROR) << "Unknown message received!";
202 return;
203 }
204
205 DCHECK(reply.header.msgh_size);
Robert Sesek 2015/05/19 23:26:23 I don't think these DCHECKs are meaningful. The ke
reveman 2015/05/27 05:03:18 In case it wasn't clear, these are to protect agai
206 DCHECK(reply.header.msgh_remote_port != MACH_PORT_NULL);
207 kr = mach_msg(&reply.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT,
208 reply.header.msgh_size, 0, MACH_PORT_NULL, kSendReplyTimeoutMs,
209 MACH_PORT_NULL);
210 if (kr != KERN_SUCCESS) {
211 MACH_LOG(ERROR, kr) << "mach_msg";
212 }
213 }
214
215 bool BrowserIOSurfaceManager::HandleRegisterIOSurfaceRequest(
216 const IOSurfaceManagerHostMsg_RegisterIOSurface& request,
217 IOSurfaceManagerMsg_RegisterIOSurfaceReply* reply) {
218 base::AutoLock lock(lock_);
219
220 gpu::Mailbox mailbox;
221 COMPILE_ASSERT(sizeof(request.mailbox_name) == sizeof(mailbox.name),
222 "Mach message mailbox size doesn't match expectation.");
223 mailbox.SetName(request.mailbox_name);
224 if (mailbox != gpu_process_mailbox_) {
225 LOG(ERROR) << "Illegal message from non-GPU process!";
226 return false;
227 }
228
229 IOSurfaceMapKey key(request.io_surface_id, request.client_id);
230 io_surfaces_.add(key, make_scoped_ptr(new base::mac::ScopedMachSendRight(
231 request.io_surface_port.name)));
232
233 reply->header.msgh_bits = MACH_MSGH_BITS_REMOTE(request.header.msgh_bits);
234 reply->header.msgh_remote_port = request.header.msgh_remote_port;
235 reply->header.msgh_size = sizeof(*reply);
236 reply->result = true;
237 return true;
238 }
239
240 bool BrowserIOSurfaceManager::HandleUnregisterIOSurfaceRequest(
241 const IOSurfaceManagerHostMsg_UnregisterIOSurface& request) {
242 base::AutoLock lock(lock_);
243
244 gpu::Mailbox mailbox;
245 COMPILE_ASSERT(sizeof(request.mailbox_name) == sizeof(mailbox.name),
246 "Mach message mailbox size doesn't match expectation.");
247 mailbox.SetName(request.mailbox_name);
248 if (mailbox != gpu_process_mailbox_) {
249 LOG(ERROR) << "Illegal message from non-GPU process!";
250 return false;
251 }
252
253 IOSurfaceMapKey key(request.io_surface_id, request.client_id);
254 io_surfaces_.erase(key);
255 return true;
256 }
257
258 bool BrowserIOSurfaceManager::HandleAcquireIOSurfaceRequest(
259 const IOSurfaceManagerHostMsg_AcquireIOSurface& request,
260 IOSurfaceManagerMsg_AcquireIOSurfaceReply* reply) {
261 base::AutoLock lock(lock_);
262
263 gpu::Mailbox mailbox;
264 COMPILE_ASSERT(sizeof(request.mailbox_name) == sizeof(mailbox.name),
265 "Mach message mailbox size doesn't match expectation.");
266 mailbox.SetName(request.mailbox_name);
267 auto child_process_id_it = child_process_ids_.find(mailbox);
268 if (child_process_id_it == child_process_ids_.end()) {
269 LOG(ERROR) << "Illegal message from non-child process!";
270 return false;
271 }
272
273 IOSurfaceMapKey key(request.io_surface_id, child_process_id_it->second);
274 auto it = io_surfaces_.find(key);
275 if (it == io_surfaces_.end()) {
276 LOG(ERROR) << "Invalid Id for IOSurface " << request.io_surface_id;
277 return false;
278 }
279
280 reply->header.msgh_bits =
281 MACH_MSGH_BITS_REMOTE(request.header.msgh_bits) | MACH_MSGH_BITS_COMPLEX;
282 reply->header.msgh_remote_port = request.header.msgh_remote_port;
283 reply->header.msgh_size = sizeof(*reply);
284 reply->body.msgh_descriptor_count = 1;
285 reply->io_surface_port.name = it->second->get();
286 reply->io_surface_port.disposition = MACH_MSG_TYPE_COPY_SEND;
287 reply->io_surface_port.type = MACH_MSG_PORT_DESCRIPTOR;
288 return true;
289 }
290
291 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698