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 3 // found in the LICENSE file. 4 5 #include "ipc/ipc_sync_message_filter.h" 6 7 #include "base/bind.h" 8 #include "base/location.h" 9 #include "base/logging.h" 10 #include "base/message_loop/message_loop_proxy.h" 11 #include "base/synchronization/waitable_event.h" 12 #include "ipc/ipc_channel.h" 13 #include "ipc/ipc_sync_message.h" 14 15 using base::MessageLoopProxy; 16 17 namespace IPC { 18 19 SyncMessageFilter::SyncMessageFilter(base::WaitableEvent* shutdown_event) 20 : sender_(NULL), 21 listener_loop_(MessageLoopProxy::current()), 22 shutdown_event_(shutdown_event) { 23 } 24 25 bool SyncMessageFilter::Send(Message* message) { 26 { 27 base::AutoLock auto_lock(lock_); 28 if (!io_loop_.get()) { 29 delete message; 30 return false; 31 } 32 } 33 34 if (!message->is_sync()) { 35 io_loop_->PostTask( 36 FROM_HERE, base::Bind(&SyncMessageFilter::SendOnIOThread, this, message)); 37 return true; 38 } 39 40 base::WaitableEvent done_event(true, false); 41 PendingSyncMsg pending_message( 42 SyncMessage::GetMessageId(*message), 43 static_cast<SyncMessage*>(message)->GetReplyDeserializer(), 44 &done_event); 45 46 { 47 base::AutoLock auto_lock(lock_); 48 // Can't use this class on the main thread or else it can lead to deadlocks. 49 // Also by definition, can't use this on IO thread since we're blocking it. 50 DCHECK(MessageLoopProxy::current().get() != listener_loop_.get()); 51 DCHECK(MessageLoopProxy::current().get() != io_loop_.get()); 52 pending_sync_messages_.insert(&pending_message); 53 } 54 55 io_loop_->PostTask( 56 FROM_HERE, base::Bind(&SyncMessageFilter::SendOnIOThread, this, message)); 57 58 base::WaitableEvent* events[2] = { shutdown_event_, &done_event }; 59 base::WaitableEvent::WaitMany(events, 2); 60 61 { 62 base::AutoLock auto_lock(lock_); 63 delete pending_message.deserializer; 64 pending_sync_messages_.erase(&pending_message); 65 } 66 67 return pending_message.send_result; 68 } 69 70 void SyncMessageFilter::OnFilterAdded(Sender* sender) { 71 sender_ = sender; 72 base::AutoLock auto_lock(lock_); 73 io_loop_ = MessageLoopProxy::current(); 74 } 75 76 void SyncMessageFilter::OnChannelError() { 77 sender_ = NULL; 78 SignalAllEvents(); 79 } 80 81 void SyncMessageFilter::OnChannelClosing() { 82 sender_ = NULL; 83 SignalAllEvents(); 84 } 85 86 bool SyncMessageFilter::OnMessageReceived(const Message& message) { 87 base::AutoLock auto_lock(lock_); 88 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin(); 89 iter != pending_sync_messages_.end(); ++iter) { 90 if (SyncMessage::IsMessageReplyTo(message, (*iter)->id)) { 91 if (!message.is_reply_error()) { 92 (*iter)->send_result = 93 (*iter)->deserializer->SerializeOutputParameters(message); 94 } 95 (*iter)->done_event->Signal(); 96 return true; 97 } 98 } 99 100 return false; 101 } 102 103 SyncMessageFilter::~SyncMessageFilter() { 104 } 105 106 void SyncMessageFilter::SendOnIOThread(Message* message) { 107 if (sender_) { 108 sender_->Send(message); 109 return; 110 } 111 112 if (message->is_sync()) { 113 // We don't know which thread sent it, but it doesn't matter, just signal 114 // them all. 115 SignalAllEvents(); 116 } 117 118 delete message; 119 } 120 121 void SyncMessageFilter::SignalAllEvents() { 122 base::AutoLock auto_lock(lock_); 123 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin(); 124 iter != pending_sync_messages_.end(); ++iter) { 125 (*iter)->done_event->Signal(); 126 } 127 } 128 129 } // namespace IPC 130