| 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_nacl.h" | 5 #include "ipc/ipc_channel_nacl.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <sys/types.h> | 9 #include <sys/types.h> |
| 10 | 10 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 } | 55 } |
| 56 DCHECK(bytes_read); | 56 DCHECK(bytes_read); |
| 57 // Resize the buffers down to the number of bytes and fds we actually read. | 57 // Resize the buffers down to the number of bytes and fds we actually read. |
| 58 contents->data.resize(bytes_read); | 58 contents->data.resize(bytes_read); |
| 59 contents->fds.resize(msg.desc_length); | 59 contents->fds.resize(msg.desc_length); |
| 60 return true; | 60 return true; |
| 61 } | 61 } |
| 62 | 62 |
| 63 } // namespace | 63 } // namespace |
| 64 | 64 |
| 65 class Channel::ChannelImpl::ReaderThreadRunner | 65 class ChannelNacl::ReaderThreadRunner |
| 66 : public base::DelegateSimpleThread::Delegate { | 66 : public base::DelegateSimpleThread::Delegate { |
| 67 public: | 67 public: |
| 68 // |pipe|: A file descriptor from which we will read using imc_recvmsg. | 68 // |pipe|: A file descriptor from which we will read using imc_recvmsg. |
| 69 // |data_read_callback|: A callback we invoke (on the main thread) when we | 69 // |data_read_callback|: A callback we invoke (on the main thread) when we |
| 70 // have read data. | 70 // have read data. |
| 71 // |failure_callback|: A callback we invoke when we have a failure reading | 71 // |failure_callback|: A callback we invoke when we have a failure reading |
| 72 // from |pipe|. | 72 // from |pipe|. |
| 73 // |main_message_loop|: A proxy for the main thread, where we will invoke the | 73 // |main_message_loop|: A proxy for the main thread, where we will invoke the |
| 74 // above callbacks. | 74 // above callbacks. |
| 75 ReaderThreadRunner( | 75 ReaderThreadRunner( |
| 76 int pipe, | 76 int pipe, |
| 77 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback, | 77 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback, |
| 78 base::Callback<void ()> failure_callback, | 78 base::Callback<void ()> failure_callback, |
| 79 scoped_refptr<base::MessageLoopProxy> main_message_loop); | 79 scoped_refptr<base::MessageLoopProxy> main_message_loop); |
| 80 | 80 |
| 81 // DelegateSimpleThread implementation. Reads data from the pipe in a loop | 81 // DelegateSimpleThread implementation. Reads data from the pipe in a loop |
| 82 // until either we are told to quit or a read fails. | 82 // until either we are told to quit or a read fails. |
| 83 virtual void Run() OVERRIDE; | 83 virtual void Run() OVERRIDE; |
| 84 | 84 |
| 85 private: | 85 private: |
| 86 int pipe_; | 86 int pipe_; |
| 87 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback_; | 87 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback_; |
| 88 base::Callback<void ()> failure_callback_; | 88 base::Callback<void ()> failure_callback_; |
| 89 scoped_refptr<base::MessageLoopProxy> main_message_loop_; | 89 scoped_refptr<base::MessageLoopProxy> main_message_loop_; |
| 90 | 90 |
| 91 DISALLOW_COPY_AND_ASSIGN(ReaderThreadRunner); | 91 DISALLOW_COPY_AND_ASSIGN(ReaderThreadRunner); |
| 92 }; | 92 }; |
| 93 | 93 |
| 94 Channel::ChannelImpl::ReaderThreadRunner::ReaderThreadRunner( | 94 ChannelNacl::ReaderThreadRunner::ReaderThreadRunner( |
| 95 int pipe, | 95 int pipe, |
| 96 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback, | 96 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback, |
| 97 base::Callback<void ()> failure_callback, | 97 base::Callback<void ()> failure_callback, |
| 98 scoped_refptr<base::MessageLoopProxy> main_message_loop) | 98 scoped_refptr<base::MessageLoopProxy> main_message_loop) |
| 99 : pipe_(pipe), | 99 : pipe_(pipe), |
| 100 data_read_callback_(data_read_callback), | 100 data_read_callback_(data_read_callback), |
| 101 failure_callback_(failure_callback), | 101 failure_callback_(failure_callback), |
| 102 main_message_loop_(main_message_loop) { | 102 main_message_loop_(main_message_loop) { |
| 103 } | 103 } |
| 104 | 104 |
| 105 void Channel::ChannelImpl::ReaderThreadRunner::Run() { | 105 void ChannelNacl::ReaderThreadRunner::Run() { |
| 106 while (true) { | 106 while (true) { |
| 107 scoped_ptr<MessageContents> msg_contents(new MessageContents); | 107 scoped_ptr<MessageContents> msg_contents(new MessageContents); |
| 108 bool success = ReadDataOnReaderThread(pipe_, msg_contents.get()); | 108 bool success = ReadDataOnReaderThread(pipe_, msg_contents.get()); |
| 109 if (success) { | 109 if (success) { |
| 110 main_message_loop_->PostTask(FROM_HERE, | 110 main_message_loop_->PostTask(FROM_HERE, |
| 111 base::Bind(data_read_callback_, base::Passed(&msg_contents))); | 111 base::Bind(data_read_callback_, base::Passed(&msg_contents))); |
| 112 } else { | 112 } else { |
| 113 main_message_loop_->PostTask(FROM_HERE, failure_callback_); | 113 main_message_loop_->PostTask(FROM_HERE, failure_callback_); |
| 114 // Because the read failed, we know we're going to quit. Don't bother | 114 // Because the read failed, we know we're going to quit. Don't bother |
| 115 // trying to read again. | 115 // trying to read again. |
| 116 return; | 116 return; |
| 117 } | 117 } |
| 118 } | 118 } |
| 119 } | 119 } |
| 120 | 120 |
| 121 Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle& channel_handle, | 121 ChannelNacl::ChannelNacl(const IPC::ChannelHandle& channel_handle, |
| 122 Mode mode, | 122 Mode mode, |
| 123 Listener* listener) | 123 Listener* listener) |
| 124 : ChannelReader(listener), | 124 : ChannelReader(listener), |
| 125 mode_(mode), | 125 mode_(mode), |
| 126 waiting_connect_(true), | 126 waiting_connect_(true), |
| 127 pipe_(-1), | 127 pipe_(-1), |
| 128 pipe_name_(channel_handle.name), | 128 pipe_name_(channel_handle.name), |
| 129 weak_ptr_factory_(this) { | 129 weak_ptr_factory_(this) { |
| 130 if (!CreatePipe(channel_handle)) { | 130 if (!CreatePipe(channel_handle)) { |
| 131 // The pipe may have been closed already. | 131 // The pipe may have been closed already. |
| 132 const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client"; | 132 const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client"; |
| 133 LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name | 133 LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name |
| 134 << "\" in " << modestr << " mode"; | 134 << "\" in " << modestr << " mode"; |
| 135 } | 135 } |
| 136 } | 136 } |
| 137 | 137 |
| 138 Channel::ChannelImpl::~ChannelImpl() { | 138 ChannelNacl::~ChannelNacl() { |
| 139 Close(); | 139 Close(); |
| 140 } | 140 } |
| 141 | 141 |
| 142 base::ProcessId Channel::ChannelImpl::peer_pid() const { | 142 base::ProcessId ChannelNacl::GetPeerPID() const { |
| 143 // This shouldn't actually get used in the untrusted side of the proxy, and we | 143 // This shouldn't actually get used in the untrusted side of the proxy, and we |
| 144 // don't have the real pid anyway. | 144 // don't have the real pid anyway. |
| 145 return -1; | 145 return -1; |
| 146 } | 146 } |
| 147 | 147 |
| 148 bool Channel::ChannelImpl::Connect() { | 148 bool ChannelNacl::Connect() { |
| 149 if (pipe_ == -1) { | 149 if (pipe_ == -1) { |
| 150 DLOG(WARNING) << "Channel creation failed: " << pipe_name_; | 150 DLOG(WARNING) << "Channel creation failed: " << pipe_name_; |
| 151 return false; | 151 return false; |
| 152 } | 152 } |
| 153 | 153 |
| 154 // Note that Connect is called on the "Channel" thread (i.e., the same thread | 154 // Note that Connect is called on the "Channel" thread (i.e., the same thread |
| 155 // where Channel::Send will be called, and the same thread that should receive | 155 // where Channel::Send will be called, and the same thread that should receive |
| 156 // messages). The constructor might be invoked on another thread (see | 156 // messages). The constructor might be invoked on another thread (see |
| 157 // ChannelProxy for an example of that). Therefore, we must wait until Connect | 157 // ChannelProxy for an example of that). Therefore, we must wait until Connect |
| 158 // is called to decide which MessageLoopProxy to pass to ReaderThreadRunner. | 158 // is called to decide which MessageLoopProxy to pass to ReaderThreadRunner. |
| 159 reader_thread_runner_.reset( | 159 reader_thread_runner_.reset( |
| 160 new ReaderThreadRunner( | 160 new ReaderThreadRunner( |
| 161 pipe_, | 161 pipe_, |
| 162 base::Bind(&Channel::ChannelImpl::DidRecvMsg, | 162 base::Bind(&ChannelNacl::DidRecvMsg, |
| 163 weak_ptr_factory_.GetWeakPtr()), | 163 weak_ptr_factory_.GetWeakPtr()), |
| 164 base::Bind(&Channel::ChannelImpl::ReadDidFail, | 164 base::Bind(&ChannelNacl::ReadDidFail, |
| 165 weak_ptr_factory_.GetWeakPtr()), | 165 weak_ptr_factory_.GetWeakPtr()), |
| 166 base::MessageLoopProxy::current())); | 166 base::MessageLoopProxy::current())); |
| 167 reader_thread_.reset( | 167 reader_thread_.reset( |
| 168 new base::DelegateSimpleThread(reader_thread_runner_.get(), | 168 new base::DelegateSimpleThread(reader_thread_runner_.get(), |
| 169 "ipc_channel_nacl reader thread")); | 169 "ipc_channel_nacl reader thread")); |
| 170 reader_thread_->Start(); | 170 reader_thread_->Start(); |
| 171 waiting_connect_ = false; | 171 waiting_connect_ = false; |
| 172 // If there were any messages queued before connection, send them. | 172 // If there were any messages queued before connection, send them. |
| 173 ProcessOutgoingMessages(); | 173 ProcessOutgoingMessages(); |
| 174 base::MessageLoopProxy::current()->PostTask(FROM_HERE, | 174 base::MessageLoopProxy::current()->PostTask(FROM_HERE, |
| 175 base::Bind(&Channel::ChannelImpl::CallOnChannelConnected, | 175 base::Bind(&ChannelNacl::CallOnChannelConnected, |
| 176 weak_ptr_factory_.GetWeakPtr())); | 176 weak_ptr_factory_.GetWeakPtr())); |
| 177 | 177 |
| 178 return true; | 178 return true; |
| 179 } | 179 } |
| 180 | 180 |
| 181 void Channel::ChannelImpl::Close() { | 181 void ChannelNacl::Close() { |
| 182 // For now, we assume that at shutdown, the reader thread will be woken with | 182 // For now, we assume that at shutdown, the reader thread will be woken with |
| 183 // a failure (see NaClIPCAdapter::BlockingRead and CloseChannel). Or... we | 183 // a failure (see NaClIPCAdapter::BlockingRead and CloseChannel). Or... we |
| 184 // might simply be killed with no chance to clean up anyway :-). | 184 // might simply be killed with no chance to clean up anyway :-). |
| 185 // If untrusted code tries to close the channel prior to shutdown, it's likely | 185 // If untrusted code tries to close the channel prior to shutdown, it's likely |
| 186 // to hang. | 186 // to hang. |
| 187 // TODO(dmichael): Can we do anything smarter here to make sure the reader | 187 // TODO(dmichael): Can we do anything smarter here to make sure the reader |
| 188 // thread wakes up and quits? | 188 // thread wakes up and quits? |
| 189 reader_thread_->Join(); | 189 reader_thread_->Join(); |
| 190 close(pipe_); | 190 close(pipe_); |
| 191 pipe_ = -1; | 191 pipe_ = -1; |
| 192 reader_thread_runner_.reset(); | 192 reader_thread_runner_.reset(); |
| 193 reader_thread_.reset(); | 193 reader_thread_.reset(); |
| 194 read_queue_.clear(); | 194 read_queue_.clear(); |
| 195 output_queue_.clear(); | 195 output_queue_.clear(); |
| 196 } | 196 } |
| 197 | 197 |
| 198 bool Channel::ChannelImpl::Send(Message* message) { | 198 bool ChannelNacl::Send(Message* message) { |
| 199 DVLOG(2) << "sending message @" << message << " on channel @" << this | 199 DVLOG(2) << "sending message @" << message << " on channel @" << this |
| 200 << " with type " << message->type(); | 200 << " with type " << message->type(); |
| 201 scoped_ptr<Message> message_ptr(message); | 201 scoped_ptr<Message> message_ptr(message); |
| 202 | 202 |
| 203 #ifdef IPC_MESSAGE_LOG_ENABLED | 203 #ifdef IPC_MESSAGE_LOG_ENABLED |
| 204 Logging::GetInstance()->OnSendMessage(message_ptr.get(), ""); | 204 Logging::GetInstance()->OnSendMessage(message_ptr.get(), ""); |
| 205 #endif // IPC_MESSAGE_LOG_ENABLED | 205 #endif // IPC_MESSAGE_LOG_ENABLED |
| 206 | 206 |
| 207 message->TraceMessageBegin(); | 207 message->TraceMessageBegin(); |
| 208 output_queue_.push_back(linked_ptr<Message>(message_ptr.release())); | 208 output_queue_.push_back(linked_ptr<Message>(message_ptr.release())); |
| 209 if (!waiting_connect_) | 209 if (!waiting_connect_) |
| 210 return ProcessOutgoingMessages(); | 210 return ProcessOutgoingMessages(); |
| 211 | 211 |
| 212 return true; | 212 return true; |
| 213 } | 213 } |
| 214 | 214 |
| 215 void Channel::ChannelImpl::DidRecvMsg(scoped_ptr<MessageContents> contents) { | 215 void ChannelNacl::DidRecvMsg(scoped_ptr<MessageContents> contents) { |
| 216 // Close sets the pipe to -1. It's possible we'll get a buffer sent to us from | 216 // Close sets the pipe to -1. It's possible we'll get a buffer sent to us from |
| 217 // the reader thread after Close is called. If so, we ignore it. | 217 // the reader thread after Close is called. If so, we ignore it. |
| 218 if (pipe_ == -1) | 218 if (pipe_ == -1) |
| 219 return; | 219 return; |
| 220 | 220 |
| 221 linked_ptr<std::vector<char> > data(new std::vector<char>); | 221 linked_ptr<std::vector<char> > data(new std::vector<char>); |
| 222 data->swap(contents->data); | 222 data->swap(contents->data); |
| 223 read_queue_.push_back(data); | 223 read_queue_.push_back(data); |
| 224 | 224 |
| 225 input_fds_.insert(input_fds_.end(), | 225 input_fds_.insert(input_fds_.end(), |
| 226 contents->fds.begin(), contents->fds.end()); | 226 contents->fds.begin(), contents->fds.end()); |
| 227 contents->fds.clear(); | 227 contents->fds.clear(); |
| 228 | 228 |
| 229 // In POSIX, we would be told when there are bytes to read by implementing | 229 // In POSIX, we would be told when there are bytes to read by implementing |
| 230 // OnFileCanReadWithoutBlocking in MessageLoopForIO::Watcher. In NaCl, we | 230 // OnFileCanReadWithoutBlocking in MessageLoopForIO::Watcher. In NaCl, we |
| 231 // instead know at this point because the reader thread posted some data to | 231 // instead know at this point because the reader thread posted some data to |
| 232 // us. | 232 // us. |
| 233 ProcessIncomingMessages(); | 233 ProcessIncomingMessages(); |
| 234 } | 234 } |
| 235 | 235 |
| 236 void Channel::ChannelImpl::ReadDidFail() { | 236 void ChannelNacl::ReadDidFail() { |
| 237 Close(); | 237 Close(); |
| 238 } | 238 } |
| 239 | 239 |
| 240 bool Channel::ChannelImpl::CreatePipe( | 240 bool ChannelNacl::CreatePipe( |
| 241 const IPC::ChannelHandle& channel_handle) { | 241 const IPC::ChannelHandle& channel_handle) { |
| 242 DCHECK(pipe_ == -1); | 242 DCHECK(pipe_ == -1); |
| 243 | 243 |
| 244 // There's one possible case in NaCl: | 244 // There's one possible case in NaCl: |
| 245 // 1) It's a channel wrapping a pipe that is given to us. | 245 // 1) It's a channel wrapping a pipe that is given to us. |
| 246 // We don't support these: | 246 // We don't support these: |
| 247 // 2) It's for a named channel. | 247 // 2) It's for a named channel. |
| 248 // 3) It's for a client that we implement ourself. | 248 // 3) It's for a client that we implement ourself. |
| 249 // 4) It's the initial IPC channel. | 249 // 4) It's the initial IPC channel. |
| 250 | 250 |
| 251 if (channel_handle.socket.fd == -1) { | 251 if (channel_handle.socket.fd == -1) { |
| 252 NOTIMPLEMENTED(); | 252 NOTIMPLEMENTED(); |
| 253 return false; | 253 return false; |
| 254 } | 254 } |
| 255 pipe_ = channel_handle.socket.fd; | 255 pipe_ = channel_handle.socket.fd; |
| 256 return true; | 256 return true; |
| 257 } | 257 } |
| 258 | 258 |
| 259 bool Channel::ChannelImpl::ProcessOutgoingMessages() { | 259 bool ChannelNacl::ProcessOutgoingMessages() { |
| 260 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's | 260 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's |
| 261 // no connection? | 261 // no connection? |
| 262 if (output_queue_.empty()) | 262 if (output_queue_.empty()) |
| 263 return true; | 263 return true; |
| 264 | 264 |
| 265 if (pipe_ == -1) | 265 if (pipe_ == -1) |
| 266 return false; | 266 return false; |
| 267 | 267 |
| 268 // Write out all the messages. The trusted implementation is guaranteed to not | 268 // Write out all the messages. The trusted implementation is guaranteed to not |
| 269 // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg. | 269 // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 297 msg->file_descriptor_set()->CommitAll(); | 297 msg->file_descriptor_set()->CommitAll(); |
| 298 } | 298 } |
| 299 | 299 |
| 300 // Message sent OK! | 300 // Message sent OK! |
| 301 DVLOG(2) << "sent message @" << msg.get() << " with type " << msg->type() | 301 DVLOG(2) << "sent message @" << msg.get() << " with type " << msg->type() |
| 302 << " on fd " << pipe_; | 302 << " on fd " << pipe_; |
| 303 } | 303 } |
| 304 return true; | 304 return true; |
| 305 } | 305 } |
| 306 | 306 |
| 307 void Channel::ChannelImpl::CallOnChannelConnected() { | 307 void ChannelNacl::CallOnChannelConnected() { |
| 308 listener()->OnChannelConnected(peer_pid()); | 308 listener()->OnChannelConnected(GetPeerPID()); |
| 309 } | 309 } |
| 310 | 310 |
| 311 Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData( | 311 ChannelNacl::ReadState ChannelNacl::ReadData( |
| 312 char* buffer, | 312 char* buffer, |
| 313 int buffer_len, | 313 int buffer_len, |
| 314 int* bytes_read) { | 314 int* bytes_read) { |
| 315 *bytes_read = 0; | 315 *bytes_read = 0; |
| 316 if (pipe_ == -1) | 316 if (pipe_ == -1) |
| 317 return READ_FAILED; | 317 return READ_FAILED; |
| 318 if (read_queue_.empty()) | 318 if (read_queue_.empty()) |
| 319 return READ_PENDING; | 319 return READ_PENDING; |
| 320 while (!read_queue_.empty() && *bytes_read < buffer_len) { | 320 while (!read_queue_.empty() && *bytes_read < buffer_len) { |
| 321 linked_ptr<std::vector<char> > vec(read_queue_.front()); | 321 linked_ptr<std::vector<char> > vec(read_queue_.front()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 332 // the code simple). | 332 // the code simple). |
| 333 std::copy(vec->begin(), vec->begin() + bytes_to_read, | 333 std::copy(vec->begin(), vec->begin() + bytes_to_read, |
| 334 buffer + *bytes_read); | 334 buffer + *bytes_read); |
| 335 vec->erase(vec->begin(), vec->begin() + bytes_to_read); | 335 vec->erase(vec->begin(), vec->begin() + bytes_to_read); |
| 336 *bytes_read += bytes_to_read; | 336 *bytes_read += bytes_to_read; |
| 337 } | 337 } |
| 338 } | 338 } |
| 339 return READ_SUCCEEDED; | 339 return READ_SUCCEEDED; |
| 340 } | 340 } |
| 341 | 341 |
| 342 bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) { | 342 bool ChannelNacl::WillDispatchInputMessage(Message* msg) { |
| 343 uint16 header_fds = msg->header()->num_fds; | 343 uint16 header_fds = msg->header()->num_fds; |
| 344 CHECK(header_fds == input_fds_.size()); | 344 CHECK(header_fds == input_fds_.size()); |
| 345 if (header_fds == 0) | 345 if (header_fds == 0) |
| 346 return true; // Nothing to do. | 346 return true; // Nothing to do. |
| 347 | 347 |
| 348 // The shenaniganery below with &foo.front() requires input_fds_ to have | 348 // The shenaniganery below with &foo.front() requires input_fds_ to have |
| 349 // contiguous underlying storage (such as a simple array or a std::vector). | 349 // contiguous underlying storage (such as a simple array or a std::vector). |
| 350 // This is why the header warns not to make input_fds_ a deque<>. | 350 // This is why the header warns not to make input_fds_ a deque<>. |
| 351 msg->file_descriptor_set()->SetDescriptors(&input_fds_.front(), | 351 msg->file_descriptor_set()->SetDescriptors(&input_fds_.front(), |
| 352 header_fds); | 352 header_fds); |
| 353 input_fds_.clear(); | 353 input_fds_.clear(); |
| 354 return true; | 354 return true; |
| 355 } | 355 } |
| 356 | 356 |
| 357 bool Channel::ChannelImpl::DidEmptyInputBuffers() { | 357 bool ChannelNacl::DidEmptyInputBuffers() { |
| 358 // When the input data buffer is empty, the fds should be too. | 358 // When the input data buffer is empty, the fds should be too. |
| 359 return input_fds_.empty(); | 359 return input_fds_.empty(); |
| 360 } | 360 } |
| 361 | 361 |
| 362 void Channel::ChannelImpl::HandleInternalMessage(const Message& msg) { | 362 void ChannelNacl::HandleInternalMessage(const Message& msg) { |
| 363 // The trusted side IPC::Channel should handle the "hello" handshake; we | 363 // The trusted side IPC::Channel should handle the "hello" handshake; we |
| 364 // should not receive the "Hello" message. | 364 // should not receive the "Hello" message. |
| 365 NOTREACHED(); | 365 NOTREACHED(); |
| 366 } | 366 } |
| 367 | 367 |
| 368 //------------------------------------------------------------------------------ | 368 // Channel's methods |
| 369 // Channel's methods simply call through to ChannelImpl. | |
| 370 | 369 |
| 371 Channel::Channel(const IPC::ChannelHandle& channel_handle, | 370 // static |
| 372 Mode mode, | 371 scoped_ptr<Channel> Channel::Create( |
| 373 Listener* listener) | 372 const IPC::ChannelHandle &channel_handle, Mode mode, Listener* listener) { |
| 374 : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) { | 373 return scoped_ptr<Channel>( |
| 375 } | 374 new ChannelNacl(channel_handle, mode, listener)); |
| 376 | |
| 377 Channel::~Channel() { | |
| 378 delete channel_impl_; | |
| 379 } | |
| 380 | |
| 381 bool Channel::Connect() { | |
| 382 return channel_impl_->Connect(); | |
| 383 } | |
| 384 | |
| 385 void Channel::Close() { | |
| 386 channel_impl_->Close(); | |
| 387 } | |
| 388 | |
| 389 base::ProcessId Channel::peer_pid() const { | |
| 390 return channel_impl_->peer_pid(); | |
| 391 } | |
| 392 | |
| 393 bool Channel::Send(Message* message) { | |
| 394 return channel_impl_->Send(message); | |
| 395 } | 375 } |
| 396 | 376 |
| 397 } // namespace IPC | 377 } // namespace IPC |
| OLD | NEW |