Chromium Code Reviews| Index: chrome/browser/extensions/api/messaging/native_message_process_host_win.cc |
| diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host_win.cc b/chrome/browser/extensions/api/messaging/native_message_process_host_win.cc |
| index a9a6819f67ba595aaadfcb8c101f7814d29761f3..a159cac156d7586bc740ad854d961d0a16144bd8 100644 |
| --- a/chrome/browser/extensions/api/messaging/native_message_process_host_win.cc |
| +++ b/chrome/browser/extensions/api/messaging/native_message_process_host_win.cc |
| @@ -12,29 +12,146 @@ |
| #include "base/process_util.h" |
| #include "content/public/browser/browser_thread.h" |
| +namespace { |
| + |
| +void AddToOverlappedOffset(OVERLAPPED* overlapped, uint32 to_add) { |
| + uint64 full_offset = |
| + static_cast<uint64>(overlapped->OffsetHigh) << 32 | overlapped->Offset; |
| + full_offset += to_add; |
| + overlapped->Offset = full_offset & 0x00000000ffffffff; |
| + overlapped->OffsetHigh = full_offset >> 32; |
| +} |
| + |
| +} // namespace |
| + |
| namespace extensions { |
| +void NativeMessageProcessHost::ReadNowForTesting() { |
| +} |
| + |
| void NativeMessageProcessHost::OnIOCompleted( |
| MessageLoopForIO::IOContext* context, |
| DWORD bytes_transfered, |
| DWORD error) { |
| - NOTREACHED(); |
| + if (error != 0) { |
| + if (native_process_handle_ != base::kNullProcessHandle && |
| + base::GetTerminationStatus(native_process_handle_, NULL) != |
| + base::TERMINATION_STATUS_STILL_RUNNING) { |
| + // Notify the message service that the channel should close. |
| + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| + base::Bind(&Client::CloseChannel, weak_client_ui_, |
| + destination_port_, true)); |
| + } |
| + return; |
| + } |
| + |
| + if (context == read_context_.get()) { |
| + switch (read_state) { |
| + case READ_STATE_INVALID: |
| + // This could be the case on destruction. |
| + return; |
| + case READ_STATE_WAITING_FOR_META: |
| + { |
|
Matt Perry
2012/10/24 23:40:31
nit: common chrome style is to put the { on the sa
eaugusti
2012/10/30 22:03:12
Done.
|
| + AddToOverlappedOffset(&read_context_->overlapped, bytes_transfered); |
| + |
| + MessageType type; |
| + uint32 message_length = 0; |
| + if (!VerifyMessageMetaData(pending_message_meta_data_, &type, |
| + &message_length)) { |
| + return; |
| + } |
| + pending_message_.resize(message_length, '\0'); |
| + // Try to read the full message. |
| + read_state = READ_STATE_WAITING_FOR_MESSGAE; |
| + ::ReadFile(read_file_, &(pending_message_)[0], message_length, NULL, |
| + &read_context_->overlapped); |
| + return; |
| + } |
| + case READ_STATE_WAITING_FOR_MESSGAE: |
| + AddToOverlappedOffset(&read_context_->overlapped, bytes_transfered); |
| + |
| + // Verify that the entire message was read. |
| + if (bytes_transfered != pending_message_.size()) { |
|
Matt Perry
2012/10/24 23:40:31
Are you guaranteed that the entire contents is rea
eaugusti
2012/10/30 22:03:12
According to the documentation, it should be. But,
|
| + LOG(ERROR) << "Could not read entire message."; |
| + return; |
| + } |
| + // Send the current message |
| + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| + base::Bind(&Client::PostMessageFromNativeProcess, weak_client_ui_, |
| + destination_port_, pending_message_)); |
| + // Do not try to read another message if this is only a |
| + // sendNativeMessage(). |
| + if (is_send_message_) { |
| + read_state = READ_STATE_INVALID; |
| + } else { |
| + // Start the read for the next message. |
| + read_state = READ_STATE_WAITING_FOR_META; |
| + ::ReadFile(read_file_, &pending_message_meta_data_, 8, NULL, |
| + &read_context_->overlapped); |
| + } |
| + return; |
| + default: |
| + NOTREACHED(); |
| + return; |
| + } |
| + } else { |
| + DCHECK(context == write_context_.get()); |
| + } |
| } |
| void NativeMessageProcessHost::InitIO() { |
| - NOTREACHED(); |
| + read_context_.reset(new MessageLoopForIO::IOContext()); |
| + write_context_.reset(new MessageLoopForIO::IOContext()); |
| + |
| + memset(&read_context_->overlapped, 0, sizeof(read_context_->overlapped)); |
| + memset(&write_context_->overlapped, 0, sizeof(write_context_->overlapped)); |
| + |
| + read_context_->handler = this; |
| + write_context_->handler = this; |
| + |
| + MessageLoopForIO::current()->RegisterIOHandler(read_file_, this); |
| + |
| + // Make a request for the type and length of the first message. |
| + read_state = READ_STATE_WAITING_FOR_META; |
| + ::ReadFile(read_file_, &pending_message_meta_data_, 8, NULL, |
| + &read_context_->overlapped); |
| +} |
| + |
| +void NativeMessageProcessHost::StopIO() { |
| + read_state = READ_STATE_INVALID; |
| + |
| + ::CancelIo(read_file_); |
| + ::CancelIo(write_file_); |
| + |
| + MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this); |
|
Matt Perry
2012/10/24 23:40:31
We generally don't want to block any thread. Is th
eaugusti
2012/10/30 22:03:12
Yeah, I think it is. ipc_channel_win does it and i
|
| + |
| + read_context_->handler = NULL; |
| + write_context_->handler = NULL; |
| + |
| + read_context_.reset(); |
| + write_context_.reset(); |
| + |
| + // Because of possible overlapped IO, the handles may not close cleanly but |
| + // with a non-zero status. We have to circumvent ScopedHandle::Close(). |
|
Matt Perry
2012/10/24 23:40:31
I don't follow this comment.
eaugusti
2012/10/30 22:03:12
Done.
|
| + ::CloseHandle(scoped_read_file_.Take()); |
| + ::CloseHandle(scoped_write_file_.Take()); |
| } |
| bool NativeMessageProcessHost::WriteData(FileHandle file, |
| const char* data, |
| size_t bytes_to_write) { |
| - NOTREACHED(); |
| - return false; |
| + DWORD bytes_written = 0; |
| + ::SetLastError(0); |
| + BOOL result = ::WriteFile(file, data, bytes_to_write, &bytes_written, |
| + &write_context_->overlapped); |
| + |
| + return result || ::GetLastError() == ERROR_IO_PENDING; |
| } |
| bool NativeMessageProcessHost::ReadData(FileHandle file, |
| char* data, |
| size_t bytes_to_read) { |
| + // Not used by win. |
|
Matt Perry
2012/10/24 23:40:31
Then why not #ifdef it out in the header? ReadMess
eaugusti
2012/10/30 22:03:12
Done.
|
| NOTREACHED(); |
| return false; |
| } |