blob: aecb8dcd9f7b7746096ab017e459acd2d682724c [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"
Carlos Caballerodd8bf7b042019-07-30 14:14:1524#include "base/message_loop/message_pump_type.h"
Ken Rockot138153b2018-07-13 23:31:5725#include "base/optional.h"
[email protected]64860882014-08-04 23:44:1726#include "base/path_service.h"
27#include "base/pickle.h"
rockotcbca72f2015-03-03 16:31:0428#include "base/run_loop.h"
skyostile687bdff2015-05-12 11:29:2129#include "base/single_thread_task_runner.h"
rockot7c6bf952016-07-14 00:34:1130#include "base/strings/stringprintf.h"
rockot9abe09b2016-08-02 20:57:3431#include "base/synchronization/waitable_event.h"
Ken Rockot138153b2018-07-13 23:31:5732#include "base/test/bind_test_util.h"
Gabriel Charettec7108742019-08-23 03:31:4033#include "base/test/task_environment.h"
sammc57ed9f982016-03-10 06:28:3534#include "base/test/test_io_thread.h"
Alexandr Ilind497eee2018-04-19 22:50:5435#include "base/test/test_shared_memory_util.h"
morrita0bd20bd2015-02-25 20:11:2736#include "base/test/test_timeouts.h"
[email protected]64860882014-08-04 23:44:1737#include "base/threading/thread.h"
gabf08ccc02016-05-11 18:51:1138#include "base/threading/thread_task_runner_handle.h"
avi246998d82015-12-22 02:39:0439#include "build/build_config.h"
[email protected]64860882014-08-04 23:44:1740#include "ipc/ipc_message.h"
Wez831ae412017-08-30 00:29:3641#include "ipc/ipc_message_utils.h"
amistryd4aa70d2016-06-23 07:52:3742#include "ipc/ipc_mojo_handle_attachment.h"
43#include "ipc/ipc_mojo_message_helper.h"
44#include "ipc/ipc_mojo_param_traits.h"
rockot9abe09b2016-08-02 20:57:3445#include "ipc/ipc_sync_channel.h"
46#include "ipc/ipc_sync_message.h"
rockot7c6bf952016-07-14 00:34:1147#include "ipc/ipc_test.mojom.h"
[email protected]64860882014-08-04 23:44:1748#include "ipc/ipc_test_base.h"
49#include "ipc/ipc_test_channel_listener.h"
Ken Rockot138153b2018-07-13 23:31:5750#include "mojo/core/embedder/embedder.h"
51#include "mojo/public/cpp/bindings/lib/validation_errors.h"
rockota9d566a2017-03-17 19:36:1552#include "mojo/public/cpp/system/wait.h"
sammc57ed9f982016-03-10 06:28:3553#include "testing/gtest/include/gtest/gtest.h"
[email protected]64860882014-08-04 23:44:1754
Fabrice de Gans-Riberi894661c2018-05-24 18:43:2255#if defined(OS_POSIX) || defined(OS_FUCHSIA)
[email protected]64860882014-08-04 23:44:1756#include "base/file_descriptor_posix.h"
morrita1aa788c2015-01-31 05:45:4257#include "ipc/ipc_platform_file_attachment_posix.h"
[email protected]64860882014-08-04 23:44:1758#endif
59
60namespace {
61
rockot7c6bf952016-07-14 00:34:1162void SendString(IPC::Sender* sender, const std::string& str) {
63 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
64 message->WriteString(str);
65 ASSERT_TRUE(sender->Send(message));
66}
67
rockot9abe09b2016-08-02 20:57:3468void SendValue(IPC::Sender* sender, int32_t value) {
69 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
70 message->WriteInt(value);
71 ASSERT_TRUE(sender->Send(message));
72}
73
[email protected]64860882014-08-04 23:44:1774class ListenerThatExpectsOK : public IPC::Listener {
75 public:
Wezfdb98482018-07-12 01:21:3976 explicit ListenerThatExpectsOK(base::OnceClosure quit_closure)
77 : received_ok_(false), quit_closure_(std::move(quit_closure)) {}
[email protected]64860882014-08-04 23:44:1778
Chris Watkins2d879af2017-11-30 02:11:5979 ~ListenerThatExpectsOK() override = default;
[email protected]64860882014-08-04 23:44:1780
dchengfe61fca2014-10-22 02:29:5281 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:2582 base::PickleIterator iter(message);
[email protected]64860882014-08-04 23:44:1783 std::string should_be_ok;
84 EXPECT_TRUE(iter.ReadString(&should_be_ok));
85 EXPECT_EQ(should_be_ok, "OK");
[email protected]e5c27752014-08-08 21:45:1386 received_ok_ = true;
Wezfdb98482018-07-12 01:21:3987 std::move(quit_closure_).Run();
[email protected]64860882014-08-04 23:44:1788 return true;
89 }
90
dchengfe61fca2014-10-22 02:29:5291 void OnChannelError() override {
[email protected]e5c27752014-08-08 21:45:1392 // The connection should be healthy while the listener is waiting
93 // message. An error can occur after that because the peer
94 // process dies.
Wezd95d48042018-02-26 20:50:4795 CHECK(received_ok_);
[email protected]64860882014-08-04 23:44:1796 }
97
rockot7c6bf952016-07-14 00:34:1198 static void SendOK(IPC::Sender* sender) { SendString(sender, "OK"); }
[email protected]e5c27752014-08-08 21:45:1399
100 private:
101 bool received_ok_;
Wezfdb98482018-07-12 01:21:39102 base::OnceClosure quit_closure_;
Wez831ae412017-08-30 00:29:36103};
104
105class TestListenerBase : public IPC::Listener {
106 public:
Wezfdb98482018-07-12 01:21:39107 explicit TestListenerBase(base::OnceClosure quit_closure)
108 : quit_closure_(std::move(quit_closure)) {}
Wez831ae412017-08-30 00:29:36109
Chris Watkins2d879af2017-11-30 02:11:59110 ~TestListenerBase() override = default;
Wezfdb98482018-07-12 01:21:39111 void OnChannelError() override { RunQuitClosure(); }
Wez831ae412017-08-30 00:29:36112
113 void set_sender(IPC::Sender* sender) { sender_ = sender; }
114 IPC::Sender* sender() const { return sender_; }
Ken Rockot138153b2018-07-13 23:31:57115 void RunQuitClosure() {
116 if (quit_closure_)
117 std::move(quit_closure_).Run();
118 }
Wez831ae412017-08-30 00:29:36119
120 private:
121 IPC::Sender* sender_ = nullptr;
Wezfdb98482018-07-12 01:21:39122 base::OnceClosure quit_closure_;
[email protected]64860882014-08-04 23:44:17123};
124
sammc4bcc4ed62016-10-27 10:13:59125using IPCChannelMojoTest = IPCChannelMojoTestBase;
rockotcbca72f2015-03-03 16:31:04126
[email protected]64860882014-08-04 23:44:17127class TestChannelListenerWithExtraExpectations
128 : public IPC::TestChannelListener {
129 public:
sammc57ed9f982016-03-10 06:28:35130 TestChannelListenerWithExtraExpectations() : is_connected_called_(false) {}
[email protected]64860882014-08-04 23:44:17131
tfarina10a5c062015-09-04 18:47:57132 void OnChannelConnected(int32_t peer_pid) override {
[email protected]64860882014-08-04 23:44:17133 IPC::TestChannelListener::OnChannelConnected(peer_pid);
134 EXPECT_TRUE(base::kNullProcessId != peer_pid);
135 is_connected_called_ = true;
136 }
137
138 bool is_connected_called() const { return is_connected_called_; }
139
140 private:
141 bool is_connected_called_;
142};
143
amistry0027a0952016-05-03 00:52:47144TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
sammc4bcc4ed62016-10-27 10:13:59145 Init("IPCChannelMojoTestClient");
[email protected]64860882014-08-04 23:44:17146
147 // Set up IPC channel and start client.
148 TestChannelListenerWithExtraExpectations listener;
morrita373af03b2014-09-09 19:35:24149 CreateChannel(&listener);
[email protected]64860882014-08-04 23:44:17150 listener.Init(sender());
151 ASSERT_TRUE(ConnectChannel());
[email protected]64860882014-08-04 23:44:17152
sammc57ed9f982016-03-10 06:28:35153 IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent");
[email protected]64860882014-08-04 23:44:17154
fdoray8e32586852016-06-22 19:56:16155 base::RunLoop().Run();
[email protected]64860882014-08-04 23:44:17156
sammc57ed9f982016-03-10 06:28:35157 channel()->Close();
[email protected]64860882014-08-04 23:44:17158
159 EXPECT_TRUE(WaitForClientShutdown());
160 EXPECT_TRUE(listener.is_connected_called());
161 EXPECT_TRUE(listener.HasSentAll());
162
163 DestroyChannel();
164}
165
166// A long running process that connects to us
sammc4bcc4ed62016-10-27 10:13:59167DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestClient) {
[email protected]64860882014-08-04 23:44:17168 TestChannelListenerWithExtraExpectations listener;
sammc57ed9f982016-03-10 06:28:35169 Connect(&listener);
170 listener.Init(channel());
[email protected]64860882014-08-04 23:44:17171
sammc57ed9f982016-03-10 06:28:35172 IPC::TestChannelListener::SendOneMessage(channel(), "hello from child");
fdoray8e32586852016-06-22 19:56:16173 base::RunLoop().Run();
[email protected]64860882014-08-04 23:44:17174 EXPECT_TRUE(listener.is_connected_called());
175 EXPECT_TRUE(listener.HasSentAll());
176
sammc57ed9f982016-03-10 06:28:35177 Close();
[email protected]64860882014-08-04 23:44:17178}
179
Wez831ae412017-08-30 00:29:36180class ListenerExpectingErrors : public TestListenerBase {
morrita0a24cfc92014-09-16 03:20:48181 public:
Wezfdb98482018-07-12 01:21:39182 ListenerExpectingErrors(base::OnceClosure quit_closure)
183 : TestListenerBase(std::move(quit_closure)), has_error_(false) {}
morrita0a24cfc92014-09-16 03:20:48184
dchengfe61fca2014-10-22 02:29:52185 bool OnMessageReceived(const IPC::Message& message) override { return true; }
morrita0a24cfc92014-09-16 03:20:48186
dchengfe61fca2014-10-22 02:29:52187 void OnChannelError() override {
morrita0a24cfc92014-09-16 03:20:48188 has_error_ = true;
Wez831ae412017-08-30 00:29:36189 TestListenerBase::OnChannelError();
morrita0a24cfc92014-09-16 03:20:48190 }
191
192 bool has_error() const { return has_error_; }
193
194 private:
195 bool has_error_;
196};
197
morrita0a24cfc92014-09-16 03:20:48198class ListenerThatQuits : public IPC::Listener {
199 public:
Wezfdb98482018-07-12 01:21:39200 explicit ListenerThatQuits(base::OnceClosure quit_closure)
201 : quit_closure_(std::move(quit_closure)) {}
morrita0a24cfc92014-09-16 03:20:48202
sammc57ed9f982016-03-10 06:28:35203 bool OnMessageReceived(const IPC::Message& message) override { return true; }
morrita0a24cfc92014-09-16 03:20:48204
Wezfdb98482018-07-12 01:21:39205 void OnChannelConnected(int32_t peer_pid) override {
206 std::move(quit_closure_).Run();
207 }
Wez831ae412017-08-30 00:29:36208
209 private:
Wezfdb98482018-07-12 01:21:39210 base::OnceClosure quit_closure_;
morrita0a24cfc92014-09-16 03:20:48211};
212
213// A long running process that connects to us.
sammc4bcc4ed62016-10-27 10:13:59214DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoErraticTestClient) {
Wez831ae412017-08-30 00:29:36215 base::RunLoop run_loop;
216 ListenerThatQuits listener(run_loop.QuitClosure());
sammc57ed9f982016-03-10 06:28:35217 Connect(&listener);
morrita0a24cfc92014-09-16 03:20:48218
Wez831ae412017-08-30 00:29:36219 run_loop.Run();
morrita0a24cfc92014-09-16 03:20:48220
sammc57ed9f982016-03-10 06:28:35221 Close();
morrita0a24cfc92014-09-16 03:20:48222}
223
rockot8c23d462016-07-25 17:33:04224TEST_F(IPCChannelMojoTest, SendFailWithPendingMessages) {
sammc4bcc4ed62016-10-27 10:13:59225 Init("IPCChannelMojoErraticTestClient");
morrita0a24cfc92014-09-16 03:20:48226
227 // Set up IPC channel and start client.
Wez831ae412017-08-30 00:29:36228 base::RunLoop run_loop;
229 ListenerExpectingErrors listener(run_loop.QuitClosure());
morrita0a24cfc92014-09-16 03:20:48230 CreateChannel(&listener);
231 ASSERT_TRUE(ConnectChannel());
232
jamesra03ae492014-10-03 04:26:48233 // This matches a value in mojo/edk/system/constants.h
morritabe6c4cc2014-09-24 23:38:44234 const int kMaxMessageNumBytes = 4 * 1024 * 1024;
235 std::string overly_large_data(kMaxMessageNumBytes, '*');
morrita0a24cfc92014-09-16 03:20:48236 // This messages are queued as pending.
morritabe6c4cc2014-09-24 23:38:44237 for (size_t i = 0; i < 10; ++i) {
sammc57ed9f982016-03-10 06:28:35238 IPC::TestChannelListener::SendOneMessage(sender(),
239 overly_large_data.c_str());
morrita0a24cfc92014-09-16 03:20:48240 }
241
Wez831ae412017-08-30 00:29:36242 run_loop.Run();
morrita0a24cfc92014-09-16 03:20:48243
sammc57ed9f982016-03-10 06:28:35244 channel()->Close();
morrita0a24cfc92014-09-16 03:20:48245
246 EXPECT_TRUE(WaitForClientShutdown());
247 EXPECT_TRUE(listener.has_error());
248
249 DestroyChannel();
250}
251
Ken Rockot138153b2018-07-13 23:31:57252class ListenerThatBindsATestStructPasser : public IPC::Listener,
253 public IPC::mojom::TestStructPasser {
254 public:
255 ListenerThatBindsATestStructPasser() : binding_(this) {}
256
257 bool OnMessageReceived(const IPC::Message& message) override { return true; }
258
259 void OnChannelConnected(int32_t peer_pid) override {}
260
261 void OnChannelError() override { NOTREACHED(); }
262
263 void OnAssociatedInterfaceRequest(
264 const std::string& interface_name,
265 mojo::ScopedInterfaceEndpointHandle handle) override {
266 CHECK_EQ(interface_name, IPC::mojom::TestStructPasser::Name_);
267 binding_.Bind(
268 IPC::mojom::TestStructPasserAssociatedRequest(std::move(handle)));
269 }
270
271 private:
272 // IPC::mojom::TestStructPasser:
273 void Pass(IPC::mojom::TestStructPtr) override { NOTREACHED(); }
274
275 mojo::AssociatedBinding<IPC::mojom::TestStructPasser> binding_;
276};
277
278class ListenerThatExpectsNoError : public IPC::Listener {
279 public:
280 ListenerThatExpectsNoError(base::OnceClosure connect_closure,
281 base::OnceClosure quit_closure)
282 : connect_closure_(std::move(connect_closure)),
283 quit_closure_(std::move(quit_closure)) {}
284
285 bool OnMessageReceived(const IPC::Message& message) override {
286 base::PickleIterator iter(message);
287 std::string should_be_ok;
288 EXPECT_TRUE(iter.ReadString(&should_be_ok));
289 EXPECT_EQ(should_be_ok, "OK");
290 std::move(quit_closure_).Run();
291 return true;
292 }
293
294 void OnChannelConnected(int32_t peer_pid) override {
295 std::move(connect_closure_).Run();
296 }
297
298 void OnChannelError() override { NOTREACHED(); }
299
300 private:
301 base::OnceClosure connect_closure_;
302 base::OnceClosure quit_closure_;
303};
304
305DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
306 IPCChannelMojoNoImplicitChanelClosureClient) {
307 base::RunLoop wait_to_connect_loop;
308 base::RunLoop wait_to_quit_loop;
309 ListenerThatExpectsNoError listener(wait_to_connect_loop.QuitClosure(),
310 wait_to_quit_loop.QuitClosure());
311 Connect(&listener);
312 wait_to_connect_loop.Run();
313
314 IPC::mojom::TestStructPasserAssociatedPtr passer;
315 channel()->GetAssociatedInterfaceSupport()->GetRemoteAssociatedInterface(
316 &passer);
317
318 // This avoids hitting DCHECKs in the serialization code meant to stop us from
319 // making such "mistakes" as the one we're about to make below.
320 mojo::internal::SerializationWarningObserverForTesting suppress_those_dchecks;
321
322 // Send an invalid message. The TestStruct argument is not allowed to be null.
323 // This will elicit a validation error in the parent process, but should not
324 // actually disconnect the channel.
325 passer->Pass(nullptr);
326
327 // Wait until the parent says it's OK to quit, so it has time to verify its
328 // expected behavior.
329 wait_to_quit_loop.Run();
330
331 Close();
332}
333
334TEST_F(IPCChannelMojoTest, NoImplicitChannelClosure) {
335 // Verifies that OnChannelError is not invoked due to conditions other than
336 // peer closure (e.g. a malformed inbound message). Instead we should always
337 // be able to handle validation errors via Mojo bad message reporting.
338
339 // NOTE: We can't create a RunLoop before Init() is called, but we have to set
340 // the default ProcessErrorCallback (which we want to reference the RunLoop)
341 // before Init() launches a child process. Hence the base::Optional here.
342 base::Optional<base::RunLoop> wait_for_error_loop;
343 bool process_error_received = false;
344 mojo::core::SetDefaultProcessErrorCallback(
345 base::BindLambdaForTesting([&](const std::string&) {
346 process_error_received = true;
347 wait_for_error_loop->Quit();
348 }));
349
350 Init("IPCChannelMojoNoImplicitChanelClosureClient");
351
352 wait_for_error_loop.emplace();
353 ListenerThatBindsATestStructPasser listener;
354 CreateChannel(&listener);
355 ASSERT_TRUE(ConnectChannel());
356
357 wait_for_error_loop->Run();
358 EXPECT_TRUE(process_error_received);
359
360 // Tell the child it can quit and wait for it to shut down.
361 ListenerThatExpectsOK::SendOK(channel());
362 EXPECT_TRUE(WaitForClientShutdown());
363 DestroyChannel();
364}
365
morrita81b17e02015-02-06 00:58:30366struct TestingMessagePipe {
367 TestingMessagePipe() {
368 EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateMessagePipe(nullptr, &self, &peer));
369 }
370
371 mojo::ScopedMessagePipeHandle self;
372 mojo::ScopedMessagePipeHandle peer;
373};
374
375class HandleSendingHelper {
376 public:
377 static std::string GetSendingFileContent() { return "Hello"; }
378
379 static void WritePipe(IPC::Message* message, TestingMessagePipe* pipe) {
380 std::string content = HandleSendingHelper::GetSendingFileContent();
381 EXPECT_EQ(MOJO_RESULT_OK,
382 mojo::WriteMessageRaw(pipe->self.get(), &content[0],
383 static_cast<uint32_t>(content.size()),
384 nullptr, 0, 0));
dchenge48600452015-12-28 02:24:50385 EXPECT_TRUE(IPC::MojoMessageHelper::WriteMessagePipeTo(
386 message, std::move(pipe->peer)));
morrita81b17e02015-02-06 00:58:30387 }
388
389 static void WritePipeThenSend(IPC::Sender* sender, TestingMessagePipe* pipe) {
390 IPC::Message* message =
391 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
392 WritePipe(message, pipe);
393 ASSERT_TRUE(sender->Send(message));
394 }
395
396 static void ReadReceivedPipe(const IPC::Message& message,
brettwbd4d7112015-06-03 04:29:25397 base::PickleIterator* iter) {
morrita81b17e02015-02-06 00:58:30398 mojo::ScopedMessagePipeHandle pipe;
399 EXPECT_TRUE(
400 IPC::MojoMessageHelper::ReadMessagePipeFrom(&message, iter, &pipe));
Ken Rockotfada7d282017-06-12 21:25:13401 std::vector<uint8_t> content;
morrita81b17e02015-02-06 00:58:30402
sammc57ed9f982016-03-10 06:28:35403 ASSERT_EQ(MOJO_RESULT_OK,
rockota9d566a2017-03-17 19:36:15404 mojo::Wait(pipe.get(), MOJO_HANDLE_SIGNAL_READABLE));
morrita81b17e02015-02-06 00:58:30405 EXPECT_EQ(MOJO_RESULT_OK,
Ken Rockotfada7d282017-06-12 21:25:13406 mojo::ReadMessageRaw(pipe.get(), &content, nullptr, 0));
407 EXPECT_EQ(std::string(content.begin(), content.end()),
408 GetSendingFileContent());
morrita81b17e02015-02-06 00:58:30409 }
410
Fabrice de Gans-Riberi894661c2018-05-24 18:43:22411#if defined(OS_POSIX) || defined(OS_FUCHSIA)
amistry20e2b1d62016-06-23 06:12:35412 static base::FilePath GetSendingFilePath(const base::FilePath& dir_path) {
413 return dir_path.Append("ListenerThatExpectsFile.txt");
morrita81b17e02015-02-06 00:58:30414 }
415
416 static void WriteFile(IPC::Message* message, base::File& file) {
417 std::string content = GetSendingFileContent();
418 file.WriteAtCurrentPos(content.data(), content.size());
419 file.Flush();
420 message->WriteAttachment(new IPC::internal::PlatformFileAttachment(
421 base::ScopedFD(file.TakePlatformFile())));
422 }
423
424 static void WriteFileThenSend(IPC::Sender* sender, base::File& file) {
425 IPC::Message* message =
426 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
427 WriteFile(message, file);
428 ASSERT_TRUE(sender->Send(message));
429 }
430
431 static void WriteFileAndPipeThenSend(IPC::Sender* sender,
432 base::File& file,
433 TestingMessagePipe* pipe) {
434 IPC::Message* message =
435 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
436 WriteFile(message, file);
437 WritePipe(message, pipe);
438 ASSERT_TRUE(sender->Send(message));
439 }
440
441 static void ReadReceivedFile(const IPC::Message& message,
brettwbd4d7112015-06-03 04:29:25442 base::PickleIterator* iter) {
rockot502c94f2016-02-03 20:20:16443 scoped_refptr<base::Pickle::Attachment> attachment;
morrita81b17e02015-02-06 00:58:30444 EXPECT_TRUE(message.ReadAttachment(iter, &attachment));
sammc6ed3efb2016-11-23 03:17:35445 EXPECT_EQ(
446 IPC::MessageAttachment::Type::PLATFORM_FILE,
447 static_cast<IPC::MessageAttachment*>(attachment.get())->GetType());
448 base::File file(
449 static_cast<IPC::internal::PlatformFileAttachment*>(attachment.get())
450 ->TakePlatformFile());
morrita81b17e02015-02-06 00:58:30451 std::string content(GetSendingFileContent().size(), ' ');
452 file.Read(0, &content[0], content.size());
453 EXPECT_EQ(content, GetSendingFileContent());
454 }
455#endif
456};
457
Wez831ae412017-08-30 00:29:36458class ListenerThatExpectsMessagePipe : public TestListenerBase {
morrita81b17e02015-02-06 00:58:30459 public:
Wezfdb98482018-07-12 01:21:39460 ListenerThatExpectsMessagePipe(base::OnceClosure quit_closure)
461 : TestListenerBase(std::move(quit_closure)) {}
morrita81b17e02015-02-06 00:58:30462
Chris Watkins2d879af2017-11-30 02:11:59463 ~ListenerThatExpectsMessagePipe() override = default;
morrita81b17e02015-02-06 00:58:30464
465 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:25466 base::PickleIterator iter(message);
morrita81b17e02015-02-06 00:58:30467 HandleSendingHelper::ReadReceivedPipe(message, &iter);
Wez831ae412017-08-30 00:29:36468 ListenerThatExpectsOK::SendOK(sender());
morrita81b17e02015-02-06 00:58:30469 return true;
470 }
morrita81b17e02015-02-06 00:58:30471};
472
amistry0027a0952016-05-03 00:52:47473TEST_F(IPCChannelMojoTest, SendMessagePipe) {
sammc4bcc4ed62016-10-27 10:13:59474 Init("IPCChannelMojoTestSendMessagePipeClient");
morrita81b17e02015-02-06 00:58:30475
Wez831ae412017-08-30 00:29:36476 base::RunLoop run_loop;
477 ListenerThatExpectsOK listener(run_loop.QuitClosure());
morrita81b17e02015-02-06 00:58:30478 CreateChannel(&listener);
479 ASSERT_TRUE(ConnectChannel());
morrita81b17e02015-02-06 00:58:30480
481 TestingMessagePipe pipe;
482 HandleSendingHelper::WritePipeThenSend(channel(), &pipe);
483
Wez831ae412017-08-30 00:29:36484 run_loop.Run();
sammc57ed9f982016-03-10 06:28:35485 channel()->Close();
morrita81b17e02015-02-06 00:58:30486
487 EXPECT_TRUE(WaitForClientShutdown());
488 DestroyChannel();
489}
490
sammc4bcc4ed62016-10-27 10:13:59491DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendMessagePipeClient) {
Wez831ae412017-08-30 00:29:36492 base::RunLoop run_loop;
493 ListenerThatExpectsMessagePipe listener(run_loop.QuitClosure());
sammc57ed9f982016-03-10 06:28:35494 Connect(&listener);
495 listener.set_sender(channel());
morrita81b17e02015-02-06 00:58:30496
Wez831ae412017-08-30 00:29:36497 run_loop.Run();
morrita81b17e02015-02-06 00:58:30498
sammc57ed9f982016-03-10 06:28:35499 Close();
morrita81b17e02015-02-06 00:58:30500}
501
morrita438a2ee2015-04-03 05:28:21502void ReadOK(mojo::MessagePipeHandle pipe) {
Ken Rockotfada7d282017-06-12 21:25:13503 std::vector<uint8_t> should_be_ok;
rockota9d566a2017-03-17 19:36:15504 CHECK_EQ(MOJO_RESULT_OK, mojo::Wait(pipe, MOJO_HANDLE_SIGNAL_READABLE));
morrita438a2ee2015-04-03 05:28:21505 CHECK_EQ(MOJO_RESULT_OK,
Ken Rockotfada7d282017-06-12 21:25:13506 mojo::ReadMessageRaw(pipe, &should_be_ok, nullptr, 0));
507 EXPECT_EQ("OK", std::string(should_be_ok.begin(), should_be_ok.end()));
morrita438a2ee2015-04-03 05:28:21508}
509
510void WriteOK(mojo::MessagePipeHandle pipe) {
511 std::string ok("OK");
512 CHECK_EQ(MOJO_RESULT_OK,
513 mojo::WriteMessageRaw(pipe, &ok[0], static_cast<uint32_t>(ok.size()),
514 nullptr, 0, 0));
515}
516
Wez831ae412017-08-30 00:29:36517class ListenerThatExpectsMessagePipeUsingParamTrait : public TestListenerBase {
morrita438a2ee2015-04-03 05:28:21518 public:
Wez831ae412017-08-30 00:29:36519 explicit ListenerThatExpectsMessagePipeUsingParamTrait(
Wezfdb98482018-07-12 01:21:39520 base::OnceClosure quit_closure,
Wez831ae412017-08-30 00:29:36521 bool receiving_valid)
Wezfdb98482018-07-12 01:21:39522 : TestListenerBase(std::move(quit_closure)),
523 receiving_valid_(receiving_valid) {}
morrita438a2ee2015-04-03 05:28:21524
Chris Watkins2d879af2017-11-30 02:11:59525 ~ListenerThatExpectsMessagePipeUsingParamTrait() override = default;
morrita438a2ee2015-04-03 05:28:21526
527 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:25528 base::PickleIterator iter(message);
morrita438a2ee2015-04-03 05:28:21529 mojo::MessagePipeHandle handle;
530 EXPECT_TRUE(IPC::ParamTraits<mojo::MessagePipeHandle>::Read(&message, &iter,
531 &handle));
532 EXPECT_EQ(handle.is_valid(), receiving_valid_);
533 if (receiving_valid_) {
534 ReadOK(handle);
535 MojoClose(handle.value());
536 }
537
Wez831ae412017-08-30 00:29:36538 ListenerThatExpectsOK::SendOK(sender());
morrita438a2ee2015-04-03 05:28:21539 return true;
540 }
541
morrita438a2ee2015-04-03 05:28:21542 private:
morrita438a2ee2015-04-03 05:28:21543 bool receiving_valid_;
544};
545
sammc4bcc4ed62016-10-27 10:13:59546class ParamTraitMessagePipeClient : public IpcChannelMojoTestClient {
sammc57ed9f982016-03-10 06:28:35547 public:
548 void RunTest(bool receiving_valid_handle) {
Wez831ae412017-08-30 00:29:36549 base::RunLoop run_loop;
sammc57ed9f982016-03-10 06:28:35550 ListenerThatExpectsMessagePipeUsingParamTrait listener(
Wez831ae412017-08-30 00:29:36551 run_loop.QuitClosure(), receiving_valid_handle);
sammc57ed9f982016-03-10 06:28:35552 Connect(&listener);
553 listener.set_sender(channel());
morrita438a2ee2015-04-03 05:28:21554
Wez831ae412017-08-30 00:29:36555 run_loop.Run();
morrita438a2ee2015-04-03 05:28:21556
sammc57ed9f982016-03-10 06:28:35557 Close();
558 }
559};
morrita438a2ee2015-04-03 05:28:21560
amistry0027a0952016-05-03 00:52:47561TEST_F(IPCChannelMojoTest, ParamTraitValidMessagePipe) {
sammc4bcc4ed62016-10-27 10:13:59562 Init("ParamTraitValidMessagePipeClient");
morrita438a2ee2015-04-03 05:28:21563
Wez831ae412017-08-30 00:29:36564 base::RunLoop run_loop;
565 ListenerThatExpectsOK listener(run_loop.QuitClosure());
morrita438a2ee2015-04-03 05:28:21566 CreateChannel(&listener);
567 ASSERT_TRUE(ConnectChannel());
morrita438a2ee2015-04-03 05:28:21568
569 TestingMessagePipe pipe;
570
danakj03de39b22016-04-23 04:21:09571 std::unique_ptr<IPC::Message> message(new IPC::Message());
morrita438a2ee2015-04-03 05:28:21572 IPC::ParamTraits<mojo::MessagePipeHandle>::Write(message.get(),
573 pipe.peer.release());
574 WriteOK(pipe.self.get());
575
sammc57ed9f982016-03-10 06:28:35576 channel()->Send(message.release());
Wez831ae412017-08-30 00:29:36577 run_loop.Run();
sammc57ed9f982016-03-10 06:28:35578 channel()->Close();
morrita438a2ee2015-04-03 05:28:21579
580 EXPECT_TRUE(WaitForClientShutdown());
581 DestroyChannel();
582}
583
sammc4bcc4ed62016-10-27 10:13:59584DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
585 ParamTraitValidMessagePipeClient,
586 ParamTraitMessagePipeClient) {
sammc57ed9f982016-03-10 06:28:35587 RunTest(true);
morrita438a2ee2015-04-03 05:28:21588}
589
amistry0027a0952016-05-03 00:52:47590TEST_F(IPCChannelMojoTest, ParamTraitInvalidMessagePipe) {
sammc4bcc4ed62016-10-27 10:13:59591 Init("ParamTraitInvalidMessagePipeClient");
morrita438a2ee2015-04-03 05:28:21592
Wez831ae412017-08-30 00:29:36593 base::RunLoop run_loop;
594 ListenerThatExpectsOK listener(run_loop.QuitClosure());
morrita438a2ee2015-04-03 05:28:21595 CreateChannel(&listener);
596 ASSERT_TRUE(ConnectChannel());
morrita438a2ee2015-04-03 05:28:21597
598 mojo::MessagePipeHandle invalid_handle;
danakj03de39b22016-04-23 04:21:09599 std::unique_ptr<IPC::Message> message(new IPC::Message());
morrita438a2ee2015-04-03 05:28:21600 IPC::ParamTraits<mojo::MessagePipeHandle>::Write(message.get(),
601 invalid_handle);
602
sammc57ed9f982016-03-10 06:28:35603 channel()->Send(message.release());
Wez831ae412017-08-30 00:29:36604 run_loop.Run();
sammc57ed9f982016-03-10 06:28:35605 channel()->Close();
morrita438a2ee2015-04-03 05:28:21606
607 EXPECT_TRUE(WaitForClientShutdown());
608 DestroyChannel();
609}
610
sammc4bcc4ed62016-10-27 10:13:59611DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
612 ParamTraitInvalidMessagePipeClient,
613 ParamTraitMessagePipeClient) {
sammc57ed9f982016-03-10 06:28:35614 RunTest(false);
morrita438a2ee2015-04-03 05:28:21615}
616
amistry0027a0952016-05-03 00:52:47617TEST_F(IPCChannelMojoTest, SendFailAfterClose) {
sammc4bcc4ed62016-10-27 10:13:59618 Init("IPCChannelMojoTestSendOkClient");
morrita17137e62015-06-23 22:29:36619
Wez831ae412017-08-30 00:29:36620 base::RunLoop run_loop;
621 ListenerThatExpectsOK listener(run_loop.QuitClosure());
morrita17137e62015-06-23 22:29:36622 CreateChannel(&listener);
623 ASSERT_TRUE(ConnectChannel());
morrita17137e62015-06-23 22:29:36624
Wez831ae412017-08-30 00:29:36625 run_loop.Run();
sammc57ed9f982016-03-10 06:28:35626 channel()->Close();
627 ASSERT_FALSE(channel()->Send(new IPC::Message()));
morrita17137e62015-06-23 22:29:36628
629 EXPECT_TRUE(WaitForClientShutdown());
630 DestroyChannel();
631}
632
Wez831ae412017-08-30 00:29:36633class ListenerSendingOneOk : public TestListenerBase {
morrita17137e62015-06-23 22:29:36634 public:
Wezfdb98482018-07-12 01:21:39635 ListenerSendingOneOk(base::OnceClosure quit_closure)
636 : TestListenerBase(std::move(quit_closure)) {}
morrita17137e62015-06-23 22:29:36637
sammc57ed9f982016-03-10 06:28:35638 bool OnMessageReceived(const IPC::Message& message) override { return true; }
morrita17137e62015-06-23 22:29:36639
tfarina10a5c062015-09-04 18:47:57640 void OnChannelConnected(int32_t peer_pid) override {
Wez831ae412017-08-30 00:29:36641 ListenerThatExpectsOK::SendOK(sender());
Wezfdb98482018-07-12 01:21:39642 RunQuitClosure();
morrita17137e62015-06-23 22:29:36643 }
morrita17137e62015-06-23 22:29:36644};
645
sammc4bcc4ed62016-10-27 10:13:59646DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendOkClient) {
Wez831ae412017-08-30 00:29:36647 base::RunLoop run_loop;
648 ListenerSendingOneOk listener(run_loop.QuitClosure());
sammc57ed9f982016-03-10 06:28:35649 Connect(&listener);
650 listener.set_sender(channel());
morrita17137e62015-06-23 22:29:36651
Wez831ae412017-08-30 00:29:36652 run_loop.Run();
morrita17137e62015-06-23 22:29:36653
sammc57ed9f982016-03-10 06:28:35654 Close();
morrita17137e62015-06-23 22:29:36655}
656
rockot7c6bf952016-07-14 00:34:11657class ListenerWithSimpleAssociatedInterface
658 : public IPC::Listener,
659 public IPC::mojom::SimpleTestDriver {
660 public:
661 static const int kNumMessages;
662
Wezfdb98482018-07-12 01:21:39663 explicit ListenerWithSimpleAssociatedInterface(base::OnceClosure quit_closure)
664 : quit_closure_(std::move(quit_closure)), binding_(this) {}
rockot7c6bf952016-07-14 00:34:11665
Chris Watkins2d879af2017-11-30 02:11:59666 ~ListenerWithSimpleAssociatedInterface() override = default;
rockot7c6bf952016-07-14 00:34:11667
668 bool OnMessageReceived(const IPC::Message& message) override {
669 base::PickleIterator iter(message);
rockot9abe09b2016-08-02 20:57:34670 int32_t should_be_expected;
671 EXPECT_TRUE(iter.ReadInt(&should_be_expected));
672 EXPECT_EQ(should_be_expected, next_expected_value_);
rockot7c6bf952016-07-14 00:34:11673 num_messages_received_++;
674 return true;
675 }
676
Wezfdb98482018-07-12 01:21:39677 void OnChannelError() override { CHECK(!quit_closure_); }
rockot7c6bf952016-07-14 00:34:11678
679 void RegisterInterfaceFactory(IPC::Channel* channel) {
680 channel->GetAssociatedInterfaceSupport()->AddAssociatedInterface(
Wezfdb98482018-07-12 01:21:39681 base::BindRepeating(&ListenerWithSimpleAssociatedInterface::BindRequest,
682 base::Unretained(this)));
rockot7c6bf952016-07-14 00:34:11683 }
684
685 private:
686 // IPC::mojom::SimpleTestDriver:
rockot9abe09b2016-08-02 20:57:34687 void ExpectValue(int32_t value) override {
688 next_expected_value_ = value;
689 }
690
tzikdd76ce712017-06-08 05:27:04691 void GetExpectedValue(GetExpectedValueCallback callback) override {
rockot9abe09b2016-08-02 20:57:34692 NOTREACHED();
693 }
694
tzikdd76ce712017-06-08 05:27:04695 void RequestValue(RequestValueCallback callback) override { NOTREACHED(); }
rockot7c6bf952016-07-14 00:34:11696
tzikdd76ce712017-06-08 05:27:04697 void RequestQuit(RequestQuitCallback callback) override {
rockot7c6bf952016-07-14 00:34:11698 EXPECT_EQ(kNumMessages, num_messages_received_);
tzikdd76ce712017-06-08 05:27:04699 std::move(callback).Run();
Wezfdb98482018-07-12 01:21:39700 std::move(quit_closure_).Run();
rockot7c6bf952016-07-14 00:34:11701 }
702
703 void BindRequest(IPC::mojom::SimpleTestDriverAssociatedRequest request) {
704 DCHECK(!binding_.is_bound());
705 binding_.Bind(std::move(request));
706 }
707
rockot9abe09b2016-08-02 20:57:34708 int32_t next_expected_value_ = 0;
rockot7c6bf952016-07-14 00:34:11709 int num_messages_received_ = 0;
Wezfdb98482018-07-12 01:21:39710 base::OnceClosure quit_closure_;
rockot7c6bf952016-07-14 00:34:11711
712 mojo::AssociatedBinding<IPC::mojom::SimpleTestDriver> binding_;
713};
714
715const int ListenerWithSimpleAssociatedInterface::kNumMessages = 1000;
716
717class ListenerSendingAssociatedMessages : public IPC::Listener {
718 public:
Wezfdb98482018-07-12 01:21:39719 explicit ListenerSendingAssociatedMessages(base::OnceClosure quit_closure)
720 : quit_closure_(std::move(quit_closure)) {}
rockot7c6bf952016-07-14 00:34:11721
722 bool OnMessageReceived(const IPC::Message& message) override { return true; }
723
724 void OnChannelConnected(int32_t peer_pid) override {
725 DCHECK(channel_);
726 channel_->GetAssociatedInterfaceSupport()->GetRemoteAssociatedInterface(
727 &driver_);
728
729 // Send a bunch of interleaved messages, alternating between the associated
730 // interface and a legacy IPC::Message.
731 for (int i = 0; i < ListenerWithSimpleAssociatedInterface::kNumMessages;
732 ++i) {
rockot9abe09b2016-08-02 20:57:34733 driver_->ExpectValue(i);
734 SendValue(channel_, i);
rockot7c6bf952016-07-14 00:34:11735 }
Wezfdb98482018-07-12 01:21:39736 driver_->RequestQuit(base::BindOnce(
737 &ListenerSendingAssociatedMessages::OnQuitAck, base::Unretained(this)));
rockot7c6bf952016-07-14 00:34:11738 }
739
740 void set_channel(IPC::Channel* channel) { channel_ = channel; }
741
742 private:
Wezfdb98482018-07-12 01:21:39743 void OnQuitAck() { std::move(quit_closure_).Run(); }
rockot7c6bf952016-07-14 00:34:11744
745 IPC::Channel* channel_ = nullptr;
746 IPC::mojom::SimpleTestDriverAssociatedPtr driver_;
Wezfdb98482018-07-12 01:21:39747 base::OnceClosure quit_closure_;
rockot7c6bf952016-07-14 00:34:11748};
749
750TEST_F(IPCChannelMojoTest, SimpleAssociatedInterface) {
sammc4bcc4ed62016-10-27 10:13:59751 Init("SimpleAssociatedInterfaceClient");
rockot7c6bf952016-07-14 00:34:11752
Wezfdb98482018-07-12 01:21:39753 base::RunLoop run_loop;
754 ListenerWithSimpleAssociatedInterface listener(run_loop.QuitClosure());
rockot7c6bf952016-07-14 00:34:11755 CreateChannel(&listener);
756 ASSERT_TRUE(ConnectChannel());
757
758 listener.RegisterInterfaceFactory(channel());
759
Wezfdb98482018-07-12 01:21:39760 run_loop.Run();
rockot7c6bf952016-07-14 00:34:11761 channel()->Close();
762
763 EXPECT_TRUE(WaitForClientShutdown());
764 DestroyChannel();
765}
766
sammc4bcc4ed62016-10-27 10:13:59767DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(SimpleAssociatedInterfaceClient) {
Wezfdb98482018-07-12 01:21:39768 base::RunLoop run_loop;
769 ListenerSendingAssociatedMessages listener(run_loop.QuitClosure());
rockot7c6bf952016-07-14 00:34:11770 Connect(&listener);
771 listener.set_channel(channel());
772
Wezfdb98482018-07-12 01:21:39773 run_loop.Run();
rockot7c6bf952016-07-14 00:34:11774
775 Close();
776}
777
rockot8d890f62016-07-14 16:37:14778class ChannelProxyRunner {
779 public:
rockota34707ca2016-07-20 04:28:32780 ChannelProxyRunner(mojo::ScopedMessagePipeHandle handle,
781 bool for_server)
782 : for_server_(for_server),
783 handle_(std::move(handle)),
rockot9abe09b2016-08-02 20:57:34784 io_thread_("ChannelProxyRunner IO thread"),
785 never_signaled_(base::WaitableEvent::ResetPolicy::MANUAL,
786 base::WaitableEvent::InitialState::NOT_SIGNALED) {
rockot8d890f62016-07-14 16:37:14787 }
788
789 void CreateProxy(IPC::Listener* listener) {
790 io_thread_.StartWithOptions(
Carlos Caballerodd8bf7b042019-07-30 14:14:15791 base::Thread::Options(base::MessagePumpType::IO, 0));
Hajime Hoshiff15e972017-11-09 06:37:09792 proxy_ = IPC::SyncChannel::Create(listener, io_thread_.task_runner(),
793 base::ThreadTaskRunnerHandle::Get(),
794 &never_signaled_);
rockot8d890f62016-07-14 16:37:14795 }
rockota34707ca2016-07-20 04:28:32796
rockot10188752016-09-08 18:24:56797 void RunProxy() {
rockota34707ca2016-07-20 04:28:32798 std::unique_ptr<IPC::ChannelFactory> factory;
799 if (for_server_) {
800 factory = IPC::ChannelMojo::CreateServerFactory(
Hajime Hoshia98f1102017-11-20 06:34:35801 std::move(handle_), io_thread_.task_runner(),
802 base::ThreadTaskRunnerHandle::Get());
rockota34707ca2016-07-20 04:28:32803 } else {
804 factory = IPC::ChannelMojo::CreateClientFactory(
Hajime Hoshia98f1102017-11-20 06:34:35805 std::move(handle_), io_thread_.task_runner(),
806 base::ThreadTaskRunnerHandle::Get());
rockota34707ca2016-07-20 04:28:32807 }
rockot10188752016-09-08 18:24:56808 proxy_->Init(std::move(factory), true);
rockota34707ca2016-07-20 04:28:32809 }
rockot8d890f62016-07-14 16:37:14810
811 IPC::ChannelProxy* proxy() { return proxy_.get(); }
812
813 private:
rockota34707ca2016-07-20 04:28:32814 const bool for_server_;
rockot8d890f62016-07-14 16:37:14815
rockota34707ca2016-07-20 04:28:32816 mojo::ScopedMessagePipeHandle handle_;
rockot8d890f62016-07-14 16:37:14817 base::Thread io_thread_;
rockot9abe09b2016-08-02 20:57:34818 base::WaitableEvent never_signaled_;
rockotb62e2e32017-03-24 18:36:44819 std::unique_ptr<IPC::ChannelProxy> proxy_;
rockot8d890f62016-07-14 16:37:14820
821 DISALLOW_COPY_AND_ASSIGN(ChannelProxyRunner);
822};
823
824class IPCChannelProxyMojoTest : public IPCChannelMojoTestBase {
825 public:
sammc4bcc4ed62016-10-27 10:13:59826 void Init(const std::string& client_name) {
827 IPCChannelMojoTestBase::Init(client_name);
rockota34707ca2016-07-20 04:28:32828 runner_.reset(new ChannelProxyRunner(TakeHandle(), true));
rockot8d890f62016-07-14 16:37:14829 }
830 void CreateProxy(IPC::Listener* listener) { runner_->CreateProxy(listener); }
rockot10188752016-09-08 18:24:56831 void RunProxy() {
832 runner_->RunProxy();
rockot401fb2c2016-09-06 18:35:57833 }
rockot0e4de5f2016-07-22 21:18:07834 void DestroyProxy() {
835 runner_.reset();
836 base::RunLoop().RunUntilIdle();
837 }
rockot8d890f62016-07-14 16:37:14838
839 IPC::ChannelProxy* proxy() { return runner_->proxy(); }
840
841 private:
rockot8d890f62016-07-14 16:37:14842 std::unique_ptr<ChannelProxyRunner> runner_;
843};
844
845class ListenerWithSimpleProxyAssociatedInterface
846 : public IPC::Listener,
847 public IPC::mojom::SimpleTestDriver {
848 public:
849 static const int kNumMessages;
850
Wezfdb98482018-07-12 01:21:39851 explicit ListenerWithSimpleProxyAssociatedInterface(
852 base::OnceClosure quit_closure)
853 : quit_closure_(std::move(quit_closure)), binding_(this) {}
rockot8d890f62016-07-14 16:37:14854
Chris Watkins2d879af2017-11-30 02:11:59855 ~ListenerWithSimpleProxyAssociatedInterface() override = default;
rockot8d890f62016-07-14 16:37:14856
857 bool OnMessageReceived(const IPC::Message& message) override {
858 base::PickleIterator iter(message);
rockot9abe09b2016-08-02 20:57:34859 int32_t should_be_expected;
860 EXPECT_TRUE(iter.ReadInt(&should_be_expected));
861 EXPECT_EQ(should_be_expected, next_expected_value_);
rockot8d890f62016-07-14 16:37:14862 num_messages_received_++;
863 return true;
864 }
865
Wezfdb98482018-07-12 01:21:39866 void OnChannelError() override { CHECK(!quit_closure_); }
rockot8d890f62016-07-14 16:37:14867
rockotf62002a2016-09-15 00:08:59868 void OnAssociatedInterfaceRequest(
869 const std::string& interface_name,
870 mojo::ScopedInterfaceEndpointHandle handle) override {
871 DCHECK_EQ(interface_name, IPC::mojom::SimpleTestDriver::Name_);
Ken Rockot96d1b7b52017-05-13 00:29:21872 binding_.Bind(
873 IPC::mojom::SimpleTestDriverAssociatedRequest(std::move(handle)));
rockot8d890f62016-07-14 16:37:14874 }
875
876 bool received_all_messages() const {
Wezfdb98482018-07-12 01:21:39877 return num_messages_received_ == kNumMessages && !quit_closure_;
rockot8d890f62016-07-14 16:37:14878 }
879
880 private:
881 // IPC::mojom::SimpleTestDriver:
rockot9abe09b2016-08-02 20:57:34882 void ExpectValue(int32_t value) override {
883 next_expected_value_ = value;
884 }
885
tzikdd76ce712017-06-08 05:27:04886 void GetExpectedValue(GetExpectedValueCallback callback) override {
887 std::move(callback).Run(next_expected_value_);
rockot9abe09b2016-08-02 20:57:34888 }
889
tzikdd76ce712017-06-08 05:27:04890 void RequestValue(RequestValueCallback callback) override { NOTREACHED(); }
rockot8d890f62016-07-14 16:37:14891
tzikdd76ce712017-06-08 05:27:04892 void RequestQuit(RequestQuitCallback callback) override {
tzikdd76ce712017-06-08 05:27:04893 std::move(callback).Run();
rockot0e4de5f2016-07-22 21:18:07894 binding_.Close();
Wezfdb98482018-07-12 01:21:39895 std::move(quit_closure_).Run();
rockot8d890f62016-07-14 16:37:14896 }
897
898 void BindRequest(IPC::mojom::SimpleTestDriverAssociatedRequest request) {
899 DCHECK(!binding_.is_bound());
900 binding_.Bind(std::move(request));
901 }
902
rockot9abe09b2016-08-02 20:57:34903 int32_t next_expected_value_ = 0;
rockot8d890f62016-07-14 16:37:14904 int num_messages_received_ = 0;
Wezfdb98482018-07-12 01:21:39905 base::OnceClosure quit_closure_;
rockot8d890f62016-07-14 16:37:14906
907 mojo::AssociatedBinding<IPC::mojom::SimpleTestDriver> binding_;
908};
909
910const int ListenerWithSimpleProxyAssociatedInterface::kNumMessages = 1000;
911
912TEST_F(IPCChannelProxyMojoTest, ProxyThreadAssociatedInterface) {
sammc4bcc4ed62016-10-27 10:13:59913 Init("ProxyThreadAssociatedInterfaceClient");
rockot8d890f62016-07-14 16:37:14914
Wezfdb98482018-07-12 01:21:39915 base::RunLoop run_loop;
916 ListenerWithSimpleProxyAssociatedInterface listener(run_loop.QuitClosure());
rockot8d890f62016-07-14 16:37:14917 CreateProxy(&listener);
rockot8d890f62016-07-14 16:37:14918 RunProxy();
919
Wezfdb98482018-07-12 01:21:39920 run_loop.Run();
rockot8d890f62016-07-14 16:37:14921
922 EXPECT_TRUE(WaitForClientShutdown());
923 EXPECT_TRUE(listener.received_all_messages());
924
rockot0e4de5f2016-07-22 21:18:07925 DestroyProxy();
rockot8d890f62016-07-14 16:37:14926}
927
928class ChannelProxyClient {
929 public:
930 void Init(mojo::ScopedMessagePipeHandle handle) {
rockota34707ca2016-07-20 04:28:32931 runner_.reset(new ChannelProxyRunner(std::move(handle), false));
rockot8d890f62016-07-14 16:37:14932 }
rockot9abe09b2016-08-02 20:57:34933
rockot8d890f62016-07-14 16:37:14934 void CreateProxy(IPC::Listener* listener) { runner_->CreateProxy(listener); }
rockot9abe09b2016-08-02 20:57:34935
rockot10188752016-09-08 18:24:56936 void RunProxy() { runner_->RunProxy(); }
rockot9abe09b2016-08-02 20:57:34937
rockot0e4de5f2016-07-22 21:18:07938 void DestroyProxy() {
939 runner_.reset();
940 base::RunLoop().RunUntilIdle();
941 }
rockot8d890f62016-07-14 16:37:14942
rockot9abe09b2016-08-02 20:57:34943 void RequestQuitAndWaitForAck(IPC::mojom::SimpleTestDriver* driver) {
944 base::RunLoop loop;
945 driver->RequestQuit(loop.QuitClosure());
946 loop.Run();
947 }
948
rockot8d890f62016-07-14 16:37:14949 IPC::ChannelProxy* proxy() { return runner_->proxy(); }
950
951 private:
Gabriel Charettedfa36042019-08-19 17:30:11952 base::test::TaskEnvironment task_environment_;
rockot8d890f62016-07-14 16:37:14953 std::unique_ptr<ChannelProxyRunner> runner_;
954};
955
rockot0e4de5f2016-07-22 21:18:07956class DummyListener : public IPC::Listener {
rockot8d890f62016-07-14 16:37:14957 public:
rockot8d890f62016-07-14 16:37:14958 // IPC::Listener
959 bool OnMessageReceived(const IPC::Message& message) override { return true; }
rockot8d890f62016-07-14 16:37:14960};
961
sammc4bcc4ed62016-10-27 10:13:59962DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
963 ProxyThreadAssociatedInterfaceClient,
964 ChannelProxyClient) {
rockot0e4de5f2016-07-22 21:18:07965 DummyListener listener;
rockot8d890f62016-07-14 16:37:14966 CreateProxy(&listener);
967 RunProxy();
rockot8d890f62016-07-14 16:37:14968
969 // Send a bunch of interleaved messages, alternating between the associated
970 // interface and a legacy IPC::Message.
971 IPC::mojom::SimpleTestDriverAssociatedPtr driver;
972 proxy()->GetRemoteAssociatedInterface(&driver);
973 for (int i = 0; i < ListenerWithSimpleProxyAssociatedInterface::kNumMessages;
974 ++i) {
rockot9abe09b2016-08-02 20:57:34975 driver->ExpectValue(i);
976 SendValue(proxy(), i);
rockot8d890f62016-07-14 16:37:14977 }
Wezfdb98482018-07-12 01:21:39978 base::RunLoop run_loop;
979 driver->RequestQuit(run_loop.QuitClosure());
980 run_loop.Run();
rockot0e4de5f2016-07-22 21:18:07981
982 DestroyProxy();
rockot8d890f62016-07-14 16:37:14983}
984
rockot401fb2c2016-09-06 18:35:57985class ListenerWithIndirectProxyAssociatedInterface
986 : public IPC::Listener,
987 public IPC::mojom::IndirectTestDriver,
988 public IPC::mojom::PingReceiver {
989 public:
990 ListenerWithIndirectProxyAssociatedInterface()
991 : driver_binding_(this), ping_receiver_binding_(this) {}
Chris Watkins2d879af2017-11-30 02:11:59992 ~ListenerWithIndirectProxyAssociatedInterface() override = default;
rockot401fb2c2016-09-06 18:35:57993
rockot70bbb59492017-01-25 00:56:51994 // IPC::Listener:
rockot401fb2c2016-09-06 18:35:57995 bool OnMessageReceived(const IPC::Message& message) override { return true; }
996
rockot70bbb59492017-01-25 00:56:51997 void OnAssociatedInterfaceRequest(
998 const std::string& interface_name,
999 mojo::ScopedInterfaceEndpointHandle handle) override {
1000 DCHECK(!driver_binding_.is_bound());
1001 DCHECK_EQ(interface_name, IPC::mojom::IndirectTestDriver::Name_);
Ken Rockot96d1b7b52017-05-13 00:29:211002 driver_binding_.Bind(
1003 IPC::mojom::IndirectTestDriverAssociatedRequest(std::move(handle)));
rockot401fb2c2016-09-06 18:35:571004 }
1005
Wezfdb98482018-07-12 01:21:391006 void set_ping_handler(const base::RepeatingClosure& handler) {
rockot401fb2c2016-09-06 18:35:571007 ping_handler_ = handler;
1008 }
1009
1010 private:
1011 // IPC::mojom::IndirectTestDriver:
1012 void GetPingReceiver(
1013 IPC::mojom::PingReceiverAssociatedRequest request) override {
1014 ping_receiver_binding_.Bind(std::move(request));
1015 }
1016
1017 // IPC::mojom::PingReceiver:
tzikdd76ce712017-06-08 05:27:041018 void Ping(PingCallback callback) override {
1019 std::move(callback).Run();
rockot401fb2c2016-09-06 18:35:571020 ping_handler_.Run();
1021 }
1022
rockot401fb2c2016-09-06 18:35:571023 mojo::AssociatedBinding<IPC::mojom::IndirectTestDriver> driver_binding_;
1024 mojo::AssociatedBinding<IPC::mojom::PingReceiver> ping_receiver_binding_;
1025
Wezfdb98482018-07-12 01:21:391026 base::RepeatingClosure ping_handler_;
rockot401fb2c2016-09-06 18:35:571027};
1028
1029TEST_F(IPCChannelProxyMojoTest, ProxyThreadAssociatedInterfaceIndirect) {
1030 // Tests that we can pipeline interface requests and subsequent messages
1031 // targeting proxy thread bindings, and the channel will still dispatch
1032 // messages appropriately.
1033
sammc4bcc4ed62016-10-27 10:13:591034 Init("ProxyThreadAssociatedInterfaceIndirectClient");
rockot401fb2c2016-09-06 18:35:571035
1036 ListenerWithIndirectProxyAssociatedInterface listener;
1037 CreateProxy(&listener);
rockot401fb2c2016-09-06 18:35:571038 RunProxy();
1039
1040 base::RunLoop loop;
1041 listener.set_ping_handler(loop.QuitClosure());
1042 loop.Run();
1043
1044 EXPECT_TRUE(WaitForClientShutdown());
1045
1046 DestroyProxy();
1047}
1048
sammc4bcc4ed62016-10-27 10:13:591049DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
rockot401fb2c2016-09-06 18:35:571050 ProxyThreadAssociatedInterfaceIndirectClient,
1051 ChannelProxyClient) {
1052 DummyListener listener;
1053 CreateProxy(&listener);
1054 RunProxy();
1055
1056 // Use an interface requested via another interface. On the remote end both
1057 // interfaces are bound on the proxy thread. This ensures that the Ping
1058 // message we send will still be dispatched properly even though the remote
1059 // endpoint may not have been bound yet by the time the message is initially
1060 // processed on the IO thread.
1061 IPC::mojom::IndirectTestDriverAssociatedPtr driver;
1062 IPC::mojom::PingReceiverAssociatedPtr ping_receiver;
1063 proxy()->GetRemoteAssociatedInterface(&driver);
yzshen1aa8e56c2017-02-16 23:15:451064 driver->GetPingReceiver(mojo::MakeRequest(&ping_receiver));
rockot401fb2c2016-09-06 18:35:571065
1066 base::RunLoop loop;
1067 ping_receiver->Ping(loop.QuitClosure());
1068 loop.Run();
1069
1070 DestroyProxy();
1071}
1072
rockot9abe09b2016-08-02 20:57:341073class ListenerWithSyncAssociatedInterface
1074 : public IPC::Listener,
1075 public IPC::mojom::SimpleTestDriver {
1076 public:
1077 ListenerWithSyncAssociatedInterface() : binding_(this) {}
Chris Watkins2d879af2017-11-30 02:11:591078 ~ListenerWithSyncAssociatedInterface() override = default;
rockot9abe09b2016-08-02 20:57:341079
1080 void set_sync_sender(IPC::Sender* sync_sender) { sync_sender_ = sync_sender; }
1081
rockot9abe09b2016-08-02 20:57:341082 void RunUntilQuitRequested() {
1083 base::RunLoop loop;
1084 quit_closure_ = loop.QuitClosure();
1085 loop.Run();
1086 }
1087
1088 void CloseBinding() { binding_.Close(); }
1089
1090 void set_response_value(int32_t response) {
1091 response_value_ = response;
1092 }
1093
1094 private:
1095 // IPC::mojom::SimpleTestDriver:
1096 void ExpectValue(int32_t value) override {
1097 next_expected_value_ = value;
1098 }
1099
tzikdd76ce712017-06-08 05:27:041100 void GetExpectedValue(GetExpectedValueCallback callback) override {
1101 std::move(callback).Run(next_expected_value_);
rockot9abe09b2016-08-02 20:57:341102 }
1103
tzikdd76ce712017-06-08 05:27:041104 void RequestValue(RequestValueCallback callback) override {
1105 std::move(callback).Run(response_value_);
rockot9abe09b2016-08-02 20:57:341106 }
1107
tzikdd76ce712017-06-08 05:27:041108 void RequestQuit(RequestQuitCallback callback) override {
Wezfdb98482018-07-12 01:21:391109 std::move(quit_closure_).Run();
tzikdd76ce712017-06-08 05:27:041110 std::move(callback).Run();
rockot9abe09b2016-08-02 20:57:341111 }
1112
1113 // IPC::Listener:
1114 bool OnMessageReceived(const IPC::Message& message) override {
1115 EXPECT_EQ(0u, message.type());
1116 EXPECT_TRUE(message.is_sync());
1117 EXPECT_TRUE(message.should_unblock());
1118 std::unique_ptr<IPC::Message> reply(
1119 IPC::SyncMessage::GenerateReply(&message));
1120 reply->WriteInt(response_value_);
1121 DCHECK(sync_sender_);
1122 EXPECT_TRUE(sync_sender_->Send(reply.release()));
1123 return true;
1124 }
1125
rockot70bbb59492017-01-25 00:56:511126 void OnAssociatedInterfaceRequest(
1127 const std::string& interface_name,
1128 mojo::ScopedInterfaceEndpointHandle handle) override {
1129 DCHECK(!binding_.is_bound());
1130 DCHECK_EQ(interface_name, IPC::mojom::SimpleTestDriver::Name_);
Ken Rockot96d1b7b52017-05-13 00:29:211131 binding_.Bind(
1132 IPC::mojom::SimpleTestDriverAssociatedRequest(std::move(handle)));
rockot70bbb59492017-01-25 00:56:511133 }
1134
rockot9abe09b2016-08-02 20:57:341135 void BindRequest(IPC::mojom::SimpleTestDriverAssociatedRequest request) {
1136 DCHECK(!binding_.is_bound());
1137 binding_.Bind(std::move(request));
1138 }
1139
1140 IPC::Sender* sync_sender_ = nullptr;
1141 int32_t next_expected_value_ = 0;
1142 int32_t response_value_ = 0;
Wezfdb98482018-07-12 01:21:391143 base::OnceClosure quit_closure_;
rockot9abe09b2016-08-02 20:57:341144
1145 mojo::AssociatedBinding<IPC::mojom::SimpleTestDriver> binding_;
1146};
1147
1148class SyncReplyReader : public IPC::MessageReplyDeserializer {
1149 public:
1150 explicit SyncReplyReader(int32_t* storage) : storage_(storage) {}
Chris Watkins2d879af2017-11-30 02:11:591151 ~SyncReplyReader() override = default;
rockot9abe09b2016-08-02 20:57:341152
1153 private:
1154 // IPC::MessageReplyDeserializer:
1155 bool SerializeOutputParameters(const IPC::Message& message,
1156 base::PickleIterator iter) override {
1157 if (!iter.ReadInt(storage_))
1158 return false;
1159 return true;
1160 }
1161
1162 int32_t* storage_;
1163
1164 DISALLOW_COPY_AND_ASSIGN(SyncReplyReader);
1165};
1166
1167TEST_F(IPCChannelProxyMojoTest, SyncAssociatedInterface) {
sammc4bcc4ed62016-10-27 10:13:591168 Init("SyncAssociatedInterface");
rockot9abe09b2016-08-02 20:57:341169
1170 ListenerWithSyncAssociatedInterface listener;
1171 CreateProxy(&listener);
1172 listener.set_sync_sender(proxy());
rockot9abe09b2016-08-02 20:57:341173 RunProxy();
1174
1175 // Run the client's simple sanity check to completion.
1176 listener.RunUntilQuitRequested();
1177
1178 // Verify that we can send a sync IPC and service an incoming sync request
1179 // while waiting on it
1180 listener.set_response_value(42);
1181 IPC::mojom::SimpleTestClientAssociatedPtr client;
1182 proxy()->GetRemoteAssociatedInterface(&client);
1183 int32_t received_value;
1184 EXPECT_TRUE(client->RequestValue(&received_value));
1185 EXPECT_EQ(42, received_value);
1186
1187 // Do it again. This time the client will send a classical sync IPC to us
1188 // while we wait.
1189 received_value = 0;
1190 EXPECT_TRUE(client->RequestValue(&received_value));
1191 EXPECT_EQ(42, received_value);
1192
1193 // Now make a classical sync IPC request to the client. It will send a
1194 // sync associated interface message to us while we wait.
1195 received_value = 0;
1196 std::unique_ptr<IPC::SyncMessage> request(
1197 new IPC::SyncMessage(0, 0, IPC::Message::PRIORITY_NORMAL,
1198 new SyncReplyReader(&received_value)));
1199 EXPECT_TRUE(proxy()->Send(request.release()));
1200 EXPECT_EQ(42, received_value);
1201
1202 listener.CloseBinding();
1203 EXPECT_TRUE(WaitForClientShutdown());
1204
1205 DestroyProxy();
1206}
1207
1208class SimpleTestClientImpl : public IPC::mojom::SimpleTestClient,
1209 public IPC::Listener {
1210 public:
1211 SimpleTestClientImpl() : binding_(this) {}
1212
1213 void set_driver(IPC::mojom::SimpleTestDriver* driver) { driver_ = driver; }
1214 void set_sync_sender(IPC::Sender* sync_sender) { sync_sender_ = sync_sender; }
1215
rockot9abe09b2016-08-02 20:57:341216 void WaitForValueRequest() {
1217 run_loop_.reset(new base::RunLoop);
1218 run_loop_->Run();
1219 }
1220
1221 void UseSyncSenderForRequest(bool use_sync_sender) {
1222 use_sync_sender_ = use_sync_sender;
1223 }
1224
1225 private:
1226 // IPC::mojom::SimpleTestClient:
tzikdd76ce712017-06-08 05:27:041227 void RequestValue(RequestValueCallback callback) override {
rockot9abe09b2016-08-02 20:57:341228 int32_t response = 0;
1229 if (use_sync_sender_) {
1230 std::unique_ptr<IPC::SyncMessage> reply(new IPC::SyncMessage(
1231 0, 0, IPC::Message::PRIORITY_NORMAL, new SyncReplyReader(&response)));
1232 EXPECT_TRUE(sync_sender_->Send(reply.release()));
1233 } else {
1234 DCHECK(driver_);
1235 EXPECT_TRUE(driver_->RequestValue(&response));
1236 }
1237
tzikdd76ce712017-06-08 05:27:041238 std::move(callback).Run(response);
rockot9abe09b2016-08-02 20:57:341239
1240 DCHECK(run_loop_);
1241 run_loop_->Quit();
1242 }
1243
1244 // IPC::Listener:
1245 bool OnMessageReceived(const IPC::Message& message) override {
1246 int32_t response;
1247 DCHECK(driver_);
1248 EXPECT_TRUE(driver_->RequestValue(&response));
1249 std::unique_ptr<IPC::Message> reply(
1250 IPC::SyncMessage::GenerateReply(&message));
1251 reply->WriteInt(response);
1252 EXPECT_TRUE(sync_sender_->Send(reply.release()));
1253
1254 DCHECK(run_loop_);
1255 run_loop_->Quit();
1256 return true;
1257 }
1258
rockot70bbb59492017-01-25 00:56:511259 void OnAssociatedInterfaceRequest(
1260 const std::string& interface_name,
1261 mojo::ScopedInterfaceEndpointHandle handle) override {
1262 DCHECK(!binding_.is_bound());
1263 DCHECK_EQ(interface_name, IPC::mojom::SimpleTestClient::Name_);
1264
Ken Rockot96d1b7b52017-05-13 00:29:211265 binding_.Bind(
1266 IPC::mojom::SimpleTestClientAssociatedRequest(std::move(handle)));
rockot70bbb59492017-01-25 00:56:511267 }
1268
rockot9abe09b2016-08-02 20:57:341269 bool use_sync_sender_ = false;
1270 mojo::AssociatedBinding<IPC::mojom::SimpleTestClient> binding_;
1271 IPC::Sender* sync_sender_ = nullptr;
1272 IPC::mojom::SimpleTestDriver* driver_ = nullptr;
1273 std::unique_ptr<base::RunLoop> run_loop_;
1274
1275 DISALLOW_COPY_AND_ASSIGN(SimpleTestClientImpl);
1276};
1277
sammc4bcc4ed62016-10-27 10:13:591278DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(SyncAssociatedInterface,
1279 ChannelProxyClient) {
rockot9abe09b2016-08-02 20:57:341280 SimpleTestClientImpl client_impl;
1281 CreateProxy(&client_impl);
1282 client_impl.set_sync_sender(proxy());
rockot9abe09b2016-08-02 20:57:341283 RunProxy();
1284
1285 IPC::mojom::SimpleTestDriverAssociatedPtr driver;
1286 proxy()->GetRemoteAssociatedInterface(&driver);
1287 client_impl.set_driver(driver.get());
1288
1289 // Simple sync message sanity check.
1290 driver->ExpectValue(42);
1291 int32_t expected_value = 0;
1292 EXPECT_TRUE(driver->GetExpectedValue(&expected_value));
1293 EXPECT_EQ(42, expected_value);
1294 RequestQuitAndWaitForAck(driver.get());
1295
1296 // Wait for the test driver to perform a sync call test with our own sync
1297 // associated interface message nested inside.
1298 client_impl.UseSyncSenderForRequest(false);
1299 client_impl.WaitForValueRequest();
1300
1301 // Wait for the test driver to perform a sync call test with our own classical
1302 // sync IPC nested inside.
1303 client_impl.UseSyncSenderForRequest(true);
1304 client_impl.WaitForValueRequest();
1305
1306 // Wait for the test driver to perform a classical sync IPC request, with our
1307 // own sync associated interface message nested inside.
1308 client_impl.UseSyncSenderForRequest(false);
1309 client_impl.WaitForValueRequest();
1310
1311 DestroyProxy();
1312}
1313
rockot10188752016-09-08 18:24:561314TEST_F(IPCChannelProxyMojoTest, Pause) {
1315 // Ensures that pausing a channel elicits the expected behavior when sending
1316 // messages, unpausing, sending more messages, and then manually flushing.
1317 // Specifically a sequence like:
rockot401fb2c2016-09-06 18:35:571318 //
1319 // Connect()
1320 // Send(A)
rockot10188752016-09-08 18:24:561321 // Pause()
rockot401fb2c2016-09-06 18:35:571322 // Send(B)
rockot401fb2c2016-09-06 18:35:571323 // Send(C)
rockot10188752016-09-08 18:24:561324 // Unpause(false)
1325 // Send(D)
1326 // Send(E)
rockot401fb2c2016-09-06 18:35:571327 // Flush()
1328 //
rockot10188752016-09-08 18:24:561329 // must result in the other end receiving messages A, D, E, B, D; in that
rockot401fb2c2016-09-06 18:35:571330 // order.
1331 //
1332 // This behavior is required by some consumers of IPC::Channel, and it is not
1333 // sufficient to leave this up to the consumer to implement since associated
1334 // interface requests and messages also need to be queued according to the
1335 // same policy.
sammc4bcc4ed62016-10-27 10:13:591336 Init("CreatePausedClient");
rockot401fb2c2016-09-06 18:35:571337
1338 DummyListener listener;
1339 CreateProxy(&listener);
rockot10188752016-09-08 18:24:561340 RunProxy();
1341
1342 // This message must be sent immediately since the channel is unpaused.
1343 SendValue(proxy(), 1);
1344
1345 proxy()->Pause();
rockot401fb2c2016-09-06 18:35:571346
1347 // These messages must be queued internally since the channel is paused.
rockot401fb2c2016-09-06 18:35:571348 SendValue(proxy(), 2);
rockot10188752016-09-08 18:24:561349 SendValue(proxy(), 3);
rockot401fb2c2016-09-06 18:35:571350
1351 proxy()->Unpause(false /* flush */);
1352
1353 // These messages must be sent immediately since the channel is unpaused.
rockot401fb2c2016-09-06 18:35:571354 SendValue(proxy(), 4);
rockot10188752016-09-08 18:24:561355 SendValue(proxy(), 5);
rockot401fb2c2016-09-06 18:35:571356
1357 // Now we flush the previously queued messages.
1358 proxy()->Flush();
1359
1360 EXPECT_TRUE(WaitForClientShutdown());
1361 DestroyProxy();
1362}
1363
1364class ExpectValueSequenceListener : public IPC::Listener {
1365 public:
Wezfdb98482018-07-12 01:21:391366 ExpectValueSequenceListener(base::queue<int32_t>* expected_values,
1367 base::OnceClosure quit_closure)
1368 : expected_values_(expected_values),
1369 quit_closure_(std::move(quit_closure)) {}
Chris Watkins2d879af2017-11-30 02:11:591370 ~ExpectValueSequenceListener() override = default;
rockot401fb2c2016-09-06 18:35:571371
1372 // IPC::Listener:
1373 bool OnMessageReceived(const IPC::Message& message) override {
1374 DCHECK(!expected_values_->empty());
1375 base::PickleIterator iter(message);
1376 int32_t should_be_expected;
1377 EXPECT_TRUE(iter.ReadInt(&should_be_expected));
1378 EXPECT_EQ(expected_values_->front(), should_be_expected);
1379 expected_values_->pop();
1380 if (expected_values_->empty())
Wezfdb98482018-07-12 01:21:391381 std::move(quit_closure_).Run();
rockot401fb2c2016-09-06 18:35:571382 return true;
1383 }
1384
1385 private:
Brett Wilsona62d9c02017-09-20 20:53:201386 base::queue<int32_t>* expected_values_;
Wezfdb98482018-07-12 01:21:391387 base::OnceClosure quit_closure_;
rockot401fb2c2016-09-06 18:35:571388
1389 DISALLOW_COPY_AND_ASSIGN(ExpectValueSequenceListener);
1390};
1391
sammc4bcc4ed62016-10-27 10:13:591392DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(CreatePausedClient,
1393 ChannelProxyClient) {
Brett Wilsona62d9c02017-09-20 20:53:201394 base::queue<int32_t> expected_values;
Wezfdb98482018-07-12 01:21:391395 base::RunLoop run_loop;
1396 ExpectValueSequenceListener listener(&expected_values,
1397 run_loop.QuitClosure());
rockot401fb2c2016-09-06 18:35:571398 CreateProxy(&listener);
rockot401fb2c2016-09-06 18:35:571399 expected_values.push(1);
rockot10188752016-09-08 18:24:561400 expected_values.push(4);
1401 expected_values.push(5);
rockot401fb2c2016-09-06 18:35:571402 expected_values.push(2);
rockot10188752016-09-08 18:24:561403 expected_values.push(3);
rockot401fb2c2016-09-06 18:35:571404 RunProxy();
Wezfdb98482018-07-12 01:21:391405 run_loop.Run();
rockot401fb2c2016-09-06 18:35:571406 EXPECT_TRUE(expected_values.empty());
1407 DestroyProxy();
1408}
1409
sammc5c8a6c62017-02-04 01:33:381410TEST_F(IPCChannelProxyMojoTest, AssociatedRequestClose) {
1411 Init("DropAssociatedRequest");
1412
1413 DummyListener listener;
1414 CreateProxy(&listener);
1415 RunProxy();
1416
1417 IPC::mojom::AssociatedInterfaceVendorAssociatedPtr vendor;
1418 proxy()->GetRemoteAssociatedInterface(&vendor);
1419 IPC::mojom::SimpleTestDriverAssociatedPtr tester;
yzshen1aa8e56c2017-02-16 23:15:451420 vendor->GetTestInterface(mojo::MakeRequest(&tester));
sammc5c8a6c62017-02-04 01:33:381421 base::RunLoop run_loop;
1422 tester.set_connection_error_handler(run_loop.QuitClosure());
1423 run_loop.Run();
1424
1425 proxy()->GetRemoteAssociatedInterface(&tester);
1426 EXPECT_TRUE(WaitForClientShutdown());
1427 DestroyProxy();
1428}
1429
1430class AssociatedInterfaceDroppingListener : public IPC::Listener {
1431 public:
Wezfdb98482018-07-12 01:21:391432 AssociatedInterfaceDroppingListener(base::OnceClosure callback)
1433 : callback_(std::move(callback)) {}
sammc5c8a6c62017-02-04 01:33:381434 bool OnMessageReceived(const IPC::Message& message) override { return false; }
1435
1436 void OnAssociatedInterfaceRequest(
1437 const std::string& interface_name,
1438 mojo::ScopedInterfaceEndpointHandle handle) override {
1439 if (interface_name == IPC::mojom::SimpleTestDriver::Name_)
Wezfdb98482018-07-12 01:21:391440 std::move(callback_).Run();
sammc5c8a6c62017-02-04 01:33:381441 }
1442
1443 private:
Wezfdb98482018-07-12 01:21:391444 base::OnceClosure callback_;
sammc5c8a6c62017-02-04 01:33:381445};
1446
1447DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(DropAssociatedRequest,
1448 ChannelProxyClient) {
1449 base::RunLoop run_loop;
1450 AssociatedInterfaceDroppingListener listener(run_loop.QuitClosure());
1451 CreateProxy(&listener);
1452 RunProxy();
1453 run_loop.Run();
1454 DestroyProxy();
1455}
1456
Wez831ae412017-08-30 00:29:361457#if !defined(OS_MACOSX)
1458// TODO(wez): On Mac we need to set up a MachPortBroker before we can transfer
1459// Mach ports (which underpin Sharedmemory on Mac) across IPC.
1460
1461class ListenerThatExpectsSharedMemory : public TestListenerBase {
1462 public:
Wezfdb98482018-07-12 01:21:391463 ListenerThatExpectsSharedMemory(base::OnceClosure quit_closure)
1464 : TestListenerBase(std::move(quit_closure)) {}
Wez831ae412017-08-30 00:29:361465
1466 bool OnMessageReceived(const IPC::Message& message) override {
1467 base::PickleIterator iter(message);
1468
1469 base::SharedMemoryHandle shared_memory;
1470 EXPECT_TRUE(IPC::ReadParam(&message, &iter, &shared_memory));
1471 EXPECT_TRUE(shared_memory.IsValid());
1472 shared_memory.Close();
1473
1474 ListenerThatExpectsOK::SendOK(sender());
1475 return true;
1476 }
1477};
1478
1479TEST_F(IPCChannelMojoTest, SendSharedMemory) {
1480 Init("IPCChannelMojoTestSendSharedMemoryClient");
1481
1482 // Create some shared-memory to share.
1483 base::SharedMemoryCreateOptions options;
1484 options.size = 1004;
1485
1486 base::SharedMemory shmem;
1487 ASSERT_TRUE(shmem.Create(options));
1488
1489 // Create a success listener, and launch the child process.
1490 base::RunLoop run_loop;
1491 ListenerThatExpectsOK listener(run_loop.QuitClosure());
1492 CreateChannel(&listener);
1493 ASSERT_TRUE(ConnectChannel());
1494
1495 // Send the child process an IPC with |shmem| attached, to verify
1496 // that is is correctly wrapped, transferred and unwrapped.
1497 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
1498 IPC::WriteParam(message, shmem.handle());
1499 ASSERT_TRUE(channel()->Send(message));
1500
1501 run_loop.Run();
1502
1503 channel()->Close();
1504
1505 EXPECT_TRUE(WaitForClientShutdown());
1506 DestroyChannel();
1507}
1508
1509DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendSharedMemoryClient) {
1510 base::RunLoop run_loop;
1511 ListenerThatExpectsSharedMemory listener(run_loop.QuitClosure());
1512 Connect(&listener);
1513 listener.set_sender(channel());
1514
1515 run_loop.Run();
1516
1517 Close();
1518}
1519
Alexandr Ilind497eee2018-04-19 22:50:541520template <class SharedMemoryRegionType>
1521class IPCChannelMojoSharedMemoryRegionTypedTest : public IPCChannelMojoTest {};
1522
1523struct WritableRegionTraits {
1524 using RegionType = base::WritableSharedMemoryRegion;
1525 static const char kClientName[];
1526};
1527const char WritableRegionTraits::kClientName[] =
1528 "IPCChannelMojoTestSendWritableSharedMemoryRegionClient";
1529struct UnsafeRegionTraits {
1530 using RegionType = base::UnsafeSharedMemoryRegion;
1531 static const char kClientName[];
1532};
1533const char UnsafeRegionTraits::kClientName[] =
1534 "IPCChannelMojoTestSendUnsafeSharedMemoryRegionClient";
1535struct ReadOnlyRegionTraits {
1536 using RegionType = base::ReadOnlySharedMemoryRegion;
1537 static const char kClientName[];
1538};
1539const char ReadOnlyRegionTraits::kClientName[] =
1540 "IPCChannelMojoTestSendReadOnlySharedMemoryRegionClient";
1541
1542typedef ::testing::
1543 Types<WritableRegionTraits, UnsafeRegionTraits, ReadOnlyRegionTraits>
1544 AllSharedMemoryRegionTraits;
Victor Costanebc52732019-02-15 02:39:471545TYPED_TEST_SUITE(IPCChannelMojoSharedMemoryRegionTypedTest,
1546 AllSharedMemoryRegionTraits);
Alexandr Ilind497eee2018-04-19 22:50:541547
1548template <class SharedMemoryRegionType>
1549class ListenerThatExpectsSharedMemoryRegion : public TestListenerBase {
1550 public:
Wezfdb98482018-07-12 01:21:391551 explicit ListenerThatExpectsSharedMemoryRegion(base::OnceClosure quit_closure)
Alexandr Ilind497eee2018-04-19 22:50:541552 : TestListenerBase(std::move(quit_closure)) {}
1553
1554 bool OnMessageReceived(const IPC::Message& message) override {
1555 base::PickleIterator iter(message);
1556
1557 SharedMemoryRegionType region;
1558 EXPECT_TRUE(IPC::ReadParam(&message, &iter, &region));
1559 EXPECT_TRUE(region.IsValid());
1560
1561 // Verify the shared memory region has expected content.
1562 typename SharedMemoryRegionType::MappingType mapping = region.Map();
1563 std::string content = HandleSendingHelper::GetSendingFileContent();
1564 EXPECT_EQ(0, memcmp(mapping.memory(), content.data(), content.size()));
1565
1566 ListenerThatExpectsOK::SendOK(sender());
1567 return true;
1568 }
1569};
1570
1571TYPED_TEST(IPCChannelMojoSharedMemoryRegionTypedTest, Send) {
1572 this->Init(TypeParam::kClientName);
1573
1574 const size_t size = 1004;
1575 typename TypeParam::RegionType region;
1576 base::WritableSharedMemoryMapping mapping;
1577 std::tie(region, mapping) =
1578 base::CreateMappedRegion<typename TypeParam::RegionType>(size);
1579
1580 std::string content = HandleSendingHelper::GetSendingFileContent();
1581 memcpy(mapping.memory(), content.data(), content.size());
1582
1583 // Create a success listener, and launch the child process.
1584 base::RunLoop run_loop;
1585 ListenerThatExpectsOK listener(run_loop.QuitClosure());
1586 this->CreateChannel(&listener);
1587 ASSERT_TRUE(this->ConnectChannel());
1588
1589 // Send the child process an IPC with |shmem| attached, to verify
1590 // that is is correctly wrapped, transferred and unwrapped.
1591 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
1592 IPC::WriteParam(message, region);
1593 ASSERT_TRUE(this->channel()->Send(message));
1594
1595 run_loop.Run();
1596
1597 this->channel()->Close();
1598
1599 EXPECT_TRUE(this->WaitForClientShutdown());
1600 EXPECT_FALSE(region.IsValid());
1601 this->DestroyChannel();
1602}
1603
1604DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
1605 IPCChannelMojoTestSendWritableSharedMemoryRegionClient) {
1606 base::RunLoop run_loop;
1607 ListenerThatExpectsSharedMemoryRegion<base::WritableSharedMemoryRegion>
1608 listener(run_loop.QuitClosure());
1609 Connect(&listener);
1610 listener.set_sender(channel());
1611
1612 run_loop.Run();
1613
1614 Close();
1615}
1616DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
1617 IPCChannelMojoTestSendUnsafeSharedMemoryRegionClient) {
1618 base::RunLoop run_loop;
1619 ListenerThatExpectsSharedMemoryRegion<base::UnsafeSharedMemoryRegion>
1620 listener(run_loop.QuitClosure());
1621 Connect(&listener);
1622 listener.set_sender(channel());
1623
1624 run_loop.Run();
1625
1626 Close();
1627}
1628DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
1629 IPCChannelMojoTestSendReadOnlySharedMemoryRegionClient) {
1630 base::RunLoop run_loop;
1631 ListenerThatExpectsSharedMemoryRegion<base::ReadOnlySharedMemoryRegion>
1632 listener(run_loop.QuitClosure());
1633 Connect(&listener);
1634 listener.set_sender(channel());
1635
1636 run_loop.Run();
1637
1638 Close();
1639}
Wez831ae412017-08-30 00:29:361640#endif // !defined(OS_MACOSX)
1641
Fabrice de Gans-Riberi894661c2018-05-24 18:43:221642#if defined(OS_POSIX) || defined(OS_FUCHSIA)
rockot8d890f62016-07-14 16:37:141643
Wez831ae412017-08-30 00:29:361644class ListenerThatExpectsFile : public TestListenerBase {
[email protected]64860882014-08-04 23:44:171645 public:
Wezfdb98482018-07-12 01:21:391646 explicit ListenerThatExpectsFile(base::OnceClosure quit_closure)
1647 : TestListenerBase(std::move(quit_closure)) {}
[email protected]64860882014-08-04 23:44:171648
dchengfe61fca2014-10-22 02:29:521649 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:251650 base::PickleIterator iter(message);
morrita81b17e02015-02-06 00:58:301651 HandleSendingHelper::ReadReceivedFile(message, &iter);
Wez831ae412017-08-30 00:29:361652 ListenerThatExpectsOK::SendOK(sender());
[email protected]64860882014-08-04 23:44:171653 return true;
1654 }
[email protected]64860882014-08-04 23:44:171655};
1656
Wez831ae412017-08-30 00:29:361657TEST_F(IPCChannelMojoTest, SendPlatformFile) {
1658 Init("IPCChannelMojoTestSendPlatformFileClient");
[email protected]64860882014-08-04 23:44:171659
Wez831ae412017-08-30 00:29:361660 base::RunLoop run_loop;
1661 ListenerThatExpectsOK listener(run_loop.QuitClosure());
morrita373af03b2014-09-09 19:35:241662 CreateChannel(&listener);
[email protected]64860882014-08-04 23:44:171663 ASSERT_TRUE(ConnectChannel());
[email protected]64860882014-08-04 23:44:171664
amistry20e2b1d62016-06-23 06:12:351665 base::ScopedTempDir temp_dir;
1666 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
vabr16e5f602016-09-15 18:14:001667 base::File file(HandleSendingHelper::GetSendingFilePath(temp_dir.GetPath()),
[email protected]64860882014-08-04 23:44:171668 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
morrita81b17e02015-02-06 00:58:301669 base::File::FLAG_READ);
1670 HandleSendingHelper::WriteFileThenSend(channel(), file);
Wez831ae412017-08-30 00:29:361671 run_loop.Run();
[email protected]64860882014-08-04 23:44:171672
sammc57ed9f982016-03-10 06:28:351673 channel()->Close();
[email protected]64860882014-08-04 23:44:171674
1675 EXPECT_TRUE(WaitForClientShutdown());
1676 DestroyChannel();
1677}
1678
Wez831ae412017-08-30 00:29:361679DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendPlatformFileClient) {
1680 base::RunLoop run_loop;
1681 ListenerThatExpectsFile listener(run_loop.QuitClosure());
sammc57ed9f982016-03-10 06:28:351682 Connect(&listener);
1683 listener.set_sender(channel());
[email protected]64860882014-08-04 23:44:171684
Wez831ae412017-08-30 00:29:361685 run_loop.Run();
[email protected]64860882014-08-04 23:44:171686
sammc57ed9f982016-03-10 06:28:351687 Close();
[email protected]64860882014-08-04 23:44:171688}
morrita81b17e02015-02-06 00:58:301689
Wez831ae412017-08-30 00:29:361690class ListenerThatExpectsFileAndMessagePipe : public TestListenerBase {
morrita81b17e02015-02-06 00:58:301691 public:
Wezfdb98482018-07-12 01:21:391692 explicit ListenerThatExpectsFileAndMessagePipe(base::OnceClosure quit_closure)
1693 : TestListenerBase(std::move(quit_closure)) {}
morrita81b17e02015-02-06 00:58:301694
Chris Watkins2d879af2017-11-30 02:11:591695 ~ListenerThatExpectsFileAndMessagePipe() override = default;
morrita81b17e02015-02-06 00:58:301696
1697 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:251698 base::PickleIterator iter(message);
morrita81b17e02015-02-06 00:58:301699 HandleSendingHelper::ReadReceivedFile(message, &iter);
1700 HandleSendingHelper::ReadReceivedPipe(message, &iter);
Wez831ae412017-08-30 00:29:361701 ListenerThatExpectsOK::SendOK(sender());
morrita81b17e02015-02-06 00:58:301702 return true;
1703 }
morrita81b17e02015-02-06 00:58:301704};
1705
Wez831ae412017-08-30 00:29:361706TEST_F(IPCChannelMojoTest, SendPlatformFileAndMessagePipe) {
1707 Init("IPCChannelMojoTestSendPlatformFileAndMessagePipeClient");
morrita81b17e02015-02-06 00:58:301708
Wez831ae412017-08-30 00:29:361709 base::RunLoop run_loop;
1710 ListenerThatExpectsOK listener(run_loop.QuitClosure());
morrita81b17e02015-02-06 00:58:301711 CreateChannel(&listener);
1712 ASSERT_TRUE(ConnectChannel());
morrita81b17e02015-02-06 00:58:301713
amistry20e2b1d62016-06-23 06:12:351714 base::ScopedTempDir temp_dir;
1715 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
vabr16e5f602016-09-15 18:14:001716 base::File file(HandleSendingHelper::GetSendingFilePath(temp_dir.GetPath()),
morrita81b17e02015-02-06 00:58:301717 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
1718 base::File::FLAG_READ);
1719 TestingMessagePipe pipe;
1720 HandleSendingHelper::WriteFileAndPipeThenSend(channel(), file, &pipe);
1721
Wez831ae412017-08-30 00:29:361722 run_loop.Run();
sammc57ed9f982016-03-10 06:28:351723 channel()->Close();
morrita81b17e02015-02-06 00:58:301724
1725 EXPECT_TRUE(WaitForClientShutdown());
1726 DestroyChannel();
1727}
1728
sammc57ed9f982016-03-10 06:28:351729DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
Wez831ae412017-08-30 00:29:361730 IPCChannelMojoTestSendPlatformFileAndMessagePipeClient) {
1731 base::RunLoop run_loop;
1732 ListenerThatExpectsFileAndMessagePipe listener(run_loop.QuitClosure());
sammc57ed9f982016-03-10 06:28:351733 Connect(&listener);
1734 listener.set_sender(channel());
morrita81b17e02015-02-06 00:58:301735
Wez831ae412017-08-30 00:29:361736 run_loop.Run();
morrita81b17e02015-02-06 00:58:301737
sammc57ed9f982016-03-10 06:28:351738 Close();
morrita81b17e02015-02-06 00:58:301739}
1740
Fabrice de Gans-Riberi894661c2018-05-24 18:43:221741#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
[email protected]64860882014-08-04 23:44:171742
morrita0bd20bd2015-02-25 20:11:271743#if defined(OS_LINUX)
1744
1745const base::ProcessId kMagicChildId = 54321;
1746
Wez831ae412017-08-30 00:29:361747class ListenerThatVerifiesPeerPid : public TestListenerBase {
morrita0bd20bd2015-02-25 20:11:271748 public:
Wezfdb98482018-07-12 01:21:391749 explicit ListenerThatVerifiesPeerPid(base::OnceClosure quit_closure)
1750 : TestListenerBase(std::move(quit_closure)) {}
Wez831ae412017-08-30 00:29:361751
tfarina10a5c062015-09-04 18:47:571752 void OnChannelConnected(int32_t peer_pid) override {
morrita0bd20bd2015-02-25 20:11:271753 EXPECT_EQ(peer_pid, kMagicChildId);
Wezfdb98482018-07-12 01:21:391754 RunQuitClosure();
morrita0bd20bd2015-02-25 20:11:271755 }
1756
1757 bool OnMessageReceived(const IPC::Message& message) override {
1758 NOTREACHED();
1759 return true;
1760 }
1761};
1762
sammc57ed9f982016-03-10 06:28:351763TEST_F(IPCChannelMojoTest, VerifyGlobalPid) {
sammc4bcc4ed62016-10-27 10:13:591764 Init("IPCChannelMojoTestVerifyGlobalPidClient");
morrita0bd20bd2015-02-25 20:11:271765
Wez831ae412017-08-30 00:29:361766 base::RunLoop run_loop;
1767 ListenerThatVerifiesPeerPid listener(run_loop.QuitClosure());
morrita0bd20bd2015-02-25 20:11:271768 CreateChannel(&listener);
1769 ASSERT_TRUE(ConnectChannel());
morrita0bd20bd2015-02-25 20:11:271770
Wez831ae412017-08-30 00:29:361771 run_loop.Run();
rockotcbca72f2015-03-03 16:31:041772 channel()->Close();
morrita0bd20bd2015-02-25 20:11:271773
1774 EXPECT_TRUE(WaitForClientShutdown());
1775 DestroyChannel();
1776}
1777
sammc4bcc4ed62016-10-27 10:13:591778DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestVerifyGlobalPidClient) {
morrita0bd20bd2015-02-25 20:11:271779 IPC::Channel::SetGlobalPid(kMagicChildId);
Wez831ae412017-08-30 00:29:361780
1781 base::RunLoop run_loop;
1782 ListenerThatQuits listener(run_loop.QuitClosure());
sammc57ed9f982016-03-10 06:28:351783 Connect(&listener);
morrita0bd20bd2015-02-25 20:11:271784
Wez831ae412017-08-30 00:29:361785 run_loop.Run();
morrita0bd20bd2015-02-25 20:11:271786
sammc57ed9f982016-03-10 06:28:351787 Close();
morrita0bd20bd2015-02-25 20:11:271788}
1789
sammc57ed9f982016-03-10 06:28:351790#endif // OS_LINUX
morrita0bd20bd2015-02-25 20:11:271791
[email protected]64860882014-08-04 23:44:171792} // namespace