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 29 matching lines...) Expand all Loading... |
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 TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), | 123 TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), |
125 "ChannelWin::ProcessMessageForDelivery", | 124 "ChannelWin::ProcessMessageForDelivery", |
126 message->flags(), | 125 message->flags(), |
127 TRACE_EVENT_FLAG_FLOW_OUT); | 126 TRACE_EVENT_FLAG_FLOW_OUT); |
128 | 127 |
129 // |output_queue_| takes ownership of |message|. | 128 // |output_queue_| takes ownership of |message|. |
130 OutputElement* element = new OutputElement(message); | 129 output_queue_.push(message); |
131 output_queue_.push(element); | |
132 | |
133 #if USE_ATTACHMENT_BROKER | |
134 if (message->HasBrokerableAttachments()) { | |
135 // |output_queue_| takes ownership of |ids.buffer|. | |
136 Message::SerializedAttachmentIds ids = | |
137 message->SerializedIdsOfBrokerableAttachments(); | |
138 OutputElement* new_element = new OutputElement(ids.buffer, ids.size); | |
139 output_queue_.push(new_element); | |
140 } | |
141 #endif | |
142 | |
143 // ensure waiting to write | 130 // ensure waiting to write |
144 if (!waiting_connect_) { | 131 if (!waiting_connect_) { |
145 if (!output_state_.is_pending) { | 132 if (!output_state_.is_pending) { |
146 if (!ProcessOutgoingMessages(NULL, 0)) | 133 if (!ProcessOutgoingMessages(NULL, 0)) |
147 return false; | 134 return false; |
148 } | 135 } |
149 } | 136 } |
150 | 137 |
151 return true; | 138 return true; |
152 } | 139 } |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 | 356 |
370 // Don't send the secret to the untrusted process, and don't send a secret | 357 // Don't send the secret to the untrusted process, and don't send a secret |
371 // if the value is zero (for IPC backwards compatability). | 358 // if the value is zero (for IPC backwards compatability). |
372 int32 secret = validate_client_ ? 0 : client_secret_; | 359 int32 secret = validate_client_ ? 0 : client_secret_; |
373 if (!m->WriteInt(GetCurrentProcessId()) || | 360 if (!m->WriteInt(GetCurrentProcessId()) || |
374 (secret && !m->WriteUInt32(secret))) { | 361 (secret && !m->WriteUInt32(secret))) { |
375 pipe_.Close(); | 362 pipe_.Close(); |
376 return false; | 363 return false; |
377 } | 364 } |
378 | 365 |
379 OutputElement* element = new OutputElement(m.release()); | 366 output_queue_.push(m.release()); |
380 output_queue_.push(element); | |
381 return true; | 367 return true; |
382 } | 368 } |
383 | 369 |
384 bool ChannelWin::Connect() { | 370 bool ChannelWin::Connect() { |
385 DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once"; | 371 DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once"; |
386 | 372 |
387 if (!thread_check_.get()) | 373 if (!thread_check_.get()) |
388 thread_check_.reset(new base::ThreadChecker()); | 374 thread_check_.reset(new base::ThreadChecker()); |
389 | 375 |
390 if (!pipe_.IsValid()) | 376 if (!pipe_.IsValid()) |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 if (output_state_.is_pending) { | 446 if (output_state_.is_pending) { |
461 DCHECK(context); | 447 DCHECK(context); |
462 output_state_.is_pending = false; | 448 output_state_.is_pending = false; |
463 if (!context || bytes_written == 0) { | 449 if (!context || bytes_written == 0) { |
464 DWORD err = GetLastError(); | 450 DWORD err = GetLastError(); |
465 LOG(ERROR) << "pipe error: " << err; | 451 LOG(ERROR) << "pipe error: " << err; |
466 return false; | 452 return false; |
467 } | 453 } |
468 // Message was sent. | 454 // Message was sent. |
469 CHECK(!output_queue_.empty()); | 455 CHECK(!output_queue_.empty()); |
470 OutputElement* element = output_queue_.front(); | 456 Message* m = output_queue_.front(); |
471 output_queue_.pop(); | 457 output_queue_.pop(); |
472 delete element; | 458 delete m; |
473 } | 459 } |
474 | 460 |
475 if (output_queue_.empty()) | 461 if (output_queue_.empty()) |
476 return true; | 462 return true; |
477 | 463 |
478 if (!pipe_.IsValid()) | 464 if (!pipe_.IsValid()) |
479 return false; | 465 return false; |
480 | 466 |
481 // Write to pipe... | 467 // Write to pipe... |
482 OutputElement* element = output_queue_.front(); | 468 Message* m = output_queue_.front(); |
483 DCHECK(element->size() <= INT_MAX); | 469 DCHECK(m->size() <= INT_MAX); |
484 BOOL ok = WriteFile(pipe_.Get(), element->data(), | 470 BOOL ok = WriteFile(pipe_.Get(), |
485 static_cast<uint32>(element->size()), NULL, | 471 m->data(), |
| 472 static_cast<uint32>(m->size()), |
| 473 NULL, |
486 &output_state_.context.overlapped); | 474 &output_state_.context.overlapped); |
487 if (!ok) { | 475 if (!ok) { |
488 DWORD write_error = GetLastError(); | 476 DWORD write_error = GetLastError(); |
489 if (write_error == ERROR_IO_PENDING) { | 477 if (write_error == ERROR_IO_PENDING) { |
490 output_state_.is_pending = true; | 478 output_state_.is_pending = true; |
491 | 479 |
492 const Message* m = element->get_message(); | 480 DVLOG(2) << "sent pending message @" << m << " on channel @" << this |
493 if (m) { | 481 << " with type " << m->type(); |
494 DVLOG(2) << "sent pending message @" << m << " on channel @" << this | |
495 << " with type " << m->type(); | |
496 } | |
497 | 482 |
498 return true; | 483 return true; |
499 } | 484 } |
500 LOG(ERROR) << "pipe error: " << write_error; | 485 LOG(ERROR) << "pipe error: " << write_error; |
501 return false; | 486 return false; |
502 } | 487 } |
503 | 488 |
504 const Message* m = element->get_message(); | 489 DVLOG(2) << "sent message @" << m << " on channel @" << this |
505 if (m) { | 490 << " with type " << m->type(); |
506 DVLOG(2) << "sent message @" << m << " on channel @" << this | |
507 << " with type " << m->type(); | |
508 } | |
509 | 491 |
510 output_state_.is_pending = true; | 492 output_state_.is_pending = true; |
511 return true; | 493 return true; |
512 } | 494 } |
513 | 495 |
514 void ChannelWin::OnIOCompleted( | 496 void ChannelWin::OnIOCompleted( |
515 base::MessageLoopForIO::IOContext* context, | 497 base::MessageLoopForIO::IOContext* context, |
516 DWORD bytes_transfered, | 498 DWORD bytes_transfered, |
517 DWORD error) { | 499 DWORD error) { |
518 bool ok = true; | 500 bool ok = true; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 int secret; | 575 int secret; |
594 do { // Guarantee we get a non-zero value. | 576 do { // Guarantee we get a non-zero value. |
595 secret = base::RandInt(0, std::numeric_limits<int>::max()); | 577 secret = base::RandInt(0, std::numeric_limits<int>::max()); |
596 } while (secret == 0); | 578 } while (secret == 0); |
597 | 579 |
598 id.append(GenerateUniqueRandomChannelID()); | 580 id.append(GenerateUniqueRandomChannelID()); |
599 return id.append(base::StringPrintf("\\%d", secret)); | 581 return id.append(base::StringPrintf("\\%d", secret)); |
600 } | 582 } |
601 | 583 |
602 } // namespace IPC | 584 } // namespace IPC |
OLD | NEW |