blob: d4fdca56b72edb6f3faef345e53aa6d77ac6b7db [file] [log] [blame]
[email protected]64860882014-08-04 23:44:171// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
amistryd4aa70d2016-06-23 07:52:375#include "ipc/ipc_channel_mojo.h"
[email protected]64860882014-08-04 23:44:176
avi246998d82015-12-22 02:39:047#include <stddef.h>
8#include <stdint.h>
danakj03de39b22016-04-23 04:21:099
dcheng0917ec42015-11-19 07:00:2010#include <memory>
dchenge48600452015-12-28 02:24:5011#include <utility>
dcheng0917ec42015-11-19 07:00:2012
[email protected]64860882014-08-04 23:44:1713#include "base/bind.h"
14#include "base/bind_helpers.h"
jam76bcf0c2015-10-02 21:01:2815#include "base/command_line.h"
[email protected]64860882014-08-04 23:44:1716#include "base/lazy_instance.h"
avi246998d82015-12-22 02:39:0417#include "base/macros.h"
danakj03de39b22016-04-23 04:21:0918#include "base/memory/ptr_util.h"
rockot0e4de5f2016-07-22 21:18:0719#include "base/process/process_handle.h"
gabf08ccc02016-05-11 18:51:1120#include "base/threading/thread_task_runner_handle.h"
avi246998d82015-12-22 02:39:0421#include "build/build_config.h"
[email protected]64860882014-08-04 23:44:1722#include "ipc/ipc_listener.h"
morrita7126b7a2014-12-17 19:01:4023#include "ipc/ipc_logging.h"
morrita4b5c28e22015-01-14 21:17:0624#include "ipc/ipc_message_attachment_set.h"
morrita7126b7a2014-12-17 19:01:4025#include "ipc/ipc_message_macros.h"
amistryd4aa70d2016-06-23 07:52:3726#include "ipc/ipc_mojo_bootstrap.h"
27#include "ipc/ipc_mojo_handle_attachment.h"
rockot85dce0862015-11-13 01:33:5928#include "mojo/public/cpp/bindings/binding.h"
amistrycbdbf182016-06-09 04:08:1229#include "mojo/public/cpp/system/platform_handle.h"
[email protected]64860882014-08-04 23:44:1730
amistrye309ea32016-06-06 03:20:4931#if defined(OS_POSIX)
morrita1aa788c2015-01-31 05:45:4232#include "ipc/ipc_platform_file_attachment_posix.h"
33#endif
34
sammc57ed9f982016-03-10 06:28:3535#if defined(OS_MACOSX)
36#include "ipc/mach_port_attachment_mac.h"
37#endif
38
39#if defined(OS_WIN)
40#include "ipc/handle_attachment_win.h"
41#endif
42
[email protected]64860882014-08-04 23:44:1743namespace IPC {
44
45namespace {
46
[email protected]64860882014-08-04 23:44:1747class MojoChannelFactory : public ChannelFactory {
48 public:
rockota34707ca2016-07-20 04:28:3249 MojoChannelFactory(
50 mojo::ScopedMessagePipeHandle handle,
51 Channel::Mode mode,
52 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner)
53 : handle_(std::move(handle)),
54 mode_(mode),
55 ipc_task_runner_(ipc_task_runner) {}
[email protected]64860882014-08-04 23:44:1756
sammc57ed9f982016-03-10 06:28:3557 std::string GetName() const override { return ""; }
[email protected]64860882014-08-04 23:44:1758
danakj03de39b22016-04-23 04:21:0959 std::unique_ptr<Channel> BuildChannel(Listener* listener) override {
rockota34707ca2016-07-20 04:28:3260 return ChannelMojo::Create(
61 std::move(handle_), mode_, listener, ipc_task_runner_);
62 }
63
64 scoped_refptr<base::SingleThreadTaskRunner> GetIPCTaskRunner() override {
65 return ipc_task_runner_;
[email protected]64860882014-08-04 23:44:1766 }
67
68 private:
sammc57ed9f982016-03-10 06:28:3569 mojo::ScopedMessagePipeHandle handle_;
sammce4d0abd2016-03-07 22:38:0470 const Channel::Mode mode_;
rockota34707ca2016-07-20 04:28:3271 scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_;
[email protected]64860882014-08-04 23:44:1772
sammce4d0abd2016-03-07 22:38:0473 DISALLOW_COPY_AND_ASSIGN(MojoChannelFactory);
morritaf8f92dcd2014-10-27 20:10:2574};
75
sammc57ed9f982016-03-10 06:28:3576mojom::SerializedHandlePtr CreateSerializedHandle(
77 mojo::ScopedHandle handle,
78 mojom::SerializedHandle::Type type) {
79 mojom::SerializedHandlePtr serialized_handle = mojom::SerializedHandle::New();
80 serialized_handle->the_handle = std::move(handle);
81 serialized_handle->type = type;
82 return serialized_handle;
83}
84
amistrycbdbf182016-06-09 04:08:1285MojoResult WrapPlatformHandle(base::PlatformFile handle,
sammc57ed9f982016-03-10 06:28:3586 mojom::SerializedHandle::Type type,
87 mojom::SerializedHandlePtr* serialized) {
amistrycbdbf182016-06-09 04:08:1288 mojo::ScopedHandle wrapped_handle = mojo::WrapPlatformFile(handle);
89 if (!wrapped_handle.is_valid())
90 return MOJO_RESULT_UNKNOWN;
sammc57ed9f982016-03-10 06:28:3591
amistrycbdbf182016-06-09 04:08:1292 *serialized = CreateSerializedHandle(std::move(wrapped_handle), type);
sammc57ed9f982016-03-10 06:28:3593 return MOJO_RESULT_OK;
94}
95
amistrycbdbf182016-06-09 04:08:1296#if defined(OS_MACOSX)
97
98MojoResult WrapMachPort(mach_port_t mach_port,
99 mojom::SerializedHandlePtr* serialized) {
100 MojoPlatformHandle platform_handle = {
101 sizeof(MojoPlatformHandle), MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT,
102 static_cast<uint64_t>(mach_port)
103 };
104
105 MojoHandle wrapped_handle;
106 MojoResult result = MojoWrapPlatformHandle(&platform_handle, &wrapped_handle);
107 if (result != MOJO_RESULT_OK)
108 return result;
109
110 *serialized = CreateSerializedHandle(
111 mojo::MakeScopedHandle(mojo::Handle(wrapped_handle)),
112 mojom::SerializedHandle::Type::MACH_PORT);
113 return MOJO_RESULT_OK;
114}
115
116#endif
117
amistrye309ea32016-06-06 03:20:49118#if defined(OS_POSIX)
morrita98ac98f2015-02-25 02:55:04119
120base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) {
121 return attachment->Owns() ? base::ScopedFD(attachment->TakePlatformFile())
122 : base::ScopedFD(dup(attachment->file()));
123}
124
125#endif
126
sammc57ed9f982016-03-10 06:28:35127MojoResult WrapAttachmentImpl(MessageAttachment* attachment,
128 mojom::SerializedHandlePtr* serialized) {
129 if (attachment->GetType() == MessageAttachment::TYPE_MOJO_HANDLE) {
130 *serialized = CreateSerializedHandle(
131 static_cast<internal::MojoHandleAttachment&>(*attachment).TakeHandle(),
132 mojom::SerializedHandle::Type::MOJO_HANDLE);
133 return MOJO_RESULT_OK;
134 }
amistrye309ea32016-06-06 03:20:49135#if defined(OS_POSIX)
sammc57ed9f982016-03-10 06:28:35136 if (attachment->GetType() == MessageAttachment::TYPE_PLATFORM_FILE) {
137 // We dup() the handles in IPC::Message to transmit.
138 // IPC::MessageAttachmentSet has intricate lifecycle semantics
139 // of FDs, so just to dup()-and-own them is the safest option.
140 base::ScopedFD file = TakeOrDupFile(
141 static_cast<IPC::internal::PlatformFileAttachment*>(attachment));
142 if (!file.is_valid()) {
143 DPLOG(WARNING) << "Failed to dup FD to transmit.";
144 return MOJO_RESULT_UNKNOWN;
145 }
146
amistrycbdbf182016-06-09 04:08:12147 return WrapPlatformHandle(file.release(),
amistry980a61b2016-06-09 02:51:20148 mojom::SerializedHandle::Type::PLATFORM_FILE,
sammc57ed9f982016-03-10 06:28:35149 serialized);
150 }
151#endif
152#if defined(OS_MACOSX)
153 DCHECK_EQ(attachment->GetType(),
154 MessageAttachment::TYPE_BROKERABLE_ATTACHMENT);
155 DCHECK_EQ(static_cast<BrokerableAttachment&>(*attachment).GetBrokerableType(),
156 BrokerableAttachment::MACH_PORT);
157 internal::MachPortAttachmentMac& mach_port_attachment =
158 static_cast<internal::MachPortAttachmentMac&>(*attachment);
amistrycbdbf182016-06-09 04:08:12159 MojoResult result = WrapMachPort(mach_port_attachment.get_mach_port(),
160 serialized);
sammc57ed9f982016-03-10 06:28:35161 mach_port_attachment.reset_mach_port_ownership();
162 return result;
163#elif defined(OS_WIN)
164 DCHECK_EQ(attachment->GetType(),
165 MessageAttachment::TYPE_BROKERABLE_ATTACHMENT);
166 DCHECK_EQ(static_cast<BrokerableAttachment&>(*attachment).GetBrokerableType(),
167 BrokerableAttachment::WIN_HANDLE);
168 internal::HandleAttachmentWin& handle_attachment =
169 static_cast<internal::HandleAttachmentWin&>(*attachment);
170 MojoResult result = WrapPlatformHandle(
amistrycbdbf182016-06-09 04:08:12171 handle_attachment.get_handle(),
sammc57ed9f982016-03-10 06:28:35172 mojom::SerializedHandle::Type::WIN_HANDLE, serialized);
173 handle_attachment.reset_handle_ownership();
174 return result;
175#else
176 NOTREACHED();
177 return MOJO_RESULT_UNKNOWN;
178#endif // defined(OS_MACOSX)
179}
180
181MojoResult WrapAttachment(MessageAttachment* attachment,
yzshen24b40a32016-08-24 01:10:13182 std::vector<mojom::SerializedHandlePtr>* handles) {
sammc57ed9f982016-03-10 06:28:35183 mojom::SerializedHandlePtr serialized_handle;
184 MojoResult wrap_result = WrapAttachmentImpl(attachment, &serialized_handle);
185 if (wrap_result != MOJO_RESULT_OK) {
186 LOG(WARNING) << "Pipe failed to wrap handles. Closing: " << wrap_result;
187 return wrap_result;
188 }
189 handles->push_back(std::move(serialized_handle));
190 return MOJO_RESULT_OK;
191}
192
193MojoResult UnwrapAttachment(mojom::SerializedHandlePtr handle,
194 scoped_refptr<MessageAttachment>* attachment) {
195 if (handle->type == mojom::SerializedHandle::Type::MOJO_HANDLE) {
196 *attachment =
197 new IPC::internal::MojoHandleAttachment(std::move(handle->the_handle));
198 return MOJO_RESULT_OK;
199 }
amistrycbdbf182016-06-09 04:08:12200 MojoPlatformHandle platform_handle = { sizeof(MojoPlatformHandle), 0, 0 };
201 MojoResult unwrap_result = MojoUnwrapPlatformHandle(
sammc57ed9f982016-03-10 06:28:35202 handle->the_handle.release().value(), &platform_handle);
203 if (unwrap_result != MOJO_RESULT_OK)
204 return unwrap_result;
amistry980a61b2016-06-09 02:51:20205#if defined(OS_POSIX)
amistrycbdbf182016-06-09 04:08:12206 if (handle->type == mojom::SerializedHandle::Type::PLATFORM_FILE) {
207 base::PlatformFile file = base::kInvalidPlatformFile;
208 if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR)
209 file = static_cast<base::PlatformFile>(platform_handle.value);
210 *attachment = new internal::PlatformFileAttachment(file);
amistry980a61b2016-06-09 02:51:20211 return MOJO_RESULT_OK;
212 }
213#endif // defined(OS_POSIX)
sammc57ed9f982016-03-10 06:28:35214#if defined(OS_MACOSX)
amistrycbdbf182016-06-09 04:08:12215 if (handle->type == mojom::SerializedHandle::Type::MACH_PORT) {
216 mach_port_t mach_port = MACH_PORT_NULL;
217 if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT)
218 mach_port = static_cast<mach_port_t>(platform_handle.value);
sammc57ed9f982016-03-10 06:28:35219 *attachment = new internal::MachPortAttachmentMac(
amistrycbdbf182016-06-09 04:08:12220 mach_port, internal::MachPortAttachmentMac::FROM_WIRE);
sammc57ed9f982016-03-10 06:28:35221 return MOJO_RESULT_OK;
222 }
223#endif // defined(OS_MACOSX)
224#if defined(OS_WIN)
225 if (handle->type == mojom::SerializedHandle::Type::WIN_HANDLE) {
amistrycbdbf182016-06-09 04:08:12226 base::PlatformFile handle = base::kInvalidPlatformFile;
227 if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE)
228 handle = reinterpret_cast<base::PlatformFile>(platform_handle.value);
sammc57ed9f982016-03-10 06:28:35229 *attachment = new internal::HandleAttachmentWin(
amistrycbdbf182016-06-09 04:08:12230 handle, internal::HandleAttachmentWin::FROM_WIRE);
sammc57ed9f982016-03-10 06:28:35231 return MOJO_RESULT_OK;
232 }
233#endif // defined(OS_WIN)
234 NOTREACHED();
235 return MOJO_RESULT_UNKNOWN;
236}
237
rockotdbb3bb6b2015-05-11 22:53:22238} // namespace
[email protected]64860882014-08-04 23:44:17239
240//------------------------------------------------------------------------------
241
[email protected]64860882014-08-04 23:44:17242// static
danakj03de39b22016-04-23 04:21:09243std::unique_ptr<ChannelMojo> ChannelMojo::Create(
sammc57ed9f982016-03-10 06:28:35244 mojo::ScopedMessagePipeHandle handle,
245 Mode mode,
rockota34707ca2016-07-20 04:28:32246 Listener* listener,
247 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
248 return base::WrapUnique(
249 new ChannelMojo(std::move(handle), mode, listener, ipc_task_runner));
[email protected]64860882014-08-04 23:44:17250}
251
252// static
danakj03de39b22016-04-23 04:21:09253std::unique_ptr<ChannelFactory> ChannelMojo::CreateServerFactory(
rockota34707ca2016-07-20 04:28:32254 mojo::ScopedMessagePipeHandle handle,
255 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
ricead4fe03702016-09-05 05:06:18256 return base::MakeUnique<MojoChannelFactory>(
257 std::move(handle), Channel::MODE_SERVER, ipc_task_runner);
[email protected]64860882014-08-04 23:44:17258}
259
morrita54f6f80c2014-09-23 21:16:00260// static
danakj03de39b22016-04-23 04:21:09261std::unique_ptr<ChannelFactory> ChannelMojo::CreateClientFactory(
rockota34707ca2016-07-20 04:28:32262 mojo::ScopedMessagePipeHandle handle,
263 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
ricead4fe03702016-09-05 05:06:18264 return base::MakeUnique<MojoChannelFactory>(
265 std::move(handle), Channel::MODE_CLIENT, ipc_task_runner);
morrita54f6f80c2014-09-23 21:16:00266}
267
rockota34707ca2016-07-20 04:28:32268ChannelMojo::ChannelMojo(
269 mojo::ScopedMessagePipeHandle handle,
270 Mode mode,
271 Listener* listener,
272 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner)
rockot0e4de5f2016-07-22 21:18:07273 : pipe_(handle.get()), listener_(listener), weak_factory_(this) {
morrita54f6f80c2014-09-23 21:16:00274 // Create MojoBootstrap after all members are set as it touches
275 // ChannelMojo from a different thread.
rockot0e4de5f2016-07-22 21:18:07276 bootstrap_ =
277 MojoBootstrap::Create(std::move(handle), mode, this, ipc_task_runner);
[email protected]64860882014-08-04 23:44:17278}
279
280ChannelMojo::~ChannelMojo() {
281 Close();
morritae9453ea2014-09-26 03:20:48282}
morrita54f6f80c2014-09-23 21:16:00283
[email protected]64860882014-08-04 23:44:17284bool ChannelMojo::Connect() {
erikchen90971902016-04-25 23:45:31285 WillConnect();
rockot0e4de5f2016-07-22 21:18:07286
287 DCHECK(!task_runner_);
288 task_runner_ = base::ThreadTaskRunnerHandle::Get();
289 DCHECK(!message_reader_);
290
sammce4d0abd2016-03-07 22:38:04291 bootstrap_->Connect();
292 return true;
[email protected]64860882014-08-04 23:44:17293}
294
rockot10188752016-09-08 18:24:56295void ChannelMojo::Pause() {
296 bootstrap_->Pause();
297}
298
rockot401fb2c2016-09-06 18:35:57299void ChannelMojo::Unpause(bool flush) {
rockot10188752016-09-08 18:24:56300 bootstrap_->Unpause();
rockot401fb2c2016-09-06 18:35:57301 if (flush)
302 Flush();
303}
304
305void ChannelMojo::Flush() {
306 bootstrap_->Flush();
307}
308
[email protected]64860882014-08-04 23:44:17309void ChannelMojo::Close() {
rockot0e4de5f2016-07-22 21:18:07310 // NOTE: The MessagePipeReader's destructor may re-enter this function. Use
311 // caution when changing this method.
312 std::unique_ptr<internal::MessagePipeReader> reader =
313 std::move(message_reader_);
msramek5507fee2016-07-22 10:06:21314 reader.reset();
rockot0e4de5f2016-07-22 21:18:07315
316 base::AutoLock lock(associated_interface_lock_);
317 associated_interfaces_.clear();
sammce4d0abd2016-03-07 22:38:04318}
morritab4472142015-04-20 21:20:12319
sammce4d0abd2016-03-07 22:38:04320// MojoBootstrap::Delegate implementation
rockot0e4de5f2016-07-22 21:18:07321void ChannelMojo::OnPipesAvailable(mojom::ChannelAssociatedPtr sender,
322 mojom::ChannelAssociatedRequest receiver) {
rockot10188752016-09-08 18:24:56323 sender->SetPeerPid(GetSelfPID());
rockot0e4de5f2016-07-22 21:18:07324 message_reader_.reset(new internal::MessagePipeReader(
325 pipe_, std::move(sender), std::move(receiver), this));
[email protected]64860882014-08-04 23:44:17326}
327
rockot506f92fa22016-03-23 01:32:18328void ChannelMojo::OnPipeError() {
rockotc18f64f2016-03-25 04:49:18329 DCHECK(task_runner_);
rockot506f92fa22016-03-23 01:32:18330 if (task_runner_->RunsTasksOnCurrentThread()) {
331 listener_->OnChannelError();
332 } else {
333 task_runner_->PostTask(
334 FROM_HERE,
335 base::Bind(&ChannelMojo::OnPipeError, weak_factory_.GetWeakPtr()));
336 }
[email protected]64860882014-08-04 23:44:17337}
338
rockot0e4de5f2016-07-22 21:18:07339void ChannelMojo::OnAssociatedInterfaceRequest(
340 const std::string& name,
341 mojo::ScopedInterfaceEndpointHandle handle) {
342 GenericAssociatedInterfaceFactory factory;
343 {
344 base::AutoLock locker(associated_interface_lock_);
345 auto iter = associated_interfaces_.find(name);
346 if (iter != associated_interfaces_.end())
347 factory = iter->second;
msramek5507fee2016-07-22 10:06:21348 }
rockot508da2462016-07-22 03:53:59349
rockot0e4de5f2016-07-22 21:18:07350 if (!factory.is_null())
351 factory.Run(std::move(handle));
352}
353
354bool ChannelMojo::Send(Message* message) {
355 std::unique_ptr<Message> scoped_message = base::WrapUnique(message);
356 if (!message_reader_)
357 return false;
358
amistry1e355dd12016-07-11 21:33:28359 // Comment copied from ipc_channel_posix.cc:
360 // We can't close the pipe here, because calling OnChannelError may destroy
361 // this object, and that would be bad if we are called from Send(). Instead,
362 // we return false and hope the caller will close the pipe. If they do not,
363 // the pipe will still be closed next time OnFileCanReadWithoutBlocking is
364 // called.
365 //
366 // With Mojo, there's no OnFileCanReadWithoutBlocking, but we expect the
367 // pipe's connection error handler will be invoked in its place.
rockot0e4de5f2016-07-22 21:18:07368 return message_reader_->Send(std::move(scoped_message));
rockot506f92fa22016-03-23 01:32:18369}
370
371bool ChannelMojo::IsSendThreadSafe() const {
rockotf14a8ae2016-06-16 19:28:41372 return false;
[email protected]64860882014-08-04 23:44:17373}
374
375base::ProcessId ChannelMojo::GetPeerPID() const {
sammc57ed9f982016-03-10 06:28:35376 if (!message_reader_)
377 return base::kNullProcessId;
sammc57ed9f982016-03-10 06:28:35378 return message_reader_->GetPeerPid();
[email protected]64860882014-08-04 23:44:17379}
380
381base::ProcessId ChannelMojo::GetSelfPID() const {
rockot0e4de5f2016-07-22 21:18:07382#if defined(OS_LINUX)
383 if (int global_pid = GetGlobalPid())
384 return global_pid;
385#endif // OS_LINUX
386#if defined(OS_NACL)
387 return -1;
388#else
389 return base::GetCurrentProcId();
390#endif // defined(OS_NACL)
[email protected]64860882014-08-04 23:44:17391}
392
rockot7c6bf952016-07-14 00:34:11393Channel::AssociatedInterfaceSupport*
394ChannelMojo::GetAssociatedInterfaceSupport() { return this; }
395
rockot0e4de5f2016-07-22 21:18:07396void ChannelMojo::OnPeerPidReceived() {
397 listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
398}
399
sammce4d0abd2016-03-07 22:38:04400void ChannelMojo::OnMessageReceived(const Message& message) {
morrita7126b7a2014-12-17 19:01:40401 TRACE_EVENT2("ipc,toplevel", "ChannelMojo::OnMessageReceived",
402 "class", IPC_MESSAGE_ID_CLASS(message.type()),
403 "line", IPC_MESSAGE_ID_LINE(message.type()));
sammc57ed9f982016-03-10 06:28:35404 if (AttachmentBroker* broker = AttachmentBroker::GetGlobal()) {
405 if (broker->OnMessageReceived(message))
406 return;
407 }
[email protected]64860882014-08-04 23:44:17408 listener_->OnMessageReceived(message);
409 if (message.dispatch_error())
410 listener_->OnBadMessageReceived(message);
411}
412
amistrye309ea32016-06-06 03:20:49413#if defined(OS_POSIX) && !defined(OS_NACL_SFI)
[email protected]64860882014-08-04 23:44:17414int ChannelMojo::GetClientFileDescriptor() const {
sammce4d0abd2016-03-07 22:38:04415 return -1;
[email protected]64860882014-08-04 23:44:17416}
417
morritaa409ccc2014-10-20 23:53:25418base::ScopedFD ChannelMojo::TakeClientFileDescriptor() {
sammce4d0abd2016-03-07 22:38:04419 return base::ScopedFD(GetClientFileDescriptor());
[email protected]64860882014-08-04 23:44:17420}
amistrye309ea32016-06-06 03:20:49421#endif // defined(OS_POSIX) && !defined(OS_NACL_SFI)
morrita3b41d6c2014-09-11 19:06:29422
423// static
morrita4b5c28e22015-01-14 21:17:06424MojoResult ChannelMojo::ReadFromMessageAttachmentSet(
morrita96693852014-09-24 20:11:45425 Message* message,
yzshen24b40a32016-08-24 01:10:13426 base::Optional<std::vector<mojom::SerializedHandlePtr>>* handles) {
427 DCHECK(!*handles);
428
429 MojoResult result = MOJO_RESULT_OK;
430 if (!message->HasAttachments())
431 return result;
432
433 std::vector<mojom::SerializedHandlePtr> output_handles;
434 MessageAttachmentSet* set = message->attachment_set();
435
436 for (unsigned i = 0;
437 result == MOJO_RESULT_OK && i < set->num_non_brokerable_attachments();
438 ++i) {
439 result = WrapAttachment(set->GetNonBrokerableAttachmentAt(i).get(),
440 &output_handles);
morrita3b41d6c2014-09-11 19:06:29441 }
yzshen24b40a32016-08-24 01:10:13442 for (unsigned i = 0;
443 result == MOJO_RESULT_OK && i < set->num_brokerable_attachments(); ++i) {
444 result = WrapAttachment(set->GetBrokerableAttachmentAt(i).get(),
445 &output_handles);
446 }
447
448 set->CommitAllDescriptors();
449
450 if (!output_handles.empty())
451 *handles = std::move(output_handles);
452
453 return result;
morrita3b41d6c2014-09-11 19:06:29454}
455
morrita81b17e02015-02-06 00:58:30456// static
457MojoResult ChannelMojo::WriteToMessageAttachmentSet(
yzshen24b40a32016-08-24 01:10:13458 base::Optional<std::vector<mojom::SerializedHandlePtr>> handle_buffer,
morrita81b17e02015-02-06 00:58:30459 Message* message) {
yzshen24b40a32016-08-24 01:10:13460 if (!handle_buffer)
461 return MOJO_RESULT_OK;
462 for (size_t i = 0; i < handle_buffer->size(); ++i) {
sammc57ed9f982016-03-10 06:28:35463 scoped_refptr<MessageAttachment> unwrapped_attachment;
yzshen24b40a32016-08-24 01:10:13464 MojoResult unwrap_result =
465 UnwrapAttachment(std::move((*handle_buffer)[i]), &unwrapped_attachment);
sammc57ed9f982016-03-10 06:28:35466 if (unwrap_result != MOJO_RESULT_OK) {
467 LOG(WARNING) << "Pipe failed to unwrap handles. Closing: "
468 << unwrap_result;
469 return unwrap_result;
470 }
471 DCHECK(unwrapped_attachment);
472
morrita81b17e02015-02-06 00:58:30473 bool ok = message->attachment_set()->AddAttachment(
sammc57ed9f982016-03-10 06:28:35474 std::move(unwrapped_attachment));
morrita81b17e02015-02-06 00:58:30475 DCHECK(ok);
476 if (!ok) {
morritaa3889aa2015-03-16 22:40:51477 LOG(ERROR) << "Failed to add new Mojo handle.";
morrita81b17e02015-02-06 00:58:30478 return MOJO_RESULT_UNKNOWN;
479 }
480 }
morrita81b17e02015-02-06 00:58:30481 return MOJO_RESULT_OK;
482}
[email protected]64860882014-08-04 23:44:17483
rockot7c6bf952016-07-14 00:34:11484mojo::AssociatedGroup* ChannelMojo::GetAssociatedGroup() {
485 DCHECK(bootstrap_);
486 return bootstrap_->GetAssociatedGroup();
487}
488
489void ChannelMojo::AddGenericAssociatedInterface(
490 const std::string& name,
491 const GenericAssociatedInterfaceFactory& factory) {
rockot0e4de5f2016-07-22 21:18:07492 base::AutoLock locker(associated_interface_lock_);
rockot7c6bf952016-07-14 00:34:11493 auto result = associated_interfaces_.insert({ name, factory });
494 DCHECK(result.second);
495}
496
497void ChannelMojo::GetGenericRemoteAssociatedInterface(
498 const std::string& name,
499 mojo::ScopedInterfaceEndpointHandle handle) {
rockot0e4de5f2016-07-22 21:18:07500 if (message_reader_)
501 message_reader_->GetRemoteInterface(name, std::move(handle));
rockot8d890f62016-07-14 16:37:14502}
503
[email protected]64860882014-08-04 23:44:17504} // namespace IPC