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