Skip to content

Commit

Permalink
ipc: Make a wrapper and attachment for mach ports.
Browse files Browse the repository at this point in the history
This is part of the plumbing required to allow attachment brokers to pass mach
ports between processes.

BUG=535711

Review URL: https://codereview.chromium.org/1372303006

Cr-Commit-Position: refs/heads/master@{#351852}
  • Loading branch information
erikchen authored and Commit bot committed Oct 1, 2015
1 parent 1cf9a35 commit 1c1e665
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 0 deletions.
4 changes: 4 additions & 0 deletions ipc/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ component("ipc") {
"ipc_sync_message.h",
"ipc_sync_message_filter.cc",
"ipc_sync_message_filter.h",
"mach_port_attachment_mac.cc",
"mach_port_attachment_mac.h",
"mach_port_mac.cc",
"mach_port_mac.h",
"message_filter.cc",
"message_filter.h",
"message_filter_router.cc",
Expand Down
1 change: 1 addition & 0 deletions ipc/brokerable_attachment.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class IPC_EXPORT BrokerableAttachment : public MessageAttachment {
enum BrokerableType {
PLACEHOLDER,
WIN_HANDLE,
MACH_PORT,
};

// The identifier is unique across all Chrome processes.
Expand Down
4 changes: 4 additions & 0 deletions ipc/ipc.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@
'ipc_sync_message.h',
'ipc_sync_message_filter.cc',
'ipc_sync_message_filter.h',
'mach_port_attachment_mac.cc',
'mach_port_attachment_mac.h',
'mach_port_mac.cc',
'mach_port_mac.h',
'message_filter.cc',
'message_filter.h',
'message_filter_router.cc',
Expand Down
35 changes: 35 additions & 0 deletions ipc/mach_port_attachment_mac.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// 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/mach_port_attachment_mac.h"

namespace IPC {
namespace internal {

MachPortAttachmentMac::MachPortAttachmentMac(mach_port_t mach_port)
: mach_port_(mach_port) {}

MachPortAttachmentMac::MachPortAttachmentMac(const WireFormat& wire_format)
: BrokerableAttachment(wire_format.attachment_id),
mach_port_(static_cast<mach_port_t>(wire_format.mach_port)) {}

MachPortAttachmentMac::MachPortAttachmentMac(
const BrokerableAttachment::AttachmentId& id)
: BrokerableAttachment(id), mach_port_(MACH_PORT_NULL) {}

MachPortAttachmentMac::~MachPortAttachmentMac() {}

MachPortAttachmentMac::BrokerableType MachPortAttachmentMac::GetBrokerableType()
const {
return MACH_PORT;
}

MachPortAttachmentMac::WireFormat MachPortAttachmentMac::GetWireFormat(
const base::ProcessId& destination) const {
return WireFormat(static_cast<uint32_t>(mach_port_), destination,
GetIdentifier());
}

} // namespace internal
} // namespace IPC
67 changes: 67 additions & 0 deletions ipc/mach_port_attachment_mac.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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.

#ifndef IPC_MACH_PORT_ATTACHMENT_MAC_H_
#define IPC_MACH_PORT_ATTACHMENT_MAC_H_

#include <mach/mach.h>
#include <stdint.h>

#include "base/process/process_handle.h"
#include "ipc/brokerable_attachment.h"
#include "ipc/ipc_export.h"
#include "ipc/mach_port_mac.h"

namespace IPC {
namespace internal {

// This class represents an OSX mach_port_t attached to a Chrome IPC message.
class IPC_EXPORT MachPortAttachmentMac : public BrokerableAttachment {
public:
struct IPC_EXPORT WireFormat {
// IPC translation requires that classes passed through IPC have a default
// constructor.
WireFormat() : mach_port(0), destination_process(0) {}

WireFormat(uint32_t mach_port,
const base::ProcessId& destination_process,
const AttachmentId& attachment_id)
: mach_port(mach_port),
destination_process(destination_process),
attachment_id(attachment_id) {}

// The mach port that is intended for duplication, or the mach port that has
// been duplicated, depending on context.
// The type is uint32_t instead of mach_port_t to ensure that the wire
// format stays consistent.
uint32_t mach_port;
static_assert(sizeof(mach_port_t) <= sizeof(uint32_t),
"mach_port_t must be smaller than uint32_t");

// The id of the destination process that the handle is duplicated into.
base::ProcessId destination_process;

AttachmentId attachment_id;
};

explicit MachPortAttachmentMac(mach_port_t mach_port);
explicit MachPortAttachmentMac(const WireFormat& wire_format);
explicit MachPortAttachmentMac(const BrokerableAttachment::AttachmentId& id);

BrokerableType GetBrokerableType() const override;

// Returns the wire format of this attachment.
WireFormat GetWireFormat(const base::ProcessId& destination) const;

mach_port_t get_mach_port() const { return mach_port_; }

private:
~MachPortAttachmentMac() override;
mach_port_t mach_port_;
};

} // namespace internal
} // namespace IPC

#endif // IPC_MACH_PORT_ATTACHMENT_MAC_H_
48 changes: 48 additions & 0 deletions ipc/mach_port_mac.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// 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/mach_port_mac.h"

#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_number_conversions.h"
#include "ipc/mach_port_attachment_mac.h"

namespace IPC {

// static
void ParamTraits<MachPortMac>::Write(Message* m, const param_type& p) {
if (!m->WriteAttachment(
new IPC::internal::MachPortAttachmentMac(p.get_mach_port()))) {
NOTREACHED();
}
}

// static
bool ParamTraits<MachPortMac>::Read(const Message* m,
base::PickleIterator* iter,
param_type* r) {
scoped_refptr<MessageAttachment> attachment;
if (!m->ReadAttachment(iter, &attachment))
return false;
if (attachment->GetType() != MessageAttachment::TYPE_BROKERABLE_ATTACHMENT)
return false;
BrokerableAttachment* brokerable_attachment =
static_cast<BrokerableAttachment*>(attachment.get());
if (brokerable_attachment->GetBrokerableType() !=
BrokerableAttachment::MACH_PORT) {
return false;
}
IPC::internal::MachPortAttachmentMac* mach_port_attachment =
static_cast<IPC::internal::MachPortAttachmentMac*>(brokerable_attachment);
r->set_mach_port(mach_port_attachment->get_mach_port());
return true;
}

// static
void ParamTraits<MachPortMac>::Log(const param_type& p, std::string* l) {
l->append(base::StringPrintf("mach port: 0x%X", p.get_mach_port()));
}

} // namespace IPC
40 changes: 40 additions & 0 deletions ipc/mach_port_mac.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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.

#ifndef IPC_MACH_PORT_MAC_H_
#define IPC_MACH_PORT_MAC_H_

#include <mach/mach.h>

#include "ipc/ipc_export.h"
#include "ipc/ipc_message_macros.h"

namespace IPC {

// MachPortMac is a wrapper around an OSX mach_port_t that can be transported
// across Chrome IPC channels that support attachment brokering. The mach_port_t
// will be duplicated into the destination process by the attachment broker.
class IPC_EXPORT MachPortMac {
public:
MachPortMac() : mach_port_(MACH_PORT_NULL) {}
explicit MachPortMac(const mach_port_t& mach_port) : mach_port_(mach_port) {}

mach_port_t get_mach_port() const { return mach_port_; }
void set_mach_port(mach_port_t mach_port) { mach_port_ = mach_port; }

private:
mach_port_t mach_port_;
};

template <>
struct IPC_EXPORT ParamTraits<MachPortMac> {
typedef MachPortMac param_type;
static void Write(Message* m, const param_type& p);
static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
static void Log(const param_type& p, std::string* l);
};

} // namespace IPC

#endif // IPC_MACH_PORT_MAC_H_

0 comments on commit 1c1e665

Please sign in to comment.