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 AddToOverlappedOffset(&read_context_->overlapped, bytes_transfered); |
| 55 |
| 56 MessageType type; |
| 57 uint32 message_length = 0; |
| 58 if (!VerifyMessageMetaData(pending_message_meta_data_, &type, |
| 59 &message_length)) { |
| 60 return; |
| 61 } |
| 62 pending_message_.resize(message_length, '\0'); |
| 63 // Try to read the full message. |
| 64 read_state = READ_STATE_WAITING_FOR_MESSAGE; |
| 65 ::ReadFile(read_file_, &(pending_message_)[0], message_length, NULL, |
| 66 &read_context_->overlapped); |
| 67 return; |
| 68 } |
| 69 case READ_STATE_WAITING_FOR_MESSAGE: |
| 70 AddToOverlappedOffset(&read_context_->overlapped, bytes_transfered); |
| 71 |
| 72 // Verify that the entire message was read. |
| 73 if (bytes_transfered != pending_message_.size()) { |
| 74 LOG(ERROR) << "Could not read entire message."; |
| 75 return; |
| 76 } |
| 77 // Send the current message |
| 78 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| 79 base::Bind(&Client::PostMessageFromNativeProcess, weak_client_ui_, |
| 80 destination_port_, pending_message_)); |
| 81 // Do not try to read another message if this is only a |
| 82 // sendNativeMessage(). |
| 83 if (is_send_message_) { |
| 84 read_state = READ_STATE_INVALID; |
| 85 } else { |
| 86 // Start the read for the next message. |
| 87 read_state = READ_STATE_WAITING_FOR_META; |
| 88 ::ReadFile(read_file_, &pending_message_meta_data_, 8, NULL, |
| 89 &read_context_->overlapped); |
| 90 } |
| 91 return; |
| 92 default: |
| 93 NOTREACHED(); |
| 94 return; |
| 95 } |
| 96 } else { |
| 97 DCHECK(context == write_context_.get()); |
| 98 } |
22 } | 99 } |
23 | 100 |
24 void NativeMessageProcessHost::InitIO() { | 101 void NativeMessageProcessHost::InitIO() { |
25 NOTREACHED(); | 102 read_context_.reset(new MessageLoopForIO::IOContext()); |
| 103 write_context_.reset(new MessageLoopForIO::IOContext()); |
| 104 |
| 105 memset(&read_context_->overlapped, 0, sizeof(read_context_->overlapped)); |
| 106 memset(&write_context_->overlapped, 0, sizeof(write_context_->overlapped)); |
| 107 |
| 108 read_context_->handler = this; |
| 109 write_context_->handler = this; |
| 110 |
| 111 MessageLoopForIO::current()->RegisterIOHandler(read_file_, this); |
| 112 |
| 113 // Make a request for the type and length of the first message. |
| 114 read_state = READ_STATE_WAITING_FOR_META; |
| 115 ::ReadFile(read_file_, &pending_message_meta_data_, 8, NULL, |
| 116 &read_context_->overlapped); |
| 117 } |
| 118 |
| 119 void NativeMessageProcessHost::StopIO() { |
| 120 read_state = READ_STATE_INVALID; |
| 121 |
| 122 MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this); |
| 123 |
| 124 read_context_->handler = NULL; |
| 125 write_context_->handler = NULL; |
| 126 |
| 127 read_context_.reset(); |
| 128 write_context_.reset(); |
| 129 |
| 130 // Because of the asynchronous IO, ::CloseHandle() may return a non-zero |
| 131 // status. This is expected, but will trigger a CHECK in |
| 132 // ScopedHandle::Close(). To circumvent this, we will take ownership of the |
| 133 // raw handle and close it manually. |
| 134 ::CloseHandle(scoped_read_file_.Take()); |
| 135 ::CloseHandle(scoped_write_file_.Take()); |
26 } | 136 } |
27 | 137 |
28 bool NativeMessageProcessHost::WriteData(FileHandle file, | 138 bool NativeMessageProcessHost::WriteData(FileHandle file, |
29 const char* data, | 139 const char* data, |
30 size_t bytes_to_write) { | 140 size_t bytes_to_write) { |
31 NOTREACHED(); | 141 DWORD bytes_written = 0; |
32 return false; | 142 ::SetLastError(0); |
33 } | 143 BOOL result = ::WriteFile(file, data, bytes_to_write, &bytes_written, |
| 144 &write_context_->overlapped); |
34 | 145 |
35 bool NativeMessageProcessHost::ReadData(FileHandle file, | 146 return result || ::GetLastError() == ERROR_IO_PENDING; |
36 char* data, | |
37 size_t bytes_to_read) { | |
38 NOTREACHED(); | |
39 return false; | |
40 } | 147 } |
41 | 148 |
42 } // namespace extensions | 149 } // namespace extensions |
OLD | NEW |