blob: 9b8ece18d4db3f034fa65e246b69b5fb4a0e040f [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),
morritab4472142015-04-20 21:20:1250 channel_send_thread_safe_(false),
[email protected]b51352a2014-02-26 05:18:0451 message_filter_router_(new MessageFilterRouter()),
erikchenbcc79612015-07-31 00:04:4252 peer_pid_(base::kNullProcessId),
53 attachment_broker_endpoint_(false) {
[email protected]17571642013-06-01 04:11:2754 DCHECK(ipc_task_runner_.get());
[email protected]1f9cf472014-04-17 05:07:1855 // The Listener thread where Messages are handled must be a separate thread
56 // to avoid oversubscribing the IO thread. If you trigger this error, you
57 // need to either:
58 // 1) Create the ChannelProxy on a different thread, or
59 // 2) Just use Channel
60 // Note, we currently make an exception for a NULL listener. That usage
61 // basically works, but is outside the intent of ChannelProxy. This support
62 // will disappear, so please don't rely on it. See crbug.com/364241
63 DCHECK(!listener || (ipc_task_runner_.get() != listener_task_runner_.get()));
initial.commit09911bf2008-07-26 23:55:2964}
65
[email protected]92bf9062011-05-02 18:00:4966ChannelProxy::Context::~Context() {
67}
68
[email protected]b2432302012-07-02 21:15:5269void ChannelProxy::Context::ClearIPCTaskRunner() {
70 ipc_task_runner_ = NULL;
71}
72
danakj03de39b22016-04-23 04:21:0973void ChannelProxy::Context::CreateChannel(
74 std::unique_ptr<ChannelFactory> factory) {
morritab4472142015-04-20 21:20:1275 base::AutoLock l(channel_lifetime_lock_);
[email protected]7e3d7522014-03-20 21:00:5076 DCHECK(!channel_);
rockota34707ca2016-07-20 04:28:3277 DCHECK_EQ(factory->GetIPCTaskRunner(), ipc_task_runner_);
[email protected]64860882014-08-04 23:44:1778 channel_id_ = factory->GetName();
79 channel_ = factory->BuildChannel(this);
morritab4472142015-04-20 21:20:1280 channel_send_thread_safe_ = channel_->IsSendThreadSafe();
erikchena09b9be72015-08-10 19:22:3381 channel_->SetAttachmentBrokerEndpoint(attachment_broker_endpoint_);
rockot0e4de5f2016-07-22 21:18:0782
83 Channel::AssociatedInterfaceSupport* support =
84 channel_->GetAssociatedInterfaceSupport();
85 if (support) {
86 associated_group_ = *support->GetAssociatedGroup();
87
88 base::AutoLock l(pending_filters_lock_);
89 for (auto& entry : pending_interfaces_)
90 support->AddGenericAssociatedInterface(entry.first, entry.second);
91 pending_interfaces_.clear();
92 }
initial.commit09911bf2008-07-26 23:55:2993}
94
[email protected]d65cab7a2008-08-12 01:25:4195bool ChannelProxy::Context::TryFilters(const Message& message) {
[email protected]b51352a2014-02-26 05:18:0496 DCHECK(message_filter_router_);
initial.commit09911bf2008-07-26 23:55:2997#ifdef IPC_MESSAGE_LOG_ENABLED
[email protected]8e8bb6d2010-12-13 08:18:5598 Logging* logger = Logging::GetInstance();
initial.commit09911bf2008-07-26 23:55:2999 if (logger->Enabled())
100 logger->OnPreDispatchMessage(message);
101#endif
102
[email protected]b51352a2014-02-26 05:18:04103 if (message_filter_router_->TryFilters(message)) {
[email protected]ef2f6ba2014-05-15 23:06:07104 if (message.dispatch_error()) {
105 listener_task_runner_->PostTask(
106 FROM_HERE, base::Bind(&Context::OnDispatchBadMessage, this, message));
107 }
initial.commit09911bf2008-07-26 23:55:29108#ifdef IPC_MESSAGE_LOG_ENABLED
[email protected]b51352a2014-02-26 05:18:04109 if (logger->Enabled())
110 logger->OnPostDispatchMessage(message, channel_id_);
initial.commit09911bf2008-07-26 23:55:29111#endif
[email protected]b51352a2014-02-26 05:18:04112 return true;
initial.commit09911bf2008-07-26 23:55:29113 }
[email protected]d65cab7a2008-08-12 01:25:41114 return false;
115}
116
117// Called on the IPC::Channel thread
rockot10188752016-09-08 18:24:56118void ChannelProxy::Context::PauseChannel() {
119 DCHECK(channel_);
120 channel_->Pause();
121}
122
123// Called on the IPC::Channel thread
rockot401fb2c2016-09-06 18:35:57124void ChannelProxy::Context::UnpauseChannel(bool flush) {
125 DCHECK(channel_);
126 channel_->Unpause(flush);
127}
128
129// Called on the IPC::Channel thread
130void ChannelProxy::Context::FlushChannel() {
131 DCHECK(channel_);
132 channel_->Flush();
133}
134
135// Called on the IPC::Channel thread
[email protected]a95986a82010-12-24 06:19:28136bool ChannelProxy::Context::OnMessageReceived(const Message& message) {
[email protected]d65cab7a2008-08-12 01:25:41137 // First give a chance to the filters to process this message.
[email protected]3cdb7af812008-10-24 19:21:13138 if (!TryFilters(message))
139 OnMessageReceivedNoFilter(message);
[email protected]a95986a82010-12-24 06:19:28140 return true;
[email protected]3cdb7af812008-10-24 19:21:13141}
initial.commit09911bf2008-07-26 23:55:29142
[email protected]3cdb7af812008-10-24 19:21:13143// Called on the IPC::Channel thread
[email protected]a95986a82010-12-24 06:19:28144bool ChannelProxy::Context::OnMessageReceivedNoFilter(const Message& message) {
[email protected]b2432302012-07-02 21:15:52145 listener_task_runner_->PostTask(
[email protected]72b6f8e22011-11-12 21:16:41146 FROM_HERE, base::Bind(&Context::OnDispatchMessage, this, message));
[email protected]a95986a82010-12-24 06:19:28147 return true;
initial.commit09911bf2008-07-26 23:55:29148}
149
150// Called on the IPC::Channel thread
tfarina10a5c062015-09-04 18:47:57151void ChannelProxy::Context::OnChannelConnected(int32_t peer_pid) {
[email protected]7e3d7522014-03-20 21:00:50152 // We cache off the peer_pid so it can be safely accessed from both threads.
amistry78ef5f1b2016-07-19 02:52:31153 {
154 base::AutoLock l(peer_pid_lock_);
155 peer_pid_ = channel_->GetPeerPID();
156 }
[email protected]7e3d7522014-03-20 21:00:50157
[email protected]4b580bf2010-12-02 19:16:07158 // Add any pending filters. This avoids a race condition where someone
159 // creates a ChannelProxy, calls AddFilter, and then right after starts the
160 // peer process. The IO thread could receive a message before the task to add
161 // the filter is run on the IO thread.
162 OnAddFilter();
163
[email protected]b2432302012-07-02 21:15:52164 // See above comment about using listener_task_runner_ here.
165 listener_task_runner_->PostTask(
[email protected]72b6f8e22011-11-12 21:16:41166 FROM_HERE, base::Bind(&Context::OnDispatchConnected, this));
initial.commit09911bf2008-07-26 23:55:29167}
168
169// Called on the IPC::Channel thread
170void ChannelProxy::Context::OnChannelError() {
[email protected]5fa1c542009-05-05 20:36:07171 for (size_t i = 0; i < filters_.size(); ++i)
172 filters_[i]->OnChannelError();
173
[email protected]b2432302012-07-02 21:15:52174 // See above comment about using listener_task_runner_ here.
175 listener_task_runner_->PostTask(
[email protected]72b6f8e22011-11-12 21:16:41176 FROM_HERE, base::Bind(&Context::OnDispatchError, this));
initial.commit09911bf2008-07-26 23:55:29177}
178
179// Called on the IPC::Channel thread
rockotf62002a2016-09-15 00:08:59180void ChannelProxy::Context::OnAssociatedInterfaceRequest(
181 const std::string& interface_name,
182 mojo::ScopedInterfaceEndpointHandle handle) {
183 listener_task_runner_->PostTask(
184 FROM_HERE, base::Bind(&Context::OnDispatchAssociatedInterfaceRequest,
185 this, interface_name, base::Passed(&handle)));
186}
187
188// Called on the IPC::Channel thread
rockot10188752016-09-08 18:24:56189void ChannelProxy::Context::OnChannelOpened() {
initial.commit09911bf2008-07-26 23:55:29190 DCHECK(channel_ != NULL);
191
192 // Assume a reference to ourselves on behalf of this thread. This reference
193 // will be released when we are closed.
194 AddRef();
195
rockot10188752016-09-08 18:24:56196 if (!channel_->Connect()) {
initial.commit09911bf2008-07-26 23:55:29197 OnChannelError();
198 return;
199 }
200
201 for (size_t i = 0; i < filters_.size(); ++i)
[email protected]42ce94e2010-12-08 19:28:09202 filters_[i]->OnFilterAdded(channel_.get());
initial.commit09911bf2008-07-26 23:55:29203}
204
205// Called on the IPC::Channel thread
[email protected]3cdb7af812008-10-24 19:21:13206void ChannelProxy::Context::OnChannelClosed() {
pkasting2053ce22015-04-15 06:10:09207 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
208 tracked_objects::ScopedTracker tracking_profile(
209 FROM_HERE_WITH_EXPLICIT_FUNCTION(
210 "477117 ChannelProxy::Context::OnChannelClosed"));
initial.commit09911bf2008-07-26 23:55:29211 // It's okay for IPC::ChannelProxy::Close to be called more than once, which
212 // would result in this branch being taken.
[email protected]7e3d7522014-03-20 21:00:50213 if (!channel_)
initial.commit09911bf2008-07-26 23:55:29214 return;
215
216 for (size_t i = 0; i < filters_.size(); ++i) {
217 filters_[i]->OnChannelClosing();
218 filters_[i]->OnFilterRemoved();
219 }
220
221 // We don't need the filters anymore.
[email protected]b51352a2014-02-26 05:18:04222 message_filter_router_->Clear();
initial.commit09911bf2008-07-26 23:55:29223 filters_.clear();
[email protected]7e3d7522014-03-20 21:00:50224 // We don't need the lock, because at this point, the listener thread can't
225 // access it any more.
226 pending_filters_.clear();
initial.commit09911bf2008-07-26 23:55:29227
morritab4472142015-04-20 21:20:12228 ClearChannel();
initial.commit09911bf2008-07-26 23:55:29229
230 // Balance with the reference taken during startup. This may result in
231 // self-destruction.
232 Release();
233}
234
[email protected]772a5b22012-08-09 20:39:12235void ChannelProxy::Context::Clear() {
236 listener_ = NULL;
237}
238
initial.commit09911bf2008-07-26 23:55:29239// Called on the IPC::Channel thread
danakj03de39b22016-04-23 04:21:09240void ChannelProxy::Context::OnSendMessage(std::unique_ptr<Message> message) {
pkasting2053ce22015-04-15 06:10:09241 // TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
242 tracked_objects::ScopedTracker tracking_profile(
243 FROM_HERE_WITH_EXPLICIT_FUNCTION(
244 "477117 ChannelProxy::Context::OnSendMessage"));
[email protected]7e3d7522014-03-20 21:00:50245 if (!channel_) {
[email protected]87339f02010-09-02 21:45:50246 OnChannelClosed();
247 return;
248 }
[email protected]7e3d7522014-03-20 21:00:50249
[email protected]f729d15a2012-04-28 02:12:00250 if (!channel_->Send(message.release()))
initial.commit09911bf2008-07-26 23:55:29251 OnChannelError();
252}
253
254// Called on the IPC::Channel thread
[email protected]4b580bf2010-12-02 19:16:07255void ChannelProxy::Context::OnAddFilter() {
[email protected]7e3d7522014-03-20 21:00:50256 // Our OnChannelConnected method has not yet been called, so we can't be
257 // sure that channel_ is valid yet. When OnChannelConnected *is* called,
258 // it invokes OnAddFilter, so any pending filter(s) will be added at that
259 // time.
amistry78ef5f1b2016-07-19 02:52:31260 // No lock necessary for |peer_pid_| because it is only modified on this
261 // thread.
[email protected]7e3d7522014-03-20 21:00:50262 if (peer_pid_ == base::kNullProcessId)
263 return;
264
[email protected]413889302011-08-16 22:12:39265 std::vector<scoped_refptr<MessageFilter> > new_filters;
[email protected]4b580bf2010-12-02 19:16:07266 {
[email protected]20305ec2011-01-21 04:55:52267 base::AutoLock auto_lock(pending_filters_lock_);
[email protected]413889302011-08-16 22:12:39268 new_filters.swap(pending_filters_);
[email protected]4b580bf2010-12-02 19:16:07269 }
initial.commit09911bf2008-07-26 23:55:29270
[email protected]413889302011-08-16 22:12:39271 for (size_t i = 0; i < new_filters.size(); ++i) {
272 filters_.push_back(new_filters[i]);
[email protected]4b580bf2010-12-02 19:16:07273
[email protected]b51352a2014-02-26 05:18:04274 message_filter_router_->AddFilter(new_filters[i].get());
275
[email protected]7e3d7522014-03-20 21:00:50276 // The channel has already been created and connected, so we need to
277 // inform the filters right now.
278 new_filters[i]->OnFilterAdded(channel_.get());
279 new_filters[i]->OnChannelConnected(peer_pid_);
[email protected]4b580bf2010-12-02 19:16:07280 }
initial.commit09911bf2008-07-26 23:55:29281}
282
283// Called on the IPC::Channel thread
284void ChannelProxy::Context::OnRemoveFilter(MessageFilter* filter) {
amistry78ef5f1b2016-07-19 02:52:31285 // No lock necessary for |peer_pid_| because it is only modified on this
286 // thread.
[email protected]7e3d7522014-03-20 21:00:50287 if (peer_pid_ == base::kNullProcessId) {
288 // The channel is not yet connected, so any filters are still pending.
289 base::AutoLock auto_lock(pending_filters_lock_);
290 for (size_t i = 0; i < pending_filters_.size(); ++i) {
291 if (pending_filters_[i].get() == filter) {
292 filter->OnFilterRemoved();
293 pending_filters_.erase(pending_filters_.begin() + i);
294 return;
295 }
296 }
297 return;
298 }
299 if (!channel_)
[email protected]6d057a0c2013-07-09 21:12:07300 return; // The filters have already been deleted.
301
[email protected]b51352a2014-02-26 05:18:04302 message_filter_router_->RemoveFilter(filter);
303
initial.commit09911bf2008-07-26 23:55:29304 for (size_t i = 0; i < filters_.size(); ++i) {
305 if (filters_[i].get() == filter) {
306 filter->OnFilterRemoved();
307 filters_.erase(filters_.begin() + i);
308 return;
309 }
310 }
311
312 NOTREACHED() << "filter to be removed not found";
313}
314
315// Called on the listener's thread
[email protected]4b580bf2010-12-02 19:16:07316void ChannelProxy::Context::AddFilter(MessageFilter* filter) {
[email protected]20305ec2011-01-21 04:55:52317 base::AutoLock auto_lock(pending_filters_lock_);
[email protected]4b580bf2010-12-02 19:16:07318 pending_filters_.push_back(make_scoped_refptr(filter));
[email protected]b2432302012-07-02 21:15:52319 ipc_task_runner_->PostTask(
[email protected]72b6f8e22011-11-12 21:16:41320 FROM_HERE, base::Bind(&Context::OnAddFilter, this));
[email protected]4b580bf2010-12-02 19:16:07321}
322
323// Called on the listener's thread
initial.commit09911bf2008-07-26 23:55:29324void ChannelProxy::Context::OnDispatchMessage(const Message& message) {
325 if (!listener_)
326 return;
327
[email protected]827ab812009-03-12 07:17:17328 OnDispatchConnected();
329
initial.commit09911bf2008-07-26 23:55:29330#ifdef IPC_MESSAGE_LOG_ENABLED
ssid6c1dc892016-03-28 19:56:49331 Logging* logger = Logging::GetInstance();
initial.commit09911bf2008-07-26 23:55:29332 if (message.type() == IPC_LOGGING_ID) {
333 logger->OnReceivedLoggingMessage(message);
334 return;
335 }
336
337 if (logger->Enabled())
338 logger->OnPreDispatchMessage(message);
339#endif
340
341 listener_->OnMessageReceived(message);
[email protected]ef2f6ba2014-05-15 23:06:07342 if (message.dispatch_error())
343 listener_->OnBadMessageReceived(message);
initial.commit09911bf2008-07-26 23:55:29344
345#ifdef IPC_MESSAGE_LOG_ENABLED
346 if (logger->Enabled())
347 logger->OnPostDispatchMessage(message, channel_id_);
348#endif
349}
350
351// Called on the listener's thread
[email protected]827ab812009-03-12 07:17:17352void ChannelProxy::Context::OnDispatchConnected() {
353 if (channel_connected_called_)
354 return;
355
amistry78ef5f1b2016-07-19 02:52:31356 base::ProcessId peer_pid;
357 {
358 base::AutoLock l(peer_pid_lock_);
359 peer_pid = peer_pid_;
360 }
[email protected]827ab812009-03-12 07:17:17361 channel_connected_called_ = true;
initial.commit09911bf2008-07-26 23:55:29362 if (listener_)
amistry78ef5f1b2016-07-19 02:52:31363 listener_->OnChannelConnected(peer_pid);
initial.commit09911bf2008-07-26 23:55:29364}
365
366// Called on the listener's thread
367void ChannelProxy::Context::OnDispatchError() {
368 if (listener_)
369 listener_->OnChannelError();
370}
371
[email protected]ef2f6ba2014-05-15 23:06:07372// Called on the listener's thread
373void ChannelProxy::Context::OnDispatchBadMessage(const Message& message) {
374 if (listener_)
375 listener_->OnBadMessageReceived(message);
376}
377
rockotf62002a2016-09-15 00:08:59378// Called on the listener's thread
379void ChannelProxy::Context::OnDispatchAssociatedInterfaceRequest(
380 const std::string& interface_name,
381 mojo::ScopedInterfaceEndpointHandle handle) {
382 if (listener_)
383 listener_->OnAssociatedInterfaceRequest(interface_name, std::move(handle));
384}
385
morritab4472142015-04-20 21:20:12386void ChannelProxy::Context::ClearChannel() {
387 base::AutoLock l(channel_lifetime_lock_);
388 channel_.reset();
rockot0e4de5f2016-07-22 21:18:07389 associated_group_ = mojo::AssociatedGroup();
390}
391
392void ChannelProxy::Context::AddGenericAssociatedInterface(
393 const std::string& name,
394 const GenericAssociatedInterfaceFactory& factory) {
395 AddGenericAssociatedInterfaceForIOThread(
396 name, base::Bind(&BindAssociatedInterfaceOnTaskRunner,
397 listener_task_runner_, factory));
398}
399
400void ChannelProxy::Context::AddGenericAssociatedInterfaceForIOThread(
401 const std::string& name,
402 const GenericAssociatedInterfaceFactory& factory) {
403 base::AutoLock l(channel_lifetime_lock_);
404 if (!channel_) {
405 base::AutoLock l(pending_filters_lock_);
406 pending_interfaces_.emplace_back(name, factory);
407 return;
408 }
409 Channel::AssociatedInterfaceSupport* support =
410 channel_->GetAssociatedInterfaceSupport();
411 DCHECK(support);
412 support->AddGenericAssociatedInterface(name, factory);
morritab4472142015-04-20 21:20:12413}
414
rockotf14a8ae2016-06-16 19:28:41415void ChannelProxy::Context::SendFromThisThread(Message* message) {
416 base::AutoLock l(channel_lifetime_lock_);
417 if (!channel_)
418 return;
419 DCHECK(channel_->IsSendThreadSafe());
420 channel_->Send(message);
421}
422
423void ChannelProxy::Context::Send(Message* message) {
424 if (channel_send_thread_safe_) {
425 SendFromThisThread(message);
426 return;
morritab4472142015-04-20 21:20:12427 }
428
429 ipc_task_runner()->PostTask(
430 FROM_HERE, base::Bind(&ChannelProxy::Context::OnSendMessage, this,
rockotf14a8ae2016-06-16 19:28:41431 base::Passed(base::WrapUnique(message))));
morritab4472142015-04-20 21:20:12432}
433
rockotac64ae92f2015-08-06 00:32:29434bool ChannelProxy::Context::IsChannelSendThreadSafe() const {
435 return channel_send_thread_safe_;
436}
437
rockot8d890f62016-07-14 16:37:14438// Called on the IPC::Channel thread
439void ChannelProxy::Context::GetRemoteAssociatedInterface(
440 const std::string& name,
441 mojo::ScopedInterfaceEndpointHandle handle) {
442 if (!channel_)
443 return;
444 Channel::AssociatedInterfaceSupport* associated_interface_support =
445 channel_->GetAssociatedInterfaceSupport();
446 DCHECK(associated_interface_support);
447 associated_interface_support->GetGenericRemoteAssociatedInterface(
448 name, std::move(handle));
449}
450
initial.commit09911bf2008-07-26 23:55:29451//-----------------------------------------------------------------------------
452
[email protected]fca876a12014-06-05 16:15:38453// static
danakj03de39b22016-04-23 04:21:09454std::unique_ptr<ChannelProxy> ChannelProxy::Create(
[email protected]fca876a12014-06-05 16:15:38455 const IPC::ChannelHandle& channel_handle,
456 Channel::Mode mode,
457 Listener* listener,
erikchen30dc2812015-09-24 03:26:38458 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
danakj03de39b22016-04-23 04:21:09459 std::unique_ptr<ChannelProxy> channel(
460 new ChannelProxy(listener, ipc_task_runner));
erikchen30dc2812015-09-24 03:26:38461 channel->Init(channel_handle, mode, true);
dchenge48600452015-12-28 02:24:50462 return channel;
initial.commit09911bf2008-07-26 23:55:29463}
464
[email protected]64860882014-08-04 23:44:17465// static
danakj03de39b22016-04-23 04:21:09466std::unique_ptr<ChannelProxy> ChannelProxy::Create(
467 std::unique_ptr<ChannelFactory> factory,
[email protected]64860882014-08-04 23:44:17468 Listener* listener,
dchengfd033702014-08-28 16:59:29469 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
danakj03de39b22016-04-23 04:21:09470 std::unique_ptr<ChannelProxy> channel(
471 new ChannelProxy(listener, ipc_task_runner));
dchenge48600452015-12-28 02:24:50472 channel->Init(std::move(factory), true);
473 return channel;
[email protected]64860882014-08-04 23:44:17474}
475
[email protected]952394af2011-11-16 01:06:46476ChannelProxy::ChannelProxy(Context* context)
rockota34707ca2016-07-20 04:28:32477 : context_(context), did_init_(false) {
mbarbellae97877bc2015-03-06 21:51:14478#if defined(ENABLE_IPC_FUZZER)
479 outgoing_message_filter_ = NULL;
480#endif
initial.commit09911bf2008-07-26 23:55:29481}
482
dchengfd033702014-08-28 16:59:29483ChannelProxy::ChannelProxy(
484 Listener* listener,
485 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner)
rockotf14a8ae2016-06-16 19:28:41486 : context_(new Context(listener, ipc_task_runner)), did_init_(false) {
487#if defined(ENABLE_IPC_FUZZER)
488 outgoing_message_filter_ = NULL;
489#endif
490}
[email protected]fca876a12014-06-05 16:15:38491
[email protected]dec76e802010-09-23 22:43:53492ChannelProxy::~ChannelProxy() {
[email protected]f775d102012-12-05 01:00:36493 DCHECK(CalledOnValidThread());
494
[email protected]dec76e802010-09-23 22:43:53495 Close();
496}
497
[email protected]3b0e4662014-06-02 20:29:30498void ChannelProxy::Init(const IPC::ChannelHandle& channel_handle,
499 Channel::Mode mode,
rockot10188752016-09-08 18:24:56500 bool create_pipe_now) {
[email protected]42ce94e2010-12-08 19:28:09501#if defined(OS_POSIX)
502 // When we are creating a server on POSIX, we need its file descriptor
503 // to be created immediately so that it can be accessed and passed
504 // to other processes. Forcing it to be created immediately avoids
505 // race conditions that may otherwise arise.
[email protected]1707726c2011-02-03 20:35:09506 if (mode & Channel::MODE_SERVER_FLAG) {
[email protected]42ce94e2010-12-08 19:28:09507 create_pipe_now = true;
508 }
509#endif // defined(OS_POSIX)
rockota34707ca2016-07-20 04:28:32510 Init(
511 ChannelFactory::Create(channel_handle, mode, context_->ipc_task_runner()),
rockot10188752016-09-08 18:24:56512 create_pipe_now);
[email protected]64860882014-08-04 23:44:17513}
514
danakj03de39b22016-04-23 04:21:09515void ChannelProxy::Init(std::unique_ptr<ChannelFactory> factory,
rockot10188752016-09-08 18:24:56516 bool create_pipe_now) {
[email protected]64860882014-08-04 23:44:17517 DCHECK(CalledOnValidThread());
518 DCHECK(!did_init_);
[email protected]42ce94e2010-12-08 19:28:09519
initial.commit09911bf2008-07-26 23:55:29520 if (create_pipe_now) {
521 // Create the channel immediately. This effectively sets up the
522 // low-level pipe so that the client can connect. Without creating
523 // the pipe immediately, it is possible for a listener to attempt
524 // to connect and get an error since the pipe doesn't exist yet.
dchenge48600452015-12-28 02:24:50525 context_->CreateChannel(std::move(factory));
initial.commit09911bf2008-07-26 23:55:29526 } else {
[email protected]b2432302012-07-02 21:15:52527 context_->ipc_task_runner()->PostTask(
tzik07cace42016-09-01 04:21:25528 FROM_HERE, base::Bind(&Context::CreateChannel, context_,
dcheng0917ec42015-11-19 07:00:20529 base::Passed(&factory)));
initial.commit09911bf2008-07-26 23:55:29530 }
531
532 // complete initialization on the background thread
[email protected]b2432302012-07-02 21:15:52533 context_->ipc_task_runner()->PostTask(
rockot401fb2c2016-09-06 18:35:57534 FROM_HERE,
rockot10188752016-09-08 18:24:56535 base::Bind(&Context::OnChannelOpened, context_));
[email protected]952394af2011-11-16 01:06:46536
537 did_init_ = true;
rockot29ade1b2015-08-07 06:23:59538 OnChannelInit();
initial.commit09911bf2008-07-26 23:55:29539}
540
rockot10188752016-09-08 18:24:56541void ChannelProxy::Pause() {
542 context_->ipc_task_runner()->PostTask(
543 FROM_HERE, base::Bind(&Context::PauseChannel, context_));
544}
545
rockot401fb2c2016-09-06 18:35:57546void ChannelProxy::Unpause(bool flush) {
547 context_->ipc_task_runner()->PostTask(
548 FROM_HERE, base::Bind(&Context::UnpauseChannel, context_, flush));
549}
550
551void ChannelProxy::Flush() {
552 context_->ipc_task_runner()->PostTask(
553 FROM_HERE, base::Bind(&Context::FlushChannel, context_));
554}
555
initial.commit09911bf2008-07-26 23:55:29556void ChannelProxy::Close() {
[email protected]f775d102012-12-05 01:00:36557 DCHECK(CalledOnValidThread());
558
initial.commit09911bf2008-07-26 23:55:29559 // Clear the backpointer to the listener so that any pending calls to
560 // Context::OnDispatchMessage or OnDispatchError will be ignored. It is
561 // possible that the channel could be closed while it is receiving messages!
[email protected]3cdb7af812008-10-24 19:21:13562 context_->Clear();
initial.commit09911bf2008-07-26 23:55:29563
[email protected]b2432302012-07-02 21:15:52564 if (context_->ipc_task_runner()) {
565 context_->ipc_task_runner()->PostTask(
tzik07cace42016-09-01 04:21:25566 FROM_HERE, base::Bind(&Context::OnChannelClosed, context_));
initial.commit09911bf2008-07-26 23:55:29567 }
568}
569
570bool ChannelProxy::Send(Message* message) {
rockotf14a8ae2016-06-16 19:28:41571 DCHECK(did_init_);
[email protected]f775d102012-12-05 01:00:36572
rockotf14a8ae2016-06-16 19:28:41573 // TODO(alexeypa): add DCHECK(CalledOnValidThread()) here. Currently there are
574 // tests that call Send() from a wrong thread. See http://crbug.com/163523.
[email protected]89480312011-05-04 17:14:16575
rockotf14a8ae2016-06-16 19:28:41576#ifdef ENABLE_IPC_FUZZER
577 // In IPC fuzzing builds, it is possible to define a filter to apply to
578 // outgoing messages. It will either rewrite the message and return a new
579 // one, freeing the original, or return the message unchanged.
580 if (outgoing_message_filter())
581 message = outgoing_message_filter()->Rewrite(message);
582#endif
583
584#ifdef IPC_MESSAGE_LOG_ENABLED
585 Logging::GetInstance()->OnSendMessage(message, context_->channel_id());
586#endif
587
588 context_->Send(message);
589 return true;
initial.commit09911bf2008-07-26 23:55:29590}
591
592void ChannelProxy::AddFilter(MessageFilter* filter) {
[email protected]f775d102012-12-05 01:00:36593 DCHECK(CalledOnValidThread());
594
[email protected]4b580bf2010-12-02 19:16:07595 context_->AddFilter(filter);
initial.commit09911bf2008-07-26 23:55:29596}
597
598void ChannelProxy::RemoveFilter(MessageFilter* filter) {
[email protected]f775d102012-12-05 01:00:36599 DCHECK(CalledOnValidThread());
600
[email protected]b2432302012-07-02 21:15:52601 context_->ipc_task_runner()->PostTask(
tzik07cace42016-09-01 04:21:25602 FROM_HERE, base::Bind(&Context::OnRemoveFilter, context_,
vmpstra34d11322016-03-21 20:28:47603 base::RetainedRef(filter)));
initial.commit09911bf2008-07-26 23:55:29604}
605
msramek5507fee2016-07-22 10:06:21606void ChannelProxy::AddGenericAssociatedInterface(
607 const std::string& name,
608 const GenericAssociatedInterfaceFactory& factory) {
rockot0e4de5f2016-07-22 21:18:07609 context()->AddGenericAssociatedInterface(name, factory);
610}
611
612void ChannelProxy::AddGenericAssociatedInterfaceForIOThread(
613 const std::string& name,
614 const GenericAssociatedInterfaceFactory& factory) {
615 context()->AddGenericAssociatedInterfaceForIOThread(name, factory);
rockot8d890f62016-07-14 16:37:14616}
617
618mojo::AssociatedGroup* ChannelProxy::GetAssociatedGroup() {
rockot0e4de5f2016-07-22 21:18:07619 return context()->associated_group();
rockot8d890f62016-07-14 16:37:14620}
621
622void ChannelProxy::GetGenericRemoteAssociatedInterface(
623 const std::string& name,
624 mojo::ScopedInterfaceEndpointHandle handle) {
rockot5a908952016-07-28 20:08:17625 DCHECK(did_init_);
rockot8d890f62016-07-14 16:37:14626 context_->ipc_task_runner()->PostTask(
627 FROM_HERE, base::Bind(&Context::GetRemoteAssociatedInterface,
tzik07cace42016-09-01 04:21:25628 context_, name, base::Passed(&handle)));
rockot8d890f62016-07-14 16:37:14629}
630
[email protected]b2432302012-07-02 21:15:52631void ChannelProxy::ClearIPCTaskRunner() {
[email protected]f775d102012-12-05 01:00:36632 DCHECK(CalledOnValidThread());
633
[email protected]b2432302012-07-02 21:15:52634 context()->ClearIPCTaskRunner();
[email protected]42f1d7822009-07-23 18:17:55635}
636
erikchena09b9be72015-08-10 19:22:33637base::ProcessId ChannelProxy::GetPeerPID() const {
amistry78ef5f1b2016-07-19 02:52:31638 base::AutoLock l(context_->peer_pid_lock_);
erikchena09b9be72015-08-10 19:22:33639 return context_->peer_pid_;
640}
641
642void ChannelProxy::OnSetAttachmentBrokerEndpoint() {
erikchen90971902016-04-25 23:45:31643 CHECK(!did_init_);
erikchena09b9be72015-08-10 19:22:33644 context()->set_attachment_broker_endpoint(is_attachment_broker_endpoint());
645}
646
hidehikof7295f22014-10-28 11:57:21647#if defined(OS_POSIX) && !defined(OS_NACL_SFI)
[email protected]e74488c2008-12-22 22:43:41648// See the TODO regarding lazy initialization of the channel in
649// ChannelProxy::Init().
[email protected]2ce26c432011-09-19 17:08:12650int ChannelProxy::GetClientFileDescriptor() {
[email protected]f775d102012-12-05 01:00:36651 DCHECK(CalledOnValidThread());
652
[email protected]2ce26c432011-09-19 17:08:12653 Channel* channel = context_.get()->channel_.get();
[email protected]42ce94e2010-12-08 19:28:09654 // Channel must have been created first.
655 DCHECK(channel) << context_.get()->channel_id_;
[email protected]cc8f1462009-06-12 17:36:55656 return channel->GetClientFileDescriptor();
[email protected]e74488c2008-12-22 22:43:41657}
[email protected]8ec3fbe2011-04-06 12:01:44658
morritaa409ccc2014-10-20 23:53:25659base::ScopedFD ChannelProxy::TakeClientFileDescriptor() {
[email protected]f775d102012-12-05 01:00:36660 DCHECK(CalledOnValidThread());
661
[email protected]2ce26c432011-09-19 17:08:12662 Channel* channel = context_.get()->channel_.get();
663 // Channel must have been created first.
664 DCHECK(channel) << context_.get()->channel_id_;
665 return channel->TakeClientFileDescriptor();
666}
[email protected]e74488c2008-12-22 22:43:41667#endif
668
rockot29ade1b2015-08-07 06:23:59669void ChannelProxy::OnChannelInit() {
670}
671
initial.commit09911bf2008-07-26 23:55:29672//-----------------------------------------------------------------------------
673
674} // namespace IPC