api_bindings_client_browsertest.cc 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // Copyright 2018 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. #include <fuchsia/web/cpp/fidl.h>
  5. #include <lib/fidl/cpp/binding.h>
  6. #include "base/barrier_closure.h"
  7. #include "base/files/file_util.h"
  8. #include "base/fuchsia/mem_buffer_util.h"
  9. #include "base/path_service.h"
  10. #include "base/test/bind.h"
  11. #include "base/test/test_future.h"
  12. #include "components/cast/message_port/fuchsia/create_web_message.h"
  13. #include "components/cast/message_port/fuchsia/message_port_fuchsia.h"
  14. #include "content/public/test/browser_test.h"
  15. #include "fuchsia_web/common/test/fit_adapter.h"
  16. #include "fuchsia_web/common/test/frame_test_util.h"
  17. #include "fuchsia_web/common/test/test_navigation_listener.h"
  18. #include "fuchsia_web/runners/cast/api_bindings_client.h"
  19. #include "fuchsia_web/runners/cast/fake_api_bindings.h"
  20. #include "fuchsia_web/runners/cast/named_message_port_connector_fuchsia.h"
  21. #include "fuchsia_web/webengine/test/frame_for_test.h"
  22. #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
  23. #include "testing/gtest/include/gtest/gtest.h"
  24. namespace {
  25. class ApiBindingsClientTest : public WebEngineBrowserTest {
  26. public:
  27. ApiBindingsClientTest() : api_service_binding_(&api_service_) {
  28. set_test_server_root(base::FilePath("fuchsia_web/runners/cast/testdata"));
  29. }
  30. ~ApiBindingsClientTest() override = default;
  31. ApiBindingsClientTest(const ApiBindingsClientTest&) = delete;
  32. ApiBindingsClientTest& operator=(const ApiBindingsClientTest&) = delete;
  33. void SetUp() override { WebEngineBrowserTest::SetUp(); }
  34. protected:
  35. void StartClient(bool disconnect_before_attach,
  36. base::OnceClosure on_error_closure) {
  37. base::ScopedAllowBlockingForTesting allow_blocking;
  38. // Get the bindings from |api_service_|.
  39. base::RunLoop run_loop;
  40. client_ = std::make_unique<ApiBindingsClient>(
  41. api_service_binding_.NewBinding(), run_loop.QuitClosure());
  42. ASSERT_FALSE(client_->HasBindings());
  43. run_loop.Run();
  44. ASSERT_TRUE(client_->HasBindings());
  45. frame_ = FrameForTest::Create(context(), fuchsia::web::CreateFrameParams());
  46. connector_ =
  47. std::make_unique<NamedMessagePortConnectorFuchsia>(frame_.get());
  48. if (disconnect_before_attach)
  49. api_service_binding_.Unbind();
  50. base::RunLoop().RunUntilIdle();
  51. client_->AttachToFrame(frame_.get(), connector_.get(),
  52. std::move(on_error_closure));
  53. }
  54. void SetUpOnMainThread() override {
  55. WebEngineBrowserTest::SetUpOnMainThread();
  56. ASSERT_TRUE(embedded_test_server()->Start());
  57. }
  58. void TearDownOnMainThread() override {
  59. // Destroy |client_| before the MessageLoop is destroyed.
  60. client_.reset();
  61. }
  62. FrameForTest frame_;
  63. std::unique_ptr<NamedMessagePortConnectorFuchsia> connector_;
  64. FakeApiBindingsImpl api_service_;
  65. fidl::Binding<chromium::cast::ApiBindings> api_service_binding_;
  66. std::unique_ptr<ApiBindingsClient> client_;
  67. };
  68. // Tests API registration, injection, and message IPC.
  69. // Registers a port that echoes messages received over a MessagePort back to the
  70. // sender.
  71. IN_PROC_BROWSER_TEST_F(ApiBindingsClientTest, EndToEnd) {
  72. // Define the injected bindings.
  73. std::vector<chromium::cast::ApiBinding> binding_list;
  74. chromium::cast::ApiBinding echo_binding;
  75. echo_binding.set_before_load_script(base::MemBufferFromString(
  76. "window.echo = cast.__platform__.PortConnector.bind('echoService');",
  77. "test"));
  78. binding_list.emplace_back(std::move(echo_binding));
  79. api_service_.set_bindings(std::move(binding_list));
  80. StartClient(false, base::MakeExpectedNotRunClosure(FROM_HERE));
  81. base::RunLoop post_message_responses_loop;
  82. base::RepeatingClosure post_message_response_closure =
  83. base::BarrierClosure(2, post_message_responses_loop.QuitClosure());
  84. // Navigate to a test page that makes use of the injected bindings.
  85. const GURL test_url = embedded_test_server()->GetURL("/echo.html");
  86. EXPECT_TRUE(LoadUrlAndExpectResponse(frame_.GetNavigationController(),
  87. fuchsia::web::LoadUrlParams(),
  88. test_url.spec()));
  89. frame_.navigation_listener().RunUntilUrlEquals(test_url);
  90. std::string connect_message;
  91. std::unique_ptr<cast_api_bindings::MessagePort> connect_port;
  92. connector_->GetConnectMessage(&connect_message, &connect_port);
  93. frame_->PostMessage(
  94. "*", CreateWebMessage(connect_message, std::move(connect_port)),
  95. [&post_message_response_closure](
  96. fuchsia::web::Frame_PostMessage_Result result) {
  97. ASSERT_TRUE(result.is_response());
  98. post_message_response_closure.Run();
  99. });
  100. // Connect to the echo service hosted by the page and send a ping to it.
  101. fuchsia::web::WebMessage message;
  102. message.set_data(base::MemBufferFromString("ping", "ping-msg"));
  103. fuchsia::web::MessagePortPtr port =
  104. api_service_.RunAndReturnConnectedPort("echoService").Bind();
  105. port->PostMessage(std::move(message),
  106. [&post_message_response_closure](
  107. fuchsia::web::MessagePort_PostMessage_Result result) {
  108. ASSERT_TRUE(result.is_response());
  109. post_message_response_closure.Run();
  110. });
  111. // Handle the ping response.
  112. base::test::TestFuture<fuchsia::web::WebMessage> response;
  113. port->ReceiveMessage(CallbackToFitFunction(response.GetCallback()));
  114. ASSERT_TRUE(response.Wait());
  115. absl::optional<std::string> response_string =
  116. base::StringFromMemBuffer(response.Get().data());
  117. ASSERT_TRUE(response_string.has_value());
  118. EXPECT_EQ("ack ping", *response_string);
  119. // Ensure that we've received acks for all messages.
  120. post_message_responses_loop.Run();
  121. }
  122. IN_PROC_BROWSER_TEST_F(ApiBindingsClientTest,
  123. ClientDisconnectsBeforeFrameAttached) {
  124. bool error_signaled = false;
  125. StartClient(
  126. true, base::BindOnce([](bool* error_signaled) { *error_signaled = true; },
  127. base::Unretained(&error_signaled)));
  128. EXPECT_TRUE(error_signaled);
  129. }
  130. } // namespace