Commit 6d83a0be authored by Wez's avatar Wez Committed by Commit Bot

Reland "Migrate call-sites away from un-managed PlatformHandle[Vector]s."

This is a reland of 7df6fead, which was
speculatively reverted as possible cause of crbug.com/788192, since the
CL originally landed only after that regression.

Original change's description:
> Migrate call-sites away from un-managed PlatformHandle[Vector]s.
>
> As the first step to merging ScopedPlatformHandle into PlatformHandle
> to have a single, always-managed container for platform handles, we:
>
> - Replace ScopedPlatformHandleVectorPtr and PlatformHandleVector
>   with vector<ScopedPlatformHandle>.
> - Replace PlatformHandle with ScopedPlatformHandle in some core APIs.
> - Use const& to pass handles to APIs without passing ownership, for
>   both individual platform handles, and vectors.
>
> Bug: 753541
> Change-Id: Id965dcf3770ef11bf36f78277fa7199ea779599e
> Reviewed-on: https://chromium-review.googlesource.com/742309
> Reviewed-by: Ricky Liang <jcliang@chromium.org>
> Reviewed-by: Ken Rockot <rockot@chromium.org>
> Reviewed-by: Dominick Ng <dominickn@chromium.org>
> Reviewed-by: Luis Hector Chavez <lhchavez@chromium.org>
> Commit-Queue: Wez <wez@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#518343}

Bug: 753541
TBR: lhchavez, jcliang, dominickn, rockot
Change-Id: I9d50f06052b2118aec8872ca149504fbed245f1a
Reviewed-on: https://chromium-review.googlesource.com/792255Reviewed-by: default avatarWez <wez@chromium.org>
Commit-Queue: Wez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#519505}
parent 6d1a552b
......@@ -41,8 +41,7 @@ bool UnixDomainSocketAcceptor::Listen() {
void UnixDomainSocketAcceptor::OnFileCanReadWithoutBlocking(int fd) {
DCHECK(fd == listen_handle_.get().handle);
mojo::edk::ScopedPlatformHandle connection_handle;
if (!mojo::edk::ServerAcceptConnection(listen_handle_.get(),
&connection_handle)) {
if (!mojo::edk::ServerAcceptConnection(listen_handle_, &connection_handle)) {
Close();
delegate_->OnListenError();
return;
......
......@@ -9,6 +9,7 @@
#include <unistd.h>
#include <utility>
#include <vector>
#include "base/location.h"
#include "base/posix/eintr_wrapper.h"
......@@ -27,7 +28,6 @@
#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/platform_channel_utils_posix.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/public/cpp/bindings/binding.h"
......@@ -183,7 +183,7 @@ mojo::ScopedMessagePipeHandle ArcSessionDelegateImpl::ConnectMojoInternal(
}
mojo::edk::ScopedPlatformHandle scoped_fd;
if (!mojo::edk::ServerAcceptConnection(socket_fd.get(), &scoped_fd,
if (!mojo::edk::ServerAcceptConnection(socket_fd, &scoped_fd,
/* check_peer_user = */ false) ||
!scoped_fd.is_valid()) {
return mojo::ScopedMessagePipeHandle();
......@@ -202,9 +202,8 @@ mojo::ScopedMessagePipeHandle ArcSessionDelegateImpl::ConnectMojoInternal(
mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy,
channel_pair.PassServerHandle()));
mojo::edk::ScopedPlatformHandleVectorPtr handles(
new mojo::edk::PlatformHandleVector{
channel_pair.PassClientHandle().release()});
std::vector<mojo::edk::ScopedPlatformHandle> handles;
handles.emplace_back(channel_pair.PassClientHandle());
// We need to send the length of the message as a single byte, so make sure it
// fits.
......@@ -213,8 +212,7 @@ mojo::ScopedMessagePipeHandle ArcSessionDelegateImpl::ConnectMojoInternal(
struct iovec iov[] = {{&message_length, sizeof(message_length)},
{const_cast<char*>(token.c_str()), token.size()}};
ssize_t result = mojo::edk::PlatformChannelSendmsgWithHandles(
scoped_fd.get(), iov, sizeof(iov) / sizeof(iov[0]), handles->data(),
handles->size());
scoped_fd, iov, sizeof(iov) / sizeof(iov[0]), handles);
if (result == -1) {
PLOG(ERROR) << "sendmsg";
return mojo::ScopedMessagePipeHandle();
......
......@@ -9,6 +9,8 @@
#include <poll.h>
#include <sys/uio.h>
#include <vector>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/posix/eintr_wrapper.h"
......@@ -20,7 +22,6 @@
#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/platform_channel_utils_posix.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
namespace media {
......@@ -265,8 +266,7 @@ void CameraHalDispatcherImpl::StartServiceLoop(
}
mojo::edk::ScopedPlatformHandle accepted_fd;
if (mojo::edk::ServerAcceptConnection(proxy_fd_.get(), &accepted_fd,
false) &&
if (mojo::edk::ServerAcceptConnection(proxy_fd_, &accepted_fd, false) &&
accepted_fd.is_valid()) {
VLOG(1) << "Accepted a connection";
// Hardcode pid 0 since it is unused in mojo.
......@@ -282,13 +282,12 @@ void CameraHalDispatcherImpl::StartServiceLoop(
mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy,
channel_pair.PassServerHandle()));
mojo::edk::ScopedPlatformHandleVectorPtr handles(
new mojo::edk::PlatformHandleVector{
channel_pair.PassClientHandle().release()});
std::vector<mojo::edk::ScopedPlatformHandle> handles;
handles.emplace_back(channel_pair.PassClientHandle());
struct iovec iov = {const_cast<char*>(token.c_str()), token.length()};
ssize_t result = mojo::edk::PlatformChannelSendmsgWithHandles(
accepted_fd.get(), &iov, 1, handles->data(), handles->size());
accepted_fd, &iov, 1, handles);
if (result == -1) {
PLOG(ERROR) << "sendmsg()";
} else {
......
......@@ -96,7 +96,6 @@ source_set("platform") {
"platform_handle.h",
"platform_handle_utils.h",
"platform_handle_utils_win.cc",
"platform_handle_vector.h",
"platform_shared_buffer.cc",
"platform_shared_buffer.h",
"scoped_platform_handle.h",
......
......@@ -14,6 +14,7 @@
#include <sys/uio.h>
#include <unistd.h>
#include <utility>
#include <vector>
#include "base/containers/circular_deque.h"
#include "base/files/file_path.h"
......@@ -24,7 +25,6 @@
#include "base/macros.h"
#include "mojo/edk/embedder/platform_channel_utils_posix.h"
#include "mojo/edk/embedder/platform_handle.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -90,7 +90,7 @@ TEST_F(PlatformChannelPairPosixTest, NoSigPipe) {
PLOG(WARNING) << "read (expected 0 for EOF)";
// Test our replacement for |write()|/|send()|.
result = PlatformChannelWrite(server_handle.get(), kHello, sizeof(kHello));
result = PlatformChannelWrite(server_handle, kHello, sizeof(kHello));
EXPECT_EQ(-1, result);
if (errno != EPIPE)
PLOG(WARNING) << "write (expected EPIPE)";
......@@ -98,7 +98,7 @@ TEST_F(PlatformChannelPairPosixTest, NoSigPipe) {
// Test our replacement for |writev()|/|sendv()|.
struct iovec iov[2] = {{const_cast<char*>(kHello), sizeof(kHello)},
{const_cast<char*>(kHello), sizeof(kHello)}};
result = PlatformChannelWritev(server_handle.get(), iov, 2);
result = PlatformChannelWritev(server_handle, iov, 2);
EXPECT_EQ(-1, result);
if (errno != EPIPE)
PLOG(WARNING) << "write (expected EPIPE)";
......@@ -113,15 +113,15 @@ TEST_F(PlatformChannelPairPosixTest, SendReceiveData) {
std::string send_string(1 << i, 'A' + i);
EXPECT_EQ(static_cast<ssize_t>(send_string.size()),
PlatformChannelWrite(server_handle.get(), send_string.data(),
PlatformChannelWrite(server_handle, send_string.data(),
send_string.size()));
WaitReadable(client_handle.get());
char buf[10000] = {};
base::circular_deque<PlatformHandle> received_handles;
ssize_t result = PlatformChannelRecvmsg(client_handle.get(), buf,
sizeof(buf), &received_handles);
base::circular_deque<ScopedPlatformHandle> received_handles;
ssize_t result = PlatformChannelRecvmsg(client_handle, buf, sizeof(buf),
&received_handles);
EXPECT_EQ(static_cast<ssize_t>(send_string.size()), result);
EXPECT_EQ(send_string, std::string(buf, static_cast<size_t>(result)));
EXPECT_TRUE(received_handles.empty());
......@@ -149,40 +149,38 @@ TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) {
// Make |i| files, with the j-th file consisting of j copies of the digit
// |c|.
const char c = '0' + (i % 10);
ScopedPlatformHandleVectorPtr platform_handles(new PlatformHandleVector);
std::vector<ScopedPlatformHandle> platform_handles;
for (size_t j = 1; j <= i; j++) {
base::FilePath unused;
base::ScopedFILE fp(
base::CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused));
ASSERT_TRUE(fp);
ASSERT_EQ(j, fwrite(std::string(j, c).data(), 1, j, fp.get()));
platform_handles->push_back(
test::PlatformHandleFromFILE(std::move(fp)).release());
ASSERT_TRUE(platform_handles->back().is_valid());
platform_handles.push_back(test::PlatformHandleFromFILE(std::move(fp)));
ASSERT_TRUE(platform_handles.back().is_valid());
}
// Send the FDs (+ "hello").
struct iovec iov = {const_cast<char*>(kHello), sizeof(kHello)};
// We assume that the |sendmsg()| actually sends all the data.
EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
PlatformChannelSendmsgWithHandles(server_handle.get(), &iov, 1,
&platform_handles->at(0),
platform_handles->size()));
PlatformChannelSendmsgWithHandles(server_handle, &iov, 1,
std::move(platform_handles)));
WaitReadable(client_handle.get());
char buf[10000] = {};
base::circular_deque<PlatformHandle> received_handles;
base::circular_deque<ScopedPlatformHandle> received_handles;
// We assume that the |recvmsg()| actually reads all the data.
EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
PlatformChannelRecvmsg(client_handle.get(), buf, sizeof(buf),
PlatformChannelRecvmsg(client_handle, buf, sizeof(buf),
&received_handles));
EXPECT_STREQ(kHello, buf);
EXPECT_EQ(i, received_handles.size());
for (size_t j = 0; !received_handles.empty(); j++) {
for (size_t j = 0; j < received_handles.size(); j++) {
base::ScopedFILE fp(test::FILEFromPlatformHandle(
ScopedPlatformHandle(received_handles.front()), "rb"));
std::move(received_handles.front()), "rb"));
received_handles.pop_front();
ASSERT_TRUE(fp);
rewind(fp.get());
......@@ -213,30 +211,28 @@ TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) {
ASSERT_TRUE(fp);
ASSERT_EQ(file_contents.size(),
fwrite(file_contents.data(), 1, file_contents.size(), fp.get()));
ScopedPlatformHandleVectorPtr platform_handles(new PlatformHandleVector);
platform_handles->push_back(
test::PlatformHandleFromFILE(std::move(fp)).release());
ASSERT_TRUE(platform_handles->back().is_valid());
std::vector<ScopedPlatformHandle> platform_handles(1);
platform_handles[0] = test::PlatformHandleFromFILE(std::move(fp));
ASSERT_TRUE(platform_handles.back().is_valid());
// Send the FD (+ "hello").
struct iovec iov = {const_cast<char*>(kHello), sizeof(kHello)};
// We assume that the |sendmsg()| actually sends all the data.
EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
PlatformChannelSendmsgWithHandles(server_handle.get(), &iov, 1,
&platform_handles->at(0),
platform_handles->size()));
PlatformChannelSendmsgWithHandles(server_handle, &iov, 1,
std::move(platform_handles)));
}
WaitReadable(client_handle.get());
// Start with an invalid handle in the deque.
base::circular_deque<PlatformHandle> received_handles;
received_handles.push_back(PlatformHandle());
// Start with an invalid handle in the vector.
base::circular_deque<ScopedPlatformHandle> received_handles;
received_handles.push_back(ScopedPlatformHandle());
char buf[100] = {};
// We assume that the |recvmsg()| actually reads all the data.
EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
PlatformChannelRecvmsg(client_handle.get(), buf, sizeof(buf),
PlatformChannelRecvmsg(client_handle, buf, sizeof(buf),
&received_handles));
EXPECT_STREQ(kHello, buf);
ASSERT_EQ(2u, received_handles.size());
......@@ -244,9 +240,8 @@ TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) {
EXPECT_TRUE(received_handles[1].is_valid());
{
base::ScopedFILE fp(test::FILEFromPlatformHandle(
ScopedPlatformHandle(received_handles[1]), "rb"));
received_handles[1] = PlatformHandle();
base::ScopedFILE fp(
test::FILEFromPlatformHandle(std::move(received_handles[1]), "rb"));
ASSERT_TRUE(fp);
rewind(fp.get());
char read_buf[100];
......
......@@ -106,7 +106,7 @@ const int kSendFlags = 0;
const int kSendFlags = MSG_NOSIGNAL;
#endif
ssize_t PlatformChannelWrite(PlatformHandle h,
ssize_t PlatformChannelWrite(const ScopedPlatformHandle& h,
const void* bytes,
size_t num_bytes) {
DCHECK(h.is_valid());
......@@ -115,13 +115,13 @@ ssize_t PlatformChannelWrite(PlatformHandle h,
#if defined(OS_MACOSX) || defined(OS_NACL_NONSFI)
// send() is not available under NaCl-nonsfi.
return HANDLE_EINTR(write(h.handle, bytes, num_bytes));
return HANDLE_EINTR(write(h.get().handle, bytes, num_bytes));
#else
return send(h.handle, bytes, num_bytes, kSendFlags);
return send(h.get().handle, bytes, num_bytes, kSendFlags);
#endif
}
ssize_t PlatformChannelWritev(PlatformHandle h,
ssize_t PlatformChannelWritev(const ScopedPlatformHandle& h,
struct iovec* iov,
size_t num_iov) {
DCHECK(h.is_valid());
......@@ -129,84 +129,49 @@ ssize_t PlatformChannelWritev(PlatformHandle h,
DCHECK_GT(num_iov, 0u);
#if defined(OS_MACOSX)
return HANDLE_EINTR(writev(h.handle, iov, static_cast<int>(num_iov)));
return HANDLE_EINTR(writev(h.get().handle, iov, static_cast<int>(num_iov)));
#else
struct msghdr msg = {};
msg.msg_iov = iov;
msg.msg_iovlen = num_iov;
return HANDLE_EINTR(sendmsg(h.handle, &msg, kSendFlags));
return HANDLE_EINTR(sendmsg(h.get().handle, &msg, kSendFlags));
#endif
}
ssize_t PlatformChannelSendmsgWithHandles(PlatformHandle h,
struct iovec* iov,
size_t num_iov,
PlatformHandle* platform_handles,
size_t num_platform_handles) {
ssize_t PlatformChannelSendmsgWithHandles(
const ScopedPlatformHandle& h,
struct iovec* iov,
size_t num_iov,
const std::vector<ScopedPlatformHandle>& platform_handles) {
DCHECK(iov);
DCHECK_GT(num_iov, 0u);
DCHECK(platform_handles);
DCHECK_GT(num_platform_handles, 0u);
DCHECK_LE(num_platform_handles, kPlatformChannelMaxNumHandles);
DCHECK(!platform_handles.empty());
DCHECK_LE(platform_handles.size(), kPlatformChannelMaxNumHandles);
char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))];
struct msghdr msg = {};
msg.msg_iov = iov;
msg.msg_iovlen = num_iov;
msg.msg_control = cmsg_buf;
msg.msg_controllen = CMSG_LEN(num_platform_handles * sizeof(int));
msg.msg_controllen = CMSG_LEN(platform_handles.size() * sizeof(int));
struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(num_platform_handles * sizeof(int));
for (size_t i = 0; i < num_platform_handles; i++) {
cmsg->cmsg_len = CMSG_LEN(platform_handles.size() * sizeof(int));
for (size_t i = 0; i < platform_handles.size(); i++) {
DCHECK(platform_handles[i].is_valid());
reinterpret_cast<int*>(CMSG_DATA(cmsg))[i] = platform_handles[i].handle;
}
return HANDLE_EINTR(sendmsg(h.handle, &msg, kSendFlags));
}
bool PlatformChannelSendHandles(PlatformHandle h,
PlatformHandle* handles,
size_t num_handles) {
DCHECK(handles);
DCHECK_GT(num_handles, 0u);
DCHECK_LE(num_handles, kPlatformChannelMaxNumHandles);
// Note: |sendmsg()| fails on Mac if we don't write at least one character.
struct iovec iov = {const_cast<char*>(""), 1};
char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))];
struct msghdr msg = {};
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = cmsg_buf;
msg.msg_controllen = CMSG_LEN(num_handles * sizeof(int));
struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(num_handles * sizeof(int));
for (size_t i = 0; i < num_handles; i++) {
DCHECK(handles[i].is_valid());
reinterpret_cast<int*>(CMSG_DATA(cmsg))[i] = handles[i].handle;
reinterpret_cast<int*>(CMSG_DATA(cmsg))[i] =
platform_handles[i].get().handle;
}
ssize_t result = HANDLE_EINTR(sendmsg(h.handle, &msg, kSendFlags));
if (result < 1) {
DCHECK_EQ(result, -1);
return false;
}
for (size_t i = 0; i < num_handles; i++)
handles[i].CloseIfNecessary();
return true;
return HANDLE_EINTR(sendmsg(h.get().handle, &msg, kSendFlags));
}
ssize_t PlatformChannelRecvmsg(
PlatformHandle h,
const ScopedPlatformHandle& h,
void* buf,
size_t num_bytes,
base::circular_deque<PlatformHandle>* platform_handles,
base::circular_deque<ScopedPlatformHandle>* platform_handles,
bool block) {
DCHECK(buf);
DCHECK_GT(num_bytes, 0u);
......@@ -221,7 +186,7 @@ ssize_t PlatformChannelRecvmsg(
msg.msg_controllen = sizeof(cmsg_buf);
ssize_t result =
HANDLE_EINTR(recvmsg(h.handle, &msg, block ? 0 : MSG_DONTWAIT));
HANDLE_EINTR(recvmsg(h.get().handle, &msg, block ? 0 : MSG_DONTWAIT));
if (result < 0)
return result;
......@@ -239,7 +204,8 @@ ssize_t PlatformChannelRecvmsg(
size_t num_fds = payload_length / sizeof(int);
const int* fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
for (size_t i = 0; i < num_fds; i++) {
platform_handles->push_back(PlatformHandle(fds[i]));
platform_handles->push_back(
ScopedPlatformHandle(PlatformHandle(fds[i])));
DCHECK(platform_handles->back().is_valid());
}
}
......@@ -248,7 +214,7 @@ ssize_t PlatformChannelRecvmsg(
return result;
}
bool ServerAcceptConnection(PlatformHandle server_handle,
bool ServerAcceptConnection(const ScopedPlatformHandle& server_handle,
ScopedPlatformHandle* connection_handle,
bool check_peer_user) {
DCHECK(server_handle.is_valid());
......@@ -257,8 +223,8 @@ bool ServerAcceptConnection(PlatformHandle server_handle,
NOTREACHED();
return false;
#else
ScopedPlatformHandle accept_handle(
PlatformHandle(HANDLE_EINTR(accept(server_handle.handle, NULL, 0))));
ScopedPlatformHandle accept_handle(PlatformHandle(
HANDLE_EINTR(accept(server_handle.get().handle, NULL, 0))));
if (!accept_handle.is_valid())
return IsRecoverableError();
......
......@@ -8,10 +8,11 @@
#include <stddef.h>
#include <sys/types.h> // For |ssize_t|.
#include <memory>
#include <vector>
#include "base/containers/queue.h"
#include "base/containers/circular_deque.h"
#include "mojo/edk/embedder/platform_handle.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/system_impl_export.h"
struct iovec; // Declared in <sys/uio.h>.
......@@ -30,9 +31,13 @@ const size_t kPlatformChannelMaxNumHandles = 128;
// never raise |SIGPIPE|. (Note: On Mac, the suppression of |SIGPIPE| is set up
// by |PlatformChannelPair|.)
MOJO_SYSTEM_IMPL_EXPORT ssize_t
PlatformChannelWrite(PlatformHandle h, const void* bytes, size_t num_bytes);
PlatformChannelWrite(const ScopedPlatformHandle& h,
const void* bytes,
size_t num_bytes);
MOJO_SYSTEM_IMPL_EXPORT ssize_t
PlatformChannelWritev(PlatformHandle h, struct iovec* iov, size_t num_iov);
PlatformChannelWritev(const ScopedPlatformHandle& h,
struct iovec* iov,
size_t num_iov);
// Writes data, and the given set of |PlatformHandle|s (i.e., file descriptors)
// over the Unix domain socket given by |h| (e.g., created using
......@@ -42,34 +47,21 @@ PlatformChannelWritev(PlatformHandle h, struct iovec* iov, size_t num_iov);
// bytes of data sent on success (note that this may not be all the data
// specified by |iov|). (The handles are not closed, regardless of success or
// failure.)
MOJO_SYSTEM_IMPL_EXPORT ssize_t
PlatformChannelSendmsgWithHandles(PlatformHandle h,
struct iovec* iov,
size_t num_iov,
PlatformHandle* platform_handles,
size_t num_platform_handles);
// TODO(vtl): Remove this once I've switched things over to
// |PlatformChannelSendmsgWithHandles()|.
// Sends |PlatformHandle|s (i.e., file descriptors) over the Unix domain socket
// (e.g., created using PlatformChannelPair|). (These will be sent in a single
// message having one null byte of data and one control message header with all
// the file descriptors.) All of the handles must be valid, and there must be at
// most |kPlatformChannelMaxNumHandles| (and at least one handle). Returns true
// on success, in which case it closes all the handles.
MOJO_SYSTEM_IMPL_EXPORT bool PlatformChannelSendHandles(PlatformHandle h,
PlatformHandle* handles,
size_t num_handles);
MOJO_SYSTEM_IMPL_EXPORT ssize_t PlatformChannelSendmsgWithHandles(
const ScopedPlatformHandle& h,
struct iovec* iov,
size_t num_iov,
const std::vector<ScopedPlatformHandle>& platform_handles);
// Wrapper around |recvmsg()|, which will extract any attached file descriptors
// (in the control message) to |PlatformHandle|s (and append them to
// |platform_handles|). (This also handles |EINTR|.)
MOJO_SYSTEM_IMPL_EXPORT ssize_t
PlatformChannelRecvmsg(PlatformHandle h,
void* buf,
size_t num_bytes,
base::circular_deque<PlatformHandle>* platform_handles,
bool block = false);
MOJO_SYSTEM_IMPL_EXPORT ssize_t PlatformChannelRecvmsg(
const ScopedPlatformHandle& h,
void* buf,
size_t num_bytes,
base::circular_deque<ScopedPlatformHandle>* platform_handles,
bool block = false);
// Returns false if |server_handle| encounters an unrecoverable error.
// Returns true if it's valid to keep listening on |server_handle|. In this
......@@ -77,7 +69,7 @@ PlatformChannelRecvmsg(PlatformHandle h,
// |connection_handle| will be invalid. If |check_peer_user| is True, the
// connection will be rejected if the peer is running as a different user.
MOJO_SYSTEM_IMPL_EXPORT bool ServerAcceptConnection(
PlatformHandle server_handle,
const ScopedPlatformHandle& server_handle,
ScopedPlatformHandle* connection_handle,
bool check_peer_user = true);
......
// Copyright 2014 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 MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_
#define MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_
#include <memory>
#include <vector>
#include "mojo/edk/embedder/platform_handle.h"
#include "mojo/edk/embedder/platform_handle_utils.h"
#include "mojo/edk/system/system_impl_export.h"
namespace mojo {
namespace edk {
using PlatformHandleVector = std::vector<PlatformHandle>;
// A deleter (for use with |scoped_ptr|) which closes all handles and then
// |delete|s the |PlatformHandleVector|.
struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandleVectorDeleter {
void operator()(PlatformHandleVector* platform_handles) const {
CloseAllPlatformHandles(platform_handles);
delete platform_handles;
}
};
using ScopedPlatformHandleVectorPtr =
std::unique_ptr<PlatformHandleVector, PlatformHandleVectorDeleter>;
} // namespace edk
} // namespace mojo
#endif // MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_
......@@ -31,6 +31,7 @@ class MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle {
}
const PlatformHandle& get() const { return handle_; }
PlatformHandle& get() { return handle_; }
void swap(ScopedPlatformHandle& other) {
PlatformHandle temp = handle_;
......
......@@ -12,8 +12,8 @@
#include "base/threading/thread_task_runner_handle.h"
#include "mojo/edk/embedder/named_platform_channel_pair.h"
#include "mojo/edk/embedder/named_platform_handle.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/broker_messages.h"
namespace mojo {
......@@ -47,7 +47,8 @@ BrokerHost::~BrokerHost() {
channel_->ShutDown();
}
bool BrokerHost::PrepareHandlesForClient(PlatformHandleVector* handles) {
bool BrokerHost::PrepareHandlesForClient(
std::vector<ScopedPlatformHandle>* handles) {
#if defined(OS_WIN)
if (!Channel::Message::RewriteHandles(base::GetCurrentProcessHandle(),
client_process_, handles)) {
......@@ -74,13 +75,12 @@ bool BrokerHost::SendChannel(ScopedPlatformHandle handle) {
Channel::MessagePtr message =
CreateBrokerMessage(BrokerMessageType::INIT, 1, nullptr);
#endif
ScopedPlatformHandleVectorPtr handles;
handles.reset(new PlatformHandleVector(1));
handles->at(0) = handle.release();
std::vector<ScopedPlatformHandle> handles(1);
handles[0] = std::move(handle);
// This may legitimately fail on Windows if the client process is in another
// session, e.g., is an elevated process.
if (!PrepareHandlesForClient(handles.get()))
if (!PrepareHandlesForClient(&handles))
return false;
message->SetHandles(std::move(handles));
......@@ -119,11 +119,10 @@ void BrokerHost::OnBufferRequest(uint32_t num_bytes) {
base::UnguessableToken guid = buffer->GetGUID();
response->guid_high = guid.GetHighForSerialization();
response->guid_low = guid.GetLowForSerialization();
ScopedPlatformHandleVectorPtr handles;
handles.reset(new PlatformHandleVector(2));
handles->at(0) = buffer->PassPlatformHandle().release();
handles->at(1) = read_only_buffer->PassPlatformHandle().release();
PrepareHandlesForClient(handles.get());
std::vector<ScopedPlatformHandle> handles(2);
handles[0] = buffer->PassPlatformHandle();
handles[1] = read_only_buffer->PassPlatformHandle();
PrepareHandlesForClient(&handles);
message->SetHandles(std::move(handles));
}
......@@ -132,7 +131,7 @@ void BrokerHost::OnBufferRequest(uint32_t num_bytes) {
void BrokerHost::OnChannelMessage(const void* payload,
size_t payload_size,
ScopedPlatformHandleVectorPtr handles) {
std::vector<ScopedPlatformHandle> handles) {
if (payload_size < sizeof(BrokerMessageHeader))
return;
......
......@@ -6,13 +6,13 @@
#define MOJO_EDK_SYSTEM_BROKER_HOST_H_
#include <stdint.h>
#include <vector>
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/process/process_handle.h"
#include "base/strings/string_piece.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/channel.h"
......@@ -39,12 +39,12 @@ class BrokerHost : public Channel::Delegate,
private:
~BrokerHost() override;
bool PrepareHandlesForClient(PlatformHandleVector* handles);
bool PrepareHandlesForClient(std::vector<ScopedPlatformHandle>* handles);
// Channel::Delegate:
void OnChannelMessage(const void* payload,
size_t payload_size,
ScopedPlatformHandleVectorPtr handles) override;
std::vector<ScopedPlatformHandle> handles) override;
void OnChannelError(Channel::Error error) override;
// base::MessageLoop::DestructionObserver:
......
......@@ -13,8 +13,8 @@
#include "mojo/edk/embedder/embedder_internal.h"
#include "mojo/edk/embedder/platform_channel_utils_posix.h"
#include "mojo/edk/embedder/platform_handle_utils.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/broker_messages.h"
#include "mojo/edk/system/channel.h"
......@@ -24,14 +24,14 @@ namespace edk {
namespace {
Channel::MessagePtr WaitForBrokerMessage(
PlatformHandle platform_handle,
const ScopedPlatformHandle& platform_handle,
BrokerMessageType expected_type,
size_t expected_num_handles,
size_t expected_data_size,
base::circular_deque<PlatformHandle>* incoming_handles) {
std::vector<ScopedPlatformHandle>* incoming_handles) {
Channel::MessagePtr message(new Channel::Message(
sizeof(BrokerMessageHeader) + expected_data_size, expected_num_handles));
base::circular_deque<PlatformHandle> incoming_platform_handles;
base::circular_deque<ScopedPlatformHandle> incoming_platform_handles;
ssize_t read_result = PlatformChannelRecvmsg(
platform_handle, const_cast<void*>(message->data()),
message->data_num_bytes(), &incoming_platform_handles, true /* block */);
......@@ -47,24 +47,20 @@ Channel::MessagePtr WaitForBrokerMessage(
error = true;
}
if (!error) {
const BrokerMessageHeader* header =
reinterpret_cast<const BrokerMessageHeader*>(message->payload());
if (header->type != expected_type) {
LOG(ERROR) << "Unexpected message";
error = true;
}
}
if (error)
return nullptr;
if (error) {
CloseAllPlatformHandles(&incoming_platform_handles);
} else {
if (incoming_handles)
incoming_handles->swap(incoming_platform_handles);
const BrokerMessageHeader* header =
reinterpret_cast<const BrokerMessageHeader*>(message->payload());
if (header->type != expected_type) {
LOG(ERROR) << "Unexpected message";
return nullptr;
}
if (error)
return nullptr;
incoming_handles->resize(incoming_platform_handles.size());
std::move(incoming_platform_handles.begin(), incoming_platform_handles.end(),
incoming_handles->begin());
return message;
}
......@@ -81,10 +77,10 @@ Broker::Broker(ScopedPlatformHandle platform_handle)
PCHECK(flags != -1);
// Wait for the first message, which should contain a handle.
base::circular_deque<PlatformHandle> incoming_platform_handles;
if (WaitForBrokerMessage(sync_channel_.get(), BrokerMessageType::INIT, 1, 0,
std::vector<ScopedPlatformHandle> incoming_platform_handles;
if (WaitForBrokerMessage(sync_channel_, BrokerMessageType::INIT, 1, 0,
&incoming_platform_handles)) {
parent_channel_ = ScopedPlatformHandle(incoming_platform_handles.front());
parent_channel_ = std::move(incoming_platform_handles[0]);
}
}
......@@ -102,7 +98,7 @@ scoped_refptr<PlatformSharedBuffer> Broker::GetSharedBuffer(size_t num_bytes) {
BrokerMessageType::BUFFER_REQUEST, 0, 0, &buffer_request);
buffer_request->size = num_bytes;
ssize_t write_result = PlatformChannelWrite(
sync_channel_.get(), out_message->data(), out_message->data_num_bytes());
sync_channel_, out_message->data(), out_message->data_num_bytes());
if (write_result < 0) {
PLOG(ERROR) << "Error sending sync broker message";
return nullptr;
......@@ -112,9 +108,9 @@ scoped_refptr<PlatformSharedBuffer> Broker::GetSharedBuffer(size_t num_bytes) {
return nullptr;
}
base::circular_deque<PlatformHandle> incoming_platform_handles;
std::vector<ScopedPlatformHandle> incoming_platform_handles;
Channel::MessagePtr message = WaitForBrokerMessage(
sync_channel_.get(), BrokerMessageType::BUFFER_RESPONSE, 2,
sync_channel_, BrokerMessageType::BUFFER_RESPONSE, 2,
sizeof(BufferResponseData), &incoming_platform_handles);
if (message) {
const BufferResponseData* data;
......@@ -122,11 +118,9 @@ scoped_refptr<PlatformSharedBuffer> Broker::GetSharedBuffer(size_t num_bytes) {
return nullptr;
base::UnguessableToken guid =
base::UnguessableToken::Deserialize(data->guid_high, data->guid_low);
ScopedPlatformHandle rw_handle(incoming_platform_handles.front());
incoming_platform_handles.pop_front();
ScopedPlatformHandle ro_handle(incoming_platform_handles.front());
return PlatformSharedBuffer::CreateFromPlatformHandlePair(
num_bytes, guid, std::move(rw_handle), std::move(ro_handle));
num_bytes, guid, std::move(incoming_platform_handles[0]),
std::move(incoming_platform_handles[1]));
}
return nullptr;
......
......@@ -13,8 +13,8 @@
#include "mojo/edk/embedder/named_platform_handle.h"
#include "mojo/edk/embedder/named_platform_handle_utils.h"
#include "mojo/edk/embedder/platform_handle.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/broker.h"
#include "mojo/edk/system/broker_messages.h"
#include "mojo/edk/system/channel.h"
......@@ -35,14 +35,12 @@ bool TakeHandlesFromBrokerMessage(Channel::Message* message,
return false;
}
ScopedPlatformHandleVectorPtr handles = message->TakeHandles();
DCHECK(handles);
DCHECK_EQ(handles->size(), num_handles);
std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
DCHECK_EQ(handles.size(), num_handles);
DCHECK(out_handles);
for (size_t i = 0; i < num_handles; ++i)
out_handles[i] = ScopedPlatformHandle((*handles)[i]);
handles->clear();
out_handles[i] = std::move(handles[i]);
return true;
}
......
......@@ -251,10 +251,10 @@ Channel::MessagePtr Channel::Message::Deserialize(const void* data,
}
#if defined(OS_WIN)
ScopedPlatformHandleVectorPtr handles(new PlatformHandleVector(num_handles));
std::vector<ScopedPlatformHandle> handles(num_handles);
for (size_t i = 0; i < num_handles; i++) {
(*handles)[i].handle =
base::win::Uint32ToHandle(message->handles_[i].handle);
handles[i] = ScopedPlatformHandle(
PlatformHandle(base::win::Uint32ToHandle(message->handles_[i].handle)));
}
message->SetHandles(std::move(handles));
#endif
......@@ -343,9 +343,9 @@ bool Channel::Message::has_mach_ports() const {
if (!has_handles())
return false;
for (const auto& handle : (*handle_vector_)) {
if (handle.type == PlatformHandle::Type::MACH ||
handle.type == PlatformHandle::Type::MACH_NAME) {
for (const auto& handle : handle_vector_) {
if (handle.get().type == PlatformHandle::Type::MACH ||
handle.get().type == PlatformHandle::Type::MACH_NAME) {
return true;
}
}
......@@ -366,30 +366,32 @@ Channel::Message::Header* Channel::Message::header() const {
return reinterpret_cast<Header*>(data_);
}
void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) {
void Channel::Message::SetHandles(
std::vector<ScopedPlatformHandle> new_handles) {
if (is_legacy_message()) {
// Old semantics for ChromeOS and Android
if (legacy_header()->num_handles == 0) {
CHECK(!new_handles || new_handles->size() == 0);
CHECK(new_handles.empty());
return;
}
CHECK(new_handles && new_handles->size() == legacy_header()->num_handles);
CHECK_EQ(new_handles.size(), legacy_header()->num_handles);
std::swap(handle_vector_, new_handles);
return;
}
if (max_handles_ == 0) {
CHECK(!new_handles || new_handles->size() == 0);
CHECK(new_handles.empty());
return;
}
CHECK(new_handles && new_handles->size() <= max_handles_);
header()->num_handles = static_cast<uint16_t>(new_handles->size());
CHECK_LE(new_handles.size(), max_handles_);
header()->num_handles = static_cast<uint16_t>(new_handles.size());
std::swap(handle_vector_, new_handles);
#if defined(OS_WIN)
memset(handles_, 0, extra_header_size());
for (size_t i = 0; i < handle_vector_->size(); i++)
handles_[i].handle = base::win::HandleToUint32((*handle_vector_)[i].handle);
for (size_t i = 0; i < handle_vector_.size(); i++)
handles_[i].handle =
base::win::HandleToUint32(handle_vector_[i].get().handle);
#endif // defined(OS_WIN)
#if defined(OS_MACOSX) && !defined(OS_IOS)
......@@ -399,10 +401,10 @@ void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) {
mach_ports_header_->entries[i] =
{0, static_cast<uint32_t>(MACH_PORT_NULL)};
}
for (size_t i = 0; i < handle_vector_->size(); i++) {
if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH ||
(*handle_vector_)[i].type == PlatformHandle::Type::MACH_NAME) {
mach_port_t port = (*handle_vector_)[i].port;
for (size_t i = 0; i < handle_vector_.size(); i++) {
if (handle_vector_[i].get().type == PlatformHandle::Type::MACH ||
handle_vector_[i].get().type == PlatformHandle::Type::MACH_NAME) {
mach_port_t port = handle_vector_[i].get().port;
mach_ports_header_->entries[mach_port_index].index = i;
mach_ports_header_->entries[mach_port_index].mach_port = port;
mach_port_index++;
......@@ -413,7 +415,7 @@ void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) {
#endif
}
ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() {
std::vector<ScopedPlatformHandle> Channel::Message::TakeHandles() {
#if defined(OS_MACOSX) && !defined(OS_IOS)
if (mach_ports_header_) {
for (size_t i = 0; i < max_handles_; ++i) {
......@@ -430,23 +432,25 @@ ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() {
return std::move(handle_vector_);
}
ScopedPlatformHandleVectorPtr Channel::Message::TakeHandlesForTransport() {
std::vector<ScopedPlatformHandle> Channel::Message::TakeHandlesForTransport() {
#if defined(OS_WIN)
// Not necessary on Windows.
NOTREACHED();
return nullptr;
return std::vector<ScopedPlatformHandle>();
#elif defined(OS_MACOSX) && !defined(OS_IOS)
if (handle_vector_) {
for (auto it = handle_vector_->begin(); it != handle_vector_->end(); ) {
if (it->type == PlatformHandle::Type::MACH ||
it->type == PlatformHandle::Type::MACH_NAME) {
// For Mach port names, we can can just leak them. They're not real
// ports anyways. For real ports, they're leaked because this is a child
// process and the remote process will take ownership.
it = handle_vector_->erase(it);
} else {
++it;
}
for (auto it = handle_vector_.begin(); it != handle_vector_.end();) {
if (it->get().type == PlatformHandle::Type::MACH ||
it->get().type == PlatformHandle::Type::MACH_NAME) {
// For Mach port names, we can can just leak them. They're not real
// ports anyways. For real ports, they're leaked because this is a child
// process and the remote process will take ownership.
// TODO(wez): Removing Mach ports here because they are delivered
// out-of-band seems strange; could this be properly hidden inside the
// Mac-specific Channel impl?
ignore_result(it->release());
it = handle_vector_.erase(it);
} else {
++it;
}
}
return std::move(handle_vector_);
......@@ -457,30 +461,31 @@ ScopedPlatformHandleVectorPtr Channel::Message::TakeHandlesForTransport() {
#if defined(OS_WIN)
// static
bool Channel::Message::RewriteHandles(base::ProcessHandle from_process,
base::ProcessHandle to_process,
PlatformHandleVector* handles) {
bool Channel::Message::RewriteHandles(
base::ProcessHandle from_process,
base::ProcessHandle to_process,
std::vector<ScopedPlatformHandle>* handles) {
bool success = true;
for (size_t i = 0; i < handles->size(); ++i) {
if (!(*handles)[i].is_valid()) {
DLOG(ERROR) << "Refusing to duplicate invalid handle.";
continue;
}
DCHECK_EQ((*handles)[i].owning_process, from_process);
BOOL result = DuplicateHandle(
from_process, (*handles)[i].handle, to_process,
&(*handles)[i].handle, 0, FALSE,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
DCHECK_EQ((*handles)[i].get().owning_process, from_process);
BOOL result =
DuplicateHandle(from_process, (*handles)[i].get().handle, to_process,
&(*handles)[i].get().handle, 0, FALSE,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
if (result) {
(*handles)[i].owning_process = to_process;
(*handles)[i].get().owning_process = to_process;
} else {
success = false;
// If handle duplication fails, the source handle will already be closed
// due to DUPLICATE_CLOSE_SOURCE. Replace the handle in the message with
// an invalid handle.
(*handles)[i].handle = INVALID_HANDLE_VALUE;
(*handles)[i].owning_process = base::GetCurrentProcessHandle();
(*handles)[i].get().handle = INVALID_HANDLE_VALUE;
(*handles)[i].get().owning_process = base::GetCurrentProcessHandle();
}
}
return success;
......@@ -695,14 +700,14 @@ bool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) {
const uint16_t num_handles =
header ? header->num_handles : legacy_header->num_handles;
ScopedPlatformHandleVectorPtr handles;
std::vector<ScopedPlatformHandle> handles;
if (num_handles > 0) {
if (!GetReadPlatformHandles(num_handles, extra_header, extra_header_size,
&handles)) {
return false;
}
if (!handles) {
if (handles.empty()) {
// Not enough handles available for this message.
break;
}
......@@ -736,7 +741,7 @@ void Channel::OnError(Error error) {
bool Channel::OnControlMessage(Message::MessageType message_type,
const void* payload,
size_t payload_size,
ScopedPlatformHandleVectorPtr handles) {
std::vector<ScopedPlatformHandle> handles) {
return false;
}
......
......@@ -5,14 +5,14 @@
#ifndef MOJO_EDK_SYSTEM_CHANNEL_H_
#define MOJO_EDK_SYSTEM_CHANNEL_H_
#include "base/logging.h"
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/process/process_handle.h"
#include "base/task_runner.h"
#include "build/build_config.h"
#include "mojo/edk/embedder/connection_params.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
namespace mojo {
......@@ -179,13 +179,13 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// Note: SetHandles() and TakeHandles() invalidate any previous value of
// handles().
void SetHandles(ScopedPlatformHandleVectorPtr new_handles);
ScopedPlatformHandleVectorPtr TakeHandles();
void SetHandles(std::vector<ScopedPlatformHandle> new_handles);
std::vector<ScopedPlatformHandle> TakeHandles();
// Version of TakeHandles that returns a vector of platform handles suitable
// for transfer over an underlying OS mechanism. i.e. file descriptors over
// a unix domain socket. Any handle that cannot be transferred this way,
// such as Mach ports, will be removed.
ScopedPlatformHandleVectorPtr TakeHandlesForTransport();
std::vector<ScopedPlatformHandle> TakeHandlesForTransport();
#if defined(OS_WIN)
// Prepares the handles in this message for use in a different process.
......@@ -195,7 +195,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// duplication.
static bool RewriteHandles(base::ProcessHandle from_process,
base::ProcessHandle to_process,
PlatformHandleVector* handles);
std::vector<ScopedPlatformHandle>* handles);
#endif
void SetVersionForTest(uint16_t version_number);
......@@ -215,7 +215,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// Maximum number of handles which may be attached to this message.
size_t max_handles_ = 0;
ScopedPlatformHandleVectorPtr handle_vector_;
std::vector<ScopedPlatformHandle> handle_vector_;
#if defined(OS_WIN)
// On Windows, handles are serialised into the extra header section.
......@@ -252,9 +252,10 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// Notify of a received message. |payload| is not owned and must not be
// retained; it will be null if |payload_size| is 0. |handles| are
// transferred to the callee.
virtual void OnChannelMessage(const void* payload,
size_t payload_size,
ScopedPlatformHandleVectorPtr handles) = 0;
virtual void OnChannelMessage(
const void* payload,
size_t payload_size,
std::vector<ScopedPlatformHandle> handles) = 0;
// Notify that an error has occured and the Channel will cease operation.
virtual void OnChannelError(Error error) = 0;
......@@ -329,14 +330,14 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
size_t num_handles,
const void* extra_header,
size_t extra_header_size,
ScopedPlatformHandleVectorPtr* handles) = 0;
std::vector<ScopedPlatformHandle>* handles) = 0;
// Handles a received control message. Returns |true| if the message is
// accepted, or |false| otherwise.
virtual bool OnControlMessage(Message::MessageType message_type,
const void* payload,
size_t payload_size,
ScopedPlatformHandleVectorPtr handles);
std::vector<ScopedPlatformHandle> handles);
private:
friend class base::RefCountedThreadSafe<Channel>;
......
......@@ -15,12 +15,12 @@
#include "base/containers/circular_deque.h"
#include "base/files/scoped_file.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/synchronization/lock.h"
#include "base/task_runner.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
namespace mojo {
namespace edk {
......@@ -31,12 +31,12 @@ const size_t kMaxBatchReadCapacity = 256 * 1024;
bool UnwrapPlatformHandle(ScopedPlatformHandle handle,
Channel::Message::HandleInfoEntry* info_out,
PlatformHandleVector* handles_out) {
std::vector<ScopedPlatformHandle>* handles_out) {
DCHECK(handle.get().is_valid());
if (!handle.get().is_valid_fd()) {
*info_out = {0u, 0u};
handles_out->emplace_back(handle.release());
handles_out->emplace_back(std::move(handle));
return true;
}
......@@ -72,7 +72,7 @@ bool UnwrapPlatformHandle(ScopedPlatformHandle handle,
for (int i = 0; i < result; ++i) {
DCHECK_EQ(PA_HND_TYPE(info[0]), PA_HND_TYPE(info[i]));
DCHECK_EQ(0u, PA_HND_SUBTYPE(info[i]));
handles_out->push_back(PlatformHandle::ForHandle(handles[i]));
handles_out->emplace_back(PlatformHandle::ForHandle(handles[i]));
}
return true;
......@@ -153,26 +153,23 @@ class MessageView {
offset_ += num_bytes;
}
ScopedPlatformHandleVectorPtr TakeHandles() {
if (handles_) {
// We can only pass Fuchsia handles via IPC, so unwrap any FDIO file-
// descriptors in |handles_| into the underlying handles, and serialize
// the metadata, if any, into the extra header.
auto* handles_info = reinterpret_cast<Channel::Message::HandleInfoEntry*>(
message_->mutable_extra_header());
memset(handles_info, 0, message_->extra_header_size());
ScopedPlatformHandleVectorPtr in_handles(std::move(handles_));
handles_.reset(new PlatformHandleVector);
handles_->reserve(in_handles->size());
for (size_t i = 0; i < in_handles->size(); i++) {
ScopedPlatformHandle old_handle((*in_handles)[i]);
(*in_handles)[i] = PlatformHandle();
if (!UnwrapPlatformHandle(std::move(old_handle), &handles_info[i],
handles_.get()))
return nullptr;
}
std::vector<ScopedPlatformHandle> TakeHandles() {
if (handles_.empty())
return std::vector<ScopedPlatformHandle>();
// We can only pass Fuchsia handles via IPC, so unwrap any FDIO file-
// descriptors in |handles_| into the underlying handles, and serialize the
// metadata, if any, into the extra header.
auto* handles_info = reinterpret_cast<Channel::Message::HandleInfoEntry*>(
message_->mutable_extra_header());
memset(handles_info, 0, message_->extra_header_size());
std::vector<ScopedPlatformHandle> in_handles = std::move(handles_);
handles_.reserve(in_handles.size());
for (size_t i = 0; i < in_handles.size(); i++) {
if (!UnwrapPlatformHandle(std::move(in_handles[i]), &handles_info[i],
&handles_))
return std::vector<ScopedPlatformHandle>();
}
return std::move(handles_);
}
......@@ -180,7 +177,7 @@ class MessageView {
private:
Channel::MessagePtr message_;
size_t offset_;
ScopedPlatformHandleVectorPtr handles_;
std::vector<ScopedPlatformHandle> handles_;
DISALLOW_COPY_AND_ASSIGN(MessageView);
};
......@@ -237,10 +234,11 @@ class ChannelFuchsia : public Channel,
leak_handle_ = true;
}
bool GetReadPlatformHandles(size_t num_handles,
const void* extra_header,
size_t extra_header_size,
ScopedPlatformHandleVectorPtr* handles) override {
bool GetReadPlatformHandles(
size_t num_handles,
const void* extra_header,
size_t extra_header_size,
std::vector<ScopedPlatformHandle>* handles) override {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
if (num_handles > std::numeric_limits<uint16_t>::max())
return false;
......@@ -268,10 +266,9 @@ class ChannelFuchsia : public Channel,
if (incoming_handles_.size() < num_raw_handles)
return true;
handles->reset(new PlatformHandleVector);
(*handles)->reserve(num_handles);
handles->reserve(num_handles);
for (size_t i = 0; i < num_handles; ++i) {
(*handles)->push_back(
handles->emplace_back(
WrapPlatformHandles(handles_info[i], &incoming_handles_).release());
}
return true;
......@@ -379,18 +376,15 @@ class ChannelFuchsia : public Channel,
do {
message_view.advance_data_offset(write_bytes);
ScopedPlatformHandleVectorPtr outgoing_handles =
std::vector<ScopedPlatformHandle> outgoing_handles =
message_view.TakeHandles();
size_t handles_count = 0;
zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES] = {};
if (outgoing_handles) {
DCHECK_LE(outgoing_handles->size(), arraysize(handles));
size_t handles_count = outgoing_handles.size();
handles_count = outgoing_handles->size();
for (size_t i = 0; i < handles_count; ++i) {
DCHECK(outgoing_handles->data()[i].is_valid_handle());
handles[i] = outgoing_handles->data()[i].as_handle();
}
DCHECK_LE(handles_count, arraysize(handles));
for (size_t i = 0; i < handles_count; ++i) {
DCHECK(outgoing_handles[i].is_valid());
handles[i] = outgoing_handles[i].get().as_handle();
}
write_bytes = std::min(message_view.data_num_bytes(),
......@@ -407,13 +401,10 @@ class ChannelFuchsia : public Channel,
return false;
}
if (outgoing_handles) {
// |handles| have been transferred to the peer process, so clear them to
// avoid them being double-closed.
for (auto& outgoing_handle : *outgoing_handles) {
outgoing_handle = PlatformHandle();
}
}
// |handles| have been transferred to the peer process, so release()
// them, to avoid them being double-closed.
for (auto& outgoing_handle : outgoing_handles)
ignore_result(outgoing_handle.release());
} while (write_bytes < message_view.data_num_bytes());
return true;
......
This diff is collapsed.
......@@ -27,7 +27,7 @@ class TestChannel : public Channel {
bool(size_t num_handles,
const void* extra_header,
size_t extra_header_size,
ScopedPlatformHandleVectorPtr* handles));
std::vector<ScopedPlatformHandle>* handles));
MOCK_METHOD0(Start, void());
MOCK_METHOD0(ShutDownImpl, void());
MOCK_METHOD0(LeakHandle, void());
......@@ -50,7 +50,7 @@ class MockChannelDelegate : public Channel::Delegate {
protected:
void OnChannelMessage(const void* payload,
size_t payload_size,
ScopedPlatformHandleVectorPtr handles) override {
std::vector<ScopedPlatformHandle> handles) override {
payload_.reset(new char[payload_size]);
memcpy(payload_.get(), payload, payload_size);
payload_size_ = payload_size;
......
......@@ -20,7 +20,7 @@
#include "base/synchronization/lock.h"
#include "base/task_runner.h"
#include "base/win/win_util.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
namespace mojo {
namespace edk {
......@@ -127,20 +127,20 @@ class ChannelWin : public Channel,
size_t num_handles,
const void* extra_header,
size_t extra_header_size,
ScopedPlatformHandleVectorPtr* handles) override {
std::vector<ScopedPlatformHandle>* handles) override {
DCHECK(extra_header);
if (num_handles > std::numeric_limits<uint16_t>::max())
return false;
using HandleEntry = Channel::Message::HandleEntry;
size_t handles_size = sizeof(HandleEntry) * num_handles;
if (handles_size > extra_header_size)
return false;
DCHECK(extra_header);
handles->reset(new PlatformHandleVector(num_handles));
handles->reserve(num_handles);
const HandleEntry* extra_header_handles =
reinterpret_cast<const HandleEntry*>(extra_header);
for (size_t i = 0; i < num_handles; i++) {
(*handles)->at(i).handle =
base::win::Uint32ToHandle(extra_header_handles[i].handle);
handles->emplace_back(ScopedPlatformHandle(PlatformHandle(
base::win::Uint32ToHandle(extra_header_handles[i].handle))));
}
return true;
}
......@@ -268,9 +268,9 @@ class ChannelWin : public Channel,
outgoing_messages_.pop_front();
// Clear any handles so they don't get closed on destruction.
ScopedPlatformHandleVectorPtr handles = message->TakeHandles();
if (handles)
handles->clear();
std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
for (auto& handle : handles)
ignore_result(handle.release());
}
if (!WriteNextNoLock())
......
......@@ -305,7 +305,7 @@ void DataPipeConsumerDispatcher::StartSerialize(uint32_t* num_bytes,
bool DataPipeConsumerDispatcher::EndSerialize(
void* destination,
ports::PortName* ports,
PlatformHandle* platform_handles) {
ScopedPlatformHandle* platform_handles) {
SerializedState* state = static_cast<SerializedState*>(destination);
memcpy(&state->options, &options_, sizeof(MojoCreateDataPipeOptions));
memset(state->padding, 0, sizeof(state->padding));
......@@ -323,11 +323,10 @@ bool DataPipeConsumerDispatcher::EndSerialize(
ports[0] = control_port_.name();
buffer_handle_for_transit_ = shared_ring_buffer_->DuplicatePlatformHandle();
if (!buffer_handle_for_transit_.is_valid())
platform_handles[0] = shared_ring_buffer_->DuplicatePlatformHandle();
if (!platform_handles[0].is_valid())
return false;
platform_handles[0] = buffer_handle_for_transit_.get();
return true;
}
......@@ -346,7 +345,6 @@ void DataPipeConsumerDispatcher::CompleteTransitAndClose() {
DCHECK(in_transit_);
in_transit_ = false;
transferred_ = true;
ignore_result(buffer_handle_for_transit_.release());
CloseNoLock();
}
......@@ -354,7 +352,6 @@ void DataPipeConsumerDispatcher::CancelTransit() {
base::AutoLock lock(lock_);
DCHECK(in_transit_);
in_transit_ = false;
buffer_handle_for_transit_.reset();
UpdateSignalsStateNoLock();
}
......@@ -364,7 +361,7 @@ DataPipeConsumerDispatcher::Deserialize(const void* data,
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
PlatformHandle* handles,
ScopedPlatformHandle* handles,
size_t num_handles) {
if (num_ports != 1 || num_handles != 1 ||
num_bytes != sizeof(SerializedState)) {
......@@ -384,12 +381,12 @@ DataPipeConsumerDispatcher::Deserialize(const void* data,
base::UnguessableToken guid = base::UnguessableToken::Deserialize(
state->buffer_guid_high, state->buffer_guid_low);
PlatformHandle buffer_handle;
ScopedPlatformHandle buffer_handle;
std::swap(buffer_handle, handles[0]);
scoped_refptr<PlatformSharedBuffer> ring_buffer =
PlatformSharedBuffer::CreateFromPlatformHandle(
state->options.capacity_num_bytes, false /* read_only */, guid,
ScopedPlatformHandle(buffer_handle));
std::move(buffer_handle));
if (!ring_buffer) {
DLOG(ERROR) << "Failed to deserialize shared buffer handle.";
return nullptr;
......
......@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/dispatcher.h"
......@@ -59,7 +58,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final
uint32_t* num_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
PlatformHandle* handles) override;
ScopedPlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
......@@ -69,7 +68,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
PlatformHandle* handles,
ScopedPlatformHandle* handles,
size_t num_handles);
private:
......@@ -103,7 +102,6 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final
scoped_refptr<PlatformSharedBuffer> shared_ring_buffer_;
std::unique_ptr<PlatformSharedBufferMapping> ring_buffer_mapping_;
ScopedPlatformHandle buffer_handle_for_transit_;
bool in_two_phase_read_ = false;
uint32_t two_phase_max_bytes_read_ = 0;
......
......@@ -4,7 +4,7 @@
#include "mojo/edk/system/data_pipe_control_message.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/node_controller.h"
#include "mojo/edk/system/ports/event.h"
#include "mojo/edk/system/user_message_impl.h"
......
......@@ -266,7 +266,7 @@ void DataPipeProducerDispatcher::StartSerialize(uint32_t* num_bytes,
bool DataPipeProducerDispatcher::EndSerialize(
void* destination,
ports::PortName* ports,
PlatformHandle* platform_handles) {
ScopedPlatformHandle* platform_handles) {
SerializedState* state = static_cast<SerializedState*>(destination);
memcpy(&state->options, &options_, sizeof(MojoCreateDataPipeOptions));
memset(state->padding, 0, sizeof(state->padding));
......@@ -284,11 +284,10 @@ bool DataPipeProducerDispatcher::EndSerialize(
ports[0] = control_port_.name();
buffer_handle_for_transit_ = shared_ring_buffer_->DuplicatePlatformHandle();
if (!buffer_handle_for_transit_.is_valid())
platform_handles[0] = shared_ring_buffer_->DuplicatePlatformHandle();
if (!platform_handles[0].is_valid())
return false;
platform_handles[0] = buffer_handle_for_transit_.get();
return true;
}
......@@ -307,7 +306,6 @@ void DataPipeProducerDispatcher::CompleteTransitAndClose() {
DCHECK(in_transit_);
transferred_ = true;
in_transit_ = false;
ignore_result(buffer_handle_for_transit_.release());
CloseNoLock();
}
......@@ -315,7 +313,6 @@ void DataPipeProducerDispatcher::CancelTransit() {
base::AutoLock lock(lock_);
DCHECK(in_transit_);
in_transit_ = false;
buffer_handle_for_transit_.reset();
HandleSignalsState state = GetHandleSignalsStateNoLock();
watchers_.NotifyState(state);
......@@ -327,7 +324,7 @@ DataPipeProducerDispatcher::Deserialize(const void* data,
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
PlatformHandle* handles,
ScopedPlatformHandle* handles,
size_t num_handles) {
if (num_ports != 1 || num_handles != 1 ||
num_bytes != sizeof(SerializedState)) {
......@@ -347,12 +344,12 @@ DataPipeProducerDispatcher::Deserialize(const void* data,
base::UnguessableToken guid = base::UnguessableToken::Deserialize(
state->buffer_guid_high, state->buffer_guid_low);
PlatformHandle buffer_handle;
ScopedPlatformHandle buffer_handle;
std::swap(buffer_handle, handles[0]);
scoped_refptr<PlatformSharedBuffer> ring_buffer =
PlatformSharedBuffer::CreateFromPlatformHandle(
state->options.capacity_num_bytes, false /* read_only */, guid,
ScopedPlatformHandle(buffer_handle));
std::move(buffer_handle));
if (!ring_buffer) {
DLOG(ERROR) << "Failed to deserialize shared buffer handle.";
return nullptr;
......
......@@ -13,8 +13,8 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/ports/port_ref.h"
#include "mojo/edk/system/system_impl_export.h"
......@@ -23,7 +23,6 @@
namespace mojo {
namespace edk {
struct DataPipeControlMessage;
class NodeController;
// This is the Dispatcher implementation for the producer handle for data
......@@ -59,7 +58,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final
uint32_t* num_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
PlatformHandle* handles) override;
ScopedPlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
......@@ -69,7 +68,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
PlatformHandle* handles,
ScopedPlatformHandle* handles,
size_t num_handles);
private:
......@@ -91,8 +90,6 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final
void NotifyWrite(uint32_t num_bytes);
void OnPortStatusChanged();
void UpdateSignalsStateNoLock();
bool ProcessMessageNoLock(const DataPipeControlMessage& message,
ScopedPlatformHandleVectorPtr handles);
const MojoCreateDataPipeOptions options_;
NodeController* const node_controller_;
......@@ -108,7 +105,6 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final
scoped_refptr<PlatformSharedBuffer> shared_ring_buffer_;
std::unique_ptr<PlatformSharedBufferMapping> ring_buffer_mapping_;
ScopedPlatformHandle buffer_handle_for_transit_;
bool in_transit_ = false;
bool is_closed_ = false;
......
......@@ -142,7 +142,7 @@ void Dispatcher::StartSerialize(uint32_t* num_bytes,
bool Dispatcher::EndSerialize(void* destination,
ports::PortName* ports,
PlatformHandle* handles) {
ScopedPlatformHandle* handles) {
LOG(ERROR) << "Attempting to serialize a non-transferrable dispatcher.";
return true;
}
......@@ -162,7 +162,7 @@ scoped_refptr<Dispatcher> Dispatcher::Deserialize(
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
PlatformHandle* platform_handles,
ScopedPlatformHandle* platform_handles,
size_t num_platform_handles) {
switch (type) {
case Type::MESSAGE_PIPE:
......
......@@ -17,6 +17,7 @@
#include "base/synchronization/lock.h"
#include "mojo/edk/embedder/platform_handle.h"
#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/handle_signals_state.h"
#include "mojo/edk/system/ports/name.h"
#include "mojo/edk/system/system_impl_export.h"
......@@ -199,7 +200,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
// condition.
virtual bool EndSerialize(void* destination,
ports::PortName* ports,
PlatformHandle* handles);
ScopedPlatformHandle* handles);
// Does whatever is necessary to begin transit of the dispatcher. This
// should return |true| if transit is OK, or false if the underlying resource
......@@ -216,13 +217,14 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
virtual void CancelTransit();
// Deserializes a specific dispatcher type from an incoming message.
static scoped_refptr<Dispatcher> Deserialize(Type type,
const void* bytes,
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
PlatformHandle* platform_handles,
size_t num_platform_handles);
static scoped_refptr<Dispatcher> Deserialize(
Type type,
const void* bytes,
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
ScopedPlatformHandle* platform_handles,
size_t platform_handle_count);
protected:
friend class base::RefCountedThreadSafe<Dispatcher>;
......
......@@ -13,7 +13,7 @@
#include "base/mac/scoped_mach_port.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/process.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
namespace mojo {
namespace edk {
......@@ -65,33 +65,35 @@ void ReportChildError(ChildUMAError error) {
} // namespace
// static
void MachPortRelay::ReceivePorts(PlatformHandleVector* handles) {
void MachPortRelay::ReceivePorts(std::vector<ScopedPlatformHandle>* handles) {
DCHECK(handles);
for (size_t i = 0; i < handles->size(); i++) {
PlatformHandle* handle = handles->data() + i;
DCHECK(handle->type != PlatformHandle::Type::MACH);
if (handle->type != PlatformHandle::Type::MACH_NAME)
for (auto& handle : *handles) {
DCHECK(handle.get().type != PlatformHandle::Type::MACH);
if (handle.get().type != PlatformHandle::Type::MACH_NAME)
continue;
handle->type = PlatformHandle::Type::MACH;
handle.get().type = PlatformHandle::Type::MACH;
// MACH_PORT_NULL doesn't need translation.
if (handle->port == MACH_PORT_NULL)
if (handle.get().port == MACH_PORT_NULL)
continue;
base::mac::ScopedMachReceiveRight message_port(handle->port);
// TODO(wez): Wrapping handle.get().port in this way causes it to be
// Free()d via mach_port_mod_refs() - should PlatformHandle also do
// that if the handle never reaches here, or should this code not be
// wrapping it?
base::mac::ScopedMachReceiveRight message_port(handle.get().port);
base::mac::ScopedMachSendRight received_port(
base::ReceiveMachPort(message_port.get()));
if (received_port.get() == MACH_PORT_NULL) {
handle.get().port = received_port.release();
if (!handle.is_valid()) {
ReportChildError(ChildUMAError::ERROR_RECEIVE_MACH_MESSAGE);
handle->port = MACH_PORT_NULL;
DLOG(ERROR) << "Error receiving mach port";
continue;
}
ReportChildError(ChildUMAError::SUCCESS);
handle->port = received_port.release();
}
}
......@@ -110,18 +112,17 @@ void MachPortRelay::SendPortsToProcess(Channel::Message* message,
DCHECK(message);
mach_port_t task_port = port_provider_->TaskForPid(process);
ScopedPlatformHandleVectorPtr handles = message->TakeHandles();
std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
// Message should have handles, otherwise there's no point in calling this
// function.
DCHECK(handles);
for (size_t i = 0; i < handles->size(); i++) {
PlatformHandle* handle = &(*handles)[i];
DCHECK(handle->type != PlatformHandle::Type::MACH_NAME);
if (handle->type != PlatformHandle::Type::MACH)
DCHECK(!handles.empty());
for (auto& handle : handles) {
DCHECK(handle.get().type != PlatformHandle::Type::MACH_NAME);
if (handle.get().type != PlatformHandle::Type::MACH)
continue;
if (handle->port == MACH_PORT_NULL) {
handle->type = PlatformHandle::Type::MACH_NAME;
if (!handle.is_valid()) {
handle.get().type = PlatformHandle::Type::MACH_NAME;
continue;
}
......@@ -134,14 +135,17 @@ void MachPortRelay::SendPortsToProcess(Channel::Message* message,
// For MACH_PORT_NULL, use Type::MACH to indicate that no extraction is
// necessary.
handle->port = MACH_PORT_NULL;
// TODO(wez): But we're not setting Type::Mach... is the comment above
// out of date?
handle.get().port = MACH_PORT_NULL;
continue;
}
mach_port_name_t intermediate_port;
base::MachCreateError error_code;
intermediate_port = base::CreateIntermediateMachPort(
task_port, base::mac::ScopedMachSendRight(handle->port), &error_code);
task_port, base::mac::ScopedMachSendRight(handle.get().port),
&error_code);
if (intermediate_port == MACH_PORT_NULL) {
BrokerUMAError uma_error;
switch (error_code) {
......@@ -159,48 +163,48 @@ void MachPortRelay::SendPortsToProcess(Channel::Message* message,
break;
}
ReportBrokerError(uma_error);
handle->port = MACH_PORT_NULL;
handle.get().port = MACH_PORT_NULL;
continue;
}
ReportBrokerError(BrokerUMAError::SUCCESS);
handle->port = intermediate_port;
handle->type = PlatformHandle::Type::MACH_NAME;
handle.get().port = intermediate_port;
handle.get().type = PlatformHandle::Type::MACH_NAME;
}
message->SetHandles(std::move(handles));
}
void MachPortRelay::ExtractPort(PlatformHandle* handle,
void MachPortRelay::ExtractPort(ScopedPlatformHandle* handle,
base::ProcessHandle process) {
DCHECK_EQ(handle->type, PlatformHandle::Type::MACH_NAME);
handle->type = PlatformHandle::Type::MACH;
DCHECK_EQ(handle->get().type, PlatformHandle::Type::MACH_NAME);
handle->get().type = PlatformHandle::Type::MACH;
// No extraction necessary for MACH_PORT_NULL.
if (handle->port == MACH_PORT_NULL)
if (!handle->is_valid())
return;
mach_port_t task_port = port_provider_->TaskForPid(process);
if (task_port == MACH_PORT_NULL) {
ReportBrokerError(BrokerUMAError::ERROR_TASK_FOR_PID);
handle->port = MACH_PORT_NULL;
handle->get().port = MACH_PORT_NULL;
return;
}
mach_port_t extracted_right = MACH_PORT_NULL;
mach_msg_type_name_t extracted_right_type;
kern_return_t kr =
mach_port_extract_right(task_port, handle->port, MACH_MSG_TYPE_MOVE_SEND,
&extracted_right, &extracted_right_type);
kern_return_t kr = mach_port_extract_right(
task_port, handle->get().port, MACH_MSG_TYPE_MOVE_SEND, &extracted_right,
&extracted_right_type);
if (kr != KERN_SUCCESS) {
ReportBrokerError(BrokerUMAError::ERROR_EXTRACT_SOURCE_RIGHT);
handle->port = MACH_PORT_NULL;
handle->get().port = MACH_PORT_NULL;
return;
}
ReportBrokerError(BrokerUMAError::SUCCESS);
DCHECK_EQ(static_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_PORT_SEND),
extracted_right_type);
handle->port = extracted_right;
handle->get().port = extracted_right;
}
void MachPortRelay::AddObserver(Observer* observer) {
......
......@@ -6,6 +6,7 @@
#define MOJO_EDK_SYSTEM_MACH_PORT_RELAY_H_
#include <set>
#include <vector>
#include "base/macros.h"
#include "base/process/port_provider_mac.h"
......@@ -43,7 +44,7 @@ class MachPortRelay : public base::PortProvider::Observer {
//
// See SendPortsToProcess() for the definition of intermediate and final Mach
// ports.
static void ReceivePorts(PlatformHandleVector* handles);
static void ReceivePorts(std::vector<ScopedPlatformHandle>* handles);
explicit MachPortRelay(base::PortProvider* port_provider);
~MachPortRelay() override;
......@@ -62,7 +63,7 @@ class MachPortRelay : public base::PortProvider::Observer {
// updates the contents of the PlatformHandle to have Type::MACH and have the
// actual Mach port. On failure, replaces the contents with Type::MACH and
// MACH_PORT_NULL.
void ExtractPort(PlatformHandle* handle, base::ProcessHandle process);
void ExtractPort(ScopedPlatformHandle* handle, base::ProcessHandle process);
// Observer interface.
void AddObserver(Observer* observer);
......
......@@ -227,7 +227,7 @@ void MessagePipeDispatcher::StartSerialize(uint32_t* num_bytes,
bool MessagePipeDispatcher::EndSerialize(void* destination,
ports::PortName* ports,
PlatformHandle* handles) {
ScopedPlatformHandle* handles) {
SerializedState* state = static_cast<SerializedState*>(destination);
state->pipe_id = pipe_id_;
state->endpoint = static_cast<int8_t>(endpoint_);
......@@ -267,7 +267,7 @@ scoped_refptr<Dispatcher> MessagePipeDispatcher::Deserialize(
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
PlatformHandle* handles,
ScopedPlatformHandle* handles,
size_t num_handles) {
if (num_ports != 1 || num_handles || num_bytes != sizeof(SerializedState))
return nullptr;
......
......@@ -61,18 +61,17 @@ class MessagePipeDispatcher : public Dispatcher {
uint32_t* num_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
PlatformHandle* handles) override;
ScopedPlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
static scoped_refptr<Dispatcher> Deserialize(
const void* data,
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
PlatformHandle* handles,
size_t num_handles);
static scoped_refptr<Dispatcher> Deserialize(const void* data,
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
ScopedPlatformHandle* handles,
size_t num_handles);
private:
class PortObserverThunk;
......
This diff is collapsed.
......@@ -5,8 +5,8 @@
#ifndef MOJO_EDK_SYSTEM_NODE_CHANNEL_H_
#define MOJO_EDK_SYSTEM_NODE_CHANNEL_H_
#include <unordered_map>
#include <utility>
#include <vector>
#include "base/callback.h"
#include "base/containers/queue.h"
......@@ -18,7 +18,6 @@
#include "build/build_config.h"
#include "mojo/edk/embedder/connection_params.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/ports/name.h"
......@@ -178,7 +177,7 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
// Channel::Delegate:
void OnChannelMessage(const void* payload,
size_t payload_size,
ScopedPlatformHandleVectorPtr handles) override;
std::vector<ScopedPlatformHandle> handles) override;
void OnChannelError(Channel::Error error) override;
#if defined(OS_MACOSX) && !defined(OS_IOS)
......
......@@ -6,6 +6,7 @@
#include <algorithm>
#include <limits>
#include <vector>
#include "base/bind.h"
#include "base/containers/queue.h"
......@@ -1145,29 +1146,27 @@ void NodeController::OnRelayEventMessage(const ports::NodeName& from_node,
// Note that we explicitly mark the handles as being owned by the sending
// process before rewriting them, in order to accommodate RewriteHandles'
// internal sanity checks.
ScopedPlatformHandleVectorPtr handles = message->TakeHandles();
for (size_t i = 0; i < handles->size(); ++i)
(*handles)[i].owning_process = from_process;
if (!Channel::Message::RewriteHandles(from_process,
base::GetCurrentProcessHandle(),
handles.get())) {
std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
for (auto& handle : handles)
handle.get().owning_process = from_process;
if (!Channel::Message::RewriteHandles(
from_process, base::GetCurrentProcessHandle(), &handles)) {
DLOG(ERROR) << "Failed to relay one or more handles.";
}
message->SetHandles(std::move(handles));
#else
ScopedPlatformHandleVectorPtr handles = message->TakeHandles();
for (size_t i = 0; i < handles->size(); ++i) {
PlatformHandle* handle = &(*handles)[i];
if (handle->type == PlatformHandle::Type::MACH_NAME) {
std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
for (auto& handle : handles) {
if (handle.get().type == PlatformHandle::Type::MACH_NAME) {
MachPortRelay* relay = GetMachPortRelay();
if (!relay) {
handle->type = PlatformHandle::Type::MACH;
handle->port = MACH_PORT_NULL;
handle.get().type = PlatformHandle::Type::MACH;
handle.get().port = MACH_PORT_NULL;
DLOG(ERROR) << "Receiving Mach ports without a port relay from "
<< from_node << ".";
continue;
}
relay->ExtractPort(handle, from_process);
relay->ExtractPort(&handle, from_process);
}
}
message->SetHandles(std::move(handles));
......
......@@ -20,7 +20,6 @@
#include "base/memory/ref_counted.h"
#include "base/task_runner.h"
#include "build/build_config.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/atomic_flag.h"
......
......@@ -5,7 +5,7 @@
#include "mojo/edk/system/platform_handle_dispatcher.h"
#include "base/synchronization/lock.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
namespace mojo {
namespace edk {
......@@ -43,11 +43,11 @@ void PlatformHandleDispatcher::StartSerialize(uint32_t* num_bytes,
bool PlatformHandleDispatcher::EndSerialize(void* destination,
ports::PortName* ports,
PlatformHandle* handles) {
ScopedPlatformHandle* handles) {
base::AutoLock lock(lock_);
if (is_closed_)
return false;
handles[0] = platform_handle_.get();
handles[0] = ScopedPlatformHandle(platform_handle_.get());
return true;
}
......@@ -80,15 +80,12 @@ scoped_refptr<PlatformHandleDispatcher> PlatformHandleDispatcher::Deserialize(
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
PlatformHandle* handles,
ScopedPlatformHandle* handles,
size_t num_handles) {
if (num_bytes || num_ports || num_handles != 1)
return nullptr;
PlatformHandle handle;
std::swap(handle, handles[0]);
return PlatformHandleDispatcher::Create(ScopedPlatformHandle(handle));
return PlatformHandleDispatcher::Create(std::move(handles[0]));
}
PlatformHandleDispatcher::PlatformHandleDispatcher(
......
......@@ -30,7 +30,7 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher : public Dispatcher {
uint32_t* num_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
PlatformHandle* handles) override;
ScopedPlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
......@@ -40,7 +40,7 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher : public Dispatcher {
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
PlatformHandle* handles,
ScopedPlatformHandle* handles,
size_t num_handles);
private:
......
......@@ -12,7 +12,7 @@
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -87,11 +87,12 @@ TEST(PlatformHandleDispatcherTest, Serialization) {
EXPECT_EQ(0u, num_ports);
EXPECT_EQ(1u, num_handles);
ScopedPlatformHandleVectorPtr handles(new PlatformHandleVector(1));
EXPECT_TRUE(dispatcher->EndSerialize(nullptr, nullptr, handles->data()));
ScopedPlatformHandle received_handle;
EXPECT_TRUE(dispatcher->EndSerialize(nullptr, nullptr, &received_handle));
dispatcher->CompleteTransitAndClose();
EXPECT_TRUE(handles->at(0).is_valid());
EXPECT_TRUE(received_handle.is_valid());
ScopedPlatformHandle handle = dispatcher->PassPlatformHandle();
EXPECT_FALSE(handle.is_valid());
......@@ -100,10 +101,11 @@ TEST(PlatformHandleDispatcherTest, Serialization) {
dispatcher = static_cast<PlatformHandleDispatcher*>(
Dispatcher::Deserialize(Dispatcher::Type::PLATFORM_HANDLE, nullptr,
num_bytes, nullptr, num_ports, handles->data(),
1).get());
num_bytes, nullptr, num_ports, &received_handle,
1u)
.get());
EXPECT_FALSE(handles->at(0).is_valid());
EXPECT_FALSE(received_handle.is_valid());
EXPECT_TRUE(dispatcher->GetType() == Dispatcher::Type::PLATFORM_HANDLE);
fp = test::FILEFromPlatformHandle(dispatcher->PassPlatformHandle(), "rb");
......
......@@ -118,7 +118,7 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize(
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
PlatformHandle* platform_handles,
ScopedPlatformHandle* platform_handles,
size_t num_platform_handles) {
if (num_bytes != sizeof(SerializedState)) {
LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)";
......@@ -133,28 +133,20 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize(
return nullptr;
}
if (!platform_handles || num_platform_handles != 1 || num_ports) {
if (num_platform_handles != 1 || num_ports) {
LOG(ERROR)
<< "Invalid serialized shared buffer dispatcher (missing handles)";
return nullptr;
}
// Starts off invalid, which is what we want.
PlatformHandle platform_handle;
// We take ownership of the handle, so we have to invalidate the one in
// |platform_handles|.
std::swap(platform_handle, *platform_handles);
base::UnguessableToken guid = base::UnguessableToken::Deserialize(
serialized_state->guid_high, serialized_state->guid_low);
// Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be
// closed even if creation fails.
bool read_only = (serialized_state->flags & kSerializedStateFlagsReadOnly);
scoped_refptr<PlatformSharedBuffer> shared_buffer(
PlatformSharedBuffer::CreateFromPlatformHandle(
static_cast<size_t>(serialized_state->num_bytes), read_only, guid,
ScopedPlatformHandle(platform_handle)));
std::move(platform_handles[0])));
if (!shared_buffer) {
LOG(ERROR)
<< "Invalid serialized shared buffer dispatcher (invalid num_bytes?)";
......@@ -258,7 +250,7 @@ void SharedBufferDispatcher::StartSerialize(uint32_t* num_bytes,
bool SharedBufferDispatcher::EndSerialize(void* destination,
ports::PortName* ports,
PlatformHandle* handles) {
ScopedPlatformHandle* handles) {
SerializedState* serialized_state =
static_cast<SerializedState*>(destination);
base::AutoLock lock(lock_);
......@@ -271,12 +263,11 @@ bool SharedBufferDispatcher::EndSerialize(void* destination,
serialized_state->guid_low = guid.GetLowForSerialization();
serialized_state->padding = 0;
handle_for_transit_ = shared_buffer_->DuplicatePlatformHandle();
if (!handle_for_transit_.is_valid()) {
handles[0] = shared_buffer_->DuplicatePlatformHandle();
if (!handles[0].is_valid()) {
shared_buffer_ = nullptr;
return false;
}
handles[0] = handle_for_transit_.get();
return true;
}
......
......@@ -11,7 +11,6 @@
#include <utility>
#include "base/macros.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/dispatcher.h"
......@@ -59,8 +58,8 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher {
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
PlatformHandle* platform_handles,
size_t num_platform_handles);
ScopedPlatformHandle* platform_handles,
size_t num_handles);
// Passes the underlying platform shared buffer. This dispatcher must be
// closed after calling this function.
......@@ -82,7 +81,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher {
uint32_t* num_platform_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
PlatformHandle* handles) override;
ScopedPlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
......
......@@ -5,6 +5,7 @@
#include "mojo/edk/system/user_message_impl.h"
#include <algorithm>
#include <vector>
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros_local.h"
......@@ -146,7 +147,7 @@ MojoResult CreateOrExtendSerializedEventMessage(
DispatcherHeader* new_dispatcher_headers;
char* new_dispatcher_data;
size_t total_num_dispatchers = num_new_dispatchers;
ScopedPlatformHandleVectorPtr handles;
std::vector<ScopedPlatformHandle> handles;
if (original_message) {
DCHECK(original_header);
size_t original_dispatcher_headers_size =
......@@ -171,8 +172,8 @@ MojoResult CreateOrExtendSerializedEventMessage(
original_dispatcher_data_size);
new_dispatcher_data = dispatcher_data + original_dispatcher_data_size;
handles = original_message->TakeHandles();
if (handles)
handles->resize(num_handles);
if (!handles.empty())
handles.resize(num_handles);
memcpy(reinterpret_cast<char*>(header) + header_size,
reinterpret_cast<char*>(original_header) + original_header_size,
original_payload_size);
......@@ -184,9 +185,8 @@ MojoResult CreateOrExtendSerializedEventMessage(
reinterpret_cast<char*>(new_dispatcher_headers + num_new_dispatchers);
}
if (!handles && num_new_handles) {
handles = ScopedPlatformHandleVectorPtr(
new PlatformHandleVector(num_new_handles));
if (handles.empty() && num_new_handles) {
handles.resize(num_new_handles);
}
header->num_dispatchers =
......@@ -220,7 +220,7 @@ MojoResult CreateOrExtendSerializedEventMessage(
!d->EndSerialize(
static_cast<void*>(new_dispatcher_data),
event->ports() + port_index,
handles ? handles->data() + handle_index : nullptr)) {
!handles.empty() ? handles.data() + handle_index : nullptr)) {
fail = true;
break;
}
......@@ -234,8 +234,8 @@ MojoResult CreateOrExtendSerializedEventMessage(
// Release any platform handles we've accumulated. Their dispatchers
// retain ownership when message creation fails, so these are not actually
// leaking.
if (handles)
handles->clear();
for (auto& handle : handles)
ignore_result(handle.release());
// Leave the original message in place on failure if applicable.
if (original_message)
......@@ -552,8 +552,8 @@ MojoResult UserMessageImpl::ExtractSerializedHandles(
dispatcher_headers + header->num_dispatchers);
size_t port_index = 0;
size_t platform_handle_index = 0;
ScopedPlatformHandleVectorPtr msg_handles = channel_message_->TakeHandles();
const size_t num_msg_handles = msg_handles ? msg_handles->size() : 0;
std::vector<ScopedPlatformHandle> msg_handles =
channel_message_->TakeHandles();
for (size_t i = 0; i < header->num_dispatchers; ++i) {
const DispatcherHeader& dh = dispatcher_headers[i];
auto type = static_cast<Dispatcher::Type>(dh.type);
......@@ -576,12 +576,13 @@ MojoResult UserMessageImpl::ExtractSerializedHandles(
platform_handle_index;
next_platform_handle_index += dh.num_platform_handles;
if (!next_platform_handle_index.IsValid() ||
num_msg_handles < next_platform_handle_index.ValueOrDie()) {
msg_handles.size() < next_platform_handle_index.ValueOrDie()) {
return MOJO_RESULT_ABORTED;
}
PlatformHandle* out_handles =
num_msg_handles ? msg_handles->data() + platform_handle_index : nullptr;
ScopedPlatformHandle* out_handles =
!msg_handles.empty() ? msg_handles.data() + platform_handle_index
: nullptr;
dispatchers[i].dispatcher = Dispatcher::Deserialize(
type, dispatcher_data, dh.num_bytes,
message_event_->ports() + port_index, dh.num_ports, out_handles,
......
......@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/optional.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/ports/event.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment