Commit 8b548ab9 authored by Sharon Yang's avatar Sharon Yang Committed by Commit Bot

[Fuchsia] Add test for accessibility hit testing

Added browser tests for hit testing, implemented in 1927578.

Bug: 973095
Bug: fuchsia:16642
Change-Id: I1b4b6638b53b2aa604ac98fc0765266090fa4e71
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1929977Reviewed-by: default avatarKevin Marshall <kmarshall@chromium.org>
Commit-Queue: Kevin Marshall <kmarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726641}
parent b8c0fc44
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <fuchsia/accessibility/semantics/cpp/fidl.h> #include <fuchsia/accessibility/semantics/cpp/fidl.h>
#include <fuchsia/accessibility/semantics/cpp/fidl_test_base.h> #include <fuchsia/accessibility/semantics/cpp/fidl_test_base.h>
#include <lib/sys/cpp/component_context.h> #include <lib/sys/cpp/component_context.h>
#include <lib/ui/scenic/cpp/view_token_pair.h> #include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <zircon/types.h> #include <zircon/types.h>
#include "base/auto_reset.h" #include "base/auto_reset.h"
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include "fuchsia/engine/test/web_engine_browser_test.h" #include "fuchsia/engine/test/web_engine_browser_test.h"
#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/switches.h"
#include "ui/ozone/public/ozone_switches.h"
using fuchsia::accessibility::semantics::Node; using fuchsia::accessibility::semantics::Node;
using fuchsia::accessibility::semantics::SemanticListener; using fuchsia::accessibility::semantics::SemanticListener;
...@@ -98,6 +100,16 @@ class FakeSemanticTree ...@@ -98,6 +100,16 @@ class FakeSemanticTree
return false; return false;
} }
Node* GetNodeFromLabel(base::StringPiece name) {
for (auto& node : nodes_) {
if (node.has_attributes() && node.attributes().has_label() &&
node.attributes().label() == name) {
return &node;
}
}
return nullptr;
}
private: private:
std::vector<Node> nodes_; std::vector<Node> nodes_;
base::RepeatingClosure on_commit_updates_; base::RepeatingClosure on_commit_updates_;
...@@ -120,6 +132,25 @@ class FakeSemanticsManager : public fuchsia::accessibility::semantics::testing:: ...@@ -120,6 +132,25 @@ class FakeSemanticsManager : public fuchsia::accessibility::semantics::testing::
listener_->OnSemanticsModeChanged(is_enabled, []() {}); listener_->OnSemanticsModeChanged(is_enabled, []() {});
} }
// The value returned by hit testing is written to a class member. In the case
// Run() times out, the function continues so we don't want to write to a
// local variable.
uint32_t HitTestAtPointSync(fuchsia::math::PointF target_point) {
hit_test_result_.reset();
base::RunLoop run_loop;
listener_->HitTest(target_point,
[quit = run_loop.QuitClosure(),
this](fuchsia::accessibility::semantics::Hit hit) {
if (hit.has_node_id()) {
hit_test_result_ = hit.node_id();
}
quit.Run();
});
run_loop.Run();
return hit_test_result_.value();
}
// fuchsia::accessibility::semantics::SemanticsManager implementation. // fuchsia::accessibility::semantics::SemanticsManager implementation.
void RegisterViewForSemantics( void RegisterViewForSemantics(
fuchsia::ui::views::ViewRef view_ref, fuchsia::ui::views::ViewRef view_ref,
...@@ -139,10 +170,18 @@ class FakeSemanticsManager : public fuchsia::accessibility::semantics::testing:: ...@@ -139,10 +170,18 @@ class FakeSemanticsManager : public fuchsia::accessibility::semantics::testing::
fuchsia::accessibility::semantics::SemanticListenerPtr listener_; fuchsia::accessibility::semantics::SemanticListenerPtr listener_;
FakeSemanticTree semantic_tree_; FakeSemanticTree semantic_tree_;
fidl::Binding<SemanticTree> semantic_tree_binding_; fidl::Binding<SemanticTree> semantic_tree_binding_;
base::Optional<uint32_t> hit_test_result_;
DISALLOW_COPY_AND_ASSIGN(FakeSemanticsManager); DISALLOW_COPY_AND_ASSIGN(FakeSemanticsManager);
}; };
fuchsia::math::PointF GetCenterOfBox(fuchsia::ui::gfx::BoundingBox box) {
fuchsia::math::PointF center;
center.x = (box.min.x + box.max.x) / 2;
center.y = (box.min.y + box.max.y) / 2;
return center;
}
} // namespace } // namespace
class AccessibilityBridgeTest : public cr_fuchsia::WebEngineBrowserTest { class AccessibilityBridgeTest : public cr_fuchsia::WebEngineBrowserTest {
...@@ -154,6 +193,14 @@ class AccessibilityBridgeTest : public cr_fuchsia::WebEngineBrowserTest { ...@@ -154,6 +193,14 @@ class AccessibilityBridgeTest : public cr_fuchsia::WebEngineBrowserTest {
~AccessibilityBridgeTest() override = default; ~AccessibilityBridgeTest() override = default;
void SetUp() override {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitchNative(switches::kOzonePlatform,
switches::kHeadless);
command_line->AppendSwitch(switches::kHeadless);
cr_fuchsia::WebEngineBrowserTest::SetUp();
}
void SetUpOnMainThread() override { void SetUpOnMainThread() override {
fuchsia::accessibility::semantics::SemanticsManagerPtr fuchsia::accessibility::semantics::SemanticsManagerPtr
semantics_manager_ptr; semantics_manager_ptr;
...@@ -164,10 +211,8 @@ class AccessibilityBridgeTest : public cr_fuchsia::WebEngineBrowserTest { ...@@ -164,10 +211,8 @@ class AccessibilityBridgeTest : public cr_fuchsia::WebEngineBrowserTest {
frame_impl_ = context_impl()->GetFrameImplForTest(&frame_ptr_); frame_impl_ = context_impl()->GetFrameImplForTest(&frame_ptr_);
frame_impl_->set_semantics_manager_for_test( frame_impl_->set_semantics_manager_for_test(
std::move(semantics_manager_ptr)); std::move(semantics_manager_ptr));
frame_ptr_->EnableHeadlessRendering();
// Call CreateView to trigger creation of accessibility bridge.
auto view_tokens = scenic::NewViewTokenPair();
frame_ptr_->CreateView(std::move(view_tokens.first));
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
...@@ -202,12 +247,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, CorrectDataSent) { ...@@ -202,12 +247,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, CorrectDataSent) {
fuchsia::web::NavigationControllerPtr controller; fuchsia::web::NavigationControllerPtr controller;
frame_ptr_->GetNavigationController(controller.NewRequest()); frame_ptr_->GetNavigationController(controller.NewRequest());
ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(embedded_test_server()->Start());
GURL title1(embedded_test_server()->GetURL(kPage1Path));
semantics_manager_.SetSemanticsModeEnabled(true); semantics_manager_.SetSemanticsModeEnabled(true);
GURL page_url1(embedded_test_server()->GetURL(kPage1Path));
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse( EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
controller.get(), fuchsia::web::LoadUrlParams(), title1.spec())); controller.get(), fuchsia::web::LoadUrlParams(), page_url1.spec()));
navigation_listener_.RunUntilUrlAndTitleEquals(title1, kPage1Title); navigation_listener_.RunUntilUrlAndTitleEquals(page_url1, kPage1Title);
// Check that the data values are correct in the FakeSemanticTree. // Check that the data values are correct in the FakeSemanticTree.
// TODO(fxb/18796): Test more fields once Chrome to Fuchsia conversions are // TODO(fxb/18796): Test more fields once Chrome to Fuchsia conversions are
...@@ -228,12 +273,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, DataSentWithBatching) { ...@@ -228,12 +273,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, DataSentWithBatching) {
fuchsia::web::NavigationControllerPtr controller; fuchsia::web::NavigationControllerPtr controller;
frame_ptr_->GetNavigationController(controller.NewRequest()); frame_ptr_->GetNavigationController(controller.NewRequest());
ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(embedded_test_server()->Start());
GURL title2(embedded_test_server()->GetURL(kPage2Path));
semantics_manager_.SetSemanticsModeEnabled(true); semantics_manager_.SetSemanticsModeEnabled(true);
GURL page_url2(embedded_test_server()->GetURL(kPage2Path));
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse( EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
controller.get(), fuchsia::web::LoadUrlParams(), title2.spec())); controller.get(), fuchsia::web::LoadUrlParams(), page_url2.spec()));
navigation_listener_.RunUntilUrlAndTitleEquals(title2, kPage2Title); navigation_listener_.RunUntilUrlAndTitleEquals(page_url2, kPage2Title);
// Run until we expect more than a batch's worth of nodes to be present. // Run until we expect more than a batch's worth of nodes to be present.
semantics_manager_.semantic_tree()->RunUntilNodeCountAtLeast(kPage2NodeCount); semantics_manager_.semantic_tree()->RunUntilNodeCountAtLeast(kPage2NodeCount);
...@@ -246,12 +291,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, TestNavigation) { ...@@ -246,12 +291,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, TestNavigation) {
fuchsia::web::NavigationControllerPtr controller; fuchsia::web::NavigationControllerPtr controller;
frame_ptr_->GetNavigationController(controller.NewRequest()); frame_ptr_->GetNavigationController(controller.NewRequest());
ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(embedded_test_server()->Start());
GURL title1(embedded_test_server()->GetURL(kPage1Path));
semantics_manager_.SetSemanticsModeEnabled(true); semantics_manager_.SetSemanticsModeEnabled(true);
GURL page_url1(embedded_test_server()->GetURL(kPage1Path));
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse( EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
controller.get(), fuchsia::web::LoadUrlParams(), title1.spec())); controller.get(), fuchsia::web::LoadUrlParams(), page_url1.spec()));
navigation_listener_.RunUntilUrlAndTitleEquals(title1, kPage1Title); navigation_listener_.RunUntilUrlAndTitleEquals(page_url1, kPage1Title);
semantics_manager_.semantic_tree()->RunUntilNodeCountAtLeast(kPage1NodeCount); semantics_manager_.semantic_tree()->RunUntilNodeCountAtLeast(kPage1NodeCount);
EXPECT_TRUE( EXPECT_TRUE(
...@@ -261,9 +306,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, TestNavigation) { ...@@ -261,9 +306,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, TestNavigation) {
EXPECT_TRUE( EXPECT_TRUE(
semantics_manager_.semantic_tree()->HasNodeWithLabel(kParagraphName)); semantics_manager_.semantic_tree()->HasNodeWithLabel(kParagraphName));
GURL title2(embedded_test_server()->GetURL(kPage2Path)); GURL page_url2(embedded_test_server()->GetURL(kPage2Path));
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse( EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
controller.get(), fuchsia::web::LoadUrlParams(), title2.spec())); controller.get(), fuchsia::web::LoadUrlParams(), page_url2.spec()));
semantics_manager_.semantic_tree()->RunUntilNodeCountAtLeast(kPage2NodeCount); semantics_manager_.semantic_tree()->RunUntilNodeCountAtLeast(kPage2NodeCount);
EXPECT_TRUE( EXPECT_TRUE(
...@@ -276,3 +321,37 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, TestNavigation) { ...@@ -276,3 +321,37 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, TestNavigation) {
EXPECT_FALSE( EXPECT_FALSE(
semantics_manager_.semantic_tree()->HasNodeWithLabel(kParagraphName)); semantics_manager_.semantic_tree()->HasNodeWithLabel(kParagraphName));
} }
// Checks that the correct node ID is returned when performing hit testing.
IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, HitTest) {
fuchsia::web::NavigationControllerPtr controller;
frame_ptr_->GetNavigationController(controller.NewRequest());
ASSERT_TRUE(embedded_test_server()->Start());
semantics_manager_.SetSemanticsModeEnabled(true);
GURL page_url1(embedded_test_server()->GetURL(kPage1Path));
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
controller.get(), fuchsia::web::LoadUrlParams(), page_url1.spec()));
navigation_listener_.RunUntilUrlAndTitleEquals(page_url1, kPage1Title);
semantics_manager_.semantic_tree()->RunUntilNodeCountAtLeast(kPage1NodeCount);
EXPECT_TRUE(
semantics_manager_.semantic_tree()->HasNodeWithLabel(kParagraphName));
Node* hit_test_node =
semantics_manager_.semantic_tree()->GetNodeFromLabel(kParagraphName);
fuchsia::math::PointF target_point =
GetCenterOfBox(hit_test_node->location());
EXPECT_EQ(hit_test_node->node_id(),
semantics_manager_.HitTestAtPointSync(std::move(target_point)));
// Expect hit testing to return the root when the point given is out of
// bounds or there is no semantic node at that position.
target_point.x = -1;
target_point.y = -1;
EXPECT_EQ(0u, semantics_manager_.HitTestAtPointSync(std::move(target_point)));
target_point.x = 1;
target_point.y = 1;
EXPECT_EQ(0u, semantics_manager_.HitTestAtPointSync(std::move(target_point)));
}
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include <lib/sys/cpp/component_context.h> #include <lib/sys/cpp/component_context.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h> #include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <limits>
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/fuchsia/default_context.h" #include "base/fuchsia/default_context.h"
...@@ -51,6 +50,10 @@ namespace { ...@@ -51,6 +50,10 @@ namespace {
const logging::LogSeverity kLogSeverityNone = const logging::LogSeverity kLogSeverityNone =
std::numeric_limits<logging::LogSeverity>::min(); std::numeric_limits<logging::LogSeverity>::min();
// Size of screen bounds when using headless rendering.
constexpr gfx::Size kSemanticsTestingWindowSize = {720, 640};
constexpr gfx::Size kHeadlessWindowSize = {1, 1};
// Used for attaching popup-related metadata to a WebContents. // Used for attaching popup-related metadata to a WebContents.
constexpr char kPopupCreationInfo[] = "popup-creation-info"; constexpr char kPopupCreationInfo[] = "popup-creation-info";
class PopupFrameCreationInfoUserData : public base::SupportsUserData::Data { class PopupFrameCreationInfoUserData : public base::SupportsUserData::Data {
...@@ -528,23 +531,20 @@ void FrameImpl::CreateView(fuchsia::ui::views::ViewToken view_token) { ...@@ -528,23 +531,20 @@ void FrameImpl::CreateView(fuchsia::ui::views::ViewToken view_token) {
fuchsia::ui::views::ViewRef accessibility_view_ref; fuchsia::ui::views::ViewRef accessibility_view_ref;
zx_status_t status = properties.view_ref_pair.view_ref.reference.duplicate( zx_status_t status = properties.view_ref_pair.view_ref.reference.duplicate(
ZX_RIGHT_SAME_RIGHTS, &accessibility_view_ref.reference); ZX_RIGHT_SAME_RIGHTS, &accessibility_view_ref.reference);
if (status == ZX_OK) { if (status != ZX_OK) {
fuchsia::accessibility::semantics::SemanticsManagerPtr semantics_manager;
if (test_semantics_manager_ptr_) {
semantics_manager = std::move(test_semantics_manager_ptr_);
} else {
semantics_manager =
base::fuchsia::ComponentContextForCurrentProcess()
->svc()
->Connect<fuchsia::accessibility::semantics::SemanticsManager>();
}
accessibility_bridge_ = std::make_unique<AccessibilityBridge>(
std::move(semantics_manager), std::move(accessibility_view_ref),
web_contents_.get());
} else {
ZX_LOG(ERROR, status) << "zx_object_duplicate"; ZX_LOG(ERROR, status) << "zx_object_duplicate";
context_->DestroyFrame(this);
return;
} }
fuchsia::accessibility::semantics::SemanticsManagerPtr semantics_manager =
base::fuchsia::ComponentContextForCurrentProcess()
->svc()
->Connect<fuchsia::accessibility::semantics::SemanticsManager>();
accessibility_bridge_ = std::make_unique<AccessibilityBridge>(
std::move(semantics_manager), std::move(accessibility_view_ref),
web_contents_.get());
SetWindowTreeHost( SetWindowTreeHost(
std::make_unique<FrameWindowTreeHost>(std::move(properties))); std::make_unique<FrameWindowTreeHost>(std::move(properties)));
} }
...@@ -744,6 +744,19 @@ void FrameImpl::EnableHeadlessRendering() { ...@@ -744,6 +744,19 @@ void FrameImpl::EnableHeadlessRendering() {
SetWindowTreeHost(std::make_unique<FrameWindowTreeHost>( SetWindowTreeHost(std::make_unique<FrameWindowTreeHost>(
ui::PlatformWindowInitProperties())); ui::PlatformWindowInitProperties()));
gfx::Rect bounds(kHeadlessWindowSize);
if (semantics_manager_for_test_) {
scenic::ViewRefPair view_ref_pair = scenic::ViewRefPair::New();
accessibility_bridge_ = std::make_unique<AccessibilityBridge>(
std::move(semantics_manager_for_test_),
std::move(view_ref_pair.view_ref), web_contents_.get());
// Set bounds for testing hit testing.
bounds.set_size(kSemanticsTestingWindowSize);
}
window_tree_host_->SetBoundsInPixels(bounds);
} }
void FrameImpl::DisableHeadlessRendering() { void FrameImpl::DisableHeadlessRendering() {
......
...@@ -74,7 +74,7 @@ class FrameImpl : public fuchsia::web::Frame, ...@@ -74,7 +74,7 @@ class FrameImpl : public fuchsia::web::Frame,
void set_semantics_manager_for_test( void set_semantics_manager_for_test(
fuchsia::accessibility::semantics::SemanticsManagerPtr fuchsia::accessibility::semantics::SemanticsManagerPtr
semantics_manager) { semantics_manager) {
test_semantics_manager_ptr_ = std::move(semantics_manager); semantics_manager_for_test_ = std::move(semantics_manager);
} }
private: private:
...@@ -203,7 +203,7 @@ class FrameImpl : public fuchsia::web::Frame, ...@@ -203,7 +203,7 @@ class FrameImpl : public fuchsia::web::Frame,
ContextImpl* const context_; ContextImpl* const context_;
std::unique_ptr<AccessibilityBridge> accessibility_bridge_; std::unique_ptr<AccessibilityBridge> accessibility_bridge_;
fuchsia::accessibility::semantics::SemanticsManagerPtr fuchsia::accessibility::semantics::SemanticsManagerPtr
test_semantics_manager_ptr_; semantics_manager_for_test_;
DiscardingEventFilter discarding_event_filter_; DiscardingEventFilter discarding_event_filter_;
NavigationControllerImpl navigation_controller_; NavigationControllerImpl navigation_controller_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment