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 |