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_proxy.h" | 5 #include "ipc/ipc_channel_proxy.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 //------------------------------------------------------------------------------ | 23 //------------------------------------------------------------------------------ |
24 | 24 |
25 ChannelProxy::Context::Context( | 25 ChannelProxy::Context::Context( |
26 Listener* listener, | 26 Listener* listener, |
27 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) | 27 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) |
28 : listener_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 28 : listener_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
29 listener_(listener), | 29 listener_(listener), |
30 ipc_task_runner_(ipc_task_runner), | 30 ipc_task_runner_(ipc_task_runner), |
31 channel_connected_called_(false), | 31 channel_connected_called_(false), |
32 message_filter_router_(new MessageFilterRouter()), | 32 message_filter_router_(new MessageFilterRouter()), |
| 33 channel_send_thread_safe_(false), |
33 peer_pid_(base::kNullProcessId) { | 34 peer_pid_(base::kNullProcessId) { |
34 DCHECK(ipc_task_runner_.get()); | 35 DCHECK(ipc_task_runner_.get()); |
35 // The Listener thread where Messages are handled must be a separate thread | 36 // The Listener thread where Messages are handled must be a separate thread |
36 // to avoid oversubscribing the IO thread. If you trigger this error, you | 37 // to avoid oversubscribing the IO thread. If you trigger this error, you |
37 // need to either: | 38 // need to either: |
38 // 1) Create the ChannelProxy on a different thread, or | 39 // 1) Create the ChannelProxy on a different thread, or |
39 // 2) Just use Channel | 40 // 2) Just use Channel |
40 // Note, we currently make an exception for a NULL listener. That usage | 41 // Note, we currently make an exception for a NULL listener. That usage |
41 // basically works, but is outside the intent of ChannelProxy. This support | 42 // basically works, but is outside the intent of ChannelProxy. This support |
42 // will disappear, so please don't rely on it. See crbug.com/364241 | 43 // will disappear, so please don't rely on it. See crbug.com/364241 |
43 DCHECK(!listener || (ipc_task_runner_.get() != listener_task_runner_.get())); | 44 DCHECK(!listener || (ipc_task_runner_.get() != listener_task_runner_.get())); |
44 } | 45 } |
45 | 46 |
46 ChannelProxy::Context::~Context() { | 47 ChannelProxy::Context::~Context() { |
47 } | 48 } |
48 | 49 |
49 void ChannelProxy::Context::ClearIPCTaskRunner() { | 50 void ChannelProxy::Context::ClearIPCTaskRunner() { |
50 ipc_task_runner_ = NULL; | 51 ipc_task_runner_ = NULL; |
51 } | 52 } |
52 | 53 |
53 void ChannelProxy::Context::CreateChannel(scoped_ptr<ChannelFactory> factory) { | 54 void ChannelProxy::Context::CreateChannel(scoped_ptr<ChannelFactory> factory) { |
54 DCHECK(!channel_); | 55 DCHECK(!channel_); |
55 channel_id_ = factory->GetName(); | 56 channel_id_ = factory->GetName(); |
56 channel_ = factory->BuildChannel(this); | 57 channel_ = factory->BuildChannel(this); |
| 58 channel_send_thread_safe_ = channel_->IsSendThreadSafe(); |
57 } | 59 } |
58 | 60 |
59 bool ChannelProxy::Context::TryFilters(const Message& message) { | 61 bool ChannelProxy::Context::TryFilters(const Message& message) { |
60 DCHECK(message_filter_router_); | 62 DCHECK(message_filter_router_); |
61 #ifdef IPC_MESSAGE_LOG_ENABLED | 63 #ifdef IPC_MESSAGE_LOG_ENABLED |
62 Logging* logger = Logging::GetInstance(); | 64 Logging* logger = Logging::GetInstance(); |
63 if (logger->Enabled()) | 65 if (logger->Enabled()) |
64 logger->OnPreDispatchMessage(message); | 66 logger->OnPreDispatchMessage(message); |
65 #endif | 67 #endif |
66 | 68 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 filters_[i]->OnFilterRemoved(); | 150 filters_[i]->OnFilterRemoved(); |
149 } | 151 } |
150 | 152 |
151 // We don't need the filters anymore. | 153 // We don't need the filters anymore. |
152 message_filter_router_->Clear(); | 154 message_filter_router_->Clear(); |
153 filters_.clear(); | 155 filters_.clear(); |
154 // We don't need the lock, because at this point, the listener thread can't | 156 // We don't need the lock, because at this point, the listener thread can't |
155 // access it any more. | 157 // access it any more. |
156 pending_filters_.clear(); | 158 pending_filters_.clear(); |
157 | 159 |
158 channel_.reset(); | 160 ClearChannel(); |
159 | 161 |
160 // Balance with the reference taken during startup. This may result in | 162 // Balance with the reference taken during startup. This may result in |
161 // self-destruction. | 163 // self-destruction. |
162 Release(); | 164 Release(); |
163 } | 165 } |
164 | 166 |
165 void ChannelProxy::Context::Clear() { | 167 void ChannelProxy::Context::Clear() { |
166 listener_ = NULL; | 168 listener_ = NULL; |
167 } | 169 } |
168 | 170 |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 if (listener_) | 298 if (listener_) |
297 listener_->OnChannelError(); | 299 listener_->OnChannelError(); |
298 } | 300 } |
299 | 301 |
300 // Called on the listener's thread | 302 // Called on the listener's thread |
301 void ChannelProxy::Context::OnDispatchBadMessage(const Message& message) { | 303 void ChannelProxy::Context::OnDispatchBadMessage(const Message& message) { |
302 if (listener_) | 304 if (listener_) |
303 listener_->OnBadMessageReceived(message); | 305 listener_->OnBadMessageReceived(message); |
304 } | 306 } |
305 | 307 |
| 308 void ChannelProxy::Context::ClearChannel() { |
| 309 base::AutoLock l(channel_lifetime_lock_); |
| 310 channel_.reset(); |
| 311 } |
| 312 |
| 313 void ChannelProxy::Context::SendFromThisThread(Message* message) { |
| 314 base::AutoLock l(channel_lifetime_lock_); |
| 315 if (!channel_) |
| 316 return; |
| 317 DCHECK(channel_->IsSendThreadSafe()); |
| 318 channel_->Send(message); |
| 319 } |
| 320 |
| 321 void ChannelProxy::Context::Send(Message* message) { |
| 322 if (channel_send_thread_safe_) { |
| 323 SendFromThisThread(message); |
| 324 return; |
| 325 } |
| 326 |
| 327 ipc_task_runner()->PostTask( |
| 328 FROM_HERE, base::Bind(&ChannelProxy::Context::OnSendMessage, this, |
| 329 base::Passed(scoped_ptr<Message>(message)))); |
| 330 } |
| 331 |
306 //----------------------------------------------------------------------------- | 332 //----------------------------------------------------------------------------- |
307 | 333 |
308 // static | 334 // static |
309 scoped_ptr<ChannelProxy> ChannelProxy::Create( | 335 scoped_ptr<ChannelProxy> ChannelProxy::Create( |
310 const IPC::ChannelHandle& channel_handle, | 336 const IPC::ChannelHandle& channel_handle, |
311 Channel::Mode mode, | 337 Channel::Mode mode, |
312 Listener* listener, | 338 Listener* listener, |
313 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) { | 339 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) { |
314 scoped_ptr<ChannelProxy> channel(new ChannelProxy(listener, ipc_task_runner)); | 340 scoped_ptr<ChannelProxy> channel(new ChannelProxy(listener, ipc_task_runner)); |
315 channel->Init(channel_handle, mode, true); | 341 channel->Init(channel_handle, mode, true); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 bool ChannelProxy::Send(Message* message) { | 426 bool ChannelProxy::Send(Message* message) { |
401 DCHECK(did_init_); | 427 DCHECK(did_init_); |
402 | 428 |
403 // TODO(alexeypa): add DCHECK(CalledOnValidThread()) here. Currently there are | 429 // TODO(alexeypa): add DCHECK(CalledOnValidThread()) here. Currently there are |
404 // tests that call Send() from a wrong thread. See http://crbug.com/163523. | 430 // tests that call Send() from a wrong thread. See http://crbug.com/163523. |
405 | 431 |
406 #ifdef IPC_MESSAGE_LOG_ENABLED | 432 #ifdef IPC_MESSAGE_LOG_ENABLED |
407 Logging::GetInstance()->OnSendMessage(message, context_->channel_id()); | 433 Logging::GetInstance()->OnSendMessage(message, context_->channel_id()); |
408 #endif | 434 #endif |
409 | 435 |
410 context_->ipc_task_runner()->PostTask( | 436 context_->Send(message); |
411 FROM_HERE, | |
412 base::Bind(&ChannelProxy::Context::OnSendMessage, | |
413 context_, base::Passed(scoped_ptr<Message>(message)))); | |
414 return true; | 437 return true; |
415 } | 438 } |
416 | 439 |
417 void ChannelProxy::AddFilter(MessageFilter* filter) { | 440 void ChannelProxy::AddFilter(MessageFilter* filter) { |
418 DCHECK(CalledOnValidThread()); | 441 DCHECK(CalledOnValidThread()); |
419 | 442 |
420 context_->AddFilter(filter); | 443 context_->AddFilter(filter); |
421 } | 444 } |
422 | 445 |
423 void ChannelProxy::RemoveFilter(MessageFilter* filter) { | 446 void ChannelProxy::RemoveFilter(MessageFilter* filter) { |
(...skipping 28 matching lines...) Expand all Loading... |
452 Channel* channel = context_.get()->channel_.get(); | 475 Channel* channel = context_.get()->channel_.get(); |
453 // Channel must have been created first. | 476 // Channel must have been created first. |
454 DCHECK(channel) << context_.get()->channel_id_; | 477 DCHECK(channel) << context_.get()->channel_id_; |
455 return channel->TakeClientFileDescriptor(); | 478 return channel->TakeClientFileDescriptor(); |
456 } | 479 } |
457 #endif | 480 #endif |
458 | 481 |
459 //----------------------------------------------------------------------------- | 482 //----------------------------------------------------------------------------- |
460 | 483 |
461 } // namespace IPC | 484 } // namespace IPC |
OLD | NEW |