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.
5 #include "ipc/mojo/ipc_channel_mojo.h"
7 #include "base/base_paths.h"
8 #include "base/files/file.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/path_service.h"
11 #include "base/pickle.h"
12 #include "base/run_loop.h"
13 #include "base/test/test_timeouts.h"
14 #include "base/threading/thread.h"
15 #include "ipc/ipc_message.h"
16 #include "ipc/ipc_test_base.h"
17 #include "ipc/ipc_test_channel_listener.h"
18 #include "ipc/mojo/ipc_channel_mojo_host.h"
19 #include "ipc/mojo/ipc_mojo_handle_attachment.h"
20 #include "ipc/mojo/ipc_mojo_message_helper.h"
21 #include "ipc/mojo/scoped_ipc_support.h"
24 #include "base/file_descriptor_posix.h"
25 #include "ipc/ipc_platform_file_attachment_posix.h"
30 class ListenerThatExpectsOK
: public IPC::Listener
{
32 ListenerThatExpectsOK()
33 : received_ok_(false) {}
35 ~ListenerThatExpectsOK() override
{}
37 bool OnMessageReceived(const IPC::Message
& message
) override
{
38 PickleIterator
iter(message
);
39 std::string should_be_ok
;
40 EXPECT_TRUE(iter
.ReadString(&should_be_ok
));
41 EXPECT_EQ(should_be_ok
, "OK");
43 base::MessageLoop::current()->Quit();
47 void OnChannelError() override
{
48 // The connection should be healthy while the listener is waiting
49 // message. An error can occur after that because the peer
54 static void SendOK(IPC::Sender
* sender
) {
55 IPC::Message
* message
= new IPC::Message(
56 0, 2, IPC::Message::PRIORITY_NORMAL
);
57 message
->WriteString(std::string("OK"));
58 ASSERT_TRUE(sender
->Send(message
));
67 explicit ChannelClient(IPC::Listener
* listener
, const char* name
) {
69 new IPC::ScopedIPCSupport(main_message_loop_
.task_runner()));
70 channel_
= IPC::ChannelMojo::Create(NULL
,
71 IPCTestBase::GetChannelName(name
),
72 IPC::Channel::MODE_CLIENT
,
77 CHECK(channel_
->Connect());
83 base::RunLoop run_loop
;
84 base::MessageLoop::current()->PostTask(FROM_HERE
, run_loop
.QuitClosure());
88 IPC::ChannelMojo
* channel() const { return channel_
.get(); }
91 base::MessageLoopForIO main_message_loop_
;
92 scoped_ptr
<IPC::ScopedIPCSupport
> ipc_support_
;
93 scoped_ptr
<IPC::ChannelMojo
> channel_
;
96 class IPCChannelMojoTestBase
: public IPCTestBase
{
98 void InitWithMojo(const std::string
& test_client_name
) {
99 Init(test_client_name
);
100 ipc_support_
.reset(new IPC::ScopedIPCSupport(task_runner()));
103 void TearDown() override
{
104 // Make sure Mojo IPC support is properly shutdown on the I/O loop before
105 // TearDown continues.
106 ipc_support_
.reset();
107 base::RunLoop run_loop
;
108 task_runner()->PostTask(FROM_HERE
, run_loop
.QuitClosure());
111 IPCTestBase::TearDown();
115 scoped_ptr
<IPC::ScopedIPCSupport
> ipc_support_
;
118 class IPCChannelMojoTest
: public IPCChannelMojoTestBase
{
120 scoped_ptr
<IPC::ChannelFactory
> CreateChannelFactory(
121 const IPC::ChannelHandle
& handle
,
122 base::SequencedTaskRunner
* runner
) override
{
123 host_
.reset(new IPC::ChannelMojoHost(task_runner()));
124 return IPC::ChannelMojo::CreateServerFactory(host_
->channel_delegate(),
128 bool DidStartClient() override
{
129 bool ok
= IPCTestBase::DidStartClient();
131 host_
->OnClientLaunched(client_process().Handle());
136 scoped_ptr
<IPC::ChannelMojoHost
> host_
;
140 class TestChannelListenerWithExtraExpectations
141 : public IPC::TestChannelListener
{
143 TestChannelListenerWithExtraExpectations()
144 : is_connected_called_(false) {
147 void OnChannelConnected(int32 peer_pid
) override
{
148 IPC::TestChannelListener::OnChannelConnected(peer_pid
);
149 EXPECT_TRUE(base::kNullProcessId
!= peer_pid
);
150 is_connected_called_
= true;
153 bool is_connected_called() const { return is_connected_called_
; }
156 bool is_connected_called_
;
159 TEST_F(IPCChannelMojoTest
, ConnectedFromClient
) {
160 InitWithMojo("IPCChannelMojoTestClient");
162 // Set up IPC channel and start client.
163 TestChannelListenerWithExtraExpectations listener
;
164 CreateChannel(&listener
);
165 listener
.Init(sender());
166 ASSERT_TRUE(ConnectChannel());
167 ASSERT_TRUE(StartClient());
169 IPC::TestChannelListener::SendOneMessage(
170 sender(), "hello from parent");
172 base::MessageLoop::current()->Run();
173 EXPECT_TRUE(base::kNullProcessId
!= this->channel()->GetPeerPID());
175 this->channel()->Close();
177 EXPECT_TRUE(WaitForClientShutdown());
178 EXPECT_TRUE(listener
.is_connected_called());
179 EXPECT_TRUE(listener
.HasSentAll());
184 // A long running process that connects to us
185 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient
) {
186 TestChannelListenerWithExtraExpectations listener
;
187 ChannelClient
client(&listener
, "IPCChannelMojoTestClient");
189 listener
.Init(client
.channel());
191 IPC::TestChannelListener::SendOneMessage(
192 client
.channel(), "hello from child");
193 base::MessageLoop::current()->Run();
194 EXPECT_TRUE(listener
.is_connected_called());
195 EXPECT_TRUE(listener
.HasSentAll());
202 class ListenerExpectingErrors
: public IPC::Listener
{
204 ListenerExpectingErrors()
205 : has_error_(false) {
208 void OnChannelConnected(int32 peer_pid
) override
{
209 base::MessageLoop::current()->Quit();
212 bool OnMessageReceived(const IPC::Message
& message
) override
{ return true; }
214 void OnChannelError() override
{
216 base::MessageLoop::current()->Quit();
219 bool has_error() const { return has_error_
; }
226 class IPCChannelMojoErrorTest
: public IPCChannelMojoTestBase
{
228 scoped_ptr
<IPC::ChannelFactory
> CreateChannelFactory(
229 const IPC::ChannelHandle
& handle
,
230 base::SequencedTaskRunner
* runner
) override
{
231 host_
.reset(new IPC::ChannelMojoHost(task_runner()));
232 return IPC::ChannelMojo::CreateServerFactory(host_
->channel_delegate(),
236 bool DidStartClient() override
{
237 bool ok
= IPCTestBase::DidStartClient();
239 host_
->OnClientLaunched(client_process().Handle());
244 scoped_ptr
<IPC::ChannelMojoHost
> host_
;
247 class ListenerThatQuits
: public IPC::Listener
{
249 ListenerThatQuits() {
252 bool OnMessageReceived(const IPC::Message
& message
) override
{
256 void OnChannelConnected(int32 peer_pid
) override
{
257 base::MessageLoop::current()->Quit();
261 // A long running process that connects to us.
262 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient
) {
263 ListenerThatQuits listener
;
264 ChannelClient
client(&listener
, "IPCChannelMojoErraticTestClient");
267 base::MessageLoop::current()->Run();
274 TEST_F(IPCChannelMojoErrorTest
, SendFailWithPendingMessages
) {
275 InitWithMojo("IPCChannelMojoErraticTestClient");
277 // Set up IPC channel and start client.
278 ListenerExpectingErrors listener
;
279 CreateChannel(&listener
);
280 ASSERT_TRUE(ConnectChannel());
282 // This matches a value in mojo/edk/system/constants.h
283 const int kMaxMessageNumBytes
= 4 * 1024 * 1024;
284 std::string
overly_large_data(kMaxMessageNumBytes
, '*');
285 // This messages are queued as pending.
286 for (size_t i
= 0; i
< 10; ++i
) {
287 IPC::TestChannelListener::SendOneMessage(
288 sender(), overly_large_data
.c_str());
291 ASSERT_TRUE(StartClient());
292 base::MessageLoop::current()->Run();
294 this->channel()->Close();
296 EXPECT_TRUE(WaitForClientShutdown());
297 EXPECT_TRUE(listener
.has_error());
302 struct TestingMessagePipe
{
303 TestingMessagePipe() {
304 EXPECT_EQ(MOJO_RESULT_OK
, mojo::CreateMessagePipe(nullptr, &self
, &peer
));
307 mojo::ScopedMessagePipeHandle self
;
308 mojo::ScopedMessagePipeHandle peer
;
311 class HandleSendingHelper
{
313 static std::string
GetSendingFileContent() { return "Hello"; }
315 static void WritePipe(IPC::Message
* message
, TestingMessagePipe
* pipe
) {
316 std::string content
= HandleSendingHelper::GetSendingFileContent();
317 EXPECT_EQ(MOJO_RESULT_OK
,
318 mojo::WriteMessageRaw(pipe
->self
.get(), &content
[0],
319 static_cast<uint32_t>(content
.size()),
322 IPC::MojoMessageHelper::WriteMessagePipeTo(message
, pipe
->peer
.Pass()));
325 static void WritePipeThenSend(IPC::Sender
* sender
, TestingMessagePipe
* pipe
) {
326 IPC::Message
* message
=
327 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL
);
328 WritePipe(message
, pipe
);
329 ASSERT_TRUE(sender
->Send(message
));
332 static void ReadReceivedPipe(const IPC::Message
& message
,
333 PickleIterator
* iter
) {
334 mojo::ScopedMessagePipeHandle pipe
;
336 IPC::MojoMessageHelper::ReadMessagePipeFrom(&message
, iter
, &pipe
));
337 std::string
content(GetSendingFileContent().size(), ' ');
339 uint32_t num_bytes
= static_cast<uint32_t>(content
.size());
340 EXPECT_EQ(MOJO_RESULT_OK
,
341 mojo::ReadMessageRaw(pipe
.get(), &content
[0], &num_bytes
, nullptr,
343 EXPECT_EQ(content
, GetSendingFileContent());
346 #if defined(OS_POSIX)
347 static base::FilePath
GetSendingFilePath() {
349 bool ok
= PathService::Get(base::DIR_CACHE
, &path
);
351 return path
.Append("ListenerThatExpectsFile.txt");
354 static void WriteFile(IPC::Message
* message
, base::File
& file
) {
355 std::string content
= GetSendingFileContent();
356 file
.WriteAtCurrentPos(content
.data(), content
.size());
358 message
->WriteAttachment(new IPC::internal::PlatformFileAttachment(
359 base::ScopedFD(file
.TakePlatformFile())));
362 static void WriteFileThenSend(IPC::Sender
* sender
, base::File
& file
) {
363 IPC::Message
* message
=
364 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL
);
365 WriteFile(message
, file
);
366 ASSERT_TRUE(sender
->Send(message
));
369 static void WriteFileAndPipeThenSend(IPC::Sender
* sender
,
371 TestingMessagePipe
* pipe
) {
372 IPC::Message
* message
=
373 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL
);
374 WriteFile(message
, file
);
375 WritePipe(message
, pipe
);
376 ASSERT_TRUE(sender
->Send(message
));
379 static void ReadReceivedFile(const IPC::Message
& message
,
380 PickleIterator
* iter
) {
382 scoped_refptr
<IPC::MessageAttachment
> attachment
;
383 EXPECT_TRUE(message
.ReadAttachment(iter
, &attachment
));
384 base::File
file(attachment
->TakePlatformFile());
385 std::string
content(GetSendingFileContent().size(), ' ');
386 file
.Read(0, &content
[0], content
.size());
387 EXPECT_EQ(content
, GetSendingFileContent());
392 class ListenerThatExpectsMessagePipe
: public IPC::Listener
{
394 ListenerThatExpectsMessagePipe() : sender_(NULL
) {}
396 ~ListenerThatExpectsMessagePipe() override
{}
398 bool OnMessageReceived(const IPC::Message
& message
) override
{
399 PickleIterator
iter(message
);
400 HandleSendingHelper::ReadReceivedPipe(message
, &iter
);
401 base::MessageLoop::current()->Quit();
402 ListenerThatExpectsOK::SendOK(sender_
);
406 void OnChannelError() override
{ NOTREACHED(); }
408 void set_sender(IPC::Sender
* sender
) { sender_
= sender
; }
411 IPC::Sender
* sender_
;
414 TEST_F(IPCChannelMojoTest
, SendMessagePipe
) {
415 InitWithMojo("IPCChannelMojoTestSendMessagePipeClient");
417 ListenerThatExpectsOK listener
;
418 CreateChannel(&listener
);
419 ASSERT_TRUE(ConnectChannel());
420 ASSERT_TRUE(StartClient());
422 TestingMessagePipe pipe
;
423 HandleSendingHelper::WritePipeThenSend(channel(), &pipe
);
425 base::MessageLoop::current()->Run();
426 this->channel()->Close();
428 EXPECT_TRUE(WaitForClientShutdown());
432 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendMessagePipeClient
) {
433 ListenerThatExpectsMessagePipe listener
;
434 ChannelClient
client(&listener
, "IPCChannelMojoTestSendMessagePipeClient");
436 listener
.set_sender(client
.channel());
438 base::MessageLoop::current()->Run();
446 class IPCChannelMojoDeadHandleTest
: public IPCChannelMojoTestBase
{
448 virtual scoped_ptr
<IPC::ChannelFactory
> CreateChannelFactory(
449 const IPC::ChannelHandle
& handle
,
450 base::SequencedTaskRunner
* runner
) override
{
451 host_
.reset(new IPC::ChannelMojoHost(task_runner()));
452 return IPC::ChannelMojo::CreateServerFactory(host_
->channel_delegate(),
456 virtual bool DidStartClient() override
{
457 IPCTestBase::DidStartClient();
458 const base::ProcessHandle client
= client_process().Handle();
459 // Forces GetFileHandleForProcess() fail. It happens occasionally
460 // in production, so we should exercise it somehow.
461 // TODO(morrita): figure out how to safely test this. See crbug.com/464109.
462 // ::CloseHandle(client);
463 host_
->OnClientLaunched(client
);
468 scoped_ptr
<IPC::ChannelMojoHost
> host_
;
471 TEST_F(IPCChannelMojoDeadHandleTest
, InvalidClientHandle
) {
472 // Any client type is fine as it is going to be killed anyway.
473 InitWithMojo("IPCChannelMojoTestDoNothingClient");
475 // Set up IPC channel and start client.
476 ListenerExpectingErrors listener
;
477 CreateChannel(&listener
);
478 ASSERT_TRUE(ConnectChannel());
480 ASSERT_TRUE(StartClient());
481 base::MessageLoop::current()->Run();
483 this->channel()->Close();
485 // TODO(morrita): We need CloseHandle() call in DidStartClient(),
486 // which has been disabled since crrev.com/843113003, to
487 // make this fail. See crbug.com/464109.
488 // EXPECT_FALSE(WaitForClientShutdown());
489 WaitForClientShutdown();
490 EXPECT_TRUE(listener
.has_error());
495 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestDoNothingClient
) {
496 ListenerThatQuits listener
;
497 ChannelClient
client(&listener
, "IPCChannelMojoTestDoNothingClient");
500 // Quits without running the message loop as this client won't
501 // receive any messages from the server.
507 #if defined(OS_POSIX)
508 class ListenerThatExpectsFile
: public IPC::Listener
{
510 ListenerThatExpectsFile()
513 ~ListenerThatExpectsFile() override
{}
515 bool OnMessageReceived(const IPC::Message
& message
) override
{
516 PickleIterator
iter(message
);
517 HandleSendingHelper::ReadReceivedFile(message
, &iter
);
518 base::MessageLoop::current()->Quit();
519 ListenerThatExpectsOK::SendOK(sender_
);
523 void OnChannelError() override
{
527 void set_sender(IPC::Sender
* sender
) { sender_
= sender
; }
530 IPC::Sender
* sender_
;
534 TEST_F(IPCChannelMojoTest
, SendPlatformHandle
) {
535 InitWithMojo("IPCChannelMojoTestSendPlatformHandleClient");
537 ListenerThatExpectsOK listener
;
538 CreateChannel(&listener
);
539 ASSERT_TRUE(ConnectChannel());
540 ASSERT_TRUE(StartClient());
542 base::File
file(HandleSendingHelper::GetSendingFilePath(),
543 base::File::FLAG_CREATE_ALWAYS
| base::File::FLAG_WRITE
|
544 base::File::FLAG_READ
);
545 HandleSendingHelper::WriteFileThenSend(channel(), file
);
546 base::MessageLoop::current()->Run();
548 this->channel()->Close();
550 EXPECT_TRUE(WaitForClientShutdown());
554 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient
) {
555 ListenerThatExpectsFile listener
;
556 ChannelClient
client(
557 &listener
, "IPCChannelMojoTestSendPlatformHandleClient");
559 listener
.set_sender(client
.channel());
561 base::MessageLoop::current()->Run();
568 class ListenerThatExpectsFileAndPipe
: public IPC::Listener
{
570 ListenerThatExpectsFileAndPipe() : sender_(NULL
) {}
572 ~ListenerThatExpectsFileAndPipe() override
{}
574 bool OnMessageReceived(const IPC::Message
& message
) override
{
575 PickleIterator
iter(message
);
576 HandleSendingHelper::ReadReceivedFile(message
, &iter
);
577 HandleSendingHelper::ReadReceivedPipe(message
, &iter
);
578 base::MessageLoop::current()->Quit();
579 ListenerThatExpectsOK::SendOK(sender_
);
583 void OnChannelError() override
{ NOTREACHED(); }
585 void set_sender(IPC::Sender
* sender
) { sender_
= sender
; }
588 IPC::Sender
* sender_
;
591 TEST_F(IPCChannelMojoTest
, SendPlatformHandleAndPipe
) {
592 InitWithMojo("IPCChannelMojoTestSendPlatformHandleAndPipeClient");
594 ListenerThatExpectsOK listener
;
595 CreateChannel(&listener
);
596 ASSERT_TRUE(ConnectChannel());
597 ASSERT_TRUE(StartClient());
599 base::File
file(HandleSendingHelper::GetSendingFilePath(),
600 base::File::FLAG_CREATE_ALWAYS
| base::File::FLAG_WRITE
|
601 base::File::FLAG_READ
);
602 TestingMessagePipe pipe
;
603 HandleSendingHelper::WriteFileAndPipeThenSend(channel(), file
, &pipe
);
605 base::MessageLoop::current()->Run();
606 this->channel()->Close();
608 EXPECT_TRUE(WaitForClientShutdown());
612 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(
613 IPCChannelMojoTestSendPlatformHandleAndPipeClient
) {
614 ListenerThatExpectsFileAndPipe listener
;
615 ChannelClient
client(&listener
,
616 "IPCChannelMojoTestSendPlatformHandleAndPipeClient");
618 listener
.set_sender(client
.channel());
620 base::MessageLoop::current()->Run();
629 #if defined(OS_LINUX)
631 const base::ProcessId kMagicChildId
= 54321;
633 class ListenerThatVerifiesPeerPid
: public IPC::Listener
{
635 void OnChannelConnected(int32 peer_pid
) override
{
636 EXPECT_EQ(peer_pid
, kMagicChildId
);
637 base::MessageLoop::current()->Quit();
640 bool OnMessageReceived(const IPC::Message
& message
) override
{
646 TEST_F(IPCChannelMojoTest
, VerifyGlobalPid
) {
647 InitWithMojo("IPCChannelMojoTestVerifyGlobalPidClient");
649 ListenerThatVerifiesPeerPid listener
;
650 CreateChannel(&listener
);
651 ASSERT_TRUE(ConnectChannel());
652 ASSERT_TRUE(StartClient());
654 base::MessageLoop::current()->Run();
657 EXPECT_TRUE(WaitForClientShutdown());
661 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestVerifyGlobalPidClient
) {
662 IPC::Channel::SetGlobalPid(kMagicChildId
);
663 ListenerThatQuits listener
;
664 ChannelClient
client(&listener
,
665 "IPCChannelMojoTestVerifyGlobalPidClient");
668 base::MessageLoop::current()->Run();