blob: e2ea1bfb1ee51394f9d40c7ed79ea93e062c5d63 [file] [log] [blame]
rsleevi@chromium.org997c1d42012-04-28 11:12:00 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
jabdelmalek@google.comeb921652010-04-07 05:33:36 +09002// 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
jhawkins@chromium.org9827bd12011-11-13 06:16:41 +09007#include "base/bind.h"
ajwong@chromium.org8e2e3002011-09-22 03:05:41 +09008#include "base/location.h"
jabdelmalek@google.comeb921652010-04-07 05:33:36 +09009#include "base/logging.h"
brettw@chromium.orgab2678f2013-06-11 05:56:28 +090010#include "base/message_loop/message_loop_proxy.h"
brettw@chromium.org5238c7d2011-01-02 15:05:39 +090011#include "base/synchronization/waitable_event.h"
dmichael@chromium.orgc0c370e2014-04-25 09:07:30 +090012#include "ipc/ipc_channel.h"
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090013#include "ipc/ipc_sync_message.h"
14
sievers@chromium.org7ac134c2011-09-16 18:38:38 +090015using base::MessageLoopProxy;
16
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090017namespace IPC {
18
19SyncMessageFilter::SyncMessageFilter(base::WaitableEvent* shutdown_event)
morrita@chromium.org631fb8e2014-06-13 15:07:14 +090020 : sender_(NULL),
sievers@chromium.org7ac134c2011-09-16 18:38:38 +090021 listener_loop_(MessageLoopProxy::current()),
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090022 shutdown_event_(shutdown_event) {
23}
24
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090025bool SyncMessageFilter::Send(Message* message) {
26 {
brettw@chromium.orgabe477a2011-01-21 13:55:52 +090027 base::AutoLock auto_lock(lock_);
rsleevi@chromium.org23b66232013-06-01 13:11:27 +090028 if (!io_loop_.get()) {
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090029 delete message;
30 return false;
31 }
32 }
33
34 if (!message->is_sync()) {
35 io_loop_->PostTask(
jhawkins@chromium.org9827bd12011-11-13 06:16:41 +090036 FROM_HERE, base::Bind(&SyncMessageFilter::SendOnIOThread, this, message));
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090037 return true;
38 }
39
40 base::WaitableEvent done_event(true, false);
41 PendingSyncMsg pending_message(
42 SyncMessage::GetMessageId(*message),
viettrungluu@chromium.orgc6d17972013-01-05 05:09:15 +090043 static_cast<SyncMessage*>(message)->GetReplyDeserializer(),
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090044 &done_event);
45
46 {
brettw@chromium.orgabe477a2011-01-21 13:55:52 +090047 base::AutoLock auto_lock(lock_);
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090048 // 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.
rsleevi@chromium.org64293f12013-06-12 01:46:36 +090050 DCHECK(MessageLoopProxy::current().get() != listener_loop_.get());
51 DCHECK(MessageLoopProxy::current().get() != io_loop_.get());
dumi@chromium.org229db062010-05-29 16:00:47 +090052 pending_sync_messages_.insert(&pending_message);
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090053 }
54
55 io_loop_->PostTask(
jhawkins@chromium.org9827bd12011-11-13 06:16:41 +090056 FROM_HERE, base::Bind(&SyncMessageFilter::SendOnIOThread, this, message));
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090057
58 base::WaitableEvent* events[2] = { shutdown_event_, &done_event };
59 base::WaitableEvent::WaitMany(events, 2);
60
61 {
brettw@chromium.orgabe477a2011-01-21 13:55:52 +090062 base::AutoLock auto_lock(lock_);
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090063 delete pending_message.deserializer;
dumi@chromium.org229db062010-05-29 16:00:47 +090064 pending_sync_messages_.erase(&pending_message);
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090065 }
66
67 return pending_message.send_result;
68}
69
morrita@chromium.org631fb8e2014-06-13 15:07:14 +090070void SyncMessageFilter::OnFilterAdded(Sender* sender) {
71 sender_ = sender;
brettw@chromium.orgabe477a2011-01-21 13:55:52 +090072 base::AutoLock auto_lock(lock_);
sievers@chromium.org7ac134c2011-09-16 18:38:38 +090073 io_loop_ = MessageLoopProxy::current();
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090074}
75
76void SyncMessageFilter::OnChannelError() {
morrita@chromium.org631fb8e2014-06-13 15:07:14 +090077 sender_ = NULL;
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090078 SignalAllEvents();
79}
80
81void SyncMessageFilter::OnChannelClosing() {
morrita@chromium.org631fb8e2014-06-13 15:07:14 +090082 sender_ = NULL;
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090083 SignalAllEvents();
84}
85
86bool SyncMessageFilter::OnMessageReceived(const Message& message) {
brettw@chromium.orgabe477a2011-01-21 13:55:52 +090087 base::AutoLock auto_lock(lock_);
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090088 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin();
89 iter != pending_sync_messages_.end(); ++iter) {
dumi@chromium.org229db062010-05-29 16:00:47 +090090 if (SyncMessage::IsMessageReplyTo(message, (*iter)->id)) {
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090091 if (!message.is_reply_error()) {
dumi@chromium.org229db062010-05-29 16:00:47 +090092 (*iter)->send_result =
93 (*iter)->deserializer->SerializeOutputParameters(message);
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090094 }
dumi@chromium.org229db062010-05-29 16:00:47 +090095 (*iter)->done_event->Signal();
jabdelmalek@google.comeb921652010-04-07 05:33:36 +090096 return true;
97 }
98 }
99
100 return false;
101}
102
rsleevi@chromium.org997c1d42012-04-28 11:12:00 +0900103SyncMessageFilter::~SyncMessageFilter() {
104}
105
106void SyncMessageFilter::SendOnIOThread(Message* message) {
morrita@chromium.org631fb8e2014-06-13 15:07:14 +0900107 if (sender_) {
108 sender_->Send(message);
rsleevi@chromium.org997c1d42012-04-28 11:12:00 +0900109 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
121void 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
jabdelmalek@google.comeb921652010-04-07 05:33:36 +0900129} // namespace IPC