15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_message_filter.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ipc/ipc_channel.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_message.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::MessageLoopProxy;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace IPC {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncMessageFilter::SyncMessageFilter(base::WaitableEvent* shutdown_event)
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : sender_(NULL),
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      listener_loop_(MessageLoopProxy::current()),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shutdown_event_(shutdown_event) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncMessageFilter::Send(Message* message) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!io_loop_.get()) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete message;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!message->is_sync()) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_loop_->PostTask(
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&SyncMessageFilter::SendOnIOThread, this, message));
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent done_event(true, false);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingSyncMsg pending_message(
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SyncMessage::GetMessageId(*message),
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SyncMessage*>(message)->GetReplyDeserializer(),
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &done_event);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Can't use this class on the main thread or else it can lead to deadlocks.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Also by definition, can't use this on IO thread since we're blocking it.
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DCHECK(MessageLoopProxy::current().get() != listener_loop_.get());
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DCHECK(MessageLoopProxy::current().get() != io_loop_.get());
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_sync_messages_.insert(&pending_message);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_loop_->PostTask(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&SyncMessageFilter::SendOnIOThread, this, message));
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent* events[2] = { shutdown_event_, &done_event };
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent::WaitMany(events, 2);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete pending_message.deserializer;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_sync_messages_.erase(&pending_message);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pending_message.send_result;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SyncMessageFilter::OnFilterAdded(Sender* sender) {
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  sender_ = sender;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_loop_ = MessageLoopProxy::current();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncMessageFilter::OnChannelError() {
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  sender_ = NULL;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignalAllEvents();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncMessageFilter::OnChannelClosing() {
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  sender_ = NULL;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignalAllEvents();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncMessageFilter::OnMessageReceived(const Message& message) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != pending_sync_messages_.end(); ++iter) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SyncMessage::IsMessageReplyTo(message, (*iter)->id)) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!message.is_reply_error()) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*iter)->send_result =
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (*iter)->deserializer->SerializeOutputParameters(message);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*iter)->done_event->Signal();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncMessageFilter::~SyncMessageFilter() {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncMessageFilter::SendOnIOThread(Message* message) {
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (sender_) {
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    sender_->Send(message);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message->is_sync()) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't know which thread sent it, but it doesn't matter, just signal
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // them all.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SignalAllEvents();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete message;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncMessageFilter::SignalAllEvents() {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != pending_sync_messages_.end(); ++iter) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*iter)->done_event->Signal();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace IPC
130