OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/mojo/ipc_channel_mojo.h" | 5 #include "ipc/mojo/ipc_channel_mojo.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "ipc/ipc_listener.h" | 10 #include "ipc/ipc_listener.h" |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 void ChannelMojo::ChannelInfoDeleter::operator()( | 168 void ChannelMojo::ChannelInfoDeleter::operator()( |
169 mojo::embedder::ChannelInfo* ptr) const { | 169 mojo::embedder::ChannelInfo* ptr) const { |
170 mojo::embedder::DestroyChannel(ptr); | 170 mojo::embedder::DestroyChannel(ptr); |
171 } | 171 } |
172 | 172 |
173 //------------------------------------------------------------------------------ | 173 //------------------------------------------------------------------------------ |
174 | 174 |
175 // static | 175 // static |
176 bool ChannelMojo::ShouldBeUsed() { | 176 bool ChannelMojo::ShouldBeUsed() { |
177 // TODO(morrita): Turn this on for a set of platforms. | 177 // TODO(morrita): Turn this on for a set of platforms. |
178 return false; | 178 return true; |
Hajime Morrita
2014/12/05 02:54:09
I do this just for exercising tests. No intention
| |
179 } | 179 } |
180 | 180 |
181 // static | 181 // static |
182 scoped_ptr<ChannelMojo> ChannelMojo::Create(ChannelMojo::Delegate* delegate, | 182 scoped_ptr<ChannelMojo> ChannelMojo::Create(ChannelMojo::Delegate* delegate, |
183 const ChannelHandle& channel_handle, | 183 const ChannelHandle& channel_handle, |
184 Mode mode, | 184 Mode mode, |
185 Listener* listener) { | 185 Listener* listener) { |
186 switch (mode) { | 186 switch (mode) { |
187 case Channel::MODE_CLIENT: | 187 case Channel::MODE_CLIENT: |
188 return make_scoped_ptr( | 188 return make_scoped_ptr( |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 &ChannelMojo::InitDelegate, base::Unretained(this), delegate)); | 233 &ChannelMojo::InitDelegate, base::Unretained(this), delegate)); |
234 } | 234 } |
235 } | 235 } |
236 } | 236 } |
237 | 237 |
238 ChannelMojo::~ChannelMojo() { | 238 ChannelMojo::~ChannelMojo() { |
239 Close(); | 239 Close(); |
240 } | 240 } |
241 | 241 |
242 void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) { | 242 void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) { |
243 delegate->OnChannelCreated(weak_factory_.GetWeakPtr()); | |
244 base::AutoLock l(lock_); | |
243 delegate_ = delegate->ToWeakPtr(); | 245 delegate_ = delegate->ToWeakPtr(); |
244 delegate_->OnChannelCreated(weak_factory_.GetWeakPtr()); | |
245 } | 246 } |
246 | 247 |
247 mojo::ScopedMessagePipeHandle ChannelMojo::CreateMessagingPipe( | 248 mojo::ScopedMessagePipeHandle ChannelMojo::CreateMessagingPipe( |
248 mojo::embedder::ScopedPlatformHandle handle) { | 249 mojo::embedder::ScopedPlatformHandle handle) { |
249 DCHECK(!channel_info_.get()); | 250 DCHECK(!channel_info_.get()); |
250 mojo::embedder::ChannelInfo* channel_info; | 251 mojo::embedder::ChannelInfo* channel_info; |
251 mojo::ScopedMessagePipeHandle pipe = | 252 mojo::ScopedMessagePipeHandle pipe = |
252 mojo::embedder::CreateChannelOnIOThread(handle.Pass(), &channel_info); | 253 mojo::embedder::CreateChannelOnIOThread(handle.Pass(), &channel_info); |
253 channel_info_.reset(channel_info); | 254 channel_info_.reset(channel_info); |
254 return pipe.Pass(); | 255 return pipe.Pass(); |
255 } | 256 } |
256 | 257 |
257 bool ChannelMojo::Connect() { | 258 bool ChannelMojo::Connect() { |
258 DCHECK(!message_reader_); | 259 DCHECK(!message_reader_); |
259 return bootstrap_->Connect(); | 260 return bootstrap_->Connect(); |
260 } | 261 } |
261 | 262 |
262 void ChannelMojo::Close() { | 263 void ChannelMojo::Close() { |
263 message_reader_.reset(); | 264 // |message_reader_| has to be cleared inside the lock, |
265 // but the instance has to be deleted outside. | |
266 scoped_ptr<internal::MessagePipeReader, ReaderDeleter> to_be_dead; | |
267 | |
268 base::AutoLock l(lock_); | |
269 to_be_dead = message_reader_.Pass(); | |
264 channel_info_.reset(); | 270 channel_info_.reset(); |
265 } | 271 } |
266 | 272 |
267 void ChannelMojo::OnBootstrapError() { | 273 void ChannelMojo::OnBootstrapError() { |
268 listener_->OnChannelError(); | 274 listener_->OnChannelError(); |
269 } | 275 } |
270 | 276 |
271 void ChannelMojo::InitMessageReader(mojo::ScopedMessagePipeHandle pipe, | 277 void ChannelMojo::InitMessageReader(mojo::ScopedMessagePipeHandle pipe, |
272 int32_t peer_pid) { | 278 int32_t peer_pid) { |
273 message_reader_ = | 279 scoped_ptr<internal::MessagePipeReader> reader = |
274 make_scoped_ptr(new internal::MessagePipeReader(pipe.Pass(), this)); | 280 make_scoped_ptr(new internal::MessagePipeReader(pipe.Pass(), this)); |
281 MojoResult send_result = MOJO_RESULT_OK; | |
275 | 282 |
276 for (size_t i = 0; i < pending_messages_.size(); ++i) { | 283 { |
277 bool sent = message_reader_->Send(make_scoped_ptr(pending_messages_[i])); | 284 base::AutoLock l(lock_); |
278 pending_messages_[i] = NULL; | 285 ScopedVector<Message> pending; |
279 if (!sent) { | 286 |
280 pending_messages_.clear(); | 287 pending_messages_.swap(pending); |
281 listener_->OnChannelError(); | 288 for (size_t i = 0; i < pending.size(); ++i) { |
282 return; | 289 send_result = reader->Send(make_scoped_ptr(pending[i])); |
290 pending[i] = nullptr; | |
291 if (send_result != MOJO_RESULT_OK) | |
292 break; | |
283 } | 293 } |
294 | |
295 // We set |message_reader_| here and won't get any |pending_messages_| | |
296 // hereafter. Although we might have some if there is an error, we don't | |
297 // care. They cannot be sent anyway. | |
298 if (send_result == MOJO_RESULT_OK) | |
299 message_reader_ = reader.Pass(); | |
284 } | 300 } |
285 | 301 |
286 pending_messages_.clear(); | 302 // This should be done outside the |lock_| as delegates are called through |
303 // |CloseWithError()|. | |
304 if (reader.get()) { | |
305 DCHECK(!message_reader_.get()); | |
306 reader->CloseWithError(send_result); | |
307 return; | |
308 } | |
287 | 309 |
310 DCHECK(message_reader_.get()); | |
288 set_peer_pid(peer_pid); | 311 set_peer_pid(peer_pid); |
289 listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID())); | 312 listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID())); |
290 } | 313 } |
291 | 314 |
292 void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) { | 315 void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) { |
293 Close(); | 316 Close(); |
294 } | 317 } |
295 | 318 |
296 void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) { | 319 void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) { |
297 listener_->OnChannelError(); | 320 listener_->OnChannelError(); |
298 } | 321 } |
299 | 322 |
323 base::TaskRunner* ChannelMojo::GetIOTaskRunner() { | |
324 base::AutoLock l(lock_); | |
325 if (!delegate_) | |
326 return nullptr; | |
327 return delegate_->GetIOTaskRunner().get(); | |
328 } | |
300 | 329 |
330 // Reminder: Be thread-safe. | |
301 bool ChannelMojo::Send(Message* message) { | 331 bool ChannelMojo::Send(Message* message) { |
302 if (!message_reader_) { | 332 MojoResult send_result = MOJO_RESULT_OK; |
303 pending_messages_.push_back(message); | 333 |
304 return true; | 334 { |
335 base::AutoLock l(lock_); | |
336 | |
337 if (!message_reader_) { | |
338 pending_messages_.push_back(message); | |
339 return true; | |
340 } | |
341 | |
342 send_result = message_reader_->Send(make_scoped_ptr(message)); | |
305 } | 343 } |
306 | 344 |
307 return message_reader_->Send(make_scoped_ptr(message)); | 345 if (send_result != MOJO_RESULT_OK) { |
346 if (base::TaskRunner* runner = GetIOTaskRunner()) { | |
347 runner->PostTask( | |
348 FROM_HERE, | |
349 base::Bind(&internal::MessagePipeReader::CloseWithError, | |
350 base::Unretained(message_reader_.get()), send_result)); | |
351 // The error shouln't be visible at this point. | |
352 // It will be known eventually by |CloseWithError()| on IO thread. | |
353 return true; | |
354 } | |
355 | |
356 message_reader_->CloseWithError(send_result); | |
357 return false; | |
358 } | |
359 | |
360 return true; | |
361 } | |
362 | |
363 bool ChannelMojo::IsSendThreadSafe() const { | |
364 return true; | |
308 } | 365 } |
309 | 366 |
310 base::ProcessId ChannelMojo::GetPeerPID() const { | 367 base::ProcessId ChannelMojo::GetPeerPID() const { |
311 return peer_pid_; | 368 return peer_pid_; |
312 } | 369 } |
313 | 370 |
314 base::ProcessId ChannelMojo::GetSelfPID() const { | 371 base::ProcessId ChannelMojo::GetSelfPID() const { |
315 return base::GetCurrentProcId(); | 372 return base::GetCurrentProcId(); |
316 } | 373 } |
317 | 374 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 | 449 |
393 fdset->CommitAll(); | 450 fdset->CommitAll(); |
394 } | 451 } |
395 | 452 |
396 return MOJO_RESULT_OK; | 453 return MOJO_RESULT_OK; |
397 } | 454 } |
398 | 455 |
399 #endif // defined(OS_POSIX) && !defined(OS_NACL) | 456 #endif // defined(OS_POSIX) && !defined(OS_NACL) |
400 | 457 |
401 } // namespace IPC | 458 } // namespace IPC |
OLD | NEW |