Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit af899d6

Browse files
sanjayc77Sanjay Chouksey
andauthored
Adds response to view requestFocus platformview message (#21550)
This change adds a response to the platform view message: requestFocus This allows the caller to handle the case when the request fails with an error value. Co-authored-by: Sanjay Chouksey <[email protected]>
1 parent 3c0da65 commit af899d6

File tree

2 files changed

+131
-6
lines changed

2 files changed

+131
-6
lines changed

shell/platform/fuchsia/flutter/platform_view.cc

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -831,10 +831,21 @@ void PlatformView::HandleFlutterPlatformViewsChannelPlatformMessage(
831831
});
832832
focuser_->RequestFocus(
833833
std::move(ref),
834-
[view_ref = view_ref->value.GetUint64()](
835-
fuchsia::ui::views::Focuser_RequestFocus_Result result) {
836-
if (result.is_err()) {
837-
FML_LOG(ERROR) << "Failed to request focus for view: " << view_ref;
834+
[view_ref = view_ref->value.GetUint64(),
835+
message](fuchsia::ui::views::Focuser_RequestFocus_Result result) {
836+
if (message->response().get()) {
837+
int result_code =
838+
result.is_err()
839+
? static_cast<
840+
std::underlying_type_t<fuchsia::ui::views::Error>>(
841+
result.err())
842+
: 0;
843+
844+
std::ostringstream out;
845+
out << "[" << result_code << "]";
846+
message->response()->Complete(
847+
std::make_unique<fml::NonOwnedMapping>(
848+
(const uint8_t*)out.str().c_str(), out.str().length()));
838849
}
839850
});
840851
} else {

shell/platform/fuchsia/flutter/platform_view_unittest.cc

Lines changed: 116 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "flutter/flow/embedded_views.h"
1919
#include "flutter/lib/ui/window/platform_message.h"
2020
#include "flutter/lib/ui/window/window.h"
21+
#include "gmock/gmock.h"
2122
#include "gtest/gtest.h"
2223

2324
#include "surface.h"
@@ -131,14 +132,28 @@ class MockFocuser : public fuchsia::ui::views::Focuser {
131132
~MockFocuser() override = default;
132133

133134
bool request_focus_called = false;
135+
bool fail_request_focus = false;
134136

135137
private:
136138
void RequestFocus(fuchsia::ui::views::ViewRef view_ref,
137139
RequestFocusCallback callback) override {
138140
request_focus_called = true;
141+
auto result =
142+
fail_request_focus
143+
? fuchsia::ui::views::Focuser_RequestFocus_Result::WithErr(
144+
fuchsia::ui::views::Error::DENIED)
145+
: fuchsia::ui::views::Focuser_RequestFocus_Result::WithResponse(
146+
fuchsia::ui::views::Focuser_RequestFocus_Response());
147+
callback(std::move(result));
139148
}
140149
};
141150

151+
class MockResponse : public flutter::PlatformMessageResponse {
152+
public:
153+
MOCK_METHOD1(Complete, void(std::unique_ptr<fml::Mapping> data));
154+
MOCK_METHOD0(CompleteEmpty, void());
155+
};
156+
142157
TEST_F(PlatformViewTests, ChangesAccessibilitySettings) {
143158
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
144159

@@ -513,16 +528,115 @@ TEST_F(PlatformViewTests, RequestFocusTest) {
513528
"}",
514529
b.get());
515530

531+
// Define a custom gmock matcher to capture the response to platform message.
532+
struct DataArg {
533+
void Complete(std::unique_ptr<fml::Mapping> data) {
534+
this->data = std::move(data);
535+
}
536+
std::unique_ptr<fml::Mapping> data;
537+
};
538+
DataArg data_arg;
539+
fml::RefPtr<MockResponse> response = fml::MakeRefCounted<MockResponse>();
540+
EXPECT_CALL(*response, Complete(testing::_))
541+
.WillOnce(testing::Invoke(&data_arg, &DataArg::Complete));
542+
516543
fml::RefPtr<flutter::PlatformMessage> message =
517544
fml::MakeRefCounted<flutter::PlatformMessage>(
518545
"flutter/platform_views",
519-
std::vector<uint8_t>(buff, buff + sizeof(buff)),
520-
fml::RefPtr<flutter::PlatformMessageResponse>());
546+
std::vector<uint8_t>(buff, buff + sizeof(buff)), response);
547+
base_view->HandlePlatformMessage(message);
548+
549+
RunLoopUntilIdle();
550+
551+
EXPECT_TRUE(mock_focuser.request_focus_called);
552+
auto result = std::string((const char*)data_arg.data->GetMapping(),
553+
data_arg.data->GetSize());
554+
EXPECT_EQ(std::string("[0]"), result);
555+
}
556+
557+
// Test to make sure that PlatformView correctly registers messages sent on
558+
// the "flutter/platform_views" channel, correctly parses the JSON it receives
559+
// and calls the focuser's RequestFocus with the appropriate args.
560+
TEST_F(PlatformViewTests, RequestFocusFailTest) {
561+
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
562+
MockPlatformViewDelegate delegate;
563+
zx::eventpair a, b;
564+
zx::eventpair::create(/* flags */ 0u, &a, &b);
565+
auto view_ref = fuchsia::ui::views::ViewRef({
566+
.reference = std::move(a),
567+
});
568+
flutter::TaskRunners task_runners =
569+
flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
570+
571+
MockFocuser mock_focuser;
572+
mock_focuser.fail_request_focus = true;
573+
fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
574+
auto focuser_handle = focuser_bindings.AddBinding(&mock_focuser);
575+
576+
auto platform_view = flutter_runner::PlatformView(
577+
delegate, // delegate
578+
"test_platform_view", // label
579+
std::move(view_ref), // view_refs
580+
std::move(task_runners), // task_runners
581+
services_provider.service_directory(), // runner_services
582+
nullptr, // parent_environment_service_provider_handle
583+
nullptr, // session_listener_request
584+
std::move(focuser_handle), // focuser,
585+
nullptr, // on_session_listener_error_callback
586+
nullptr, // on_enable_wireframe_callback,
587+
nullptr, // on_create_view_callback,
588+
nullptr, // on_update_view_callback,
589+
nullptr, // on_destroy_view_callback,
590+
nullptr, // on_create_surface_callback,
591+
fml::TimeDelta::Zero(), // vsync_offset
592+
ZX_HANDLE_INVALID // vsync_event_handle
593+
);
594+
595+
// Cast platform_view to its base view so we can have access to the public
596+
// "HandlePlatformMessage" function.
597+
auto base_view = dynamic_cast<flutter::PlatformView*>(&platform_view);
598+
EXPECT_TRUE(base_view);
599+
600+
// JSON for the message to be passed into the PlatformView.
601+
char buff[254];
602+
snprintf(buff, sizeof(buff),
603+
"{"
604+
" \"method\":\"View.requestFocus\","
605+
" \"args\": {"
606+
" \"viewRef\":%u"
607+
" }"
608+
"}",
609+
b.get());
610+
611+
// Define a custom gmock matcher to capture the response to platform message.
612+
struct DataArg {
613+
void Complete(std::unique_ptr<fml::Mapping> data) {
614+
this->data = std::move(data);
615+
}
616+
std::unique_ptr<fml::Mapping> data;
617+
};
618+
DataArg data_arg;
619+
fml::RefPtr<MockResponse> response = fml::MakeRefCounted<MockResponse>();
620+
EXPECT_CALL(*response, Complete(testing::_))
621+
.WillOnce(testing::Invoke(&data_arg, &DataArg::Complete));
622+
623+
fml::RefPtr<flutter::PlatformMessage> message =
624+
fml::MakeRefCounted<flutter::PlatformMessage>(
625+
"flutter/platform_views",
626+
std::vector<uint8_t>(buff, buff + sizeof(buff)), response);
521627
base_view->HandlePlatformMessage(message);
522628

523629
RunLoopUntilIdle();
524630

525631
EXPECT_TRUE(mock_focuser.request_focus_called);
632+
auto result = std::string((const char*)data_arg.data->GetMapping(),
633+
data_arg.data->GetSize());
634+
std::ostringstream out;
635+
out << "["
636+
<< static_cast<std::underlying_type_t<fuchsia::ui::views::Error>>(
637+
fuchsia::ui::views::Error::DENIED)
638+
<< "]";
639+
EXPECT_EQ(out.str(), result);
526640
}
527641

528642
// Test to make sure that PlatformView correctly returns a Surface instance

0 commit comments

Comments
 (0)