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/threading/thread.h"
13 #include "ipc/ipc_message.h"
14 #include "ipc/ipc_test_base.h"
15 #include "ipc/ipc_test_channel_listener.h"
16 #include "ipc/mojo/ipc_channel_mojo_host.h"
19 #include "base/file_descriptor_posix.h"
24 class ListenerThatExpectsOK
: public IPC::Listener
{
26 ListenerThatExpectsOK()
27 : received_ok_(false) {}
29 ~ListenerThatExpectsOK() override
{}
31 bool OnMessageReceived(const IPC::Message
& message
) override
{
32 PickleIterator
iter(message
);
33 std::string should_be_ok
;
34 EXPECT_TRUE(iter
.ReadString(&should_be_ok
));
35 EXPECT_EQ(should_be_ok
, "OK");
37 base::MessageLoop::current()->Quit();
41 void OnChannelError() override
{
42 // The connection should be healthy while the listener is waiting
43 // message. An error can occur after that because the peer
48 static void SendOK(IPC::Sender
* sender
) {
49 IPC::Message
* message
= new IPC::Message(
50 0, 2, IPC::Message::PRIORITY_NORMAL
);
51 message
->WriteString(std::string("OK"));
52 ASSERT_TRUE(sender
->Send(message
));
61 explicit ChannelClient(IPC::Listener
* listener
, const char* name
) {
62 channel_
= IPC::ChannelMojo::Create(NULL
,
63 IPCTestBase::GetChannelName(name
),
64 IPC::Channel::MODE_CLIENT
,
69 CHECK(channel_
->Connect());
72 IPC::ChannelMojo
* channel() const { return channel_
.get(); }
75 base::MessageLoopForIO main_message_loop_
;
76 scoped_ptr
<IPC::ChannelMojo
> channel_
;
79 class IPCChannelMojoTest
: public IPCTestBase
{
81 scoped_ptr
<IPC::ChannelFactory
> CreateChannelFactory(
82 const IPC::ChannelHandle
& handle
,
83 base::TaskRunner
* runner
) override
{
84 host_
.reset(new IPC::ChannelMojoHost(task_runner()));
85 return IPC::ChannelMojo::CreateServerFactory(host_
->channel_delegate(),
89 bool DidStartClient() override
{
90 bool ok
= IPCTestBase::DidStartClient();
92 host_
->OnClientLaunched(client_process().Handle());
97 scoped_ptr
<IPC::ChannelMojoHost
> host_
;
101 class TestChannelListenerWithExtraExpectations
102 : public IPC::TestChannelListener
{
104 TestChannelListenerWithExtraExpectations()
105 : is_connected_called_(false) {
108 void OnChannelConnected(int32 peer_pid
) override
{
109 IPC::TestChannelListener::OnChannelConnected(peer_pid
);
110 EXPECT_TRUE(base::kNullProcessId
!= peer_pid
);
111 is_connected_called_
= true;
114 bool is_connected_called() const { return is_connected_called_
; }
117 bool is_connected_called_
;
120 TEST_F(IPCChannelMojoTest
, ConnectedFromClient
) {
121 Init("IPCChannelMojoTestClient");
123 // Set up IPC channel and start client.
124 TestChannelListenerWithExtraExpectations listener
;
125 CreateChannel(&listener
);
126 listener
.Init(sender());
127 ASSERT_TRUE(ConnectChannel());
128 ASSERT_TRUE(StartClient());
130 IPC::TestChannelListener::SendOneMessage(
131 sender(), "hello from parent");
133 base::MessageLoop::current()->Run();
134 EXPECT_TRUE(base::kNullProcessId
!= this->channel()->GetPeerPID());
136 this->channel()->Close();
138 EXPECT_TRUE(WaitForClientShutdown());
139 EXPECT_TRUE(listener
.is_connected_called());
140 EXPECT_TRUE(listener
.HasSentAll());
145 // A long running process that connects to us
146 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient
) {
147 TestChannelListenerWithExtraExpectations listener
;
148 ChannelClient
client(&listener
, "IPCChannelMojoTestClient");
150 listener
.Init(client
.channel());
152 IPC::TestChannelListener::SendOneMessage(
153 client
.channel(), "hello from child");
154 base::MessageLoop::current()->Run();
155 EXPECT_TRUE(listener
.is_connected_called());
156 EXPECT_TRUE(listener
.HasSentAll());
161 class ListenerExpectingErrors
: public IPC::Listener
{
163 ListenerExpectingErrors()
164 : has_error_(false) {
167 void OnChannelConnected(int32 peer_pid
) override
{
168 base::MessageLoop::current()->Quit();
171 bool OnMessageReceived(const IPC::Message
& message
) override
{ return true; }
173 void OnChannelError() override
{
175 base::MessageLoop::current()->Quit();
178 bool has_error() const { return has_error_
; }
185 class IPCChannelMojoErrorTest
: public IPCTestBase
{
187 scoped_ptr
<IPC::ChannelFactory
> CreateChannelFactory(
188 const IPC::ChannelHandle
& handle
,
189 base::TaskRunner
* runner
) override
{
190 host_
.reset(new IPC::ChannelMojoHost(task_runner()));
191 return IPC::ChannelMojo::CreateServerFactory(host_
->channel_delegate(),
195 bool DidStartClient() override
{
196 bool ok
= IPCTestBase::DidStartClient();
198 host_
->OnClientLaunched(client_process().Handle());
203 scoped_ptr
<IPC::ChannelMojoHost
> host_
;
206 class ListenerThatQuits
: public IPC::Listener
{
208 ListenerThatQuits() {
211 bool OnMessageReceived(const IPC::Message
& message
) override
{
215 void OnChannelConnected(int32 peer_pid
) override
{
216 base::MessageLoop::current()->Quit();
220 // A long running process that connects to us.
221 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient
) {
222 ListenerThatQuits listener
;
223 ChannelClient
client(&listener
, "IPCChannelMojoErraticTestClient");
226 base::MessageLoop::current()->Run();
231 TEST_F(IPCChannelMojoErrorTest
, SendFailWithPendingMessages
) {
232 Init("IPCChannelMojoErraticTestClient");
234 // Set up IPC channel and start client.
235 ListenerExpectingErrors listener
;
236 CreateChannel(&listener
);
237 ASSERT_TRUE(ConnectChannel());
239 // This matches a value in mojo/edk/system/constants.h
240 const int kMaxMessageNumBytes
= 4 * 1024 * 1024;
241 std::string
overly_large_data(kMaxMessageNumBytes
, '*');
242 // This messages are queued as pending.
243 for (size_t i
= 0; i
< 10; ++i
) {
244 IPC::TestChannelListener::SendOneMessage(
245 sender(), overly_large_data
.c_str());
248 ASSERT_TRUE(StartClient());
249 base::MessageLoop::current()->Run();
251 this->channel()->Close();
253 EXPECT_TRUE(WaitForClientShutdown());
254 EXPECT_TRUE(listener
.has_error());
260 class IPCChannelMojoDeadHandleTest
: public IPCTestBase
{
262 virtual scoped_ptr
<IPC::ChannelFactory
> CreateChannelFactory(
263 const IPC::ChannelHandle
& handle
,
264 base::TaskRunner
* runner
) override
{
265 host_
.reset(new IPC::ChannelMojoHost(task_runner()));
266 return IPC::ChannelMojo::CreateServerFactory(host_
->channel_delegate(),
270 virtual bool DidStartClient() override
{
271 IPCTestBase::DidStartClient();
272 const base::ProcessHandle client
= client_process().Handle();
273 // Forces GetFileHandleForProcess() fail. It happens occasionally
274 // in production, so we should exercise it somehow.
275 // TODO(morrita): figure out how to safely test this.
276 // ::CloseHandle(client);
277 host_
->OnClientLaunched(client
);
282 scoped_ptr
<IPC::ChannelMojoHost
> host_
;
285 TEST_F(IPCChannelMojoDeadHandleTest
, InvalidClientHandle
) {
286 // Any client type is fine as it is going to be killed anyway.
287 Init("IPCChannelMojoTestDoNothingClient");
289 // Set up IPC channel and start client.
290 ListenerExpectingErrors listener
;
291 CreateChannel(&listener
);
292 ASSERT_TRUE(ConnectChannel());
294 ASSERT_TRUE(StartClient());
295 base::MessageLoop::current()->Run();
297 this->channel()->Close();
299 // WaitForClientShutdown() fails as client_hanadle() is already
301 EXPECT_FALSE(WaitForClientShutdown());
302 EXPECT_TRUE(listener
.has_error());
307 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestDoNothingClient
) {
308 ListenerThatQuits listener
;
309 ChannelClient
client(&listener
, "IPCChannelMojoTestDoNothingClient");
312 // Quits without running the message loop as this client won't
313 // receive any messages from the server.
319 #if defined(OS_POSIX)
320 class ListenerThatExpectsFile
: public IPC::Listener
{
322 ListenerThatExpectsFile()
325 ~ListenerThatExpectsFile() override
{}
327 bool OnMessageReceived(const IPC::Message
& message
) override
{
328 PickleIterator
iter(message
);
331 EXPECT_TRUE(message
.ReadFile(&iter
, &fd
));
332 base::File
file(fd
.release());
333 std::string
content(GetSendingFileContent().size(), ' ');
334 file
.Read(0, &content
[0], content
.size());
335 EXPECT_EQ(content
, GetSendingFileContent());
336 base::MessageLoop::current()->Quit();
337 ListenerThatExpectsOK::SendOK(sender_
);
341 void OnChannelError() override
{
345 static std::string
GetSendingFileContent() {
349 static base::FilePath
GetSendingFilePath() {
351 bool ok
= PathService::Get(base::DIR_CACHE
, &path
);
353 return path
.Append("ListenerThatExpectsFile.txt");
356 static void WriteAndSendFile(IPC::Sender
* sender
, base::File
& file
) {
357 std::string content
= GetSendingFileContent();
358 file
.WriteAtCurrentPos(content
.data(), content
.size());
360 IPC::Message
* message
= new IPC::Message(
361 0, 2, IPC::Message::PRIORITY_NORMAL
);
362 message
->WriteFile(base::ScopedFD(file
.TakePlatformFile()));
363 ASSERT_TRUE(sender
->Send(message
));
366 void set_sender(IPC::Sender
* sender
) { sender_
= sender
; }
369 IPC::Sender
* sender_
;
373 TEST_F(IPCChannelMojoTest
, SendPlatformHandle
) {
374 Init("IPCChannelMojoTestSendPlatformHandleClient");
376 ListenerThatExpectsOK listener
;
377 CreateChannel(&listener
);
378 ASSERT_TRUE(ConnectChannel());
379 ASSERT_TRUE(StartClient());
381 base::File
file(ListenerThatExpectsFile::GetSendingFilePath(),
382 base::File::FLAG_CREATE_ALWAYS
| base::File::FLAG_WRITE
|
383 base::File::FLAG_READ
);
384 ListenerThatExpectsFile::WriteAndSendFile(channel(), file
);
385 base::MessageLoop::current()->Run();
387 this->channel()->Close();
389 EXPECT_TRUE(WaitForClientShutdown());
393 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient
) {
394 ListenerThatExpectsFile listener
;
395 ChannelClient
client(
396 &listener
, "IPCChannelMojoTestSendPlatformHandleClient");
398 listener
.set_sender(client
.channel());
400 base::MessageLoop::current()->Run();