| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ipc/ipc_channel_mojo.h" | 5 #include "ipc/ipc_channel_mojo.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 #include "build/build_config.h" | 30 #include "build/build_config.h" |
| 31 #include "ipc/ipc_message.h" | 31 #include "ipc/ipc_message.h" |
| 32 #include "ipc/ipc_mojo_handle_attachment.h" | 32 #include "ipc/ipc_mojo_handle_attachment.h" |
| 33 #include "ipc/ipc_mojo_message_helper.h" | 33 #include "ipc/ipc_mojo_message_helper.h" |
| 34 #include "ipc/ipc_mojo_param_traits.h" | 34 #include "ipc/ipc_mojo_param_traits.h" |
| 35 #include "ipc/ipc_sync_channel.h" | 35 #include "ipc/ipc_sync_channel.h" |
| 36 #include "ipc/ipc_sync_message.h" | 36 #include "ipc/ipc_sync_message.h" |
| 37 #include "ipc/ipc_test.mojom.h" | 37 #include "ipc/ipc_test.mojom.h" |
| 38 #include "ipc/ipc_test_base.h" | 38 #include "ipc/ipc_test_base.h" |
| 39 #include "ipc/ipc_test_channel_listener.h" | 39 #include "ipc/ipc_test_channel_listener.h" |
| 40 #include "mojo/public/cpp/bindings/binding.h" |
| 40 #include "testing/gtest/include/gtest/gtest.h" | 41 #include "testing/gtest/include/gtest/gtest.h" |
| 41 | 42 |
| 42 #if defined(OS_POSIX) | 43 #if defined(OS_POSIX) |
| 43 #include "base/file_descriptor_posix.h" | 44 #include "base/file_descriptor_posix.h" |
| 44 #include "ipc/ipc_platform_file_attachment_posix.h" | 45 #include "ipc/ipc_platform_file_attachment_posix.h" |
| 45 #endif | 46 #endif |
| 46 | 47 |
| 47 namespace { | 48 namespace { |
| 48 | 49 |
| 49 void SendString(IPC::Sender* sender, const std::string& str) { | 50 void SendString(IPC::Sender* sender, const std::string& str) { |
| 50 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); | 51 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); |
| 51 message->WriteString(str); | 52 message->WriteString(str); |
| 52 ASSERT_TRUE(sender->Send(message)); | 53 ASSERT_TRUE(sender->Send(message)); |
| 53 } | 54 } |
| 54 | 55 |
| 55 void SendValue(IPC::Sender* sender, int32_t value) { | 56 void SendValue(IPC::Sender* sender, int32_t value) { |
| 56 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); | 57 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); |
| 57 message->WriteInt(value); | 58 message->WriteInt(value); |
| 58 ASSERT_TRUE(sender->Send(message)); | 59 ASSERT_TRUE(sender->Send(message)); |
| 59 } | 60 } |
| 60 | 61 |
| 62 void SendMessagePipe(IPC::Sender* sender, mojo::ScopedMessagePipeHandle pipe) { |
| 63 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); |
| 64 IPC::MojoMessageHelper::WriteMessagePipeTo(message, std::move(pipe)); |
| 65 ASSERT_TRUE(sender->Send(message)); |
| 66 } |
| 67 |
| 61 class ListenerThatExpectsOK : public IPC::Listener { | 68 class ListenerThatExpectsOK : public IPC::Listener { |
| 62 public: | 69 public: |
| 63 ListenerThatExpectsOK() : received_ok_(false) {} | 70 ListenerThatExpectsOK() : received_ok_(false) {} |
| 64 | 71 |
| 65 ~ListenerThatExpectsOK() override {} | 72 ~ListenerThatExpectsOK() override {} |
| 66 | 73 |
| 67 bool OnMessageReceived(const IPC::Message& message) override { | 74 bool OnMessageReceived(const IPC::Message& message) override { |
| 68 base::PickleIterator iter(message); | 75 base::PickleIterator iter(message); |
| 69 std::string should_be_ok; | 76 std::string should_be_ok; |
| 70 EXPECT_TRUE(iter.ReadString(&should_be_ok)); | 77 EXPECT_TRUE(iter.ReadString(&should_be_ok)); |
| (...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 } | 690 } |
| 684 void CreateProxy(IPC::Listener* listener) { runner_->CreateProxy(listener); } | 691 void CreateProxy(IPC::Listener* listener) { runner_->CreateProxy(listener); } |
| 685 void RunProxy() { | 692 void RunProxy() { |
| 686 runner_->RunProxy(); | 693 runner_->RunProxy(); |
| 687 } | 694 } |
| 688 void DestroyProxy() { | 695 void DestroyProxy() { |
| 689 runner_.reset(); | 696 runner_.reset(); |
| 690 base::RunLoop().RunUntilIdle(); | 697 base::RunLoop().RunUntilIdle(); |
| 691 } | 698 } |
| 692 | 699 |
| 700 // Launches a secondary test client. |
| 701 std::unique_ptr<ChannelProxyRunner> |
| 702 LaunchClient(const std::string& client_name, |
| 703 IPC::Listener* listener, |
| 704 ClientHandle* client) { |
| 705 client->Init(client_name); |
| 706 std::unique_ptr<ChannelProxyRunner> runner( |
| 707 new ChannelProxyRunner(client->TakeHandle(), true)); |
| 708 runner->CreateProxy(listener); |
| 709 runner->RunProxy(); |
| 710 return runner; |
| 711 } |
| 712 |
| 693 IPC::ChannelProxy* proxy() { return runner_->proxy(); } | 713 IPC::ChannelProxy* proxy() { return runner_->proxy(); } |
| 694 | 714 |
| 695 private: | 715 private: |
| 696 std::unique_ptr<ChannelProxyRunner> runner_; | 716 std::unique_ptr<ChannelProxyRunner> runner_; |
| 697 }; | 717 }; |
| 698 | 718 |
| 699 class ListenerWithSimpleProxyAssociatedInterface | 719 class ListenerWithSimpleProxyAssociatedInterface |
| 700 : public IPC::Listener, | 720 : public IPC::Listener, |
| 701 public IPC::mojom::SimpleTestDriver { | 721 public IPC::mojom::SimpleTestDriver { |
| 702 public: | 722 public: |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 expected_values.push(4); | 1269 expected_values.push(4); |
| 1250 expected_values.push(5); | 1270 expected_values.push(5); |
| 1251 expected_values.push(2); | 1271 expected_values.push(2); |
| 1252 expected_values.push(3); | 1272 expected_values.push(3); |
| 1253 RunProxy(); | 1273 RunProxy(); |
| 1254 base::RunLoop().Run(); | 1274 base::RunLoop().Run(); |
| 1255 EXPECT_TRUE(expected_values.empty()); | 1275 EXPECT_TRUE(expected_values.empty()); |
| 1256 DestroyProxy(); | 1276 DestroyProxy(); |
| 1257 } | 1277 } |
| 1258 | 1278 |
| 1279 class TokenListener : public IPC::Listener, |
| 1280 public IPC::mojom::SynchronizationTestClient { |
| 1281 public: |
| 1282 explicit TokenListener(IPC::mojom::SynchronizationTestClientRequest request) |
| 1283 : binding_(this, std::move(request)) {} |
| 1284 ~TokenListener() override {} |
| 1285 |
| 1286 bool OnMessageReceived(const IPC::Message& message) override { |
| 1287 base::PickleIterator iter(message); |
| 1288 EXPECT_TRUE(iter.ReadString(®istered_token_)); |
| 1289 return true; |
| 1290 } |
| 1291 |
| 1292 const std::string& registered_token() const { return registered_token_; } |
| 1293 |
| 1294 void set_quit_closure(const base::Closure& closure) { |
| 1295 quit_closure_ = closure; |
| 1296 } |
| 1297 |
| 1298 private: |
| 1299 // IPC::mojom::SynchronizationTestClient: |
| 1300 void OnTokenReceived(const std::string& token, |
| 1301 const OnTokenReceivedCallback& callback) override { |
| 1302 EXPECT_FALSE(registered_token_.empty()); |
| 1303 EXPECT_EQ(registered_token_, token); |
| 1304 callback.Run(); |
| 1305 quit_closure_.Run(); |
| 1306 } |
| 1307 |
| 1308 std::string registered_token_; |
| 1309 base::Closure quit_closure_; |
| 1310 mojo::Binding<IPC::mojom::SynchronizationTestClient> binding_; |
| 1311 }; |
| 1312 |
| 1313 TEST_F(IPCChannelProxyMojoTest, ChannelSynchronizationEvent) { |
| 1314 // This test creates two child processes A and B. It then establishes a direct |
| 1315 // pipe between process A and B -- specifically process A gets a |
| 1316 // SynchronizationTestReceiver proxy to process B. |
| 1317 // |
| 1318 // Process A sends a legacy IPC message to the main process to register a |
| 1319 // token there (see TokenListener above). |
| 1320 // |
| 1321 // Process A also sends a message directly to B referencing the token, and |
| 1322 // including a channel synchronization event for B to wait on. |
| 1323 // |
| 1324 // Process B waits on the event and then sends the token back to the main |
| 1325 // process over an independent interface (SynchronizationTestClient). |
| 1326 // |
| 1327 // Because a channel synchronization event was used, it should be impossible |
| 1328 // for the main process to receive process B's message before it receives |
| 1329 // process A's token registration. |
| 1330 // |
| 1331 // This test verifies that. |
| 1332 ClientHandle sender_handle; |
| 1333 IPC::mojom::SynchronizationTestClientPtr client; |
| 1334 TokenListener sender_listener(mojo::GetProxy(&client)); |
| 1335 std::unique_ptr<ChannelProxyRunner> sender = |
| 1336 LaunchClient("SynchronizationTestSender", &sender_listener, |
| 1337 &sender_handle); |
| 1338 |
| 1339 ClientHandle receiver_handle; |
| 1340 DummyListener receiver_listener; |
| 1341 std::unique_ptr<ChannelProxyRunner> receiver = |
| 1342 LaunchClient("SynchronizationTestReceiver", &receiver_listener, |
| 1343 &receiver_handle); |
| 1344 |
| 1345 base::RunLoop loop; |
| 1346 sender_listener.set_quit_closure(loop.QuitClosure()); |
| 1347 |
| 1348 IPC::mojom::SynchronizationTestReceiverPtr receiver_proxy; |
| 1349 SendMessagePipe(receiver->proxy(), |
| 1350 mojo::GetProxy(&receiver_proxy).PassMessagePipe()); |
| 1351 |
| 1352 IPC::mojom::SynchronizationTestSenderPtr sender_proxy; |
| 1353 SendMessagePipe(sender->proxy(), |
| 1354 mojo::GetProxy(&sender_proxy).PassMessagePipe()); |
| 1355 |
| 1356 sender_proxy->SendToken(std::move(receiver_proxy), std::move(client)); |
| 1357 loop.Run(); |
| 1358 |
| 1359 sender_proxy->Quit(); |
| 1360 |
| 1361 EXPECT_TRUE(sender_handle.WaitForShutdown()); |
| 1362 EXPECT_TRUE(receiver_handle.WaitForShutdown()); |
| 1363 } |
| 1364 |
| 1365 class SynchronizationTestPipeListener : public IPC::Listener { |
| 1366 public: |
| 1367 using PipeHandler = base::Callback<void(mojo::ScopedMessagePipeHandle)>; |
| 1368 |
| 1369 SynchronizationTestPipeListener() {} |
| 1370 ~SynchronizationTestPipeListener() override {} |
| 1371 |
| 1372 bool OnMessageReceived(const IPC::Message& message) override { |
| 1373 base::PickleIterator iter(message); |
| 1374 mojo::ScopedMessagePipeHandle handle; |
| 1375 EXPECT_TRUE(IPC::MojoMessageHelper::ReadMessagePipeFrom( |
| 1376 &message, &iter, &handle)); |
| 1377 pipe_handler_.Run(std::move(handle)); |
| 1378 return true; |
| 1379 } |
| 1380 |
| 1381 void set_pipe_handler(const PipeHandler& handler) { pipe_handler_ = handler; } |
| 1382 |
| 1383 private: |
| 1384 PipeHandler pipe_handler_; |
| 1385 base::Closure quit_closure_; |
| 1386 }; |
| 1387 |
| 1388 class SynchronizationTestSenderImpl |
| 1389 : public IPC::mojom::SynchronizationTestSender { |
| 1390 public: |
| 1391 SynchronizationTestSenderImpl( |
| 1392 IPC::ChannelProxy* channel, |
| 1393 const base::Closure& quit_closure) |
| 1394 : channel_(channel), quit_closure_(quit_closure), binding_(this) {} |
| 1395 |
| 1396 ~SynchronizationTestSenderImpl() override {} |
| 1397 |
| 1398 void Bind(mojo::ScopedMessagePipeHandle handle) { |
| 1399 binding_.Bind(std::move(handle)); |
| 1400 } |
| 1401 |
| 1402 // IPC::mojom::SynchronizationTestSender: |
| 1403 void SendToken(IPC::mojom::SynchronizationTestReceiverPtr receiver, |
| 1404 IPC::mojom::SynchronizationTestClientPtr client) override { |
| 1405 // Register the token with the parent process over legacy IPC, then send it |
| 1406 // to the receiver process with a synchronization event. |
| 1407 const std::string kToken = "make IPC great again"; |
| 1408 SendString(channel_, kToken); |
| 1409 receiver->ReceiveToken( |
| 1410 kToken, std::move(client), channel_->CreateSynchronizationEvent()); |
| 1411 } |
| 1412 |
| 1413 void Quit() override { quit_closure_.Run(); } |
| 1414 |
| 1415 private: |
| 1416 IPC::ChannelProxy* const channel_; |
| 1417 const base::Closure quit_closure_; |
| 1418 mojo::Binding<IPC::mojom::SynchronizationTestSender> binding_; |
| 1419 |
| 1420 DISALLOW_COPY_AND_ASSIGN(SynchronizationTestSenderImpl); |
| 1421 }; |
| 1422 |
| 1423 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE( |
| 1424 SynchronizationTestSender, ChannelProxyClient) { |
| 1425 SynchronizationTestPipeListener listener; |
| 1426 CreateProxy(&listener); |
| 1427 RunProxy(); |
| 1428 |
| 1429 base::RunLoop loop; |
| 1430 SynchronizationTestSenderImpl impl(proxy(), loop.QuitClosure()); |
| 1431 listener.set_pipe_handler(base::Bind(&SynchronizationTestSenderImpl::Bind, |
| 1432 base::Unretained(&impl))); |
| 1433 loop.Run(); |
| 1434 DestroyProxy(); |
| 1435 } |
| 1436 |
| 1437 class SynchronizationTestReceiverImpl |
| 1438 : public IPC::mojom::SynchronizationTestReceiver, |
| 1439 public mojo::common::mojom::Event { |
| 1440 public: |
| 1441 explicit SynchronizationTestReceiverImpl( |
| 1442 const base::Closure& quit_closure) |
| 1443 : quit_closure_(quit_closure), binding_(this), event_binding_(this) {} |
| 1444 |
| 1445 ~SynchronizationTestReceiverImpl() override {} |
| 1446 |
| 1447 void Bind(mojo::ScopedMessagePipeHandle handle) { |
| 1448 binding_.Bind(std::move(handle)); |
| 1449 } |
| 1450 |
| 1451 // IPC::mojom::SynchronizationTestReceiver: |
| 1452 void ReceiveToken(const std::string& token, |
| 1453 IPC::mojom::SynchronizationTestClientPtr client, |
| 1454 mojo::common::mojom::EventRequest event) override { |
| 1455 // Hang onto the token until |event| signals. |
| 1456 received_token_ = token; |
| 1457 client_ = std::move(client); |
| 1458 event_binding_.Bind(std::move(event)); |
| 1459 } |
| 1460 |
| 1461 // mojo::common::mojom::Event: |
| 1462 void Signal() override { |
| 1463 // This request should always reach the parent process after the sender's |
| 1464 // legacy IPC which registered the same token there. |
| 1465 client_->OnTokenReceived(received_token_, quit_closure_); |
| 1466 } |
| 1467 |
| 1468 private: |
| 1469 const base::Closure quit_closure_; |
| 1470 std::string received_token_; |
| 1471 IPC::mojom::SynchronizationTestClientPtr client_; |
| 1472 mojo::Binding<IPC::mojom::SynchronizationTestReceiver> binding_; |
| 1473 mojo::Binding<mojo::common::mojom::Event> event_binding_; |
| 1474 |
| 1475 DISALLOW_COPY_AND_ASSIGN(SynchronizationTestReceiverImpl); |
| 1476 }; |
| 1477 |
| 1478 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE( |
| 1479 SynchronizationTestReceiver, ChannelProxyClient) { |
| 1480 SynchronizationTestPipeListener listener; |
| 1481 CreateProxy(&listener); |
| 1482 RunProxy(); |
| 1483 base::RunLoop loop; |
| 1484 SynchronizationTestReceiverImpl impl(loop.QuitClosure()); |
| 1485 listener.set_pipe_handler(base::Bind(&SynchronizationTestReceiverImpl::Bind, |
| 1486 base::Unretained(&impl))); |
| 1487 loop.Run(); |
| 1488 DestroyProxy(); |
| 1489 } |
| 1490 |
| 1259 #if defined(OS_POSIX) | 1491 #if defined(OS_POSIX) |
| 1260 | 1492 |
| 1261 class ListenerThatExpectsFile : public IPC::Listener { | 1493 class ListenerThatExpectsFile : public IPC::Listener { |
| 1262 public: | 1494 public: |
| 1263 ListenerThatExpectsFile() : sender_(NULL) {} | 1495 ListenerThatExpectsFile() : sender_(NULL) {} |
| 1264 | 1496 |
| 1265 ~ListenerThatExpectsFile() override {} | 1497 ~ListenerThatExpectsFile() override {} |
| 1266 | 1498 |
| 1267 bool OnMessageReceived(const IPC::Message& message) override { | 1499 bool OnMessageReceived(const IPC::Message& message) override { |
| 1268 base::PickleIterator iter(message); | 1500 base::PickleIterator iter(message); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1409 Connect(&listener); | 1641 Connect(&listener); |
| 1410 | 1642 |
| 1411 base::RunLoop().Run(); | 1643 base::RunLoop().Run(); |
| 1412 | 1644 |
| 1413 Close(); | 1645 Close(); |
| 1414 } | 1646 } |
| 1415 | 1647 |
| 1416 #endif // OS_LINUX | 1648 #endif // OS_LINUX |
| 1417 | 1649 |
| 1418 } // namespace | 1650 } // namespace |
| OLD | NEW |