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"
18 #include "base/file_descriptor_posix.h"
23 class ListenerThatExpectsOK
: public IPC::Listener
{
25 ListenerThatExpectsOK()
26 : received_ok_(false) {}
28 virtual ~ListenerThatExpectsOK() {}
30 virtual bool OnMessageReceived(const IPC::Message
& message
) OVERRIDE
{
31 PickleIterator
iter(message
);
32 std::string should_be_ok
;
33 EXPECT_TRUE(iter
.ReadString(&should_be_ok
));
34 EXPECT_EQ(should_be_ok
, "OK");
36 base::MessageLoop::current()->Quit();
40 virtual void OnChannelError() OVERRIDE
{
41 // The connection should be healthy while the listener is waiting
42 // message. An error can occur after that because the peer
47 static void SendOK(IPC::Sender
* sender
) {
48 IPC::Message
* message
= new IPC::Message(
49 0, 2, IPC::Message::PRIORITY_NORMAL
);
50 message
->WriteString(std::string("OK"));
51 ASSERT_TRUE(sender
->Send(message
));
58 class ListenerThatShouldBeNeverCalled
: public IPC::Listener
{
59 virtual bool OnMessageReceived(const IPC::Message
& message
) OVERRIDE
{
64 virtual void OnChannelError() OVERRIDE
{
68 virtual void OnChannelConnected(int32 peer_pid
) OVERRIDE
{
72 virtual void OnBadMessageReceived(const IPC::Message
& message
) OVERRIDE
{
79 explicit ChannelClient(IPC::Listener
* listener
, const char* name
) {
80 scoped_ptr
<IPC::Channel
> bootstrap(IPC::Channel::CreateClient(
81 IPCTestBase::GetChannelName(name
),
83 channel_
= IPC::ChannelMojo::Create(
84 bootstrap
.Pass(), IPC::Channel::MODE_CLIENT
, listener
,
85 main_message_loop_
.message_loop_proxy());
89 CHECK(channel_
->Connect());
92 IPC::ChannelMojo
* channel() const { return channel_
.get(); }
95 scoped_ptr
<IPC::ChannelMojo
> channel_
;
96 ListenerThatShouldBeNeverCalled never_called_
;
97 base::MessageLoopForIO main_message_loop_
;
100 class IPCChannelMojoTest
: public IPCTestBase
{
102 void CreateMojoChannel(IPC::Listener
* listener
);
105 virtual void SetUp() OVERRIDE
{
106 IPCTestBase::SetUp();
109 ListenerThatShouldBeNeverCalled never_called_
;
113 void IPCChannelMojoTest::CreateMojoChannel(IPC::Listener
* listener
) {
114 CreateChannel(&never_called_
);
115 scoped_ptr
<IPC::Channel
> mojo_channel
= IPC::ChannelMojo::Create(
116 ReleaseChannel(), IPC::Channel::MODE_SERVER
, listener
,
117 io_thread_task_runner()).PassAs
<IPC::Channel
>();
118 SetChannel(mojo_channel
.PassAs
<IPC::Channel
>());
121 class TestChannelListenerWithExtraExpectations
122 : public IPC::TestChannelListener
{
124 TestChannelListenerWithExtraExpectations()
125 : is_connected_called_(false) {
128 virtual void OnChannelConnected(int32 peer_pid
) OVERRIDE
{
129 IPC::TestChannelListener::OnChannelConnected(peer_pid
);
130 EXPECT_TRUE(base::kNullProcessId
!= peer_pid
);
131 is_connected_called_
= true;
134 bool is_connected_called() const { return is_connected_called_
; }
137 bool is_connected_called_
;
140 TEST_F(IPCChannelMojoTest
, ConnectedFromClient
) {
141 Init("IPCChannelMojoTestClient");
143 // Set up IPC channel and start client.
144 TestChannelListenerWithExtraExpectations listener
;
145 CreateMojoChannel(&listener
);
146 listener
.Init(sender());
147 ASSERT_TRUE(ConnectChannel());
148 ASSERT_TRUE(StartClient());
150 IPC::TestChannelListener::SendOneMessage(
151 sender(), "hello from parent");
153 base::MessageLoop::current()->Run();
154 EXPECT_TRUE(base::kNullProcessId
!= this->channel()->GetPeerPID());
156 this->channel()->Close();
158 EXPECT_TRUE(WaitForClientShutdown());
159 EXPECT_TRUE(listener
.is_connected_called());
160 EXPECT_TRUE(listener
.HasSentAll());
165 // A long running process that connects to us
166 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient
) {
167 TestChannelListenerWithExtraExpectations listener
;
168 ChannelClient
client(&listener
, "IPCChannelMojoTestClient");
170 listener
.Init(client
.channel());
172 IPC::TestChannelListener::SendOneMessage(
173 client
.channel(), "hello from child");
174 base::MessageLoop::current()->Run();
175 EXPECT_TRUE(listener
.is_connected_called());
176 EXPECT_TRUE(listener
.HasSentAll());
181 #if defined(OS_POSIX)
182 class ListenerThatExpectsFile
: public IPC::Listener
{
184 ListenerThatExpectsFile()
187 virtual ~ListenerThatExpectsFile() {}
189 virtual bool OnMessageReceived(const IPC::Message
& message
) OVERRIDE
{
190 PickleIterator
iter(message
);
191 base::FileDescriptor desc
;
192 EXPECT_TRUE(message
.ReadFileDescriptor(&iter
, &desc
));
193 std::string
content(GetSendingFileContent().size(), ' ');
194 base::File
file(desc
.fd
);
195 file
.Read(0, &content
[0], content
.size());
196 EXPECT_EQ(content
, GetSendingFileContent());
197 base::MessageLoop::current()->Quit();
198 ListenerThatExpectsOK::SendOK(sender_
);
202 virtual void OnChannelError() OVERRIDE
{
206 static std::string
GetSendingFileContent() {
210 static base::FilePath
GetSendingFilePath() {
212 bool ok
= PathService::Get(base::DIR_CACHE
, &path
);
214 return path
.Append("ListenerThatExpectsFile.txt");
217 static void WriteAndSendFile(IPC::Sender
* sender
, base::File
& file
) {
218 std::string content
= GetSendingFileContent();
219 file
.WriteAtCurrentPos(content
.data(), content
.size());
221 IPC::Message
* message
= new IPC::Message(
222 0, 2, IPC::Message::PRIORITY_NORMAL
);
223 message
->WriteFileDescriptor(
224 base::FileDescriptor(file
.TakePlatformFile(), false));
225 ASSERT_TRUE(sender
->Send(message
));
228 void set_sender(IPC::Sender
* sender
) { sender_
= sender
; }
231 IPC::Sender
* sender_
;
235 TEST_F(IPCChannelMojoTest
, SendPlatformHandle
) {
236 Init("IPCChannelMojoTestSendPlatformHandleClient");
238 ListenerThatExpectsOK listener
;
239 CreateMojoChannel(&listener
);
240 ASSERT_TRUE(ConnectChannel());
241 ASSERT_TRUE(StartClient());
243 base::File
file(ListenerThatExpectsFile::GetSendingFilePath(),
244 base::File::FLAG_CREATE_ALWAYS
| base::File::FLAG_WRITE
|
245 base::File::FLAG_READ
);
246 ListenerThatExpectsFile::WriteAndSendFile(channel(), file
);
247 base::MessageLoop::current()->Run();
249 this->channel()->Close();
251 EXPECT_TRUE(WaitForClientShutdown());
255 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient
) {
256 ListenerThatExpectsFile listener
;
257 ChannelClient
client(
258 &listener
, "IPCChannelMojoTestSendPlatformHandleClient");
260 listener
.set_sender(client
.channel());
262 base::MessageLoop::current()->Run();