1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ipc/ipc_channel_mojo.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <atomic>
11 #include <cstdint>
12 #include <memory>
13 #include <utility>
14
15 #include <optional>
16 #include "base/base_paths.h"
17 #include "base/containers/queue.h"
18 #include "base/files/file.h"
19 #include "base/files/scoped_temp_dir.h"
20 #include "base/functional/bind.h"
21 #include "base/functional/callback_helpers.h"
22 #include "base/location.h"
23 #include "base/memory/platform_shared_memory_region.h"
24 #include "base/memory/raw_ptr.h"
25 #include "base/memory/read_only_shared_memory_region.h"
26 #include "base/memory/shared_memory_mapping.h"
27 #include "base/memory/unsafe_shared_memory_region.h"
28 #include "base/memory/writable_shared_memory_region.h"
29 #include "base/message_loop/message_pump_type.h"
30 #include "base/path_service.h"
31 #include "base/pickle.h"
32 #include "base/process/process.h"
33 #include "base/run_loop.h"
34 #include "base/synchronization/waitable_event.h"
35 #include "base/task/single_thread_task_runner.h"
36 #include "base/test/bind.h"
37 #include "base/test/task_environment.h"
38 #include "base/test/test_io_thread.h"
39 #include "base/test/test_shared_memory_util.h"
40 #include "base/test/test_timeouts.h"
41 #include "base/threading/thread.h"
42 #include "build/build_config.h"
43 #include "ipc/ipc_message.h"
44 #include "ipc/ipc_message_utils.h"
45 #include "ipc/ipc_mojo_handle_attachment.h"
46 #include "ipc/ipc_mojo_message_helper.h"
47 #include "ipc/ipc_mojo_param_traits.h"
48 #include "ipc/ipc_sync_channel.h"
49 #include "ipc/ipc_sync_message.h"
50 #include "ipc/ipc_test.mojom.h"
51 #include "ipc/ipc_test_base.h"
52 #include "ipc/ipc_test_channel_listener.h"
53 #include "ipc/urgent_message_observer.h"
54 #include "mojo/public/cpp/bindings/associated_receiver.h"
55 #include "mojo/public/cpp/bindings/associated_remote.h"
56 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
57 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
58 #include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
59 #include "mojo/public/cpp/bindings/urgent_message_scope.h"
60 #include "mojo/public/cpp/system/functions.h"
61 #include "mojo/public/cpp/system/wait.h"
62 #include "testing/gtest/include/gtest/gtest.h"
63
64 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
65 #include "base/file_descriptor_posix.h"
66 #include "ipc/ipc_platform_file_attachment_posix.h"
67 #endif
68
69 namespace {
70
SendString(IPC::Sender * sender,const std::string & str)71 void SendString(IPC::Sender* sender, const std::string& str) {
72 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
73 message->WriteString(str);
74 ASSERT_TRUE(sender->Send(message));
75 }
76
SendValue(IPC::Sender * sender,int32_t value)77 void SendValue(IPC::Sender* sender, int32_t value) {
78 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
79 message->WriteInt(value);
80 ASSERT_TRUE(sender->Send(message));
81 }
82
83 class ListenerThatExpectsOK : public IPC::Listener {
84 public:
ListenerThatExpectsOK(base::OnceClosure quit_closure)85 explicit ListenerThatExpectsOK(base::OnceClosure quit_closure)
86 : received_ok_(false), quit_closure_(std::move(quit_closure)) {}
87
88 ~ListenerThatExpectsOK() override = default;
89
OnMessageReceived(const IPC::Message & message)90 bool OnMessageReceived(const IPC::Message& message) override {
91 base::PickleIterator iter(message);
92 std::string should_be_ok;
93 EXPECT_TRUE(iter.ReadString(&should_be_ok));
94 EXPECT_EQ(should_be_ok, "OK");
95 received_ok_ = true;
96 std::move(quit_closure_).Run();
97 return true;
98 }
99
OnChannelError()100 void OnChannelError() override {
101 // The connection should be healthy while the listener is waiting
102 // message. An error can occur after that because the peer
103 // process dies.
104 CHECK(received_ok_);
105 }
106
SendOK(IPC::Sender * sender)107 static void SendOK(IPC::Sender* sender) { SendString(sender, "OK"); }
108
109 private:
110 bool received_ok_;
111 base::OnceClosure quit_closure_;
112 };
113
114 class TestListenerBase : public IPC::Listener {
115 public:
TestListenerBase(base::OnceClosure quit_closure)116 explicit TestListenerBase(base::OnceClosure quit_closure)
117 : quit_closure_(std::move(quit_closure)) {}
118
119 ~TestListenerBase() override = default;
OnChannelError()120 void OnChannelError() override { RunQuitClosure(); }
121
set_sender(IPC::Sender * sender)122 void set_sender(IPC::Sender* sender) { sender_ = sender; }
sender() const123 IPC::Sender* sender() const { return sender_; }
RunQuitClosure()124 void RunQuitClosure() {
125 if (quit_closure_)
126 std::move(quit_closure_).Run();
127 }
128
129 private:
130 raw_ptr<IPC::Sender> sender_ = nullptr;
131 base::OnceClosure quit_closure_;
132 };
133
134 using IPCChannelMojoTest = IPCChannelMojoTestBase;
135
136 class TestChannelListenerWithExtraExpectations
137 : public IPC::TestChannelListener {
138 public:
TestChannelListenerWithExtraExpectations()139 TestChannelListenerWithExtraExpectations() : is_connected_called_(false) {}
140
OnChannelConnected(int32_t peer_pid)141 void OnChannelConnected(int32_t peer_pid) override {
142 IPC::TestChannelListener::OnChannelConnected(peer_pid);
143 EXPECT_TRUE(base::kNullProcessId != peer_pid);
144 is_connected_called_ = true;
145 }
146
is_connected_called() const147 bool is_connected_called() const { return is_connected_called_; }
148
149 private:
150 bool is_connected_called_;
151 };
152
TEST_F(IPCChannelMojoTest,ConnectedFromClient)153 TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
154 Init("IPCChannelMojoTestClient");
155
156 // Set up IPC channel and start client.
157 TestChannelListenerWithExtraExpectations listener;
158 CreateChannel(&listener);
159 listener.Init(sender());
160 ASSERT_TRUE(ConnectChannel());
161
162 IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent");
163
164 base::RunLoop().Run();
165
166 channel()->Close();
167
168 EXPECT_TRUE(WaitForClientShutdown());
169 EXPECT_TRUE(listener.is_connected_called());
170 EXPECT_TRUE(listener.HasSentAll());
171
172 DestroyChannel();
173 }
174
175 // A long running process that connects to us
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestClient)176 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestClient) {
177 TestChannelListenerWithExtraExpectations listener;
178 Connect(&listener);
179 listener.Init(channel());
180
181 IPC::TestChannelListener::SendOneMessage(channel(), "hello from child");
182 base::RunLoop().Run();
183 EXPECT_TRUE(listener.is_connected_called());
184 EXPECT_TRUE(listener.HasSentAll());
185
186 Close();
187 }
188
189 class ListenerExpectingErrors : public TestListenerBase {
190 public:
ListenerExpectingErrors(base::OnceClosure quit_closure)191 ListenerExpectingErrors(base::OnceClosure quit_closure)
192 : TestListenerBase(std::move(quit_closure)), has_error_(false) {}
193
OnMessageReceived(const IPC::Message & message)194 bool OnMessageReceived(const IPC::Message& message) override { return true; }
195
OnChannelError()196 void OnChannelError() override {
197 has_error_ = true;
198 TestListenerBase::OnChannelError();
199 }
200
has_error() const201 bool has_error() const { return has_error_; }
202
203 private:
204 bool has_error_;
205 };
206
207 class ListenerThatQuits : public IPC::Listener {
208 public:
ListenerThatQuits(base::OnceClosure quit_closure)209 explicit ListenerThatQuits(base::OnceClosure quit_closure)
210 : quit_closure_(std::move(quit_closure)) {}
211
OnMessageReceived(const IPC::Message & message)212 bool OnMessageReceived(const IPC::Message& message) override { return true; }
213
OnChannelConnected(int32_t peer_pid)214 void OnChannelConnected(int32_t peer_pid) override {
215 std::move(quit_closure_).Run();
216 }
217
218 private:
219 base::OnceClosure quit_closure_;
220 };
221
222 // A long running process that connects to us.
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoErraticTestClient)223 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoErraticTestClient) {
224 base::RunLoop run_loop;
225 ListenerThatQuits listener(run_loop.QuitClosure());
226 Connect(&listener);
227
228 run_loop.Run();
229
230 Close();
231 }
232
TEST_F(IPCChannelMojoTest,SendFailWithPendingMessages)233 TEST_F(IPCChannelMojoTest, SendFailWithPendingMessages) {
234 Init("IPCChannelMojoErraticTestClient");
235
236 // Set up IPC channel and start client.
237 base::RunLoop run_loop;
238 ListenerExpectingErrors listener(run_loop.QuitClosure());
239 CreateChannel(&listener);
240 ASSERT_TRUE(ConnectChannel());
241
242 // This matches a value in mojo/edk/system/constants.h
243 const int kMaxMessageNumBytes = 4 * 1024 * 1024;
244 std::string overly_large_data(kMaxMessageNumBytes, '*');
245 // This messages are queued as pending.
246 for (size_t i = 0; i < 10; ++i) {
247 IPC::TestChannelListener::SendOneMessage(sender(),
248 overly_large_data.c_str());
249 }
250
251 run_loop.Run();
252
253 channel()->Close();
254
255 EXPECT_TRUE(WaitForClientShutdown());
256 EXPECT_TRUE(listener.has_error());
257
258 DestroyChannel();
259 }
260
261 class ListenerThatBindsATestStructPasser : public IPC::Listener,
262 public IPC::mojom::TestStructPasser {
263 public:
264 ListenerThatBindsATestStructPasser() = default;
265 ~ListenerThatBindsATestStructPasser() override = default;
266
OnMessageReceived(const IPC::Message & message)267 bool OnMessageReceived(const IPC::Message& message) override { return true; }
268
OnChannelConnected(int32_t peer_pid)269 void OnChannelConnected(int32_t peer_pid) override {}
270
OnChannelError()271 void OnChannelError() override { NOTREACHED(); }
272
OnAssociatedInterfaceRequest(const std::string & interface_name,mojo::ScopedInterfaceEndpointHandle handle)273 void OnAssociatedInterfaceRequest(
274 const std::string& interface_name,
275 mojo::ScopedInterfaceEndpointHandle handle) override {
276 CHECK_EQ(interface_name, IPC::mojom::TestStructPasser::Name_);
277 receiver_.Bind(
278 mojo::PendingAssociatedReceiver<IPC::mojom::TestStructPasser>(
279 std::move(handle)));
280 }
281
282 private:
283 // IPC::mojom::TestStructPasser:
Pass(IPC::mojom::TestStructPtr)284 void Pass(IPC::mojom::TestStructPtr) override { NOTREACHED(); }
285
286 mojo::AssociatedReceiver<IPC::mojom::TestStructPasser> receiver_{this};
287 };
288
289 class ListenerThatExpectsNoError : public IPC::Listener {
290 public:
ListenerThatExpectsNoError(base::OnceClosure connect_closure,base::OnceClosure quit_closure)291 ListenerThatExpectsNoError(base::OnceClosure connect_closure,
292 base::OnceClosure quit_closure)
293 : connect_closure_(std::move(connect_closure)),
294 quit_closure_(std::move(quit_closure)) {}
295
OnMessageReceived(const IPC::Message & message)296 bool OnMessageReceived(const IPC::Message& message) override {
297 base::PickleIterator iter(message);
298 std::string should_be_ok;
299 EXPECT_TRUE(iter.ReadString(&should_be_ok));
300 EXPECT_EQ(should_be_ok, "OK");
301 std::move(quit_closure_).Run();
302 return true;
303 }
304
OnChannelConnected(int32_t peer_pid)305 void OnChannelConnected(int32_t peer_pid) override {
306 std::move(connect_closure_).Run();
307 }
308
OnChannelError()309 void OnChannelError() override { NOTREACHED(); }
310
311 private:
312 base::OnceClosure connect_closure_;
313 base::OnceClosure quit_closure_;
314 };
315
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoNoImplicitChanelClosureClient)316 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
317 IPCChannelMojoNoImplicitChanelClosureClient) {
318 base::RunLoop wait_to_connect_loop;
319 base::RunLoop wait_to_quit_loop;
320 ListenerThatExpectsNoError listener(wait_to_connect_loop.QuitClosure(),
321 wait_to_quit_loop.QuitClosure());
322 Connect(&listener);
323 wait_to_connect_loop.Run();
324
325 mojo::AssociatedRemote<IPC::mojom::TestStructPasser> passer;
326 channel()->GetAssociatedInterfaceSupport()->GetRemoteAssociatedInterface(
327 passer.BindNewEndpointAndPassReceiver());
328
329 // This avoids hitting DCHECKs in the serialization code meant to stop us from
330 // making such "mistakes" as the one we're about to make below.
331 mojo::internal::SerializationWarningObserverForTesting suppress_those_dchecks;
332
333 // Send an invalid message. The TestStruct argument is not allowed to be null.
334 // This will elicit a validation error in the parent process, but should not
335 // actually disconnect the channel.
336 passer->Pass(nullptr);
337
338 // Wait until the parent says it's OK to quit, so it has time to verify its
339 // expected behavior.
340 wait_to_quit_loop.Run();
341
342 Close();
343 }
344
TEST_F(IPCChannelMojoTest,NoImplicitChannelClosure)345 TEST_F(IPCChannelMojoTest, NoImplicitChannelClosure) {
346 // Verifies that OnChannelError is not invoked due to conditions other than
347 // peer closure (e.g. a malformed inbound message). Instead we should always
348 // be able to handle validation errors via Mojo bad message reporting.
349
350 // NOTE: We can't create a RunLoop before Init() is called, but we have to set
351 // the default ProcessErrorCallback (which we want to reference the RunLoop)
352 // before Init() launches a child process. Hence the std::optional here.
353 std::optional<base::RunLoop> wait_for_error_loop;
354 bool process_error_received = false;
355 mojo::SetDefaultProcessErrorHandler(
356 base::BindLambdaForTesting([&](const std::string&) {
357 process_error_received = true;
358 wait_for_error_loop->Quit();
359 }));
360
361 Init("IPCChannelMojoNoImplicitChanelClosureClient");
362
363 wait_for_error_loop.emplace();
364 ListenerThatBindsATestStructPasser listener;
365 CreateChannel(&listener);
366 ASSERT_TRUE(ConnectChannel());
367
368 wait_for_error_loop->Run();
369 EXPECT_TRUE(process_error_received);
370 mojo::SetDefaultProcessErrorHandler(base::NullCallback());
371
372 // Tell the child it can quit and wait for it to shut down.
373 ListenerThatExpectsOK::SendOK(channel());
374 EXPECT_TRUE(WaitForClientShutdown());
375 DestroyChannel();
376 }
377
378 struct TestingMessagePipe {
TestingMessagePipe__anon209110850111::TestingMessagePipe379 TestingMessagePipe() {
380 EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateMessagePipe(nullptr, &self, &peer));
381 }
382
383 mojo::ScopedMessagePipeHandle self;
384 mojo::ScopedMessagePipeHandle peer;
385 };
386
387 class HandleSendingHelper {
388 public:
GetSendingFileContent()389 static std::string GetSendingFileContent() { return "Hello"; }
390
WritePipe(IPC::Message * message,TestingMessagePipe * pipe)391 static void WritePipe(IPC::Message* message, TestingMessagePipe* pipe) {
392 std::string content = HandleSendingHelper::GetSendingFileContent();
393 EXPECT_EQ(MOJO_RESULT_OK,
394 mojo::WriteMessageRaw(pipe->self.get(), &content[0],
395 static_cast<uint32_t>(content.size()),
396 nullptr, 0, 0));
397 EXPECT_TRUE(IPC::MojoMessageHelper::WriteMessagePipeTo(
398 message, std::move(pipe->peer)));
399 }
400
WritePipeThenSend(IPC::Sender * sender,TestingMessagePipe * pipe)401 static void WritePipeThenSend(IPC::Sender* sender, TestingMessagePipe* pipe) {
402 IPC::Message* message =
403 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
404 WritePipe(message, pipe);
405 ASSERT_TRUE(sender->Send(message));
406 }
407
ReadReceivedPipe(const IPC::Message & message,base::PickleIterator * iter)408 static void ReadReceivedPipe(const IPC::Message& message,
409 base::PickleIterator* iter) {
410 mojo::ScopedMessagePipeHandle pipe;
411 EXPECT_TRUE(
412 IPC::MojoMessageHelper::ReadMessagePipeFrom(&message, iter, &pipe));
413 std::vector<uint8_t> content;
414
415 ASSERT_EQ(MOJO_RESULT_OK,
416 mojo::Wait(pipe.get(), MOJO_HANDLE_SIGNAL_READABLE));
417 EXPECT_EQ(MOJO_RESULT_OK,
418 mojo::ReadMessageRaw(pipe.get(), &content, nullptr, 0));
419 EXPECT_EQ(std::string(content.begin(), content.end()),
420 GetSendingFileContent());
421 }
422
423 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
GetSendingFilePath(const base::FilePath & dir_path)424 static base::FilePath GetSendingFilePath(const base::FilePath& dir_path) {
425 return dir_path.Append("ListenerThatExpectsFile.txt");
426 }
427
WriteFile(IPC::Message * message,base::File & file)428 static void WriteFile(IPC::Message* message, base::File& file) {
429 std::string content = GetSendingFileContent();
430 file.WriteAtCurrentPos(content.data(), content.size());
431 file.Flush();
432 message->WriteAttachment(new IPC::internal::PlatformFileAttachment(
433 base::ScopedFD(file.TakePlatformFile())));
434 }
435
WriteFileThenSend(IPC::Sender * sender,base::File & file)436 static void WriteFileThenSend(IPC::Sender* sender, base::File& file) {
437 IPC::Message* message =
438 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
439 WriteFile(message, file);
440 ASSERT_TRUE(sender->Send(message));
441 }
442
WriteFileAndPipeThenSend(IPC::Sender * sender,base::File & file,TestingMessagePipe * pipe)443 static void WriteFileAndPipeThenSend(IPC::Sender* sender,
444 base::File& file,
445 TestingMessagePipe* pipe) {
446 IPC::Message* message =
447 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
448 WriteFile(message, file);
449 WritePipe(message, pipe);
450 ASSERT_TRUE(sender->Send(message));
451 }
452
ReadReceivedFile(const IPC::Message & message,base::PickleIterator * iter)453 static void ReadReceivedFile(const IPC::Message& message,
454 base::PickleIterator* iter) {
455 scoped_refptr<base::Pickle::Attachment> attachment;
456 EXPECT_TRUE(message.ReadAttachment(iter, &attachment));
457 EXPECT_EQ(
458 IPC::MessageAttachment::Type::PLATFORM_FILE,
459 static_cast<IPC::MessageAttachment*>(attachment.get())->GetType());
460 base::File file(
461 static_cast<IPC::internal::PlatformFileAttachment*>(attachment.get())
462 ->TakePlatformFile());
463 std::string content(GetSendingFileContent().size(), ' ');
464 file.Read(0, &content[0], content.size());
465 EXPECT_EQ(content, GetSendingFileContent());
466 }
467 #endif
468 };
469
470 class ListenerThatExpectsMessagePipe : public TestListenerBase {
471 public:
ListenerThatExpectsMessagePipe(base::OnceClosure quit_closure)472 ListenerThatExpectsMessagePipe(base::OnceClosure quit_closure)
473 : TestListenerBase(std::move(quit_closure)) {}
474
475 ~ListenerThatExpectsMessagePipe() override = default;
476
OnMessageReceived(const IPC::Message & message)477 bool OnMessageReceived(const IPC::Message& message) override {
478 base::PickleIterator iter(message);
479 HandleSendingHelper::ReadReceivedPipe(message, &iter);
480 ListenerThatExpectsOK::SendOK(sender());
481 return true;
482 }
483 };
484
TEST_F(IPCChannelMojoTest,SendMessagePipe)485 TEST_F(IPCChannelMojoTest, SendMessagePipe) {
486 Init("IPCChannelMojoTestSendMessagePipeClient");
487
488 base::RunLoop run_loop;
489 ListenerThatExpectsOK listener(run_loop.QuitClosure());
490 CreateChannel(&listener);
491 ASSERT_TRUE(ConnectChannel());
492
493 TestingMessagePipe pipe;
494 HandleSendingHelper::WritePipeThenSend(channel(), &pipe);
495
496 run_loop.Run();
497 channel()->Close();
498
499 EXPECT_TRUE(WaitForClientShutdown());
500 DestroyChannel();
501 }
502
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendMessagePipeClient)503 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendMessagePipeClient) {
504 base::RunLoop run_loop;
505 ListenerThatExpectsMessagePipe listener(run_loop.QuitClosure());
506 Connect(&listener);
507 listener.set_sender(channel());
508
509 run_loop.Run();
510
511 Close();
512 }
513
ReadOK(mojo::MessagePipeHandle pipe)514 void ReadOK(mojo::MessagePipeHandle pipe) {
515 std::vector<uint8_t> should_be_ok;
516 CHECK_EQ(MOJO_RESULT_OK, mojo::Wait(pipe, MOJO_HANDLE_SIGNAL_READABLE));
517 CHECK_EQ(MOJO_RESULT_OK,
518 mojo::ReadMessageRaw(pipe, &should_be_ok, nullptr, 0));
519 EXPECT_EQ("OK", std::string(should_be_ok.begin(), should_be_ok.end()));
520 }
521
WriteOK(mojo::MessagePipeHandle pipe)522 void WriteOK(mojo::MessagePipeHandle pipe) {
523 std::string ok("OK");
524 CHECK_EQ(MOJO_RESULT_OK,
525 mojo::WriteMessageRaw(pipe, &ok[0], static_cast<uint32_t>(ok.size()),
526 nullptr, 0, 0));
527 }
528
529 class ListenerThatExpectsMessagePipeUsingParamTrait : public TestListenerBase {
530 public:
ListenerThatExpectsMessagePipeUsingParamTrait(base::OnceClosure quit_closure,bool receiving_valid)531 explicit ListenerThatExpectsMessagePipeUsingParamTrait(
532 base::OnceClosure quit_closure,
533 bool receiving_valid)
534 : TestListenerBase(std::move(quit_closure)),
535 receiving_valid_(receiving_valid) {}
536
537 ~ListenerThatExpectsMessagePipeUsingParamTrait() override = default;
538
OnMessageReceived(const IPC::Message & message)539 bool OnMessageReceived(const IPC::Message& message) override {
540 base::PickleIterator iter(message);
541 mojo::MessagePipeHandle handle;
542 EXPECT_TRUE(IPC::ParamTraits<mojo::MessagePipeHandle>::Read(&message, &iter,
543 &handle));
544 EXPECT_EQ(handle.is_valid(), receiving_valid_);
545 if (receiving_valid_) {
546 ReadOK(handle);
547 MojoClose(handle.value());
548 }
549
550 ListenerThatExpectsOK::SendOK(sender());
551 return true;
552 }
553
554 private:
555 bool receiving_valid_;
556 };
557
558 class ParamTraitMessagePipeClient : public IpcChannelMojoTestClient {
559 public:
RunTest(bool receiving_valid_handle)560 void RunTest(bool receiving_valid_handle) {
561 base::RunLoop run_loop;
562 ListenerThatExpectsMessagePipeUsingParamTrait listener(
563 run_loop.QuitClosure(), receiving_valid_handle);
564 Connect(&listener);
565 listener.set_sender(channel());
566
567 run_loop.Run();
568
569 Close();
570 }
571 };
572
TEST_F(IPCChannelMojoTest,ParamTraitValidMessagePipe)573 TEST_F(IPCChannelMojoTest, ParamTraitValidMessagePipe) {
574 Init("ParamTraitValidMessagePipeClient");
575
576 base::RunLoop run_loop;
577 ListenerThatExpectsOK listener(run_loop.QuitClosure());
578 CreateChannel(&listener);
579 ASSERT_TRUE(ConnectChannel());
580
581 TestingMessagePipe pipe;
582
583 std::unique_ptr<IPC::Message> message(new IPC::Message());
584 IPC::ParamTraits<mojo::MessagePipeHandle>::Write(message.get(),
585 pipe.peer.release());
586 WriteOK(pipe.self.get());
587
588 channel()->Send(message.release());
589 run_loop.Run();
590 channel()->Close();
591
592 EXPECT_TRUE(WaitForClientShutdown());
593 DestroyChannel();
594 }
595
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(ParamTraitValidMessagePipeClient,ParamTraitMessagePipeClient)596 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
597 ParamTraitValidMessagePipeClient,
598 ParamTraitMessagePipeClient) {
599 RunTest(true);
600 }
601
TEST_F(IPCChannelMojoTest,ParamTraitInvalidMessagePipe)602 TEST_F(IPCChannelMojoTest, ParamTraitInvalidMessagePipe) {
603 Init("ParamTraitInvalidMessagePipeClient");
604
605 base::RunLoop run_loop;
606 ListenerThatExpectsOK listener(run_loop.QuitClosure());
607 CreateChannel(&listener);
608 ASSERT_TRUE(ConnectChannel());
609
610 mojo::MessagePipeHandle invalid_handle;
611 std::unique_ptr<IPC::Message> message(new IPC::Message());
612 IPC::ParamTraits<mojo::MessagePipeHandle>::Write(message.get(),
613 invalid_handle);
614
615 channel()->Send(message.release());
616 run_loop.Run();
617 channel()->Close();
618
619 EXPECT_TRUE(WaitForClientShutdown());
620 DestroyChannel();
621 }
622
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(ParamTraitInvalidMessagePipeClient,ParamTraitMessagePipeClient)623 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
624 ParamTraitInvalidMessagePipeClient,
625 ParamTraitMessagePipeClient) {
626 RunTest(false);
627 }
628
TEST_F(IPCChannelMojoTest,SendFailAfterClose)629 TEST_F(IPCChannelMojoTest, SendFailAfterClose) {
630 Init("IPCChannelMojoTestSendOkClient");
631
632 base::RunLoop run_loop;
633 ListenerThatExpectsOK listener(run_loop.QuitClosure());
634 CreateChannel(&listener);
635 ASSERT_TRUE(ConnectChannel());
636
637 run_loop.Run();
638 channel()->Close();
639 ASSERT_FALSE(channel()->Send(new IPC::Message()));
640
641 EXPECT_TRUE(WaitForClientShutdown());
642 DestroyChannel();
643 }
644
645 class ListenerSendingOneOk : public TestListenerBase {
646 public:
ListenerSendingOneOk(base::OnceClosure quit_closure)647 ListenerSendingOneOk(base::OnceClosure quit_closure)
648 : TestListenerBase(std::move(quit_closure)) {}
649
OnMessageReceived(const IPC::Message & message)650 bool OnMessageReceived(const IPC::Message& message) override { return true; }
651
OnChannelConnected(int32_t peer_pid)652 void OnChannelConnected(int32_t peer_pid) override {
653 ListenerThatExpectsOK::SendOK(sender());
654 RunQuitClosure();
655 }
656 };
657
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendOkClient)658 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendOkClient) {
659 base::RunLoop run_loop;
660 ListenerSendingOneOk listener(run_loop.QuitClosure());
661 Connect(&listener);
662 listener.set_sender(channel());
663
664 run_loop.Run();
665
666 Close();
667 }
668
669 class ListenerWithSimpleAssociatedInterface
670 : public IPC::Listener,
671 public IPC::mojom::SimpleTestDriver {
672 public:
673 static const int kNumMessages;
674
ListenerWithSimpleAssociatedInterface(base::OnceClosure quit_closure)675 explicit ListenerWithSimpleAssociatedInterface(base::OnceClosure quit_closure)
676 : quit_closure_(std::move(quit_closure)) {}
677
678 ~ListenerWithSimpleAssociatedInterface() override = default;
679
OnMessageReceived(const IPC::Message & message)680 bool OnMessageReceived(const IPC::Message& message) override {
681 base::PickleIterator iter(message);
682 int32_t should_be_expected;
683 EXPECT_TRUE(iter.ReadInt(&should_be_expected));
684 EXPECT_EQ(should_be_expected, next_expected_value_);
685 num_messages_received_++;
686 return true;
687 }
688
OnChannelError()689 void OnChannelError() override { CHECK(!quit_closure_); }
690
RegisterInterfaceFactory(IPC::Channel * channel)691 void RegisterInterfaceFactory(IPC::Channel* channel) {
692 channel->GetAssociatedInterfaceSupport()->AddAssociatedInterface(
693 base::BindRepeating(
694 &ListenerWithSimpleAssociatedInterface::BindReceiver,
695 base::Unretained(this)));
696 }
697
698 private:
699 // IPC::mojom::SimpleTestDriver:
ExpectValue(int32_t value)700 void ExpectValue(int32_t value) override {
701 next_expected_value_ = value;
702 }
703
GetExpectedValue(GetExpectedValueCallback callback)704 void GetExpectedValue(GetExpectedValueCallback callback) override {
705 NOTREACHED();
706 }
707
RequestValue(RequestValueCallback callback)708 void RequestValue(RequestValueCallback callback) override { NOTREACHED(); }
709
RequestQuit(RequestQuitCallback callback)710 void RequestQuit(RequestQuitCallback callback) override {
711 EXPECT_EQ(kNumMessages, num_messages_received_);
712 std::move(callback).Run();
713 std::move(quit_closure_).Run();
714 }
715
BindReceiver(mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestDriver> receiver)716 void BindReceiver(
717 mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestDriver> receiver) {
718 DCHECK(!receiver_.is_bound());
719 receiver_.Bind(std::move(receiver));
720 }
721
722 int32_t next_expected_value_ = 0;
723 int num_messages_received_ = 0;
724 base::OnceClosure quit_closure_;
725
726 mojo::AssociatedReceiver<IPC::mojom::SimpleTestDriver> receiver_{this};
727 };
728
729 const int ListenerWithSimpleAssociatedInterface::kNumMessages = 1000;
730
731 class ListenerSendingAssociatedMessages : public IPC::Listener {
732 public:
ListenerSendingAssociatedMessages(base::OnceClosure quit_closure)733 explicit ListenerSendingAssociatedMessages(base::OnceClosure quit_closure)
734 : quit_closure_(std::move(quit_closure)) {}
735
OnMessageReceived(const IPC::Message & message)736 bool OnMessageReceived(const IPC::Message& message) override { return true; }
737
OnChannelConnected(int32_t peer_pid)738 void OnChannelConnected(int32_t peer_pid) override {
739 DCHECK(channel_);
740 channel_->GetAssociatedInterfaceSupport()->GetRemoteAssociatedInterface(
741 driver_.BindNewEndpointAndPassReceiver());
742
743 // Send a bunch of interleaved messages, alternating between the associated
744 // interface and a legacy IPC::Message.
745 for (int i = 0; i < ListenerWithSimpleAssociatedInterface::kNumMessages;
746 ++i) {
747 driver_->ExpectValue(i);
748 SendValue(channel_, i);
749 }
750 driver_->RequestQuit(base::BindOnce(
751 &ListenerSendingAssociatedMessages::OnQuitAck, base::Unretained(this)));
752 }
753
set_channel(IPC::Channel * channel)754 void set_channel(IPC::Channel* channel) { channel_ = channel; }
755
756 private:
OnQuitAck()757 void OnQuitAck() { std::move(quit_closure_).Run(); }
758
759 raw_ptr<IPC::Channel> channel_ = nullptr;
760 mojo::AssociatedRemote<IPC::mojom::SimpleTestDriver> driver_;
761 base::OnceClosure quit_closure_;
762 };
763
TEST_F(IPCChannelMojoTest,SimpleAssociatedInterface)764 TEST_F(IPCChannelMojoTest, SimpleAssociatedInterface) {
765 Init("SimpleAssociatedInterfaceClient");
766
767 base::RunLoop run_loop;
768 ListenerWithSimpleAssociatedInterface listener(run_loop.QuitClosure());
769 CreateChannel(&listener);
770 ASSERT_TRUE(ConnectChannel());
771
772 listener.RegisterInterfaceFactory(channel());
773
774 run_loop.Run();
775 channel()->Close();
776
777 EXPECT_TRUE(WaitForClientShutdown());
778 DestroyChannel();
779 }
780
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(SimpleAssociatedInterfaceClient)781 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(SimpleAssociatedInterfaceClient) {
782 base::RunLoop run_loop;
783 ListenerSendingAssociatedMessages listener(run_loop.QuitClosure());
784 Connect(&listener);
785 listener.set_channel(channel());
786
787 run_loop.Run();
788
789 Close();
790 }
791
792 class ChannelProxyRunner {
793 public:
ChannelProxyRunner(mojo::ScopedMessagePipeHandle handle,bool for_server)794 ChannelProxyRunner(mojo::ScopedMessagePipeHandle handle,
795 bool for_server)
796 : for_server_(for_server),
797 handle_(std::move(handle)),
798 io_thread_("ChannelProxyRunner IO thread"),
799 never_signaled_(base::WaitableEvent::ResetPolicy::MANUAL,
800 base::WaitableEvent::InitialState::NOT_SIGNALED) {
801 }
802
803 ChannelProxyRunner(const ChannelProxyRunner&) = delete;
804 ChannelProxyRunner& operator=(const ChannelProxyRunner&) = delete;
805
CreateProxy(IPC::Listener * listener,IPC::UrgentMessageObserver * urgent_message_observer=nullptr)806 void CreateProxy(
807 IPC::Listener* listener,
808 IPC::UrgentMessageObserver* urgent_message_observer = nullptr) {
809 io_thread_.StartWithOptions(
810 base::Thread::Options(base::MessagePumpType::IO, 0));
811 proxy_ = IPC::SyncChannel::Create(
812 listener, io_thread_.task_runner(),
813 base::SingleThreadTaskRunner::GetCurrentDefault(), &never_signaled_);
814 proxy_->SetUrgentMessageObserver(urgent_message_observer);
815 }
816
RunProxy()817 void RunProxy() {
818 std::unique_ptr<IPC::ChannelFactory> factory;
819 if (for_server_) {
820 factory = IPC::ChannelMojo::CreateServerFactory(
821 std::move(handle_), io_thread_.task_runner(),
822 base::SingleThreadTaskRunner::GetCurrentDefault());
823 } else {
824 factory = IPC::ChannelMojo::CreateClientFactory(
825 std::move(handle_), io_thread_.task_runner(),
826 base::SingleThreadTaskRunner::GetCurrentDefault());
827 }
828 proxy_->Init(std::move(factory), true);
829 }
830
proxy()831 IPC::ChannelProxy* proxy() { return proxy_.get(); }
832
833 private:
834 const bool for_server_;
835
836 mojo::ScopedMessagePipeHandle handle_;
837 base::Thread io_thread_;
838 base::WaitableEvent never_signaled_;
839 std::unique_ptr<IPC::ChannelProxy> proxy_;
840 };
841
842 class IPCChannelProxyMojoTest : public IPCChannelMojoTestBase {
843 public:
Init(const std::string & client_name)844 void Init(const std::string& client_name) {
845 IPCChannelMojoTestBase::Init(client_name);
846 runner_ = std::make_unique<ChannelProxyRunner>(TakeHandle(), true);
847 }
848
CreateProxy(IPC::Listener * listener,IPC::UrgentMessageObserver * urgent_message_observer=nullptr)849 void CreateProxy(
850 IPC::Listener* listener,
851 IPC::UrgentMessageObserver* urgent_message_observer = nullptr) {
852 runner_->CreateProxy(listener, urgent_message_observer);
853 }
854
RunProxy()855 void RunProxy() {
856 runner_->RunProxy();
857 }
858
DestroyProxy()859 void DestroyProxy() {
860 runner_.reset();
861 base::RunLoop().RunUntilIdle();
862 }
863
proxy()864 IPC::ChannelProxy* proxy() { return runner_->proxy(); }
865
866 private:
867 std::unique_ptr<ChannelProxyRunner> runner_;
868 };
869
870 class ListenerWithSimpleProxyAssociatedInterface
871 : public IPC::Listener,
872 public IPC::mojom::SimpleTestDriver {
873 public:
874 static const int kNumMessages;
875
ListenerWithSimpleProxyAssociatedInterface(base::OnceClosure quit_closure)876 explicit ListenerWithSimpleProxyAssociatedInterface(
877 base::OnceClosure quit_closure)
878 : quit_closure_(std::move(quit_closure)) {}
879
880 ~ListenerWithSimpleProxyAssociatedInterface() override = default;
881
OnMessageReceived(const IPC::Message & message)882 bool OnMessageReceived(const IPC::Message& message) override {
883 base::PickleIterator iter(message);
884 int32_t should_be_expected;
885 EXPECT_TRUE(iter.ReadInt(&should_be_expected));
886 EXPECT_EQ(should_be_expected, next_expected_value_);
887 num_messages_received_++;
888 return true;
889 }
890
OnChannelError()891 void OnChannelError() override { CHECK(!quit_closure_); }
892
OnAssociatedInterfaceRequest(const std::string & interface_name,mojo::ScopedInterfaceEndpointHandle handle)893 void OnAssociatedInterfaceRequest(
894 const std::string& interface_name,
895 mojo::ScopedInterfaceEndpointHandle handle) override {
896 DCHECK_EQ(interface_name, IPC::mojom::SimpleTestDriver::Name_);
897 receiver_.Bind(
898 mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestDriver>(
899 std::move(handle)));
900 }
901
received_all_messages() const902 bool received_all_messages() const {
903 return num_messages_received_ == kNumMessages && !quit_closure_;
904 }
905
906 private:
907 // IPC::mojom::SimpleTestDriver:
ExpectValue(int32_t value)908 void ExpectValue(int32_t value) override {
909 next_expected_value_ = value;
910 }
911
GetExpectedValue(GetExpectedValueCallback callback)912 void GetExpectedValue(GetExpectedValueCallback callback) override {
913 std::move(callback).Run(next_expected_value_);
914 }
915
RequestValue(RequestValueCallback callback)916 void RequestValue(RequestValueCallback callback) override { NOTREACHED(); }
917
RequestQuit(RequestQuitCallback callback)918 void RequestQuit(RequestQuitCallback callback) override {
919 std::move(callback).Run();
920 receiver_.reset();
921 std::move(quit_closure_).Run();
922 }
923
BindReceiver(mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestDriver> receiver)924 void BindReceiver(
925 mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestDriver> receiver) {
926 DCHECK(!receiver_.is_bound());
927 receiver_.Bind(std::move(receiver));
928 }
929
930 int32_t next_expected_value_ = 0;
931 int num_messages_received_ = 0;
932 base::OnceClosure quit_closure_;
933
934 mojo::AssociatedReceiver<IPC::mojom::SimpleTestDriver> receiver_{this};
935 };
936
937 const int ListenerWithSimpleProxyAssociatedInterface::kNumMessages = 1000;
938
TEST_F(IPCChannelProxyMojoTest,ProxyThreadAssociatedInterface)939 TEST_F(IPCChannelProxyMojoTest, ProxyThreadAssociatedInterface) {
940 Init("ProxyThreadAssociatedInterfaceClient");
941
942 base::RunLoop run_loop;
943 ListenerWithSimpleProxyAssociatedInterface listener(run_loop.QuitClosure());
944 CreateProxy(&listener);
945 RunProxy();
946
947 run_loop.Run();
948
949 EXPECT_TRUE(WaitForClientShutdown());
950 EXPECT_TRUE(listener.received_all_messages());
951
952 DestroyProxy();
953 }
954
955 class ChannelProxyClient {
956 public:
Init(mojo::ScopedMessagePipeHandle handle)957 void Init(mojo::ScopedMessagePipeHandle handle) {
958 runner_ = std::make_unique<ChannelProxyRunner>(std::move(handle), false);
959 }
960
CreateProxy(IPC::Listener * listener)961 void CreateProxy(IPC::Listener* listener) { runner_->CreateProxy(listener); }
962
RunProxy()963 void RunProxy() { runner_->RunProxy(); }
964
DestroyProxy()965 void DestroyProxy() {
966 runner_.reset();
967 base::RunLoop().RunUntilIdle();
968 }
969
RequestQuitAndWaitForAck(IPC::mojom::SimpleTestDriver * driver)970 void RequestQuitAndWaitForAck(IPC::mojom::SimpleTestDriver* driver) {
971 base::RunLoop loop;
972 driver->RequestQuit(loop.QuitClosure());
973 loop.Run();
974 }
975
proxy()976 IPC::ChannelProxy* proxy() { return runner_->proxy(); }
977
978 private:
979 base::test::SingleThreadTaskEnvironment task_environment_;
980 std::unique_ptr<ChannelProxyRunner> runner_;
981 };
982
983 class DummyListener : public IPC::Listener {
984 public:
985 // IPC::Listener
OnMessageReceived(const IPC::Message & message)986 bool OnMessageReceived(const IPC::Message& message) override { return true; }
987 };
988
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(ProxyThreadAssociatedInterfaceClient,ChannelProxyClient)989 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
990 ProxyThreadAssociatedInterfaceClient,
991 ChannelProxyClient) {
992 DummyListener listener;
993 CreateProxy(&listener);
994 RunProxy();
995
996 // Send a bunch of interleaved messages, alternating between the associated
997 // interface and a legacy IPC::Message.
998 mojo::AssociatedRemote<IPC::mojom::SimpleTestDriver> driver;
999 proxy()->GetRemoteAssociatedInterface(
1000 driver.BindNewEndpointAndPassReceiver());
1001 for (int i = 0; i < ListenerWithSimpleProxyAssociatedInterface::kNumMessages;
1002 ++i) {
1003 driver->ExpectValue(i);
1004 SendValue(proxy(), i);
1005 }
1006 base::RunLoop run_loop;
1007 driver->RequestQuit(run_loop.QuitClosure());
1008 run_loop.Run();
1009
1010 DestroyProxy();
1011 }
1012
1013 class ListenerWithIndirectProxyAssociatedInterface
1014 : public IPC::Listener,
1015 public IPC::mojom::IndirectTestDriver,
1016 public IPC::mojom::PingReceiver {
1017 public:
1018 ListenerWithIndirectProxyAssociatedInterface() = default;
1019 ~ListenerWithIndirectProxyAssociatedInterface() override = default;
1020
1021 // IPC::Listener:
OnMessageReceived(const IPC::Message & message)1022 bool OnMessageReceived(const IPC::Message& message) override { return true; }
1023
OnAssociatedInterfaceRequest(const std::string & interface_name,mojo::ScopedInterfaceEndpointHandle handle)1024 void OnAssociatedInterfaceRequest(
1025 const std::string& interface_name,
1026 mojo::ScopedInterfaceEndpointHandle handle) override {
1027 DCHECK(!driver_receiver_.is_bound());
1028 DCHECK_EQ(interface_name, IPC::mojom::IndirectTestDriver::Name_);
1029 driver_receiver_.Bind(
1030 mojo::PendingAssociatedReceiver<IPC::mojom::IndirectTestDriver>(
1031 std::move(handle)));
1032 }
1033
set_ping_handler(const base::RepeatingClosure & handler)1034 void set_ping_handler(const base::RepeatingClosure& handler) {
1035 ping_handler_ = handler;
1036 }
1037
1038 private:
1039 // IPC::mojom::IndirectTestDriver:
GetPingReceiver(mojo::PendingAssociatedReceiver<IPC::mojom::PingReceiver> receiver)1040 void GetPingReceiver(mojo::PendingAssociatedReceiver<IPC::mojom::PingReceiver>
1041 receiver) override {
1042 ping_receiver_receiver_.Bind(std::move(receiver));
1043 }
1044
1045 // IPC::mojom::PingReceiver:
Ping(PingCallback callback)1046 void Ping(PingCallback callback) override {
1047 std::move(callback).Run();
1048 ping_handler_.Run();
1049 }
1050
1051 mojo::AssociatedReceiver<IPC::mojom::IndirectTestDriver> driver_receiver_{
1052 this};
1053 mojo::AssociatedReceiver<IPC::mojom::PingReceiver> ping_receiver_receiver_{
1054 this};
1055
1056 base::RepeatingClosure ping_handler_;
1057 };
1058
TEST_F(IPCChannelProxyMojoTest,ProxyThreadAssociatedInterfaceIndirect)1059 TEST_F(IPCChannelProxyMojoTest, ProxyThreadAssociatedInterfaceIndirect) {
1060 // Tests that we can pipeline interface requests and subsequent messages
1061 // targeting proxy thread bindings, and the channel will still dispatch
1062 // messages appropriately.
1063
1064 Init("ProxyThreadAssociatedInterfaceIndirectClient");
1065
1066 ListenerWithIndirectProxyAssociatedInterface listener;
1067 CreateProxy(&listener);
1068 RunProxy();
1069
1070 base::RunLoop loop;
1071 listener.set_ping_handler(loop.QuitClosure());
1072 loop.Run();
1073
1074 EXPECT_TRUE(WaitForClientShutdown());
1075
1076 DestroyProxy();
1077 }
1078
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(ProxyThreadAssociatedInterfaceIndirectClient,ChannelProxyClient)1079 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
1080 ProxyThreadAssociatedInterfaceIndirectClient,
1081 ChannelProxyClient) {
1082 DummyListener listener;
1083 CreateProxy(&listener);
1084 RunProxy();
1085
1086 // Use an interface requested via another interface. On the remote end both
1087 // interfaces are bound on the proxy thread. This ensures that the Ping
1088 // message we send will still be dispatched properly even though the remote
1089 // endpoint may not have been bound yet by the time the message is initially
1090 // processed on the IO thread.
1091 mojo::AssociatedRemote<IPC::mojom::IndirectTestDriver> driver;
1092 mojo::AssociatedRemote<IPC::mojom::PingReceiver> ping_receiver;
1093 proxy()->GetRemoteAssociatedInterface(
1094 driver.BindNewEndpointAndPassReceiver());
1095 driver->GetPingReceiver(ping_receiver.BindNewEndpointAndPassReceiver());
1096
1097 base::RunLoop loop;
1098 ping_receiver->Ping(loop.QuitClosure());
1099 loop.Run();
1100
1101 DestroyProxy();
1102 }
1103
1104 class ListenerWithSyncAssociatedInterface
1105 : public IPC::Listener,
1106 public IPC::mojom::SimpleTestDriver {
1107 public:
1108 ListenerWithSyncAssociatedInterface() = default;
1109 ~ListenerWithSyncAssociatedInterface() override = default;
1110
set_sync_sender(IPC::Sender * sync_sender)1111 void set_sync_sender(IPC::Sender* sync_sender) { sync_sender_ = sync_sender; }
1112
RunUntilQuitRequested()1113 void RunUntilQuitRequested() {
1114 base::RunLoop loop;
1115 quit_closure_ = loop.QuitClosure();
1116 loop.Run();
1117 }
1118
CloseBinding()1119 void CloseBinding() { receiver_.reset(); }
1120
set_response_value(int32_t response)1121 void set_response_value(int32_t response) {
1122 response_value_ = response;
1123 }
1124
1125 private:
1126 // IPC::mojom::SimpleTestDriver:
ExpectValue(int32_t value)1127 void ExpectValue(int32_t value) override {
1128 next_expected_value_ = value;
1129 }
1130
GetExpectedValue(GetExpectedValueCallback callback)1131 void GetExpectedValue(GetExpectedValueCallback callback) override {
1132 std::move(callback).Run(next_expected_value_);
1133 }
1134
RequestValue(RequestValueCallback callback)1135 void RequestValue(RequestValueCallback callback) override {
1136 std::move(callback).Run(response_value_);
1137 }
1138
RequestQuit(RequestQuitCallback callback)1139 void RequestQuit(RequestQuitCallback callback) override {
1140 std::move(quit_closure_).Run();
1141 std::move(callback).Run();
1142 }
1143
1144 // IPC::Listener:
OnMessageReceived(const IPC::Message & message)1145 bool OnMessageReceived(const IPC::Message& message) override {
1146 EXPECT_EQ(0u, message.type());
1147 EXPECT_TRUE(message.is_sync());
1148 EXPECT_TRUE(message.should_unblock());
1149 std::unique_ptr<IPC::Message> reply(
1150 IPC::SyncMessage::GenerateReply(&message));
1151 reply->WriteInt(response_value_);
1152 DCHECK(sync_sender_);
1153 EXPECT_TRUE(sync_sender_->Send(reply.release()));
1154 return true;
1155 }
1156
OnAssociatedInterfaceRequest(const std::string & interface_name,mojo::ScopedInterfaceEndpointHandle handle)1157 void OnAssociatedInterfaceRequest(
1158 const std::string& interface_name,
1159 mojo::ScopedInterfaceEndpointHandle handle) override {
1160 DCHECK(!receiver_.is_bound());
1161 DCHECK_EQ(interface_name, IPC::mojom::SimpleTestDriver::Name_);
1162 receiver_.Bind(
1163 mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestDriver>(
1164 std::move(handle)));
1165 }
1166
BindReceiver(mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestDriver> receiver)1167 void BindReceiver(
1168 mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestDriver> receiver) {
1169 DCHECK(!receiver_.is_bound());
1170 receiver_.Bind(std::move(receiver));
1171 }
1172
1173 raw_ptr<IPC::Sender, DanglingUntriaged> sync_sender_ = nullptr;
1174 int32_t next_expected_value_ = 0;
1175 int32_t response_value_ = 0;
1176 base::OnceClosure quit_closure_;
1177
1178 mojo::AssociatedReceiver<IPC::mojom::SimpleTestDriver> receiver_{this};
1179 };
1180
1181 class SyncReplyReader : public IPC::MessageReplyDeserializer {
1182 public:
SyncReplyReader(int32_t * storage)1183 explicit SyncReplyReader(int32_t* storage) : storage_(storage) {}
1184
1185 SyncReplyReader(const SyncReplyReader&) = delete;
1186 SyncReplyReader& operator=(const SyncReplyReader&) = delete;
1187
1188 ~SyncReplyReader() override = default;
1189
1190 private:
1191 // IPC::MessageReplyDeserializer:
SerializeOutputParameters(const IPC::Message & message,base::PickleIterator iter)1192 bool SerializeOutputParameters(const IPC::Message& message,
1193 base::PickleIterator iter) override {
1194 if (!iter.ReadInt(storage_))
1195 return false;
1196 return true;
1197 }
1198
1199 raw_ptr<int32_t> storage_;
1200 };
1201
TEST_F(IPCChannelProxyMojoTest,SyncAssociatedInterface)1202 TEST_F(IPCChannelProxyMojoTest, SyncAssociatedInterface) {
1203 Init("SyncAssociatedInterface");
1204
1205 ListenerWithSyncAssociatedInterface listener;
1206 CreateProxy(&listener);
1207 listener.set_sync_sender(proxy());
1208 RunProxy();
1209
1210 // Run the client's simple sanity check to completion.
1211 listener.RunUntilQuitRequested();
1212
1213 // Verify that we can send a sync IPC and service an incoming sync request
1214 // while waiting on it
1215 listener.set_response_value(42);
1216 mojo::AssociatedRemote<IPC::mojom::SimpleTestClient> client;
1217 proxy()->GetRemoteAssociatedInterface(
1218 client.BindNewEndpointAndPassReceiver());
1219 int32_t received_value;
1220 EXPECT_TRUE(client->RequestValue(&received_value));
1221 EXPECT_EQ(42, received_value);
1222
1223 // Do it again. This time the client will send a classical sync IPC to us
1224 // while we wait.
1225 received_value = 0;
1226 EXPECT_TRUE(client->RequestValue(&received_value));
1227 EXPECT_EQ(42, received_value);
1228
1229 // Now make a classical sync IPC request to the client. It will send a
1230 // sync associated interface message to us while we wait.
1231 received_value = 0;
1232 auto request = std::make_unique<IPC::SyncMessage>(
1233 0, 0, IPC::Message::PRIORITY_NORMAL,
1234 std::make_unique<SyncReplyReader>(&received_value));
1235 EXPECT_TRUE(proxy()->Send(request.release()));
1236 EXPECT_EQ(42, received_value);
1237
1238 listener.CloseBinding();
1239 EXPECT_TRUE(WaitForClientShutdown());
1240
1241 DestroyProxy();
1242 }
1243
1244 class SimpleTestClientImpl : public IPC::mojom::SimpleTestClient,
1245 public IPC::Listener {
1246 public:
1247 SimpleTestClientImpl() = default;
1248
1249 SimpleTestClientImpl(const SimpleTestClientImpl&) = delete;
1250 SimpleTestClientImpl& operator=(const SimpleTestClientImpl&) = delete;
1251
1252 ~SimpleTestClientImpl() override = default;
1253
set_driver(IPC::mojom::SimpleTestDriver * driver)1254 void set_driver(IPC::mojom::SimpleTestDriver* driver) { driver_ = driver; }
set_sync_sender(IPC::Sender * sync_sender)1255 void set_sync_sender(IPC::Sender* sync_sender) { sync_sender_ = sync_sender; }
1256
WaitForValueRequest()1257 void WaitForValueRequest() { Run(); }
1258
Run()1259 void Run() {
1260 run_loop_ = std::make_unique<base::RunLoop>();
1261 run_loop_->Run();
1262 }
1263
UseSyncSenderForRequest(bool use_sync_sender)1264 void UseSyncSenderForRequest(bool use_sync_sender) {
1265 use_sync_sender_ = use_sync_sender;
1266 }
1267
1268 private:
1269 // IPC::mojom::SimpleTestClient:
RequestValue(RequestValueCallback callback)1270 void RequestValue(RequestValueCallback callback) override {
1271 int32_t response = 0;
1272 if (use_sync_sender_) {
1273 auto reply = std::make_unique<IPC::SyncMessage>(
1274 0, 0, IPC::Message::PRIORITY_NORMAL,
1275 std::make_unique<SyncReplyReader>(&response));
1276 EXPECT_TRUE(sync_sender_->Send(reply.release()));
1277 } else {
1278 DCHECK(driver_);
1279 EXPECT_TRUE(driver_->RequestValue(&response));
1280 }
1281
1282 std::move(callback).Run(response);
1283
1284 DCHECK(run_loop_);
1285 run_loop_->Quit();
1286 }
1287
1288 // No implementation needed. Only called on an endpoint which never binds its
1289 // receiver.
BindSync(mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestClient> receiver,BindSyncCallback callback)1290 void BindSync(
1291 mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestClient> receiver,
1292 BindSyncCallback callback) override {
1293 NOTREACHED();
1294 }
1295
GetReceiverWithQueuedSyncMessage(GetReceiverWithQueuedSyncMessageCallback callback)1296 void GetReceiverWithQueuedSyncMessage(
1297 GetReceiverWithQueuedSyncMessageCallback callback) override {
1298 // Immediately send back a sync IPC over the new pipe and expect the call to
1299 // be interrupted without a reply. Note that we also reply *before* issuing
1300 // the sync call to allow the main test process to make progress.
1301 mojo::AssociatedRemote<IPC::mojom::SimpleTestClient> remote;
1302 mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestClient>
1303 queued_receiver;
1304 {
1305 // The nested receiver we send will already know its peer is closed when
1306 // it arrives.
1307 mojo::AssociatedRemote<IPC::mojom::SimpleTestClient> unused;
1308 queued_receiver = unused.BindNewEndpointAndPassReceiver();
1309 }
1310 std::move(callback).Run(remote.BindNewEndpointAndPassReceiver());
1311 EXPECT_FALSE(remote->BindSync(std::move(queued_receiver)));
1312 }
1313
1314 // IPC::Listener:
OnMessageReceived(const IPC::Message & message)1315 bool OnMessageReceived(const IPC::Message& message) override {
1316 int32_t response;
1317 DCHECK(driver_);
1318 EXPECT_TRUE(driver_->RequestValue(&response));
1319 std::unique_ptr<IPC::Message> reply(
1320 IPC::SyncMessage::GenerateReply(&message));
1321 reply->WriteInt(response);
1322 EXPECT_TRUE(sync_sender_->Send(reply.release()));
1323
1324 DCHECK(run_loop_);
1325 run_loop_->Quit();
1326 return true;
1327 }
1328
OnAssociatedInterfaceRequest(const std::string & interface_name,mojo::ScopedInterfaceEndpointHandle handle)1329 void OnAssociatedInterfaceRequest(
1330 const std::string& interface_name,
1331 mojo::ScopedInterfaceEndpointHandle handle) override {
1332 DCHECK(!receiver_.is_bound());
1333 DCHECK_EQ(interface_name, IPC::mojom::SimpleTestClient::Name_);
1334
1335 receiver_.Bind(
1336 mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestClient>(
1337 std::move(handle)));
1338 }
1339
1340 bool use_sync_sender_ = false;
1341 mojo::AssociatedReceiver<IPC::mojom::SimpleTestClient> receiver_{this};
1342 raw_ptr<IPC::Sender> sync_sender_ = nullptr;
1343 raw_ptr<IPC::mojom::SimpleTestDriver> driver_ = nullptr;
1344 std::unique_ptr<base::RunLoop> run_loop_;
1345 };
1346
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(SyncAssociatedInterface,ChannelProxyClient)1347 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(SyncAssociatedInterface,
1348 ChannelProxyClient) {
1349 SimpleTestClientImpl client_impl;
1350 CreateProxy(&client_impl);
1351 client_impl.set_sync_sender(proxy());
1352 RunProxy();
1353
1354 mojo::AssociatedRemote<IPC::mojom::SimpleTestDriver> driver;
1355 proxy()->GetRemoteAssociatedInterface(
1356 driver.BindNewEndpointAndPassReceiver());
1357 client_impl.set_driver(driver.get());
1358
1359 // Simple sync message sanity check.
1360 driver->ExpectValue(42);
1361 int32_t expected_value = 0;
1362 EXPECT_TRUE(driver->GetExpectedValue(&expected_value));
1363 EXPECT_EQ(42, expected_value);
1364 RequestQuitAndWaitForAck(driver.get());
1365
1366 // Wait for the test driver to perform a sync call test with our own sync
1367 // associated interface message nested inside.
1368 client_impl.UseSyncSenderForRequest(false);
1369 client_impl.WaitForValueRequest();
1370
1371 // Wait for the test driver to perform a sync call test with our own classical
1372 // sync IPC nested inside.
1373 client_impl.UseSyncSenderForRequest(true);
1374 client_impl.WaitForValueRequest();
1375
1376 // Wait for the test driver to perform a classical sync IPC request, with our
1377 // own sync associated interface message nested inside.
1378 client_impl.UseSyncSenderForRequest(false);
1379 client_impl.WaitForValueRequest();
1380
1381 DestroyProxy();
1382 }
1383
1384 // TODO(https://crbug.com/1500560): Disabled for flaky behavior of forced
1385 // process termination. Will be re-enabled with a fix.
TEST_F(IPCChannelProxyMojoTest,DISABLED_SyncAssociatedInterfacePipeError)1386 TEST_F(IPCChannelProxyMojoTest, DISABLED_SyncAssociatedInterfacePipeError) {
1387 // Regression test for https://crbug.com/1494461.
1388
1389 Init("SyncAssociatedInterfacePipeError");
1390
1391 ListenerWithSyncAssociatedInterface listener;
1392 CreateProxy(&listener);
1393 listener.set_sync_sender(proxy());
1394 RunProxy();
1395
1396 mojo::AssociatedRemote<IPC::mojom::SimpleTestClient> client;
1397 proxy()->GetRemoteAssociatedInterface(
1398 client.BindNewEndpointAndPassReceiver());
1399
1400 mojo::AssociatedRemote<IPC::mojom::Terminator> terminator;
1401 proxy()->GetRemoteAssociatedInterface(
1402 terminator.BindNewEndpointAndPassReceiver());
1403
1404 // The setup here is to have the client process add a new associated endpoint
1405 // with a sync message queued on it, towards us. As soon as we receive the
1406 // endpoint we close it, but its state (including its inbound sync message
1407 // queue) isn't actually destroyed until the peer is closed too.
1408 //
1409 // Note that the client creates the endpoint rather than us, because client
1410 // endpoints are assigned lower interface IDs and will thus elicit the
1411 // necessary endpoint ordering to trigger https://crbug.com/1494461 below.
1412 {
1413 base::RunLoop loop;
1414 client->GetReceiverWithQueuedSyncMessage(base::BindLambdaForTesting(
1415 [&loop](mojo::PendingAssociatedReceiver<IPC::mojom::SimpleTestClient>
1416 receiver) { loop.Quit(); }));
1417 loop.Run();
1418 }
1419
1420 // If https://crbug.com/1494461 is present, it should be hit within this call,
1421 // as soon as client termination signals a local pipe error and marks the
1422 // above endpoint's peer as closed.
1423 EXPECT_FALSE(terminator->Terminate());
1424
1425 #if BUILDFLAG(IS_ANDROID)
1426 // NOTE: On Android, the client's forced termination will look like an error,
1427 // but it is not.
1428 WaitForClientShutdown();
1429 #else
1430 EXPECT_TRUE(WaitForClientShutdown());
1431 #endif
1432
1433 DestroyProxy();
1434 }
1435
1436 class TerminatorImpl : public IPC::mojom::Terminator {
1437 public:
1438 TerminatorImpl() = default;
1439 ~TerminatorImpl() override = default;
1440
Create(mojo::PendingAssociatedReceiver<IPC::mojom::Terminator> receiver)1441 static void Create(
1442 mojo::PendingAssociatedReceiver<IPC::mojom::Terminator> receiver) {
1443 mojo::MakeSelfOwnedAssociatedReceiver(std::make_unique<TerminatorImpl>(),
1444 std::move(receiver));
1445 }
1446
1447 // IPC::mojom::Terminator:
Terminate(TerminateCallback callback)1448 void Terminate(TerminateCallback callback) override {
1449 base::Process::TerminateCurrentProcessImmediately(0);
1450 }
1451 };
1452
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(SyncAssociatedInterfacePipeError,ChannelProxyClient)1453 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
1454 SyncAssociatedInterfacePipeError,
1455 ChannelProxyClient) {
1456 SimpleTestClientImpl client_impl;
1457 CreateProxy(&client_impl);
1458
1459 // Let the IO thread receive a message to self-terminate this process. This
1460 // is used to forcibly shut down the client on the test's request. Without
1461 // doing this (and doing a clean shutdown instead) the client will clean up
1462 // interfaces and make it impossible to trigger the regression path for
1463 // https://crbug.com/1494461.
1464 proxy()->AddAssociatedInterfaceForIOThread(
1465 base::BindRepeating(&TerminatorImpl::Create));
1466
1467 RunProxy();
1468 client_impl.Run();
1469 DestroyProxy();
1470 }
1471
TEST_F(IPCChannelProxyMojoTest,Pause)1472 TEST_F(IPCChannelProxyMojoTest, Pause) {
1473 // Ensures that pausing a channel elicits the expected behavior when sending
1474 // messages, unpausing, sending more messages, and then manually flushing.
1475 // Specifically a sequence like:
1476 //
1477 // Connect()
1478 // Send(A)
1479 // Pause()
1480 // Send(B)
1481 // Send(C)
1482 // Unpause(false)
1483 // Send(D)
1484 // Send(E)
1485 // Flush()
1486 //
1487 // must result in the other end receiving messages A, D, E, B, D; in that
1488 // order.
1489 //
1490 // This behavior is required by some consumers of IPC::Channel, and it is not
1491 // sufficient to leave this up to the consumer to implement since associated
1492 // interface requests and messages also need to be queued according to the
1493 // same policy.
1494 Init("CreatePausedClient");
1495
1496 DummyListener listener;
1497 CreateProxy(&listener);
1498 RunProxy();
1499
1500 // This message must be sent immediately since the channel is unpaused.
1501 SendValue(proxy(), 1);
1502
1503 proxy()->Pause();
1504
1505 // These messages must be queued internally since the channel is paused.
1506 SendValue(proxy(), 2);
1507 SendValue(proxy(), 3);
1508
1509 proxy()->Unpause(false /* flush */);
1510
1511 // These messages must be sent immediately since the channel is unpaused.
1512 SendValue(proxy(), 4);
1513 SendValue(proxy(), 5);
1514
1515 // Now we flush the previously queued messages.
1516 proxy()->Flush();
1517
1518 EXPECT_TRUE(WaitForClientShutdown());
1519 DestroyProxy();
1520 }
1521
1522 class ExpectValueSequenceListener : public IPC::Listener {
1523 public:
ExpectValueSequenceListener(base::queue<int32_t> * expected_values,base::OnceClosure quit_closure)1524 ExpectValueSequenceListener(base::queue<int32_t>* expected_values,
1525 base::OnceClosure quit_closure)
1526 : expected_values_(expected_values),
1527 quit_closure_(std::move(quit_closure)) {}
1528
1529 ExpectValueSequenceListener(const ExpectValueSequenceListener&) = delete;
1530 ExpectValueSequenceListener& operator=(const ExpectValueSequenceListener&) =
1531 delete;
1532
1533 ~ExpectValueSequenceListener() override = default;
1534
1535 // IPC::Listener:
OnMessageReceived(const IPC::Message & message)1536 bool OnMessageReceived(const IPC::Message& message) override {
1537 DCHECK(!expected_values_->empty());
1538 base::PickleIterator iter(message);
1539 int32_t should_be_expected;
1540 EXPECT_TRUE(iter.ReadInt(&should_be_expected));
1541 EXPECT_EQ(expected_values_->front(), should_be_expected);
1542 expected_values_->pop();
1543 if (expected_values_->empty())
1544 std::move(quit_closure_).Run();
1545 return true;
1546 }
1547
1548 private:
1549 raw_ptr<base::queue<int32_t>> expected_values_;
1550 base::OnceClosure quit_closure_;
1551 };
1552
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(CreatePausedClient,ChannelProxyClient)1553 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(CreatePausedClient,
1554 ChannelProxyClient) {
1555 base::queue<int32_t> expected_values;
1556 base::RunLoop run_loop;
1557 ExpectValueSequenceListener listener(&expected_values,
1558 run_loop.QuitClosure());
1559 CreateProxy(&listener);
1560 expected_values.push(1);
1561 expected_values.push(4);
1562 expected_values.push(5);
1563 expected_values.push(2);
1564 expected_values.push(3);
1565 RunProxy();
1566 run_loop.Run();
1567 EXPECT_TRUE(expected_values.empty());
1568 DestroyProxy();
1569 }
1570
TEST_F(IPCChannelProxyMojoTest,AssociatedRequestClose)1571 TEST_F(IPCChannelProxyMojoTest, AssociatedRequestClose) {
1572 Init("DropAssociatedRequest");
1573
1574 DummyListener listener;
1575 CreateProxy(&listener);
1576 RunProxy();
1577
1578 mojo::AssociatedRemote<IPC::mojom::AssociatedInterfaceVendor> vendor;
1579 proxy()->GetRemoteAssociatedInterface(
1580 vendor.BindNewEndpointAndPassReceiver());
1581 mojo::AssociatedRemote<IPC::mojom::SimpleTestDriver> tester;
1582 vendor->GetTestInterface(tester.BindNewEndpointAndPassReceiver());
1583 base::RunLoop run_loop;
1584 tester.set_disconnect_handler(run_loop.QuitClosure());
1585 run_loop.Run();
1586
1587 tester.reset();
1588 proxy()->GetRemoteAssociatedInterface(
1589 tester.BindNewEndpointAndPassReceiver());
1590 EXPECT_TRUE(WaitForClientShutdown());
1591 DestroyProxy();
1592 }
1593
1594 class AssociatedInterfaceDroppingListener : public IPC::Listener {
1595 public:
AssociatedInterfaceDroppingListener(base::OnceClosure callback)1596 AssociatedInterfaceDroppingListener(base::OnceClosure callback)
1597 : callback_(std::move(callback)) {}
OnMessageReceived(const IPC::Message & message)1598 bool OnMessageReceived(const IPC::Message& message) override { return false; }
1599
OnAssociatedInterfaceRequest(const std::string & interface_name,mojo::ScopedInterfaceEndpointHandle handle)1600 void OnAssociatedInterfaceRequest(
1601 const std::string& interface_name,
1602 mojo::ScopedInterfaceEndpointHandle handle) override {
1603 if (interface_name == IPC::mojom::SimpleTestDriver::Name_)
1604 std::move(callback_).Run();
1605 }
1606
1607 private:
1608 base::OnceClosure callback_;
1609 };
1610
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(DropAssociatedRequest,ChannelProxyClient)1611 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(DropAssociatedRequest,
1612 ChannelProxyClient) {
1613 base::RunLoop run_loop;
1614 AssociatedInterfaceDroppingListener listener(run_loop.QuitClosure());
1615 CreateProxy(&listener);
1616 RunProxy();
1617 run_loop.Run();
1618 DestroyProxy();
1619 }
1620
1621 #if !BUILDFLAG(IS_APPLE)
1622 // TODO(wez): On Mac we need to set up a MachPortBroker before we can transfer
1623 // Mach ports (which underpin Sharedmemory on Mac) across IPC.
1624
1625 template <class SharedMemoryRegionType>
1626 class IPCChannelMojoSharedMemoryRegionTypedTest : public IPCChannelMojoTest {};
1627
1628 struct WritableRegionTraits {
1629 using RegionType = base::WritableSharedMemoryRegion;
1630 static const char kClientName[];
1631 };
1632 const char WritableRegionTraits::kClientName[] =
1633 "IPCChannelMojoTestSendWritableSharedMemoryRegionClient";
1634 struct UnsafeRegionTraits {
1635 using RegionType = base::UnsafeSharedMemoryRegion;
1636 static const char kClientName[];
1637 };
1638 const char UnsafeRegionTraits::kClientName[] =
1639 "IPCChannelMojoTestSendUnsafeSharedMemoryRegionClient";
1640 struct ReadOnlyRegionTraits {
1641 using RegionType = base::ReadOnlySharedMemoryRegion;
1642 static const char kClientName[];
1643 };
1644 const char ReadOnlyRegionTraits::kClientName[] =
1645 "IPCChannelMojoTestSendReadOnlySharedMemoryRegionClient";
1646
1647 typedef ::testing::
1648 Types<WritableRegionTraits, UnsafeRegionTraits, ReadOnlyRegionTraits>
1649 AllSharedMemoryRegionTraits;
1650 TYPED_TEST_SUITE(IPCChannelMojoSharedMemoryRegionTypedTest,
1651 AllSharedMemoryRegionTraits);
1652
1653 template <class SharedMemoryRegionType>
1654 class ListenerThatExpectsSharedMemoryRegion : public TestListenerBase {
1655 public:
ListenerThatExpectsSharedMemoryRegion(base::OnceClosure quit_closure)1656 explicit ListenerThatExpectsSharedMemoryRegion(base::OnceClosure quit_closure)
1657 : TestListenerBase(std::move(quit_closure)) {}
1658
OnMessageReceived(const IPC::Message & message)1659 bool OnMessageReceived(const IPC::Message& message) override {
1660 base::PickleIterator iter(message);
1661
1662 SharedMemoryRegionType region;
1663 EXPECT_TRUE(IPC::ReadParam(&message, &iter, ®ion));
1664 EXPECT_TRUE(region.IsValid());
1665
1666 // Verify the shared memory region has expected content.
1667 typename SharedMemoryRegionType::MappingType mapping = region.Map();
1668 std::string content = HandleSendingHelper::GetSendingFileContent();
1669 EXPECT_EQ(0, memcmp(mapping.memory(), content.data(), content.size()));
1670
1671 ListenerThatExpectsOK::SendOK(sender());
1672 return true;
1673 }
1674 };
1675
TYPED_TEST(IPCChannelMojoSharedMemoryRegionTypedTest,Send)1676 TYPED_TEST(IPCChannelMojoSharedMemoryRegionTypedTest, Send) {
1677 this->Init(TypeParam::kClientName);
1678
1679 const size_t size = 1004;
1680 typename TypeParam::RegionType region;
1681 base::WritableSharedMemoryMapping mapping;
1682 std::tie(region, mapping) =
1683 base::CreateMappedRegion<typename TypeParam::RegionType>(size);
1684
1685 std::string content = HandleSendingHelper::GetSendingFileContent();
1686 memcpy(mapping.memory(), content.data(), content.size());
1687
1688 // Create a success listener, and launch the child process.
1689 base::RunLoop run_loop;
1690 ListenerThatExpectsOK listener(run_loop.QuitClosure());
1691 this->CreateChannel(&listener);
1692 ASSERT_TRUE(this->ConnectChannel());
1693
1694 // Send the child process an IPC with |shmem| attached, to verify
1695 // that is is correctly wrapped, transferred and unwrapped.
1696 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
1697 IPC::WriteParam(message, region);
1698 ASSERT_TRUE(this->channel()->Send(message));
1699
1700 run_loop.Run();
1701
1702 this->channel()->Close();
1703
1704 EXPECT_TRUE(this->WaitForClientShutdown());
1705 EXPECT_FALSE(region.IsValid());
1706 this->DestroyChannel();
1707 }
1708
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendWritableSharedMemoryRegionClient)1709 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
1710 IPCChannelMojoTestSendWritableSharedMemoryRegionClient) {
1711 base::RunLoop run_loop;
1712 ListenerThatExpectsSharedMemoryRegion<base::WritableSharedMemoryRegion>
1713 listener(run_loop.QuitClosure());
1714 Connect(&listener);
1715 listener.set_sender(channel());
1716
1717 run_loop.Run();
1718
1719 Close();
1720 }
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendUnsafeSharedMemoryRegionClient)1721 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
1722 IPCChannelMojoTestSendUnsafeSharedMemoryRegionClient) {
1723 base::RunLoop run_loop;
1724 ListenerThatExpectsSharedMemoryRegion<base::UnsafeSharedMemoryRegion>
1725 listener(run_loop.QuitClosure());
1726 Connect(&listener);
1727 listener.set_sender(channel());
1728
1729 run_loop.Run();
1730
1731 Close();
1732 }
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendReadOnlySharedMemoryRegionClient)1733 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
1734 IPCChannelMojoTestSendReadOnlySharedMemoryRegionClient) {
1735 base::RunLoop run_loop;
1736 ListenerThatExpectsSharedMemoryRegion<base::ReadOnlySharedMemoryRegion>
1737 listener(run_loop.QuitClosure());
1738 Connect(&listener);
1739 listener.set_sender(channel());
1740
1741 run_loop.Run();
1742
1743 Close();
1744 }
1745 #endif // !BUILDFLAG(IS_APPLE)
1746
1747 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
1748
1749 class ListenerThatExpectsFile : public TestListenerBase {
1750 public:
ListenerThatExpectsFile(base::OnceClosure quit_closure)1751 explicit ListenerThatExpectsFile(base::OnceClosure quit_closure)
1752 : TestListenerBase(std::move(quit_closure)) {}
1753
OnMessageReceived(const IPC::Message & message)1754 bool OnMessageReceived(const IPC::Message& message) override {
1755 base::PickleIterator iter(message);
1756 HandleSendingHelper::ReadReceivedFile(message, &iter);
1757 ListenerThatExpectsOK::SendOK(sender());
1758 return true;
1759 }
1760 };
1761
TEST_F(IPCChannelMojoTest,SendPlatformFile)1762 TEST_F(IPCChannelMojoTest, SendPlatformFile) {
1763 Init("IPCChannelMojoTestSendPlatformFileClient");
1764
1765 base::RunLoop run_loop;
1766 ListenerThatExpectsOK listener(run_loop.QuitClosure());
1767 CreateChannel(&listener);
1768 ASSERT_TRUE(ConnectChannel());
1769
1770 base::ScopedTempDir temp_dir;
1771 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1772 base::File file(HandleSendingHelper::GetSendingFilePath(temp_dir.GetPath()),
1773 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
1774 base::File::FLAG_READ);
1775 HandleSendingHelper::WriteFileThenSend(channel(), file);
1776 run_loop.Run();
1777
1778 channel()->Close();
1779
1780 EXPECT_TRUE(WaitForClientShutdown());
1781 DestroyChannel();
1782 }
1783
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendPlatformFileClient)1784 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendPlatformFileClient) {
1785 base::RunLoop run_loop;
1786 ListenerThatExpectsFile listener(run_loop.QuitClosure());
1787 Connect(&listener);
1788 listener.set_sender(channel());
1789
1790 run_loop.Run();
1791
1792 Close();
1793 }
1794
1795 class ListenerThatExpectsFileAndMessagePipe : public TestListenerBase {
1796 public:
ListenerThatExpectsFileAndMessagePipe(base::OnceClosure quit_closure)1797 explicit ListenerThatExpectsFileAndMessagePipe(base::OnceClosure quit_closure)
1798 : TestListenerBase(std::move(quit_closure)) {}
1799
1800 ~ListenerThatExpectsFileAndMessagePipe() override = default;
1801
OnMessageReceived(const IPC::Message & message)1802 bool OnMessageReceived(const IPC::Message& message) override {
1803 base::PickleIterator iter(message);
1804 HandleSendingHelper::ReadReceivedFile(message, &iter);
1805 HandleSendingHelper::ReadReceivedPipe(message, &iter);
1806 ListenerThatExpectsOK::SendOK(sender());
1807 return true;
1808 }
1809 };
1810
TEST_F(IPCChannelMojoTest,SendPlatformFileAndMessagePipe)1811 TEST_F(IPCChannelMojoTest, SendPlatformFileAndMessagePipe) {
1812 Init("IPCChannelMojoTestSendPlatformFileAndMessagePipeClient");
1813
1814 base::RunLoop run_loop;
1815 ListenerThatExpectsOK listener(run_loop.QuitClosure());
1816 CreateChannel(&listener);
1817 ASSERT_TRUE(ConnectChannel());
1818
1819 base::ScopedTempDir temp_dir;
1820 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1821 base::File file(HandleSendingHelper::GetSendingFilePath(temp_dir.GetPath()),
1822 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
1823 base::File::FLAG_READ);
1824 TestingMessagePipe pipe;
1825 HandleSendingHelper::WriteFileAndPipeThenSend(channel(), file, &pipe);
1826
1827 run_loop.Run();
1828 channel()->Close();
1829
1830 EXPECT_TRUE(WaitForClientShutdown());
1831 DestroyChannel();
1832 }
1833
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendPlatformFileAndMessagePipeClient)1834 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
1835 IPCChannelMojoTestSendPlatformFileAndMessagePipeClient) {
1836 base::RunLoop run_loop;
1837 ListenerThatExpectsFileAndMessagePipe listener(run_loop.QuitClosure());
1838 Connect(&listener);
1839 listener.set_sender(channel());
1840
1841 run_loop.Run();
1842
1843 Close();
1844 }
1845
1846 #endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
1847
1848 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
1849
1850 const base::ProcessId kMagicChildId = 54321;
1851
1852 class ListenerThatVerifiesPeerPid : public TestListenerBase {
1853 public:
ListenerThatVerifiesPeerPid(base::OnceClosure quit_closure)1854 explicit ListenerThatVerifiesPeerPid(base::OnceClosure quit_closure)
1855 : TestListenerBase(std::move(quit_closure)) {}
1856
OnChannelConnected(int32_t peer_pid)1857 void OnChannelConnected(int32_t peer_pid) override {
1858 EXPECT_EQ(peer_pid, kMagicChildId);
1859 RunQuitClosure();
1860 }
1861
OnMessageReceived(const IPC::Message & message)1862 bool OnMessageReceived(const IPC::Message& message) override {
1863 NOTREACHED();
1864 return true;
1865 }
1866 };
1867
1868 // The global PID is only used on systems that use the zygote. Hence, this
1869 // test is disabled on other platforms.
TEST_F(IPCChannelMojoTest,VerifyGlobalPid)1870 TEST_F(IPCChannelMojoTest, VerifyGlobalPid) {
1871 Init("IPCChannelMojoTestVerifyGlobalPidClient");
1872
1873 base::RunLoop run_loop;
1874 ListenerThatVerifiesPeerPid listener(run_loop.QuitClosure());
1875 CreateChannel(&listener);
1876 ASSERT_TRUE(ConnectChannel());
1877
1878 run_loop.Run();
1879 channel()->Close();
1880
1881 EXPECT_TRUE(WaitForClientShutdown());
1882 DestroyChannel();
1883 }
1884
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestVerifyGlobalPidClient)1885 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestVerifyGlobalPidClient) {
1886 IPC::Channel::SetGlobalPid(kMagicChildId);
1887
1888 base::RunLoop run_loop;
1889 ListenerThatQuits listener(run_loop.QuitClosure());
1890 Connect(&listener);
1891
1892 run_loop.Run();
1893
1894 Close();
1895 }
1896
1897 #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
1898
1899 class ListenerWithUrgentMessageAssociatedInterface
1900 : public IPC::mojom::InterfaceWithUrgentMethod,
1901 public IPC::Listener,
1902 public IPC::UrgentMessageObserver {
1903 public:
ListenerWithUrgentMessageAssociatedInterface(base::OnceClosure quit_closure)1904 explicit ListenerWithUrgentMessageAssociatedInterface(
1905 base::OnceClosure quit_closure)
1906 : quit_closure_(std::move(quit_closure)) {}
1907
1908 ListenerWithUrgentMessageAssociatedInterface(
1909 const ListenerWithUrgentMessageAssociatedInterface&) = delete;
1910 ListenerWithUrgentMessageAssociatedInterface& operator=(
1911 const ListenerWithUrgentMessageAssociatedInterface&) = delete;
1912
1913 ~ListenerWithUrgentMessageAssociatedInterface() override = default;
1914
num_maybe_urgent_messages_received() const1915 uint32_t num_maybe_urgent_messages_received() const {
1916 return num_maybe_urgent_messages_received_;
1917 }
1918
num_urgent_messages_received() const1919 uint32_t num_urgent_messages_received() const {
1920 return num_urgent_messages_received_;
1921 }
1922
num_non_urgent_messages_received() const1923 uint32_t num_non_urgent_messages_received() const {
1924 return num_non_urgent_messages_received_;
1925 }
1926
num_observer_urgent_messages_received() const1927 uint32_t num_observer_urgent_messages_received() const {
1928 return num_observer_urgent_messages_received_.load(
1929 std::memory_order_relaxed);
1930 }
1931
num_observer_urgent_messages_processed() const1932 uint32_t num_observer_urgent_messages_processed() const {
1933 return num_observer_urgent_messages_processed_.load(
1934 std::memory_order_relaxed);
1935 }
1936
was_process_callback_pending_during_ipc_dispatch() const1937 bool was_process_callback_pending_during_ipc_dispatch() const {
1938 return was_process_callback_pending_during_ipc_dispatch_;
1939 }
1940
1941 private:
1942 // IPC::mojom::InterfaceWithUrgentMethod:
MaybeUrgentMessage(bool is_urgent)1943 void MaybeUrgentMessage(bool is_urgent) override {
1944 ++num_maybe_urgent_messages_received_;
1945 if (!is_urgent) {
1946 return;
1947 }
1948 ++num_urgent_messages_received_;
1949 uint32_t received =
1950 num_observer_urgent_messages_received_.load(std::memory_order_relaxed);
1951 uint32_t processed =
1952 num_observer_urgent_messages_processed_.load(std::memory_order_relaxed);
1953 // The "processed" observer callback should run after the IPC is dispatched,
1954 // so there should always be at least one less processed callback here.
1955 was_process_callback_pending_during_ipc_dispatch_ =
1956 was_process_callback_pending_during_ipc_dispatch_ &&
1957 (processed < received);
1958 }
1959
NonUrgentMessage()1960 void NonUrgentMessage() override { ++num_non_urgent_messages_received_; }
1961
RequestQuit(RequestQuitCallback callback)1962 void RequestQuit(RequestQuitCallback callback) override {
1963 std::move(quit_closure_).Run();
1964 std::move(callback).Run();
1965 }
1966
1967 // IPC::Listener:
OnMessageReceived(const IPC::Message & message)1968 bool OnMessageReceived(const IPC::Message& message) override { return true; }
1969
OnAssociatedInterfaceRequest(const std::string & interface_name,mojo::ScopedInterfaceEndpointHandle handle)1970 void OnAssociatedInterfaceRequest(
1971 const std::string& interface_name,
1972 mojo::ScopedInterfaceEndpointHandle handle) override {
1973 CHECK(!receiver_.is_bound());
1974 CHECK_EQ(interface_name, IPC::mojom::InterfaceWithUrgentMethod::Name_);
1975 receiver_.Bind(
1976 mojo::PendingAssociatedReceiver<IPC::mojom::InterfaceWithUrgentMethod>(
1977 std::move(handle)));
1978 }
1979
1980 // IPC::UrgentMessageObserver:
OnUrgentMessageReceived()1981 void OnUrgentMessageReceived() override {
1982 std::atomic_fetch_add_explicit(&num_observer_urgent_messages_received_,
1983 uint32_t(1), std::memory_order_relaxed);
1984 }
1985
OnUrgentMessageProcessed()1986 void OnUrgentMessageProcessed() override {
1987 std::atomic_fetch_add_explicit(&num_observer_urgent_messages_processed_,
1988 uint32_t(1), std::memory_order_relaxed);
1989 }
1990
1991 base::OnceClosure quit_closure_;
1992 mojo::AssociatedReceiver<IPC::mojom::InterfaceWithUrgentMethod> receiver_{
1993 this};
1994 uint32_t num_maybe_urgent_messages_received_{0};
1995 uint32_t num_urgent_messages_received_{0};
1996 uint32_t num_non_urgent_messages_received_{0};
1997 std::atomic<uint32_t> num_observer_urgent_messages_received_{0};
1998 std::atomic<uint32_t> num_observer_urgent_messages_processed_{0};
1999 bool was_process_callback_pending_during_ipc_dispatch_{true};
2000 };
2001
TEST_F(IPCChannelProxyMojoTest,UrgentMessageObserver)2002 TEST_F(IPCChannelProxyMojoTest, UrgentMessageObserver) {
2003 Init("UrgentMessageObserverClient");
2004
2005 base::RunLoop run_loop;
2006 ListenerWithUrgentMessageAssociatedInterface listener(run_loop.QuitClosure());
2007 CreateProxy(&listener, /*urgent_message_observer=*/&listener);
2008 RunProxy();
2009
2010 run_loop.Run();
2011
2012 EXPECT_TRUE(WaitForClientShutdown());
2013
2014 EXPECT_EQ(listener.num_maybe_urgent_messages_received(), 5u);
2015 EXPECT_EQ(listener.num_urgent_messages_received(), 3u);
2016 EXPECT_EQ(listener.num_non_urgent_messages_received(), 2u);
2017
2018 EXPECT_EQ(listener.num_observer_urgent_messages_received(), 3u);
2019 EXPECT_EQ(listener.num_observer_urgent_messages_processed(), 3u);
2020 EXPECT_TRUE(listener.was_process_callback_pending_during_ipc_dispatch());
2021
2022 DestroyProxy();
2023 }
2024
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(UrgentMessageObserverClient,ChannelProxyClient)2025 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
2026 UrgentMessageObserverClient,
2027 ChannelProxyClient) {
2028 DummyListener listener;
2029 CreateProxy(&listener);
2030 RunProxy();
2031
2032 mojo::AssociatedRemote<IPC::mojom::InterfaceWithUrgentMethod> remote;
2033 proxy()->GetRemoteAssociatedInterface(
2034 remote.BindNewEndpointAndPassReceiver());
2035
2036 {
2037 mojo::UrgentMessageScope scope;
2038 remote->MaybeUrgentMessage(/*is_urgent=*/true);
2039 }
2040 remote->NonUrgentMessage();
2041 remote->MaybeUrgentMessage(/*is_urgent=*/false);
2042 {
2043 mojo::UrgentMessageScope scope;
2044 remote->MaybeUrgentMessage(/*is_urgent=*/true);
2045 }
2046 remote->NonUrgentMessage();
2047 remote->MaybeUrgentMessage(/*is_urgent=*/false);
2048 {
2049 mojo::UrgentMessageScope scope;
2050 remote->MaybeUrgentMessage(/*is_urgent=*/true);
2051 }
2052
2053 base::RunLoop run_loop;
2054 remote->RequestQuit(run_loop.QuitClosure());
2055 run_loop.Run();
2056
2057 DestroyProxy();
2058 }
2059
2060 } // namespace
2061