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

Unified Diff: mojo/edk/system/child_broker.cc

Issue 1555273002: [mojo] Add CreateSharedBuffer method to Broker. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: mojo/edk/system/child_broker.cc
diff --git a/mojo/edk/system/child_broker.cc b/mojo/edk/system/child_broker.cc
index 6903c8204dbd23b393729c8e859407609dc983db..627e1eb23b3ddac526ad1d3e599ed04b26007223 100644
--- a/mojo/edk/system/child_broker.cc
+++ b/mojo/edk/system/child_broker.cc
@@ -13,9 +13,17 @@
#include "base/logging.h"
#include "mojo/edk/embedder/embedder_internal.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/edk/embedder/platform_shared_buffer.h"
+#include "mojo/edk/embedder/platform_support.h"
#include "mojo/edk/system/broker_messages.h"
#include "mojo/edk/system/message_pipe_dispatcher.h"
+#if defined(OS_POSIX)
+#include <fcntl.h>
+
+#include "mojo/edk/embedder/platform_channel_utils_posix.h"
+#endif
+
namespace mojo {
namespace edk {
@@ -26,24 +34,34 @@ ChildBroker* ChildBroker::GetInstance() {
void ChildBroker::SetChildBrokerHostHandle(ScopedPlatformHandle handle) {
ScopedPlatformHandle parent_async_channel_handle;
+ parent_sync_channel_ = std::move(handle);
+
+// We have two pipes to the parent. The first is for the token
+// exchange for creating and passing handles on Windows, and creating shared
+// buffers on POSIX, since the child needs the parent's help if it is
+// sandboxed. The second is used for multiplexing related messages. We
+// send the second over the first.
#if defined(OS_POSIX)
- parent_async_channel_handle = std::move(handle);
+ // Make the synchronous channel blocking.
+ fcntl(parent_sync_channel_.get().handle, F_SETFL,
Anand Mistry (off Chromium) 2016/01/07 04:36:33 Since you rely on the channels becoming blocking,
Eliot Courtney 2016/01/07 05:01:30 Done.
+ fcntl(parent_sync_channel_.get().handle, F_GETFL, 0) & ~O_NONBLOCK);
+
+ std::deque<PlatformHandle> received_handles;
+ char buf[1];
+ ssize_t result = PlatformChannelRecvmsg(parent_sync_channel_.get(), buf, 1,
+ &received_handles);
+ CHECK_EQ(1, result);
+ CHECK_EQ(1u, received_handles.size());
+ parent_async_channel_handle.reset(received_handles.front());
#else
- // On Windows we have two pipes to the parent. The first is for the token
- // exchange for creating and passing handles, since the child needs the
- // parent's help if it is sandboxed. The second is the same as POSIX, which is
- // used for multiplexing related messages. So on Windows, we send the second
- // pipe as the first string over the first one.
- parent_sync_channel_ = handle.Pass();
-
HANDLE parent_handle = INVALID_HANDLE_VALUE;
DWORD bytes_read = 0;
BOOL rv = ReadFile(parent_sync_channel_.get().handle, &parent_handle,
sizeof(parent_handle), &bytes_read, NULL);
CHECK(rv);
parent_async_channel_handle.reset(PlatformHandle(parent_handle));
- sync_channel_lock_.Unlock();
#endif
+ sync_channel_lock_.Unlock();
internal::g_io_thread_task_runner->PostTask(
FROM_HERE,
@@ -99,6 +117,30 @@ void ChildBroker::TokenToHandle(const uint64_t* tokens,
sync_channel_lock_.Unlock();
}
}
+#else
+scoped_refptr<PlatformSharedBuffer> ChildBroker::CreateSharedBuffer(
+ size_t num_bytes) {
+ sync_channel_lock_.Lock();
Anand Mistry (off Chromium) 2016/01/07 04:36:33 Why aren't you using AutoLock?
Eliot Courtney 2016/01/07 05:01:30 This lock is actually a LockImpl, see comment: htt
+ scoped_refptr<PlatformSharedBuffer> shared_buffer;
+
+ BrokerMessage message;
+ message.size = kBrokerMessageHeaderSize + sizeof(uint32_t);
+ message.id = CREATE_SHARED_BUFFER;
+ message.num_bytes = num_bytes;
+
+ std::deque<PlatformHandle> handles;
+ if (WriteAndReadHandles(&message, &handles)) {
+ DCHECK_EQ(1u, handles.size());
+ PlatformHandle handle = handles.front();
+ if (handle.is_valid())
+ shared_buffer =
+ internal::g_platform_support->CreateSharedBufferFromHandle(
+ num_bytes, ScopedPlatformHandle(handles.front()));
+ }
+
+ sync_channel_lock_.Unlock();
+ return shared_buffer;
+}
#endif
void ChildBroker::ConnectMessagePipe(uint64_t pipe_id,
@@ -172,10 +214,8 @@ ChildBroker::ChildBroker()
in_process_pipes_channel2_(nullptr) {
DCHECK(!internal::g_broker);
internal::g_broker = this;
-#if defined(OS_WIN)
// Block any threads from calling this until we have a pipe to the parent.
sync_channel_lock_.Lock();
-#endif
}
ChildBroker::~ChildBroker() {
@@ -285,6 +325,21 @@ void ChildBroker::AttachMessagePipe(MessagePipeDispatcher* message_pipe,
#if defined(OS_WIN)
+void ChildBroker::CreatePlatformChannelPairNoLock(
+ ScopedPlatformHandle* server,
+ ScopedPlatformHandle* client) {
+ BrokerMessage message;
+ message.size = kBrokerMessageHeaderSize;
+ message.id = CREATE_PLATFORM_CHANNEL_PAIR;
+
+ uint32_t response_size = 2 * sizeof(HANDLE);
+ HANDLE handles[2];
+ if (WriteAndReadResponse(&message, handles, response_size)) {
+ server->reset(PlatformHandle(handles[0]));
+ client->reset(PlatformHandle(handles[1]));
+ }
+}
+
bool ChildBroker::WriteAndReadResponse(BrokerMessage* message,
void* response,
uint32_t response_size) {
@@ -316,21 +371,38 @@ bool ChildBroker::WriteAndReadResponse(BrokerMessage* message,
return result;
}
+#else
+bool ChildBroker::WriteAndReadHandles(BrokerMessage* message,
+ std::deque<PlatformHandle>* handles) {
+ DCHECK_EQ(0,
+ fcntl(parent_sync_channel_.get().handle, F_GETFL, 0) & O_NONBLOCK);
+ CHECK(parent_sync_channel_.is_valid());
-void ChildBroker::CreatePlatformChannelPairNoLock(
- ScopedPlatformHandle* server, ScopedPlatformHandle* client) {
- BrokerMessage message;
- message.size = kBrokerMessageHeaderSize;
- message.id = CREATE_PLATFORM_CHANNEL_PAIR;
-
- uint32_t response_size = 2 * sizeof(HANDLE);
- HANDLE handles[2];
- if (WriteAndReadResponse(&message, handles, response_size)) {
- server->reset(PlatformHandle(handles[0]));
- client->reset(PlatformHandle(handles[1]));
+ uint32_t remaining_bytes = message->size;
+ while (remaining_bytes > 0) {
+ ssize_t bytes_written = PlatformChannelWrite(
+ parent_sync_channel_.get(),
+ reinterpret_cast<uint8_t*>(message) + (message->size - remaining_bytes),
+ remaining_bytes);
+
+ if (bytes_written != -1)
+ remaining_bytes -= bytes_written;
+ else
+ return false;
}
-}
+ // Perform a blocking read (we set this fd to be blocking in
+ // SetChildBrokerHostHandle).
+ char buf[1];
+ ssize_t bytes_read =
+ PlatformChannelRecvmsg(parent_sync_channel_.get(), buf, 1, handles);
+ // If the other side shutdown, or there was an error, or we didn't get
+ // any handles.
+ if (bytes_read == 0 || bytes_read == -1 || handles->empty())
+ return false;
+
+ return true;
+}
#endif
} // namespace edk

Powered by Google App Engine
This is Rietveld 408576698