From f73cf637fd42aea6321d8752ddfc2d6e549dbf53 Mon Sep 17 00:00:00 2001 From: Shivesh Ganju Date: Tue, 20 Sep 2022 17:53:27 -0400 Subject: [PATCH] [fuchsia][scenic] Add support for viewConnected and viewDisconnected (flutter/engine#36298) signals in flatland. This PR adds support for sending 'View.viewConnected' platform message when a view gets created and 'View.viewDisconnected' signal when a view gets destroyed. Test: ffx test run "fuchsia-pkg://fuchsia.com/flutter_runner_tests#meta/flutter_runner_tests.cm" Bug: https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=93452 --- .../fuchsia/flutter/flatland_platform_view.cc | 41 +++++++++- .../fuchsia/flutter/flatland_platform_view.h | 9 +++ .../tests/flatland_platform_view_unittest.cc | 76 ++++++++++++++----- 3 files changed, 105 insertions(+), 21 deletions(-) diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.cc b/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.cc index b6babae7d45..86ea787e9d7 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.cc +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.cc @@ -153,7 +153,9 @@ void FlatlandPlatformView::OnChildViewViewRef( fuchsia::ui::views::ViewRef view_ref_clone; fidl::Clone(view_ref, &view_ref_clone); pointer_injector_delegate_->OnCreateView(view_id, std::move(view_ref_clone)); + OnChildViewConnected(content_id); + // TODO(http://fxbug.dev/109948): Remove the following GetViewRef call. child_view_info_.at(content_id) .child_view_watcher->GetViewRef( [this, content_id, view_id](fuchsia::ui::views::ViewRef view_ref) { @@ -182,7 +184,7 @@ void FlatlandPlatformView::OnCreateView(ViewCallback on_view_created, FML_CHECK(child_view_watcher); child_view_watcher.set_error_handler( - [weak, view_id](zx_status_t status) { + [weak, view_id, content_id](zx_status_t status) { FML_LOG(ERROR) << "Interface error on: ChildViewWatcher status: " << status; @@ -195,6 +197,8 @@ void FlatlandPlatformView::OnCreateView(ViewCallback on_view_created, // Disconnected views cannot listen to pointer events. weak->pointer_injector_delegate_->OnDestroyView(view_id); + + weak->OnChildViewDisconnected(content_id.value); }); platform_task_runner->PostTask( @@ -246,6 +250,7 @@ void FlatlandPlatformView::OnDisposeView(int64_t view_id_raw) { } FML_DCHECK(weak->child_view_info_.count(content_id.value) == 1); + weak->OnChildViewDisconnected(content_id.value); weak->child_view_info_.erase(content_id.value); weak->focus_delegate_->OnDisposeChildView(view_id_raw); weak->pointer_injector_delegate_->OnDestroyView(view_id_raw); @@ -254,4 +259,38 @@ void FlatlandPlatformView::OnDisposeView(int64_t view_id_raw) { on_destroy_view_callback_(view_id_raw, std::move(on_view_unbound)); } +void FlatlandPlatformView::OnChildViewConnected(uint64_t content_id) { + FML_CHECK(child_view_info_.count(content_id) == 1); + std::ostringstream out; + out << "{" + << "\"method\":\"View.viewConnected\"," + << "\"args\":{" + << " \"viewId\":" << child_view_info_.at(content_id).view_id << " }" + << "}"; + auto call = out.str(); + + std::unique_ptr message = + std::make_unique( + "flutter/platform_views", + fml::MallocMapping::Copy(call.c_str(), call.size()), nullptr); + DispatchPlatformMessage(std::move(message)); +} + +void FlatlandPlatformView::OnChildViewDisconnected(uint64_t content_id) { + FML_CHECK(child_view_info_.count(content_id) == 1); + std::ostringstream out; + out << "{" + << "\"method\":\"View.viewDisconnected\"," + << "\"args\":{" + << " \"viewId\":" << child_view_info_.at(content_id).view_id << " }" + << "}"; + auto call = out.str(); + + std::unique_ptr message = + std::make_unique( + "flutter/platform_views", + fml::MallocMapping::Copy(call.c_str(), call.size()), nullptr); + DispatchPlatformMessage(std::move(message)); +} + } // namespace flutter_runner diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.h b/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.h index 04ab78707a3..afe0819842c 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.h +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.h @@ -65,6 +65,15 @@ class FlatlandPlatformView final : public flutter_runner::PlatformView { bool focusable) override; void OnDisposeView(int64_t view_id_raw) override; + // Sends a 'View.viewConnected' platform message over 'flutter/platform_views' + // channel when a view gets created. + void OnChildViewConnected(uint64_t content_id); + + // Sends a 'View.viewDisconnected' platform message over + // 'flutter/platform_views' channel when a view gets destroyed or the child + // view watcher channel of a view closes. + void OnChildViewDisconnected(uint64_t content_id); + // child_view_ids_ maintains a persistent mapping from Flatland ContentId's to // flutter view ids, which are really zx_handle_t of ViewCreationToken. struct ChildViewInfo { diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/tests/flatland_platform_view_unittest.cc b/engine/src/flutter/shell/platform/fuchsia/flutter/tests/flatland_platform_view_unittest.cc index f2565ac69c9..48269747bc4 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/tests/flatland_platform_view_unittest.cc +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/tests/flatland_platform_view_unittest.cc @@ -750,6 +750,7 @@ TEST_F(FlatlandPlatformViewTests, EnableWireframeTest) { // "flutter/platform_views" channel for Createview. TEST_F(FlatlandPlatformViewTests, CreateViewTest) { MockPlatformViewDelegate delegate; + const uint64_t view_id = 42; flutter::TaskRunners task_runners = flutter::TaskRunners("test_runners", // label flutter_runner::CreateFMLTaskRunner( @@ -784,25 +785,41 @@ TEST_F(FlatlandPlatformViewTests, CreateViewTest) { EXPECT_TRUE(base_view); // JSON for the message to be passed into the PlatformView. - const uint8_t txt[] = - "{" - " \"method\":\"View.create\"," - " \"args\": {" - " \"viewId\":42," - " \"hitTestable\":true," - " \"focusable\":true" - " }" - "}"; + std::ostringstream create_view_message; + create_view_message << "{" + << " \"method\":\"View.create\"," + << " \"args\":{" + << " \"viewId\":" << view_id << "," + << " \"hitTestable\":true," + << " \"focusable\":true" + << " }" + << "}"; + std::string create_view_call = create_view_message.str(); std::unique_ptr message = std::make_unique( - "flutter/platform_views", fml::MallocMapping::Copy(txt, sizeof(txt)), + "flutter/platform_views", + fml::MallocMapping::Copy(create_view_call.c_str(), + create_view_call.size()), fml::RefPtr()); base_view->HandlePlatformMessage(std::move(message)); RunLoopUntilIdle(); EXPECT_TRUE(create_view_called); + + // Platform view forwards the 'View.viewConnected' message on the + // 'flutter/platform_views' channel when a view gets created. + std::ostringstream view_connected_expected_out; + view_connected_expected_out << "{" + << "\"method\":\"View.viewConnected\"," + << "\"args\":{" + << " \"viewId\":" << view_id << " }" + << "}"; + + ASSERT_NE(delegate.message(), nullptr); + EXPECT_EQ(view_connected_expected_out.str(), + ToString(delegate.message()->data())); } // This test makes sure that the PlatformView forwards messages on the @@ -924,6 +941,8 @@ TEST_F(FlatlandPlatformViewTests, UpdateViewTest) { // "flutter/platform_views" channel for DestroyView. TEST_F(FlatlandPlatformViewTests, DestroyViewTest) { MockPlatformViewDelegate delegate; + const uint64_t view_id = 42; + flutter::TaskRunners task_runners = flutter::TaskRunners("test_runners", // label flutter_runner::CreateFMLTaskRunner( @@ -970,7 +989,7 @@ TEST_F(FlatlandPlatformViewTests, DestroyViewTest) { create_message << "{" << " \"method\":\"View.create\"," << " \"args\": {" - << " \"viewId\":42," + << " \"viewId\":" << view_id << "," << " \"hitTestable\":true," << " \"focusable\":true" << " }" @@ -981,24 +1000,41 @@ TEST_F(FlatlandPlatformViewTests, DestroyViewTest) { "flutter/platform_views", create_message.str())); RunLoopUntilIdle(); - // JSON for the message to be passed into the PlatformView. - const uint8_t txt[] = - "{" - " \"method\":\"View.dispose\"," - " \"args\": {" - " \"viewId\":42" - " }" - "}"; + delegate.Reset(); + // JSON for the message to be passed into the PlatformView. + std::ostringstream dispose_message; + dispose_message << "{" + << " \"method\":\"View.dispose\"," + << " \"args\": {" + << " \"viewId\":" << view_id << " }" + << "}"; + + std::string dispose_view_call = dispose_message.str(); std::unique_ptr message = std::make_unique( - "flutter/platform_views", fml::MallocMapping::Copy(txt, sizeof(txt)), + "flutter/platform_views", + fml::MallocMapping::Copy(dispose_view_call.c_str(), + dispose_view_call.size()), fml::RefPtr()); base_view->HandlePlatformMessage(std::move(message)); RunLoopUntilIdle(); EXPECT_TRUE(destroy_view_called); + + // Platform view forwards the 'View.viewDisconnected' message on the + // 'flutter/platform_views' channel when a view gets destroyed. + std::ostringstream view_disconnected_expected_out; + view_disconnected_expected_out << "{" + << "\"method\":\"View.viewDisconnected\"," + << "\"args\":{" + << " \"viewId\":" << view_id << " }" + << "}"; + + ASSERT_NE(delegate.message(), nullptr); + EXPECT_EQ(view_disconnected_expected_out.str(), + ToString(delegate.message()->data())); } // This test makes sure that the PlatformView forwards messages on the