Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/extensions/api/messaging/native_message_process_host.h" | 5 #include "chrome/browser/extensions/api/messaging/native_message_process_host.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_pump_win.h" | 10 #include "base/message_pump_win.h" |
| 11 #include "base/platform_file.h" | 11 #include "base/platform_file.h" |
| 12 #include "base/process_util.h" | 12 #include "base/process_util.h" |
| 13 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
| 14 | 14 |
| 15 namespace { | |
| 16 | |
| 17 void AddToOverlappedOffset(OVERLAPPED* overlapped, uint32 to_add) { | |
| 18 uint64 full_offset = | |
| 19 static_cast<uint64>(overlapped->OffsetHigh) << 32 | overlapped->Offset; | |
| 20 full_offset += to_add; | |
| 21 overlapped->Offset = full_offset & 0x00000000ffffffff; | |
| 22 overlapped->OffsetHigh = full_offset >> 32; | |
| 23 } | |
| 24 | |
| 25 } // namespace | |
| 26 | |
| 15 namespace extensions { | 27 namespace extensions { |
| 16 | 28 |
| 29 void NativeMessageProcessHost::ReadNowForTesting() { | |
| 30 } | |
| 31 | |
| 17 void NativeMessageProcessHost::OnIOCompleted( | 32 void NativeMessageProcessHost::OnIOCompleted( |
| 18 MessageLoopForIO::IOContext* context, | 33 MessageLoopForIO::IOContext* context, |
| 19 DWORD bytes_transfered, | 34 DWORD bytes_transfered, |
| 20 DWORD error) { | 35 DWORD error) { |
| 21 NOTREACHED(); | 36 if (error != 0) { |
| 37 if (native_process_handle_ != base::kNullProcessHandle && | |
| 38 base::GetTerminationStatus(native_process_handle_, NULL) != | |
| 39 base::TERMINATION_STATUS_STILL_RUNNING) { | |
| 40 // Notify the message service that the channel should close. | |
| 41 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | |
| 42 base::Bind(&Client::CloseChannel, weak_client_ui_, | |
| 43 destination_port_, true)); | |
| 44 } | |
| 45 return; | |
| 46 } | |
| 47 | |
| 48 if (context == read_context_.get()) { | |
| 49 switch (read_state) { | |
| 50 case READ_STATE_INVALID: | |
| 51 // This could be the case on destruction. | |
| 52 return; | |
| 53 case READ_STATE_WAITING_FOR_META: | |
| 54 { | |
|
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.
| |
| 55 AddToOverlappedOffset(&read_context_->overlapped, bytes_transfered); | |
| 56 | |
| 57 MessageType type; | |
| 58 uint32 message_length = 0; | |
| 59 if (!VerifyMessageMetaData(pending_message_meta_data_, &type, | |
| 60 &message_length)) { | |
| 61 return; | |
| 62 } | |
| 63 pending_message_.resize(message_length, '\0'); | |
| 64 // Try to read the full message. | |
| 65 read_state = READ_STATE_WAITING_FOR_MESSGAE; | |
| 66 ::ReadFile(read_file_, &(pending_message_)[0], message_length, NULL, | |
| 67 &read_context_->overlapped); | |
| 68 return; | |
| 69 } | |
| 70 case READ_STATE_WAITING_FOR_MESSGAE: | |
| 71 AddToOverlappedOffset(&read_context_->overlapped, bytes_transfered); | |
| 72 | |
| 73 // Verify that the entire message was read. | |
| 74 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,
| |
| 75 LOG(ERROR) << "Could not read entire message."; | |
| 76 return; | |
| 77 } | |
| 78 // Send the current message | |
| 79 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | |
| 80 base::Bind(&Client::PostMessageFromNativeProcess, weak_client_ui_, | |
| 81 destination_port_, pending_message_)); | |
| 82 // Do not try to read another message if this is only a | |
| 83 // sendNativeMessage(). | |
| 84 if (is_send_message_) { | |
| 85 read_state = READ_STATE_INVALID; | |
| 86 } else { | |
| 87 // Start the read for the next message. | |
| 88 read_state = READ_STATE_WAITING_FOR_META; | |
| 89 ::ReadFile(read_file_, &pending_message_meta_data_, 8, NULL, | |
| 90 &read_context_->overlapped); | |
| 91 } | |
| 92 return; | |
| 93 default: | |
| 94 NOTREACHED(); | |
| 95 return; | |
| 96 } | |
| 97 } else { | |
| 98 DCHECK(context == write_context_.get()); | |
| 99 } | |
| 22 } | 100 } |
| 23 | 101 |
| 24 void NativeMessageProcessHost::InitIO() { | 102 void NativeMessageProcessHost::InitIO() { |
| 25 NOTREACHED(); | 103 read_context_.reset(new MessageLoopForIO::IOContext()); |
| 104 write_context_.reset(new MessageLoopForIO::IOContext()); | |
| 105 | |
| 106 memset(&read_context_->overlapped, 0, sizeof(read_context_->overlapped)); | |
| 107 memset(&write_context_->overlapped, 0, sizeof(write_context_->overlapped)); | |
| 108 | |
| 109 read_context_->handler = this; | |
| 110 write_context_->handler = this; | |
| 111 | |
| 112 MessageLoopForIO::current()->RegisterIOHandler(read_file_, this); | |
| 113 | |
| 114 // Make a request for the type and length of the first message. | |
| 115 read_state = READ_STATE_WAITING_FOR_META; | |
| 116 ::ReadFile(read_file_, &pending_message_meta_data_, 8, NULL, | |
| 117 &read_context_->overlapped); | |
| 118 } | |
| 119 | |
| 120 void NativeMessageProcessHost::StopIO() { | |
| 121 read_state = READ_STATE_INVALID; | |
| 122 | |
| 123 ::CancelIo(read_file_); | |
| 124 ::CancelIo(write_file_); | |
| 125 | |
| 126 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
| |
| 127 | |
| 128 read_context_->handler = NULL; | |
| 129 write_context_->handler = NULL; | |
| 130 | |
| 131 read_context_.reset(); | |
| 132 write_context_.reset(); | |
| 133 | |
| 134 // Because of possible overlapped IO, the handles may not close cleanly but | |
| 135 // 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.
| |
| 136 ::CloseHandle(scoped_read_file_.Take()); | |
| 137 ::CloseHandle(scoped_write_file_.Take()); | |
| 26 } | 138 } |
| 27 | 139 |
| 28 bool NativeMessageProcessHost::WriteData(FileHandle file, | 140 bool NativeMessageProcessHost::WriteData(FileHandle file, |
| 29 const char* data, | 141 const char* data, |
| 30 size_t bytes_to_write) { | 142 size_t bytes_to_write) { |
| 31 NOTREACHED(); | 143 DWORD bytes_written = 0; |
| 32 return false; | 144 ::SetLastError(0); |
| 145 BOOL result = ::WriteFile(file, data, bytes_to_write, &bytes_written, | |
| 146 &write_context_->overlapped); | |
| 147 | |
| 148 return result || ::GetLastError() == ERROR_IO_PENDING; | |
| 33 } | 149 } |
| 34 | 150 |
| 35 bool NativeMessageProcessHost::ReadData(FileHandle file, | 151 bool NativeMessageProcessHost::ReadData(FileHandle file, |
| 36 char* data, | 152 char* data, |
| 37 size_t bytes_to_read) { | 153 size_t bytes_to_read) { |
| 154 // 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.
| |
| 38 NOTREACHED(); | 155 NOTREACHED(); |
| 39 return false; | 156 return false; |
| 40 } | 157 } |
| 41 | 158 |
| 42 } // namespace extensions | 159 } // namespace extensions |
| OLD | NEW |