OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/message_port.h" | 5 #include "content/common/message_port.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/threading/thread_task_runner_handle.h" | 9 #include "base/threading/thread_task_runner_handle.h" |
10 | 10 |
(...skipping 29 matching lines...) Expand all Loading... |
40 // static | 40 // static |
41 std::vector<mojo::ScopedMessagePipeHandle> MessagePort::ReleaseHandles( | 41 std::vector<mojo::ScopedMessagePipeHandle> MessagePort::ReleaseHandles( |
42 const std::vector<MessagePort>& ports) { | 42 const std::vector<MessagePort>& ports) { |
43 std::vector<mojo::ScopedMessagePipeHandle> handles(ports.size()); | 43 std::vector<mojo::ScopedMessagePipeHandle> handles(ports.size()); |
44 for (size_t i = 0; i < ports.size(); ++i) | 44 for (size_t i = 0; i < ports.size(); ++i) |
45 handles[i] = ports[i].ReleaseHandle(); | 45 handles[i] = ports[i].ReleaseHandle(); |
46 return handles; | 46 return handles; |
47 } | 47 } |
48 | 48 |
49 void MessagePort::PostMessage(const base::string16& encoded_message, | 49 void MessagePort::PostMessage(const base::string16& encoded_message, |
50 std::vector<MessagePort> ports) { | 50 std::vector<MessagePort> ports, |
| 51 std::vector<mojo::ScopedHandle> extra_handles) { |
51 DCHECK(state_->handle_.is_valid()); | 52 DCHECK(state_->handle_.is_valid()); |
52 | 53 |
53 uint32_t num_bytes = encoded_message.size() * sizeof(base::char16); | 54 uint32_t num_message_bytes = encoded_message.size() * sizeof(base::char16); |
54 | 55 |
55 // NOTE: It is OK to ignore the return value of MojoWriteMessage here. HTML | 56 // NOTE: It is OK to ignore the return value of MojoWriteMessage here. HTML |
56 // MessagePorts have no way of reporting when the peer is gone. | 57 // MessagePorts have no way of reporting when the peer is gone. |
57 | 58 |
58 if (ports.empty()) { | 59 // When we have handles to pass, we add a 4-byte prefix to the encoded |
59 MojoWriteMessage(state_->handle_.get().value(), | 60 // message to indicate how many of the handles correspond to ports. |
60 encoded_message.data(), | 61 |
61 num_bytes, | 62 if (ports.empty() && extra_handles.empty()) { |
62 nullptr, | 63 MojoWriteMessage(state_->handle_.get().value(), encoded_message.data(), |
63 0, | 64 num_message_bytes, nullptr, 0, |
64 MOJO_WRITE_MESSAGE_FLAG_NONE); | 65 MOJO_WRITE_MESSAGE_FLAG_NONE); |
65 } else { | 66 } else { |
66 uint32_t num_handles = static_cast<uint32_t>(ports.size()); | 67 uint32_t num_ports = static_cast<uint32_t>(ports.size()); |
| 68 uint32_t num_extra_handles = static_cast<uint32_t>(extra_handles.size()); |
| 69 uint32_t num_handles = num_ports + num_extra_handles; |
| 70 uint32_t num_bytes = num_message_bytes + sizeof(num_ports); |
| 71 |
| 72 std::unique_ptr<uint8_t> bytes(new uint8_t[num_bytes]); |
| 73 memcpy(bytes.get(), &num_ports, sizeof(num_ports)); |
| 74 memcpy(bytes.get() + num_ports, encoded_message.data(), num_message_bytes); |
| 75 |
67 std::unique_ptr<MojoHandle[]> handles(new MojoHandle[num_handles]); | 76 std::unique_ptr<MojoHandle[]> handles(new MojoHandle[num_handles]); |
68 for (uint32_t i = 0; i < num_handles; ++i) | 77 for (uint32_t i = 0; i < num_ports; ++i) |
69 handles[i] = ports[i].ReleaseHandle().release().value(); | 78 handles[i] = ports[i].ReleaseHandle().release().value(); |
70 MojoWriteMessage(state_->handle_.get().value(), | 79 for (uint32_t i = 0; i < num_extra_handles; ++i) |
71 encoded_message.data(), | 80 handles[num_ports + i] = extra_handles[i].release().value(); |
72 num_bytes, | 81 |
73 handles.get(), | 82 MojoWriteMessage(state_->handle_.get().value(), bytes.get(), num_bytes, |
74 num_handles, | 83 handles.get(), num_handles, MOJO_WRITE_MESSAGE_FLAG_NONE); |
75 MOJO_WRITE_MESSAGE_FLAG_NONE); | |
76 } | 84 } |
77 } | 85 } |
78 | 86 |
79 bool MessagePort::GetMessage(base::string16* encoded_message, | 87 bool MessagePort::GetMessage(base::string16* encoded_message, |
80 std::vector<MessagePort>* ports) { | 88 std::vector<MessagePort>* ports, |
| 89 std::vector<mojo::ScopedHandle>* extra_handles) { |
81 DCHECK(state_->handle_.is_valid()); | 90 DCHECK(state_->handle_.is_valid()); |
82 | 91 |
83 uint32_t num_bytes = 0; | 92 uint32_t num_bytes = 0; |
84 uint32_t num_handles = 0; | 93 uint32_t num_handles = 0; |
85 | 94 |
86 MojoResult rv = MojoReadMessage(state_->handle_.get().value(), | 95 MojoResult rv = MojoReadMessage(state_->handle_.get().value(), |
87 nullptr, | 96 nullptr, |
88 &num_bytes, | 97 &num_bytes, |
89 nullptr, | 98 nullptr, |
90 &num_handles, | 99 &num_handles, |
91 MOJO_READ_MESSAGE_FLAG_NONE); | 100 MOJO_READ_MESSAGE_FLAG_NONE); |
92 if (rv == MOJO_RESULT_OK) { | 101 if (rv == MOJO_RESULT_OK) { |
93 encoded_message->clear(); | 102 encoded_message->clear(); |
94 ports->clear(); | 103 ports->clear(); |
| 104 extra_handles->clear(); |
95 return true; | 105 return true; |
96 } | 106 } |
97 if (rv != MOJO_RESULT_RESOURCE_EXHAUSTED) | 107 if (rv != MOJO_RESULT_RESOURCE_EXHAUSTED) |
98 return false; | 108 return false; |
99 | 109 |
100 CHECK(num_bytes % 2 == 0); | 110 CHECK(num_bytes % 2 == 0); |
101 | 111 |
102 base::string16 buffer; | 112 base::string16 buffer; |
103 buffer.resize(num_bytes / sizeof(base::char16)); | 113 buffer.resize(num_bytes / sizeof(base::char16)); |
104 | 114 |
105 std::unique_ptr<MojoHandle[]> handles; | 115 std::unique_ptr<MojoHandle[]> handles; |
106 if (num_handles) | 116 if (num_handles) |
107 handles.reset(new MojoHandle[num_handles]); | 117 handles.reset(new MojoHandle[num_handles]); |
108 | 118 |
109 rv = MojoReadMessage(state_->handle_.get().value(), | 119 rv = MojoReadMessage(state_->handle_.get().value(), |
110 num_bytes ? &buffer[0] : nullptr, | 120 num_bytes ? &buffer[0] : nullptr, |
111 &num_bytes, | 121 &num_bytes, |
112 handles.get(), | 122 handles.get(), |
113 &num_handles, | 123 &num_handles, |
114 MOJO_READ_MESSAGE_FLAG_NONE); | 124 MOJO_READ_MESSAGE_FLAG_NONE); |
115 if (rv != MOJO_RESULT_OK) | 125 if (rv != MOJO_RESULT_OK) |
116 return false; | 126 return false; |
117 | 127 |
118 buffer.swap(*encoded_message); | 128 // When we have received handles, the message contains a 4-byte prefix |
| 129 // indicating how many of the handles correspond to ports. |
119 | 130 |
120 if (num_handles) { | 131 if (num_handles) { |
121 ports->resize(static_cast<size_t>(num_handles)); | 132 uint32_t num_ports; |
122 for (uint32_t i = 0; i < num_handles; ++i) { | 133 memcpy(&num_ports, buffer.data(), sizeof(num_ports)); |
| 134 *encoded_message = buffer.substr(sizeof(num_ports) / sizeof(base::char16)); |
| 135 |
| 136 CHECK(num_ports <= num_handles); |
| 137 |
| 138 uint32_t num_extra_handles = num_handles - num_ports; |
| 139 |
| 140 ports->resize(static_cast<size_t>(num_ports)); |
| 141 extra_handles->resize(static_cast<size_t>(num_extra_handles)); |
| 142 |
| 143 for (uint32_t i = 0; i < num_ports; ++i) { |
123 ports->at(i) = MessagePort( | 144 ports->at(i) = MessagePort( |
124 mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(handles[i]))); | 145 mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(handles[i]))); |
125 } | 146 } |
| 147 for (uint32_t i = 0; i < num_extra_handles; ++i) { |
| 148 extra_handles->at(i) = |
| 149 mojo::ScopedHandle(mojo::Handle(handles[num_ports + i])); |
| 150 } |
| 151 } else { |
| 152 buffer.swap(*encoded_message); |
| 153 ports->clear(); |
| 154 extra_handles->clear(); |
126 } | 155 } |
127 return true; | 156 return true; |
128 } | 157 } |
129 | 158 |
130 void MessagePort::SetCallback(const base::Closure& callback) { | 159 void MessagePort::SetCallback(const base::Closure& callback) { |
131 state_->CancelWatch(); | 160 state_->CancelWatch(); |
132 state_->callback_ = callback; | 161 state_->callback_ = callback; |
133 state_->AddWatch(); | 162 state_->AddWatch(); |
134 } | 163 } |
135 | 164 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 if (result == MOJO_RESULT_CANCELLED) { | 253 if (result == MOJO_RESULT_CANCELLED) { |
225 // Last notification. Release the watch context's owned State ref. This is | 254 // Last notification. Release the watch context's owned State ref. This is |
226 // balanced in MessagePort::State::AddWatch. | 255 // balanced in MessagePort::State::AddWatch. |
227 state->Release(); | 256 state->Release(); |
228 } else { | 257 } else { |
229 state->OnHandleReady(result); | 258 state->OnHandleReady(result); |
230 } | 259 } |
231 } | 260 } |
232 | 261 |
233 } // namespace content | 262 } // namespace content |
OLD | NEW |