Chromium Code Reviews| 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 |