blob: 387efad41e55afffaca9fc4d120ae3e7a42756b2 [file] [log] [blame]
[email protected]64860882014-08-04 23:44:171// 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
amistryd4aa70d2016-06-23 07:52:375#include "ipc/ipc_channel_mojo.h"
[email protected]64860882014-08-04 23:44:176
avi246998d82015-12-22 02:39:047#include <stddef.h>
tfarina10a5c062015-09-04 18:47:578#include <stdint.h>
rockot7c6bf952016-07-14 00:34:119
danakj03de39b22016-04-23 04:21:0910#include <memory>
dchenge48600452015-12-28 02:24:5011#include <utility>
tfarina10a5c062015-09-04 18:47:5712
[email protected]64860882014-08-04 23:44:1713#include "base/base_paths.h"
rockot8d890f62016-07-14 16:37:1414#include "base/bind.h"
sammc5c8a6c62017-02-04 01:33:3815#include "base/callback_helpers.h"
Brett Wilsona62d9c02017-09-20 20:53:2016#include "base/containers/queue.h"
[email protected]64860882014-08-04 23:44:1717#include "base/files/file.h"
amistry20e2b1d62016-06-23 06:12:3518#include "base/files/scoped_temp_dir.h"
skyostile687bdff2015-05-12 11:29:2119#include "base/location.h"
rockot8d890f62016-07-14 16:37:1420#include "base/macros.h"
Alexandr Ilind497eee2018-04-19 22:50:5421#include "base/memory/platform_shared_memory_region.h"
Wez831ae412017-08-30 00:29:3622#include "base/memory/shared_memory.h"
Alexandr Ilind497eee2018-04-19 22:50:5423#include "base/memory/shared_memory_mapping.h"
Ken Rockot138153b2018-07-13 23:31:5724#include "base/optional.h"
[email protected]64860882014-08-04 23:44:1725#include "base/path_service.h"
26#include "base/pickle.h"
rockotcbca72f2015-03-03 16:31:0427#include "base/run_loop.h"
skyostile687bdff2015-05-12 11:29:2128#include "base/single_thread_task_runner.h"
rockot7c6bf952016-07-14 00:34:1129#include "base/strings/stringprintf.h"
rockot9abe09b2016-08-02 20:57:3430#include "base/synchronization/waitable_event.h"
Ken Rockot138153b2018-07-13 23:31:5731#include "base/test/bind_test_util.h"
Carlos Caballero05cd1c32019-06-07 16:42:1432#include "base/test/scoped_task_environment.h"
sammc57ed9f982016-03-10 06:28:3533#include "base/test/test_io_thread.h"
Alexandr Ilind497eee2018-04-19 22:50:5434#include "base/test/test_shared_memory_util.h"
morrita0bd20bd2015-02-25 20:11:2735#include "base/test/test_timeouts.h"
[email protected]64860882014-08-04 23:44:1736#include "base/threading/thread.h"
gabf08ccc02016-05-11 18:51:1137#include "base/threading/thread_task_runner_handle.h"
avi246998d82015-12-22 02:39:0438#include "build/build_config.h"
[email protected]64860882014-08-04 23:44:1739#include "ipc/ipc_message.h"
Wez831ae412017-08-30 00:29:3640#include "ipc/ipc_message_utils.h"
amistryd4aa70d2016-06-23 07:52:3741#include "ipc/ipc_mojo_handle_attachment.h"
42#include "ipc/ipc_mojo_message_helper.h"
43#include "ipc/ipc_mojo_param_traits.h"
rockot9abe09b2016-08-02 20:57:3444#include "ipc/ipc_sync_channel.h"
45#include "ipc/ipc_sync_message.h"
rockot7c6bf952016-07-14 00:34:1146#include "ipc/ipc_test.mojom.h"
[email protected]64860882014-08-04 23:44:1747#include "ipc/ipc_test_base.h"
48#include "ipc/ipc_test_channel_listener.h"
Ken Rockot138153b2018-07-13 23:31:5749#include "mojo/core/embedder/embedder.h"
50#include "mojo/public/cpp/bindings/lib/validation_errors.h"
rockota9d566a2017-03-17 19:36:1551#include "mojo/public/cpp/system/wait.h"
sammc57ed9f982016-03-10 06:28:3552#include "testing/gtest/include/gtest/gtest.h"
[email protected]64860882014-08-04 23:44:1753
Fabrice de Gans-Riberi894661c2018-05-24 18:43:2254#if defined(OS_POSIX) || defined(OS_FUCHSIA)
[email protected]64860882014-08-04 23:44:1755#include "base/file_descriptor_posix.h"
morrita1aa788c2015-01-31 05:45:4256#include "ipc/ipc_platform_file_attachment_posix.h"
[email protected]64860882014-08-04 23:44:1757#endif
58
59namespace {
60
rockot7c6bf952016-07-14 00:34:1161void 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
rockot9abe09b2016-08-02 20:57:3467void 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
[email protected]64860882014-08-04 23:44:1773class ListenerThatExpectsOK : public IPC::Listener {
74 public:
Wezfdb98482018-07-12 01:21:3975 explicit ListenerThatExpectsOK(base::OnceClosure quit_closure)
76 : received_ok_(false), quit_closure_(std::move(quit_closure)) {}
[email protected]64860882014-08-04 23:44:1777
Chris Watkins2d879af2017-11-30 02:11:5978 ~ListenerThatExpectsOK() override = default;
[email protected]64860882014-08-04 23:44:1779
dchengfe61fca2014-10-22 02:29:5280 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:2581 base::PickleIterator iter(message);
[email protected]64860882014-08-04 23:44:1782 std::string should_be_ok;
83 EXPECT_TRUE(iter.ReadString(&should_be_ok));
84 EXPECT_EQ(should_be_ok, "OK");
[email protected]e5c27752014-08-08 21:45:1385 received_ok_ = true;
Wezfdb98482018-07-12 01:21:3986 std::move(quit_closure_).Run();
[email protected]64860882014-08-04 23:44:1787 return true;
88 }
89
dchengfe61fca2014-10-22 02:29:5290 void OnChannelError() override {
[email protected]e5c27752014-08-08 21:45:1391 // The connection should be healthy while the listener is waiting
92 // message. An error can occur after that because the peer
93 // process dies.
Wezd95d48042018-02-26 20:50:4794 CHECK(received_ok_);
[email protected]64860882014-08-04 23:44:1795 }
96
rockot7c6bf952016-07-14 00:34:1197 static void SendOK(IPC::Sender* sender) { SendString(sender, "OK"); }
[email protected]e5c27752014-08-08 21:45:1398
99 private:
100 bool received_ok_;
Wezfdb98482018-07-12 01:21:39101 base::OnceClosure quit_closure_;
Wez831ae412017-08-30 00:29:36102};
103
104class TestListenerBase : public IPC::Listener {
105 public:
Wezfdb98482018-07-12 01:21:39106 explicit TestListenerBase(base::OnceClosure quit_closure)
107 : quit_closure_(std::move(quit_closure)) {}
Wez831ae412017-08-30 00:29:36108
Chris Watkins2d879af2017-11-30 02:11:59109 ~TestListenerBase() override = default;
Wezfdb98482018-07-12 01:21:39110 void OnChannelError() override { RunQuitClosure(); }
Wez831ae412017-08-30 00:29:36111
112 void set_sender(IPC::Sender* sender) { sender_ = sender; }
113 IPC::Sender* sender() const { return sender_; }
Ken Rockot138153b2018-07-13 23:31:57114 void RunQuitClosure() {
115 if (quit_closure_)
116 std::move(quit_closure_).Run();
117 }
Wez831ae412017-08-30 00:29:36118
119 private:
120 IPC::Sender* sender_ = nullptr;
Wezfdb98482018-07-12 01:21:39121 base::OnceClosure quit_closure_;
[email protected]64860882014-08-04 23:44:17122};
123
sammc4bcc4ed62016-10-27 10:13:59124using IPCChannelMojoTest = IPCChannelMojoTestBase;
rockotcbca72f2015-03-03 16:31:04125
[email protected]64860882014-08-04 23:44:17126class TestChannelListenerWithExtraExpectations
127 : public IPC::TestChannelListener {
128 public:
sammc57ed9f982016-03-10 06:28:35129 TestChannelListenerWithExtraExpectations() : is_connected_called_(false) {}
[email protected]64860882014-08-04 23:44:17130
tfarina10a5c062015-09-04 18:47:57131 void OnChannelConnected(int32_t peer_pid) override {
[email protected]64860882014-08-04 23:44:17132 IPC::TestChannelListener::OnChannelConnected(peer_pid);
133 EXPECT_TRUE(base::kNullProcessId != peer_pid);
134 is_connected_called_ = true;
135 }
136
137 bool is_connected_called() const { return is_connected_called_; }
138
139 private:
140 bool is_connected_called_;
141};
142
amistry0027a0952016-05-03 00:52:47143TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
sammc4bcc4ed62016-10-27 10:13:59144 Init("IPCChannelMojoTestClient");
[email protected]64860882014-08-04 23:44:17145
146 // Set up IPC channel and start client.
147 TestChannelListenerWithExtraExpectations listener;
morrita373af03b2014-09-09 19:35:24148 CreateChannel(&listener);
[email protected]64860882014-08-04 23:44:17149 listener.Init(sender());
150 ASSERT_TRUE(ConnectChannel());
[email protected]64860882014-08-04 23:44:17151
sammc57ed9f982016-03-10 06:28:35152 IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent");
[email protected]64860882014-08-04 23:44:17153
fdoray8e32586852016-06-22 19:56:16154 base::RunLoop().Run();
[email protected]64860882014-08-04 23:44:17155
sammc57ed9f982016-03-10 06:28:35156 channel()->Close();
[email protected]64860882014-08-04 23:44:17157
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
sammc4bcc4ed62016-10-27 10:13:59166DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestClient) {
[email protected]64860882014-08-04 23:44:17167 TestChannelListenerWithExtraExpectations listener;
sammc57ed9f982016-03-10 06:28:35168 Connect(&listener);
169 listener.Init(channel());
[email protected]64860882014-08-04 23:44:17170
sammc57ed9f982016-03-10 06:28:35171 IPC::TestChannelListener::SendOneMessage(channel(), "hello from child");
fdoray8e32586852016-06-22 19:56:16172 base::RunLoop().Run();
[email protected]64860882014-08-04 23:44:17173 EXPECT_TRUE(listener.is_connected_called());
174 EXPECT_TRUE(listener.HasSentAll());
175
sammc57ed9f982016-03-10 06:28:35176 Close();
[email protected]64860882014-08-04 23:44:17177}
178
Wez831ae412017-08-30 00:29:36179class ListenerExpectingErrors : public TestListenerBase {
morrita0a24cfc92014-09-16 03:20:48180 public:
Wezfdb98482018-07-12 01:21:39181 ListenerExpectingErrors(base::OnceClosure quit_closure)
182 : TestListenerBase(std::move(quit_closure)), has_error_(false) {}
morrita0a24cfc92014-09-16 03:20:48183
dchengfe61fca2014-10-22 02:29:52184 bool OnMessageReceived(const IPC::Message& message) override { return true; }
morrita0a24cfc92014-09-16 03:20:48185
dchengfe61fca2014-10-22 02:29:52186 void OnChannelError() override {
morrita0a24cfc92014-09-16 03:20:48187 has_error_ = true;
Wez831ae412017-08-30 00:29:36188 TestListenerBase::OnChannelError();
morrita0a24cfc92014-09-16 03:20:48189 }
190
191 bool has_error() const { return has_error_; }
192
193 private:
194 bool has_error_;
195};
196
morrita0a24cfc92014-09-16 03:20:48197class ListenerThatQuits : public IPC::Listener {
198 public:
Wezfdb98482018-07-12 01:21:39199 explicit ListenerThatQuits(base::OnceClosure quit_closure)
200 : quit_closure_(std::move(quit_closure)) {}
morrita0a24cfc92014-09-16 03:20:48201
sammc57ed9f982016-03-10 06:28:35202 bool OnMessageReceived(const IPC::Message& message) override { return true; }
morrita0a24cfc92014-09-16 03:20:48203
Wezfdb98482018-07-12 01:21:39204 void OnChannelConnected(int32_t peer_pid) override {
205 std::move(quit_closure_).Run();
206 }
Wez831ae412017-08-30 00:29:36207
208 private:
Wezfdb98482018-07-12 01:21:39209 base::OnceClosure quit_closure_;
morrita0a24cfc92014-09-16 03:20:48210};
211
212// A long running process that connects to us.
sammc4bcc4ed62016-10-27 10:13:59213DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoErraticTestClient) {
Wez831ae412017-08-30 00:29:36214 base::RunLoop run_loop;
215 ListenerThatQuits listener(run_loop.QuitClosure());
sammc57ed9f982016-03-10 06:28:35216 Connect(&listener);
morrita0a24cfc92014-09-16 03:20:48217
Wez831ae412017-08-30 00:29:36218 run_loop.Run();
morrita0a24cfc92014-09-16 03:20:48219
sammc57ed9f982016-03-10 06:28:35220 Close();
morrita0a24cfc92014-09-16 03:20:48221}
222
rockot8c23d462016-07-25 17:33:04223TEST_F(IPCChannelMojoTest, SendFailWithPendingMessages) {
sammc4bcc4ed62016-10-27 10:13:59224 Init("IPCChannelMojoErraticTestClient");
morrita0a24cfc92014-09-16 03:20:48225
226 // Set up IPC channel and start client.
Wez831ae412017-08-30 00:29:36227 base::RunLoop run_loop;
228 ListenerExpectingErrors listener(run_loop.QuitClosure());
morrita0a24cfc92014-09-16 03:20:48229 CreateChannel(&listener);
230 ASSERT_TRUE(ConnectChannel());
231
jamesra03ae492014-10-03 04:26:48232 // This matches a value in mojo/edk/system/constants.h
morritabe6c4cc2014-09-24 23:38:44233 const int kMaxMessageNumBytes = 4 * 1024 * 1024;
234 std::string overly_large_data(kMaxMessageNumBytes, '*');
morrita0a24cfc92014-09-16 03:20:48235 // This messages are queued as pending.
morritabe6c4cc2014-09-24 23:38:44236 for (size_t i = 0; i < 10; ++i) {
sammc57ed9f982016-03-10 06:28:35237 IPC::TestChannelListener::SendOneMessage(sender(),
238 overly_large_data.c_str());
morrita0a24cfc92014-09-16 03:20:48239 }
240
Wez831ae412017-08-30 00:29:36241 run_loop.Run();
morrita0a24cfc92014-09-16 03:20:48242
sammc57ed9f982016-03-10 06:28:35243 channel()->Close();
morrita0a24cfc92014-09-16 03:20:48244
245 EXPECT_TRUE(WaitForClientShutdown());
246 EXPECT_TRUE(listener.has_error());
247
248 DestroyChannel();
249}
250
Ken Rockot138153b2018-07-13 23:31:57251class ListenerThatBindsATestStructPasser : public IPC::Listener,
252 public IPC::mojom::TestStructPasser {
253 public:
254 ListenerThatBindsATestStructPasser() : binding_(this) {}
255
256 bool OnMessageReceived(const IPC::Message& message) override { return true; }
257
258 void OnChannelConnected(int32_t peer_pid) override {}
259
260 void OnChannelError() override { NOTREACHED(); }
261
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:
272 void Pass(IPC::mojom::TestStructPtr) override { NOTREACHED(); }
273
274 mojo::AssociatedBinding<IPC::mojom::TestStructPasser> binding_;
275};
276
277class ListenerThatExpectsNoError : public IPC::Listener {
278 public:
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
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
293 void OnChannelConnected(int32_t peer_pid) override {
294 std::move(connect_closure_).Run();
295 }
296
297 void OnChannelError() override { NOTREACHED(); }
298
299 private:
300 base::OnceClosure connect_closure_;
301 base::OnceClosure quit_closure_;
302};
303
304DEFINE_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
333TEST_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
morrita81b17e02015-02-06 00:58:30365struct TestingMessagePipe {
366 TestingMessagePipe() {
367 EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateMessagePipe(nullptr, &self, &peer));
368 }
369
370 mojo::ScopedMessagePipeHandle self;
371 mojo::ScopedMessagePipeHandle peer;
372};
373
374class HandleSendingHelper {
375 public:
376 static std::string GetSendingFileContent() { return "Hello"; }
377
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));
dchenge48600452015-12-28 02:24:50384 EXPECT_TRUE(IPC::MojoMessageHelper::WriteMessagePipeTo(
385 message, std::move(pipe->peer)));
morrita81b17e02015-02-06 00:58:30386 }
387
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
395 static void ReadReceivedPipe(const IPC::Message& message,
brettwbd4d7112015-06-03 04:29:25396 base::PickleIterator* iter) {
morrita81b17e02015-02-06 00:58:30397 mojo::ScopedMessagePipeHandle pipe;
398 EXPECT_TRUE(
399 IPC::MojoMessageHelper::ReadMessagePipeFrom(&message, iter, &pipe));
Ken Rockotfada7d282017-06-12 21:25:13400 std::vector<uint8_t> content;
morrita81b17e02015-02-06 00:58:30401
sammc57ed9f982016-03-10 06:28:35402 ASSERT_EQ(MOJO_RESULT_OK,
rockota9d566a2017-03-17 19:36:15403 mojo::Wait(pipe.get(), MOJO_HANDLE_SIGNAL_READABLE));
morrita81b17e02015-02-06 00:58:30404 EXPECT_EQ(MOJO_RESULT_OK,
Ken Rockotfada7d282017-06-12 21:25:13405 mojo::ReadMessageRaw(pipe.get(), &content, nullptr, 0));
406 EXPECT_EQ(std::string(content.begin(), content.end()),
407 GetSendingFileContent());
morrita81b17e02015-02-06 00:58:30408 }
409
Fabrice de Gans-Riberi894661c2018-05-24 18:43:22410#if defined(OS_POSIX) || defined(OS_FUCHSIA)
amistry20e2b1d62016-06-23 06:12:35411 static base::FilePath GetSendingFilePath(const base::FilePath& dir_path) {
412 return dir_path.Append("ListenerThatExpectsFile.txt");
morrita81b17e02015-02-06 00:58:30413 }
414
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
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
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
440 static void ReadReceivedFile(const IPC::Message& message,
brettwbd4d7112015-06-03 04:29:25441 base::PickleIterator* iter) {
rockot502c94f2016-02-03 20:20:16442 scoped_refptr<base::Pickle::Attachment> attachment;
morrita81b17e02015-02-06 00:58:30443 EXPECT_TRUE(message.ReadAttachment(iter, &attachment));
sammc6ed3efb2016-11-23 03:17:35444 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());
morrita81b17e02015-02-06 00:58:30450 std::string content(GetSendingFileContent().size(), ' ');
451 file.Read(0, &content[0], content.size());
452 EXPECT_EQ(content, GetSendingFileContent());
453 }
454#endif
455};
456
Wez831ae412017-08-30 00:29:36457class ListenerThatExpectsMessagePipe : public TestListenerBase {
morrita81b17e02015-02-06 00:58:30458 public:
Wezfdb98482018-07-12 01:21:39459 ListenerThatExpectsMessagePipe(base::OnceClosure quit_closure)
460 : TestListenerBase(std::move(quit_closure)) {}
morrita81b17e02015-02-06 00:58:30461
Chris Watkins2d879af2017-11-30 02:11:59462 ~ListenerThatExpectsMessagePipe() override = default;
morrita81b17e02015-02-06 00:58:30463
464 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:25465 base::PickleIterator iter(message);
morrita81b17e02015-02-06 00:58:30466 HandleSendingHelper::ReadReceivedPipe(message, &iter);
Wez831ae412017-08-30 00:29:36467 ListenerThatExpectsOK::SendOK(sender());
morrita81b17e02015-02-06 00:58:30468 return true;
469 }
morrita81b17e02015-02-06 00:58:30470};
471
amistry0027a0952016-05-03 00:52:47472TEST_F(IPCChannelMojoTest, SendMessagePipe) {
sammc4bcc4ed62016-10-27 10:13:59473 Init("IPCChannelMojoTestSendMessagePipeClient");
morrita81b17e02015-02-06 00:58:30474
Wez831ae412017-08-30 00:29:36475 base::RunLoop run_loop;
476 ListenerThatExpectsOK listener(run_loop.QuitClosure());
morrita81b17e02015-02-06 00:58:30477 CreateChannel(&listener);
478 ASSERT_TRUE(ConnectChannel());
morrita81b17e02015-02-06 00:58:30479
480 TestingMessagePipe pipe;
481 HandleSendingHelper::WritePipeThenSend(channel(), &pipe);
482
Wez831ae412017-08-30 00:29:36483 run_loop.Run();
sammc57ed9f982016-03-10 06:28:35484 channel()->Close();
morrita81b17e02015-02-06 00:58:30485
486 EXPECT_TRUE(WaitForClientShutdown());
487 DestroyChannel();
488}
489
sammc4bcc4ed62016-10-27 10:13:59490DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendMessagePipeClient) {
Wez831ae412017-08-30 00:29:36491 base::RunLoop run_loop;
492 ListenerThatExpectsMessagePipe listener(run_loop.QuitClosure());
sammc57ed9f982016-03-10 06:28:35493 Connect(&listener);
494 listener.set_sender(channel());
morrita81b17e02015-02-06 00:58:30495
Wez831ae412017-08-30 00:29:36496 run_loop.Run();
morrita81b17e02015-02-06 00:58:30497
sammc57ed9f982016-03-10 06:28:35498 Close();
morrita81b17e02015-02-06 00:58:30499}
500
morrita438a2ee2015-04-03 05:28:21501void ReadOK(mojo::MessagePipeHandle pipe) {
Ken Rockotfada7d282017-06-12 21:25:13502 std::vector<uint8_t> should_be_ok;
rockota9d566a2017-03-17 19:36:15503 CHECK_EQ(MOJO_RESULT_OK, mojo::Wait(pipe, MOJO_HANDLE_SIGNAL_READABLE));
morrita438a2ee2015-04-03 05:28:21504 CHECK_EQ(MOJO_RESULT_OK,
Ken Rockotfada7d282017-06-12 21:25:13505 mojo::ReadMessageRaw(pipe, &should_be_ok, nullptr, 0));
506 EXPECT_EQ("OK", std::string(should_be_ok.begin(), should_be_ok.end()));
morrita438a2ee2015-04-03 05:28:21507}
508
509void 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
Wez831ae412017-08-30 00:29:36516class ListenerThatExpectsMessagePipeUsingParamTrait : public TestListenerBase {
morrita438a2ee2015-04-03 05:28:21517 public:
Wez831ae412017-08-30 00:29:36518 explicit ListenerThatExpectsMessagePipeUsingParamTrait(
Wezfdb98482018-07-12 01:21:39519 base::OnceClosure quit_closure,
Wez831ae412017-08-30 00:29:36520 bool receiving_valid)
Wezfdb98482018-07-12 01:21:39521 : TestListenerBase(std::move(quit_closure)),
522 receiving_valid_(receiving_valid) {}
morrita438a2ee2015-04-03 05:28:21523
Chris Watkins2d879af2017-11-30 02:11:59524 ~ListenerThatExpectsMessagePipeUsingParamTrait() override = default;
morrita438a2ee2015-04-03 05:28:21525
526 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:25527 base::PickleIterator iter(message);
morrita438a2ee2015-04-03 05:28:21528 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
Wez831ae412017-08-30 00:29:36537 ListenerThatExpectsOK::SendOK(sender());
morrita438a2ee2015-04-03 05:28:21538 return true;
539 }
540
morrita438a2ee2015-04-03 05:28:21541 private:
morrita438a2ee2015-04-03 05:28:21542 bool receiving_valid_;
543};
544
sammc4bcc4ed62016-10-27 10:13:59545class ParamTraitMessagePipeClient : public IpcChannelMojoTestClient {
sammc57ed9f982016-03-10 06:28:35546 public:
547 void RunTest(bool receiving_valid_handle) {
Wez831ae412017-08-30 00:29:36548 base::RunLoop run_loop;
sammc57ed9f982016-03-10 06:28:35549 ListenerThatExpectsMessagePipeUsingParamTrait listener(
Wez831ae412017-08-30 00:29:36550 run_loop.QuitClosure(), receiving_valid_handle);
sammc57ed9f982016-03-10 06:28:35551 Connect(&listener);
552 listener.set_sender(channel());
morrita438a2ee2015-04-03 05:28:21553
Wez831ae412017-08-30 00:29:36554 run_loop.Run();
morrita438a2ee2015-04-03 05:28:21555
sammc57ed9f982016-03-10 06:28:35556 Close();
557 }
558};
morrita438a2ee2015-04-03 05:28:21559
amistry0027a0952016-05-03 00:52:47560TEST_F(IPCChannelMojoTest, ParamTraitValidMessagePipe) {
sammc4bcc4ed62016-10-27 10:13:59561 Init("ParamTraitValidMessagePipeClient");
morrita438a2ee2015-04-03 05:28:21562
Wez831ae412017-08-30 00:29:36563 base::RunLoop run_loop;
564 ListenerThatExpectsOK listener(run_loop.QuitClosure());
morrita438a2ee2015-04-03 05:28:21565 CreateChannel(&listener);
566 ASSERT_TRUE(ConnectChannel());
morrita438a2ee2015-04-03 05:28:21567
568 TestingMessagePipe pipe;
569
danakj03de39b22016-04-23 04:21:09570 std::unique_ptr<IPC::Message> message(new IPC::Message());
morrita438a2ee2015-04-03 05:28:21571 IPC::ParamTraits<mojo::MessagePipeHandle>::Write(message.get(),
572 pipe.peer.release());
573 WriteOK(pipe.self.get());
574
sammc57ed9f982016-03-10 06:28:35575 channel()->Send(message.release());
Wez831ae412017-08-30 00:29:36576 run_loop.Run();
sammc57ed9f982016-03-10 06:28:35577 channel()->Close();
morrita438a2ee2015-04-03 05:28:21578
579 EXPECT_TRUE(WaitForClientShutdown());
580 DestroyChannel();
581}
582
sammc4bcc4ed62016-10-27 10:13:59583DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
584 ParamTraitValidMessagePipeClient,
585 ParamTraitMessagePipeClient) {
sammc57ed9f982016-03-10 06:28:35586 RunTest(true);
morrita438a2ee2015-04-03 05:28:21587}
588
amistry0027a0952016-05-03 00:52:47589TEST_F(IPCChannelMojoTest, ParamTraitInvalidMessagePipe) {
sammc4bcc4ed62016-10-27 10:13:59590 Init("ParamTraitInvalidMessagePipeClient");
morrita438a2ee2015-04-03 05:28:21591
Wez831ae412017-08-30 00:29:36592 base::RunLoop run_loop;
593 ListenerThatExpectsOK listener(run_loop.QuitClosure());
morrita438a2ee2015-04-03 05:28:21594 CreateChannel(&listener);
595 ASSERT_TRUE(ConnectChannel());
morrita438a2ee2015-04-03 05:28:21596
597 mojo::MessagePipeHandle invalid_handle;
danakj03de39b22016-04-23 04:21:09598 std::unique_ptr<IPC::Message> message(new IPC::Message());
morrita438a2ee2015-04-03 05:28:21599 IPC::ParamTraits<mojo::MessagePipeHandle>::Write(message.get(),
600 invalid_handle);
601
sammc57ed9f982016-03-10 06:28:35602 channel()->Send(message.release());
Wez831ae412017-08-30 00:29:36603 run_loop.Run();
sammc57ed9f982016-03-10 06:28:35604 channel()->Close();
morrita438a2ee2015-04-03 05:28:21605
606 EXPECT_TRUE(WaitForClientShutdown());
607 DestroyChannel();
608}
609
sammc4bcc4ed62016-10-27 10:13:59610DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
611 ParamTraitInvalidMessagePipeClient,
612 ParamTraitMessagePipeClient) {
sammc57ed9f982016-03-10 06:28:35613 RunTest(false);
morrita438a2ee2015-04-03 05:28:21614}
615
amistry0027a0952016-05-03 00:52:47616TEST_F(IPCChannelMojoTest, SendFailAfterClose) {
sammc4bcc4ed62016-10-27 10:13:59617 Init("IPCChannelMojoTestSendOkClient");
morrita17137e62015-06-23 22:29:36618
Wez831ae412017-08-30 00:29:36619 base::RunLoop run_loop;
620 ListenerThatExpectsOK listener(run_loop.QuitClosure());
morrita17137e62015-06-23 22:29:36621 CreateChannel(&listener);
622 ASSERT_TRUE(ConnectChannel());
morrita17137e62015-06-23 22:29:36623
Wez831ae412017-08-30 00:29:36624 run_loop.Run();
sammc57ed9f982016-03-10 06:28:35625 channel()->Close();
626 ASSERT_FALSE(channel()->Send(new IPC::Message()));
morrita17137e62015-06-23 22:29:36627
628 EXPECT_TRUE(WaitForClientShutdown());
629 DestroyChannel();
630}
631
Wez831ae412017-08-30 00:29:36632class ListenerSendingOneOk : public TestListenerBase {
morrita17137e62015-06-23 22:29:36633 public:
Wezfdb98482018-07-12 01:21:39634 ListenerSendingOneOk(base::OnceClosure quit_closure)
635 : TestListenerBase(std::move(quit_closure)) {}
morrita17137e62015-06-23 22:29:36636
sammc57ed9f982016-03-10 06:28:35637 bool OnMessageReceived(const IPC::Message& message) override { return true; }
morrita17137e62015-06-23 22:29:36638
tfarina10a5c062015-09-04 18:47:57639 void OnChannelConnected(int32_t peer_pid) override {
Wez831ae412017-08-30 00:29:36640 ListenerThatExpectsOK::SendOK(sender());
Wezfdb98482018-07-12 01:21:39641 RunQuitClosure();
morrita17137e62015-06-23 22:29:36642 }
morrita17137e62015-06-23 22:29:36643};
644
sammc4bcc4ed62016-10-27 10:13:59645DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendOkClient) {
Wez831ae412017-08-30 00:29:36646 base::RunLoop run_loop;
647 ListenerSendingOneOk listener(run_loop.QuitClosure());
sammc57ed9f982016-03-10 06:28:35648 Connect(&listener);
649 listener.set_sender(channel());
morrita17137e62015-06-23 22:29:36650
Wez831ae412017-08-30 00:29:36651 run_loop.Run();
morrita17137e62015-06-23 22:29:36652
sammc57ed9f982016-03-10 06:28:35653 Close();
morrita17137e62015-06-23 22:29:36654}
655
rockot7c6bf952016-07-14 00:34:11656class ListenerWithSimpleAssociatedInterface
657 : public IPC::Listener,
658 public IPC::mojom::SimpleTestDriver {
659 public:
660 static const int kNumMessages;
661
Wezfdb98482018-07-12 01:21:39662 explicit ListenerWithSimpleAssociatedInterface(base::OnceClosure quit_closure)
663 : quit_closure_(std::move(quit_closure)), binding_(this) {}
rockot7c6bf952016-07-14 00:34:11664
Chris Watkins2d879af2017-11-30 02:11:59665 ~ListenerWithSimpleAssociatedInterface() override = default;
rockot7c6bf952016-07-14 00:34:11666
667 bool OnMessageReceived(const IPC::Message& message) override {
668 base::PickleIterator iter(message);
rockot9abe09b2016-08-02 20:57:34669 int32_t should_be_expected;
670 EXPECT_TRUE(iter.ReadInt(&should_be_expected));
671 EXPECT_EQ(should_be_expected, next_expected_value_);
rockot7c6bf952016-07-14 00:34:11672 num_messages_received_++;
673 return true;
674 }
675
Wezfdb98482018-07-12 01:21:39676 void OnChannelError() override { CHECK(!quit_closure_); }
rockot7c6bf952016-07-14 00:34:11677
678 void RegisterInterfaceFactory(IPC::Channel* channel) {
679 channel->GetAssociatedInterfaceSupport()->AddAssociatedInterface(
Wezfdb98482018-07-12 01:21:39680 base::BindRepeating(&ListenerWithSimpleAssociatedInterface::BindRequest,
681 base::Unretained(this)));
rockot7c6bf952016-07-14 00:34:11682 }
683
684 private:
685 // IPC::mojom::SimpleTestDriver:
rockot9abe09b2016-08-02 20:57:34686 void ExpectValue(int32_t value) override {
687 next_expected_value_ = value;
688 }
689
tzikdd76ce712017-06-08 05:27:04690 void GetExpectedValue(GetExpectedValueCallback callback) override {
rockot9abe09b2016-08-02 20:57:34691 NOTREACHED();
692 }
693
tzikdd76ce712017-06-08 05:27:04694 void RequestValue(RequestValueCallback callback) override { NOTREACHED(); }
rockot7c6bf952016-07-14 00:34:11695
tzikdd76ce712017-06-08 05:27:04696 void RequestQuit(RequestQuitCallback callback) override {
rockot7c6bf952016-07-14 00:34:11697 EXPECT_EQ(kNumMessages, num_messages_received_);
tzikdd76ce712017-06-08 05:27:04698 std::move(callback).Run();
Wezfdb98482018-07-12 01:21:39699 std::move(quit_closure_).Run();
rockot7c6bf952016-07-14 00:34:11700 }
701
702 void BindRequest(IPC::mojom::SimpleTestDriverAssociatedRequest request) {
703 DCHECK(!binding_.is_bound());
704 binding_.Bind(std::move(request));
705 }
706
rockot9abe09b2016-08-02 20:57:34707 int32_t next_expected_value_ = 0;
rockot7c6bf952016-07-14 00:34:11708 int num_messages_received_ = 0;
Wezfdb98482018-07-12 01:21:39709 base::OnceClosure quit_closure_;
rockot7c6bf952016-07-14 00:34:11710
711 mojo::AssociatedBinding<IPC::mojom::SimpleTestDriver> binding_;
712};
713
714const int ListenerWithSimpleAssociatedInterface::kNumMessages = 1000;
715
716class ListenerSendingAssociatedMessages : public IPC::Listener {
717 public:
Wezfdb98482018-07-12 01:21:39718 explicit ListenerSendingAssociatedMessages(base::OnceClosure quit_closure)
719 : quit_closure_(std::move(quit_closure)) {}
rockot7c6bf952016-07-14 00:34:11720
721 bool OnMessageReceived(const IPC::Message& message) override { return true; }
722
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) {
rockot9abe09b2016-08-02 20:57:34732 driver_->ExpectValue(i);
733 SendValue(channel_, i);
rockot7c6bf952016-07-14 00:34:11734 }
Wezfdb98482018-07-12 01:21:39735 driver_->RequestQuit(base::BindOnce(
736 &ListenerSendingAssociatedMessages::OnQuitAck, base::Unretained(this)));
rockot7c6bf952016-07-14 00:34:11737 }
738
739 void set_channel(IPC::Channel* channel) { channel_ = channel; }
740
741 private:
Wezfdb98482018-07-12 01:21:39742 void OnQuitAck() { std::move(quit_closure_).Run(); }
rockot7c6bf952016-07-14 00:34:11743
744 IPC::Channel* channel_ = nullptr;
745 IPC::mojom::SimpleTestDriverAssociatedPtr driver_;
Wezfdb98482018-07-12 01:21:39746 base::OnceClosure quit_closure_;
rockot7c6bf952016-07-14 00:34:11747};
748
749TEST_F(IPCChannelMojoTest, SimpleAssociatedInterface) {
sammc4bcc4ed62016-10-27 10:13:59750 Init("SimpleAssociatedInterfaceClient");
rockot7c6bf952016-07-14 00:34:11751
Wezfdb98482018-07-12 01:21:39752 base::RunLoop run_loop;
753 ListenerWithSimpleAssociatedInterface listener(run_loop.QuitClosure());
rockot7c6bf952016-07-14 00:34:11754 CreateChannel(&listener);
755 ASSERT_TRUE(ConnectChannel());
756
757 listener.RegisterInterfaceFactory(channel());
758
Wezfdb98482018-07-12 01:21:39759 run_loop.Run();
rockot7c6bf952016-07-14 00:34:11760 channel()->Close();
761
762 EXPECT_TRUE(WaitForClientShutdown());
763 DestroyChannel();
764}
765
sammc4bcc4ed62016-10-27 10:13:59766DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(SimpleAssociatedInterfaceClient) {
Wezfdb98482018-07-12 01:21:39767 base::RunLoop run_loop;
768 ListenerSendingAssociatedMessages listener(run_loop.QuitClosure());
rockot7c6bf952016-07-14 00:34:11769 Connect(&listener);
770 listener.set_channel(channel());
771
Wezfdb98482018-07-12 01:21:39772 run_loop.Run();
rockot7c6bf952016-07-14 00:34:11773
774 Close();
775}
776
rockot8d890f62016-07-14 16:37:14777class ChannelProxyRunner {
778 public:
rockota34707ca2016-07-20 04:28:32779 ChannelProxyRunner(mojo::ScopedMessagePipeHandle handle,
780 bool for_server)
781 : for_server_(for_server),
782 handle_(std::move(handle)),
rockot9abe09b2016-08-02 20:57:34783 io_thread_("ChannelProxyRunner IO thread"),
784 never_signaled_(base::WaitableEvent::ResetPolicy::MANUAL,
785 base::WaitableEvent::InitialState::NOT_SIGNALED) {
rockot8d890f62016-07-14 16:37:14786 }
787
788 void CreateProxy(IPC::Listener* listener) {
789 io_thread_.StartWithOptions(
790 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
Hajime Hoshiff15e972017-11-09 06:37:09791 proxy_ = IPC::SyncChannel::Create(listener, io_thread_.task_runner(),
792 base::ThreadTaskRunnerHandle::Get(),
793 &never_signaled_);
rockot8d890f62016-07-14 16:37:14794 }
rockota34707ca2016-07-20 04:28:32795
rockot10188752016-09-08 18:24:56796 void RunProxy() {
rockota34707ca2016-07-20 04:28:32797 std::unique_ptr<IPC::ChannelFactory> factory;
798 if (for_server_) {
799 factory = IPC::ChannelMojo::CreateServerFactory(
Hajime Hoshia98f1102017-11-20 06:34:35800 std::move(handle_), io_thread_.task_runner(),
801 base::ThreadTaskRunnerHandle::Get());
rockota34707ca2016-07-20 04:28:32802 } else {
803 factory = IPC::ChannelMojo::CreateClientFactory(
Hajime Hoshia98f1102017-11-20 06:34:35804 std::move(handle_), io_thread_.task_runner(),
805 base::ThreadTaskRunnerHandle::Get());
rockota34707ca2016-07-20 04:28:32806 }
rockot10188752016-09-08 18:24:56807 proxy_->Init(std::move(factory), true);
rockota34707ca2016-07-20 04:28:32808 }
rockot8d890f62016-07-14 16:37:14809
810 IPC::ChannelProxy* proxy() { return proxy_.get(); }
811
812 private:
rockota34707ca2016-07-20 04:28:32813 const bool for_server_;
rockot8d890f62016-07-14 16:37:14814
rockota34707ca2016-07-20 04:28:32815 mojo::ScopedMessagePipeHandle handle_;
rockot8d890f62016-07-14 16:37:14816 base::Thread io_thread_;
rockot9abe09b2016-08-02 20:57:34817 base::WaitableEvent never_signaled_;
rockotb62e2e32017-03-24 18:36:44818 std::unique_ptr<IPC::ChannelProxy> proxy_;
rockot8d890f62016-07-14 16:37:14819
820 DISALLOW_COPY_AND_ASSIGN(ChannelProxyRunner);
821};
822
823class IPCChannelProxyMojoTest : public IPCChannelMojoTestBase {
824 public:
sammc4bcc4ed62016-10-27 10:13:59825 void Init(const std::string& client_name) {
826 IPCChannelMojoTestBase::Init(client_name);
rockota34707ca2016-07-20 04:28:32827 runner_.reset(new ChannelProxyRunner(TakeHandle(), true));
rockot8d890f62016-07-14 16:37:14828 }
829 void CreateProxy(IPC::Listener* listener) { runner_->CreateProxy(listener); }
rockot10188752016-09-08 18:24:56830 void RunProxy() {
831 runner_->RunProxy();
rockot401fb2c2016-09-06 18:35:57832 }
rockot0e4de5f2016-07-22 21:18:07833 void DestroyProxy() {
834 runner_.reset();
835 base::RunLoop().RunUntilIdle();
836 }
rockot8d890f62016-07-14 16:37:14837
838 IPC::ChannelProxy* proxy() { return runner_->proxy(); }
839
840 private:
rockot8d890f62016-07-14 16:37:14841 std::unique_ptr<ChannelProxyRunner> runner_;
842};
843
844class ListenerWithSimpleProxyAssociatedInterface
845 : public IPC::Listener,
846 public IPC::mojom::SimpleTestDriver {
847 public:
848 static const int kNumMessages;
849
Wezfdb98482018-07-12 01:21:39850 explicit ListenerWithSimpleProxyAssociatedInterface(
851 base::OnceClosure quit_closure)
852 : quit_closure_(std::move(quit_closure)), binding_(this) {}
rockot8d890f62016-07-14 16:37:14853
Chris Watkins2d879af2017-11-30 02:11:59854 ~ListenerWithSimpleProxyAssociatedInterface() override = default;
rockot8d890f62016-07-14 16:37:14855
856 bool OnMessageReceived(const IPC::Message& message) override {
857 base::PickleIterator iter(message);
rockot9abe09b2016-08-02 20:57:34858 int32_t should_be_expected;
859 EXPECT_TRUE(iter.ReadInt(&should_be_expected));
860 EXPECT_EQ(should_be_expected, next_expected_value_);
rockot8d890f62016-07-14 16:37:14861 num_messages_received_++;
862 return true;
863 }
864
Wezfdb98482018-07-12 01:21:39865 void OnChannelError() override { CHECK(!quit_closure_); }
rockot8d890f62016-07-14 16:37:14866
rockotf62002a2016-09-15 00:08:59867 void OnAssociatedInterfaceRequest(
868 const std::string& interface_name,
869 mojo::ScopedInterfaceEndpointHandle handle) override {
870 DCHECK_EQ(interface_name, IPC::mojom::SimpleTestDriver::Name_);
Ken Rockot96d1b7b52017-05-13 00:29:21871 binding_.Bind(
872 IPC::mojom::SimpleTestDriverAssociatedRequest(std::move(handle)));
rockot8d890f62016-07-14 16:37:14873 }
874
875 bool received_all_messages() const {
Wezfdb98482018-07-12 01:21:39876 return num_messages_received_ == kNumMessages && !quit_closure_;
rockot8d890f62016-07-14 16:37:14877 }
878
879 private:
880 // IPC::mojom::SimpleTestDriver:
rockot9abe09b2016-08-02 20:57:34881 void ExpectValue(int32_t value) override {
882 next_expected_value_ = value;
883 }
884
tzikdd76ce712017-06-08 05:27:04885 void GetExpectedValue(GetExpectedValueCallback callback) override {
886 std::move(callback).Run(next_expected_value_);
rockot9abe09b2016-08-02 20:57:34887 }
888
tzikdd76ce712017-06-08 05:27:04889 void RequestValue(RequestValueCallback callback) override { NOTREACHED(); }
rockot8d890f62016-07-14 16:37:14890
tzikdd76ce712017-06-08 05:27:04891 void RequestQuit(RequestQuitCallback callback) override {
tzikdd76ce712017-06-08 05:27:04892 std::move(callback).Run();
rockot0e4de5f2016-07-22 21:18:07893 binding_.Close();
Wezfdb98482018-07-12 01:21:39894 std::move(quit_closure_).Run();
rockot8d890f62016-07-14 16:37:14895 }
896
897 void BindRequest(IPC::mojom::SimpleTestDriverAssociatedRequest request) {
898 DCHECK(!binding_.is_bound());
899 binding_.Bind(std::move(request));
900 }
901
rockot9abe09b2016-08-02 20:57:34902 int32_t next_expected_value_ = 0;
rockot8d890f62016-07-14 16:37:14903 int num_messages_received_ = 0;
Wezfdb98482018-07-12 01:21:39904 base::OnceClosure quit_closure_;
rockot8d890f62016-07-14 16:37:14905
906 mojo::AssociatedBinding<IPC::mojom::SimpleTestDriver> binding_;
907};
908
909const int ListenerWithSimpleProxyAssociatedInterface::kNumMessages = 1000;
910
911TEST_F(IPCChannelProxyMojoTest, ProxyThreadAssociatedInterface) {
sammc4bcc4ed62016-10-27 10:13:59912 Init("ProxyThreadAssociatedInterfaceClient");
rockot8d890f62016-07-14 16:37:14913
Wezfdb98482018-07-12 01:21:39914 base::RunLoop run_loop;
915 ListenerWithSimpleProxyAssociatedInterface listener(run_loop.QuitClosure());
rockot8d890f62016-07-14 16:37:14916 CreateProxy(&listener);
rockot8d890f62016-07-14 16:37:14917 RunProxy();
918
Wezfdb98482018-07-12 01:21:39919 run_loop.Run();
rockot8d890f62016-07-14 16:37:14920
921 EXPECT_TRUE(WaitForClientShutdown());
922 EXPECT_TRUE(listener.received_all_messages());
923
rockot0e4de5f2016-07-22 21:18:07924 DestroyProxy();
rockot8d890f62016-07-14 16:37:14925}
926
927class ChannelProxyClient {
928 public:
929 void Init(mojo::ScopedMessagePipeHandle handle) {
rockota34707ca2016-07-20 04:28:32930 runner_.reset(new ChannelProxyRunner(std::move(handle), false));
rockot8d890f62016-07-14 16:37:14931 }
rockot9abe09b2016-08-02 20:57:34932
rockot8d890f62016-07-14 16:37:14933 void CreateProxy(IPC::Listener* listener) { runner_->CreateProxy(listener); }
rockot9abe09b2016-08-02 20:57:34934
rockot10188752016-09-08 18:24:56935 void RunProxy() { runner_->RunProxy(); }
rockot9abe09b2016-08-02 20:57:34936
rockot0e4de5f2016-07-22 21:18:07937 void DestroyProxy() {
938 runner_.reset();
939 base::RunLoop().RunUntilIdle();
940 }
rockot8d890f62016-07-14 16:37:14941
rockot9abe09b2016-08-02 20:57:34942 void RequestQuitAndWaitForAck(IPC::mojom::SimpleTestDriver* driver) {
943 base::RunLoop loop;
944 driver->RequestQuit(loop.QuitClosure());
945 loop.Run();
946 }
947
rockot8d890f62016-07-14 16:37:14948 IPC::ChannelProxy* proxy() { return runner_->proxy(); }
949
950 private:
Carlos Caballero05cd1c32019-06-07 16:42:14951 base::test::ScopedTaskEnvironment scoped_task_environment_;
rockot8d890f62016-07-14 16:37:14952 std::unique_ptr<ChannelProxyRunner> runner_;
953};
954
rockot0e4de5f2016-07-22 21:18:07955class DummyListener : public IPC::Listener {
rockot8d890f62016-07-14 16:37:14956 public:
rockot8d890f62016-07-14 16:37:14957 // IPC::Listener
958 bool OnMessageReceived(const IPC::Message& message) override { return true; }
rockot8d890f62016-07-14 16:37:14959};
960
sammc4bcc4ed62016-10-27 10:13:59961DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
962 ProxyThreadAssociatedInterfaceClient,
963 ChannelProxyClient) {
rockot0e4de5f2016-07-22 21:18:07964 DummyListener listener;
rockot8d890f62016-07-14 16:37:14965 CreateProxy(&listener);
966 RunProxy();
rockot8d890f62016-07-14 16:37:14967
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) {
rockot9abe09b2016-08-02 20:57:34974 driver->ExpectValue(i);
975 SendValue(proxy(), i);
rockot8d890f62016-07-14 16:37:14976 }
Wezfdb98482018-07-12 01:21:39977 base::RunLoop run_loop;
978 driver->RequestQuit(run_loop.QuitClosure());
979 run_loop.Run();
rockot0e4de5f2016-07-22 21:18:07980
981 DestroyProxy();
rockot8d890f62016-07-14 16:37:14982}
983
rockot401fb2c2016-09-06 18:35:57984class ListenerWithIndirectProxyAssociatedInterface
985 : public IPC::Listener,
986 public IPC::mojom::IndirectTestDriver,
987 public IPC::mojom::PingReceiver {
988 public:
989 ListenerWithIndirectProxyAssociatedInterface()
990 : driver_binding_(this), ping_receiver_binding_(this) {}
Chris Watkins2d879af2017-11-30 02:11:59991 ~ListenerWithIndirectProxyAssociatedInterface() override = default;
rockot401fb2c2016-09-06 18:35:57992
rockot70bbb59492017-01-25 00:56:51993 // IPC::Listener:
rockot401fb2c2016-09-06 18:35:57994 bool OnMessageReceived(const IPC::Message& message) override { return true; }
995
rockot70bbb59492017-01-25 00:56:51996 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_);
Ken Rockot96d1b7b52017-05-13 00:29:211001 driver_binding_.Bind(
1002 IPC::mojom::IndirectTestDriverAssociatedRequest(std::move(handle)));
rockot401fb2c2016-09-06 18:35:571003 }
1004
Wezfdb98482018-07-12 01:21:391005 void set_ping_handler(const base::RepeatingClosure& handler) {
rockot401fb2c2016-09-06 18:35:571006 ping_handler_ = handler;
1007 }
1008
1009 private:
1010 // IPC::mojom::IndirectTestDriver:
1011 void GetPingReceiver(
1012 IPC::mojom::PingReceiverAssociatedRequest request) override {
1013 ping_receiver_binding_.Bind(std::move(request));
1014 }
1015
1016 // IPC::mojom::PingReceiver:
tzikdd76ce712017-06-08 05:27:041017 void Ping(PingCallback callback) override {
1018 std::move(callback).Run();
rockot401fb2c2016-09-06 18:35:571019 ping_handler_.Run();
1020 }
1021
rockot401fb2c2016-09-06 18:35:571022 mojo::AssociatedBinding<IPC::mojom::IndirectTestDriver> driver_binding_;
1023 mojo::AssociatedBinding<IPC::mojom::PingReceiver> ping_receiver_binding_;
1024
Wezfdb98482018-07-12 01:21:391025 base::RepeatingClosure ping_handler_;
rockot401fb2c2016-09-06 18:35:571026};
1027
1028TEST_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
sammc4bcc4ed62016-10-27 10:13:591033 Init("ProxyThreadAssociatedInterfaceIndirectClient");
rockot401fb2c2016-09-06 18:35:571034
1035 ListenerWithIndirectProxyAssociatedInterface listener;
1036 CreateProxy(&listener);
rockot401fb2c2016-09-06 18:35:571037 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
sammc4bcc4ed62016-10-27 10:13:591048DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
rockot401fb2c2016-09-06 18:35:571049 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);
yzshen1aa8e56c2017-02-16 23:15:451063 driver->GetPingReceiver(mojo::MakeRequest(&ping_receiver));
rockot401fb2c2016-09-06 18:35:571064
1065 base::RunLoop loop;
1066 ping_receiver->Ping(loop.QuitClosure());
1067 loop.Run();
1068
1069 DestroyProxy();
1070}
1071
rockot9abe09b2016-08-02 20:57:341072class ListenerWithSyncAssociatedInterface
1073 : public IPC::Listener,
1074 public IPC::mojom::SimpleTestDriver {
1075 public:
1076 ListenerWithSyncAssociatedInterface() : binding_(this) {}
Chris Watkins2d879af2017-11-30 02:11:591077 ~ListenerWithSyncAssociatedInterface() override = default;
rockot9abe09b2016-08-02 20:57:341078
1079 void set_sync_sender(IPC::Sender* sync_sender) { sync_sender_ = sync_sender; }
1080
rockot9abe09b2016-08-02 20:57:341081 void RunUntilQuitRequested() {
1082 base::RunLoop loop;
1083 quit_closure_ = loop.QuitClosure();
1084 loop.Run();
1085 }
1086
1087 void CloseBinding() { binding_.Close(); }
1088
1089 void set_response_value(int32_t response) {
1090 response_value_ = response;
1091 }
1092
1093 private:
1094 // IPC::mojom::SimpleTestDriver:
1095 void ExpectValue(int32_t value) override {
1096 next_expected_value_ = value;
1097 }
1098
tzikdd76ce712017-06-08 05:27:041099 void GetExpectedValue(GetExpectedValueCallback callback) override {
1100 std::move(callback).Run(next_expected_value_);
rockot9abe09b2016-08-02 20:57:341101 }
1102
tzikdd76ce712017-06-08 05:27:041103 void RequestValue(RequestValueCallback callback) override {
1104 std::move(callback).Run(response_value_);
rockot9abe09b2016-08-02 20:57:341105 }
1106
tzikdd76ce712017-06-08 05:27:041107 void RequestQuit(RequestQuitCallback callback) override {
Wezfdb98482018-07-12 01:21:391108 std::move(quit_closure_).Run();
tzikdd76ce712017-06-08 05:27:041109 std::move(callback).Run();
rockot9abe09b2016-08-02 20:57:341110 }
1111
1112 // IPC::Listener:
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
rockot70bbb59492017-01-25 00:56:511125 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_);
Ken Rockot96d1b7b52017-05-13 00:29:211130 binding_.Bind(
1131 IPC::mojom::SimpleTestDriverAssociatedRequest(std::move(handle)));
rockot70bbb59492017-01-25 00:56:511132 }
1133
rockot9abe09b2016-08-02 20:57:341134 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;
Wezfdb98482018-07-12 01:21:391142 base::OnceClosure quit_closure_;
rockot9abe09b2016-08-02 20:57:341143
1144 mojo::AssociatedBinding<IPC::mojom::SimpleTestDriver> binding_;
1145};
1146
1147class SyncReplyReader : public IPC::MessageReplyDeserializer {
1148 public:
1149 explicit SyncReplyReader(int32_t* storage) : storage_(storage) {}
Chris Watkins2d879af2017-11-30 02:11:591150 ~SyncReplyReader() override = default;
rockot9abe09b2016-08-02 20:57:341151
1152 private:
1153 // IPC::MessageReplyDeserializer:
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
1166TEST_F(IPCChannelProxyMojoTest, SyncAssociatedInterface) {
sammc4bcc4ed62016-10-27 10:13:591167 Init("SyncAssociatedInterface");
rockot9abe09b2016-08-02 20:57:341168
1169 ListenerWithSyncAssociatedInterface listener;
1170 CreateProxy(&listener);
1171 listener.set_sync_sender(proxy());
rockot9abe09b2016-08-02 20:57:341172 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
1207class SimpleTestClientImpl : public IPC::mojom::SimpleTestClient,
1208 public IPC::Listener {
1209 public:
1210 SimpleTestClientImpl() : binding_(this) {}
1211
1212 void set_driver(IPC::mojom::SimpleTestDriver* driver) { driver_ = driver; }
1213 void set_sync_sender(IPC::Sender* sync_sender) { sync_sender_ = sync_sender; }
1214
rockot9abe09b2016-08-02 20:57:341215 void WaitForValueRequest() {
1216 run_loop_.reset(new base::RunLoop);
1217 run_loop_->Run();
1218 }
1219
1220 void UseSyncSenderForRequest(bool use_sync_sender) {
1221 use_sync_sender_ = use_sync_sender;
1222 }
1223
1224 private:
1225 // IPC::mojom::SimpleTestClient:
tzikdd76ce712017-06-08 05:27:041226 void RequestValue(RequestValueCallback callback) override {
rockot9abe09b2016-08-02 20:57:341227 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
tzikdd76ce712017-06-08 05:27:041237 std::move(callback).Run(response);
rockot9abe09b2016-08-02 20:57:341238
1239 DCHECK(run_loop_);
1240 run_loop_->Quit();
1241 }
1242
1243 // IPC::Listener:
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
rockot70bbb59492017-01-25 00:56:511258 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
Ken Rockot96d1b7b52017-05-13 00:29:211264 binding_.Bind(
1265 IPC::mojom::SimpleTestClientAssociatedRequest(std::move(handle)));
rockot70bbb59492017-01-25 00:56:511266 }
1267
rockot9abe09b2016-08-02 20:57:341268 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
sammc4bcc4ed62016-10-27 10:13:591277DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(SyncAssociatedInterface,
1278 ChannelProxyClient) {
rockot9abe09b2016-08-02 20:57:341279 SimpleTestClientImpl client_impl;
1280 CreateProxy(&client_impl);
1281 client_impl.set_sync_sender(proxy());
rockot9abe09b2016-08-02 20:57:341282 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
rockot10188752016-09-08 18:24:561313TEST_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:
rockot401fb2c2016-09-06 18:35:571317 //
1318 // Connect()
1319 // Send(A)
rockot10188752016-09-08 18:24:561320 // Pause()
rockot401fb2c2016-09-06 18:35:571321 // Send(B)
rockot401fb2c2016-09-06 18:35:571322 // Send(C)
rockot10188752016-09-08 18:24:561323 // Unpause(false)
1324 // Send(D)
1325 // Send(E)
rockot401fb2c2016-09-06 18:35:571326 // Flush()
1327 //
rockot10188752016-09-08 18:24:561328 // must result in the other end receiving messages A, D, E, B, D; in that
rockot401fb2c2016-09-06 18:35:571329 // 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.
sammc4bcc4ed62016-10-27 10:13:591335 Init("CreatePausedClient");
rockot401fb2c2016-09-06 18:35:571336
1337 DummyListener listener;
1338 CreateProxy(&listener);
rockot10188752016-09-08 18:24:561339 RunProxy();
1340
1341 // This message must be sent immediately since the channel is unpaused.
1342 SendValue(proxy(), 1);
1343
1344 proxy()->Pause();
rockot401fb2c2016-09-06 18:35:571345
1346 // These messages must be queued internally since the channel is paused.
rockot401fb2c2016-09-06 18:35:571347 SendValue(proxy(), 2);
rockot10188752016-09-08 18:24:561348 SendValue(proxy(), 3);
rockot401fb2c2016-09-06 18:35:571349
1350 proxy()->Unpause(false /* flush */);
1351
1352 // These messages must be sent immediately since the channel is unpaused.
rockot401fb2c2016-09-06 18:35:571353 SendValue(proxy(), 4);
rockot10188752016-09-08 18:24:561354 SendValue(proxy(), 5);
rockot401fb2c2016-09-06 18:35:571355
1356 // Now we flush the previously queued messages.
1357 proxy()->Flush();
1358
1359 EXPECT_TRUE(WaitForClientShutdown());
1360 DestroyProxy();
1361}
1362
1363class ExpectValueSequenceListener : public IPC::Listener {
1364 public:
Wezfdb98482018-07-12 01:21:391365 ExpectValueSequenceListener(base::queue<int32_t>* expected_values,
1366 base::OnceClosure quit_closure)
1367 : expected_values_(expected_values),
1368 quit_closure_(std::move(quit_closure)) {}
Chris Watkins2d879af2017-11-30 02:11:591369 ~ExpectValueSequenceListener() override = default;
rockot401fb2c2016-09-06 18:35:571370
1371 // IPC::Listener:
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())
Wezfdb98482018-07-12 01:21:391380 std::move(quit_closure_).Run();
rockot401fb2c2016-09-06 18:35:571381 return true;
1382 }
1383
1384 private:
Brett Wilsona62d9c02017-09-20 20:53:201385 base::queue<int32_t>* expected_values_;
Wezfdb98482018-07-12 01:21:391386 base::OnceClosure quit_closure_;
rockot401fb2c2016-09-06 18:35:571387
1388 DISALLOW_COPY_AND_ASSIGN(ExpectValueSequenceListener);
1389};
1390
sammc4bcc4ed62016-10-27 10:13:591391DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(CreatePausedClient,
1392 ChannelProxyClient) {
Brett Wilsona62d9c02017-09-20 20:53:201393 base::queue<int32_t> expected_values;
Wezfdb98482018-07-12 01:21:391394 base::RunLoop run_loop;
1395 ExpectValueSequenceListener listener(&expected_values,
1396 run_loop.QuitClosure());
rockot401fb2c2016-09-06 18:35:571397 CreateProxy(&listener);
rockot401fb2c2016-09-06 18:35:571398 expected_values.push(1);
rockot10188752016-09-08 18:24:561399 expected_values.push(4);
1400 expected_values.push(5);
rockot401fb2c2016-09-06 18:35:571401 expected_values.push(2);
rockot10188752016-09-08 18:24:561402 expected_values.push(3);
rockot401fb2c2016-09-06 18:35:571403 RunProxy();
Wezfdb98482018-07-12 01:21:391404 run_loop.Run();
rockot401fb2c2016-09-06 18:35:571405 EXPECT_TRUE(expected_values.empty());
1406 DestroyProxy();
1407}
1408
sammc5c8a6c62017-02-04 01:33:381409TEST_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;
yzshen1aa8e56c2017-02-16 23:15:451419 vendor->GetTestInterface(mojo::MakeRequest(&tester));
sammc5c8a6c62017-02-04 01:33:381420 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
1429class AssociatedInterfaceDroppingListener : public IPC::Listener {
1430 public:
Wezfdb98482018-07-12 01:21:391431 AssociatedInterfaceDroppingListener(base::OnceClosure callback)
1432 : callback_(std::move(callback)) {}
sammc5c8a6c62017-02-04 01:33:381433 bool OnMessageReceived(const IPC::Message& message) override { return false; }
1434
1435 void OnAssociatedInterfaceRequest(
1436 const std::string& interface_name,
1437 mojo::ScopedInterfaceEndpointHandle handle) override {
1438 if (interface_name == IPC::mojom::SimpleTestDriver::Name_)
Wezfdb98482018-07-12 01:21:391439 std::move(callback_).Run();
sammc5c8a6c62017-02-04 01:33:381440 }
1441
1442 private:
Wezfdb98482018-07-12 01:21:391443 base::OnceClosure callback_;
sammc5c8a6c62017-02-04 01:33:381444};
1445
1446DEFINE_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
Wez831ae412017-08-30 00:29:361456#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
1460class ListenerThatExpectsSharedMemory : public TestListenerBase {
1461 public:
Wezfdb98482018-07-12 01:21:391462 ListenerThatExpectsSharedMemory(base::OnceClosure quit_closure)
1463 : TestListenerBase(std::move(quit_closure)) {}
Wez831ae412017-08-30 00:29:361464
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
1478TEST_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
1508DEFINE_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
Alexandr Ilind497eee2018-04-19 22:50:541519template <class SharedMemoryRegionType>
1520class IPCChannelMojoSharedMemoryRegionTypedTest : public IPCChannelMojoTest {};
1521
1522struct WritableRegionTraits {
1523 using RegionType = base::WritableSharedMemoryRegion;
1524 static const char kClientName[];
1525};
1526const char WritableRegionTraits::kClientName[] =
1527 "IPCChannelMojoTestSendWritableSharedMemoryRegionClient";
1528struct UnsafeRegionTraits {
1529 using RegionType = base::UnsafeSharedMemoryRegion;
1530 static const char kClientName[];
1531};
1532const char UnsafeRegionTraits::kClientName[] =
1533 "IPCChannelMojoTestSendUnsafeSharedMemoryRegionClient";
1534struct ReadOnlyRegionTraits {
1535 using RegionType = base::ReadOnlySharedMemoryRegion;
1536 static const char kClientName[];
1537};
1538const char ReadOnlyRegionTraits::kClientName[] =
1539 "IPCChannelMojoTestSendReadOnlySharedMemoryRegionClient";
1540
1541typedef ::testing::
1542 Types<WritableRegionTraits, UnsafeRegionTraits, ReadOnlyRegionTraits>
1543 AllSharedMemoryRegionTraits;
Victor Costanebc52732019-02-15 02:39:471544TYPED_TEST_SUITE(IPCChannelMojoSharedMemoryRegionTypedTest,
1545 AllSharedMemoryRegionTraits);
Alexandr Ilind497eee2018-04-19 22:50:541546
1547template <class SharedMemoryRegionType>
1548class ListenerThatExpectsSharedMemoryRegion : public TestListenerBase {
1549 public:
Wezfdb98482018-07-12 01:21:391550 explicit ListenerThatExpectsSharedMemoryRegion(base::OnceClosure quit_closure)
Alexandr Ilind497eee2018-04-19 22:50:541551 : TestListenerBase(std::move(quit_closure)) {}
1552
1553 bool OnMessageReceived(const IPC::Message& message) override {
1554 base::PickleIterator iter(message);
1555
1556 SharedMemoryRegionType region;
1557 EXPECT_TRUE(IPC::ReadParam(&message, &iter, &region));
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
1570TYPED_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
1603DEFINE_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}
1615DEFINE_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}
1627DEFINE_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}
Wez831ae412017-08-30 00:29:361639#endif // !defined(OS_MACOSX)
1640
Fabrice de Gans-Riberi894661c2018-05-24 18:43:221641#if defined(OS_POSIX) || defined(OS_FUCHSIA)
rockot8d890f62016-07-14 16:37:141642
Wez831ae412017-08-30 00:29:361643class ListenerThatExpectsFile : public TestListenerBase {
[email protected]64860882014-08-04 23:44:171644 public:
Wezfdb98482018-07-12 01:21:391645 explicit ListenerThatExpectsFile(base::OnceClosure quit_closure)
1646 : TestListenerBase(std::move(quit_closure)) {}
[email protected]64860882014-08-04 23:44:171647
dchengfe61fca2014-10-22 02:29:521648 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:251649 base::PickleIterator iter(message);
morrita81b17e02015-02-06 00:58:301650 HandleSendingHelper::ReadReceivedFile(message, &iter);
Wez831ae412017-08-30 00:29:361651 ListenerThatExpectsOK::SendOK(sender());
[email protected]64860882014-08-04 23:44:171652 return true;
1653 }
[email protected]64860882014-08-04 23:44:171654};
1655
Wez831ae412017-08-30 00:29:361656TEST_F(IPCChannelMojoTest, SendPlatformFile) {
1657 Init("IPCChannelMojoTestSendPlatformFileClient");
[email protected]64860882014-08-04 23:44:171658
Wez831ae412017-08-30 00:29:361659 base::RunLoop run_loop;
1660 ListenerThatExpectsOK listener(run_loop.QuitClosure());
morrita373af03b2014-09-09 19:35:241661 CreateChannel(&listener);
[email protected]64860882014-08-04 23:44:171662 ASSERT_TRUE(ConnectChannel());
[email protected]64860882014-08-04 23:44:171663
amistry20e2b1d62016-06-23 06:12:351664 base::ScopedTempDir temp_dir;
1665 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
vabr16e5f602016-09-15 18:14:001666 base::File file(HandleSendingHelper::GetSendingFilePath(temp_dir.GetPath()),
[email protected]64860882014-08-04 23:44:171667 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
morrita81b17e02015-02-06 00:58:301668 base::File::FLAG_READ);
1669 HandleSendingHelper::WriteFileThenSend(channel(), file);
Wez831ae412017-08-30 00:29:361670 run_loop.Run();
[email protected]64860882014-08-04 23:44:171671
sammc57ed9f982016-03-10 06:28:351672 channel()->Close();
[email protected]64860882014-08-04 23:44:171673
1674 EXPECT_TRUE(WaitForClientShutdown());
1675 DestroyChannel();
1676}
1677
Wez831ae412017-08-30 00:29:361678DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendPlatformFileClient) {
1679 base::RunLoop run_loop;
1680 ListenerThatExpectsFile listener(run_loop.QuitClosure());
sammc57ed9f982016-03-10 06:28:351681 Connect(&listener);
1682 listener.set_sender(channel());
[email protected]64860882014-08-04 23:44:171683
Wez831ae412017-08-30 00:29:361684 run_loop.Run();
[email protected]64860882014-08-04 23:44:171685
sammc57ed9f982016-03-10 06:28:351686 Close();
[email protected]64860882014-08-04 23:44:171687}
morrita81b17e02015-02-06 00:58:301688
Wez831ae412017-08-30 00:29:361689class ListenerThatExpectsFileAndMessagePipe : public TestListenerBase {
morrita81b17e02015-02-06 00:58:301690 public:
Wezfdb98482018-07-12 01:21:391691 explicit ListenerThatExpectsFileAndMessagePipe(base::OnceClosure quit_closure)
1692 : TestListenerBase(std::move(quit_closure)) {}
morrita81b17e02015-02-06 00:58:301693
Chris Watkins2d879af2017-11-30 02:11:591694 ~ListenerThatExpectsFileAndMessagePipe() override = default;
morrita81b17e02015-02-06 00:58:301695
1696 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:251697 base::PickleIterator iter(message);
morrita81b17e02015-02-06 00:58:301698 HandleSendingHelper::ReadReceivedFile(message, &iter);
1699 HandleSendingHelper::ReadReceivedPipe(message, &iter);
Wez831ae412017-08-30 00:29:361700 ListenerThatExpectsOK::SendOK(sender());
morrita81b17e02015-02-06 00:58:301701 return true;
1702 }
morrita81b17e02015-02-06 00:58:301703};
1704
Wez831ae412017-08-30 00:29:361705TEST_F(IPCChannelMojoTest, SendPlatformFileAndMessagePipe) {
1706 Init("IPCChannelMojoTestSendPlatformFileAndMessagePipeClient");
morrita81b17e02015-02-06 00:58:301707
Wez831ae412017-08-30 00:29:361708 base::RunLoop run_loop;
1709 ListenerThatExpectsOK listener(run_loop.QuitClosure());
morrita81b17e02015-02-06 00:58:301710 CreateChannel(&listener);
1711 ASSERT_TRUE(ConnectChannel());
morrita81b17e02015-02-06 00:58:301712
amistry20e2b1d62016-06-23 06:12:351713 base::ScopedTempDir temp_dir;
1714 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
vabr16e5f602016-09-15 18:14:001715 base::File file(HandleSendingHelper::GetSendingFilePath(temp_dir.GetPath()),
morrita81b17e02015-02-06 00:58:301716 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
1717 base::File::FLAG_READ);
1718 TestingMessagePipe pipe;
1719 HandleSendingHelper::WriteFileAndPipeThenSend(channel(), file, &pipe);
1720
Wez831ae412017-08-30 00:29:361721 run_loop.Run();
sammc57ed9f982016-03-10 06:28:351722 channel()->Close();
morrita81b17e02015-02-06 00:58:301723
1724 EXPECT_TRUE(WaitForClientShutdown());
1725 DestroyChannel();
1726}
1727
sammc57ed9f982016-03-10 06:28:351728DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
Wez831ae412017-08-30 00:29:361729 IPCChannelMojoTestSendPlatformFileAndMessagePipeClient) {
1730 base::RunLoop run_loop;
1731 ListenerThatExpectsFileAndMessagePipe listener(run_loop.QuitClosure());
sammc57ed9f982016-03-10 06:28:351732 Connect(&listener);
1733 listener.set_sender(channel());
morrita81b17e02015-02-06 00:58:301734
Wez831ae412017-08-30 00:29:361735 run_loop.Run();
morrita81b17e02015-02-06 00:58:301736
sammc57ed9f982016-03-10 06:28:351737 Close();
morrita81b17e02015-02-06 00:58:301738}
1739
Fabrice de Gans-Riberi894661c2018-05-24 18:43:221740#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
[email protected]64860882014-08-04 23:44:171741
morrita0bd20bd2015-02-25 20:11:271742#if defined(OS_LINUX)
1743
1744const base::ProcessId kMagicChildId = 54321;
1745
Wez831ae412017-08-30 00:29:361746class ListenerThatVerifiesPeerPid : public TestListenerBase {
morrita0bd20bd2015-02-25 20:11:271747 public:
Wezfdb98482018-07-12 01:21:391748 explicit ListenerThatVerifiesPeerPid(base::OnceClosure quit_closure)
1749 : TestListenerBase(std::move(quit_closure)) {}
Wez831ae412017-08-30 00:29:361750
tfarina10a5c062015-09-04 18:47:571751 void OnChannelConnected(int32_t peer_pid) override {
morrita0bd20bd2015-02-25 20:11:271752 EXPECT_EQ(peer_pid, kMagicChildId);
Wezfdb98482018-07-12 01:21:391753 RunQuitClosure();
morrita0bd20bd2015-02-25 20:11:271754 }
1755
1756 bool OnMessageReceived(const IPC::Message& message) override {
1757 NOTREACHED();
1758 return true;
1759 }
1760};
1761
sammc57ed9f982016-03-10 06:28:351762TEST_F(IPCChannelMojoTest, VerifyGlobalPid) {
sammc4bcc4ed62016-10-27 10:13:591763 Init("IPCChannelMojoTestVerifyGlobalPidClient");
morrita0bd20bd2015-02-25 20:11:271764
Wez831ae412017-08-30 00:29:361765 base::RunLoop run_loop;
1766 ListenerThatVerifiesPeerPid listener(run_loop.QuitClosure());
morrita0bd20bd2015-02-25 20:11:271767 CreateChannel(&listener);
1768 ASSERT_TRUE(ConnectChannel());
morrita0bd20bd2015-02-25 20:11:271769
Wez831ae412017-08-30 00:29:361770 run_loop.Run();
rockotcbca72f2015-03-03 16:31:041771 channel()->Close();
morrita0bd20bd2015-02-25 20:11:271772
1773 EXPECT_TRUE(WaitForClientShutdown());
1774 DestroyChannel();
1775}
1776
sammc4bcc4ed62016-10-27 10:13:591777DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestVerifyGlobalPidClient) {
morrita0bd20bd2015-02-25 20:11:271778 IPC::Channel::SetGlobalPid(kMagicChildId);
Wez831ae412017-08-30 00:29:361779
1780 base::RunLoop run_loop;
1781 ListenerThatQuits listener(run_loop.QuitClosure());
sammc57ed9f982016-03-10 06:28:351782 Connect(&listener);
morrita0bd20bd2015-02-25 20:11:271783
Wez831ae412017-08-30 00:29:361784 run_loop.Run();
morrita0bd20bd2015-02-25 20:11:271785
sammc57ed9f982016-03-10 06:28:351786 Close();
morrita0bd20bd2015-02-25 20:11:271787}
1788
sammc57ed9f982016-03-10 06:28:351789#endif // OS_LINUX
morrita0bd20bd2015-02-25 20:11:271790
[email protected]64860882014-08-04 23:44:171791} // namespace