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 @@
#include <fuchsia/accessibility/semantics/cpp/fidl.h>
#include <fuchsia/accessibility/semantics/cpp/fidl_test_base.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 "base/auto_reset.h"
......@@ -23,6 +23,8 @@
#include "fuchsia/engine/test/web_engine_browser_test.h"
#include "net/test/embedded_test_server/embedded_test_server.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::SemanticListener;
......@@ -98,6 +100,16 @@ class FakeSemanticTree
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:
std::vector<Node> nodes_;
base::RepeatingClosure on_commit_updates_;
......@@ -120,6 +132,25 @@ class FakeSemanticsManager : public fuchsia::accessibility::semantics::testing::
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.
void RegisterViewForSemantics(
fuchsia::ui::views::ViewRef view_ref,
......@@ -139,10 +170,18 @@ class FakeSemanticsManager : public fuchsia::accessibility::semantics::testing::
fuchsia::accessibility::semantics::SemanticListenerPtr listener_;
FakeSemanticTree semantic_tree_;
fidl::Binding<SemanticTree> semantic_tree_binding_;
base::Optional<uint32_t> hit_test_result_;
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
class AccessibilityBridgeTest : public cr_fuchsia::WebEngineBrowserTest {
......@@ -154,6 +193,14 @@ class AccessibilityBridgeTest : public cr_fuchsia::WebEngineBrowserTest {
~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 {
fuchsia::accessibility::semantics::SemanticsManagerPtr
semantics_manager_ptr;
......@@ -164,10 +211,8 @@ class AccessibilityBridgeTest : public cr_fuchsia::WebEngineBrowserTest {
frame_impl_ = context_impl()->GetFrameImplForTest(&frame_ptr_);
frame_impl_->set_semantics_manager_for_test(
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();
}
......@@ -202,12 +247,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, CorrectDataSent) {
fuchsia::web::NavigationControllerPtr controller;
frame_ptr_->GetNavigationController(controller.NewRequest());
ASSERT_TRUE(embedded_test_server()->Start());
GURL title1(embedded_test_server()->GetURL(kPage1Path));
semantics_manager_.SetSemanticsModeEnabled(true);
GURL page_url1(embedded_test_server()->GetURL(kPage1Path));
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
controller.get(), fuchsia::web::LoadUrlParams(), title1.spec()));
navigation_listener_.RunUntilUrlAndTitleEquals(title1, kPage1Title);
controller.get(), fuchsia::web::LoadUrlParams(), page_url1.spec()));
navigation_listener_.RunUntilUrlAndTitleEquals(page_url1, kPage1Title);
// Check that the data values are correct in the FakeSemanticTree.
// TODO(fxb/18796): Test more fields once Chrome to Fuchsia conversions are
......@@ -228,12 +273,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, DataSentWithBatching) {
fuchsia::web::NavigationControllerPtr controller;
frame_ptr_->GetNavigationController(controller.NewRequest());
ASSERT_TRUE(embedded_test_server()->Start());
GURL title2(embedded_test_server()->GetURL(kPage2Path));
semantics_manager_.SetSemanticsModeEnabled(true);
GURL page_url2(embedded_test_server()->GetURL(kPage2Path));
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
controller.get(), fuchsia::web::LoadUrlParams(), title2.spec()));
navigation_listener_.RunUntilUrlAndTitleEquals(title2, kPage2Title);
controller.get(), fuchsia::web::LoadUrlParams(), page_url2.spec()));
navigation_listener_.RunUntilUrlAndTitleEquals(page_url2, kPage2Title);
// Run until we expect more than a batch's worth of nodes to be present.
semantics_manager_.semantic_tree()->RunUntilNodeCountAtLeast(kPage2NodeCount);
......@@ -246,12 +291,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, TestNavigation) {
fuchsia::web::NavigationControllerPtr controller;
frame_ptr_->GetNavigationController(controller.NewRequest());
ASSERT_TRUE(embedded_test_server()->Start());
GURL title1(embedded_test_server()->GetURL(kPage1Path));
semantics_manager_.SetSemanticsModeEnabled(true);
GURL page_url1(embedded_test_server()->GetURL(kPage1Path));
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
controller.get(), fuchsia::web::LoadUrlParams(), title1.spec()));
navigation_listener_.RunUntilUrlAndTitleEquals(title1, kPage1Title);
controller.get(), fuchsia::web::LoadUrlParams(), page_url1.spec()));
navigation_listener_.RunUntilUrlAndTitleEquals(page_url1, kPage1Title);
semantics_manager_.semantic_tree()->RunUntilNodeCountAtLeast(kPage1NodeCount);
EXPECT_TRUE(
......@@ -261,9 +306,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, TestNavigation) {
EXPECT_TRUE(
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(
controller.get(), fuchsia::web::LoadUrlParams(), title2.spec()));
controller.get(), fuchsia::web::LoadUrlParams(), page_url2.spec()));
semantics_manager_.semantic_tree()->RunUntilNodeCountAtLeast(kPage2NodeCount);
EXPECT_TRUE(
......@@ -276,3 +321,37 @@ IN_PROC_BROWSER_TEST_F(AccessibilityBridgeTest, TestNavigation) {
EXPECT_FALSE(
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 @@
#include <lib/sys/cpp/component_context.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <limits>
#include "base/bind_helpers.h"
#include "base/fuchsia/default_context.h"
......@@ -51,6 +50,10 @@ namespace {
const logging::LogSeverity kLogSeverityNone =
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.
constexpr char kPopupCreationInfo[] = "popup-creation-info";
class PopupFrameCreationInfoUserData : public base::SupportsUserData::Data {
......@@ -528,23 +531,20 @@ void FrameImpl::CreateView(fuchsia::ui::views::ViewToken view_token) {
fuchsia::ui::views::ViewRef accessibility_view_ref;
zx_status_t status = properties.view_ref_pair.view_ref.reference.duplicate(
ZX_RIGHT_SAME_RIGHTS, &accessibility_view_ref.reference);
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 {
if (status != ZX_OK) {
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(
std::make_unique<FrameWindowTreeHost>(std::move(properties)));
}
......@@ -744,6 +744,19 @@ void FrameImpl::EnableHeadlessRendering() {
SetWindowTreeHost(std::make_unique<FrameWindowTreeHost>(
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() {
......
......@@ -74,7 +74,7 @@ class FrameImpl : public fuchsia::web::Frame,
void set_semantics_manager_for_test(
fuchsia::accessibility::semantics::SemanticsManagerPtr
semantics_manager) {
test_semantics_manager_ptr_ = std::move(semantics_manager);
semantics_manager_for_test_ = std::move(semantics_manager);
}
private:
......@@ -203,7 +203,7 @@ class FrameImpl : public fuchsia::web::Frame,
ContextImpl* const context_;
std::unique_ptr<AccessibilityBridge> accessibility_bridge_;
fuchsia::accessibility::semantics::SemanticsManagerPtr
test_semantics_manager_ptr_;
semantics_manager_for_test_;
DiscardingEventFilter discarding_event_filter_;
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