blob: c1d6a32cd234f4cef654d166cb0476c2ade842ef [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"
[email protected]b2432302012-07-02 21:15:5217#include "base/single_thread_task_runner.h"
gabf08ccc02016-05-11 18:51:1118#include "base/threading/thread_task_runner_handle.h"
avi246998d82015-12-22 02:39:0419#include "build/build_config.h"
[email protected]64860882014-08-04 23:44:1720#include "ipc/ipc_channel_factory.h"
[email protected]57319ce2012-06-11 22:35:2621#include "ipc/ipc_listener.h"
[email protected]946d1b22009-07-22 23:57:2122#include "ipc/ipc_logging.h"
[email protected]9ec16852012-05-11 23:24:3723#include "ipc/ipc_message_macros.h"
[email protected]74122042014-04-25 00:07:3024#include "ipc/message_filter.h"
25#include "ipc/message_filter_router.h"
Julie Jeongeun Kim69604f62019-12-04 01:59:5226#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
initial.commit09911bf2008-07-26 23:55:2927
28namespace IPC {
29
[email protected]163951422009-07-28 22:09:4530//------------------------------------------------------------------------------
initial.commit09911bf2008-07-26 23:55:2931
dchengfd033702014-08-28 16:59:2932ChannelProxy::Context::Context(
33 Listener* listener,
Hajime Hoshiff15e972017-11-09 06:37:0934 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
35 const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner)
Yuzu Saijo8866b1d2019-05-24 03:23:2836 : default_listener_task_runner_(listener_task_runner),
initial.commit09911bf2008-07-26 23:55:2937 listener_(listener),
[email protected]b2432302012-07-02 21:15:5238 ipc_task_runner_(ipc_task_runner),
[email protected]0a6fc4b2012-04-05 02:38:3439 channel_connected_called_(false),
[email protected]b51352a2014-02-26 05:18:0440 message_filter_router_(new MessageFilterRouter()),
sammcf810f07f2016-11-10 22:34:0741 peer_pid_(base::kNullProcessId) {
[email protected]17571642013-06-01 04:11:2742 DCHECK(ipc_task_runner_.get());
[email protected]1f9cf472014-04-17 05:07:1843 // The Listener thread where Messages are handled must be a separate thread
44 // to avoid oversubscribing the IO thread. If you trigger this error, you
45 // need to either:
46 // 1) Create the ChannelProxy on a different thread, or
47 // 2) Just use Channel
48 // Note, we currently make an exception for a NULL listener. That usage
49 // basically works, but is outside the intent of ChannelProxy. This support
50 // will disappear, so please don't rely on it. See crbug.com/364241
Yuzu Saijo8866b1d2019-05-24 03:23:2851 DCHECK(!listener ||
52 (ipc_task_runner_.get() != default_listener_task_runner_.get()));
initial.commit09911bf2008-07-26 23:55:2953}
54
Chris Watkins2d879af2017-11-30 02:11:5955ChannelProxy::Context::~Context() = default;
[email protected]92bf9062011-05-02 18:00:4956
[email protected]b2432302012-07-02 21:15:5257void ChannelProxy::Context::ClearIPCTaskRunner() {
kylechar07bacf52019-11-15 15:37:1458 ipc_task_runner_.reset();
[email protected]b2432302012-07-02 21:15:5259}
60
danakj03de39b22016-04-23 04:21:0961void ChannelProxy::Context::CreateChannel(
62 std::unique_ptr<ChannelFactory> factory) {
morritab4472142015-04-20 21:20:1263 base::AutoLock l(channel_lifetime_lock_);
[email protected]7e3d7522014-03-20 21:00:5064 DCHECK(!channel_);
rockota34707ca2016-07-20 04:28:3265 DCHECK_EQ(factory->GetIPCTaskRunner(), ipc_task_runner_);
[email protected]64860882014-08-04 23:44:1766 channel_ = factory->BuildChannel(this);
rockot0e4de5f2016-07-22 21:18:0767
68 Channel::AssociatedInterfaceSupport* support =
69 channel_->GetAssociatedInterfaceSupport();
70 if (support) {
rockota628d0b2017-02-09 08:40:1571 thread_safe_channel_ = support->CreateThreadSafeChannel();
rockot0e4de5f2016-07-22 21:18:0772
73 base::AutoLock l(pending_filters_lock_);
rockot70bbb59492017-01-25 00:56:5174 for (auto& entry : pending_io_thread_interfaces_)
rockot0e4de5f2016-07-22 21:18:0775 support->AddGenericAssociatedInterface(entry.first, entry.second);
rockot70bbb59492017-01-25 00:56:5176 pending_io_thread_interfaces_.clear();
rockot0e4de5f2016-07-22 21:18:0777 }
initial.commit09911bf2008-07-26 23:55:2978}
79
[email protected]d65cab7a2008-08-12 01:25:4180bool ChannelProxy::Context::TryFilters(const Message& message) {
[email protected]b51352a2014-02-26 05:18:0481 DCHECK(message_filter_router_);
davidsz041528a2017-05-12 09:19:2382#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
[email protected]8e8bb6d2010-12-13 08:18:5583 Logging* logger = Logging::GetInstance();
initial.commit09911bf2008-07-26 23:55:2984 if (logger->Enabled())
85 logger->OnPreDispatchMessage(message);
86#endif
87
[email protected]b51352a2014-02-26 05:18:0488 if (message_filter_router_->TryFilters(message)) {
[email protected]ef2f6ba2014-05-15 23:06:0789 if (message.dispatch_error()) {
Yuzu Saijo8866b1d2019-05-24 03:23:2890 GetTaskRunner(message.routing_id())
91 ->PostTask(FROM_HERE, base::BindOnce(&Context::OnDispatchBadMessage,
92 this, message));
[email protected]ef2f6ba2014-05-15 23:06:0793 }
davidsz041528a2017-05-12 09:19:2394#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
[email protected]b51352a2014-02-26 05:18:0495 if (logger->Enabled())
sammca1b3b4d2016-11-15 00:34:3696 logger->OnPostDispatchMessage(message);
initial.commit09911bf2008-07-26 23:55:2997#endif
[email protected]b51352a2014-02-26 05:18:0498 return true;
initial.commit09911bf2008-07-26 23:55:2999 }
[email protected]d65cab7a2008-08-12 01:25:41100 return false;
101}
102
103// Called on the IPC::Channel thread
rockot10188752016-09-08 18:24:56104void ChannelProxy::Context::PauseChannel() {
105 DCHECK(channel_);
106 channel_->Pause();
107}
108
109// Called on the IPC::Channel thread
rockot401fb2c2016-09-06 18:35:57110void ChannelProxy::Context::UnpauseChannel(bool flush) {
111 DCHECK(channel_);
112 channel_->Unpause(flush);
113}
114
115// Called on the IPC::Channel thread
116void ChannelProxy::Context::FlushChannel() {
117 DCHECK(channel_);
118 channel_->Flush();
119}
120
121// Called on the IPC::Channel thread
[email protected]a95986a82010-12-24 06:19:28122bool ChannelProxy::Context::OnMessageReceived(const Message& message) {
[email protected]d65cab7a2008-08-12 01:25:41123 // First give a chance to the filters to process this message.
[email protected]3cdb7af812008-10-24 19:21:13124 if (!TryFilters(message))
125 OnMessageReceivedNoFilter(message);
[email protected]a95986a82010-12-24 06:19:28126 return true;
[email protected]3cdb7af812008-10-24 19:21:13127}
initial.commit09911bf2008-07-26 23:55:29128
[email protected]3cdb7af812008-10-24 19:21:13129// Called on the IPC::Channel thread
[email protected]a95986a82010-12-24 06:19:28130bool ChannelProxy::Context::OnMessageReceivedNoFilter(const Message& message) {
Yuzu Saijo8866b1d2019-05-24 03:23:28131 GetTaskRunner(message.routing_id())
132 ->PostTask(FROM_HERE,
133 base::BindOnce(&Context::OnDispatchMessage, this, message));
[email protected]a95986a82010-12-24 06:19:28134 return true;
initial.commit09911bf2008-07-26 23:55:29135}
136
137// Called on the IPC::Channel thread
tfarina10a5c062015-09-04 18:47:57138void ChannelProxy::Context::OnChannelConnected(int32_t peer_pid) {
[email protected]7e3d7522014-03-20 21:00:50139 // We cache off the peer_pid so it can be safely accessed from both threads.
amistry78ef5f1b2016-07-19 02:52:31140 {
141 base::AutoLock l(peer_pid_lock_);
sammcf810f07f2016-11-10 22:34:07142 peer_pid_ = peer_pid;
amistry78ef5f1b2016-07-19 02:52:31143 }
[email protected]7e3d7522014-03-20 21:00:50144
[email protected]4b580bf2010-12-02 19:16:07145 // Add any pending filters. This avoids a race condition where someone
146 // creates a ChannelProxy, calls AddFilter, and then right after starts the
147 // peer process. The IO thread could receive a message before the task to add
148 // the filter is run on the IO thread.
149 OnAddFilter();
150
Yuzu Saijo8866b1d2019-05-24 03:23:28151 // See above comment about using default_listener_task_runner_ here.
152 default_listener_task_runner_->PostTask(
kylecharf448cc92019-02-19 20:28:09153 FROM_HERE, base::BindOnce(&Context::OnDispatchConnected, this));
initial.commit09911bf2008-07-26 23:55:29154}
155
156// Called on the IPC::Channel thread
157void ChannelProxy::Context::OnChannelError() {
[email protected]5fa1c542009-05-05 20:36:07158 for (size_t i = 0; i < filters_.size(); ++i)
159 filters_[i]->OnChannelError();
160
Yuzu Saijo8866b1d2019-05-24 03:23:28161 // See above comment about using default_listener_task_runner_ here.
162 default_listener_task_runner_->PostTask(
kylecharf448cc92019-02-19 20:28:09163 FROM_HERE, base::BindOnce(&Context::OnDispatchError, this));
initial.commit09911bf2008-07-26 23:55:29164}
165
166// Called on the IPC::Channel thread
rockotf62002a2016-09-15 00:08:59167void ChannelProxy::Context::OnAssociatedInterfaceRequest(
168 const std::string& interface_name,
169 mojo::ScopedInterfaceEndpointHandle handle) {
Yuzu Saijo8866b1d2019-05-24 03:23:28170 default_listener_task_runner_->PostTask(
kylecharf448cc92019-02-19 20:28:09171 FROM_HERE, base::BindOnce(&Context::OnDispatchAssociatedInterfaceRequest,
172 this, interface_name, std::move(handle)));
rockotf62002a2016-09-15 00:08:59173}
174
175// Called on the IPC::Channel thread
rockot10188752016-09-08 18:24:56176void ChannelProxy::Context::OnChannelOpened() {
initial.commit09911bf2008-07-26 23:55:29177 DCHECK(channel_ != NULL);
178
179 // Assume a reference to ourselves on behalf of this thread. This reference
180 // will be released when we are closed.
181 AddRef();
182
rockot10188752016-09-08 18:24:56183 if (!channel_->Connect()) {
initial.commit09911bf2008-07-26 23:55:29184 OnChannelError();
185 return;
186 }
187
188 for (size_t i = 0; i < filters_.size(); ++i)
[email protected]42ce94e2010-12-08 19:28:09189 filters_[i]->OnFilterAdded(channel_.get());
initial.commit09911bf2008-07-26 23:55:29190}
191
192// Called on the IPC::Channel thread
[email protected]3cdb7af812008-10-24 19:21:13193void ChannelProxy::Context::OnChannelClosed() {
initial.commit09911bf2008-07-26 23:55:29194 // It's okay for IPC::ChannelProxy::Close to be called more than once, which
195 // would result in this branch being taken.
[email protected]7e3d7522014-03-20 21:00:50196 if (!channel_)
initial.commit09911bf2008-07-26 23:55:29197 return;
198
tzik0e85f1d2016-11-05 09:26:44199 for (auto& filter : pending_filters_) {
200 filter->OnChannelClosing();
201 filter->OnFilterRemoved();
202 }
203 for (auto& filter : filters_) {
204 filter->OnChannelClosing();
205 filter->OnFilterRemoved();
initial.commit09911bf2008-07-26 23:55:29206 }
207
208 // We don't need the filters anymore.
[email protected]b51352a2014-02-26 05:18:04209 message_filter_router_->Clear();
initial.commit09911bf2008-07-26 23:55:29210 filters_.clear();
[email protected]7e3d7522014-03-20 21:00:50211 // We don't need the lock, because at this point, the listener thread can't
212 // access it any more.
213 pending_filters_.clear();
initial.commit09911bf2008-07-26 23:55:29214
morritab4472142015-04-20 21:20:12215 ClearChannel();
initial.commit09911bf2008-07-26 23:55:29216
217 // Balance with the reference taken during startup. This may result in
218 // self-destruction.
219 Release();
220}
221
[email protected]772a5b22012-08-09 20:39:12222void ChannelProxy::Context::Clear() {
223 listener_ = NULL;
224}
225
initial.commit09911bf2008-07-26 23:55:29226// Called on the IPC::Channel thread
Etienne Bergeron0a07d73d2019-06-27 16:40:47227void ChannelProxy::Context::OnSendMessage(std::unique_ptr<Message> message) {
Sigurdur Asgeirssond655dd65f2019-11-12 19:32:20228 if (quota_checker_)
229 quota_checker_->AfterMessagesDequeued(1);
230
[email protected]7e3d7522014-03-20 21:00:50231 if (!channel_) {
[email protected]87339f02010-09-02 21:45:50232 OnChannelClosed();
233 return;
234 }
[email protected]7e3d7522014-03-20 21:00:50235
[email protected]f729d15a2012-04-28 02:12:00236 if (!channel_->Send(message.release()))
initial.commit09911bf2008-07-26 23:55:29237 OnChannelError();
238}
239
240// Called on the IPC::Channel thread
[email protected]4b580bf2010-12-02 19:16:07241void ChannelProxy::Context::OnAddFilter() {
[email protected]7e3d7522014-03-20 21:00:50242 // Our OnChannelConnected method has not yet been called, so we can't be
243 // sure that channel_ is valid yet. When OnChannelConnected *is* called,
244 // it invokes OnAddFilter, so any pending filter(s) will be added at that
245 // time.
amistry78ef5f1b2016-07-19 02:52:31246 // No lock necessary for |peer_pid_| because it is only modified on this
247 // thread.
[email protected]7e3d7522014-03-20 21:00:50248 if (peer_pid_ == base::kNullProcessId)
249 return;
250
[email protected]413889302011-08-16 22:12:39251 std::vector<scoped_refptr<MessageFilter> > new_filters;
[email protected]4b580bf2010-12-02 19:16:07252 {
[email protected]20305ec2011-01-21 04:55:52253 base::AutoLock auto_lock(pending_filters_lock_);
[email protected]413889302011-08-16 22:12:39254 new_filters.swap(pending_filters_);
[email protected]4b580bf2010-12-02 19:16:07255 }
initial.commit09911bf2008-07-26 23:55:29256
[email protected]413889302011-08-16 22:12:39257 for (size_t i = 0; i < new_filters.size(); ++i) {
258 filters_.push_back(new_filters[i]);
[email protected]4b580bf2010-12-02 19:16:07259
[email protected]b51352a2014-02-26 05:18:04260 message_filter_router_->AddFilter(new_filters[i].get());
261
[email protected]7e3d7522014-03-20 21:00:50262 // The channel has already been created and connected, so we need to
263 // inform the filters right now.
264 new_filters[i]->OnFilterAdded(channel_.get());
265 new_filters[i]->OnChannelConnected(peer_pid_);
[email protected]4b580bf2010-12-02 19:16:07266 }
initial.commit09911bf2008-07-26 23:55:29267}
268
269// Called on the IPC::Channel thread
270void ChannelProxy::Context::OnRemoveFilter(MessageFilter* filter) {
amistry78ef5f1b2016-07-19 02:52:31271 // No lock necessary for |peer_pid_| because it is only modified on this
272 // thread.
[email protected]7e3d7522014-03-20 21:00:50273 if (peer_pid_ == base::kNullProcessId) {
274 // The channel is not yet connected, so any filters are still pending.
275 base::AutoLock auto_lock(pending_filters_lock_);
276 for (size_t i = 0; i < pending_filters_.size(); ++i) {
277 if (pending_filters_[i].get() == filter) {
278 filter->OnFilterRemoved();
279 pending_filters_.erase(pending_filters_.begin() + i);
280 return;
281 }
282 }
283 return;
284 }
285 if (!channel_)
[email protected]6d057a0c2013-07-09 21:12:07286 return; // The filters have already been deleted.
287
[email protected]b51352a2014-02-26 05:18:04288 message_filter_router_->RemoveFilter(filter);
289
initial.commit09911bf2008-07-26 23:55:29290 for (size_t i = 0; i < filters_.size(); ++i) {
291 if (filters_[i].get() == filter) {
292 filter->OnFilterRemoved();
293 filters_.erase(filters_.begin() + i);
294 return;
295 }
296 }
297
298 NOTREACHED() << "filter to be removed not found";
299}
300
301// Called on the listener's thread
[email protected]4b580bf2010-12-02 19:16:07302void ChannelProxy::Context::AddFilter(MessageFilter* filter) {
[email protected]20305ec2011-01-21 04:55:52303 base::AutoLock auto_lock(pending_filters_lock_);
kylecharda69d882017-10-04 05:49:52304 pending_filters_.push_back(base::WrapRefCounted(filter));
kylecharf448cc92019-02-19 20:28:09305 ipc_task_runner_->PostTask(FROM_HERE,
306 base::BindOnce(&Context::OnAddFilter, this));
[email protected]4b580bf2010-12-02 19:16:07307}
308
309// Called on the listener's thread
initial.commit09911bf2008-07-26 23:55:29310void ChannelProxy::Context::OnDispatchMessage(const Message& message) {
311 if (!listener_)
312 return;
313
[email protected]827ab812009-03-12 07:17:17314 OnDispatchConnected();
315
davidsz041528a2017-05-12 09:19:23316#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
ssid6c1dc892016-03-28 19:56:49317 Logging* logger = Logging::GetInstance();
initial.commit09911bf2008-07-26 23:55:29318 if (message.type() == IPC_LOGGING_ID) {
319 logger->OnReceivedLoggingMessage(message);
320 return;
321 }
322
323 if (logger->Enabled())
324 logger->OnPreDispatchMessage(message);
325#endif
326
327 listener_->OnMessageReceived(message);
[email protected]ef2f6ba2014-05-15 23:06:07328 if (message.dispatch_error())
329 listener_->OnBadMessageReceived(message);
initial.commit09911bf2008-07-26 23:55:29330
davidsz041528a2017-05-12 09:19:23331#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
initial.commit09911bf2008-07-26 23:55:29332 if (logger->Enabled())
sammca1b3b4d2016-11-15 00:34:36333 logger->OnPostDispatchMessage(message);
initial.commit09911bf2008-07-26 23:55:29334#endif
335}
336
Yuzu Saijo8866b1d2019-05-24 03:23:28337// Called on the listener's thread.
338void ChannelProxy::Context::AddListenerTaskRunner(
339 int32_t routing_id,
340 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
341 DCHECK(default_listener_task_runner_->BelongsToCurrentThread());
342 DCHECK(task_runner);
343 base::AutoLock lock(listener_thread_task_runners_lock_);
Jan Wilken Dörrie0cab5a5ab2019-06-07 09:11:31344 if (!base::Contains(listener_thread_task_runners_, routing_id))
Yuzu Saijo8866b1d2019-05-24 03:23:28345 listener_thread_task_runners_.insert({routing_id, std::move(task_runner)});
346}
347
348// Called on the listener's thread.
349void ChannelProxy::Context::RemoveListenerTaskRunner(int32_t routing_id) {
350 DCHECK(default_listener_task_runner_->BelongsToCurrentThread());
351 base::AutoLock lock(listener_thread_task_runners_lock_);
Yuzu Saijo3b6330012019-07-11 03:51:27352 listener_thread_task_runners_.erase(routing_id);
Yuzu Saijo8866b1d2019-05-24 03:23:28353}
354
355// Called on the IPC::Channel thread.
Yuzu Saijo3b6330012019-07-11 03:51:27356scoped_refptr<base::SingleThreadTaskRunner>
357ChannelProxy::Context::GetTaskRunner(int32_t routing_id) {
Yuzu Saijo8866b1d2019-05-24 03:23:28358 DCHECK(ipc_task_runner_->BelongsToCurrentThread());
359 if (routing_id == MSG_ROUTING_NONE)
Yuzu Saijo3b6330012019-07-11 03:51:27360 return default_listener_task_runner_;
Yuzu Saijo8866b1d2019-05-24 03:23:28361
362 base::AutoLock lock(listener_thread_task_runners_lock_);
Yuzu Saijo3b6330012019-07-11 03:51:27363 auto task_runner = listener_thread_task_runners_.find(routing_id);
364 if (task_runner == listener_thread_task_runners_.end())
365 return default_listener_task_runner_;
366 DCHECK(task_runner->second);
367 return task_runner->second;
Yuzu Saijo8866b1d2019-05-24 03:23:28368}
369
initial.commit09911bf2008-07-26 23:55:29370// Called on the listener's thread
[email protected]827ab812009-03-12 07:17:17371void ChannelProxy::Context::OnDispatchConnected() {
372 if (channel_connected_called_)
373 return;
374
amistry78ef5f1b2016-07-19 02:52:31375 base::ProcessId peer_pid;
376 {
377 base::AutoLock l(peer_pid_lock_);
378 peer_pid = peer_pid_;
379 }
[email protected]827ab812009-03-12 07:17:17380 channel_connected_called_ = true;
initial.commit09911bf2008-07-26 23:55:29381 if (listener_)
amistry78ef5f1b2016-07-19 02:52:31382 listener_->OnChannelConnected(peer_pid);
initial.commit09911bf2008-07-26 23:55:29383}
384
385// Called on the listener's thread
386void ChannelProxy::Context::OnDispatchError() {
387 if (listener_)
388 listener_->OnChannelError();
389}
390
[email protected]ef2f6ba2014-05-15 23:06:07391// Called on the listener's thread
392void ChannelProxy::Context::OnDispatchBadMessage(const Message& message) {
393 if (listener_)
394 listener_->OnBadMessageReceived(message);
395}
396
rockotf62002a2016-09-15 00:08:59397// Called on the listener's thread
398void ChannelProxy::Context::OnDispatchAssociatedInterfaceRequest(
399 const std::string& interface_name,
400 mojo::ScopedInterfaceEndpointHandle handle) {
401 if (listener_)
402 listener_->OnAssociatedInterfaceRequest(interface_name, std::move(handle));
403}
404
morritab4472142015-04-20 21:20:12405void ChannelProxy::Context::ClearChannel() {
406 base::AutoLock l(channel_lifetime_lock_);
407 channel_.reset();
rockot0e4de5f2016-07-22 21:18:07408}
409
rockot0e4de5f2016-07-22 21:18:07410void ChannelProxy::Context::AddGenericAssociatedInterfaceForIOThread(
411 const std::string& name,
412 const GenericAssociatedInterfaceFactory& factory) {
413 base::AutoLock l(channel_lifetime_lock_);
414 if (!channel_) {
415 base::AutoLock l(pending_filters_lock_);
rockot70bbb59492017-01-25 00:56:51416 pending_io_thread_interfaces_.emplace_back(name, factory);
rockot0e4de5f2016-07-22 21:18:07417 return;
418 }
419 Channel::AssociatedInterfaceSupport* support =
420 channel_->GetAssociatedInterfaceSupport();
rockotfd3d90842016-09-15 23:57:29421 if (support)
422 support->AddGenericAssociatedInterface(name, factory);
morritab4472142015-04-20 21:20:12423}
424
Etienne Bergeron0a07d73d2019-06-27 16:40:47425void ChannelProxy::Context::Send(Message* message) {
Sigurdur Asgeirssond655dd65f2019-11-12 19:32:20426 if (quota_checker_)
427 quota_checker_->BeforeMessagesEnqueued(1);
428
morritab4472142015-04-20 21:20:12429 ipc_task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09430 FROM_HERE, base::BindOnce(&ChannelProxy::Context::OnSendMessage, this,
Etienne Bergeron0a07d73d2019-06-27 16:40:47431 base::WrapUnique(message)));
morritab4472142015-04-20 21:20:12432}
433
initial.commit09911bf2008-07-26 23:55:29434//-----------------------------------------------------------------------------
435
[email protected]fca876a12014-06-05 16:15:38436// static
danakj03de39b22016-04-23 04:21:09437std::unique_ptr<ChannelProxy> ChannelProxy::Create(
[email protected]fca876a12014-06-05 16:15:38438 const IPC::ChannelHandle& channel_handle,
439 Channel::Mode mode,
440 Listener* listener,
Hajime Hoshiff15e972017-11-09 06:37:09441 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
442 const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner) {
danakj03de39b22016-04-23 04:21:09443 std::unique_ptr<ChannelProxy> channel(
Hajime Hoshiff15e972017-11-09 06:37:09444 new ChannelProxy(listener, ipc_task_runner, listener_task_runner));
erikchen30dc2812015-09-24 03:26:38445 channel->Init(channel_handle, mode, true);
dchenge48600452015-12-28 02:24:50446 return channel;
initial.commit09911bf2008-07-26 23:55:29447}
448
[email protected]64860882014-08-04 23:44:17449// static
danakj03de39b22016-04-23 04:21:09450std::unique_ptr<ChannelProxy> ChannelProxy::Create(
451 std::unique_ptr<ChannelFactory> factory,
[email protected]64860882014-08-04 23:44:17452 Listener* listener,
Hajime Hoshiff15e972017-11-09 06:37:09453 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
454 const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner) {
danakj03de39b22016-04-23 04:21:09455 std::unique_ptr<ChannelProxy> channel(
Hajime Hoshiff15e972017-11-09 06:37:09456 new ChannelProxy(listener, ipc_task_runner, listener_task_runner));
dchenge48600452015-12-28 02:24:50457 channel->Init(std::move(factory), true);
458 return channel;
[email protected]64860882014-08-04 23:44:17459}
460
[email protected]952394af2011-11-16 01:06:46461ChannelProxy::ChannelProxy(Context* context)
rockota34707ca2016-07-20 04:28:32462 : context_(context), did_init_(false) {
mbarbellae97877bc2015-03-06 21:51:14463#if defined(ENABLE_IPC_FUZZER)
464 outgoing_message_filter_ = NULL;
465#endif
initial.commit09911bf2008-07-26 23:55:29466}
467
dchengfd033702014-08-28 16:59:29468ChannelProxy::ChannelProxy(
469 Listener* listener,
Hajime Hoshiff15e972017-11-09 06:37:09470 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
471 const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner)
472 : context_(new Context(listener, ipc_task_runner, listener_task_runner)),
473 did_init_(false) {
rockotf14a8ae2016-06-16 19:28:41474#if defined(ENABLE_IPC_FUZZER)
475 outgoing_message_filter_ = NULL;
476#endif
477}
[email protected]fca876a12014-06-05 16:15:38478
[email protected]dec76e802010-09-23 22:43:53479ChannelProxy::~ChannelProxy() {
gab21edbfa2017-05-31 16:49:12480 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]f775d102012-12-05 01:00:36481
[email protected]dec76e802010-09-23 22:43:53482 Close();
483}
484
[email protected]3b0e4662014-06-02 20:29:30485void ChannelProxy::Init(const IPC::ChannelHandle& channel_handle,
486 Channel::Mode mode,
rockot10188752016-09-08 18:24:56487 bool create_pipe_now) {
Fabrice de Gans-Riberi894661c2018-05-24 18:43:22488#if defined(OS_POSIX) || defined(OS_FUCHSIA)
[email protected]42ce94e2010-12-08 19:28:09489 // When we are creating a server on POSIX, we need its file descriptor
490 // to be created immediately so that it can be accessed and passed
491 // to other processes. Forcing it to be created immediately avoids
492 // race conditions that may otherwise arise.
[email protected]1707726c2011-02-03 20:35:09493 if (mode & Channel::MODE_SERVER_FLAG) {
[email protected]42ce94e2010-12-08 19:28:09494 create_pipe_now = true;
495 }
Fabrice de Gans-Riberi894661c2018-05-24 18:43:22496#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
rockota34707ca2016-07-20 04:28:32497 Init(
498 ChannelFactory::Create(channel_handle, mode, context_->ipc_task_runner()),
rockot10188752016-09-08 18:24:56499 create_pipe_now);
[email protected]64860882014-08-04 23:44:17500}
501
danakj03de39b22016-04-23 04:21:09502void ChannelProxy::Init(std::unique_ptr<ChannelFactory> factory,
rockot10188752016-09-08 18:24:56503 bool create_pipe_now) {
gab21edbfa2017-05-31 16:49:12504 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]64860882014-08-04 23:44:17505 DCHECK(!did_init_);
[email protected]42ce94e2010-12-08 19:28:09506
Sigurdur Asgeirssond655dd65f2019-11-12 19:32:20507 DCHECK(!context_->quota_checker_);
508 context_->quota_checker_ = factory->GetQuotaChecker();
509
initial.commit09911bf2008-07-26 23:55:29510 if (create_pipe_now) {
511 // Create the channel immediately. This effectively sets up the
512 // low-level pipe so that the client can connect. Without creating
513 // the pipe immediately, it is possible for a listener to attempt
514 // to connect and get an error since the pipe doesn't exist yet.
dchenge48600452015-12-28 02:24:50515 context_->CreateChannel(std::move(factory));
initial.commit09911bf2008-07-26 23:55:29516 } else {
[email protected]b2432302012-07-02 21:15:52517 context_->ipc_task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09518 FROM_HERE,
519 base::BindOnce(&Context::CreateChannel, context_, std::move(factory)));
initial.commit09911bf2008-07-26 23:55:29520 }
521
522 // complete initialization on the background thread
[email protected]b2432302012-07-02 21:15:52523 context_->ipc_task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09524 FROM_HERE, base::BindOnce(&Context::OnChannelOpened, context_));
[email protected]952394af2011-11-16 01:06:46525
526 did_init_ = true;
rockot29ade1b2015-08-07 06:23:59527 OnChannelInit();
initial.commit09911bf2008-07-26 23:55:29528}
529
rockot10188752016-09-08 18:24:56530void ChannelProxy::Pause() {
531 context_->ipc_task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09532 FROM_HERE, base::BindOnce(&Context::PauseChannel, context_));
rockot10188752016-09-08 18:24:56533}
534
rockot401fb2c2016-09-06 18:35:57535void ChannelProxy::Unpause(bool flush) {
536 context_->ipc_task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09537 FROM_HERE, base::BindOnce(&Context::UnpauseChannel, context_, flush));
rockot401fb2c2016-09-06 18:35:57538}
539
540void ChannelProxy::Flush() {
541 context_->ipc_task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09542 FROM_HERE, base::BindOnce(&Context::FlushChannel, context_));
rockot401fb2c2016-09-06 18:35:57543}
544
initial.commit09911bf2008-07-26 23:55:29545void ChannelProxy::Close() {
gab21edbfa2017-05-31 16:49:12546 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]f775d102012-12-05 01:00:36547
initial.commit09911bf2008-07-26 23:55:29548 // Clear the backpointer to the listener so that any pending calls to
549 // Context::OnDispatchMessage or OnDispatchError will be ignored. It is
550 // possible that the channel could be closed while it is receiving messages!
[email protected]3cdb7af812008-10-24 19:21:13551 context_->Clear();
initial.commit09911bf2008-07-26 23:55:29552
[email protected]b2432302012-07-02 21:15:52553 if (context_->ipc_task_runner()) {
554 context_->ipc_task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09555 FROM_HERE, base::BindOnce(&Context::OnChannelClosed, context_));
initial.commit09911bf2008-07-26 23:55:29556 }
557}
558
559bool ChannelProxy::Send(Message* message) {
John Abd-El-Malekd1d6f6a2017-07-18 20:01:00560 DCHECK(!message->is_sync()) << "Need to use IPC::SyncChannel";
Etienne Bergeron0a07d73d2019-06-27 16:40:47561 SendInternal(message);
John Abd-El-Malekd1d6f6a2017-07-18 20:01:00562 return true;
563}
564
Etienne Bergeron0a07d73d2019-06-27 16:40:47565void ChannelProxy::SendInternal(Message* message) {
rockotf14a8ae2016-06-16 19:28:41566 DCHECK(did_init_);
[email protected]f775d102012-12-05 01:00:36567
rockotf14a8ae2016-06-16 19:28:41568 // TODO(alexeypa): add DCHECK(CalledOnValidThread()) here. Currently there are
569 // tests that call Send() from a wrong thread. See http://crbug.com/163523.
[email protected]89480312011-05-04 17:14:16570
rockotf14a8ae2016-06-16 19:28:41571#ifdef ENABLE_IPC_FUZZER
572 // In IPC fuzzing builds, it is possible to define a filter to apply to
573 // outgoing messages. It will either rewrite the message and return a new
574 // one, freeing the original, or return the message unchanged.
575 if (outgoing_message_filter())
576 message = outgoing_message_filter()->Rewrite(message);
577#endif
578
davidsz041528a2017-05-12 09:19:23579#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
sammca1b3b4d2016-11-15 00:34:36580 Logging::GetInstance()->OnSendMessage(message);
rockotf14a8ae2016-06-16 19:28:41581#endif
582
Etienne Bergeron0a07d73d2019-06-27 16:40:47583 context_->Send(message);
initial.commit09911bf2008-07-26 23:55:29584}
585
586void ChannelProxy::AddFilter(MessageFilter* filter) {
gab21edbfa2017-05-31 16:49:12587 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]f775d102012-12-05 01:00:36588
[email protected]4b580bf2010-12-02 19:16:07589 context_->AddFilter(filter);
initial.commit09911bf2008-07-26 23:55:29590}
591
592void ChannelProxy::RemoveFilter(MessageFilter* filter) {
gab21edbfa2017-05-31 16:49:12593 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]f775d102012-12-05 01:00:36594
[email protected]b2432302012-07-02 21:15:52595 context_->ipc_task_runner()->PostTask(
kylecharf448cc92019-02-19 20:28:09596 FROM_HERE, base::BindOnce(&Context::OnRemoveFilter, context_,
597 base::RetainedRef(filter)));
initial.commit09911bf2008-07-26 23:55:29598}
599
rockot0e4de5f2016-07-22 21:18:07600void ChannelProxy::AddGenericAssociatedInterfaceForIOThread(
601 const std::string& name,
602 const GenericAssociatedInterfaceFactory& factory) {
603 context()->AddGenericAssociatedInterfaceForIOThread(name, factory);
rockot8d890f62016-07-14 16:37:14604}
605
rockot8d890f62016-07-14 16:37:14606void ChannelProxy::GetGenericRemoteAssociatedInterface(
607 const std::string& name,
608 mojo::ScopedInterfaceEndpointHandle handle) {
rockot5a908952016-07-28 20:08:17609 DCHECK(did_init_);
Ken Rockot96d1b7b52017-05-13 00:29:21610 context()->thread_safe_channel().GetAssociatedInterface(
Julie Jeongeun Kim69604f62019-12-04 01:59:52611 name, mojo::PendingAssociatedReceiver<mojom::GenericInterface>(
612 std::move(handle)));
rockot8d890f62016-07-14 16:37:14613}
614
[email protected]b2432302012-07-02 21:15:52615void ChannelProxy::ClearIPCTaskRunner() {
gab21edbfa2017-05-31 16:49:12616 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]b2432302012-07-02 21:15:52617 context()->ClearIPCTaskRunner();
[email protected]42f1d7822009-07-23 18:17:55618}
619
rockot29ade1b2015-08-07 06:23:59620void ChannelProxy::OnChannelInit() {
621}
622
initial.commit09911bf2008-07-26 23:55:29623//-----------------------------------------------------------------------------
624
625} // namespace IPC