Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / sandbox / mac / xpc_message_server.cc
blobe161b5a2d0ca0fa088063afcee987426692db8ee
1 // Copyright 2014 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.
5 #include "sandbox/mac/xpc_message_server.h"
7 #include <bsm/libbsm.h>
9 #include <string>
11 #include "base/mac/mach_logging.h"
12 #include "base/strings/stringprintf.h"
13 #include "sandbox/mac/xpc.h"
15 namespace sandbox {
17 XPCMessageServer::XPCMessageServer(MessageDemuxer* demuxer,
18 mach_port_t server_receive_right)
19 : demuxer_(demuxer),
20 server_port_(server_receive_right),
21 reply_message_(NULL) {
22 CHECK(InitializeXPC());
25 XPCMessageServer::~XPCMessageServer() {
28 bool XPCMessageServer::Initialize() {
29 // Allocate a port for use as a new server port if one was not passed to the
30 // constructor.
31 if (!server_port_.is_valid()) {
32 mach_port_t port;
33 kern_return_t kr;
34 if ((kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE,
35 &port)) != KERN_SUCCESS) {
36 MACH_LOG(ERROR, kr) << "Failed to allocate new server port.";
37 return false;
39 server_port_.reset(port);
42 std::string label = base::StringPrintf(
43 "org.chromium.sandbox.XPCMessageServer.%p", demuxer_);
44 dispatch_source_.reset(new base::DispatchSourceMach(
45 label.c_str(), server_port_.get(), ^{ ReceiveMessage(); }));
46 dispatch_source_->Resume();
48 return true;
51 pid_t XPCMessageServer::GetMessageSenderPID(IPCMessage request) {
52 audit_token_t token;
53 xpc_dictionary_get_audit_token(request.xpc, &token);
54 // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid().
55 pid_t sender_pid;
56 audit_token_to_au32(token,
57 NULL, NULL, NULL, NULL, NULL, &sender_pid, NULL, NULL);
58 return sender_pid;
61 IPCMessage XPCMessageServer::CreateReply(IPCMessage request) {
62 if (!reply_message_)
63 reply_message_ = xpc_dictionary_create_reply(request.xpc);
65 IPCMessage reply;
66 reply.xpc = reply_message_;
67 return reply;
70 bool XPCMessageServer::SendReply(IPCMessage reply) {
71 if (!reply.xpc)
72 return false;
74 int rv = xpc_pipe_routine_reply(reply.xpc);
75 if (rv) {
76 LOG(ERROR) << "Failed to xpc_pipe_routine_reply(): " << rv;
77 return false;
79 return true;
82 void XPCMessageServer::ForwardMessage(IPCMessage request,
83 mach_port_t destination) {
84 xpc_pipe_t pipe = xpc_pipe_create_from_port(destination, 0);
85 int rv = xpc_pipe_routine_forward(pipe, request.xpc);
86 if (rv) {
87 LOG(ERROR) << "Failed to xpc_pipe_routine_forward(): " << rv;
89 xpc_release(pipe);
92 void XPCMessageServer::RejectMessage(IPCMessage request, int error_code) {
93 IPCMessage reply = CreateReply(request);
94 // The message wasn't expecting a reply, so rejecting means ignoring it.
95 if (reply.xpc) {
96 xpc_dictionary_set_int64(reply.xpc, "error", error_code);
97 SendReply(reply);
101 mach_port_t XPCMessageServer::GetServerPort() const {
102 return server_port_.get();
105 void XPCMessageServer::ReceiveMessage() {
106 IPCMessage request;
107 int rv = xpc_pipe_receive(server_port_, &request.xpc);
108 if (rv) {
109 LOG(ERROR) << "Failed to xpc_pipe_receive(): " << rv;
110 return;
113 demuxer_->DemuxMessage(request);
115 xpc_release(request.xpc);
116 if (reply_message_) {
117 xpc_release(reply_message_);
118 reply_message_ = NULL;
122 } // namespace sandbox