| 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 "ipc/ipc_channel_win.h" | 5 #include "ipc/ipc_channel_win.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 | 8 |
| 9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 waiting_connect_(mode & MODE_SERVER_FLAG), | 46 waiting_connect_(mode & MODE_SERVER_FLAG), |
| 47 processing_incoming_(false), | 47 processing_incoming_(false), |
| 48 validate_client_(false), | 48 validate_client_(false), |
| 49 client_secret_(0), | 49 client_secret_(0), |
| 50 broker_(broker), | 50 broker_(broker), |
| 51 weak_factory_(this) { | 51 weak_factory_(this) { |
| 52 CreatePipe(channel_handle, mode); | 52 CreatePipe(channel_handle, mode); |
| 53 } | 53 } |
| 54 | 54 |
| 55 ChannelWin::~ChannelWin() { | 55 ChannelWin::~ChannelWin() { |
| 56 CleanUp(); | |
| 57 Close(); | 56 Close(); |
| 58 } | 57 } |
| 59 | 58 |
| 60 void ChannelWin::Close() { | 59 void ChannelWin::Close() { |
| 61 if (thread_check_.get()) | 60 if (thread_check_.get()) |
| 62 DCHECK(thread_check_->CalledOnValidThread()); | 61 DCHECK(thread_check_->CalledOnValidThread()); |
| 63 | 62 |
| 64 if (input_state_.is_pending || output_state_.is_pending) | 63 if (input_state_.is_pending || output_state_.is_pending) |
| 65 CancelIo(pipe_.Get()); | 64 CancelIo(pipe_.Get()); |
| 66 | 65 |
| 67 // Closing the handle at this point prevents us from issuing more requests | 66 // Closing the handle at this point prevents us from issuing more requests |
| 68 // form OnIOCompleted(). | 67 // form OnIOCompleted(). |
| 69 if (pipe_.IsValid()) | 68 if (pipe_.IsValid()) |
| 70 pipe_.Close(); | 69 pipe_.Close(); |
| 71 | 70 |
| 72 // Make sure all IO has completed. | 71 // Make sure all IO has completed. |
| 73 while (input_state_.is_pending || output_state_.is_pending) { | 72 while (input_state_.is_pending || output_state_.is_pending) { |
| 74 base::MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this); | 73 base::MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this); |
| 75 } | 74 } |
| 76 | 75 |
| 77 while (!output_queue_.empty()) { | 76 while (!output_queue_.empty()) { |
| 78 OutputElement* element = output_queue_.front(); | 77 Message* m = output_queue_.front(); |
| 79 output_queue_.pop(); | 78 output_queue_.pop(); |
| 80 delete element; | 79 delete m; |
| 81 } | 80 } |
| 82 } | 81 } |
| 83 | 82 |
| 84 bool ChannelWin::Send(Message* message) { | 83 bool ChannelWin::Send(Message* message) { |
| 85 DCHECK(thread_check_->CalledOnValidThread()); | 84 DCHECK(thread_check_->CalledOnValidThread()); |
| 86 DVLOG(2) << "sending message @" << message << " on channel @" << this | 85 DVLOG(2) << "sending message @" << message << " on channel @" << this |
| 87 << " with type " << message->type() | 86 << " with type " << message->type() |
| 88 << " (" << output_queue_.size() << " in queue)"; | 87 << " (" << output_queue_.size() << " in queue)"; |
| 89 | 88 |
| 90 if (!prelim_queue_.empty()) { | 89 if (!prelim_queue_.empty()) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 117 } | 116 } |
| 118 } | 117 } |
| 119 | 118 |
| 120 #ifdef IPC_MESSAGE_LOG_ENABLED | 119 #ifdef IPC_MESSAGE_LOG_ENABLED |
| 121 Logging::GetInstance()->OnSendMessage(message, ""); | 120 Logging::GetInstance()->OnSendMessage(message, ""); |
| 122 #endif | 121 #endif |
| 123 | 122 |
| 124 message->TraceMessageBegin(); | 123 message->TraceMessageBegin(); |
| 125 | 124 |
| 126 // |output_queue_| takes ownership of |message|. | 125 // |output_queue_| takes ownership of |message|. |
| 127 OutputElement* element = new OutputElement(message); | 126 output_queue_.push(message); |
| 128 output_queue_.push(element); | |
| 129 | |
| 130 #if USE_ATTACHMENT_BROKER | |
| 131 if (message->HasBrokerableAttachments()) { | |
| 132 // |output_queue_| takes ownership of |ids.buffer|. | |
| 133 Message::SerializedAttachmentIds ids = | |
| 134 message->SerializedIdsOfBrokerableAttachments(); | |
| 135 OutputElement* new_element = new OutputElement(ids.buffer, ids.size); | |
| 136 output_queue_.push(new_element); | |
| 137 } | |
| 138 #endif | |
| 139 | |
| 140 // ensure waiting to write | 127 // ensure waiting to write |
| 141 if (!waiting_connect_) { | 128 if (!waiting_connect_) { |
| 142 if (!output_state_.is_pending) { | 129 if (!output_state_.is_pending) { |
| 143 if (!ProcessOutgoingMessages(NULL, 0)) | 130 if (!ProcessOutgoingMessages(NULL, 0)) |
| 144 return false; | 131 return false; |
| 145 } | 132 } |
| 146 } | 133 } |
| 147 | 134 |
| 148 return true; | 135 return true; |
| 149 } | 136 } |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 | 353 |
| 367 // Don't send the secret to the untrusted process, and don't send a secret | 354 // Don't send the secret to the untrusted process, and don't send a secret |
| 368 // if the value is zero (for IPC backwards compatability). | 355 // if the value is zero (for IPC backwards compatability). |
| 369 int32 secret = validate_client_ ? 0 : client_secret_; | 356 int32 secret = validate_client_ ? 0 : client_secret_; |
| 370 if (!m->WriteInt(GetCurrentProcessId()) || | 357 if (!m->WriteInt(GetCurrentProcessId()) || |
| 371 (secret && !m->WriteUInt32(secret))) { | 358 (secret && !m->WriteUInt32(secret))) { |
| 372 pipe_.Close(); | 359 pipe_.Close(); |
| 373 return false; | 360 return false; |
| 374 } | 361 } |
| 375 | 362 |
| 376 OutputElement* element = new OutputElement(m.release()); | 363 output_queue_.push(m.release()); |
| 377 output_queue_.push(element); | |
| 378 return true; | 364 return true; |
| 379 } | 365 } |
| 380 | 366 |
| 381 bool ChannelWin::Connect() { | 367 bool ChannelWin::Connect() { |
| 382 DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once"; | 368 DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once"; |
| 383 | 369 |
| 384 if (!thread_check_.get()) | 370 if (!thread_check_.get()) |
| 385 thread_check_.reset(new base::ThreadChecker()); | 371 thread_check_.reset(new base::ThreadChecker()); |
| 386 | 372 |
| 387 if (!pipe_.IsValid()) | 373 if (!pipe_.IsValid()) |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 if (output_state_.is_pending) { | 443 if (output_state_.is_pending) { |
| 458 DCHECK(context); | 444 DCHECK(context); |
| 459 output_state_.is_pending = false; | 445 output_state_.is_pending = false; |
| 460 if (!context || bytes_written == 0) { | 446 if (!context || bytes_written == 0) { |
| 461 DWORD err = GetLastError(); | 447 DWORD err = GetLastError(); |
| 462 LOG(ERROR) << "pipe error: " << err; | 448 LOG(ERROR) << "pipe error: " << err; |
| 463 return false; | 449 return false; |
| 464 } | 450 } |
| 465 // Message was sent. | 451 // Message was sent. |
| 466 CHECK(!output_queue_.empty()); | 452 CHECK(!output_queue_.empty()); |
| 467 OutputElement* element = output_queue_.front(); | 453 Message* m = output_queue_.front(); |
| 468 output_queue_.pop(); | 454 output_queue_.pop(); |
| 469 delete element; | 455 delete m; |
| 470 } | 456 } |
| 471 | 457 |
| 472 if (output_queue_.empty()) | 458 if (output_queue_.empty()) |
| 473 return true; | 459 return true; |
| 474 | 460 |
| 475 if (!pipe_.IsValid()) | 461 if (!pipe_.IsValid()) |
| 476 return false; | 462 return false; |
| 477 | 463 |
| 478 // Write to pipe... | 464 // Write to pipe... |
| 479 OutputElement* element = output_queue_.front(); | 465 Message* m = output_queue_.front(); |
| 480 DCHECK(element->size() <= INT_MAX); | 466 DCHECK(m->size() <= INT_MAX); |
| 481 BOOL ok = WriteFile(pipe_.Get(), element->data(), | 467 BOOL ok = WriteFile(pipe_.Get(), |
| 482 static_cast<uint32>(element->size()), NULL, | 468 m->data(), |
| 469 static_cast<uint32>(m->size()), |
| 470 NULL, |
| 483 &output_state_.context.overlapped); | 471 &output_state_.context.overlapped); |
| 484 if (!ok) { | 472 if (!ok) { |
| 485 DWORD write_error = GetLastError(); | 473 DWORD write_error = GetLastError(); |
| 486 if (write_error == ERROR_IO_PENDING) { | 474 if (write_error == ERROR_IO_PENDING) { |
| 487 output_state_.is_pending = true; | 475 output_state_.is_pending = true; |
| 488 | 476 |
| 489 const Message* m = element->get_message(); | 477 DVLOG(2) << "sent pending message @" << m << " on channel @" << this |
| 490 if (m) { | 478 << " with type " << m->type(); |
| 491 DVLOG(2) << "sent pending message @" << m << " on channel @" << this | |
| 492 << " with type " << m->type(); | |
| 493 } | |
| 494 | 479 |
| 495 return true; | 480 return true; |
| 496 } | 481 } |
| 497 LOG(ERROR) << "pipe error: " << write_error; | 482 LOG(ERROR) << "pipe error: " << write_error; |
| 498 return false; | 483 return false; |
| 499 } | 484 } |
| 500 | 485 |
| 501 const Message* m = element->get_message(); | 486 DVLOG(2) << "sent message @" << m << " on channel @" << this |
| 502 if (m) { | 487 << " with type " << m->type(); |
| 503 DVLOG(2) << "sent message @" << m << " on channel @" << this | |
| 504 << " with type " << m->type(); | |
| 505 } | |
| 506 | 488 |
| 507 output_state_.is_pending = true; | 489 output_state_.is_pending = true; |
| 508 return true; | 490 return true; |
| 509 } | 491 } |
| 510 | 492 |
| 511 void ChannelWin::OnIOCompleted( | 493 void ChannelWin::OnIOCompleted( |
| 512 base::MessageLoopForIO::IOContext* context, | 494 base::MessageLoopForIO::IOContext* context, |
| 513 DWORD bytes_transfered, | 495 DWORD bytes_transfered, |
| 514 DWORD error) { | 496 DWORD error) { |
| 515 bool ok = true; | 497 bool ok = true; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 int secret; | 572 int secret; |
| 591 do { // Guarantee we get a non-zero value. | 573 do { // Guarantee we get a non-zero value. |
| 592 secret = base::RandInt(0, std::numeric_limits<int>::max()); | 574 secret = base::RandInt(0, std::numeric_limits<int>::max()); |
| 593 } while (secret == 0); | 575 } while (secret == 0); |
| 594 | 576 |
| 595 id.append(GenerateUniqueRandomChannelID()); | 577 id.append(GenerateUniqueRandomChannelID()); |
| 596 return id.append(base::StringPrintf("\\%d", secret)); | 578 return id.append(base::StringPrintf("\\%d", secret)); |
| 597 } | 579 } |
| 598 | 580 |
| 599 } // namespace IPC | 581 } // namespace IPC |
| OLD | NEW |