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 |