blob: f74dc83a4133b926c4aa67ddd04d1442dd2db6da [file] [log] [blame]
jschuh@chromium.orga5cd0762012-04-05 11:38:34 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
agl@chromium.org1c6dcf22009-07-23 08:57:21 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
dmichael@chromium.orgc0c370e2014-04-25 09:07:30 +09005#include "ipc/ipc_channel_proxy.h"
6
jhawkins@chromium.org9827bd12011-11-13 06:16:41 +09007#include "base/bind.h"
jhawkins@chromium.orge34d0ad2011-11-29 11:24:28 +09008#include "base/compiler_specific.h"
ajwong@chromium.org8e2e3002011-09-22 03:05:41 +09009#include "base/location.h"
levin@chromium.org5c528682011-03-28 10:54:15 +090010#include "base/memory/ref_counted.h"
11#include "base/memory/scoped_ptr.h"
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +090012#include "base/single_thread_task_runner.h"
13#include "base/thread_task_runner_handle.h"
morrita@chromium.org15996aa2014-08-05 08:44:17 +090014#include "ipc/ipc_channel_factory.h"
brettw@chromium.orgf947ed02012-06-12 07:35:26 +090015#include "ipc/ipc_listener.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090016#include "ipc/ipc_logging.h"
piman@chromium.org24b15ad2012-05-12 08:24:37 +090017#include "ipc/ipc_message_macros.h"
dmichael@chromium.orgc0c370e2014-04-25 09:07:30 +090018#include "ipc/message_filter.h"
19#include "ipc/message_filter_router.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090020
21namespace IPC {
22
jcampan@chromium.org1c86b552009-07-29 07:09:45 +090023//------------------------------------------------------------------------------
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090024
dchengea780ac2014-08-29 01:59:29 +090025ChannelProxy::Context::Context(
26 Listener* listener,
27 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner)
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +090028 : listener_task_runner_(base::ThreadTaskRunnerHandle::Get()),
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090029 listener_(listener),
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +090030 ipc_task_runner_(ipc_task_runner),
jschuh@chromium.orga5cd0762012-04-05 11:38:34 +090031 channel_connected_called_(false),
jdduke@chromium.org03f232f2014-02-26 14:18:04 +090032 message_filter_router_(new MessageFilterRouter()),
jschuh@chromium.orga5cd0762012-04-05 11:38:34 +090033 peer_pid_(base::kNullProcessId) {
rsleevi@chromium.org23b66232013-06-01 13:11:27 +090034 DCHECK(ipc_task_runner_.get());
dmichael@chromium.org1446d8a2014-04-17 14:07:18 +090035 // 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 // need to either:
38 // 1) Create the ChannelProxy on a different thread, or
39 // 2) Just use Channel
40 // 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 // will disappear, so please don't rely on it. See crbug.com/364241
43 DCHECK(!listener || (ipc_task_runner_.get() != listener_task_runner_.get()));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090044}
45
jam@chromium.org06d18442011-05-03 03:00:49 +090046ChannelProxy::Context::~Context() {
47}
48
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +090049void ChannelProxy::Context::ClearIPCTaskRunner() {
50 ipc_task_runner_ = NULL;
51}
52
morrita@chromium.org15996aa2014-08-05 08:44:17 +090053void ChannelProxy::Context::CreateChannel(scoped_ptr<ChannelFactory> factory) {
dmichael@chromium.org31a16812014-03-21 06:00:50 +090054 DCHECK(!channel_);
morrita@chromium.org15996aa2014-08-05 08:44:17 +090055 channel_id_ = factory->GetName();
56 channel_ = factory->BuildChannel(this);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090057}
58
59bool ChannelProxy::Context::TryFilters(const Message& message) {
jdduke@chromium.org03f232f2014-02-26 14:18:04 +090060 DCHECK(message_filter_router_);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090061#ifdef IPC_MESSAGE_LOG_ENABLED
satish@chromium.orgaa870602010-12-13 17:18:55 +090062 Logging* logger = Logging::GetInstance();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090063 if (logger->Enabled())
64 logger->OnPreDispatchMessage(message);
65#endif
66
jdduke@chromium.org03f232f2014-02-26 14:18:04 +090067 if (message_filter_router_->TryFilters(message)) {
jam@chromium.org822f1fb2014-05-16 08:06:07 +090068 if (message.dispatch_error()) {
69 listener_task_runner_->PostTask(
70 FROM_HERE, base::Bind(&Context::OnDispatchBadMessage, this, message));
71 }
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090072#ifdef IPC_MESSAGE_LOG_ENABLED
jdduke@chromium.org03f232f2014-02-26 14:18:04 +090073 if (logger->Enabled())
74 logger->OnPostDispatchMessage(message, channel_id_);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090075#endif
jdduke@chromium.org03f232f2014-02-26 14:18:04 +090076 return true;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090077 }
78 return false;
79}
80
81// Called on the IPC::Channel thread
jam@chromium.org8a2c7842010-12-24 15:19:28 +090082bool ChannelProxy::Context::OnMessageReceived(const Message& message) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090083 // First give a chance to the filters to process this message.
84 if (!TryFilters(message))
85 OnMessageReceivedNoFilter(message);
jam@chromium.org8a2c7842010-12-24 15:19:28 +090086 return true;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090087}
88
89// Called on the IPC::Channel thread
jam@chromium.org8a2c7842010-12-24 15:19:28 +090090bool ChannelProxy::Context::OnMessageReceivedNoFilter(const Message& message) {
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +090091 listener_task_runner_->PostTask(
jhawkins@chromium.org9827bd12011-11-13 06:16:41 +090092 FROM_HERE, base::Bind(&Context::OnDispatchMessage, this, message));
jam@chromium.org8a2c7842010-12-24 15:19:28 +090093 return true;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090094}
95
96// Called on the IPC::Channel thread
97void ChannelProxy::Context::OnChannelConnected(int32 peer_pid) {
dmichael@chromium.org31a16812014-03-21 06:00:50 +090098 // We cache off the peer_pid so it can be safely accessed from both threads.
morrita@chromium.orgfde2b6b2014-06-07 05:13:51 +090099 peer_pid_ = channel_->GetPeerPID();
dmichael@chromium.org31a16812014-03-21 06:00:50 +0900100
jam@chromium.orge57135c2010-12-03 04:16:07 +0900101 // Add any pending filters. This avoids a race condition where someone
102 // creates a ChannelProxy, calls AddFilter, and then right after starts the
103 // peer process. The IO thread could receive a message before the task to add
104 // the filter is run on the IO thread.
105 OnAddFilter();
106
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +0900107 // See above comment about using listener_task_runner_ here.
108 listener_task_runner_->PostTask(
jhawkins@chromium.org9827bd12011-11-13 06:16:41 +0900109 FROM_HERE, base::Bind(&Context::OnDispatchConnected, this));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900110}
111
112// Called on the IPC::Channel thread
113void ChannelProxy::Context::OnChannelError() {
114 for (size_t i = 0; i < filters_.size(); ++i)
115 filters_[i]->OnChannelError();
116
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +0900117 // See above comment about using listener_task_runner_ here.
118 listener_task_runner_->PostTask(
jhawkins@chromium.org9827bd12011-11-13 06:16:41 +0900119 FROM_HERE, base::Bind(&Context::OnDispatchError, this));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900120}
121
122// Called on the IPC::Channel thread
123void ChannelProxy::Context::OnChannelOpened() {
124 DCHECK(channel_ != NULL);
125
126 // Assume a reference to ourselves on behalf of this thread. This reference
127 // will be released when we are closed.
128 AddRef();
129
130 if (!channel_->Connect()) {
131 OnChannelError();
132 return;
133 }
134
135 for (size_t i = 0; i < filters_.size(); ++i)
dmaclach@chromium.org058c4a72010-12-09 04:28:09 +0900136 filters_[i]->OnFilterAdded(channel_.get());
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900137}
138
139// Called on the IPC::Channel thread
140void ChannelProxy::Context::OnChannelClosed() {
141 // It's okay for IPC::ChannelProxy::Close to be called more than once, which
142 // would result in this branch being taken.
dmichael@chromium.org31a16812014-03-21 06:00:50 +0900143 if (!channel_)
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900144 return;
145
146 for (size_t i = 0; i < filters_.size(); ++i) {
147 filters_[i]->OnChannelClosing();
148 filters_[i]->OnFilterRemoved();
149 }
150
151 // We don't need the filters anymore.
jdduke@chromium.org03f232f2014-02-26 14:18:04 +0900152 message_filter_router_->Clear();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900153 filters_.clear();
dmichael@chromium.org31a16812014-03-21 06:00:50 +0900154 // We don't need the lock, because at this point, the listener thread can't
155 // access it any more.
156 pending_filters_.clear();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900157
dmaclach@chromium.org058c4a72010-12-09 04:28:09 +0900158 channel_.reset();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900159
160 // Balance with the reference taken during startup. This may result in
161 // self-destruction.
162 Release();
163}
164
hans@chromium.orge62750c2012-08-10 05:39:12 +0900165void ChannelProxy::Context::Clear() {
166 listener_ = NULL;
167}
168
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900169// Called on the IPC::Channel thread
rsleevi@chromium.org997c1d42012-04-28 11:12:00 +0900170void ChannelProxy::Context::OnSendMessage(scoped_ptr<Message> message) {
dmichael@chromium.org31a16812014-03-21 06:00:50 +0900171 if (!channel_) {
ananta@chromium.org999f2972010-09-03 06:45:50 +0900172 OnChannelClosed();
173 return;
174 }
dmichael@chromium.org31a16812014-03-21 06:00:50 +0900175
rsleevi@chromium.org997c1d42012-04-28 11:12:00 +0900176 if (!channel_->Send(message.release()))
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900177 OnChannelError();
178}
179
180// Called on the IPC::Channel thread
jam@chromium.orge57135c2010-12-03 04:16:07 +0900181void ChannelProxy::Context::OnAddFilter() {
dmichael@chromium.org31a16812014-03-21 06:00:50 +0900182 // Our OnChannelConnected method has not yet been called, so we can't be
183 // sure that channel_ is valid yet. When OnChannelConnected *is* called,
184 // it invokes OnAddFilter, so any pending filter(s) will be added at that
185 // time.
186 if (peer_pid_ == base::kNullProcessId)
187 return;
188
evan@chromium.orgaa538712011-08-17 07:12:39 +0900189 std::vector<scoped_refptr<MessageFilter> > new_filters;
jam@chromium.orge57135c2010-12-03 04:16:07 +0900190 {
brettw@chromium.orgabe477a2011-01-21 13:55:52 +0900191 base::AutoLock auto_lock(pending_filters_lock_);
evan@chromium.orgaa538712011-08-17 07:12:39 +0900192 new_filters.swap(pending_filters_);
jam@chromium.orge57135c2010-12-03 04:16:07 +0900193 }
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900194
evan@chromium.orgaa538712011-08-17 07:12:39 +0900195 for (size_t i = 0; i < new_filters.size(); ++i) {
196 filters_.push_back(new_filters[i]);
jam@chromium.orge57135c2010-12-03 04:16:07 +0900197
jdduke@chromium.org03f232f2014-02-26 14:18:04 +0900198 message_filter_router_->AddFilter(new_filters[i].get());
199
dmichael@chromium.org31a16812014-03-21 06:00:50 +0900200 // The channel has already been created and connected, so we need to
201 // inform the filters right now.
202 new_filters[i]->OnFilterAdded(channel_.get());
203 new_filters[i]->OnChannelConnected(peer_pid_);
jam@chromium.orge57135c2010-12-03 04:16:07 +0900204 }
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900205}
206
207// Called on the IPC::Channel thread
208void ChannelProxy::Context::OnRemoveFilter(MessageFilter* filter) {
dmichael@chromium.org31a16812014-03-21 06:00:50 +0900209 if (peer_pid_ == base::kNullProcessId) {
210 // The channel is not yet connected, so any filters are still pending.
211 base::AutoLock auto_lock(pending_filters_lock_);
212 for (size_t i = 0; i < pending_filters_.size(); ++i) {
213 if (pending_filters_[i].get() == filter) {
214 filter->OnFilterRemoved();
215 pending_filters_.erase(pending_filters_.begin() + i);
216 return;
217 }
218 }
219 return;
220 }
221 if (!channel_)
jam@chromium.orgca4f6e22013-07-10 06:12:07 +0900222 return; // The filters have already been deleted.
223
jdduke@chromium.org03f232f2014-02-26 14:18:04 +0900224 message_filter_router_->RemoveFilter(filter);
225
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900226 for (size_t i = 0; i < filters_.size(); ++i) {
227 if (filters_[i].get() == filter) {
228 filter->OnFilterRemoved();
229 filters_.erase(filters_.begin() + i);
230 return;
231 }
232 }
233
234 NOTREACHED() << "filter to be removed not found";
235}
236
237// Called on the listener's thread
jam@chromium.orge57135c2010-12-03 04:16:07 +0900238void ChannelProxy::Context::AddFilter(MessageFilter* filter) {
brettw@chromium.orgabe477a2011-01-21 13:55:52 +0900239 base::AutoLock auto_lock(pending_filters_lock_);
jam@chromium.orge57135c2010-12-03 04:16:07 +0900240 pending_filters_.push_back(make_scoped_refptr(filter));
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +0900241 ipc_task_runner_->PostTask(
jhawkins@chromium.org9827bd12011-11-13 06:16:41 +0900242 FROM_HERE, base::Bind(&Context::OnAddFilter, this));
jam@chromium.orge57135c2010-12-03 04:16:07 +0900243}
244
245// Called on the listener's thread
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900246void ChannelProxy::Context::OnDispatchMessage(const Message& message) {
rbyers@chromium.org8255d6c2012-02-15 05:08:09 +0900247#ifdef IPC_MESSAGE_LOG_ENABLED
248 Logging* logger = Logging::GetInstance();
249 std::string name;
250 logger->GetMessageText(message.type(), &name, &message, NULL);
epenner@chromium.org24f2bea2014-05-03 06:29:24 +0900251 TRACE_EVENT1("ipc", "ChannelProxy::Context::OnDispatchMessage",
rbyers@chromium.org8255d6c2012-02-15 05:08:09 +0900252 "name", name);
253#else
epenner@chromium.org24f2bea2014-05-03 06:29:24 +0900254 TRACE_EVENT2("ipc", "ChannelProxy::Context::OnDispatchMessage",
piman@chromium.org24b15ad2012-05-12 08:24:37 +0900255 "class", IPC_MESSAGE_ID_CLASS(message.type()),
256 "line", IPC_MESSAGE_ID_LINE(message.type()));
rbyers@chromium.org8255d6c2012-02-15 05:08:09 +0900257#endif
258
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900259 if (!listener_)
260 return;
261
262 OnDispatchConnected();
263
264#ifdef IPC_MESSAGE_LOG_ENABLED
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900265 if (message.type() == IPC_LOGGING_ID) {
266 logger->OnReceivedLoggingMessage(message);
267 return;
268 }
269
270 if (logger->Enabled())
271 logger->OnPreDispatchMessage(message);
272#endif
273
274 listener_->OnMessageReceived(message);
jam@chromium.org822f1fb2014-05-16 08:06:07 +0900275 if (message.dispatch_error())
276 listener_->OnBadMessageReceived(message);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900277
278#ifdef IPC_MESSAGE_LOG_ENABLED
279 if (logger->Enabled())
280 logger->OnPostDispatchMessage(message, channel_id_);
281#endif
282}
283
284// Called on the listener's thread
285void ChannelProxy::Context::OnDispatchConnected() {
286 if (channel_connected_called_)
287 return;
288
289 channel_connected_called_ = true;
290 if (listener_)
291 listener_->OnChannelConnected(peer_pid_);
292}
293
294// Called on the listener's thread
295void ChannelProxy::Context::OnDispatchError() {
296 if (listener_)
297 listener_->OnChannelError();
298}
299
jam@chromium.org822f1fb2014-05-16 08:06:07 +0900300// Called on the listener's thread
301void ChannelProxy::Context::OnDispatchBadMessage(const Message& message) {
302 if (listener_)
303 listener_->OnBadMessageReceived(message);
304}
305
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900306//-----------------------------------------------------------------------------
307
morrita@chromium.org15b48602014-06-06 01:15:38 +0900308// static
309scoped_ptr<ChannelProxy> ChannelProxy::Create(
310 const IPC::ChannelHandle& channel_handle,
311 Channel::Mode mode,
312 Listener* listener,
dchengea780ac2014-08-29 01:59:29 +0900313 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
morrita@chromium.org15b48602014-06-06 01:15:38 +0900314 scoped_ptr<ChannelProxy> channel(new ChannelProxy(listener, ipc_task_runner));
315 channel->Init(channel_handle, mode, true);
316 return channel.Pass();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900317}
318
morrita@chromium.org15996aa2014-08-05 08:44:17 +0900319// static
320scoped_ptr<ChannelProxy> ChannelProxy::Create(
321 scoped_ptr<ChannelFactory> factory,
322 Listener* listener,
dchengea780ac2014-08-29 01:59:29 +0900323 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
morrita@chromium.org15996aa2014-08-05 08:44:17 +0900324 scoped_ptr<ChannelProxy> channel(new ChannelProxy(listener, ipc_task_runner));
325 channel->Init(factory.Pass(), true);
326 return channel.Pass();
327}
328
kkania@chromium.org9ccb4692011-11-16 10:06:46 +0900329ChannelProxy::ChannelProxy(Context* context)
tsepez@chromium.orge68ddef2011-05-05 02:14:16 +0900330 : context_(context),
kkania@chromium.org9ccb4692011-11-16 10:06:46 +0900331 did_init_(false) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900332}
333
dchengea780ac2014-08-29 01:59:29 +0900334ChannelProxy::ChannelProxy(
335 Listener* listener,
336 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner)
morrita@chromium.org15b48602014-06-06 01:15:38 +0900337 : context_(new Context(listener, ipc_task_runner)), did_init_(false) {
338}
339
erg@google.com2ec53b42010-09-24 07:43:53 +0900340ChannelProxy::~ChannelProxy() {
alexeypa@chromium.org0192ff02012-12-05 10:00:36 +0900341 DCHECK(CalledOnValidThread());
342
erg@google.com2ec53b42010-09-24 07:43:53 +0900343 Close();
344}
345
lambroslambrou@chromium.org773476a2014-06-03 05:29:30 +0900346void ChannelProxy::Init(const IPC::ChannelHandle& channel_handle,
347 Channel::Mode mode,
348 bool create_pipe_now) {
dmaclach@chromium.org058c4a72010-12-09 04:28:09 +0900349#if defined(OS_POSIX)
350 // When we are creating a server on POSIX, we need its file descriptor
351 // to be created immediately so that it can be accessed and passed
352 // to other processes. Forcing it to be created immediately avoids
353 // race conditions that may otherwise arise.
dmaclach@chromium.orgf146c292011-02-04 05:35:09 +0900354 if (mode & Channel::MODE_SERVER_FLAG) {
dmaclach@chromium.org058c4a72010-12-09 04:28:09 +0900355 create_pipe_now = true;
356 }
357#endif // defined(OS_POSIX)
morrita@chromium.org15996aa2014-08-05 08:44:17 +0900358 Init(ChannelFactory::Create(channel_handle, mode),
359 create_pipe_now);
360}
361
362void ChannelProxy::Init(scoped_ptr<ChannelFactory> factory,
363 bool create_pipe_now) {
364 DCHECK(CalledOnValidThread());
365 DCHECK(!did_init_);
dmaclach@chromium.org058c4a72010-12-09 04:28:09 +0900366
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900367 if (create_pipe_now) {
368 // Create the channel immediately. This effectively sets up the
369 // low-level pipe so that the client can connect. Without creating
370 // the pipe immediately, it is possible for a listener to attempt
371 // to connect and get an error since the pipe doesn't exist yet.
morrita@chromium.org15996aa2014-08-05 08:44:17 +0900372 context_->CreateChannel(factory.Pass());
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900373 } else {
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +0900374 context_->ipc_task_runner()->PostTask(
morrita@chromium.org15996aa2014-08-05 08:44:17 +0900375 FROM_HERE, base::Bind(&Context::CreateChannel,
376 context_.get(), Passed(factory.Pass())));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900377 }
378
379 // complete initialization on the background thread
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +0900380 context_->ipc_task_runner()->PostTask(
jhawkins@chromium.org9827bd12011-11-13 06:16:41 +0900381 FROM_HERE, base::Bind(&Context::OnChannelOpened, context_.get()));
kkania@chromium.org9ccb4692011-11-16 10:06:46 +0900382
383 did_init_ = true;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900384}
385
386void ChannelProxy::Close() {
alexeypa@chromium.org0192ff02012-12-05 10:00:36 +0900387 DCHECK(CalledOnValidThread());
388
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900389 // Clear the backpointer to the listener so that any pending calls to
390 // Context::OnDispatchMessage or OnDispatchError will be ignored. It is
391 // possible that the channel could be closed while it is receiving messages!
392 context_->Clear();
393
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +0900394 if (context_->ipc_task_runner()) {
395 context_->ipc_task_runner()->PostTask(
jhawkins@chromium.org9827bd12011-11-13 06:16:41 +0900396 FROM_HERE, base::Bind(&Context::OnChannelClosed, context_.get()));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900397 }
398}
399
400bool ChannelProxy::Send(Message* message) {
kkania@chromium.org9ccb4692011-11-16 10:06:46 +0900401 DCHECK(did_init_);
alexeypa@chromium.org0192ff02012-12-05 10:00:36 +0900402
403 // TODO(alexeypa): add DCHECK(CalledOnValidThread()) here. Currently there are
404 // tests that call Send() from a wrong thread. See http://crbug.com/163523.
tsepez@chromium.orge68ddef2011-05-05 02:14:16 +0900405
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900406#ifdef IPC_MESSAGE_LOG_ENABLED
satish@chromium.orgaa870602010-12-13 17:18:55 +0900407 Logging::GetInstance()->OnSendMessage(message, context_->channel_id());
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900408#endif
409
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +0900410 context_->ipc_task_runner()->PostTask(
jhawkins@chromium.orge34d0ad2011-11-29 11:24:28 +0900411 FROM_HERE,
rsleevi@chromium.org997c1d42012-04-28 11:12:00 +0900412 base::Bind(&ChannelProxy::Context::OnSendMessage,
413 context_, base::Passed(scoped_ptr<Message>(message))));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900414 return true;
415}
416
417void ChannelProxy::AddFilter(MessageFilter* filter) {
alexeypa@chromium.org0192ff02012-12-05 10:00:36 +0900418 DCHECK(CalledOnValidThread());
419
jam@chromium.orge57135c2010-12-03 04:16:07 +0900420 context_->AddFilter(filter);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900421}
422
423void ChannelProxy::RemoveFilter(MessageFilter* filter) {
alexeypa@chromium.org0192ff02012-12-05 10:00:36 +0900424 DCHECK(CalledOnValidThread());
425
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +0900426 context_->ipc_task_runner()->PostTask(
jhawkins@chromium.org9827bd12011-11-13 06:16:41 +0900427 FROM_HERE, base::Bind(&Context::OnRemoveFilter, context_.get(),
428 make_scoped_refptr(filter)));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900429}
430
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +0900431void ChannelProxy::ClearIPCTaskRunner() {
alexeypa@chromium.org0192ff02012-12-05 10:00:36 +0900432 DCHECK(CalledOnValidThread());
433
sergeyu@chromium.org5b6d49c2012-07-03 06:15:52 +0900434 context()->ClearIPCTaskRunner();
nsylvain@chromium.orgc12dde32009-07-24 03:17:55 +0900435}
436
dmichael@chromium.orgb798bb42012-06-01 04:37:54 +0900437#if defined(OS_POSIX) && !defined(OS_NACL)
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900438// See the TODO regarding lazy initialization of the channel in
439// ChannelProxy::Init().
phajdan.jr@chromium.orgaf9455b2011-09-20 02:08:12 +0900440int ChannelProxy::GetClientFileDescriptor() {
alexeypa@chromium.org0192ff02012-12-05 10:00:36 +0900441 DCHECK(CalledOnValidThread());
442
phajdan.jr@chromium.orgaf9455b2011-09-20 02:08:12 +0900443 Channel* channel = context_.get()->channel_.get();
dmaclach@chromium.org058c4a72010-12-09 04:28:09 +0900444 // Channel must have been created first.
445 DCHECK(channel) << context_.get()->channel_id_;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900446 return channel->GetClientFileDescriptor();
447}
wez@chromium.org7cce0912011-04-06 21:01:44 +0900448
phajdan.jr@chromium.orgaf9455b2011-09-20 02:08:12 +0900449int ChannelProxy::TakeClientFileDescriptor() {
alexeypa@chromium.org0192ff02012-12-05 10:00:36 +0900450 DCHECK(CalledOnValidThread());
451
phajdan.jr@chromium.orgaf9455b2011-09-20 02:08:12 +0900452 Channel* channel = context_.get()->channel_.get();
453 // Channel must have been created first.
454 DCHECK(channel) << context_.get()->channel_id_;
455 return channel->TakeClientFileDescriptor();
456}
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900457#endif
458
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900459//-----------------------------------------------------------------------------
460
461} // namespace IPC