| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 ChannelWin::State::~State() { | 52 ChannelWin::State::~State() { |
| 53 COMPILE_ASSERT(!offsetof(ChannelWin::State, context), | 53 COMPILE_ASSERT(!offsetof(ChannelWin::State, context), |
| 54 starts_with_io_context); | 54 starts_with_io_context); |
| 55 } | 55 } |
| 56 | 56 |
| 57 ChannelWin::ChannelWin(const IPC::ChannelHandle &channel_handle, | 57 ChannelWin::ChannelWin(const IPC::ChannelHandle &channel_handle, |
| 58 Mode mode, Listener* listener) | 58 Mode mode, Listener* listener) |
| 59 : ChannelReader(listener), | 59 : ChannelReader(listener), |
| 60 input_state_(this), | 60 input_state_(this), |
| 61 output_state_(this), | 61 output_state_(this), |
| 62 pipe_(INVALID_HANDLE_VALUE), | |
| 63 peer_pid_(base::kNullProcessId), | 62 peer_pid_(base::kNullProcessId), |
| 64 waiting_connect_(mode & MODE_SERVER_FLAG), | 63 waiting_connect_(mode & MODE_SERVER_FLAG), |
| 65 processing_incoming_(false), | 64 processing_incoming_(false), |
| 66 validate_client_(false), | 65 validate_client_(false), |
| 67 writing_(false), | 66 writing_(false), |
| 68 debug_flags_(0), | 67 debug_flags_(0), |
| 69 write_error_(0), | 68 write_error_(0), |
| 70 last_write_error_(0), | 69 last_write_error_(0), |
| 71 write_size_(0), | 70 write_size_(0), |
| 72 client_secret_(0), | 71 client_secret_(0), |
| 73 weak_factory_(this) { | 72 weak_factory_(this) { |
| 74 CreatePipe(channel_handle, mode); | 73 CreatePipe(channel_handle, mode); |
| 75 } | 74 } |
| 76 | 75 |
| 77 ChannelWin::~ChannelWin() { | 76 ChannelWin::~ChannelWin() { |
| 78 Close(); | 77 Close(); |
| 79 } | 78 } |
| 80 | 79 |
| 81 void ChannelWin::Close() { | 80 void ChannelWin::Close() { |
| 82 if (thread_check_.get()) { | 81 if (thread_check_.get()) { |
| 83 DCHECK(thread_check_->CalledOnValidThread()); | 82 DCHECK(thread_check_->CalledOnValidThread()); |
| 84 } | 83 } |
| 85 debug_flags_ |= CLOSED; | 84 debug_flags_ |= CLOSED; |
| 86 | 85 |
| 87 if (input_state_.is_pending || output_state_.is_pending) | 86 if (input_state_.is_pending || output_state_.is_pending) |
| 88 CancelIo(pipe_); | 87 CancelIo(pipe_.Get()); |
| 89 | 88 |
| 90 // Closing the handle at this point prevents us from issuing more requests | 89 // Closing the handle at this point prevents us from issuing more requests |
| 91 // form OnIOCompleted(). | 90 // form OnIOCompleted(). |
| 92 if (pipe_ != INVALID_HANDLE_VALUE) { | 91 if (pipe_.IsValid()) |
| 93 CloseHandle(pipe_); | 92 pipe_.Close(); |
| 94 pipe_ = INVALID_HANDLE_VALUE; | |
| 95 } | |
| 96 | 93 |
| 97 if (input_state_.is_pending) | 94 if (input_state_.is_pending) |
| 98 debug_flags_ |= WAIT_FOR_READ; | 95 debug_flags_ |= WAIT_FOR_READ; |
| 99 | 96 |
| 100 if (output_state_.is_pending) | 97 if (output_state_.is_pending) |
| 101 debug_flags_ |= WAIT_FOR_WRITE; | 98 debug_flags_ |= WAIT_FOR_WRITE; |
| 102 | 99 |
| 103 // Make sure all IO has completed. | 100 // Make sure all IO has completed. |
| 104 base::Time start = base::Time::Now(); | 101 base::Time start = base::Time::Now(); |
| 105 while (input_state_.is_pending || output_state_.is_pending) { | 102 while (input_state_.is_pending || output_state_.is_pending) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 return true; | 148 return true; |
| 152 // If ERROR_SEM_TIMEOUT occurred, the pipe exists but is handling another | 149 // If ERROR_SEM_TIMEOUT occurred, the pipe exists but is handling another |
| 153 // connection. | 150 // connection. |
| 154 return GetLastError() == ERROR_SEM_TIMEOUT; | 151 return GetLastError() == ERROR_SEM_TIMEOUT; |
| 155 } | 152 } |
| 156 | 153 |
| 157 ChannelWin::ReadState ChannelWin::ReadData( | 154 ChannelWin::ReadState ChannelWin::ReadData( |
| 158 char* buffer, | 155 char* buffer, |
| 159 int buffer_len, | 156 int buffer_len, |
| 160 int* /* bytes_read */) { | 157 int* /* bytes_read */) { |
| 161 if (INVALID_HANDLE_VALUE == pipe_) | 158 if (!pipe_.IsValid()) |
| 162 return READ_FAILED; | 159 return READ_FAILED; |
| 163 | 160 |
| 164 debug_flags_ |= READ_MSG; | 161 debug_flags_ |= READ_MSG; |
| 165 DWORD bytes_read = 0; | 162 DWORD bytes_read = 0; |
| 166 BOOL ok = ReadFile(pipe_, buffer, buffer_len, | 163 BOOL ok = ReadFile(pipe_.Get(), buffer, buffer_len, |
| 167 &bytes_read, &input_state_.context.overlapped); | 164 &bytes_read, &input_state_.context.overlapped); |
| 168 if (!ok) { | 165 if (!ok) { |
| 169 DWORD err = GetLastError(); | 166 DWORD err = GetLastError(); |
| 170 if (err == ERROR_IO_PENDING) { | 167 if (err == ERROR_IO_PENDING) { |
| 171 input_state_.is_pending = true; | 168 input_state_.is_pending = true; |
| 172 return READ_PENDING; | 169 return READ_PENDING; |
| 173 } | 170 } |
| 174 LOG(ERROR) << "pipe error: " << err; | 171 LOG(ERROR) << "pipe error: " << err; |
| 175 return READ_FAILED; | 172 return READ_FAILED; |
| 176 } | 173 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 return base::ASCIIToWide(name.append(channel_id.substr(0, index - 1))); | 234 return base::ASCIIToWide(name.append(channel_id.substr(0, index - 1))); |
| 238 } | 235 } |
| 239 | 236 |
| 240 // This case is here to support predictable named pipes in tests. | 237 // This case is here to support predictable named pipes in tests. |
| 241 if (secret) | 238 if (secret) |
| 242 *secret = 0; | 239 *secret = 0; |
| 243 return base::ASCIIToWide(name.append(channel_id)); | 240 return base::ASCIIToWide(name.append(channel_id)); |
| 244 } | 241 } |
| 245 | 242 |
| 246 bool ChannelWin::CreatePipe(const IPC::ChannelHandle &channel_handle, | 243 bool ChannelWin::CreatePipe(const IPC::ChannelHandle &channel_handle, |
| 247 Mode mode) { | 244 Mode mode) { |
| 248 DCHECK_EQ(INVALID_HANDLE_VALUE, pipe_); | 245 DCHECK(!pipe_.IsValid()); |
| 249 base::string16 pipe_name; | 246 base::string16 pipe_name; |
| 250 // If we already have a valid pipe for channel just copy it. | 247 // If we already have a valid pipe for channel just copy it. |
| 251 if (channel_handle.pipe.handle) { | 248 if (channel_handle.pipe.handle) { |
| 249 // TODO(rvargas) crbug.com/415294: ChannelHandle should either go away in |
| 250 // favor of two independent entities (name/file), or it should be a move- |
| 251 // only type with a base::File member. In any case, this code should not |
| 252 // call DuplicateHandle. |
| 252 DCHECK(channel_handle.name.empty()); | 253 DCHECK(channel_handle.name.empty()); |
| 253 pipe_name = L"Not Available"; // Just used for LOG | 254 pipe_name = L"Not Available"; // Just used for LOG |
| 254 // Check that the given pipe confirms to the specified mode. We can | 255 // Check that the given pipe confirms to the specified mode. We can |
| 255 // only check for PIPE_TYPE_MESSAGE & PIPE_SERVER_END flags since the | 256 // only check for PIPE_TYPE_MESSAGE & PIPE_SERVER_END flags since the |
| 256 // other flags (PIPE_TYPE_BYTE, and PIPE_CLIENT_END) are defined as 0. | 257 // other flags (PIPE_TYPE_BYTE, and PIPE_CLIENT_END) are defined as 0. |
| 257 DWORD flags = 0; | 258 DWORD flags = 0; |
| 258 GetNamedPipeInfo(channel_handle.pipe.handle, &flags, NULL, NULL, NULL); | 259 GetNamedPipeInfo(channel_handle.pipe.handle, &flags, NULL, NULL, NULL); |
| 259 DCHECK(!(flags & PIPE_TYPE_MESSAGE)); | 260 DCHECK(!(flags & PIPE_TYPE_MESSAGE)); |
| 260 if (((mode & MODE_SERVER_FLAG) && !(flags & PIPE_SERVER_END)) || | 261 if (((mode & MODE_SERVER_FLAG) && !(flags & PIPE_SERVER_END)) || |
| 261 ((mode & MODE_CLIENT_FLAG) && (flags & PIPE_SERVER_END))) { | 262 ((mode & MODE_CLIENT_FLAG) && (flags & PIPE_SERVER_END))) { |
| 262 LOG(WARNING) << "Inconsistent open mode. Mode :" << mode; | 263 LOG(WARNING) << "Inconsistent open mode. Mode :" << mode; |
| 263 return false; | 264 return false; |
| 264 } | 265 } |
| 266 HANDLE local_handle; |
| 265 if (!DuplicateHandle(GetCurrentProcess(), | 267 if (!DuplicateHandle(GetCurrentProcess(), |
| 266 channel_handle.pipe.handle, | 268 channel_handle.pipe.handle, |
| 267 GetCurrentProcess(), | 269 GetCurrentProcess(), |
| 268 &pipe_, | 270 &local_handle, |
| 269 0, | 271 0, |
| 270 FALSE, | 272 FALSE, |
| 271 DUPLICATE_SAME_ACCESS)) { | 273 DUPLICATE_SAME_ACCESS)) { |
| 272 LOG(WARNING) << "DuplicateHandle failed. Error :" << GetLastError(); | 274 LOG(WARNING) << "DuplicateHandle failed. Error :" << GetLastError(); |
| 273 return false; | 275 return false; |
| 274 } | 276 } |
| 277 pipe_.Set(local_handle); |
| 275 } else if (mode & MODE_SERVER_FLAG) { | 278 } else if (mode & MODE_SERVER_FLAG) { |
| 276 DCHECK(!channel_handle.pipe.handle); | 279 DCHECK(!channel_handle.pipe.handle); |
| 277 const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | | 280 const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | |
| 278 FILE_FLAG_FIRST_PIPE_INSTANCE; | 281 FILE_FLAG_FIRST_PIPE_INSTANCE; |
| 279 pipe_name = PipeName(channel_handle.name, &client_secret_); | 282 pipe_name = PipeName(channel_handle.name, &client_secret_); |
| 280 validate_client_ = !!client_secret_; | 283 validate_client_ = !!client_secret_; |
| 281 pipe_ = CreateNamedPipeW(pipe_name.c_str(), | 284 pipe_.Set(CreateNamedPipeW(pipe_name.c_str(), |
| 282 open_mode, | 285 open_mode, |
| 283 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, | 286 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, |
| 284 1, | 287 1, |
| 285 Channel::kReadBufferSize, | 288 Channel::kReadBufferSize, |
| 286 Channel::kReadBufferSize, | 289 Channel::kReadBufferSize, |
| 287 5000, | 290 5000, |
| 288 NULL); | 291 NULL)); |
| 289 } else if (mode & MODE_CLIENT_FLAG) { | 292 } else if (mode & MODE_CLIENT_FLAG) { |
| 290 DCHECK(!channel_handle.pipe.handle); | 293 DCHECK(!channel_handle.pipe.handle); |
| 291 pipe_name = PipeName(channel_handle.name, &client_secret_); | 294 pipe_name = PipeName(channel_handle.name, &client_secret_); |
| 292 pipe_ = CreateFileW(pipe_name.c_str(), | 295 pipe_.Set(CreateFileW(pipe_name.c_str(), |
| 293 GENERIC_READ | GENERIC_WRITE, | 296 GENERIC_READ | GENERIC_WRITE, |
| 294 0, | 297 0, |
| 295 NULL, | 298 NULL, |
| 296 OPEN_EXISTING, | 299 OPEN_EXISTING, |
| 297 SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION | | 300 SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION | |
| 298 FILE_FLAG_OVERLAPPED, | 301 FILE_FLAG_OVERLAPPED, |
| 299 NULL); | 302 NULL)); |
| 300 } else { | 303 } else { |
| 301 NOTREACHED(); | 304 NOTREACHED(); |
| 302 } | 305 } |
| 303 | 306 |
| 304 if (pipe_ == INVALID_HANDLE_VALUE) { | 307 if (!pipe_.IsValid()) { |
| 305 // If this process is being closed, the pipe may be gone already. | 308 // If this process is being closed, the pipe may be gone already. |
| 306 PLOG(WARNING) << "Unable to create pipe \"" << pipe_name << "\" in " | 309 PLOG(WARNING) << "Unable to create pipe \"" << pipe_name << "\" in " |
| 307 << (mode & MODE_SERVER_FLAG ? "server" : "client") << " mode"; | 310 << (mode & MODE_SERVER_FLAG ? "server" : "client") << " mode"; |
| 308 return false; | 311 return false; |
| 309 } | 312 } |
| 310 | 313 |
| 311 // Create the Hello message to be sent when Connect is called | 314 // Create the Hello message to be sent when Connect is called |
| 312 scoped_ptr<Message> m(new Message(MSG_ROUTING_NONE, | 315 scoped_ptr<Message> m(new Message(MSG_ROUTING_NONE, |
| 313 HELLO_MESSAGE_TYPE, | 316 HELLO_MESSAGE_TYPE, |
| 314 IPC::Message::PRIORITY_NORMAL)); | 317 IPC::Message::PRIORITY_NORMAL)); |
| 315 | 318 |
| 316 // Don't send the secret to the untrusted process, and don't send a secret | 319 // Don't send the secret to the untrusted process, and don't send a secret |
| 317 // if the value is zero (for IPC backwards compatability). | 320 // if the value is zero (for IPC backwards compatability). |
| 318 int32 secret = validate_client_ ? 0 : client_secret_; | 321 int32 secret = validate_client_ ? 0 : client_secret_; |
| 319 if (!m->WriteInt(GetCurrentProcessId()) || | 322 if (!m->WriteInt(GetCurrentProcessId()) || |
| 320 (secret && !m->WriteUInt32(secret))) { | 323 (secret && !m->WriteUInt32(secret))) { |
| 321 CloseHandle(pipe_); | 324 pipe_.Close(); |
| 322 pipe_ = INVALID_HANDLE_VALUE; | |
| 323 return false; | 325 return false; |
| 324 } | 326 } |
| 325 | 327 |
| 326 debug_flags_ |= INIT_DONE; | 328 debug_flags_ |= INIT_DONE; |
| 327 | 329 |
| 328 output_queue_.push(m.release()); | 330 output_queue_.push(m.release()); |
| 329 return true; | 331 return true; |
| 330 } | 332 } |
| 331 | 333 |
| 332 bool ChannelWin::Connect() { | 334 bool ChannelWin::Connect() { |
| 333 DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once"; | 335 DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once"; |
| 334 | 336 |
| 335 if (!thread_check_.get()) | 337 if (!thread_check_.get()) |
| 336 thread_check_.reset(new base::ThreadChecker()); | 338 thread_check_.reset(new base::ThreadChecker()); |
| 337 | 339 |
| 338 if (pipe_ == INVALID_HANDLE_VALUE) | 340 if (!pipe_.IsValid()) |
| 339 return false; | 341 return false; |
| 340 | 342 |
| 341 base::MessageLoopForIO::current()->RegisterIOHandler(pipe_, this); | 343 base::MessageLoopForIO::current()->RegisterIOHandler(pipe_.Get(), this); |
| 342 | 344 |
| 343 // Check to see if there is a client connected to our pipe... | 345 // Check to see if there is a client connected to our pipe... |
| 344 if (waiting_connect_) | 346 if (waiting_connect_) |
| 345 ProcessConnection(); | 347 ProcessConnection(); |
| 346 | 348 |
| 347 if (!input_state_.is_pending) { | 349 if (!input_state_.is_pending) { |
| 348 // Complete setup asynchronously. By not setting input_state_.is_pending | 350 // Complete setup asynchronously. By not setting input_state_.is_pending |
| 349 // to true, we indicate to OnIOCompleted that this is the special | 351 // to true, we indicate to OnIOCompleted that this is the special |
| 350 // initialization signal. | 352 // initialization signal. |
| 351 base::MessageLoopForIO::current()->PostTask( | 353 base::MessageLoopForIO::current()->PostTask( |
| 352 FROM_HERE, | 354 FROM_HERE, |
| 353 base::Bind(&ChannelWin::OnIOCompleted, | 355 base::Bind(&ChannelWin::OnIOCompleted, |
| 354 weak_factory_.GetWeakPtr(), | 356 weak_factory_.GetWeakPtr(), |
| 355 &input_state_.context, | 357 &input_state_.context, |
| 356 0, | 358 0, |
| 357 0)); | 359 0)); |
| 358 } | 360 } |
| 359 | 361 |
| 360 if (!waiting_connect_) | 362 if (!waiting_connect_) |
| 361 ProcessOutgoingMessages(NULL, 0); | 363 ProcessOutgoingMessages(NULL, 0); |
| 362 return true; | 364 return true; |
| 363 } | 365 } |
| 364 | 366 |
| 365 bool ChannelWin::ProcessConnection() { | 367 bool ChannelWin::ProcessConnection() { |
| 366 DCHECK(thread_check_->CalledOnValidThread()); | 368 DCHECK(thread_check_->CalledOnValidThread()); |
| 367 if (input_state_.is_pending) | 369 if (input_state_.is_pending) |
| 368 input_state_.is_pending = false; | 370 input_state_.is_pending = false; |
| 369 | 371 |
| 370 // Do we have a client connected to our pipe? | 372 // Do we have a client connected to our pipe? |
| 371 if (INVALID_HANDLE_VALUE == pipe_) | 373 if (!pipe_.IsValid()) |
| 372 return false; | 374 return false; |
| 373 | 375 |
| 374 BOOL ok = ConnectNamedPipe(pipe_, &input_state_.context.overlapped); | 376 BOOL ok = ConnectNamedPipe(pipe_.Get(), &input_state_.context.overlapped); |
| 375 debug_flags_ |= CALLED_CONNECT; | 377 debug_flags_ |= CALLED_CONNECT; |
| 376 | 378 |
| 377 DWORD err = GetLastError(); | 379 DWORD err = GetLastError(); |
| 378 if (ok) { | 380 if (ok) { |
| 379 // Uhm, the API documentation says that this function should never | 381 // Uhm, the API documentation says that this function should never |
| 380 // return success when used in overlapped mode. | 382 // return success when used in overlapped mode. |
| 381 NOTREACHED(); | 383 NOTREACHED(); |
| 382 return false; | 384 return false; |
| 383 } | 385 } |
| 384 | 386 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 // Message was sent. | 422 // Message was sent. |
| 421 CHECK(!output_queue_.empty()); | 423 CHECK(!output_queue_.empty()); |
| 422 Message* m = output_queue_.front(); | 424 Message* m = output_queue_.front(); |
| 423 output_queue_.pop(); | 425 output_queue_.pop(); |
| 424 delete m; | 426 delete m; |
| 425 } | 427 } |
| 426 | 428 |
| 427 if (output_queue_.empty()) | 429 if (output_queue_.empty()) |
| 428 return true; | 430 return true; |
| 429 | 431 |
| 430 if (INVALID_HANDLE_VALUE == pipe_) | 432 if (!pipe_.IsValid()) |
| 431 return false; | 433 return false; |
| 432 | 434 |
| 433 // Write to pipe... | 435 // Write to pipe... |
| 434 Message* m = output_queue_.front(); | 436 Message* m = output_queue_.front(); |
| 435 DCHECK(m->size() <= INT_MAX); | 437 DCHECK(m->size() <= INT_MAX); |
| 436 debug_flags_ |= WRITE_MSG; | 438 debug_flags_ |= WRITE_MSG; |
| 437 CHECK(!writing_); | 439 CHECK(!writing_); |
| 438 writing_ = true; | 440 writing_ = true; |
| 439 write_size_ = static_cast<uint32>(m->size()); | 441 write_size_ = static_cast<uint32>(m->size()); |
| 440 write_error_ = 0; | 442 write_error_ = 0; |
| 441 BOOL ok = WriteFile(pipe_, | 443 BOOL ok = WriteFile(pipe_.Get(), |
| 442 m->data(), | 444 m->data(), |
| 443 write_size_, | 445 write_size_, |
| 444 NULL, | 446 NULL, |
| 445 &output_state_.context.overlapped); | 447 &output_state_.context.overlapped); |
| 446 if (!ok) { | 448 if (!ok) { |
| 447 write_error_ = GetLastError(); | 449 write_error_ = GetLastError(); |
| 448 if (write_error_ == ERROR_IO_PENDING) { | 450 if (write_error_ == ERROR_IO_PENDING) { |
| 449 output_state_.is_pending = true; | 451 output_state_.is_pending = true; |
| 450 | 452 |
| 451 DVLOG(2) << "sent pending message @" << m << " on channel @" << this | 453 DVLOG(2) << "sent pending message @" << m << " on channel @" << this |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 if (input_state_.is_pending) { | 496 if (input_state_.is_pending) { |
| 495 // This is the normal case for everything except the initialization step. | 497 // This is the normal case for everything except the initialization step. |
| 496 debug_flags_ |= READ_COMPLETED; | 498 debug_flags_ |= READ_COMPLETED; |
| 497 if (debug_flags_ & WAIT_FOR_READ) { | 499 if (debug_flags_ & WAIT_FOR_READ) { |
| 498 CHECK(!(debug_flags_ & WAIT_FOR_READ_COMPLETE)); | 500 CHECK(!(debug_flags_ & WAIT_FOR_READ_COMPLETE)); |
| 499 debug_flags_ |= WAIT_FOR_READ_COMPLETE; | 501 debug_flags_ |= WAIT_FOR_READ_COMPLETE; |
| 500 } | 502 } |
| 501 input_state_.is_pending = false; | 503 input_state_.is_pending = false; |
| 502 if (!bytes_transfered) | 504 if (!bytes_transfered) |
| 503 ok = false; | 505 ok = false; |
| 504 else if (pipe_ != INVALID_HANDLE_VALUE) | 506 else if (pipe_.IsValid()) |
| 505 ok = AsyncReadComplete(bytes_transfered); | 507 ok = AsyncReadComplete(bytes_transfered); |
| 506 } else { | 508 } else { |
| 507 DCHECK(!bytes_transfered); | 509 DCHECK(!bytes_transfered); |
| 508 } | 510 } |
| 509 | 511 |
| 510 // Request more data. | 512 // Request more data. |
| 511 if (ok) | 513 if (ok) |
| 512 ok = ProcessIncomingMessages(); | 514 ok = ProcessIncomingMessages(); |
| 513 } else { | 515 } else { |
| 514 DCHECK(context == &output_state_.context); | 516 DCHECK(context == &output_state_.context); |
| 515 CHECK(writing_); | 517 CHECK(writing_); |
| 516 CHECK(output_state_.is_pending); | 518 CHECK(output_state_.is_pending); |
| 517 writing_ = false; | 519 writing_ = false; |
| 518 debug_flags_ |= WRITE_COMPLETED; | 520 debug_flags_ |= WRITE_COMPLETED; |
| 519 if (debug_flags_ & WAIT_FOR_WRITE) { | 521 if (debug_flags_ & WAIT_FOR_WRITE) { |
| 520 CHECK(!(debug_flags_ & WAIT_FOR_WRITE_COMPLETE)); | 522 CHECK(!(debug_flags_ & WAIT_FOR_WRITE_COMPLETE)); |
| 521 debug_flags_ |= WAIT_FOR_WRITE_COMPLETE; | 523 debug_flags_ |= WAIT_FOR_WRITE_COMPLETE; |
| 522 } | 524 } |
| 523 ok = ProcessOutgoingMessages(context, bytes_transfered); | 525 ok = ProcessOutgoingMessages(context, bytes_transfered); |
| 524 } | 526 } |
| 525 if (!ok && INVALID_HANDLE_VALUE != pipe_) { | 527 if (!ok && pipe_.IsValid()) { |
| 526 // We don't want to re-enter Close(). | 528 // We don't want to re-enter Close(). |
| 527 Close(); | 529 Close(); |
| 528 listener()->OnChannelError(); | 530 listener()->OnChannelError(); |
| 529 } | 531 } |
| 530 } | 532 } |
| 531 | 533 |
| 532 //------------------------------------------------------------------------------ | 534 //------------------------------------------------------------------------------ |
| 533 // Channel's methods | 535 // Channel's methods |
| 534 | 536 |
| 535 // static | 537 // static |
| (...skipping 22 matching lines...) Expand all Loading... |
| 558 int secret; | 560 int secret; |
| 559 do { // Guarantee we get a non-zero value. | 561 do { // Guarantee we get a non-zero value. |
| 560 secret = base::RandInt(0, std::numeric_limits<int>::max()); | 562 secret = base::RandInt(0, std::numeric_limits<int>::max()); |
| 561 } while (secret == 0); | 563 } while (secret == 0); |
| 562 | 564 |
| 563 id.append(GenerateUniqueRandomChannelID()); | 565 id.append(GenerateUniqueRandomChannelID()); |
| 564 return id.append(base::StringPrintf("\\%d", secret)); | 566 return id.append(base::StringPrintf("\\%d", secret)); |
| 565 } | 567 } |
| 566 | 568 |
| 567 } // namespace IPC | 569 } // namespace IPC |
| OLD | NEW |