Chromium Code Reviews| Index: ipc/mojo/ipc_channel_mojo.cc |
| diff --git a/ipc/mojo/ipc_channel_mojo.cc b/ipc/mojo/ipc_channel_mojo.cc |
| index cdb928175dabcfda3104553ad88846b026b952b6..3a713d30c8e7289e07b63b6a50d325f2aa492bb3 100644 |
| --- a/ipc/mojo/ipc_channel_mojo.cc |
| +++ b/ipc/mojo/ipc_channel_mojo.cc |
| @@ -8,6 +8,7 @@ |
| #include "base/bind_helpers.h" |
| #include "base/lazy_instance.h" |
| #include "ipc/ipc_listener.h" |
| +#include "ipc/mojo/ipc_channel_mojo_readers.h" |
| #include "mojo/embedder/embedder.h" |
| #if defined(OS_POSIX) && !defined(OS_NACL) |
| @@ -82,371 +83,10 @@ mojo::embedder::PlatformHandle ToPlatformHandle( |
| #endif |
| } |
| -//------------------------------------------------------------------------------ |
| - |
| -// TODO(morrita): This should be built using higher-level Mojo construct |
| -// for clarity and extensibility. |
| -class HelloMessage { |
| - public: |
| - static Pickle CreateRequest(int32 pid) { |
| - Pickle request; |
| - request.WriteString(kHelloRequestMagic); |
| - request.WriteInt(pid); |
| - return request; |
| - } |
| - |
| - static bool ReadRequest(Pickle& pickle, int32* pid) { |
| - PickleIterator iter(pickle); |
| - std::string hello; |
| - if (!iter.ReadString(&hello)) { |
| - DLOG(WARNING) << "Failed to Read magic string."; |
| - return false; |
| - } |
| - |
| - if (hello != kHelloRequestMagic) { |
| - DLOG(WARNING) << "Magic mismatch:" << hello; |
| - return false; |
| - } |
| - |
| - int read_pid; |
| - if (!iter.ReadInt(&read_pid)) { |
| - DLOG(WARNING) << "Failed to Read PID."; |
| - return false; |
| - } |
| - |
| - *pid = read_pid; |
| - return true; |
| - } |
| - |
| - static Pickle CreateResponse(int32 pid) { |
| - Pickle request; |
| - request.WriteString(kHelloResponseMagic); |
| - request.WriteInt(pid); |
| - return request; |
| - } |
| - |
| - static bool ReadResponse(Pickle& pickle, int32* pid) { |
| - PickleIterator iter(pickle); |
| - std::string hello; |
| - if (!iter.ReadString(&hello)) { |
| - DLOG(WARNING) << "Failed to read magic string."; |
| - return false; |
| - } |
| - |
| - if (hello != kHelloResponseMagic) { |
| - DLOG(WARNING) << "Magic mismatch:" << hello; |
| - return false; |
| - } |
| - |
| - int read_pid; |
| - if (!iter.ReadInt(&read_pid)) { |
| - DLOG(WARNING) << "Failed to read PID."; |
| - return false; |
| - } |
| - |
| - *pid = read_pid; |
| - return true; |
| - } |
| - |
| - private: |
| - static const char* kHelloRequestMagic; |
| - static const char* kHelloResponseMagic; |
| -}; |
| - |
| -const char* HelloMessage::kHelloRequestMagic = "MREQ"; |
| -const char* HelloMessage::kHelloResponseMagic = "MRES"; |
| - |
| } // namespace |
| //------------------------------------------------------------------------------ |
| -// A MessagePipeReader implemenation for IPC::Message communication. |
| -class ChannelMojo::MessageReader : public internal::MessagePipeReader { |
| - public: |
| - MessageReader(mojo::ScopedMessagePipeHandle pipe, ChannelMojo* owner) |
| - : internal::MessagePipeReader(pipe.Pass()), |
| - owner_(owner) {} |
| - |
| - bool Send(scoped_ptr<Message> message); |
| - virtual void OnMessageReceived() OVERRIDE; |
| - virtual void OnPipeClosed() OVERRIDE; |
| - virtual void OnPipeError(MojoResult error) OVERRIDE; |
| - |
| - private: |
| - ChannelMojo* owner_; |
| -}; |
| - |
| -void ChannelMojo::MessageReader::OnMessageReceived() { |
| - Message message(data_buffer().empty() ? "" : &data_buffer()[0], |
| - static_cast<uint32>(data_buffer().size())); |
| - |
| - std::vector<MojoHandle> handle_buffer; |
| - TakeHandleBuffer(&handle_buffer); |
| -#if defined(OS_POSIX) && !defined(OS_NACL) |
| - for (size_t i = 0; i < handle_buffer.size(); ++i) { |
| - mojo::embedder::ScopedPlatformHandle platform_handle; |
| - MojoResult unwrap_result = mojo::embedder::PassWrappedPlatformHandle( |
| - handle_buffer[i], &platform_handle); |
| - if (unwrap_result != MOJO_RESULT_OK) { |
| - DLOG(WARNING) << "Pipe failed to covert handles. Closing: " |
| - << unwrap_result; |
| - CloseWithError(unwrap_result); |
| - return; |
| - } |
| - |
| - bool ok = message.file_descriptor_set()->Add(platform_handle.release().fd); |
| - DCHECK(ok); |
| - } |
| -#else |
| - DCHECK(handle_buffer.empty()); |
| -#endif |
| - |
| - message.TraceMessageEnd(); |
| - owner_->OnMessageReceived(message); |
| -} |
| - |
| -void ChannelMojo::MessageReader::OnPipeClosed() { |
| - if (!owner_) |
| - return; |
| - owner_->OnPipeClosed(this); |
| - owner_ = NULL; |
| -} |
| - |
| -void ChannelMojo::MessageReader::OnPipeError(MojoResult error) { |
| - if (!owner_) |
| - return; |
| - owner_->OnPipeError(this); |
| -} |
| - |
| -bool ChannelMojo::MessageReader::Send(scoped_ptr<Message> message) { |
| - DCHECK(IsValid()); |
| - |
| - message->TraceMessageBegin(); |
| - std::vector<MojoHandle> handles; |
| -#if defined(OS_POSIX) && !defined(OS_NACL) |
| - // We dup() the handles in IPC::Message to transmit. |
| - // IPC::FileDescriptorSet has intricate lifecycle semantics |
| - // of FDs, so just to dup()-and-own them is the safest option. |
| - if (message->HasFileDescriptors()) { |
| - FileDescriptorSet* fdset = message->file_descriptor_set(); |
| - for (size_t i = 0; i < fdset->size(); ++i) { |
| - int fd_to_send = dup(fdset->GetDescriptorAt(i)); |
| - if (-1 == fd_to_send) { |
| - DPLOG(WARNING) << "Failed to dup FD to transmit."; |
| - std::for_each(handles.begin(), handles.end(), &MojoClose); |
| - CloseWithError(MOJO_RESULT_UNKNOWN); |
| - return false; |
| - } |
| - |
| - MojoHandle wrapped_handle; |
| - MojoResult wrap_result = CreatePlatformHandleWrapper( |
| - mojo::embedder::ScopedPlatformHandle( |
| - mojo::embedder::PlatformHandle(fd_to_send)), |
| - &wrapped_handle); |
| - if (MOJO_RESULT_OK != wrap_result) { |
| - DLOG(WARNING) << "Pipe failed to wrap handles. Closing: " |
| - << wrap_result; |
| - std::for_each(handles.begin(), handles.end(), &MojoClose); |
| - CloseWithError(wrap_result); |
| - return false; |
| - } |
| - |
| - handles.push_back(wrapped_handle); |
| - } |
| - } |
| -#endif |
| - MojoResult write_result = MojoWriteMessage( |
| - handle(), |
| - message->data(), static_cast<uint32>(message->size()), |
| - handles.empty() ? NULL : &handles[0], |
| - static_cast<uint32>(handles.size()), |
| - MOJO_WRITE_MESSAGE_FLAG_NONE); |
| - if (MOJO_RESULT_OK != write_result) { |
| - std::for_each(handles.begin(), handles.end(), &MojoClose); |
| - CloseWithError(write_result); |
| - return false; |
| - } |
| - |
| - return true; |
| -} |
| - |
| -//------------------------------------------------------------------------------ |
| - |
| -// MessagePipeReader implementation for control messages. |
| -// Actual message handling is implemented by sublcasses. |
| -class ChannelMojo::ControlReader : public internal::MessagePipeReader { |
| - public: |
| - ControlReader(mojo::ScopedMessagePipeHandle pipe, ChannelMojo* owner) |
| - : internal::MessagePipeReader(pipe.Pass()), |
| - owner_(owner) {} |
| - |
| - virtual bool Connect() { return true; } |
| - virtual void OnPipeClosed() OVERRIDE; |
| - virtual void OnPipeError(MojoResult error) OVERRIDE; |
| - |
| - protected: |
| - ChannelMojo* owner_; |
| -}; |
| - |
| -void ChannelMojo::ControlReader::OnPipeClosed() { |
| - if (!owner_) |
| - return; |
| - owner_->OnPipeClosed(this); |
| - owner_ = NULL; |
| -} |
| - |
| -void ChannelMojo::ControlReader::OnPipeError(MojoResult error) { |
| - if (!owner_) |
| - return; |
| - owner_->OnPipeError(this); |
| -} |
| - |
| -//------------------------------------------------------------------------------ |
| - |
| -// ControlReader for server-side ChannelMojo. |
| -class ChannelMojo::ServerControlReader : public ChannelMojo::ControlReader { |
| - public: |
| - ServerControlReader(mojo::ScopedMessagePipeHandle pipe, ChannelMojo* owner) |
| - : ControlReader(pipe.Pass(), owner) { } |
| - |
| - virtual bool Connect() OVERRIDE; |
| - virtual void OnMessageReceived() OVERRIDE; |
| - |
| - private: |
| - MojoResult SendHelloRequest(); |
| - MojoResult RespondHelloResponse(); |
| - |
| - mojo::ScopedMessagePipeHandle message_pipe_; |
| -}; |
| - |
| -bool ChannelMojo::ServerControlReader::Connect() { |
| - MojoResult result = SendHelloRequest(); |
| - if (result != MOJO_RESULT_OK) { |
| - CloseWithError(result); |
| - return false; |
| - } |
| - |
| - return true; |
| -} |
| - |
| -MojoResult ChannelMojo::ServerControlReader::SendHelloRequest() { |
| - DCHECK(IsValid()); |
| - DCHECK(!message_pipe_.is_valid()); |
| - |
| - mojo::ScopedMessagePipeHandle self; |
| - mojo::ScopedMessagePipeHandle peer; |
| - MojoResult create_result = mojo::CreateMessagePipe( |
| - NULL, &message_pipe_, &peer); |
| - if (MOJO_RESULT_OK != create_result) { |
| - DLOG(WARNING) << "mojo::CreateMessagePipe failed: " << create_result; |
| - return create_result; |
| - } |
| - |
| - MojoHandle peer_to_send = peer.get().value(); |
| - Pickle request = HelloMessage::CreateRequest(owner_->GetSelfPID()); |
| - MojoResult write_result = MojoWriteMessage( |
| - handle(), |
| - request.data(), static_cast<uint32>(request.size()), |
| - &peer_to_send, 1, |
| - MOJO_WRITE_MESSAGE_FLAG_NONE); |
| - if (MOJO_RESULT_OK != write_result) { |
| - DLOG(WARNING) << "Writing Hello request failed: " << create_result; |
| - return write_result; |
| - } |
| - |
| - // |peer| is sent and no longer owned by |this|. |
| - (void)peer.release(); |
| - return MOJO_RESULT_OK; |
| -} |
| - |
| -MojoResult ChannelMojo::ServerControlReader::RespondHelloResponse() { |
| - Pickle request(data_buffer().empty() ? "" : &data_buffer()[0], |
| - static_cast<uint32>(data_buffer().size())); |
| - |
| - int32 read_pid = 0; |
| - if (!HelloMessage::ReadResponse(request, &read_pid)) { |
| - DLOG(ERROR) << "Failed to parse Hello response."; |
| - return MOJO_RESULT_UNKNOWN; |
| - } |
| - |
| - base::ProcessId pid = static_cast<base::ProcessId>(read_pid); |
| - owner_->set_peer_pid(pid); |
| - owner_->OnConnected(message_pipe_.Pass()); |
| - return MOJO_RESULT_OK; |
| -} |
| - |
| -void ChannelMojo::ServerControlReader::OnMessageReceived() { |
| - MojoResult result = RespondHelloResponse(); |
| - if (result != MOJO_RESULT_OK) |
| - CloseWithError(result); |
| -} |
| - |
| -//------------------------------------------------------------------------------ |
| - |
| -// ControlReader for client-side ChannelMojo. |
| -class ChannelMojo::ClientControlReader : public ChannelMojo::ControlReader { |
| - public: |
| - ClientControlReader(mojo::ScopedMessagePipeHandle pipe, ChannelMojo* owner) |
| - : ControlReader(pipe.Pass(), owner) {} |
| - |
| - virtual void OnMessageReceived() OVERRIDE; |
| - |
| - private: |
| - MojoResult RespondHelloRequest(MojoHandle message_channel); |
| -}; |
| - |
| -MojoResult ChannelMojo::ClientControlReader::RespondHelloRequest( |
| - MojoHandle message_channel) { |
| - DCHECK(IsValid()); |
| - |
| - mojo::ScopedMessagePipeHandle received_pipe( |
| - (mojo::MessagePipeHandle(message_channel))); |
| - |
| - int32 read_request = 0; |
| - Pickle request(data_buffer().empty() ? "" : &data_buffer()[0], |
| - static_cast<uint32>(data_buffer().size())); |
| - if (!HelloMessage::ReadRequest(request, &read_request)) { |
| - DLOG(ERROR) << "Hello request has wrong magic."; |
| - return MOJO_RESULT_UNKNOWN; |
| - } |
| - |
| - base::ProcessId pid = read_request; |
| - Pickle response = HelloMessage::CreateResponse(owner_->GetSelfPID()); |
| - MojoResult write_result = MojoWriteMessage( |
| - handle(), |
| - response.data(), static_cast<uint32>(response.size()), |
| - NULL, 0, |
| - MOJO_WRITE_MESSAGE_FLAG_NONE); |
| - if (MOJO_RESULT_OK != write_result) { |
| - DLOG(ERROR) << "Writing Hello response failed: " << write_result; |
| - return write_result; |
| - } |
| - |
| - owner_->set_peer_pid(pid); |
| - owner_->OnConnected(received_pipe.Pass()); |
| - return MOJO_RESULT_OK; |
| -} |
| - |
| -void ChannelMojo::ClientControlReader::OnMessageReceived() { |
| - std::vector<MojoHandle> handle_buffer; |
| - TakeHandleBuffer(&handle_buffer); |
| - if (handle_buffer.size() != 1) { |
| - DLOG(ERROR) << "Hello request doesn't contains required handle: " |
| - << handle_buffer.size(); |
| - CloseWithError(MOJO_RESULT_UNKNOWN); |
| - return; |
| - } |
| - |
| - MojoResult result = RespondHelloRequest(handle_buffer[0]); |
| - if (result != MOJO_RESULT_OK) { |
| - DLOG(ERROR) << "Failed to respond Hello request. Closing: " |
| - << result; |
| - CloseWithError(result); |
| - } |
| -} |
| - |
| -//------------------------------------------------------------------------------ |
| - |
| void ChannelMojo::ChannelInfoDeleter::operator()( |
| mojo::embedder::ChannelInfo* ptr) const { |
| mojo::embedder::DestroyChannelOnIOThread(ptr); |
| @@ -458,9 +98,8 @@ void ChannelMojo::ChannelInfoDeleter::operator()( |
| scoped_ptr<ChannelMojo> ChannelMojo::Create( |
| const ChannelHandle &channel_handle, Mode mode, Listener* listener, |
| scoped_refptr<base::TaskRunner> io_thread_task_runner) { |
| - return make_scoped_ptr(new ChannelMojo( |
| - Channel::Create(channel_handle, mode, g_null_listener.Pointer()), |
| - mode, listener, io_thread_task_runner)); |
| + return make_scoped_ptr( |
| + new ChannelMojo(channel_handle, mode, listener, io_thread_task_runner)); |
| } |
| // static |
| @@ -473,11 +112,14 @@ scoped_ptr<ChannelFactory> ChannelMojo::CreateFactory( |
| io_thread_task_runner)).PassAs<ChannelFactory>(); |
| } |
| -ChannelMojo::ChannelMojo( |
| - scoped_ptr<Channel> bootstrap, Mode mode, Listener* listener, |
| - scoped_refptr<base::TaskRunner> io_thread_task_runner) |
| - : bootstrap_(bootstrap.Pass()), |
| - mode_(mode), listener_(listener), |
| +ChannelMojo::ChannelMojo(const ChannelHandle& channel_handle, |
| + Mode mode, |
| + Listener* listener, |
| + scoped_refptr<base::TaskRunner> io_thread_task_runner) |
| + : bootstrap_( |
| + Channel::Create(channel_handle, mode, g_null_listener.Pointer())), |
| + mode_(mode), |
| + listener_(listener), |
| peer_pid_(base::kNullProcessId), |
| weak_factory_(this) { |
| if (base::MessageLoopProxy::current() == io_thread_task_runner.get()) { |
| @@ -504,10 +146,12 @@ void ChannelMojo::InitOnIOThread() { |
| switch (mode_) { |
| case MODE_SERVER: |
| - control_reader_.reset(new ServerControlReader(control_pipe.Pass(), this)); |
| + control_reader_.reset( |
| + new internal::ServerControlReader(control_pipe.Pass(), this)); |
| break; |
| case MODE_CLIENT: |
| - control_reader_.reset(new ClientControlReader(control_pipe.Pass(), this)); |
| + control_reader_.reset( |
| + new internal::ClientControlReader(control_pipe.Pass(), this)); |
| break; |
| default: |
| NOTREACHED(); |
| @@ -527,7 +171,8 @@ void ChannelMojo::Close() { |
| } |
| void ChannelMojo::OnConnected(mojo::ScopedMessagePipeHandle pipe) { |
| - message_reader_ = make_scoped_ptr(new MessageReader(pipe.Pass(), this)); |
| + message_reader_ = |
| + make_scoped_ptr(new internal::MessageReader(pipe.Pass(), this)); |
| for (size_t i = 0; i < pending_messages_.size(); ++i) { |
| message_reader_->Send(make_scoped_ptr(pending_messages_[i])); |
| @@ -583,6 +228,62 @@ int ChannelMojo::GetClientFileDescriptor() const { |
| int ChannelMojo::TakeClientFileDescriptor() { |
| return bootstrap_->TakeClientFileDescriptor(); |
| } |
| + |
| +// static |
| +MojoResult ChannelMojo::WriteToFileDescriptorSet( |
| + Message& message, |
| + const std::vector<MojoHandle>& handle_buffer) { |
| + for (size_t i = 0; i < handle_buffer.size(); ++i) { |
| + mojo::embedder::ScopedPlatformHandle platform_handle; |
| + MojoResult unwrap_result = mojo::embedder::PassWrappedPlatformHandle( |
| + handle_buffer[i], &platform_handle); |
| + if (unwrap_result != MOJO_RESULT_OK) { |
| + DLOG(WARNING) << "Pipe failed to covert handles. Closing: " |
| + << unwrap_result; |
| + return false; |
|
yzshen1
2014/09/09 23:52:39
This is supposed to be a MojoResult.
|
| + } |
| + |
| + bool ok = message.file_descriptor_set()->Add(platform_handle.release().fd); |
| + DCHECK(ok); |
| + } |
| + |
| + return MOJO_RESULT_OK; |
| +} |
| + |
| +// static |
| +MojoResult ChannelMojo::ReadFromFileDescriptorSet( |
| + const Message& message, |
| + std::vector<MojoHandle>& handles) { |
| + // We dup() the handles in IPC::Message to transmit. |
| + // IPC::FileDescriptorSet has intricate lifecycle semantics |
| + // of FDs, so just to dup()-and-own them is the safest option. |
| + if (message.HasFileDescriptors()) { |
| + const FileDescriptorSet* fdset = message.file_descriptor_set(); |
| + for (size_t i = 0; i < fdset->size(); ++i) { |
| + int fd_to_send = dup(fdset->GetDescriptorAt(i)); |
| + if (-1 == fd_to_send) { |
| + DPLOG(WARNING) << "Failed to dup FD to transmit."; |
| + return MOJO_RESULT_UNKNOWN; |
| + } |
| + |
| + MojoHandle wrapped_handle; |
| + MojoResult wrap_result = CreatePlatformHandleWrapper( |
| + mojo::embedder::ScopedPlatformHandle( |
| + mojo::embedder::PlatformHandle(fd_to_send)), |
| + &wrapped_handle); |
| + if (MOJO_RESULT_OK != wrap_result) { |
| + DLOG(WARNING) << "Pipe failed to wrap handles. Closing: " |
| + << wrap_result; |
| + return wrap_result; |
| + } |
| + |
| + handles.push_back(wrapped_handle); |
| + } |
| + } |
| + |
| + return MOJO_RESULT_OK; |
| +} |
| + |
| #endif // defined(OS_POSIX) && !defined(OS_NACL) |
| } // namespace IPC |