Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(587)

Side by Side Diff: ipc/ipc_channel_win.cc

Issue 310293002: Make IPC::Channel polymorphic (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Another attempt to fix build breakage Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ipc/ipc_channel_win.h ('k') | ipc/ipc_message.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/pickle.h" 13 #include "base/pickle.h"
14 #include "base/process/process_handle.h" 14 #include "base/process/process_handle.h"
15 #include "base/rand_util.h" 15 #include "base/rand_util.h"
16 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
18 #include "base/threading/thread_checker.h" 18 #include "base/threading/thread_checker.h"
19 #include "base/win/scoped_handle.h" 19 #include "base/win/scoped_handle.h"
20 #include "ipc/ipc_listener.h" 20 #include "ipc/ipc_listener.h"
21 #include "ipc/ipc_logging.h" 21 #include "ipc/ipc_logging.h"
22 #include "ipc/ipc_message_utils.h" 22 #include "ipc/ipc_message_utils.h"
23 23
24 namespace IPC { 24 namespace IPC {
25 25
26 Channel::ChannelImpl::State::State(ChannelImpl* channel) : is_pending(false) { 26 ChannelWin::State::State(ChannelWin* channel) : is_pending(false) {
27 memset(&context.overlapped, 0, sizeof(context.overlapped)); 27 memset(&context.overlapped, 0, sizeof(context.overlapped));
28 context.handler = channel; 28 context.handler = channel;
29 } 29 }
30 30
31 Channel::ChannelImpl::State::~State() { 31 ChannelWin::State::~State() {
32 COMPILE_ASSERT(!offsetof(Channel::ChannelImpl::State, context), 32 COMPILE_ASSERT(!offsetof(ChannelWin::State, context),
33 starts_with_io_context); 33 starts_with_io_context);
34 } 34 }
35 35
36 Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle &channel_handle, 36 ChannelWin::ChannelWin(const IPC::ChannelHandle &channel_handle,
37 Mode mode, Listener* listener) 37 Mode mode, Listener* listener)
38 : ChannelReader(listener), 38 : ChannelReader(listener),
39 input_state_(this), 39 input_state_(this),
40 output_state_(this), 40 output_state_(this),
41 pipe_(INVALID_HANDLE_VALUE), 41 pipe_(INVALID_HANDLE_VALUE),
42 peer_pid_(base::kNullProcessId), 42 peer_pid_(base::kNullProcessId),
43 waiting_connect_(mode & MODE_SERVER_FLAG), 43 waiting_connect_(mode & MODE_SERVER_FLAG),
44 processing_incoming_(false), 44 processing_incoming_(false),
45 weak_factory_(this), 45 weak_factory_(this),
46 client_secret_(0), 46 client_secret_(0),
47 validate_client_(false) { 47 validate_client_(false) {
48 CreatePipe(channel_handle, mode); 48 CreatePipe(channel_handle, mode);
49 } 49 }
50 50
51 Channel::ChannelImpl::~ChannelImpl() { 51 ChannelWin::~ChannelWin() {
52 Close(); 52 Close();
53 } 53 }
54 54
55 void Channel::ChannelImpl::Close() { 55 void ChannelWin::Close() {
56 if (thread_check_.get()) { 56 if (thread_check_.get()) {
57 DCHECK(thread_check_->CalledOnValidThread()); 57 DCHECK(thread_check_->CalledOnValidThread());
58 } 58 }
59 59
60 if (input_state_.is_pending || output_state_.is_pending) 60 if (input_state_.is_pending || output_state_.is_pending)
61 CancelIo(pipe_); 61 CancelIo(pipe_);
62 62
63 // Closing the handle at this point prevents us from issuing more requests 63 // Closing the handle at this point prevents us from issuing more requests
64 // form OnIOCompleted(). 64 // form OnIOCompleted().
65 if (pipe_ != INVALID_HANDLE_VALUE) { 65 if (pipe_ != INVALID_HANDLE_VALUE) {
66 CloseHandle(pipe_); 66 CloseHandle(pipe_);
67 pipe_ = INVALID_HANDLE_VALUE; 67 pipe_ = INVALID_HANDLE_VALUE;
68 } 68 }
69 69
70 // Make sure all IO has completed. 70 // Make sure all IO has completed.
71 base::Time start = base::Time::Now(); 71 base::Time start = base::Time::Now();
72 while (input_state_.is_pending || output_state_.is_pending) { 72 while (input_state_.is_pending || output_state_.is_pending) {
73 base::MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this); 73 base::MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this);
74 } 74 }
75 75
76 while (!output_queue_.empty()) { 76 while (!output_queue_.empty()) {
77 Message* m = output_queue_.front(); 77 Message* m = output_queue_.front();
78 output_queue_.pop(); 78 output_queue_.pop();
79 delete m; 79 delete m;
80 } 80 }
81 } 81 }
82 82
83 bool Channel::ChannelImpl::Send(Message* message) { 83 bool ChannelWin::Send(Message* message) {
84 DCHECK(thread_check_->CalledOnValidThread()); 84 DCHECK(thread_check_->CalledOnValidThread());
85 DVLOG(2) << "sending message @" << message << " on channel @" << this 85 DVLOG(2) << "sending message @" << message << " on channel @" << this
86 << " with type " << message->type() 86 << " with type " << message->type()
87 << " (" << output_queue_.size() << " in queue)"; 87 << " (" << output_queue_.size() << " in queue)";
88 88
89 #ifdef IPC_MESSAGE_LOG_ENABLED 89 #ifdef IPC_MESSAGE_LOG_ENABLED
90 Logging::GetInstance()->OnSendMessage(message, ""); 90 Logging::GetInstance()->OnSendMessage(message, "");
91 #endif 91 #endif
92 92
93 message->TraceMessageBegin(); 93 message->TraceMessageBegin();
94 output_queue_.push(message); 94 output_queue_.push(message);
95 // ensure waiting to write 95 // ensure waiting to write
96 if (!waiting_connect_) { 96 if (!waiting_connect_) {
97 if (!output_state_.is_pending) { 97 if (!output_state_.is_pending) {
98 if (!ProcessOutgoingMessages(NULL, 0)) 98 if (!ProcessOutgoingMessages(NULL, 0))
99 return false; 99 return false;
100 } 100 }
101 } 101 }
102 102
103 return true; 103 return true;
104 } 104 }
105 105
106 base::ProcessId ChannelWin::GetPeerPID() const {
107 return peer_pid_;
108 }
109
106 // static 110 // static
107 bool Channel::ChannelImpl::IsNamedServerInitialized( 111 bool ChannelWin::IsNamedServerInitialized(
108 const std::string& channel_id) { 112 const std::string& channel_id) {
109 if (WaitNamedPipe(PipeName(channel_id, NULL).c_str(), 1)) 113 if (WaitNamedPipe(PipeName(channel_id, NULL).c_str(), 1))
110 return true; 114 return true;
111 // If ERROR_SEM_TIMEOUT occurred, the pipe exists but is handling another 115 // If ERROR_SEM_TIMEOUT occurred, the pipe exists but is handling another
112 // connection. 116 // connection.
113 return GetLastError() == ERROR_SEM_TIMEOUT; 117 return GetLastError() == ERROR_SEM_TIMEOUT;
114 } 118 }
115 119
116 Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData( 120 ChannelWin::ReadState ChannelWin::ReadData(
117 char* buffer, 121 char* buffer,
118 int buffer_len, 122 int buffer_len,
119 int* /* bytes_read */) { 123 int* /* bytes_read */) {
120 if (INVALID_HANDLE_VALUE == pipe_) 124 if (INVALID_HANDLE_VALUE == pipe_)
121 return READ_FAILED; 125 return READ_FAILED;
122 126
123 DWORD bytes_read = 0; 127 DWORD bytes_read = 0;
124 BOOL ok = ReadFile(pipe_, buffer, buffer_len, 128 BOOL ok = ReadFile(pipe_, buffer, buffer_len,
125 &bytes_read, &input_state_.context.overlapped); 129 &bytes_read, &input_state_.context.overlapped);
126 if (!ok) { 130 if (!ok) {
(...skipping 11 matching lines...) Expand all
138 // will be signalled even in the "synchronously completed" state. 142 // will be signalled even in the "synchronously completed" state.
139 // 143 //
140 // This allows us to potentially process some outgoing messages and 144 // This allows us to potentially process some outgoing messages and
141 // interleave other work on this thread when we're getting hammered with 145 // interleave other work on this thread when we're getting hammered with
142 // input messages. Potentially, this could be tuned to be more efficient 146 // input messages. Potentially, this could be tuned to be more efficient
143 // with some testing. 147 // with some testing.
144 input_state_.is_pending = true; 148 input_state_.is_pending = true;
145 return READ_PENDING; 149 return READ_PENDING;
146 } 150 }
147 151
148 bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) { 152 bool ChannelWin::WillDispatchInputMessage(Message* msg) {
149 // Make sure we get a hello when client validation is required. 153 // Make sure we get a hello when client validation is required.
150 if (validate_client_) 154 if (validate_client_)
151 return IsHelloMessage(*msg); 155 return IsHelloMessage(*msg);
152 return true; 156 return true;
153 } 157 }
154 158
155 void Channel::ChannelImpl::HandleInternalMessage(const Message& msg) { 159 void ChannelWin::HandleInternalMessage(const Message& msg) {
156 DCHECK_EQ(msg.type(), static_cast<unsigned>(Channel::HELLO_MESSAGE_TYPE)); 160 DCHECK_EQ(msg.type(), static_cast<unsigned>(Channel::HELLO_MESSAGE_TYPE));
157 // The hello message contains one parameter containing the PID. 161 // The hello message contains one parameter containing the PID.
158 PickleIterator it(msg); 162 PickleIterator it(msg);
159 int32 claimed_pid; 163 int32 claimed_pid;
160 bool failed = !it.ReadInt(&claimed_pid); 164 bool failed = !it.ReadInt(&claimed_pid);
161 165
162 if (!failed && validate_client_) { 166 if (!failed && validate_client_) {
163 int32 secret; 167 int32 secret;
164 failed = it.ReadInt(&secret) ? (secret != client_secret_) : true; 168 failed = it.ReadInt(&secret) ? (secret != client_secret_) : true;
165 } 169 }
166 170
167 if (failed) { 171 if (failed) {
168 NOTREACHED(); 172 NOTREACHED();
169 Close(); 173 Close();
170 listener()->OnChannelError(); 174 listener()->OnChannelError();
171 return; 175 return;
172 } 176 }
173 177
174 peer_pid_ = claimed_pid; 178 peer_pid_ = claimed_pid;
175 // Validation completed. 179 // Validation completed.
176 validate_client_ = false; 180 validate_client_ = false;
177 listener()->OnChannelConnected(claimed_pid); 181 listener()->OnChannelConnected(claimed_pid);
178 } 182 }
179 183
180 bool Channel::ChannelImpl::DidEmptyInputBuffers() { 184 bool ChannelWin::DidEmptyInputBuffers() {
181 // We don't need to do anything here. 185 // We don't need to do anything here.
182 return true; 186 return true;
183 } 187 }
184 188
185 // static 189 // static
186 const base::string16 Channel::ChannelImpl::PipeName( 190 const base::string16 ChannelWin::PipeName(
187 const std::string& channel_id, int32* secret) { 191 const std::string& channel_id, int32* secret) {
188 std::string name("\\\\.\\pipe\\chrome."); 192 std::string name("\\\\.\\pipe\\chrome.");
189 193
190 // Prevent the shared secret from ending up in the pipe name. 194 // Prevent the shared secret from ending up in the pipe name.
191 size_t index = channel_id.find_first_of('\\'); 195 size_t index = channel_id.find_first_of('\\');
192 if (index != std::string::npos) { 196 if (index != std::string::npos) {
193 if (secret) // Retrieve the secret if asked for. 197 if (secret) // Retrieve the secret if asked for.
194 base::StringToInt(channel_id.substr(index + 1), secret); 198 base::StringToInt(channel_id.substr(index + 1), secret);
195 return base::ASCIIToWide(name.append(channel_id.substr(0, index - 1))); 199 return base::ASCIIToWide(name.append(channel_id.substr(0, index - 1)));
196 } 200 }
197 201
198 // This case is here to support predictable named pipes in tests. 202 // This case is here to support predictable named pipes in tests.
199 if (secret) 203 if (secret)
200 *secret = 0; 204 *secret = 0;
201 return base::ASCIIToWide(name.append(channel_id)); 205 return base::ASCIIToWide(name.append(channel_id));
202 } 206 }
203 207
204 bool Channel::ChannelImpl::CreatePipe(const IPC::ChannelHandle &channel_handle, 208 bool ChannelWin::CreatePipe(const IPC::ChannelHandle &channel_handle,
205 Mode mode) { 209 Mode mode) {
206 DCHECK_EQ(INVALID_HANDLE_VALUE, pipe_); 210 DCHECK_EQ(INVALID_HANDLE_VALUE, pipe_);
207 base::string16 pipe_name; 211 base::string16 pipe_name;
208 // If we already have a valid pipe for channel just copy it. 212 // If we already have a valid pipe for channel just copy it.
209 if (channel_handle.pipe.handle) { 213 if (channel_handle.pipe.handle) {
210 DCHECK(channel_handle.name.empty()); 214 DCHECK(channel_handle.name.empty());
211 pipe_name = L"Not Available"; // Just used for LOG 215 pipe_name = L"Not Available"; // Just used for LOG
212 // Check that the given pipe confirms to the specified mode. We can 216 // Check that the given pipe confirms to the specified mode. We can
213 // only check for PIPE_TYPE_MESSAGE & PIPE_SERVER_END flags since the 217 // only check for PIPE_TYPE_MESSAGE & PIPE_SERVER_END flags since the
214 // other flags (PIPE_TYPE_BYTE, and PIPE_CLIENT_END) are defined as 0. 218 // other flags (PIPE_TYPE_BYTE, and PIPE_CLIENT_END) are defined as 0.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 (secret && !m->WriteUInt32(secret))) { 283 (secret && !m->WriteUInt32(secret))) {
280 CloseHandle(pipe_); 284 CloseHandle(pipe_);
281 pipe_ = INVALID_HANDLE_VALUE; 285 pipe_ = INVALID_HANDLE_VALUE;
282 return false; 286 return false;
283 } 287 }
284 288
285 output_queue_.push(m.release()); 289 output_queue_.push(m.release());
286 return true; 290 return true;
287 } 291 }
288 292
289 bool Channel::ChannelImpl::Connect() { 293 bool ChannelWin::Connect() {
290 DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once"; 294 DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once";
291 295
292 if (!thread_check_.get()) 296 if (!thread_check_.get())
293 thread_check_.reset(new base::ThreadChecker()); 297 thread_check_.reset(new base::ThreadChecker());
294 298
295 if (pipe_ == INVALID_HANDLE_VALUE) 299 if (pipe_ == INVALID_HANDLE_VALUE)
296 return false; 300 return false;
297 301
298 base::MessageLoopForIO::current()->RegisterIOHandler(pipe_, this); 302 base::MessageLoopForIO::current()->RegisterIOHandler(pipe_, this);
299 303
300 // Check to see if there is a client connected to our pipe... 304 // Check to see if there is a client connected to our pipe...
301 if (waiting_connect_) 305 if (waiting_connect_)
302 ProcessConnection(); 306 ProcessConnection();
303 307
304 if (!input_state_.is_pending) { 308 if (!input_state_.is_pending) {
305 // Complete setup asynchronously. By not setting input_state_.is_pending 309 // Complete setup asynchronously. By not setting input_state_.is_pending
306 // to true, we indicate to OnIOCompleted that this is the special 310 // to true, we indicate to OnIOCompleted that this is the special
307 // initialization signal. 311 // initialization signal.
308 base::MessageLoopForIO::current()->PostTask( 312 base::MessageLoopForIO::current()->PostTask(
309 FROM_HERE, 313 FROM_HERE,
310 base::Bind(&Channel::ChannelImpl::OnIOCompleted, 314 base::Bind(&ChannelWin::OnIOCompleted,
311 weak_factory_.GetWeakPtr(), 315 weak_factory_.GetWeakPtr(),
312 &input_state_.context, 316 &input_state_.context,
313 0, 317 0,
314 0)); 318 0));
315 } 319 }
316 320
317 if (!waiting_connect_) 321 if (!waiting_connect_)
318 ProcessOutgoingMessages(NULL, 0); 322 ProcessOutgoingMessages(NULL, 0);
319 return true; 323 return true;
320 } 324 }
321 325
322 bool Channel::ChannelImpl::ProcessConnection() { 326 bool ChannelWin::ProcessConnection() {
323 DCHECK(thread_check_->CalledOnValidThread()); 327 DCHECK(thread_check_->CalledOnValidThread());
324 if (input_state_.is_pending) 328 if (input_state_.is_pending)
325 input_state_.is_pending = false; 329 input_state_.is_pending = false;
326 330
327 // Do we have a client connected to our pipe? 331 // Do we have a client connected to our pipe?
328 if (INVALID_HANDLE_VALUE == pipe_) 332 if (INVALID_HANDLE_VALUE == pipe_)
329 return false; 333 return false;
330 334
331 BOOL ok = ConnectNamedPipe(pipe_, &input_state_.context.overlapped); 335 BOOL ok = ConnectNamedPipe(pipe_, &input_state_.context.overlapped);
332 336
(...skipping 16 matching lines...) Expand all
349 // The pipe is being closed. 353 // The pipe is being closed.
350 return false; 354 return false;
351 default: 355 default:
352 NOTREACHED(); 356 NOTREACHED();
353 return false; 357 return false;
354 } 358 }
355 359
356 return true; 360 return true;
357 } 361 }
358 362
359 bool Channel::ChannelImpl::ProcessOutgoingMessages( 363 bool ChannelWin::ProcessOutgoingMessages(
360 base::MessageLoopForIO::IOContext* context, 364 base::MessageLoopForIO::IOContext* context,
361 DWORD bytes_written) { 365 DWORD bytes_written) {
362 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's 366 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
363 // no connection? 367 // no connection?
364 DCHECK(thread_check_->CalledOnValidThread()); 368 DCHECK(thread_check_->CalledOnValidThread());
365 369
366 if (output_state_.is_pending) { 370 if (output_state_.is_pending) {
367 DCHECK(context); 371 DCHECK(context);
368 output_state_.is_pending = false; 372 output_state_.is_pending = false;
369 if (!context || bytes_written == 0) { 373 if (!context || bytes_written == 0) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 return false; 410 return false;
407 } 411 }
408 412
409 DVLOG(2) << "sent message @" << m << " on channel @" << this 413 DVLOG(2) << "sent message @" << m << " on channel @" << this
410 << " with type " << m->type(); 414 << " with type " << m->type();
411 415
412 output_state_.is_pending = true; 416 output_state_.is_pending = true;
413 return true; 417 return true;
414 } 418 }
415 419
416 void Channel::ChannelImpl::OnIOCompleted( 420 void ChannelWin::OnIOCompleted(
417 base::MessageLoopForIO::IOContext* context, 421 base::MessageLoopForIO::IOContext* context,
418 DWORD bytes_transfered, 422 DWORD bytes_transfered,
419 DWORD error) { 423 DWORD error) {
420 bool ok = true; 424 bool ok = true;
421 DCHECK(thread_check_->CalledOnValidThread()); 425 DCHECK(thread_check_->CalledOnValidThread());
422 if (context == &input_state_.context) { 426 if (context == &input_state_.context) {
423 if (waiting_connect_) { 427 if (waiting_connect_) {
424 if (!ProcessConnection()) 428 if (!ProcessConnection())
425 return; 429 return;
426 // We may have some messages queued up to send... 430 // We may have some messages queued up to send...
(...skipping 29 matching lines...) Expand all
456 ok = ProcessOutgoingMessages(context, bytes_transfered); 460 ok = ProcessOutgoingMessages(context, bytes_transfered);
457 } 461 }
458 if (!ok && INVALID_HANDLE_VALUE != pipe_) { 462 if (!ok && INVALID_HANDLE_VALUE != pipe_) {
459 // We don't want to re-enter Close(). 463 // We don't want to re-enter Close().
460 Close(); 464 Close();
461 listener()->OnChannelError(); 465 listener()->OnChannelError();
462 } 466 }
463 } 467 }
464 468
465 //------------------------------------------------------------------------------ 469 //------------------------------------------------------------------------------
466 // Channel's methods simply call through to ChannelImpl. 470 // Channel's methods
467 Channel::Channel(const IPC::ChannelHandle &channel_handle, Mode mode,
468 Listener* listener)
469 : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) {
470 }
471 471
472 Channel::~Channel() { 472 // static
473 delete channel_impl_; 473 scoped_ptr<Channel> Channel::Create(
474 } 474 const IPC::ChannelHandle &channel_handle, Mode mode, Listener* listener) {
475 475 return scoped_ptr<Channel>(
476 bool Channel::Connect() { 476 new ChannelWin(channel_handle, mode, listener));
477 return channel_impl_->Connect();
478 }
479
480 void Channel::Close() {
481 if (channel_impl_)
482 channel_impl_->Close();
483 }
484
485 base::ProcessId Channel::peer_pid() const {
486 return channel_impl_->peer_pid();
487 }
488
489 bool Channel::Send(Message* message) {
490 return channel_impl_->Send(message);
491 } 477 }
492 478
493 // static 479 // static
494 bool Channel::IsNamedServerInitialized(const std::string& channel_id) { 480 bool Channel::IsNamedServerInitialized(const std::string& channel_id) {
495 return ChannelImpl::IsNamedServerInitialized(channel_id); 481 return ChannelWin::IsNamedServerInitialized(channel_id);
496 } 482 }
497 483
498 // static 484 // static
499 std::string Channel::GenerateVerifiedChannelID(const std::string& prefix) { 485 std::string Channel::GenerateVerifiedChannelID(const std::string& prefix) {
500 // Windows pipes can be enumerated by low-privileged processes. So, we 486 // Windows pipes can be enumerated by low-privileged processes. So, we
501 // append a strong random value after the \ character. This value is not 487 // append a strong random value after the \ character. This value is not
502 // included in the pipe name, but sent as part of the client hello, to 488 // included in the pipe name, but sent as part of the client hello, to
503 // hijacking the pipe name to spoof the client. 489 // hijacking the pipe name to spoof the client.
504 490
505 std::string id = prefix; 491 std::string id = prefix;
506 if (!id.empty()) 492 if (!id.empty())
507 id.append("."); 493 id.append(".");
508 494
509 int secret; 495 int secret;
510 do { // Guarantee we get a non-zero value. 496 do { // Guarantee we get a non-zero value.
511 secret = base::RandInt(0, std::numeric_limits<int>::max()); 497 secret = base::RandInt(0, std::numeric_limits<int>::max());
512 } while (secret == 0); 498 } while (secret == 0);
513 499
514 id.append(GenerateUniqueRandomChannelID()); 500 id.append(GenerateUniqueRandomChannelID());
515 return id.append(base::StringPrintf("\\%d", secret)); 501 return id.append(base::StringPrintf("\\%d", secret));
516 } 502 }
517 503
518 } // namespace IPC 504 } // namespace IPC
OLDNEW
« no previous file with comments | « ipc/ipc_channel_win.h ('k') | ipc/ipc_message.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698