| 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..e89ccc1624426d82882af664c3dd8722e7973f95 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,31 +12,138 @@
|
| #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: {
|
| + 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_MESSAGE;
|
| + ::ReadFile(read_file_, &(pending_message_)[0], message_length, NULL,
|
| + &read_context_->overlapped);
|
| + return;
|
| + }
|
| + case READ_STATE_WAITING_FOR_MESSAGE:
|
| + AddToOverlappedOffset(&read_context_->overlapped, bytes_transfered);
|
| +
|
| + // Verify that the entire message was read.
|
| + if (bytes_transfered != pending_message_.size()) {
|
| + 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;
|
| +
|
| + MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this);
|
| +
|
| + read_context_->handler = NULL;
|
| + write_context_->handler = NULL;
|
| +
|
| + read_context_.reset();
|
| + write_context_.reset();
|
| +
|
| + // Because of the asynchronous IO, ::CloseHandle() may return a non-zero
|
| + // status. This is expected, but will trigger a CHECK in
|
| + // ScopedHandle::Close(). To circumvent this, we will take ownership of the
|
| + // raw handle and close it manually.
|
| + ::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);
|
|
|
| -bool NativeMessageProcessHost::ReadData(FileHandle file,
|
| - char* data,
|
| - size_t bytes_to_read) {
|
| - NOTREACHED();
|
| - return false;
|
| + return result || ::GetLastError() == ERROR_IO_PENDING;
|
| }
|
|
|
| } // namespace extensions
|
|
|