blob: 3365aef248747a657965bfd82c5751a8e69630b8 [file] [log] [blame]
[email protected]0a6fc4b2012-04-05 02:38:341// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]74122042014-04-25 00:07:305#include "ipc/ipc_channel_proxy.h"
6
avi246998d82015-12-22 02:39:047#include <stddef.h>
8#include <stdint.h>
danakj03de39b22016-04-23 04:21:099
dchenge48600452015-12-28 02:24:5010#include <utility>
avi246998d82015-12-22 02:39:0411
[email protected]72b6f8e22011-11-12 21:16:4112#include "base/bind.h"
[email protected]b53225082011-11-29 02:24:2813#include "base/compiler_specific.h"
[email protected]c62dd9d2011-09-21 18:05:4114#include "base/location.h"
danakj03de39b22016-04-23 04:21:0915#include "base/memory/ptr_util.h"
[email protected]3b63f8f42011-03-28 01:54:1516#include "base/memory/ref_counted.h"
pkasting2053ce22015-04-15 06:10:0917#include "base/profiler/scoped_tracker.h"
[email protected]b2432302012-07-02 21:15:5218#include "base/single_thread_task_runner.h"
gabf08ccc02016-05-11 18:51:1119#include "base/threading/thread_task_runner_handle.h"
avi246998d82015-12-22 02:39:0420#include "build/build_config.h"
[email protected]64860882014-08-04 23:44:1721#include "ipc/ipc_channel_factory.h"
[email protected]57319ce2012-06-11 22:35:2622#include "ipc/ipc_listener.h"
[email protected]946d1b22009-07-22 23:57:2123#include "ipc/ipc_logging.h"
[email protected]9ec16852012-05-11 23:24:3724#include "ipc/ipc_message_macros.h"
[email protected]74122042014-04-25 00:07:3025#include "ipc/message_filter.h"
26#include "ipc/message_filter_router.h"
initial.commit09911bf2008-07-26 23:55:2927
28namespace IPC {
29
rockot8d890f62016-07-14 16:37:1430namespace {
31
32void BindAssociatedInterfaceOnTaskRunner(
33 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
34 const ChannelProxy::GenericAssociatedInterfaceFactory& factory,
35 mojo::ScopedInterfaceEndpointHandle handle) {
36 task_runner->PostTask(FROM_HERE, base::Bind(factory, base::Passed(&handle)));
37}
38
39} // namespace
40
[email protected]163951422009-07-28 22:09:4541//------------------------------------------------------------------------------
initial.commit09911bf2008-07-26 23:55:2942
dchengfd033702014-08-28 16:59:2943ChannelProxy::Context::Context(
44 Listener* listener,
45 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner)
[email protected]b2432302012-07-02 21:15:5246 : listener_task_runner_(base::ThreadTaskRunnerHandle::Get()),
initial.commit09911bf2008-07-26 23:55:2947 listener_(listener),
[email protected]b2432302012-07-02 21:15:5248 ipc_task_runner_(ipc_task_runner),
[email protected]0a6fc4b2012-04-05 02:38:3449 channel_connected_called_(false),
[email protected]b51352a2014-02-26 05:18:0450 message_filter_router_(new MessageFilterRouter()),
sammcf810f07f2016-11-10 22:34:0751 peer_pid_(base::kNullProcessId) {
[email protected]17571642013-06-01 04:11:2752 DCHECK(ipc_task_runner_.get());
[email protected]1f9cf472014-04-17 05:07:1853 // The Listener thread where Messages are handled must be a separate thread
54 // to avoid oversubscribing the IO thread. If you trigger this error, you
55 // need to either:
56 // 1) Create the ChannelProxy on a different thread, or
57 // 2) Just use Channel
58 // Note, we currently make an exception for a NULL listener. That usage
59 // basically works, but is outside the intent of ChannelProxy. This support
60 // will disappear, so please don't rely on it. See crbug.com/364241
61 DCHECK(!listener || (ipc_task_runner_.get() != listener_task_runner_.get()));
initial.commit09911bf2008-07-26 23:55:2962}
63
[email protected]92bf9062011-05-02 18:00:4964ChannelProxy::Context::~Context() {
65}
66
[email protected]b2432302012-07-02 21:15:5267void ChannelProxy::Context::ClearIPCTaskRunner() {
68 ipc_task_runner_ = NULL;
69}
70
danakj03de39b22016-04-23 04:21:0971void ChannelProxy::Context::CreateChannel(
72 std::unique_ptr<ChannelFactory> factory) {
morritab4472142015-04-20 21:20:1273 base::AutoLock l(channel_lifetime_lock_);
[email protected]7e3d7522014-03-20 21:00:5074 DCHECK(!channel_);
rockota34707ca2016-07-20 04:28:3275 DCHECK_EQ(factory->GetIPCTaskRunner(), ipc_task_runner_);
[email protected]64860882014-08-04 23:44:1776 channel_ = factory->BuildChannel(this);
rockot0e4de5f2016-07-22 21:18:0777
78 Channel::AssociatedInterfaceSupport* support =
79 channel_->GetAssociatedInterfaceSupport();
80 if (support) {
81 associated_group_ = *support->GetAssociatedGroup();
82
83 base::AutoLock l(pending_filters_lock_);
84 for (auto& entry : pending_interfaces_)
85 support->AddGenericAssociatedInterface(entry.first, entry.second);
86 pending_interfaces_.clear();
87 }
initial.commit09911bf2008-07-26 23:55:2988}
89
[email protected]d65cab7a2008-08-12 01:25:4190bool ChannelProxy::Context::TryFilters(const Message& message) {
[email protected]b51352a2014-02-26 05:18:0491 DCHECK(message_filter_router_);
initial.commit09911bf2008-07-26 23:55:2992#ifdef IPC_MESSAGE_LOG_ENABLED
[email protected]8e8bb6d2010-12-13 08:18:5593 Logging* logger = Logging::GetInstance();
initial.commit09911bf2008-07-26 23:55:2994 if (logger->Enabled())
95 logger->OnPreDispatchMessage(message);
96#endif
97
[email protected]b51352a2014-02-26 05:18:0498 if (message_filter_router_->TryFilters(message)) {
[email protected]ef2f6ba2014-05-15 23:06:0799 if (message.dispatch_error()) {
100 listener_task_runner_->PostTask(
101 FROM_HERE, base::Bind(&Context::OnDispatchBadMessage, this, message));
102 }
initial.commit09911bf2008-07-26 23:55:29103#ifdef IPC_MESSAGE_LOG_ENABLED
[email protected]b51352a2014-02-26 05:18:04104 if (logger->Enabled())
sammca1b3b4d2016-11-15 00:34:36105 logger->OnPostDispatchMessage(message);
initial.commit09911bf2008-07-26 23:55:29106#endif
[email protected]b51352a2014-02-26 05:18:04107 return true;
initial.commit09911bf2008-07-26 23:55:29108 }
[email protected]d65cab7a2008-08-12 01:25:41109 return false;
110}
111
112// Called on the IPC::Channel thread
rockot10188752016-09-08 18:24:56113void ChannelProxy::Context::PauseChannel() {
114 DCHECK(channel_);
115 channel_->Pause();
116}
117
118// Called on the IPC::Channel thread
rockot401fb2c2016-09-06 18:35:57119void ChannelProxy::Context::UnpauseChannel(bool flush) {
120 DCHECK(channel_);
121 channel_->Unpause(flush);
122}
123
124// Called on the IPC::Channel thread
125void ChannelProxy::Context::FlushChannel() {
126 DCHECK(channel_);
127 channel_->Flush();
128}
129
130// Called on the IPC::Channel thread
[email protected]a95986a82010-12-24 06:19:28131bool ChannelProxy::Context::OnMessageReceived(const Message& message) {
[email protected]d65cab7a2008-08-12 01:25:41132 // First give a chance to the filters to process this message.
[email protected]3cdb7af812008-10-24 19:21:13133 if (!TryFilters(message))
134 OnMessageReceivedNoFilter(message);
[email protected]a95986a82010-12-24 06:19:28135 return true;
[email protected]3cdb7af812008-10-24 19:21:13136}
initial.commit09911bf2008-07-26 23:55:29137
[email protected]3cdb7af812008-10-24 19:21:13138// Called on the IPC::Channel thread
[email protected]a95986a82010-12-24 06:19:28139bool ChannelProxy::Context::OnMessageReceivedNoFilter(const Message& message) {
[email protected]b2432302012-07-02 21:15:52140 listener_task_runner_->PostTask(
[email protected]72b6f8e22011-11-12 21:16:41141 FROM_HERE, base::Bind(&Context::OnDispatchMessage, this, message));
[email protected]a95986a82010-12-24 06:19:28142 return true;
initial.commit09911bf2008-07-26 23:55:29143}
144
145// Called on the IPC::Channel thread
tfarina10a5c062015-09-04 18:47:57146void ChannelProxy::Context::OnChannelConnected(int32_t peer_pid) {
[email protected]7e3d7522014-03-20 21:00:50147 // We cache off the peer_pid so it can be safely accessed from both threads.
amistry78ef5f1b2016-07-19 02:52:31148 {
149 base::AutoLock l(peer_pid_lock_);
sammcf810f07f2016-11-10 22:34:07150 peer_pid_ = peer_pid;
amistry78ef5f1b2016-07-19 02:52:31151 }
[email protected]7e3d7522014-03-20 21:00:50152
[email protected]4b580bf2010-12-02 19:16:07153 // Add any pending filters. This avoids a race condition where someone
154 // creates a ChannelProxy, calls AddFilter, and then right after starts the
155 // peer process. The IO thread could receive a message before the task to add
156 // the filter is run on the IO thread.
157 OnAddFilter();
158
[email protected]b2432302012-07-02 21:15:52159 // See above comment about using listener_task_runner_ here.
160 listener_task_runner_->PostTask(
[email protected]72b6f8e22011-11-12 21:16:41161 FROM_HERE, base::Bind(&Context::OnDispatchConnected, this));
initial.commit09911bf2008-07-26 23:55:29162}
163
164// Called on the IPC::Channel thread
165void ChannelProxy::Context::OnChannelError() {
[email protected]5fa1c542009-05-05 20:36:07166 for (size_t i = 0; i < filters_.size(); ++i)
167 filters_[i]->OnChannelError();
168
[email protected]b2432302012-07-02 21:15:52169 // See above comment about using listener_task_runner_ here.
170 listener_task_runner_->PostTask(
[email protected]72b6f8e22011-11-12 21:16:41171 FROM_HERE, base::Bind(&Context::OnDispatchError, this));
initial.commit09911bf2008-07-26 23:55:29172}
173
174// Called on the IPC::Channel thread
rockotf62002a2016-09-15 00:08:59175void ChannelProxy::Context::OnAssociatedInterfaceRequest(
176 const std::string& interface_name,
177 mojo::ScopedInterfaceEndpointHandle handle) {
178 listener_task_runner_->PostTask(
179 FROM_HERE, base::Bind(&Context::OnDispatchAssociatedInterfaceRequest,
180 this, interface_name, base::Passed(&handle)));
181}
182
183// Called on the IPC::Channel thread
rockot10188752016-09-08 18:24:56184void ChannelProxy::Context::OnChannelOpened() {
initial.commit09911bf2008-07-26 23:55:29185 DCHECK(channel_ != NULL);
186
187 // Assume a reference to ourselves on behalf of this thread. This reference
188 // will be released when we are closed.
189 AddRef();
190
rockot10188752016-09-08 18:24:56191 if (!channel_->Connect()) {
initial.commit09911bf2008-07-26 23:55:29192 OnChannelError();
193 return;
194 }
195
196 for (size_t i = 0; i < filters_.size(); ++i)
[email protected]42ce94e2010-12-08 19:28:09197 filters_[i]->OnFilterAdded(channel_.get());
initial.commit09911bf2008-07-26 23:55:29198}
199
200// Called on the IPC::Channel thread
[email protected]3cdb7af812008-10-24 19:21:13201void ChannelProxy::Context::OnChannelClosed() {
pkasting2053ce22015-04-15 06:10:09202 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
203 tracked_objects::ScopedTracker tracking_profile(
204 FROM_HERE_WITH_EXPLICIT_FUNCTION(
205 "477117 ChannelProxy::Context::OnChannelClosed"));
initial.commit09911bf2008-07-26 23:55:29206 // It's okay for IPC::ChannelProxy::Close to be called more than once, which
207 // would result in this branch being taken.
[email protected]7e3d7522014-03-20 21:00:50208 if (!channel_)
initial.commit09911bf2008-07-26 23:55:29209 return;
210
tzik0e85f1d2016-11-05 09:26:44211 for (auto& filter : pending_filters_) {
212 filter->OnChannelClosing();
213 filter->OnFilterRemoved();
214 }
215 for (auto& filter : filters_) {
216 filter->OnChannelClosing();
217 filter->OnFilterRemoved();
initial.commit09911bf2008-07-26 23:55:29218 }
219
220 // We don't need the filters anymore.
[email protected]b51352a2014-02-26 05:18:04221 message_filter_router_->Clear();
initial.commit09911bf2008-07-26 23:55:29222 filters_.clear();
[email protected]7e3d7522014-03-20 21:00:50223 // We don't need the lock, because at this point, the listener thread can't
224 // access it any more.
225 pending_filters_.clear();
initial.commit09911bf2008-07-26 23:55:29226
morritab4472142015-04-20 21:20:12227 ClearChannel();
initial.commit09911bf2008-07-26 23:55:29228
229 // Balance with the reference taken during startup. This may result in
230 // self-destruction.
231 Release();
232}
233
[email protected]772a5b22012-08-09 20:39:12234void ChannelProxy::Context::Clear() {
235 listener_ = NULL;
236}
237
initial.commit09911bf2008-07-26 23:55:29238// Called on the IPC::Channel thread
danakj03de39b22016-04-23 04:21:09239void ChannelProxy::Context::OnSendMessage(std::unique_ptr<Message> message) {
pkasting2053ce22015-04-15 06:10:09240 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
241 tracked_objects::ScopedTracker tracking_profile(
242 FROM_HERE_WITH_EXPLICIT_FUNCTION(
243 "477117 ChannelProxy::Context::OnSendMessage"));
[email protected]7e3d7522014-03-20 21:00:50244 if (!channel_) {
[email protected]87339f02010-09-02 21:45:50245 OnChannelClosed();
246 return;
247 }
[email protected]7e3d7522014-03-20 21:00:50248
[email protected]f729d15a2012-04-28 02:12:00249 if (!channel_->Send(message.release()))
initial.commit09911bf2008-07-26 23:55:29250 OnChannelError();
251}
252
253// Called on the IPC::Channel thread
[email protected]4b580bf2010-12-02 19:16:07254void ChannelProxy::Context::OnAddFilter() {
[email protected]7e3d7522014-03-20 21:00:50255 // Our OnChannelConnected method has not yet been called, so we can't be
256 // sure that channel_ is valid yet. When OnChannelConnected *is* called,
257 // it invokes OnAddFilter, so any pending filter(s) will be added at that
258 // time.
amistry78ef5f1b2016-07-19 02:52:31259 // No lock necessary for |peer_pid_| because it is only modified on this
260 // thread.
[email protected]7e3d7522014-03-20 21:00:50261 if (peer_pid_ == base::kNullProcessId)
262 return;
263
[email protected]413889302011-08-16 22:12:39264 std::vector<scoped_refptr<MessageFilter> > new_filters;
[email protected]4b580bf2010-12-02 19:16:07265 {
[email protected]20305ec2011-01-21 04:55:52266 base::AutoLock auto_lock(pending_filters_lock_);
[email protected]413889302011-08-16 22:12:39267 new_filters.swap(pending_filters_);
[email protected]4b580bf2010-12-02 19:16:07268 }
initial.commit09911bf2008-07-26 23:55:29269
[email protected]413889302011-08-16 22:12:39270 for (size_t i = 0; i < new_filters.size(); ++i) {
271 filters_.push_back(new_filters[i]);
[email protected]4b580bf2010-12-02 19:16:07272
[email protected]b51352a2014-02-26 05:18:04273 message_filter_router_->AddFilter(new_filters[i].get());
274
[email protected]7e3d7522014-03-20 21:00:50275 // The channel has already been created and connected, so we need to
276 // inform the filters right now.
277 new_filters[i]->OnFilterAdded(channel_.get());
278 new_filters[i]->OnChannelConnected(peer_pid_);
[email protected]4b580bf2010-12-02 19:16:07279 }
initial.commit09911bf2008-07-26 23:55:29280}
281
282// Called on the IPC::Channel thread
283void ChannelProxy::Context::OnRemoveFilter(MessageFilter* filter) {
amistry78ef5f1b2016-07-19 02:52:31284 // No lock necessary for |peer_pid_| because it is only modified on this
285 // thread.
[email protected]7e3d7522014-03-20 21:00:50286 if (peer_pid_ == base::kNullProcessId) {
287 // The channel is not yet connected, so any filters are still pending.
288 base::AutoLock auto_lock(pending_filters_lock_);
289 for (size_t i = 0; i < pending_filters_.size(); ++i) {
290 if (pending_filters_[i].get() == filter) {
291 filter->OnFilterRemoved();
292 pending_filters_.erase(pending_filters_.begin() + i);
293 return;
294 }
295 }
296 return;
297 }
298 if (!channel_)
[email protected]6d057a0c2013-07-09 21:12:07299 return; // The filters have already been deleted.
300
[email protected]b51352a2014-02-26 05:18:04301 message_filter_router_->RemoveFilter(filter);
302
initial.commit09911bf2008-07-26 23:55:29303 for (size_t i = 0; i < filters_.size(); ++i) {
304 if (filters_[i].get() == filter) {
305 filter->OnFilterRemoved();
306 filters_.erase(filters_.begin() + i);
307 return;
308 }
309 }
310
311 NOTREACHED() << "filter to be removed not found";
312}
313
314// Called on the listener's thread
[email protected]4b580bf2010-12-02 19:16:07315void ChannelProxy::Context::AddFilter(MessageFilter* filter) {
[email protected]20305ec2011-01-21 04:55:52316 base::AutoLock auto_lock(pending_filters_lock_);
[email protected]4b580bf2010-12-02 19:16:07317 pending_filters_.push_back(make_scoped_refptr(filter));
[email protected]b2432302012-07-02 21:15:52318 ipc_task_runner_->PostTask(
[email protected]72b6f8e22011-11-12 21:16:41319 FROM_HERE, base::Bind(&Context::OnAddFilter, this));
[email protected]4b580bf2010-12-02 19:16:07320}
321
322// Called on the listener's thread
initial.commit09911bf2008-07-26 23:55:29323void ChannelProxy::Context::OnDispatchMessage(const Message& message) {
324 if (!listener_)
325 return;
326
[email protected]827ab812009-03-12 07:17:17327 OnDispatchConnected();
328
initial.commit09911bf2008-07-26 23:55:29329#ifdef IPC_MESSAGE_LOG_ENABLED
ssid6c1dc892016-03-28 19:56:49330 Logging* logger = Logging::GetInstance();
initial.commit09911bf2008-07-26 23:55:29331 if (message.type() == IPC_LOGGING_ID) {
332 logger->OnReceivedLoggingMessage(message);
333 return;
334 }
335
336 if (logger->Enabled())
337 logger->OnPreDispatchMessage(message);
338#endif
339
340 listener_->OnMessageReceived(message);
[email protected]ef2f6ba2014-05-15 23:06:07341 if (message.dispatch_error())
342 listener_->OnBadMessageReceived(message);
initial.commit09911bf2008-07-26 23:55:29343
344#ifdef IPC_MESSAGE_LOG_ENABLED
345 if (logger->Enabled())
sammca1b3b4d2016-11-15 00:34:36346 logger->OnPostDispatchMessage(message);
initial.commit09911bf2008-07-26 23:55:29347#endif
348}
349
350// Called on the listener's thread
[email protected]827ab812009-03-12 07:17:17351void ChannelProxy::Context::OnDispatchConnected() {
352 if (channel_connected_called_)
353 return;
354
amistry78ef5f1b2016-07-19 02:52:31355 base::ProcessId peer_pid;
356 {
357 base::AutoLock l(peer_pid_lock_);
358 peer_pid = peer_pid_;
359 }
[email protected]827ab812009-03-12 07:17:17360 channel_connected_called_ = true;
initial.commit09911bf2008-07-26 23:55:29361 if (listener_)
amistry78ef5f1b2016-07-19 02:52:31362 listener_->OnChannelConnected(peer_pid);
initial.commit09911bf2008-07-26 23:55:29363}
364
365// Called on the listener's thread
366void ChannelProxy::Context::OnDispatchError() {
367 if (listener_)
368 listener_->OnChannelError();
369}
370
[email protected]ef2f6ba2014-05-15 23:06:07371// Called on the listener's thread
372void ChannelProxy::Context::OnDispatchBadMessage(const Message& message) {
373 if (listener_)
374 listener_->OnBadMessageReceived(message);
375}
376
rockotf62002a2016-09-15 00:08:59377// Called on the listener's thread
378void ChannelProxy::Context::OnDispatchAssociatedInterfaceRequest(
379 const std::string& interface_name,
380 mojo::ScopedInterfaceEndpointHandle handle) {
381 if (listener_)
382 listener_->OnAssociatedInterfaceRequest(interface_name, std::move(handle));
383}
384
morritab4472142015-04-20 21:20:12385void ChannelProxy::Context::ClearChannel() {
386 base::AutoLock l(channel_lifetime_lock_);
387 channel_.reset();
rockot0e4de5f2016-07-22 21:18:07388 associated_group_ = mojo::AssociatedGroup();
389}
390
391void ChannelProxy::Context::AddGenericAssociatedInterface(
392 const std::string& name,
393 const GenericAssociatedInterfaceFactory& factory) {
394 AddGenericAssociatedInterfaceForIOThread(
395 name, base::Bind(&BindAssociatedInterfaceOnTaskRunner,
396 listener_task_runner_, factory));
397}
398
399void ChannelProxy::Context::AddGenericAssociatedInterfaceForIOThread(
400 const std::string& name,
401 const GenericAssociatedInterfaceFactory& factory) {
402 base::AutoLock l(channel_lifetime_lock_);
403 if (!channel_) {
404 base::AutoLock l(pending_filters_lock_);
405 pending_interfaces_.emplace_back(name, factory);
406 return;
407 }
408 Channel::AssociatedInterfaceSupport* support =
409 channel_->GetAssociatedInterfaceSupport();
rockotfd3d90842016-09-15 23:57:29410 if (support)
411 support->AddGenericAssociatedInterface(name, factory);
morritab4472142015-04-20 21:20:12412}
413
rockotf14a8ae2016-06-16 19:28:41414void ChannelProxy::Context::Send(Message* message) {
morritab4472142015-04-20 21:20:12415 ipc_task_runner()->PostTask(
416 FROM_HERE, base::Bind(&ChannelProxy::Context::OnSendMessage, this,
rockotf14a8ae2016-06-16 19:28:41417 base::Passed(base::WrapUnique(message))));
morritab4472142015-04-20 21:20:12418}
419
rockot8d890f62016-07-14 16:37:14420// Called on the IPC::Channel thread
421void ChannelProxy::Context::GetRemoteAssociatedInterface(
422 const std::string& name,
423 mojo::ScopedInterfaceEndpointHandle handle) {
424 if (!channel_)
425 return;
426 Channel::AssociatedInterfaceSupport* associated_interface_support =
427 channel_->GetAssociatedInterfaceSupport();
428 DCHECK(associated_interface_support);
429 associated_interface_support->GetGenericRemoteAssociatedInterface(
430 name, std::move(handle));
431}
432
initial.commit09911bf2008-07-26 23:55:29433//-----------------------------------------------------------------------------
434
[email protected]fca876a12014-06-05 16:15:38435// static
danakj03de39b22016-04-23 04:21:09436std::unique_ptr<ChannelProxy> ChannelProxy::Create(
[email protected]fca876a12014-06-05 16:15:38437 const IPC::ChannelHandle& channel_handle,
438 Channel::Mode mode,
439 Listener* listener,
erikchen30dc2812015-09-24 03:26:38440 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
danakj03de39b22016-04-23 04:21:09441 std::unique_ptr<ChannelProxy> channel(
442 new ChannelProxy(listener, ipc_task_runner));
erikchen30dc2812015-09-24 03:26:38443 channel->Init(channel_handle, mode, true);
dchenge48600452015-12-28 02:24:50444 return channel;
initial.commit09911bf2008-07-26 23:55:29445}
446
[email protected]64860882014-08-04 23:44:17447// static
danakj03de39b22016-04-23 04:21:09448std::unique_ptr<ChannelProxy> ChannelProxy::Create(
449 std::unique_ptr<ChannelFactory> factory,
[email protected]64860882014-08-04 23:44:17450 Listener* listener,
dchengfd033702014-08-28 16:59:29451 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
danakj03de39b22016-04-23 04:21:09452 std::unique_ptr<ChannelProxy> channel(
453 new ChannelProxy(listener, ipc_task_runner));
dchenge48600452015-12-28 02:24:50454 channel->Init(std::move(factory), true);
455 return channel;
[email protected]64860882014-08-04 23:44:17456}
457
[email protected]952394af2011-11-16 01:06:46458ChannelProxy::ChannelProxy(Context* context)
rockota34707ca2016-07-20 04:28:32459 : context_(context), did_init_(false) {
mbarbellae97877bc2015-03-06 21:51:14460#if defined(ENABLE_IPC_FUZZER)
461 outgoing_message_filter_ = NULL;
462#endif
initial.commit09911bf2008-07-26 23:55:29463}
464
dchengfd033702014-08-28 16:59:29465ChannelProxy::ChannelProxy(
466 Listener* listener,
467 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner)
rockotf14a8ae2016-06-16 19:28:41468 : context_(new Context(listener, ipc_task_runner)), did_init_(false) {
469#if defined(ENABLE_IPC_FUZZER)
470 outgoing_message_filter_ = NULL;
471#endif
472}
[email protected]fca876a12014-06-05 16:15:38473
[email protected]dec76e802010-09-23 22:43:53474ChannelProxy::~ChannelProxy() {
[email protected]f775d102012-12-05 01:00:36475 DCHECK(CalledOnValidThread());
476
[email protected]dec76e802010-09-23 22:43:53477 Close();
478}
479
[email protected]3b0e4662014-06-02 20:29:30480void ChannelProxy::Init(const IPC::ChannelHandle& channel_handle,
481 Channel::Mode mode,
rockot10188752016-09-08 18:24:56482 bool create_pipe_now) {
[email protected]42ce94e2010-12-08 19:28:09483#if defined(OS_POSIX)
484 // When we are creating a server on POSIX, we need its file descriptor
485 // to be created immediately so that it can be accessed and passed
486 // to other processes. Forcing it to be created immediately avoids
487 // race conditions that may otherwise arise.
[email protected]1707726c2011-02-03 20:35:09488 if (mode & Channel::MODE_SERVER_FLAG) {
[email protected]42ce94e2010-12-08 19:28:09489 create_pipe_now = true;
490 }
491#endif // defined(OS_POSIX)
rockota34707ca2016-07-20 04:28:32492 Init(
493 ChannelFactory::Create(channel_handle, mode, context_->ipc_task_runner()),
rockot10188752016-09-08 18:24:56494 create_pipe_now);
[email protected]64860882014-08-04 23:44:17495}
496
danakj03de39b22016-04-23 04:21:09497void ChannelProxy::Init(std::unique_ptr<ChannelFactory> factory,
rockot10188752016-09-08 18:24:56498 bool create_pipe_now) {
[email protected]64860882014-08-04 23:44:17499 DCHECK(CalledOnValidThread());
500 DCHECK(!did_init_);
[email protected]42ce94e2010-12-08 19:28:09501
initial.commit09911bf2008-07-26 23:55:29502 if (create_pipe_now) {
503 // Create the channel immediately. This effectively sets up the
504 // low-level pipe so that the client can connect. Without creating
505 // the pipe immediately, it is possible for a listener to attempt
506 // to connect and get an error since the pipe doesn't exist yet.
dchenge48600452015-12-28 02:24:50507 context_->CreateChannel(std::move(factory));
initial.commit09911bf2008-07-26 23:55:29508 } else {
[email protected]b2432302012-07-02 21:15:52509 context_->ipc_task_runner()->PostTask(
tzik07cace42016-09-01 04:21:25510 FROM_HERE, base::Bind(&Context::CreateChannel, context_,
dcheng0917ec42015-11-19 07:00:20511 base::Passed(&factory)));
initial.commit09911bf2008-07-26 23:55:29512 }
513
514 // complete initialization on the background thread
[email protected]b2432302012-07-02 21:15:52515 context_->ipc_task_runner()->PostTask(
rockot401fb2c2016-09-06 18:35:57516 FROM_HERE,
rockot10188752016-09-08 18:24:56517 base::Bind(&Context::OnChannelOpened, context_));
[email protected]952394af2011-11-16 01:06:46518
519 did_init_ = true;
rockot29ade1b2015-08-07 06:23:59520 OnChannelInit();
initial.commit09911bf2008-07-26 23:55:29521}
522
rockot10188752016-09-08 18:24:56523void ChannelProxy::Pause() {
524 context_->ipc_task_runner()->PostTask(
525 FROM_HERE, base::Bind(&Context::PauseChannel, context_));
526}
527
rockot401fb2c2016-09-06 18:35:57528void ChannelProxy::Unpause(bool flush) {
529 context_->ipc_task_runner()->PostTask(
530 FROM_HERE, base::Bind(&Context::UnpauseChannel, context_, flush));
531}
532
533void ChannelProxy::Flush() {
534 context_->ipc_task_runner()->PostTask(
535 FROM_HERE, base::Bind(&Context::FlushChannel, context_));
536}
537
initial.commit09911bf2008-07-26 23:55:29538void ChannelProxy::Close() {
[email protected]f775d102012-12-05 01:00:36539 DCHECK(CalledOnValidThread());
540
initial.commit09911bf2008-07-26 23:55:29541 // Clear the backpointer to the listener so that any pending calls to
542 // Context::OnDispatchMessage or OnDispatchError will be ignored. It is
543 // possible that the channel could be closed while it is receiving messages!
[email protected]3cdb7af812008-10-24 19:21:13544 context_->Clear();
initial.commit09911bf2008-07-26 23:55:29545
[email protected]b2432302012-07-02 21:15:52546 if (context_->ipc_task_runner()) {
547 context_->ipc_task_runner()->PostTask(
tzik07cace42016-09-01 04:21:25548 FROM_HERE, base::Bind(&Context::OnChannelClosed, context_));
initial.commit09911bf2008-07-26 23:55:29549 }
550}
551
552bool ChannelProxy::Send(Message* message) {
rockotf14a8ae2016-06-16 19:28:41553 DCHECK(did_init_);
[email protected]f775d102012-12-05 01:00:36554
rockotf14a8ae2016-06-16 19:28:41555 // TODO(alexeypa): add DCHECK(CalledOnValidThread()) here. Currently there are
556 // tests that call Send() from a wrong thread. See http://crbug.com/163523.
[email protected]89480312011-05-04 17:14:16557
rockotf14a8ae2016-06-16 19:28:41558#ifdef ENABLE_IPC_FUZZER
559 // In IPC fuzzing builds, it is possible to define a filter to apply to
560 // outgoing messages. It will either rewrite the message and return a new
561 // one, freeing the original, or return the message unchanged.
562 if (outgoing_message_filter())
563 message = outgoing_message_filter()->Rewrite(message);
564#endif
565
566#ifdef IPC_MESSAGE_LOG_ENABLED
sammca1b3b4d2016-11-15 00:34:36567 Logging::GetInstance()->OnSendMessage(message);
rockotf14a8ae2016-06-16 19:28:41568#endif
569
570 context_->Send(message);
571 return true;
initial.commit09911bf2008-07-26 23:55:29572}
573
574void ChannelProxy::AddFilter(MessageFilter* filter) {
[email protected]f775d102012-12-05 01:00:36575 DCHECK(CalledOnValidThread());
576
[email protected]4b580bf2010-12-02 19:16:07577 context_->AddFilter(filter);
initial.commit09911bf2008-07-26 23:55:29578}
579
580void ChannelProxy::RemoveFilter(MessageFilter* filter) {
[email protected]f775d102012-12-05 01:00:36581 DCHECK(CalledOnValidThread());
582
[email protected]b2432302012-07-02 21:15:52583 context_->ipc_task_runner()->PostTask(
tzik07cace42016-09-01 04:21:25584 FROM_HERE, base::Bind(&Context::OnRemoveFilter, context_,
vmpstra34d11322016-03-21 20:28:47585 base::RetainedRef(filter)));
initial.commit09911bf2008-07-26 23:55:29586}
587
msramek5507fee2016-07-22 10:06:21588void ChannelProxy::AddGenericAssociatedInterface(
589 const std::string& name,
590 const GenericAssociatedInterfaceFactory& factory) {
rockot0e4de5f2016-07-22 21:18:07591 context()->AddGenericAssociatedInterface(name, factory);
592}
593
594void ChannelProxy::AddGenericAssociatedInterfaceForIOThread(
595 const std::string& name,
596 const GenericAssociatedInterfaceFactory& factory) {
597 context()->AddGenericAssociatedInterfaceForIOThread(name, factory);
rockot8d890f62016-07-14 16:37:14598}
599
600mojo::AssociatedGroup* ChannelProxy::GetAssociatedGroup() {
rockot0e4de5f2016-07-22 21:18:07601 return context()->associated_group();
rockot8d890f62016-07-14 16:37:14602}
603
604void ChannelProxy::GetGenericRemoteAssociatedInterface(
605 const std::string& name,
606 mojo::ScopedInterfaceEndpointHandle handle) {
rockot5a908952016-07-28 20:08:17607 DCHECK(did_init_);
rockot8d890f62016-07-14 16:37:14608 context_->ipc_task_runner()->PostTask(
609 FROM_HERE, base::Bind(&Context::GetRemoteAssociatedInterface,
tzik07cace42016-09-01 04:21:25610 context_, name, base::Passed(&handle)));
rockot8d890f62016-07-14 16:37:14611}
612
[email protected]b2432302012-07-02 21:15:52613void ChannelProxy::ClearIPCTaskRunner() {
[email protected]f775d102012-12-05 01:00:36614 DCHECK(CalledOnValidThread());
615
[email protected]b2432302012-07-02 21:15:52616 context()->ClearIPCTaskRunner();
[email protected]42f1d7822009-07-23 18:17:55617}
618
rockot29ade1b2015-08-07 06:23:59619void ChannelProxy::OnChannelInit() {
620}
621
initial.commit09911bf2008-07-26 23:55:29622//-----------------------------------------------------------------------------
623
624} // namespace IPC