Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
chromium /chromium /src /refs/heads/main /. /ipc /ipc_mojo_bootstrap.cc
blob: 75056be9b688fa7cb4eb2fec7e324eb7d5da7be5 [file] [log] [blame]
Avi Drissmanea1be232022-09-14 23:29:06[diff] [blame]1// Copyright 2014 The Chromium Authors
morrita54f6f80c2014-09-23 21:16:00[diff] [blame]2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
amistryd4aa70d2016-06-23 07:52:37[diff] [blame]5#include"ipc/ipc_mojo_bootstrap.h"
morrita54f6f80c2014-09-23 21:16:00[diff] [blame]6
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]7#include<inttypes.h>
tfarina10a5c062015-09-04 18:47:57[diff] [blame]8#include<stdint.h>
rockot02b8e182016-07-13 20:08:30[diff] [blame]9
Peter Kasting604e91f2025-01-27 21:12:28[diff] [blame]10#include<algorithm>
rockot02b8e182016-07-13 20:08:30[diff] [blame]11#include<map>
12#include<memory>
Arthur Sonzogni5bc3326c2024-02-29 19:39:05[diff] [blame]13#include<optional>
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]14#include<set>
dchenge48600452015-12-28 02:24:50[diff] [blame]15#include<utility>
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]16#include<vector>
tfarina10a5c062015-09-04 18:47:57[diff] [blame]17
Hans Wennborg4ed044f2020-04-27 09:43:38[diff] [blame]18#include"base/check_op.h"
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]19#include"base/containers/circular_deque.h"
Lei Zhang812c5392021-05-18 04:44:32[diff] [blame]20#include"base/containers/contains.h"
François Dorayfad1b8b2024-01-04 20:22:53[diff] [blame]21#include"base/feature_list.h"
Avi Drissmancac43f22023-01-12 00:58:41[diff] [blame]22#include"base/functional/bind.h"
23#include"base/functional/callback.h"
Etienne Pierre-dorayfc7952f02025-06-06 00:04:33[diff] [blame]24#include"base/hash/hash.h"
danakj03de39b22016-04-23 04:21:09[diff] [blame]25#include"base/memory/ptr_util.h"
Keishi Hattori0e45c022021-11-27 09:25:52[diff] [blame]26#include"base/memory/raw_ptr.h"
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]27#include"base/no_destructor.h"
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]28#include"base/sequence_checker.h"
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]29#include"base/strings/stringprintf.h"
rockot02b8e182016-07-13 20:08:30[diff] [blame]30#include"base/synchronization/lock.h"
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]31#include"base/synchronization/waitable_event.h"
Harkiran Bolaria8b1cf112020-09-15 22:58:34[diff] [blame]32#include"base/task/common/task_annotator.h"
Patrick Monette643cdf62021-10-15 19:13:42[diff] [blame]33#include"base/task/sequenced_task_runner.h"
34#include"base/task/single_thread_task_runner.h"
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]35#include"base/thread_annotations.h"
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]36#include"base/trace_event/memory_allocator_dump.h"
37#include"base/trace_event/memory_dump_manager.h"
38#include"base/trace_event/memory_dump_provider.h"
Alexander Timinda1f2c52021-11-03 02:23:05[diff] [blame]39#include"base/trace_event/typed_macros.h"
Ken Rockotfb81dc02018-05-15 21:59:26[diff] [blame]40#include"ipc/ipc_channel.h"
Scott Haseleycf0f1722023-11-03 21:39:01[diff] [blame]41#include"ipc/urgent_message_observer.h"
François Doray927a0822024-05-15 21:57:28[diff] [blame]42#include"mojo/public/c/system/types.h"
rockot02b8e182016-07-13 20:08:30[diff] [blame]43#include"mojo/public/cpp/bindings/associated_group.h"
44#include"mojo/public/cpp/bindings/associated_group_controller.h"
rockot02b8e182016-07-13 20:08:30[diff] [blame]45#include"mojo/public/cpp/bindings/connector.h"
Ken Rockotc1b27ca2024-04-13 00:37:39[diff] [blame]46#include"mojo/public/cpp/bindings/features.h"
rockot02b8e182016-07-13 20:08:30[diff] [blame]47#include"mojo/public/cpp/bindings/interface_endpoint_client.h"
48#include"mojo/public/cpp/bindings/interface_endpoint_controller.h"
49#include"mojo/public/cpp/bindings/interface_id.h"
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]50#include"mojo/public/cpp/bindings/message.h"
rockot02b8e182016-07-13 20:08:30[diff] [blame]51#include"mojo/public/cpp/bindings/message_header_validator.h"
Alexander Timinda1f2c52021-11-03 02:23:05[diff] [blame]52#include"mojo/public/cpp/bindings/mojo_buildflags.h"
rockot02b8e182016-07-13 20:08:30[diff] [blame]53#include"mojo/public/cpp/bindings/pipe_control_message_handler.h"
54#include"mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h"
55#include"mojo/public/cpp/bindings/pipe_control_message_proxy.h"
François Doray927a0822024-05-15 21:57:28[diff] [blame]56#include"mojo/public/cpp/bindings/scoped_message_error_crash_key.h"
Ken Rockotaa20dcc2018-03-28 03:06:51[diff] [blame]57#include"mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h"
Alexander Timinda1f2c52021-11-03 02:23:05[diff] [blame]58#include"mojo/public/cpp/bindings/tracing_helpers.h"
morrita54f6f80c2014-09-23 21:16:00[diff] [blame]59
60namespace IPC{
61
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]62classChannelAssociatedGroupController;
63
François Dorayfad1b8b2024-01-04 20:22:53[diff] [blame]64namespace{
65
Peter Kasting4b18d0c2024-09-18 00:56:11[diff] [blame]66constinit thread_localbool off_sequence_binding_allowed=false;
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]67
François Dorayfad1b8b2024-01-04 20:22:53[diff] [blame]68BASE_FEATURE(kMojoChannelAssociatedSendUsesRunOrPostTask,
69"MojoChannelAssociatedSendUsesRunOrPostTask",
François Doray806498022024-01-11 21:37:28[diff] [blame]70 base::FEATURE_DISABLED_BY_DEFAULT);
François Dorayfad1b8b2024-01-04 20:22:53[diff] [blame]71
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]72// Used to track some internal Channel state in pursuit of message leaks.
73//
Alison Gale81f4f2c72024-04-22 19:33:31[diff] [blame]74// TODO(crbug.com/40563310): Remove this.
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]75classControllerMemoryDumpProvider
76:public base::trace_event::MemoryDumpProvider{
77public:
78ControllerMemoryDumpProvider(){
79 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
80this,"IPCChannel",nullptr);
81}
82
Peter Boströmc68c5aa2021-09-28 00:28:00[diff] [blame]83ControllerMemoryDumpProvider(constControllerMemoryDumpProvider&)=delete;
84ControllerMemoryDumpProvider&operator=(constControllerMemoryDumpProvider&)=
85delete;
86
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]87~ControllerMemoryDumpProvider() override{
88 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
89this);
90}
91
92voidAddController(ChannelAssociatedGroupController* controller){
93 base::AutoLock lock(lock_);
94 controllers_.insert(controller);
95}
96
97voidRemoveController(ChannelAssociatedGroupController* controller){
98 base::AutoLock lock(lock_);
99 controllers_.erase(controller);
100}
101
102// base::trace_event::MemoryDumpProvider:
103boolOnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
104 base::trace_event::ProcessMemoryDump* pmd) override;
105
106private:
107 base::Lock lock_;
Ali Hijazi133b2d92024-02-09 14:01:52[diff] [blame]108 std::set<raw_ptr<ChannelAssociatedGroupController,SetExperimental>>
109 controllers_;
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]110};
111
112ControllerMemoryDumpProvider&GetMemoryDumpProvider(){
113static base::NoDestructor<ControllerMemoryDumpProvider> provider;
114return*provider;
115}
116
Siddhartha S03484422019-04-23 20:30:00[diff] [blame]117// Messages are grouped by this info when recording memory metrics.
118structMessageMemoryDumpInfo{
119MessageMemoryDumpInfo(const mojo::Message& message)
120: id(message.name()), profiler_tag(message.heap_profiler_tag()){}
121MessageMemoryDumpInfo()=default;
122
123booloperator==(constMessageMemoryDumpInfo& other)const{
124return other.id== id&& other.profiler_tag== profiler_tag;
125}
126
127uint32_t id=0;
128constchar* profiler_tag=nullptr;
129};
130
131structMessageMemoryDumpInfoHash{
132size_toperator()(constMessageMemoryDumpInfo& info)const{
Daniel Cheng5c5a6522019-11-19 18:03:36[diff] [blame]133return base::HashInts(
134 info.id, info.profiler_tag? base::FastHash(info.profiler_tag):0);
Siddhartha S03484422019-04-23 20:30:00[diff] [blame]135}
136};
137
Scott Haseleycf0f1722023-11-03 21:39:01[diff] [blame]138classScopedUrgentMessageNotification{
139public:
140explicitScopedUrgentMessageNotification(
141UrgentMessageObserver* observer=nullptr)
142: observer_(observer){
143if(observer_){
144 observer_->OnUrgentMessageReceived();
145}
146}
147
148~ScopedUrgentMessageNotification(){
149if(observer_){
150 observer_->OnUrgentMessageProcessed();
151}
152}
153
154ScopedUrgentMessageNotification(ScopedUrgentMessageNotification&& other)
155: observer_(std::exchange(other.observer_,nullptr)){}
156
157ScopedUrgentMessageNotification&operator=(
158ScopedUrgentMessageNotification&& other){
159 observer_= std::exchange(other.observer_,nullptr);
160return*this;
161}
162
163private:
164 raw_ptr<UrgentMessageObserver> observer_;
165};
166
François Dorayfad1b8b2024-01-04 20:22:53[diff] [blame]167}// namespace
168
rockot02b8e182016-07-13 20:08:30[diff] [blame]169classChannelAssociatedGroupController
170:public mojo::AssociatedGroupController,
171public mojo::MessageReceiver,
172public mojo::PipeControlMessageHandlerDelegate{
173public:
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]174ChannelAssociatedGroupController(
175bool set_interface_id_namespace_bit,
Hajime Hoshia98f1102017-11-20 06:34:35[diff] [blame]176const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
Ken Rockot7308d4b2022-12-13 06:35:56[diff] [blame]177const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner)
rockotb01ef6a2016-07-27 03:24:32[diff] [blame]178: task_runner_(ipc_task_runner),
Hajime Hoshia98f1102017-11-20 06:34:35[diff] [blame]179 proxy_task_runner_(proxy_task_runner),
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]180 set_interface_id_namespace_bit_(set_interface_id_namespace_bit),
Dave Tapuskaf2df43e2019-10-10 22:10:10[diff] [blame]181 dispatcher_(this),
rockot02b8e182016-07-13 20:08:30[diff] [blame]182 control_message_handler_(this),
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]183 control_message_proxy_thunk_(this),
184 control_message_proxy_(&control_message_proxy_thunk_){
rockot02b8e182016-07-13 20:08:30[diff] [blame]185 control_message_handler_.SetDescription(
Ken Rockotcd23f752020-06-20 01:22:31[diff] [blame]186"IPC::mojom::Bootstrap [primary] PipeControlMessageHandler");
Dave Tapuskaf2df43e2019-10-10 22:10:10[diff] [blame]187 dispatcher_.SetValidator(std::make_unique<mojo::MessageHeaderValidator>(
Ken Rockotcd23f752020-06-20 01:22:31[diff] [blame]188"IPC::mojom::Bootstrap [primary] MessageHeaderValidator"));
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]189
190GetMemoryDumpProvider().AddController(this);
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]191
192 DETACH_FROM_SEQUENCE(sequence_checker_);
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]193}
194
Peter Boström896f1372021-11-05 01:12:30[diff] [blame]195ChannelAssociatedGroupController(constChannelAssociatedGroupController&)=
196delete;
197ChannelAssociatedGroupController&operator=(
198constChannelAssociatedGroupController&)=delete;
199
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]200size_tGetQueuedMessageCount(){
201 base::AutoLock lock(outgoing_messages_lock_);
202return outgoing_messages_.size();
rockot02b8e182016-07-13 20:08:30[diff] [blame]203}
204
Siddhartha S03484422019-04-23 20:30:00[diff] [blame]205voidGetTopQueuedMessageMemoryDumpInfo(MessageMemoryDumpInfo* info,
206size_t* count){
207 std::unordered_map<MessageMemoryDumpInfo,size_t,MessageMemoryDumpInfoHash>
208 counts;
209 std::pair<MessageMemoryDumpInfo,size_t> top_message_info_and_count={
210MessageMemoryDumpInfo(),0};
Siddharthad1cfec12018-09-17 21:42:15[diff] [blame]211 base::AutoLock lock(outgoing_messages_lock_);
212for(constauto& message: outgoing_messages_){
Siddhartha S03484422019-04-23 20:30:00[diff] [blame]213auto it_and_inserted= counts.emplace(MessageMemoryDumpInfo(message),0);
Siddharthad1cfec12018-09-17 21:42:15[diff] [blame]214 it_and_inserted.first->second++;
Siddhartha S03484422019-04-23 20:30:00[diff] [blame]215if(it_and_inserted.first->second> top_message_info_and_count.second)
216 top_message_info_and_count=*it_and_inserted.first;
Siddharthad1cfec12018-09-17 21:42:15[diff] [blame]217}
Siddhartha S03484422019-04-23 20:30:00[diff] [blame]218*info= top_message_info_and_count.first;
219*count= top_message_info_and_count.second;
Siddharthad1cfec12018-09-17 21:42:15[diff] [blame]220}
221
rockot10188752016-09-08 18:24:56[diff] [blame]222voidPause(){
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]223 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
224 CHECK(was_bound_or_message_sent_);
225 CHECK(!paused_);
rockot10188752016-09-08 18:24:56[diff] [blame]226 paused_=true;
227}
228
229voidUnpause(){
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]230 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
231 CHECK(was_bound_or_message_sent_);
232 CHECK(paused_);
rockot10188752016-09-08 18:24:56[diff] [blame]233 paused_=false;
rockot401fb2c2016-09-06 18:35:57[diff] [blame]234}
235
236voidFlushOutgoingMessages(){
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]237 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
238 CHECK(was_bound_or_message_sent_);
239
rockotc4cc691e2016-08-19 18:48:57[diff] [blame]240 std::vector<mojo::Message> outgoing_messages;
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]241{
242 base::AutoLock lock(outgoing_messages_lock_);
243 std::swap(outgoing_messages, outgoing_messages_);
244}
Sigurdur Asgeirssond655dd65f2019-11-12 19:32:20[diff] [blame]245
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]246for(auto& message: outgoing_messages)
rockotc4cc691e2016-08-19 18:48:57[diff] [blame]247SendMessage(&message);
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]248}
249
Ken Rockot9fae8bcd2021-06-04 22:09:49[diff] [blame]250voidBind(mojo::ScopedMessagePipeHandle handle,
251 mojo::PendingAssociatedRemote<mojom::Channel>* sender,
252 mojo::PendingAssociatedReceiver<mojom::Channel>* receiver){
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]253 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
254
Ken Rockot9fae8bcd2021-06-04 22:09:49[diff] [blame]255 connector_= std::make_unique<mojo::Connector>(
256 std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
257"IPC Channel");
258 connector_->set_incoming_receiver(&dispatcher_);
259 connector_->set_connection_error_handler(
260 base::BindOnce(&ChannelAssociatedGroupController::OnPipeError,
261 base::Unretained(this)));
262 connector_->set_enforce_errors_from_incoming_receiver(false);
Ken Rockot9fae8bcd2021-06-04 22:09:49[diff] [blame]263
264// Don't let the Connector do any sort of queuing on our behalf. Individual
265// messages bound for the IPC::ChannelProxy thread (i.e. that vast majority
266// of messages received by this Connector) are already individually
267// scheduled for dispatch by ChannelProxy, so Connector's normal mode of
268// operation would only introduce a redundant scheduling step for most
269// messages.
270 connector_->set_force_immediate_dispatch(true);
271
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]272 mojo::InterfaceId sender_id, receiver_id;
273if(set_interface_id_namespace_bit_){
274 sender_id=1| mojo::kInterfaceIdNamespaceMask;
275 receiver_id=1;
276}else{
277 sender_id=1;
278 receiver_id=1| mojo::kInterfaceIdNamespaceMask;
279}
280
281{
282 base::AutoLock locker(lock_);
283Endpoint* sender_endpoint=newEndpoint(this, sender_id);
284Endpoint* receiver_endpoint=newEndpoint(this, receiver_id);
285 endpoints_.insert({ sender_id, sender_endpoint});
286 endpoints_.insert({ receiver_id, receiver_endpoint});
yzshen0a5971312017-02-02 05:13:47[diff] [blame]287 sender_endpoint->set_handle_created();
288 receiver_endpoint->set_handle_created();
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]289}
290
291 mojo::ScopedInterfaceEndpointHandle sender_handle=
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]292CreateScopedInterfaceEndpointHandle(sender_id);
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]293 mojo::ScopedInterfaceEndpointHandle receiver_handle=
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]294CreateScopedInterfaceEndpointHandle(receiver_id);
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]295
Ken Rockotfbbd4442021-06-04 01:19:14[diff] [blame]296*sender= mojo::PendingAssociatedRemote<mojom::Channel>(
297 std::move(sender_handle),0);
Julie Jeongeun Kim903b34b2019-09-25 11:11:54[diff] [blame]298*receiver= mojo::PendingAssociatedReceiver<mojom::Channel>(
299 std::move(receiver_handle));
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]300
301if(!was_bound_or_message_sent_){
302 was_bound_or_message_sent_=true;
303 DETACH_FROM_SEQUENCE(sequence_checker_);
304}
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]305}
rockot02b8e182016-07-13 20:08:30[diff] [blame]306
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]307voidStartReceiving(){
308 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
309 CHECK(was_bound_or_message_sent_);
310 connector_->StartReceiving(task_runner_);
311}
Ken Rockot9fae8bcd2021-06-04 22:09:49[diff] [blame]312
rockot02b8e182016-07-13 20:08:30[diff] [blame]313voidShutDown(){
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]314 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Ken Rockot3e7284bb2018-02-06 16:11:16[diff] [blame]315 shut_down_=true;
Bruce Dawsona40d48472020-04-20 20:57:24[diff] [blame]316if(connector_)
317 connector_->CloseMessagePipe();
rockot02b8e182016-07-13 20:08:30[diff] [blame]318OnPipeError();
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]319 connector_.reset();
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]320
321 base::AutoLock lock(outgoing_messages_lock_);
Ken Rockot3e7284bb2018-02-06 16:11:16[diff] [blame]322 outgoing_messages_.clear();
rockot02b8e182016-07-13 20:08:30[diff] [blame]323}
324
325// mojo::AssociatedGroupController:
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]326 mojo::InterfaceIdAssociateInterface(
327 mojo::ScopedInterfaceEndpointHandle handle_to_send) override{
328if(!handle_to_send.pending_association())
329return mojo::kInvalidInterfaceId;
330
rockot02b8e182016-07-13 20:08:30[diff] [blame]331uint32_t id=0;
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]332{
333 base::AutoLock locker(lock_);
334do{
335if(next_interface_id_>= mojo::kInterfaceIdNamespaceMask)
336 next_interface_id_=2;
337 id= next_interface_id_++;
338if(set_interface_id_namespace_bit_)
339 id|= mojo::kInterfaceIdNamespaceMask;
Jan Wilken Dörrie73c901e2019-06-12 09:02:32[diff] [blame]340}while(base::Contains(endpoints_, id));
rockot02b8e182016-07-13 20:08:30[diff] [blame]341
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]342Endpoint* endpoint=newEndpoint(this, id);
343if(encountered_error_)
344 endpoint->set_peer_closed();
345 endpoint->set_handle_created();
346 endpoints_.insert({id, endpoint});
347}
rockot02b8e182016-07-13 20:08:30[diff] [blame]348
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]349if(!NotifyAssociation(&handle_to_send, id)){
350// The peer handle of |handle_to_send|, which is supposed to join this
351// associated group, has been closed.
352{
353 base::AutoLock locker(lock_);
354Endpoint* endpoint=FindEndpoint(id);
355if(endpoint)
356MarkClosedAndMaybeRemove(endpoint);
357}
358
359 control_message_proxy_.NotifyPeerEndpointClosed(
360 id, handle_to_send.disconnect_reason());
361}
362return id;
rockot02b8e182016-07-13 20:08:30[diff] [blame]363}
364
365 mojo::ScopedInterfaceEndpointHandleCreateLocalEndpointHandle(
366 mojo::InterfaceId id) override{
367if(!mojo::IsValidInterfaceId(id))
368return mojo::ScopedInterfaceEndpointHandle();
369
Ken Rockotcd23f752020-06-20 01:22:31[diff] [blame]370// Unless it is the primary ID, |id| is from the remote side and therefore
Yuzhu Shen9f87fb02017-08-11 17:07:06[diff] [blame]371// its namespace bit is supposed to be different than the value that this
372// router would use.
Ken Rockotcd23f752020-06-20 01:22:31[diff] [blame]373if(!mojo::IsPrimaryInterfaceId(id)&&
Yuzhu Shen9f87fb02017-08-11 17:07:06[diff] [blame]374 set_interface_id_namespace_bit_==
375 mojo::HasInterfaceIdNamespaceBitSet(id)){
376return mojo::ScopedInterfaceEndpointHandle();
377}
378
rockot02b8e182016-07-13 20:08:30[diff] [blame]379 base::AutoLock locker(lock_);
380bool inserted=false;
381Endpoint* endpoint=FindOrInsertEndpoint(id,&inserted);
yzshenea784ea2017-01-31 21:20:20[diff] [blame]382if(inserted){
383 DCHECK(!endpoint->handle_created());
384if(encountered_error_)
385 endpoint->set_peer_closed();
386}else{
387if(endpoint->handle_created())
388return mojo::ScopedInterfaceEndpointHandle();
389}
rockot02b8e182016-07-13 20:08:30[diff] [blame]390
yzshenea784ea2017-01-31 21:20:20[diff] [blame]391 endpoint->set_handle_created();
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]392returnCreateScopedInterfaceEndpointHandle(id);
rockot02b8e182016-07-13 20:08:30[diff] [blame]393}
394
yzshen8be41d3a2017-01-23 20:40:37[diff] [blame]395voidCloseEndpointHandle(
396 mojo::InterfaceId id,
Arthur Sonzogni59ac8222023-11-10 09:46:54[diff] [blame]397const std::optional<mojo::DisconnectReason>& reason) override{
rockot02b8e182016-07-13 20:08:30[diff] [blame]398if(!mojo::IsValidInterfaceId(id))
399return;
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]400{
401 base::AutoLock locker(lock_);
Jan Wilken Dörrie73c901e2019-06-12 09:02:32[diff] [blame]402 DCHECK(base::Contains(endpoints_, id));
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]403Endpoint* endpoint= endpoints_[id].get();
404 DCHECK(!endpoint->client());
405 DCHECK(!endpoint->closed());
406MarkClosedAndMaybeRemove(endpoint);
rockot02b8e182016-07-13 20:08:30[diff] [blame]407}
408
Ken Rockotcd23f752020-06-20 01:22:31[diff] [blame]409if(!mojo::IsPrimaryInterfaceId(id)|| reason)
yzshen8be41d3a2017-01-23 20:40:37[diff] [blame]410 control_message_proxy_.NotifyPeerEndpointClosed(id, reason);
rockot02b8e182016-07-13 20:08:30[diff] [blame]411}
412
Ken Rockotc1b27ca2024-04-13 00:37:39[diff] [blame]413voidNotifyLocalEndpointOfPeerClosure(mojo::InterfaceId id) override{
Ken Rockotc1b27ca2024-04-13 00:37:39[diff] [blame]414if(!task_runner_->RunsTasksInCurrentSequence()){
415 task_runner_->PostTask(
416 FROM_HERE, base::BindOnce(&ChannelAssociatedGroupController::
417NotifyLocalEndpointOfPeerClosure,
418 base::WrapRefCounted(this), id));
419return;
420}
421OnPeerAssociatedEndpointClosed(id, std::nullopt);
422}
423
rockot02b8e182016-07-13 20:08:30[diff] [blame]424 mojo::InterfaceEndpointController*AttachEndpointClient(
425const mojo::ScopedInterfaceEndpointHandle& handle,
426 mojo::InterfaceEndpointClient* client,
Sam McNallyde5ae672017-06-19 23:34:45[diff] [blame]427 scoped_refptr<base::SequencedTaskRunner> runner) override{
rockot02b8e182016-07-13 20:08:30[diff] [blame]428const mojo::InterfaceId id= handle.id();
429
430 DCHECK(mojo::IsValidInterfaceId(id));
431 DCHECK(client);
432
433 base::AutoLock locker(lock_);
Jan Wilken Dörrie73c901e2019-06-12 09:02:32[diff] [blame]434 DCHECK(base::Contains(endpoints_, id));
rockot02b8e182016-07-13 20:08:30[diff] [blame]435
436Endpoint* endpoint= endpoints_[id].get();
437 endpoint->AttachClient(client, std::move(runner));
438
439if(endpoint->peer_closed())
440NotifyEndpointOfError(endpoint,true/* force_async */);
441
442return endpoint;
443}
444
445voidDetachEndpointClient(
446const mojo::ScopedInterfaceEndpointHandle& handle) override{
447const mojo::InterfaceId id= handle.id();
448
449 DCHECK(mojo::IsValidInterfaceId(id));
450
451 base::AutoLock locker(lock_);
Jan Wilken Dörrie73c901e2019-06-12 09:02:32[diff] [blame]452 DCHECK(base::Contains(endpoints_, id));
rockot02b8e182016-07-13 20:08:30[diff] [blame]453
454Endpoint* endpoint= endpoints_[id].get();
455 endpoint->DetachClient();
456}
457
458voidRaiseError() override{
Ken Rockot138153b2018-07-13 23:31:57[diff] [blame]459// We ignore errors on channel endpoints, leaving the pipe open. There are
460// good reasons for this:
461//
462// * We should never close a channel endpoint in either process as long as
463// the child process is still alive. The child's endpoint should only be
464// closed implicitly by process death, and the browser's endpoint should
465// only be closed after the child process is confirmed to be dead. Crash
466// reporting logic in Chrome relies on this behavior in order to do the
467// right thing.
468//
469// * There are two interesting conditions under which RaiseError() can be
470// implicitly reached: an incoming message fails validation, or the
471// local endpoint drops a response callback without calling it.
472//
473// * In the validation case, we also report the message as bad, and this
474// will imminently trigger the common bad-IPC path in the browser,
475// causing the browser to kill the offending renderer.
476//
477// * In the dropped response callback case, the net result of ignoring the
478// issue is generally innocuous. While indicative of programmer error,
479// it's not a severe failure and is already covered by separate DCHECKs.
480//
481// See https://crbug.com/861607 for additional discussion.
rockot02b8e182016-07-13 20:08:30[diff] [blame]482}
483
Ken Rockot474df0142017-07-12 13:28:56[diff] [blame]484boolPrefersSerializedMessages() override{returntrue;}
485
Scott Haseleycf0f1722023-11-03 21:39:01[diff] [blame]486voidSetUrgentMessageObserver(UrgentMessageObserver* observer){
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]487 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
488 CHECK(!was_bound_or_message_sent_);
Scott Haseleycf0f1722023-11-03 21:39:01[diff] [blame]489 urgent_message_observer_= observer;
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]490 DETACH_FROM_SEQUENCE(sequence_checker_);
Scott Haseleycf0f1722023-11-03 21:39:01[diff] [blame]491}
492
rockot02b8e182016-07-13 20:08:30[diff] [blame]493private:
494classEndpoint;
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]495classControlMessageProxyThunk;
rockot02b8e182016-07-13 20:08:30[diff] [blame]496friendclassEndpoint;
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]497friendclassControlMessageProxyThunk;
rockot02b8e182016-07-13 20:08:30[diff] [blame]498
yzshen0a5971312017-02-02 05:13:47[diff] [blame]499// MessageWrapper objects are always destroyed under the controller's lock. On
500// destruction, if the message it wrappers contains
501// ScopedInterfaceEndpointHandles (which cannot be destructed under the
502// controller's lock), the wrapper unlocks to clean them up.
503classMessageWrapper{
yzshenea784ea2017-01-31 21:20:20[diff] [blame]504public:
yzshen0a5971312017-02-02 05:13:47[diff] [blame]505MessageWrapper()=default;
yzshenea784ea2017-01-31 21:20:20[diff] [blame]506
yzshen0a5971312017-02-02 05:13:47[diff] [blame]507MessageWrapper(ChannelAssociatedGroupController* controller,
508 mojo::Message message)
509: controller_(controller), value_(std::move(message)){}
yzshenea784ea2017-01-31 21:20:20[diff] [blame]510
yzshen0a5971312017-02-02 05:13:47[diff] [blame]511MessageWrapper(MessageWrapper&& other)
yzshenea784ea2017-01-31 21:20:20[diff] [blame]512: controller_(other.controller_), value_(std::move(other.value_)){}
513
Peter Boströmc68c5aa2021-09-28 00:28:00[diff] [blame]514MessageWrapper(constMessageWrapper&)=delete;
515MessageWrapper&operator=(constMessageWrapper&)=delete;
516
yzshen0a5971312017-02-02 05:13:47[diff] [blame]517~MessageWrapper(){
518if(value_.associated_endpoint_handles()->empty())
yzshenea784ea2017-01-31 21:20:20[diff] [blame]519return;
520
521 controller_->lock_.AssertAcquired();
yzshen0a5971312017-02-02 05:13:47[diff] [blame]522{
yzshenea784ea2017-01-31 21:20:20[diff] [blame]523 base::AutoUnlock unlocker(controller_->lock_);
yzshen0a5971312017-02-02 05:13:47[diff] [blame]524 value_.mutable_associated_endpoint_handles()->clear();
yzshenea784ea2017-01-31 21:20:20[diff] [blame]525}
526}
527
yzshen0a5971312017-02-02 05:13:47[diff] [blame]528MessageWrapper&operator=(MessageWrapper&& other){
yzshenea784ea2017-01-31 21:20:20[diff] [blame]529 controller_= other.controller_;
530 value_= std::move(other.value_);
531return*this;
532}
533
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]534boolHasRequestId(uint64_t request_id){
535return!value_.IsNull()&& value_.version()>=1&&
536 value_.header_v1()->request_id== request_id;
537}
538
yzshen0a5971312017-02-02 05:13:47[diff] [blame]539 mojo::Message& value(){return value_;}
yzshenea784ea2017-01-31 21:20:20[diff] [blame]540
541private:
Keishi Hattori0e45c022021-11-27 09:25:52[diff] [blame]542 raw_ptr<ChannelAssociatedGroupController> controller_=nullptr;
yzshenea784ea2017-01-31 21:20:20[diff] [blame]543 mojo::Message value_;
yzshenea784ea2017-01-31 21:20:20[diff] [blame]544};
545
rockot02b8e182016-07-13 20:08:30[diff] [blame]546classEndpoint:public base::RefCountedThreadSafe<Endpoint>,
547public mojo::InterfaceEndpointController{
548public:
549Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id)
550: controller_(controller), id_(id){}
551
Peter Boström896f1372021-11-05 01:12:30[diff] [blame]552Endpoint(constEndpoint&)=delete;
553Endpoint&operator=(constEndpoint&)=delete;
554
rockot02b8e182016-07-13 20:08:30[diff] [blame]555 mojo::InterfaceId id()const{return id_;}
556
557bool closed()const{
558 controller_->lock_.AssertAcquired();
559return closed_;
560}
561
562void set_closed(){
563 controller_->lock_.AssertAcquired();
564 closed_=true;
565}
566
567bool peer_closed()const{
568 controller_->lock_.AssertAcquired();
569return peer_closed_;
570}
571
572void set_peer_closed(){
573 controller_->lock_.AssertAcquired();
574 peer_closed_=true;
575}
576
yzshenea784ea2017-01-31 21:20:20[diff] [blame]577bool handle_created()const{
578 controller_->lock_.AssertAcquired();
579return handle_created_;
580}
581
582void set_handle_created(){
583 controller_->lock_.AssertAcquired();
584 handle_created_=true;
585}
586
Arthur Sonzogni59ac8222023-11-10 09:46:54[diff] [blame]587const std::optional<mojo::DisconnectReason>& disconnect_reason()const{
yzshen8be41d3a2017-01-23 20:40:37[diff] [blame]588return disconnect_reason_;
589}
590
591void set_disconnect_reason(
Arthur Sonzogni59ac8222023-11-10 09:46:54[diff] [blame]592const std::optional<mojo::DisconnectReason>& disconnect_reason){
yzshen8be41d3a2017-01-23 20:40:37[diff] [blame]593 disconnect_reason_= disconnect_reason;
594}
595
Sam McNallyde5ae672017-06-19 23:34:45[diff] [blame]596 base::SequencedTaskRunner* task_runner()const{
rockot02b8e182016-07-13 20:08:30[diff] [blame]597return task_runner_.get();
598}
599
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]600bool was_bound_off_sequence()const{return was_bound_off_sequence_;}
601
rockot02b8e182016-07-13 20:08:30[diff] [blame]602 mojo::InterfaceEndpointClient* client()const{
603 controller_->lock_.AssertAcquired();
604return client_;
605}
606
607voidAttachClient(mojo::InterfaceEndpointClient* client,
Sam McNallyde5ae672017-06-19 23:34:45[diff] [blame]608 scoped_refptr<base::SequencedTaskRunner> runner){
rockot02b8e182016-07-13 20:08:30[diff] [blame]609 controller_->lock_.AssertAcquired();
610 DCHECK(!client_);
611 DCHECK(!closed_);
rockot02b8e182016-07-13 20:08:30[diff] [blame]612
613 task_runner_= std::move(runner);
614 client_= client;
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]615
Peter Kasting525a0142023-03-08 21:56:27[diff] [blame]616if(off_sequence_binding_allowed){
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]617 was_bound_off_sequence_=true;
Peter Kasting525a0142023-03-08 21:56:27[diff] [blame]618}
rockot02b8e182016-07-13 20:08:30[diff] [blame]619}
620
621voidDetachClient(){
622 controller_->lock_.AssertAcquired();
623 DCHECK(client_);
rockot02b8e182016-07-13 20:08:30[diff] [blame]624 DCHECK(!closed_);
625
626 task_runner_=nullptr;
627 client_=nullptr;
rockot9abe09b2016-08-02 20:57:34[diff] [blame]628 sync_watcher_.reset();
629}
630
Arthur Sonzogni59ac8222023-11-10 09:46:54[diff] [blame]631 std::optional<uint32_t>EnqueueSyncMessage(MessageWrapper message){
rockot9abe09b2016-08-02 20:57:34[diff] [blame]632 controller_->lock_.AssertAcquired();
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]633if(exclusive_wait_&& exclusive_wait_->TryFulfillingWith(message)){
634 exclusive_wait_=nullptr;
Arthur Sonzogni59ac8222023-11-10 09:46:54[diff] [blame]635return std::nullopt;
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]636}
637
rockot9abe09b2016-08-02 20:57:34[diff] [blame]638uint32_t id=GenerateSyncMessageId();
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]639 sync_messages_.emplace_back(id, std::move(message));
rockot9abe09b2016-08-02 20:57:34[diff] [blame]640SignalSyncMessageEvent();
641return id;
642}
643
644voidSignalSyncMessageEvent(){
645 controller_->lock_.AssertAcquired();
yzshene25b5d52017-02-28 21:56:31[diff] [blame]646
Ken Rockotaa20dcc2018-03-28 03:06:51[diff] [blame]647if(sync_watcher_)
648 sync_watcher_->SignalEvent();
rockot9abe09b2016-08-02 20:57:34[diff] [blame]649}
650
yzshen0a5971312017-02-02 05:13:47[diff] [blame]651MessageWrapperPopSyncMessage(uint32_t id){
rockot9abe09b2016-08-02 20:57:34[diff] [blame]652 controller_->lock_.AssertAcquired();
653if(sync_messages_.empty()|| sync_messages_.front().first!= id)
yzshen0a5971312017-02-02 05:13:47[diff] [blame]654returnMessageWrapper();
655MessageWrapper message= std::move(sync_messages_.front().second);
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]656 sync_messages_.pop_front();
rockot9abe09b2016-08-02 20:57:34[diff] [blame]657return message;
rockot02b8e182016-07-13 20:08:30[diff] [blame]658}
659
660// mojo::InterfaceEndpointController:
661boolSendMessage(mojo::Message* message) override{
peary28cd3bd22017-06-29 02:15:28[diff] [blame]662 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30[diff] [blame]663 message->set_interface_id(id_);
664return controller_->SendMessage(message);
665}
666
667voidAllowWokenUpBySyncWatchOnSameThread() override{
peary28cd3bd22017-06-29 02:15:28[diff] [blame]668 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30[diff] [blame]669
rockot9abe09b2016-08-02 20:57:34[diff] [blame]670EnsureSyncWatcherExists();
Ken Rockotaa20dcc2018-03-28 03:06:51[diff] [blame]671 sync_watcher_->AllowWokenUpBySyncWatchOnSameSequence();
rockot02b8e182016-07-13 20:08:30[diff] [blame]672}
673
Ken Rockot5b3136c2021-04-26 17:45:59[diff] [blame]674boolSyncWatch(constbool& should_stop) override{
peary28cd3bd22017-06-29 02:15:28[diff] [blame]675 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot02b8e182016-07-13 20:08:30[diff] [blame]676
Ken Rockotcd23f752020-06-20 01:22:31[diff] [blame]677// It's not legal to make sync calls from the primary endpoint's thread,
rockot02b8e182016-07-13 20:08:30[diff] [blame]678// and in fact they must only happen from the proxy task runner.
rockot7604e7b72016-07-28 17:37:39[diff] [blame]679 DCHECK(!controller_->task_runner_->BelongsToCurrentThread());
rockot02b8e182016-07-13 20:08:30[diff] [blame]680 DCHECK(controller_->proxy_task_runner_->BelongsToCurrentThread());
681
rockot9abe09b2016-08-02 20:57:34[diff] [blame]682EnsureSyncWatcherExists();
Xuehui Xie327082692023-06-21 16:08:04[diff] [blame]683{
684 base::AutoLock locker(controller_->lock_);
685if(peer_closed_){
686SignalSyncMessageEvent();
687}
688}
Ken Rockot54272972021-04-20 22:08:04[diff] [blame]689return sync_watcher_->SyncWatch(&should_stop);
rockot02b8e182016-07-13 20:08:30[diff] [blame]690}
691
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]692MessageWrapperWaitForIncomingSyncReply(uint64_t request_id){
Arthur Sonzogni59ac8222023-11-10 09:46:54[diff] [blame]693 std::optional<ExclusiveSyncWait> wait;
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]694{
695 base::AutoLock lock(controller_->lock_);
696for(auto&[id, message]: sync_messages_){
697if(message.HasRequestId(request_id)){
698return std::move(message);
699}
700}
701
702 DCHECK(!exclusive_wait_);
703 wait.emplace(request_id);
704 exclusive_wait_=&wait.value();
705}
706
707 wait->event.Wait();
708return std::move(wait->message);
709}
710
Ken Rockot5b3136c2021-04-26 17:45:59[diff] [blame]711boolSyncWatchExclusive(uint64_t request_id) override{
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]712MessageWrapper message=WaitForIncomingSyncReply(request_id);
713if(message.value().IsNull()||!client_){
714returnfalse;
715}
716
717if(!client_->HandleIncomingMessage(&message.value())){
718 base::AutoLock locker(controller_->lock_);
719 controller_->RaiseError();
720returnfalse;
721}
722
723returntrue;
Ken Rockot5b3136c2021-04-26 17:45:59[diff] [blame]724}
725
Ken Rockot9f69e162021-04-19 14:16:29[diff] [blame]726voidRegisterExternalSyncWaiter(uint64_t request_id) override{}
727
rockot02b8e182016-07-13 20:08:30[diff] [blame]728private:
729friendclass base::RefCountedThreadSafe<Endpoint>;
730
rockot9abe09b2016-08-02 20:57:34[diff] [blame]731~Endpoint() override{
732 controller_->lock_.AssertAcquired();
733 DCHECK(!client_);
734 DCHECK(closed_);
735 DCHECK(peer_closed_);
736 DCHECK(!sync_watcher_);
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]737if(exclusive_wait_){
738 exclusive_wait_->event.Signal();
739}
rockot9abe09b2016-08-02 20:57:34[diff] [blame]740}
741
rockotb62e2e32017-03-24 18:36:44[diff] [blame]742voidOnSyncMessageEventReady(){
peary28cd3bd22017-06-29 02:15:28[diff] [blame]743 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot9abe09b2016-08-02 20:57:34[diff] [blame]744
Ken Rockot120b4b02022-12-01 01:44:05[diff] [blame]745// SUBTLE: The order of these scoped_refptrs matters.
746// `controller_keepalive` MUST outlive `keepalive` because the Endpoint
747// holds raw pointer to the AssociatedGroupController.
rockot9abe09b2016-08-02 20:57:34[diff] [blame]748 scoped_refptr<AssociatedGroupController> controller_keepalive(
Keishi Hattori0e45c022021-11-27 09:25:52[diff] [blame]749 controller_.get());
Ken Rockot120b4b02022-12-01 01:44:05[diff] [blame]750 scoped_refptr<Endpoint> keepalive(this);
Ken Rockotaa20dcc2018-03-28 03:06:51[diff] [blame]751 base::AutoLock locker(controller_->lock_);
752bool more_to_process=false;
753if(!sync_messages_.empty()){
754MessageWrapper message_wrapper=
755 std::move(sync_messages_.front().second);
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]756 sync_messages_.pop_front();
rockot9abe09b2016-08-02 20:57:34[diff] [blame]757
Ken Rockotaa20dcc2018-03-28 03:06:51[diff] [blame]758bool dispatch_succeeded;
759 mojo::InterfaceEndpointClient* client= client_;
760{
761 base::AutoUnlock unlocker(controller_->lock_);
762 dispatch_succeeded=
763 client->HandleIncomingMessage(&message_wrapper.value());
rockot9abe09b2016-08-02 20:57:34[diff] [blame]764}
765
Ken Rockotaa20dcc2018-03-28 03:06:51[diff] [blame]766if(!sync_messages_.empty())
767 more_to_process=true;
rockot9abe09b2016-08-02 20:57:34[diff] [blame]768
Ken Rockotaa20dcc2018-03-28 03:06:51[diff] [blame]769if(!dispatch_succeeded)
770 controller_->RaiseError();
rockot9abe09b2016-08-02 20:57:34[diff] [blame]771}
772
Ken Rockotaa20dcc2018-03-28 03:06:51[diff] [blame]773if(!more_to_process)
774 sync_watcher_->ResetEvent();
775
776// If there are no queued sync messages and the peer has closed, there
777// there won't be incoming sync messages in the future. If any
778// SyncWatch() calls are on the stack for this endpoint, resetting the
779// watcher will allow them to exit as the stack undwinds.
780if(!more_to_process&& peer_closed_)
rockot9abe09b2016-08-02 20:57:34[diff] [blame]781 sync_watcher_.reset();
rockot9abe09b2016-08-02 20:57:34[diff] [blame]782}
783
784voidEnsureSyncWatcherExists(){
peary28cd3bd22017-06-29 02:15:28[diff] [blame]785 DCHECK(task_runner_->RunsTasksInCurrentSequence());
rockot9abe09b2016-08-02 20:57:34[diff] [blame]786if(sync_watcher_)
787return;
788
Ken Rockotaa20dcc2018-03-28 03:06:51[diff] [blame]789 base::AutoLock locker(controller_->lock_);
790 sync_watcher_= std::make_unique<mojo::SequenceLocalSyncEventWatcher>(
791 base::BindRepeating(&Endpoint::OnSyncMessageEventReady,
792 base::Unretained(this)));
793if(peer_closed_||!sync_messages_.empty())
794SignalSyncMessageEvent();
rockot9abe09b2016-08-02 20:57:34[diff] [blame]795}
796
797uint32_tGenerateSyncMessageId(){
798// Overflow is fine.
799uint32_t id= next_sync_message_id_++;
800 DCHECK(sync_messages_.empty()|| sync_messages_.front().first!= id);
801return id;
802}
rockot02b8e182016-07-13 20:08:30[diff] [blame]803
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]804// Tracks the state of a pending sync wait which excludes all other incoming
805// IPC on the waiting thread.
806structExclusiveSyncWait{
807explicitExclusiveSyncWait(uint64_t request_id)
808: request_id(request_id){}
809~ExclusiveSyncWait()=default;
810
811boolTryFulfillingWith(MessageWrapper& wrapper){
812if(!wrapper.HasRequestId(request_id)){
813returnfalse;
814}
815
816 message= std::move(wrapper);
817 event.Signal();
818returntrue;
819}
820
821uint64_t request_id;
822 base::WaitableEvent event;
823MessageWrapper message;
824};
825
Keishi Hattori0e45c022021-11-27 09:25:52[diff] [blame]826const raw_ptr<ChannelAssociatedGroupController> controller_;
rockot02b8e182016-07-13 20:08:30[diff] [blame]827const mojo::InterfaceId id_;
828
829bool closed_=false;
830bool peer_closed_=false;
yzshenea784ea2017-01-31 21:20:20[diff] [blame]831bool handle_created_=false;
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]832bool was_bound_off_sequence_=false;
Arthur Sonzogni59ac8222023-11-10 09:46:54[diff] [blame]833 std::optional<mojo::DisconnectReason> disconnect_reason_;
Keishi Hattori0e45c022021-11-27 09:25:52[diff] [blame]834 raw_ptr<mojo::InterfaceEndpointClient> client_=nullptr;
Sam McNallyde5ae672017-06-19 23:34:45[diff] [blame]835 scoped_refptr<base::SequencedTaskRunner> task_runner_;
Ken Rockotaa20dcc2018-03-28 03:06:51[diff] [blame]836 std::unique_ptr<mojo::SequenceLocalSyncEventWatcher> sync_watcher_;
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]837 base::circular_deque<std::pair<uint32_t,MessageWrapper>> sync_messages_;
Keishi Hattoric1b00232022-11-22 09:04:26[diff] [blame]838 raw_ptr<ExclusiveSyncWait> exclusive_wait_=nullptr;
rockot9abe09b2016-08-02 20:57:34[diff] [blame]839uint32_t next_sync_message_id_=0;
rockot02b8e182016-07-13 20:08:30[diff] [blame]840};
841
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]842classControlMessageProxyThunk:publicMessageReceiver{
843public:
844explicitControlMessageProxyThunk(
845ChannelAssociatedGroupController* controller)
846: controller_(controller){}
847
Peter Boström896f1372021-11-05 01:12:30[diff] [blame]848ControlMessageProxyThunk(constControlMessageProxyThunk&)=delete;
849ControlMessageProxyThunk&operator=(constControlMessageProxyThunk&)=
850delete;
851
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]852private:
853// MessageReceiver:
854boolAccept(mojo::Message* message) override{
855return controller_->SendMessage(message);
856}
857
Keishi Hattori0e45c022021-11-27 09:25:52[diff] [blame]858 raw_ptr<ChannelAssociatedGroupController> controller_;
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]859};
860
rockot02b8e182016-07-13 20:08:30[diff] [blame]861~ChannelAssociatedGroupController() override{
rockotb01ef6a2016-07-27 03:24:32[diff] [blame]862 DCHECK(!connector_);
863
rockot02b8e182016-07-13 20:08:30[diff] [blame]864 base::AutoLock locker(lock_);
rockot02b8e182016-07-13 20:08:30[diff] [blame]865for(auto iter= endpoints_.begin(); iter!= endpoints_.end();){
866Endpoint* endpoint= iter->second.get();
867++iter;
868
yzshene003d592017-01-24 21:42:17[diff] [blame]869if(!endpoint->closed()){
870// This happens when a NotifyPeerEndpointClosed message been received,
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]871// but the interface ID hasn't been used to create local endpoint
872// handle.
yzshene003d592017-01-24 21:42:17[diff] [blame]873 DCHECK(!endpoint->client());
874 DCHECK(endpoint->peer_closed());
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]875MarkClosed(endpoint);
yzshene003d592017-01-24 21:42:17[diff] [blame]876}else{
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]877MarkPeerClosed(endpoint);
yzshene003d592017-01-24 21:42:17[diff] [blame]878}
rockot02b8e182016-07-13 20:08:30[diff] [blame]879}
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]880 endpoints_.clear();
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]881
882GetMemoryDumpProvider().RemoveController(this);
rockot02b8e182016-07-13 20:08:30[diff] [blame]883}
884
885boolSendMessage(mojo::Message* message){
Siddhartha S03484422019-04-23 20:30:00[diff] [blame]886 DCHECK(message->heap_profiler_tag());
rockot7604e7b72016-07-28 17:37:39[diff] [blame]887if(task_runner_->BelongsToCurrentThread()){
François Dorayfad1b8b2024-01-04 20:22:53[diff] [blame]888returnSendMessageOnSequence(message);
rockot02b8e182016-07-13 20:08:30[diff] [blame]889}
François Dorayfad1b8b2024-01-04 20:22:53[diff] [blame]890
891// PostTask (or RunOrPostTask) so that `message` is sent after messages from
892// tasks that are already queued (e.g. by `IPC::ChannelProxy::Send`).
893auto callback= base::BindOnce(
894&ChannelAssociatedGroupController::SendMessageOnSequenceViaTask,this,
895 std::move(*message));
896if(base::FeatureList::IsEnabled(
897 kMojoChannelAssociatedSendUsesRunOrPostTask)){
898 task_runner_->RunOrPostTask(base::subtle::RunOrPostTaskPassKey(),
899 FROM_HERE, std::move(callback));
900}else{
901 task_runner_->PostTask(FROM_HERE, std::move(callback));
902}
903
904returntrue;
rockot02b8e182016-07-13 20:08:30[diff] [blame]905}
906
François Dorayfad1b8b2024-01-04 20:22:53[diff] [blame]907boolSendMessageOnSequence(mojo::Message* message){
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]908 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
909 was_bound_or_message_sent_=true;
910
François Dorayfad1b8b2024-01-04 20:22:53[diff] [blame]911if(!connector_|| paused_){
912if(!shut_down_){
913 base::AutoLock lock(outgoing_messages_lock_);
914 outgoing_messages_.emplace_back(std::move(*message));
915}
916returntrue;
917}
François Doray927a0822024-05-15 21:57:28[diff] [blame]918
François Dorayfb408352024-10-29 17:11:59[diff] [blame]919MojoResult result= connector_->AcceptAndGetResult(message);
920if(result== MOJO_RESULT_OK){
921returntrue;
François Doray927a0822024-05-15 21:57:28[diff] [blame]922}
923
Daniel Cheng84e7ad42025-05-26 23:02:27[diff] [blame]924 CHECK(connector_->encountered_error());
François Dorayfb408352024-10-29 17:11:59[diff] [blame]925returnfalse;
François Dorayfad1b8b2024-01-04 20:22:53[diff] [blame]926}
927
928voidSendMessageOnSequenceViaTask(mojo::Message message){
929if(!SendMessageOnSequence(&message)){
rockot02b8e182016-07-13 20:08:30[diff] [blame]930RaiseError();
François Dorayfad1b8b2024-01-04 20:22:53[diff] [blame]931}
rockot02b8e182016-07-13 20:08:30[diff] [blame]932}
933
934voidOnPipeError(){
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]935 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
rockot02b8e182016-07-13 20:08:30[diff] [blame]936
937// We keep |this| alive here because it's possible for the notifications
938// below to release all other references.
939 scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
940
941 base::AutoLock locker(lock_);
942 encountered_error_=true;
943
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]944 std::vector<uint32_t> endpoints_to_remove;
rockot02b8e182016-07-13 20:08:30[diff] [blame]945 std::vector<scoped_refptr<Endpoint>> endpoints_to_notify;
946for(auto iter= endpoints_.begin(); iter!= endpoints_.end();){
947Endpoint* endpoint= iter->second.get();
948++iter;
949
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]950if(endpoint->client()){
rockot02b8e182016-07-13 20:08:30[diff] [blame]951 endpoints_to_notify.push_back(endpoint);
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]952}
rockot02b8e182016-07-13 20:08:30[diff] [blame]953
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]954if(MarkPeerClosed(endpoint)){
955 endpoints_to_remove.push_back(endpoint->id());
956}
rockot02b8e182016-07-13 20:08:30[diff] [blame]957}
958
959for(auto& endpoint: endpoints_to_notify){
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]960// Because a notification may in turn detach any endpoint, we have to
rockot02b8e182016-07-13 20:08:30[diff] [blame]961// check each client again here.
962if(endpoint->client())
963NotifyEndpointOfError(endpoint.get(),false/* force_async */);
964}
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]965
966for(uint32_t id: endpoints_to_remove){
967 endpoints_.erase(id);
968}
rockot02b8e182016-07-13 20:08:30[diff] [blame]969}
970
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]971voidNotifyEndpointOfError(Endpoint* endpoint,bool force_async)
972 EXCLUSIVE_LOCKS_REQUIRED(lock_){
rockot02b8e182016-07-13 20:08:30[diff] [blame]973 DCHECK(endpoint->task_runner()&& endpoint->client());
peary28cd3bd22017-06-29 02:15:28[diff] [blame]974if(endpoint->task_runner()->RunsTasksInCurrentSequence()&&!force_async){
rockot02b8e182016-07-13 20:08:30[diff] [blame]975 mojo::InterfaceEndpointClient* client= endpoint->client();
Arthur Sonzogni59ac8222023-11-10 09:46:54[diff] [blame]976 std::optional<mojo::DisconnectReason> reason(
yzshen8be41d3a2017-01-23 20:40:37[diff] [blame]977 endpoint->disconnect_reason());
rockot02b8e182016-07-13 20:08:30[diff] [blame]978
979 base::AutoUnlock unlocker(lock_);
yzshen8be41d3a2017-01-23 20:40:37[diff] [blame]980 client->NotifyError(reason);
rockot02b8e182016-07-13 20:08:30[diff] [blame]981}else{
982 endpoint->task_runner()->PostTask(
Ari Chivukula2bf6f292022-11-28 18:29:46[diff] [blame]983 FROM_HERE,
984 base::BindOnce(&ChannelAssociatedGroupController::
985NotifyEndpointOfErrorOnEndpointThread,
986this, endpoint->id(),
987// This is safe as `endpoint` is verified to be in
988// `endpoints_` (a map with ownership) before use.
989 base::UnsafeDangling(endpoint)));
rockot02b8e182016-07-13 20:08:30[diff] [blame]990}
991}
992
Ari Chivukula2bf6f292022-11-28 18:29:46[diff] [blame]993// `endpoint` might be a dangling ptr and must be checked before dereference.
rockot9abe09b2016-08-02 20:57:34[diff] [blame]994voidNotifyEndpointOfErrorOnEndpointThread(mojo::InterfaceId id,
Paul Semelff2ca67b2022-12-21 15:46:02[diff] [blame]995MayBeDangling<Endpoint> endpoint){
rockot02b8e182016-07-13 20:08:30[diff] [blame]996 base::AutoLock locker(lock_);
rockot9abe09b2016-08-02 20:57:34[diff] [blame]997auto iter= endpoints_.find(id);
998if(iter== endpoints_.end()|| iter->second.get()!= endpoint)
999return;
rockot02b8e182016-07-13 20:08:30[diff] [blame]1000if(!endpoint->client())
1001return;
rockot9abe09b2016-08-02 20:57:34[diff] [blame]1002
peary28cd3bd22017-06-29 02:15:28[diff] [blame]1003 DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
rockot9abe09b2016-08-02 20:57:34[diff] [blame]1004NotifyEndpointOfError(endpoint,false/* force_async */);
rockot02b8e182016-07-13 20:08:30[diff] [blame]1005}
1006
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]1007// Marks `endpoint` as closed and returns true if and only if its peer was
1008// also already closed.
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1009boolMarkClosed(Endpoint* endpoint) EXCLUSIVE_LOCKS_REQUIRED(lock_){
rockot02b8e182016-07-13 20:08:30[diff] [blame]1010 endpoint->set_closed();
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]1011return endpoint->peer_closed();
Ken Rockot68645462023-11-07 23:11:56[diff] [blame]1012}
1013
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]1014// Marks `endpoint` as having a closed peer and returns true if and only if
1015// `endpoint` itself was also already closed.
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1016boolMarkPeerClosed(Endpoint* endpoint) EXCLUSIVE_LOCKS_REQUIRED(lock_){
Igor Kraskevich0e427862023-11-08 10:13:53[diff] [blame]1017 endpoint->set_peer_closed();
1018 endpoint->SignalSyncMessageEvent();
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]1019return endpoint->closed();
1020}
1021
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1022voidMarkClosedAndMaybeRemove(Endpoint* endpoint)
1023 EXCLUSIVE_LOCKS_REQUIRED(lock_){
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]1024if(MarkClosed(endpoint)){
Ken Rockot68645462023-11-07 23:11:56[diff] [blame]1025 endpoints_.erase(endpoint->id());
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]1026}
1027}
1028
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1029voidMarkPeerClosedAndMaybeRemove(Endpoint* endpoint)
1030 EXCLUSIVE_LOCKS_REQUIRED(lock_){
Ken Rockotcd4c1f12023-11-08 23:22:16[diff] [blame]1031if(MarkPeerClosed(endpoint)){
1032 endpoints_.erase(endpoint->id());
1033}
rockot02b8e182016-07-13 20:08:30[diff] [blame]1034}
1035
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1036Endpoint*FindOrInsertEndpoint(mojo::InterfaceId id,bool* inserted)
1037 EXCLUSIVE_LOCKS_REQUIRED(lock_){
rockot02b8e182016-07-13 20:08:30[diff] [blame]1038 DCHECK(!inserted||!*inserted);
1039
yzshen0a5971312017-02-02 05:13:47[diff] [blame]1040Endpoint* endpoint=FindEndpoint(id);
1041if(!endpoint){
1042 endpoint=newEndpoint(this, id);
1043 endpoints_.insert({id, endpoint});
1044if(inserted)
1045*inserted=true;
1046}
rockot02b8e182016-07-13 20:08:30[diff] [blame]1047return endpoint;
1048}
1049
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1050Endpoint*FindEndpoint(mojo::InterfaceId id) EXCLUSIVE_LOCKS_REQUIRED(lock_){
yzshen0a5971312017-02-02 05:13:47[diff] [blame]1051auto iter= endpoints_.find(id);
1052return iter!= endpoints_.end()? iter->second.get():nullptr;
1053}
1054
rockot02b8e182016-07-13 20:08:30[diff] [blame]1055// mojo::MessageReceiver:
1056boolAccept(mojo::Message* message) override{
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1057 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
rockot02b8e182016-07-13 20:08:30[diff] [blame]1058
yzshen0a5971312017-02-02 05:13:47[diff] [blame]1059if(!message->DeserializeAssociatedEndpointHandles(this))
1060returnfalse;
1061
1062if(mojo::PipeControlMessageHandler::IsPipeControlMessage(message))
1063return control_message_handler_.Accept(message);
rockot02b8e182016-07-13 20:08:30[diff] [blame]1064
1065 mojo::InterfaceId id= message->interface_id();
Ken Rockot9f69e162021-04-19 14:16:29[diff] [blame]1066if(!mojo::IsValidInterfaceId(id))
1067returnfalse;
rockot02b8e182016-07-13 20:08:30[diff] [blame]1068
Ken Rockot4fede4552019-05-09 01:16:41[diff] [blame]1069 base::ReleasableAutoLock locker(&lock_);
yzshen0a5971312017-02-02 05:13:47[diff] [blame]1070Endpoint* endpoint=FindEndpoint(id);
1071if(!endpoint)
1072returntrue;
1073
1074 mojo::InterfaceEndpointClient* client= endpoint->client();
peary28cd3bd22017-06-29 02:15:28[diff] [blame]1075if(!client||!endpoint->task_runner()->RunsTasksInCurrentSequence()){
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]1076// The ChannelProxy for this channel is bound to `proxy_task_runner_` and
1077// by default legacy IPCs must dispatch to either the IO thread or the
1078// proxy task runner. We generally impose the same constraint on
1079// associated interface endpoints so that FIFO can be guaranteed across
1080// all interfaces without stalling any of them to wait for a pending
1081// endpoint to be bound.
rockot02b8e182016-07-13 20:08:30[diff] [blame]1082//
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]1083// This allows us to assume that if an endpoint is not yet bound when we
1084// receive a message targeting it, it *will* be bound on the proxy task
1085// runner by the time a newly posted task runs there. Hence we simply post
1086// a hopeful dispatch task to that task runner.
1087//
1088// As it turns out, there are even some instances of endpoints binding to
1089// alternative (non-IO-thread, non-proxy) task runners, but still
1090// ultimately relying on the fact that we schedule their messages on the
1091// proxy task runner. So even if the endpoint is already bound, we
1092// default to scheduling it on the proxy task runner as long as it's not
1093// bound specifically to the IO task runner.
1094// TODO(rockot): Try to sort out these cases and maybe eliminate them.
1095//
1096// Finally, it's also possible that an endpoint was bound to an
1097// alternative task runner and it really does want its messages to
1098// dispatch there. In that case `was_bound_off_sequence()` will be true to
1099// signal that we should really use that task runner.
1100const scoped_refptr<base::SequencedTaskRunner> task_runner=
1101 client&& endpoint->was_bound_off_sequence()
1102? endpoint->task_runner()
1103: proxy_task_runner_.get();
rockot9abe09b2016-08-02 20:57:34[diff] [blame]1104
Scott Haseleycf0f1722023-11-03 21:39:01[diff] [blame]1105ScopedUrgentMessageNotification scoped_urgent_message_notification(
1106 message->has_flag(mojo::Message::kFlagIsUrgent)
1107? urgent_message_observer_
1108:nullptr);
1109
rockotc4cc691e2016-08-19 18:48:57[diff] [blame]1110if(message->has_flag(mojo::Message::kFlagIsSync)){
yzshen0a5971312017-02-02 05:13:47[diff] [blame]1111MessageWrapper message_wrapper(this, std::move(*message));
rockot9abe09b2016-08-02 20:57:34[diff] [blame]1112// Sync messages may need to be handled by the endpoint if it's blocking
1113// on a sync reply. We pass ownership of the message to the endpoint's
1114// sync message queue. If the endpoint was blocking, it will dequeue the
1115// message and dispatch it. Otherwise the posted |AcceptSyncMessage()|
1116// call will dequeue the message and dispatch it.
Arthur Sonzogni59ac8222023-11-10 09:46:54[diff] [blame]1117 std::optional<uint32_t> message_id=
yzshenea784ea2017-01-31 21:20:20[diff] [blame]1118 endpoint->EnqueueSyncMessage(std::move(message_wrapper));
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]1119if(message_id){
1120 task_runner->PostTask(
1121 FROM_HERE,
1122 base::BindOnce(
1123&ChannelAssociatedGroupController::AcceptSyncMessage,this,
Scott Haseleycf0f1722023-11-03 21:39:01[diff] [blame]1124 id,*message_id,
1125 std::move(scoped_urgent_message_notification)));
Ken Rockotb6f92122022-10-31 04:52:24[diff] [blame]1126}
rockot9abe09b2016-08-02 20:57:34[diff] [blame]1127returntrue;
1128}
1129
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]1130// If |task_runner| has been torn down already, this PostTask will fail
1131// and destroy |message|. That operation may need to in turn destroy
Ken Rockot4fede4552019-05-09 01:16:41[diff] [blame]1132// in-transit associated endpoints and thus acquire |lock_|. We no longer
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]1133// need the lock to be held now, so we can release it before the PostTask.
Harkiran Bolaria8b1cf112020-09-15 22:58:34[diff] [blame]1134{
1135// Grab interface name from |client| before releasing the lock to ensure
1136// that |client| is safe to access.
1137 base::TaskAnnotator::ScopedSetIpcHash scoped_set_ipc_hash(
1138 client? client->interface_name():"unknown interface");
1139 locker.Release();
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]1140 task_runner->PostTask(
Harkiran Bolaria8b1cf112020-09-15 22:58:34[diff] [blame]1141 FROM_HERE,
1142 base::BindOnce(
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]1143&ChannelAssociatedGroupController::AcceptOnEndpointThread,this,
Scott Haseleycf0f1722023-11-03 21:39:01[diff] [blame]1144 std::move(*message),
1145 std::move(scoped_urgent_message_notification)));
Harkiran Bolaria8b1cf112020-09-15 22:58:34[diff] [blame]1146}
rockot02b8e182016-07-13 20:08:30[diff] [blame]1147returntrue;
1148}
1149
Ken Rockot4fede4552019-05-09 01:16:41[diff] [blame]1150 locker.Release();
Harkiran Bolaria8b1cf112020-09-15 22:58:34[diff] [blame]1151// It's safe to access |client| here without holding a lock, because this
1152// code runs on a proxy thread and |client| can't be destroyed from any
1153// thread.
yzshen0a5971312017-02-02 05:13:47[diff] [blame]1154return client->HandleIncomingMessage(message);
rockot02b8e182016-07-13 20:08:30[diff] [blame]1155}
1156
Scott Haseleycf0f1722023-11-03 21:39:01[diff] [blame]1157voidAcceptOnEndpointThread(
1158 mojo::Message message,
1159ScopedUrgentMessageNotification scoped_urgent_message_notification){
Stephen Nusko8e400642020-09-16 13:48:59[diff] [blame]1160 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("mojom"),
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]1161"ChannelAssociatedGroupController::AcceptOnEndpointThread");
rockot02b8e182016-07-13 20:08:30[diff] [blame]1162
rockotc4cc691e2016-08-19 18:48:57[diff] [blame]1163 mojo::InterfaceId id= message.interface_id();
Ken Rockotcd23f752020-06-20 01:22:31[diff] [blame]1164 DCHECK(mojo::IsValidInterfaceId(id)&&!mojo::IsPrimaryInterfaceId(id));
rockot8d890f62016-07-14 16:37:14[diff] [blame]1165
1166 base::AutoLock locker(lock_);
yzshen0a5971312017-02-02 05:13:47[diff] [blame]1167Endpoint* endpoint=FindEndpoint(id);
rockot8d890f62016-07-14 16:37:14[diff] [blame]1168if(!endpoint)
1169return;
1170
1171 mojo::InterfaceEndpointClient* client= endpoint->client();
Greg Thompsonfe432e762021-06-04 06:47:14[diff] [blame]1172if(!client)
rockot8d890f62016-07-14 16:37:14[diff] [blame]1173return;
1174
Ken Rockot0747c942021-12-07 20:51:59[diff] [blame]1175if(!endpoint->task_runner()->RunsTasksInCurrentSequence()&&
1176!proxy_task_runner_->RunsTasksInCurrentSequence()){
1177return;
1178}
1179
Alexander Timin24027abc2022-02-24 00:47:55[diff] [blame]1180// TODO(altimin): This event is temporarily kept as a debug fallback. Remove
1181// it once the new implementation proves to be stable.
Alexander Timinda1f2c52021-11-03 02:23:05[diff] [blame]1182 TRACE_EVENT(
Alexander Timin24027abc2022-02-24 00:47:55[diff] [blame]1183 TRACE_DISABLED_BY_DEFAULT("mojom"),
Alexander Timinda1f2c52021-11-03 02:23:05[diff] [blame]1184// Using client->interface_name() is safe here because this is a static
1185// string defined for each mojo interface.
1186 perfetto::StaticString(client->interface_name()),
1187[&](perfetto::EventContext& ctx){
1188staticconstuint8_t* toplevel_flow_enabled=
1189 TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("toplevel.flow");
1190if(!*toplevel_flow_enabled)
1191return;
1192
1193 perfetto::Flow::Global(message.GetTraceId())(ctx);
1194});
rockot8d890f62016-07-14 16:37:14[diff] [blame]1195
rockot9abe09b2016-08-02 20:57:34[diff] [blame]1196// Sync messages should never make their way to this method.
yzshen0a5971312017-02-02 05:13:47[diff] [blame]1197 DCHECK(!message.has_flag(mojo::Message::kFlagIsSync));
rockot8d890f62016-07-14 16:37:14[diff] [blame]1198
1199bool result=false;
1200{
1201 base::AutoUnlock unlocker(lock_);
yzshen0a5971312017-02-02 05:13:47[diff] [blame]1202 result= client->HandleIncomingMessage(&message);
rockot8d890f62016-07-14 16:37:14[diff] [blame]1203}
1204
1205if(!result)
1206RaiseError();
1207}
1208
Scott Haseleycf0f1722023-11-03 21:39:01[diff] [blame]1209voidAcceptSyncMessage(
1210 mojo::InterfaceId interface_id,
1211uint32_t message_id,
1212ScopedUrgentMessageNotification scoped_urgent_message_notification){
Stephen Nusko8e400642020-09-16 13:48:59[diff] [blame]1213 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("mojom"),
1214"ChannelAssociatedGroupController::AcceptSyncMessage");
rockot9abe09b2016-08-02 20:57:34[diff] [blame]1215
1216 base::AutoLock locker(lock_);
yzshen0a5971312017-02-02 05:13:47[diff] [blame]1217Endpoint* endpoint=FindEndpoint(interface_id);
rockot9abe09b2016-08-02 20:57:34[diff] [blame]1218if(!endpoint)
1219return;
1220
csharrison1af8d6ab2017-04-21 17:47:23[diff] [blame]1221// Careful, if the endpoint is detached its members are cleared. Check for
1222// that before dereferencing.
1223 mojo::InterfaceEndpointClient* client= endpoint->client();
1224if(!client)
1225return;
1226
Ken Rockot0747c942021-12-07 20:51:59[diff] [blame]1227if(!endpoint->task_runner()->RunsTasksInCurrentSequence()&&
1228!proxy_task_runner_->RunsTasksInCurrentSequence()){
1229return;
1230}
1231
Stephen Nusko8e400642020-09-16 13:48:59[diff] [blame]1232// Using client->interface_name() is safe here because this is a static
1233// string defined for each mojo interface.
1234 TRACE_EVENT0("mojom", client->interface_name());
yzshen0a5971312017-02-02 05:13:47[diff] [blame]1235MessageWrapper message_wrapper= endpoint->PopSyncMessage(message_id);
rockot9abe09b2016-08-02 20:57:34[diff] [blame]1236
1237// The message must have already been dequeued by the endpoint waking up
1238// from a sync wait. Nothing to do.
yzshenea784ea2017-01-31 21:20:20[diff] [blame]1239if(message_wrapper.value().IsNull())
rockot9abe09b2016-08-02 20:57:34[diff] [blame]1240return;
1241
rockot9abe09b2016-08-02 20:57:34[diff] [blame]1242bool result=false;
1243{
1244 base::AutoUnlock unlocker(lock_);
yzshen0a5971312017-02-02 05:13:47[diff] [blame]1245 result= client->HandleIncomingMessage(&message_wrapper.value());
rockot9abe09b2016-08-02 20:57:34[diff] [blame]1246}
1247
1248if(!result)
1249RaiseError();
1250}
1251
rockot02b8e182016-07-13 20:08:30[diff] [blame]1252// mojo::PipeControlMessageHandlerDelegate:
yzshen8be41d3a2017-01-23 20:40:37[diff] [blame]1253boolOnPeerAssociatedEndpointClosed(
1254 mojo::InterfaceId id,
Arthur Sonzogni59ac8222023-11-10 09:46:54[diff] [blame]1255const std::optional<mojo::DisconnectReason>& reason) override{
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1256 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
rockot02b8e182016-07-13 20:08:30[diff] [blame]1257
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]1258 scoped_refptr<ChannelAssociatedGroupController> keepalive(this);
rockot02b8e182016-07-13 20:08:30[diff] [blame]1259 base::AutoLock locker(lock_);
1260 scoped_refptr<Endpoint> endpoint=FindOrInsertEndpoint(id,nullptr);
yzshen8be41d3a2017-01-23 20:40:37[diff] [blame]1261if(reason)
1262 endpoint->set_disconnect_reason(reason);
rockot02b8e182016-07-13 20:08:30[diff] [blame]1263if(!endpoint->peer_closed()){
1264if(endpoint->client())
1265NotifyEndpointOfError(endpoint.get(),false/* force_async */);
1266MarkPeerClosedAndMaybeRemove(endpoint.get());
1267}
1268
1269returntrue;
1270}
1271
Ken Rockoteb2366a2020-01-13 21:13:46[diff] [blame]1272boolWaitForFlushToComplete(
1273 mojo::ScopedMessagePipeHandle flush_pipe) override{
1274// We don't support async flushing on the IPC Channel pipe.
1275returnfalse;
1276}
1277
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1278const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
Ken Rockot4fede4552019-05-09 01:16:41[diff] [blame]1279const scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_;
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]1280constbool set_interface_id_namespace_bit_;
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1281
1282// Ensures sequenced access to members below.
1283 SEQUENCE_CHECKER(sequence_checker_);
1284
1285// Whether `Bind()` or `SendMessageOnSequence()` was called.
1286// `sequence_checker_` can be detached when this is `false`.
1287bool was_bound_or_message_sent_ GUARDED_BY_CONTEXT(sequence_checker_)=false;
1288
1289bool paused_ GUARDED_BY_CONTEXT(sequence_checker_)=false;
1290bool shut_down_ GUARDED_BY_CONTEXT(sequence_checker_)=false;
1291 std::unique_ptr<mojo::Connector> connector_
1292 GUARDED_BY_CONTEXT(sequence_checker_);
1293 mojo::MessageDispatcher dispatcher_ GUARDED_BY_CONTEXT(sequence_checker_);
1294 mojo::PipeControlMessageHandler control_message_handler_
1295 GUARDED_BY_CONTEXT(sequence_checker_);
1296ControlMessageProxyThunk control_message_proxy_thunk_
1297 GUARDED_BY_CONTEXT(sequence_checker_);
1298 raw_ptr<UrgentMessageObserver> urgent_message_observer_
1299 GUARDED_BY_CONTEXT(sequence_checker_)=nullptr;
rockot58909542016-11-10 20:05:45[diff] [blame]1300
1301// NOTE: It is unsafe to call into this object while holding |lock_|.
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]1302 mojo::PipeControlMessageProxy control_message_proxy_;
1303
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1304// Outgoing messages sent before this controller Bound() to a pipe or while it
1305// was paused. Protected by a lock to support memory dumps from any thread.
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]1306 base::Lock outgoing_messages_lock_;
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1307 std::vector<mojo::Message> outgoing_messages_
1308 GUARDED_BY(outgoing_messages_lock_);
rockot02b8e182016-07-13 20:08:30[diff] [blame]1309
1310// Guards the fields below for thread-safe access.
1311 base::Lock lock_;
1312
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1313bool encountered_error_ GUARDED_BY(lock_)=false;
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]1314
1315// ID #1 is reserved for the mojom::Channel interface.
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1316uint32_t next_interface_id_ GUARDED_BY(lock_)=2;
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]1317
François Dorayf8ec16da22024-01-17 21:55:12[diff] [blame]1318 std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_ GUARDED_BY(lock_);
rockot02b8e182016-07-13 20:08:30[diff] [blame]1319};
1320
François Dorayfad1b8b2024-01-04 20:22:53[diff] [blame]1321namespace{
1322
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]1323boolControllerMemoryDumpProvider::OnMemoryDump(
1324const base::trace_event::MemoryDumpArgs& args,
1325 base::trace_event::ProcessMemoryDump* pmd){
1326 base::AutoLock lock(lock_);
Ali Hijazi133b2d92024-02-09 14:01:52[diff] [blame]1327for(ChannelAssociatedGroupController* controller: controllers_){
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]1328 base::trace_event::MemoryAllocatorDump* dump= pmd->CreateAllocatorDump(
1329 base::StringPrintf("mojo/queued_ipc_channel_message/0x%"PRIxPTR,
1330reinterpret_cast<uintptr_t>(controller)));
1331 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
1332 base::trace_event::MemoryAllocatorDump::kUnitsObjects,
1333 controller->GetQueuedMessageCount());
Siddhartha S03484422019-04-23 20:30:00[diff] [blame]1334MessageMemoryDumpInfo info;
1335size_t count=0;
1336 controller->GetTopQueuedMessageMemoryDumpInfo(&info,&count);
1337 dump->AddScalar("top_message_name","id", info.id);
Siddharthad1cfec12018-09-17 21:42:15[diff] [blame]1338 dump->AddScalar("top_message_count",
1339 base::trace_event::MemoryAllocatorDump::kUnitsObjects,
Siddhartha S03484422019-04-23 20:30:00[diff] [blame]1340 count);
1341
1342if(info.profiler_tag){
1343// TODO(ssid): Memory dumps currently do not support adding string
1344// arguments in background dumps. So, add this value as a trace event for
1345// now.
ssidbc86cb72019-05-16 00:25:37[diff] [blame]1346 TRACE_EVENT2(base::trace_event::MemoryDumpManager::kTraceCategory,
Siddhartha S03484422019-04-23 20:30:00[diff] [blame]1347"ControllerMemoryDumpProvider::OnMemoryDump",
ssidbc86cb72019-05-16 00:25:37[diff] [blame]1348"top_queued_message_tag", info.profiler_tag,
1349"count", count);
Siddhartha S03484422019-04-23 20:30:00[diff] [blame]1350}
Ken Rockot2b6de982018-03-20 22:28:13[diff] [blame]1351}
1352
1353returntrue;
1354}
1355
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]1356classMojoBootstrapImpl:publicMojoBootstrap{
rockot02b8e182016-07-13 20:08:30[diff] [blame]1357public:
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]1358MojoBootstrapImpl(
1359 mojo::ScopedMessagePipeHandle handle,
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]1360const scoped_refptr<ChannelAssociatedGroupController> controller)
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]1361: controller_(controller),
1362 associated_group_(controller),
1363 handle_(std::move(handle)){}
rockot02b8e182016-07-13 20:08:30[diff] [blame]1364
Peter Boströmc68c5aa2021-09-28 00:28:00[diff] [blame]1365MojoBootstrapImpl(constMojoBootstrapImpl&)=delete;
1366MojoBootstrapImpl&operator=(constMojoBootstrapImpl&)=delete;
1367
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]1368~MojoBootstrapImpl() override{
1369 controller_->ShutDown();
rockot02b8e182016-07-13 20:08:30[diff] [blame]1370}
1371
1372private:
Julie Jeongeun Kim903b34b2019-09-25 11:11:54[diff] [blame]1373voidConnect(
Ken Rockotfbbd4442021-06-04 01:19:14[diff] [blame]1374 mojo::PendingAssociatedRemote<mojom::Channel>* sender,
Julie Jeongeun Kim903b34b2019-09-25 11:11:54[diff] [blame]1375 mojo::PendingAssociatedReceiver<mojom::Channel>* receiver) override{
Ken Rockot9fae8bcd2021-06-04 22:09:49[diff] [blame]1376 controller_->Bind(std::move(handle_), sender, receiver);
msramek5507fee2016-07-22 10:06:21[diff] [blame]1377}
1378
Ken Rockot9fae8bcd2021-06-04 22:09:49[diff] [blame]1379voidStartReceiving() override{ controller_->StartReceiving();}
1380
rockot10188752016-09-08 18:24:56[diff] [blame]1381voidPause() override{
1382 controller_->Pause();
1383}
1384
1385voidUnpause() override{
1386 controller_->Unpause();
rockot401fb2c2016-09-06 18:35:57[diff] [blame]1387}
1388
1389voidFlush() override{
1390 controller_->FlushOutgoingMessages();
1391}
1392
msramek5507fee2016-07-22 10:06:21[diff] [blame]1393 mojo::AssociatedGroup*GetAssociatedGroup() override{
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]1394return&associated_group_;
msramek5507fee2016-07-22 10:06:21[diff] [blame]1395}
1396
Scott Haseleycf0f1722023-11-03 21:39:01[diff] [blame]1397voidSetUrgentMessageObserver(UrgentMessageObserver* observer) override{
1398 controller_->SetUrgentMessageObserver(observer);
1399}
1400
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]1401 scoped_refptr<ChannelAssociatedGroupController> controller_;
yzshen2859a2ac2017-02-14 22:24:25[diff] [blame]1402 mojo::AssociatedGroup associated_group_;
msramek5507fee2016-07-22 10:06:21[diff] [blame]1403
rockot0e4de5f2016-07-22 21:18:07[diff] [blame]1404 mojo::ScopedMessagePipeHandle handle_;
msramek5507fee2016-07-22 10:06:21[diff] [blame]1405};
1406
morrita54f6f80c2014-09-23 21:16:00[diff] [blame]1407}// namespace
1408
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]1409ScopedAllowOffSequenceChannelAssociatedBindings::
1410ScopedAllowOffSequenceChannelAssociatedBindings()
Peter Kasting525a0142023-03-08 21:56:27[diff] [blame]1411: resetter_(&off_sequence_binding_allowed,true){}
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]1412
1413ScopedAllowOffSequenceChannelAssociatedBindings::
Peter Kasting525a0142023-03-08 21:56:27[diff] [blame]1414~ScopedAllowOffSequenceChannelAssociatedBindings()=default;
Ken Rockotc5cc02732021-06-04 08:02:41[diff] [blame]1415
morrita54f6f80c2014-09-23 21:16:00[diff] [blame]1416// static
danakj03de39b22016-04-23 04:21:09[diff] [blame]1417std::unique_ptr<MojoBootstrap>MojoBootstrap::Create(
sammc57ed9f982016-03-10 06:28:35[diff] [blame]1418 mojo::ScopedMessagePipeHandle handle,
1419Channel::Mode mode,
Hajime Hoshia98f1102017-11-20 06:34:35[diff] [blame]1420const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
Ken Rockot7308d4b2022-12-13 06:35:56[diff] [blame]1421const scoped_refptr<base::SingleThreadTaskRunner>& proxy_task_runner){
Jeremy Roman160eb922017-08-29 17:43:43[diff] [blame]1422return std::make_unique<MojoBootstrapImpl>(
Ken Rockot7308d4b2022-12-13 06:35:56[diff] [blame]1423 std::move(handle),
1424 base::MakeRefCounted<ChannelAssociatedGroupController>(
1425 mode==Channel::MODE_SERVER, ipc_task_runner, proxy_task_runner));
sammc57ed9f982016-03-10 06:28:35[diff] [blame]1426}
1427
morrita54f6f80c2014-09-23 21:16:00[diff] [blame]1428}// namespace IPC

[8]ページ先頭

©2009-2025 Movatter.jp