OLD | NEW |
---|---|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/common/ipc_channel_win.h" | 5 #include "chrome/common/ipc_channel_win.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/non_thread_safe.h" | |
12 #include "base/win_util.h" | 13 #include "base/win_util.h" |
13 #include "chrome/common/chrome_counters.h" | 14 #include "chrome/common/chrome_counters.h" |
14 #include "chrome/common/ipc_logging.h" | 15 #include "chrome/common/ipc_logging.h" |
15 #include "chrome/common/ipc_message_utils.h" | 16 #include "chrome/common/ipc_message_utils.h" |
16 | 17 |
17 namespace IPC { | 18 namespace IPC { |
18 //------------------------------------------------------------------------------ | 19 //------------------------------------------------------------------------------ |
19 | 20 |
20 Channel::ChannelImpl::State::State(ChannelImpl* channel) : is_pending(false) { | 21 Channel::ChannelImpl::State::State(ChannelImpl* channel) : is_pending(false) { |
21 memset(&context.overlapped, 0, sizeof(context.overlapped)); | 22 memset(&context.overlapped, 0, sizeof(context.overlapped)); |
(...skipping 17 matching lines...) Expand all Loading... | |
39 processing_incoming_(false), | 40 processing_incoming_(false), |
40 ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) { | 41 ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) { |
41 if (!CreatePipe(channel_id, mode)) { | 42 if (!CreatePipe(channel_id, mode)) { |
42 // The pipe may have been closed already. | 43 // The pipe may have been closed already. |
43 LOG(WARNING) << "Unable to create pipe named \"" << channel_id << | 44 LOG(WARNING) << "Unable to create pipe named \"" << channel_id << |
44 "\" in " << (mode == 0 ? "server" : "client") << " mode."; | 45 "\" in " << (mode == 0 ? "server" : "client") << " mode."; |
45 } | 46 } |
46 } | 47 } |
47 | 48 |
48 void Channel::ChannelImpl::Close() { | 49 void Channel::ChannelImpl::Close() { |
50 if (thread_check_.get()) { | |
51 DCHECK(thread_check_->CalledOnValidThread()); | |
52 } | |
53 | |
49 bool waited = false; | 54 bool waited = false; |
50 if (input_state_.is_pending || output_state_.is_pending) { | 55 if (input_state_.is_pending || output_state_.is_pending) { |
51 CancelIo(pipe_); | 56 CancelIo(pipe_); |
52 waited = true; | 57 waited = true; |
53 } | 58 } |
54 | 59 |
55 // Closing the handle at this point prevents us from issuing more requests | 60 // Closing the handle at this point prevents us from issuing more requests |
56 // form OnIOCompleted(). | 61 // form OnIOCompleted(). |
57 if (pipe_ != INVALID_HANDLE_VALUE) { | 62 if (pipe_ != INVALID_HANDLE_VALUE) { |
58 CloseHandle(pipe_); | 63 CloseHandle(pipe_); |
(...skipping 11 matching lines...) Expand all Loading... | |
70 } | 75 } |
71 | 76 |
72 while (!output_queue_.empty()) { | 77 while (!output_queue_.empty()) { |
73 Message* m = output_queue_.front(); | 78 Message* m = output_queue_.front(); |
74 output_queue_.pop(); | 79 output_queue_.pop(); |
75 delete m; | 80 delete m; |
76 } | 81 } |
77 } | 82 } |
78 | 83 |
79 bool Channel::ChannelImpl::Send(Message* message) { | 84 bool Channel::ChannelImpl::Send(Message* message) { |
85 DCHECK(thread_check_->CalledOnValidThread()); | |
80 chrome::Counters::ipc_send_counter().Increment(); | 86 chrome::Counters::ipc_send_counter().Increment(); |
81 #ifdef IPC_MESSAGE_DEBUG_EXTRA | 87 #ifdef IPC_MESSAGE_DEBUG_EXTRA |
82 DLOG(INFO) << "sending message @" << message << " on channel @" << this | 88 DLOG(INFO) << "sending message @" << message << " on channel @" << this |
83 << " with type " << message->type() | 89 << " with type " << message->type() |
84 << " (" << output_queue_.size() << " in queue)"; | 90 << " (" << output_queue_.size() << " in queue)"; |
85 #endif | 91 #endif |
86 | 92 |
87 #ifdef IPC_MESSAGE_LOG_ENABLED | 93 #ifdef IPC_MESSAGE_LOG_ENABLED |
88 Logging::current()->OnSendMessage(message, L""); | 94 Logging::current()->OnSendMessage(message, L""); |
89 #endif | 95 #endif |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
160 return false; | 166 return false; |
161 } | 167 } |
162 | 168 |
163 output_queue_.push(m.release()); | 169 output_queue_.push(m.release()); |
164 return true; | 170 return true; |
165 } | 171 } |
166 | 172 |
167 bool Channel::ChannelImpl::Connect() { | 173 bool Channel::ChannelImpl::Connect() { |
168 DLOG(WARNING) << "Connect called twice"; | 174 DLOG(WARNING) << "Connect called twice"; |
169 | 175 |
176 if (!thread_check_.get()) | |
jam
2009/01/28 03:33:58
since this is only used in debug builds, it should
| |
177 thread_check_.reset(new NonThreadSafe()); | |
178 | |
170 if (pipe_ == INVALID_HANDLE_VALUE) | 179 if (pipe_ == INVALID_HANDLE_VALUE) |
171 return false; | 180 return false; |
172 | 181 |
173 MessageLoopForIO::current()->RegisterIOHandler(pipe_, this); | 182 MessageLoopForIO::current()->RegisterIOHandler(pipe_, this); |
174 | 183 |
175 // Check to see if there is a client connected to our pipe... | 184 // Check to see if there is a client connected to our pipe... |
176 if (waiting_connect_) | 185 if (waiting_connect_) |
177 ProcessConnection(); | 186 ProcessConnection(); |
178 | 187 |
179 if (!input_state_.is_pending) { | 188 if (!input_state_.is_pending) { |
180 // Complete setup asynchronously. By not setting input_state_.is_pending | 189 // Complete setup asynchronously. By not setting input_state_.is_pending |
181 // to true, we indicate to OnIOCompleted that this is the special | 190 // to true, we indicate to OnIOCompleted that this is the special |
182 // initialization signal. | 191 // initialization signal. |
183 MessageLoopForIO::current()->PostTask(FROM_HERE, factory_.NewRunnableMethod( | 192 MessageLoopForIO::current()->PostTask(FROM_HERE, factory_.NewRunnableMethod( |
184 &Channel::ChannelImpl::OnIOCompleted, &input_state_.context, 0, 0)); | 193 &Channel::ChannelImpl::OnIOCompleted, &input_state_.context, 0, 0)); |
185 } | 194 } |
186 | 195 |
187 if (!waiting_connect_) | 196 if (!waiting_connect_) |
188 ProcessOutgoingMessages(NULL, 0); | 197 ProcessOutgoingMessages(NULL, 0); |
189 return true; | 198 return true; |
190 } | 199 } |
191 | 200 |
192 bool Channel::ChannelImpl::ProcessConnection() { | 201 bool Channel::ChannelImpl::ProcessConnection() { |
202 DCHECK(thread_check_->CalledOnValidThread()); | |
193 if (input_state_.is_pending) | 203 if (input_state_.is_pending) |
194 input_state_.is_pending = false; | 204 input_state_.is_pending = false; |
195 | 205 |
196 // Do we have a client connected to our pipe? | 206 // Do we have a client connected to our pipe? |
197 if (INVALID_HANDLE_VALUE == pipe_) | 207 if (INVALID_HANDLE_VALUE == pipe_) |
198 return false; | 208 return false; |
199 | 209 |
200 BOOL ok = ConnectNamedPipe(pipe_, &input_state_.context.overlapped); | 210 BOOL ok = ConnectNamedPipe(pipe_, &input_state_.context.overlapped); |
201 | 211 |
202 DWORD err = GetLastError(); | 212 DWORD err = GetLastError(); |
(...skipping 15 matching lines...) Expand all Loading... | |
218 NOTREACHED(); | 228 NOTREACHED(); |
219 return false; | 229 return false; |
220 } | 230 } |
221 | 231 |
222 return true; | 232 return true; |
223 } | 233 } |
224 | 234 |
225 bool Channel::ChannelImpl::ProcessIncomingMessages( | 235 bool Channel::ChannelImpl::ProcessIncomingMessages( |
226 MessageLoopForIO::IOContext* context, | 236 MessageLoopForIO::IOContext* context, |
227 DWORD bytes_read) { | 237 DWORD bytes_read) { |
238 DCHECK(thread_check_->CalledOnValidThread()); | |
228 if (input_state_.is_pending) { | 239 if (input_state_.is_pending) { |
229 input_state_.is_pending = false; | 240 input_state_.is_pending = false; |
230 DCHECK(context); | 241 DCHECK(context); |
231 | 242 |
232 if (!context || !bytes_read) | 243 if (!context || !bytes_read) |
233 return false; | 244 return false; |
234 } else { | 245 } else { |
235 // This happens at channel initialization. | 246 // This happens at channel initialization. |
236 DCHECK(!bytes_read && context == &input_state_.context); | 247 DCHECK(!bytes_read && context == &input_state_.context); |
237 } | 248 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
306 } | 317 } |
307 | 318 |
308 return true; | 319 return true; |
309 } | 320 } |
310 | 321 |
311 bool Channel::ChannelImpl::ProcessOutgoingMessages( | 322 bool Channel::ChannelImpl::ProcessOutgoingMessages( |
312 MessageLoopForIO::IOContext* context, | 323 MessageLoopForIO::IOContext* context, |
313 DWORD bytes_written) { | 324 DWORD bytes_written) { |
314 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's | 325 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's |
315 // no connection? | 326 // no connection? |
327 DCHECK(thread_check_->CalledOnValidThread()); | |
316 | 328 |
317 if (output_state_.is_pending) { | 329 if (output_state_.is_pending) { |
318 DCHECK(context); | 330 DCHECK(context); |
319 output_state_.is_pending = false; | 331 output_state_.is_pending = false; |
320 if (!context || bytes_written == 0) { | 332 if (!context || bytes_written == 0) { |
321 DWORD err = GetLastError(); | 333 DWORD err = GetLastError(); |
322 LOG(ERROR) << "pipe error: " << err; | 334 LOG(ERROR) << "pipe error: " << err; |
323 return false; | 335 return false; |
324 } | 336 } |
325 // Message was sent. | 337 // Message was sent. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
363 " with type " << m->type(); | 375 " with type " << m->type(); |
364 #endif | 376 #endif |
365 | 377 |
366 output_state_.is_pending = true; | 378 output_state_.is_pending = true; |
367 return true; | 379 return true; |
368 } | 380 } |
369 | 381 |
370 void Channel::ChannelImpl::OnIOCompleted(MessageLoopForIO::IOContext* context, | 382 void Channel::ChannelImpl::OnIOCompleted(MessageLoopForIO::IOContext* context, |
371 DWORD bytes_transfered, DWORD error) { | 383 DWORD bytes_transfered, DWORD error) { |
372 bool ok; | 384 bool ok; |
385 DCHECK(thread_check_->CalledOnValidThread()); | |
373 if (context == &input_state_.context) { | 386 if (context == &input_state_.context) { |
374 if (waiting_connect_) { | 387 if (waiting_connect_) { |
375 if (!ProcessConnection()) | 388 if (!ProcessConnection()) |
376 return; | 389 return; |
377 // We may have some messages queued up to send... | 390 // We may have some messages queued up to send... |
378 if (!output_queue_.empty() && !output_state_.is_pending) | 391 if (!output_queue_.empty() && !output_state_.is_pending) |
379 ProcessOutgoingMessages(NULL, 0); | 392 ProcessOutgoingMessages(NULL, 0); |
380 if (input_state_.is_pending) | 393 if (input_state_.is_pending) |
381 return; | 394 return; |
382 // else, fall-through and look for incoming messages... | 395 // else, fall-through and look for incoming messages... |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
418 | 431 |
419 void Channel::set_listener(Listener* listener) { | 432 void Channel::set_listener(Listener* listener) { |
420 channel_impl_->set_listener(listener); | 433 channel_impl_->set_listener(listener); |
421 } | 434 } |
422 | 435 |
423 bool Channel::Send(Message* message) { | 436 bool Channel::Send(Message* message) { |
424 return channel_impl_->Send(message); | 437 return channel_impl_->Send(message); |
425 } | 438 } |
426 | 439 |
427 } // namespace IPC | 440 } // namespace IPC |
OLD | NEW |