Index: content/common/message_port.cc |
diff --git a/content/common/message_port.cc b/content/common/message_port.cc |
index a57236a7b28759d5ab7d1b0d963e74817327b64f..1d6dda4aaca6fcce1a6875b665c377ac29733e86 100644 |
--- a/content/common/message_port.cc |
+++ b/content/common/message_port.cc |
@@ -47,37 +47,46 @@ std::vector<mojo::ScopedMessagePipeHandle> MessagePort::ReleaseHandles( |
} |
void MessagePort::PostMessage(const base::string16& encoded_message, |
- std::vector<MessagePort> ports) { |
+ std::vector<MessagePort> ports, |
+ std::vector<mojo::ScopedHandle> extra_handles) { |
DCHECK(state_->handle_.is_valid()); |
- uint32_t num_bytes = encoded_message.size() * sizeof(base::char16); |
+ uint32_t num_message_bytes = encoded_message.size() * sizeof(base::char16); |
// NOTE: It is OK to ignore the return value of MojoWriteMessage here. HTML |
// MessagePorts have no way of reporting when the peer is gone. |
- if (ports.empty()) { |
- MojoWriteMessage(state_->handle_.get().value(), |
- encoded_message.data(), |
- num_bytes, |
- nullptr, |
- 0, |
+ // When we have handles to pass, we add a 4-byte prefix to the encoded |
+ // message to indicate how many of the handles correspond to ports. |
+ |
+ if (ports.empty() && extra_handles.empty()) { |
+ MojoWriteMessage(state_->handle_.get().value(), encoded_message.data(), |
+ num_message_bytes, nullptr, 0, |
MOJO_WRITE_MESSAGE_FLAG_NONE); |
} else { |
- uint32_t num_handles = static_cast<uint32_t>(ports.size()); |
+ uint32_t num_ports = static_cast<uint32_t>(ports.size()); |
+ uint32_t num_extra_handles = static_cast<uint32_t>(extra_handles.size()); |
+ uint32_t num_handles = num_ports + num_extra_handles; |
+ uint32_t num_bytes = num_message_bytes + sizeof(num_ports); |
+ |
+ std::unique_ptr<uint8_t> bytes(new uint8_t[num_bytes]); |
+ memcpy(bytes.get(), &num_ports, sizeof(num_ports)); |
+ memcpy(bytes.get() + num_ports, encoded_message.data(), num_message_bytes); |
+ |
std::unique_ptr<MojoHandle[]> handles(new MojoHandle[num_handles]); |
- for (uint32_t i = 0; i < num_handles; ++i) |
+ for (uint32_t i = 0; i < num_ports; ++i) |
handles[i] = ports[i].ReleaseHandle().release().value(); |
- MojoWriteMessage(state_->handle_.get().value(), |
- encoded_message.data(), |
- num_bytes, |
- handles.get(), |
- num_handles, |
- MOJO_WRITE_MESSAGE_FLAG_NONE); |
+ for (uint32_t i = 0; i < num_extra_handles; ++i) |
+ handles[num_ports + i] = extra_handles[i].release().value(); |
+ |
+ MojoWriteMessage(state_->handle_.get().value(), bytes.get(), num_bytes, |
+ handles.get(), num_handles, MOJO_WRITE_MESSAGE_FLAG_NONE); |
} |
} |
bool MessagePort::GetMessage(base::string16* encoded_message, |
- std::vector<MessagePort>* ports) { |
+ std::vector<MessagePort>* ports, |
+ std::vector<mojo::ScopedHandle>* extra_handles) { |
DCHECK(state_->handle_.is_valid()); |
uint32_t num_bytes = 0; |
@@ -92,6 +101,7 @@ bool MessagePort::GetMessage(base::string16* encoded_message, |
if (rv == MOJO_RESULT_OK) { |
encoded_message->clear(); |
ports->clear(); |
+ extra_handles->clear(); |
return true; |
} |
if (rv != MOJO_RESULT_RESOURCE_EXHAUSTED) |
@@ -115,14 +125,33 @@ bool MessagePort::GetMessage(base::string16* encoded_message, |
if (rv != MOJO_RESULT_OK) |
return false; |
- buffer.swap(*encoded_message); |
+ // When we have received handles, the message contains a 4-byte prefix |
+ // indicating how many of the handles correspond to ports. |
if (num_handles) { |
- ports->resize(static_cast<size_t>(num_handles)); |
- for (uint32_t i = 0; i < num_handles; ++i) { |
+ uint32_t num_ports; |
+ memcpy(&num_ports, buffer.data(), sizeof(num_ports)); |
+ *encoded_message = buffer.substr(sizeof(num_ports) / sizeof(base::char16)); |
+ |
+ CHECK(num_ports <= num_handles); |
+ |
+ uint32_t num_extra_handles = num_handles - num_ports; |
+ |
+ ports->resize(static_cast<size_t>(num_ports)); |
+ extra_handles->resize(static_cast<size_t>(num_extra_handles)); |
+ |
+ for (uint32_t i = 0; i < num_ports; ++i) { |
ports->at(i) = MessagePort( |
mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(handles[i]))); |
} |
+ for (uint32_t i = 0; i < num_extra_handles; ++i) { |
+ extra_handles->at(i) = |
+ mojo::ScopedHandle(mojo::Handle(handles[num_ports + i])); |
+ } |
+ } else { |
+ buffer.swap(*encoded_message); |
+ ports->clear(); |
+ extra_handles->clear(); |
} |
return true; |
} |