Commit 0297659d authored by Victor Fei's avatar Victor Fei Committed by Commit Bot

Stablizing Mac autofill accessibility when popup show/hides

This is a follow up change of CL:1667787, which introduced
AutofillPopupControllerImpl::FireControlsChangedEvent for autofill
popup accessibility.

On Mac and potentially other platforms, when accessibility is
enabled, upon invoking autofill popup and FireControlsChangedEvent
we end up dereferencing a nullptr of AxPlatformNode due to
Mac does not have a complete implementation of AxPlatformNode yet.

This CL fixes the above by adding a check for AxPlatformNode in
FireControlsChangedEvent.

Changes:
 1. Introduced a check for invalid AxPlatformNode in
    AutofillPopupControllerImpl::FireControlsChangedEvent to return
    early from firing event.
 2. Added associated unit tests for FireControlsChangedEvent.
 3. Exposed GetWebContentsPopupControllerAxId virtual to
    AutofillPopupDelegate..

Bug: 986587
Change-Id: I9a6ed49330a9ea9d7d4e5483c3ee06d5675919ee
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1714297
Commit-Queue: Victor Fei <vicfei@microsoft.com>
Reviewed-by: default avatarEvan Stade <estade@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarIan Prest <iapres@microsoft.com>
Reviewed-by: default avatarNektarios Paisios <nektar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#686461}
parent b6df81a7
...@@ -597,24 +597,31 @@ void AutofillPopupControllerImpl::FireControlsChangedEvent(bool is_show) { ...@@ -597,24 +597,31 @@ void AutofillPopupControllerImpl::FireControlsChangedEvent(bool is_show) {
// Retrieve the ax node id associated with the current web contents' element // Retrieve the ax node id associated with the current web contents' element
// that has a controller relation to the current autofill popup. // that has a controller relation to the current autofill popup.
int32_t node_id = static_cast<AutofillExternalDelegate*>(delegate_.get()) int32_t node_id = delegate_->GetWebContentsPopupControllerAxId();
->GetWebContentsPopupControllerAxId();
// We can only raise controls changed accessibility event when we have a valid // We can only raise controls changed accessibility event when we have a valid
// ax tree and an ax node associated with the ax tree for the popup // ax tree and an ax node associated with the ax tree for the popup
// controller, and a valid ax unique id for the popup controllee. // controller, and a valid ax unique id for the popup controllee.
if (!ax_tree_manager || !ax_tree_manager->GetDelegate(tree_id, node_id) || if (!ax_tree_manager)
!view_->GetAxUniqueId()) return;
ui::AXPlatformNodeDelegate* ax_platform_node_delegate =
ax_tree_manager->GetDelegate(tree_id, node_id);
if (!ax_platform_node_delegate)
return;
ui::AXPlatformNode* target_node =
ax_platform_node_delegate->GetFromNodeID(node_id);
base::Optional<int32_t> popup_ax_id = view_->GetAxUniqueId();
if (!target_node || !popup_ax_id)
return; return;
// All the conditions are valid, raise the accessibility event and set global
// popup ax unique id.
if (is_show) if (is_show)
ui::SetActivePopupAxUniqueId(view_->GetAxUniqueId()); ui::SetActivePopupAxUniqueId(popup_ax_id);
else else
ui::ClearActivePopupAxUniqueId(); ui::ClearActivePopupAxUniqueId();
ax_tree_manager->GetDelegate(tree_id, node_id) target_node->NotifyAccessibilityEvent(ax::mojom::Event::kControlsChanged);
->GetFromNodeID(node_id)
->NotifyAccessibilityEvent(ax::mojom::Event::kControlsChanged);
} }
} // namespace autofill } // namespace autofill
...@@ -139,6 +139,11 @@ class AutofillPopupControllerImpl : public AutofillPopupController { ...@@ -139,6 +139,11 @@ class AutofillPopupControllerImpl : public AutofillPopupController {
AutofillPopupLayoutModel& LayoutModelForTesting() { return layout_model_; } AutofillPopupLayoutModel& LayoutModelForTesting() { return layout_model_; }
// Raise an accessibility event to indicate the controls relation of the
// form control of the popup and popup itself has changed based on the popup's
// show or hide action.
void FireControlsChangedEvent(bool is_show);
private: private:
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
FRIEND_TEST_ALL_PREFIXES(AutofillPopupControllerUnitTest, ElideText); FRIEND_TEST_ALL_PREFIXES(AutofillPopupControllerUnitTest, ElideText);
...@@ -155,12 +160,8 @@ class AutofillPopupControllerImpl : public AutofillPopupController { ...@@ -155,12 +160,8 @@ class AutofillPopupControllerImpl : public AutofillPopupController {
// Hides |view_| unless it is null and then deletes |this|. // Hides |view_| unless it is null and then deletes |this|.
void HideViewAndDie(); void HideViewAndDie();
// Raise an accessibility event to indicate the controls relation of the
// form control of the popup and popup itself has changed based on the popup's
// show or hide action.
void FireControlsChangedEvent(bool is_show);
friend class AutofillPopupControllerUnitTest; friend class AutofillPopupControllerUnitTest;
friend class AutofillPopupControllerAccessibilityUnitTest;
void SetViewForTesting(AutofillPopupView* view) { view_ = view; } void SetViewForTesting(AutofillPopupView* view) { view_ = view; }
PopupControllerCommon controller_common_; PopupControllerCommon controller_common_;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/optional.h" #include "base/optional.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/accessibility/accessibility_state_utils.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h" #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
#include "chrome/browser/ui/autofill/autofill_popup_view.h" #include "chrome/browser/ui/autofill/autofill_popup_view.h"
#include "chrome/browser/ui/autofill/popup_view_common.h" #include "chrome/browser/ui/autofill/popup_view_common.h"
...@@ -23,14 +24,26 @@ ...@@ -23,14 +24,26 @@
#include "components/autofill/core/browser/autofill_manager.h" #include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/test_autofill_client.h" #include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/ui/popup_item_ids.h" #include "components/autofill/core/browser/ui/popup_item_ids.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/ax_active_popup.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_tree_id.h"
#include "ui/accessibility/ax_tree_manager.h"
#include "ui/accessibility/ax_tree_manager_map.h"
#include "ui/accessibility/platform/ax_platform_node_base.h"
#include "ui/accessibility/platform/ax_platform_node_delegate_base.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/text_utils.h" #include "ui/gfx/text_utils.h"
#if !defined(OS_CHROMEOS)
#include "content/public/browser/browser_accessibility_state.h"
#endif
using ::testing::_; using ::testing::_;
using ::testing::AtLeast; using ::testing::AtLeast;
using ::testing::Mock; using ::testing::Mock;
...@@ -42,12 +55,48 @@ using base::WeakPtr; ...@@ -42,12 +55,48 @@ using base::WeakPtr;
namespace autofill { namespace autofill {
namespace { namespace {
class MockAutofillDriver : public TestAutofillDriver {
public:
MockAutofillDriver() = default;
~MockAutofillDriver() override = default;
MOCK_CONST_METHOD0(GetAxTreeId, ui::AXTreeID());
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillDriver);
};
class MockAutofillClient : public autofill::TestAutofillClient {
public:
MockAutofillClient() : prefs_(autofill::test::PrefServiceForTesting()) {}
~MockAutofillClient() override = default;
PrefService* GetPrefs() override { return prefs_.get(); }
private:
std::unique_ptr<PrefService> prefs_;
DISALLOW_COPY_AND_ASSIGN(MockAutofillClient);
};
class MockAutofillManager : public AutofillManager {
public:
MockAutofillManager(AutofillDriver* driver, MockAutofillClient* client)
: AutofillManager(driver,
client,
client->GetPersonalDataManager(),
client->GetAutocompleteHistoryManager()) {}
~MockAutofillManager() override = default;
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillManager);
};
class MockAutofillExternalDelegate : public AutofillExternalDelegate { class MockAutofillExternalDelegate : public AutofillExternalDelegate {
public: public:
MockAutofillExternalDelegate(AutofillManager* autofill_manager, MockAutofillExternalDelegate(AutofillManager* autofill_manager,
AutofillDriver* autofill_driver) AutofillDriver* autofill_driver)
: AutofillExternalDelegate(autofill_manager, autofill_driver) {} : AutofillExternalDelegate(autofill_manager, autofill_driver) {}
~MockAutofillExternalDelegate() override {} ~MockAutofillExternalDelegate() override = default;
void DidSelectSuggestion(const base::string16& value, void DidSelectSuggestion(const base::string16& value,
int identifier) override {} int identifier) override {}
...@@ -62,22 +111,10 @@ class MockAutofillExternalDelegate : public AutofillExternalDelegate { ...@@ -62,22 +111,10 @@ class MockAutofillExternalDelegate : public AutofillExternalDelegate {
MOCK_METHOD0(OnPopupSuppressed, void()); MOCK_METHOD0(OnPopupSuppressed, void());
}; };
class MockAutofillClient : public autofill::TestAutofillClient {
public:
MockAutofillClient() : prefs_(autofill::test::PrefServiceForTesting()) {}
~MockAutofillClient() override {}
PrefService* GetPrefs() override { return prefs_.get(); }
private:
std::unique_ptr<PrefService> prefs_;
DISALLOW_COPY_AND_ASSIGN(MockAutofillClient);
};
class MockAutofillPopupView : public AutofillPopupView { class MockAutofillPopupView : public AutofillPopupView {
public: public:
MockAutofillPopupView() {} MockAutofillPopupView() = default;
~MockAutofillPopupView() override = default;
MOCK_METHOD0(Show, void()); MOCK_METHOD0(Show, void());
MOCK_METHOD0(Hide, void()); MOCK_METHOD0(Hide, void());
...@@ -104,22 +141,23 @@ class TestAutofillPopupController : public AutofillPopupControllerImpl { ...@@ -104,22 +141,23 @@ class TestAutofillPopupController : public AutofillPopupControllerImpl {
LayoutModelForTesting().SetUpForTesting( LayoutModelForTesting().SetUpForTesting(
std::make_unique<MockPopupViewCommonForUnitTesting>()); std::make_unique<MockPopupViewCommonForUnitTesting>());
} }
~TestAutofillPopupController() override {} ~TestAutofillPopupController() override = default;
// Making protected functions public for testing // Making protected functions public for testing
using AutofillPopupControllerImpl::element_bounds;
using AutofillPopupControllerImpl::FireControlsChangedEvent;
using AutofillPopupControllerImpl::GetElidedLabelAt;
using AutofillPopupControllerImpl::GetElidedValueAt;
using AutofillPopupControllerImpl::GetLineCount; using AutofillPopupControllerImpl::GetLineCount;
using AutofillPopupControllerImpl::GetSuggestionAt; using AutofillPopupControllerImpl::GetSuggestionAt;
using AutofillPopupControllerImpl::GetElidedValueAt; using AutofillPopupControllerImpl::GetWeakPtr;
using AutofillPopupControllerImpl::GetElidedLabelAt; using AutofillPopupControllerImpl::popup_bounds;
using AutofillPopupControllerImpl::RemoveSelectedLine;
using AutofillPopupControllerImpl::selected_line; using AutofillPopupControllerImpl::selected_line;
using AutofillPopupControllerImpl::SetSelectedLine;
using AutofillPopupControllerImpl::SelectNextLine; using AutofillPopupControllerImpl::SelectNextLine;
using AutofillPopupControllerImpl::SelectPreviousLine; using AutofillPopupControllerImpl::SelectPreviousLine;
using AutofillPopupControllerImpl::RemoveSelectedLine; using AutofillPopupControllerImpl::SetSelectedLine;
using AutofillPopupControllerImpl::popup_bounds;
using AutofillPopupControllerImpl::element_bounds;
using AutofillPopupControllerImpl::SetValues; using AutofillPopupControllerImpl::SetValues;
using AutofillPopupControllerImpl::GetWeakPtr;
MOCK_METHOD0(OnSuggestionsChanged, void()); MOCK_METHOD0(OnSuggestionsChanged, void());
MOCK_METHOD0(Hide, void()); MOCK_METHOD0(Hide, void());
...@@ -128,6 +166,39 @@ class TestAutofillPopupController : public AutofillPopupControllerImpl { ...@@ -128,6 +166,39 @@ class TestAutofillPopupController : public AutofillPopupControllerImpl {
} }
}; };
class MockAxTreeManager : public ui::AXTreeManager {
public:
MockAxTreeManager() = default;
~MockAxTreeManager() = default;
MOCK_CONST_METHOD2(GetNodeFromTree,
ui::AXNode*(const ui::AXTreeID tree_id,
const int32_t node_id));
MOCK_CONST_METHOD2(GetDelegate,
ui::AXPlatformNodeDelegate*(const ui::AXTreeID tree_id,
const int32_t node_id));
MOCK_CONST_METHOD1(GetRootDelegate,
ui::AXPlatformNodeDelegate*(const ui::AXTreeID tree_id));
MOCK_CONST_METHOD0(GetTreeID, ui::AXTreeID());
MOCK_CONST_METHOD0(GetParentTreeID, ui::AXTreeID());
MOCK_CONST_METHOD0(GetRootAsAXNode, ui::AXNode*());
MOCK_CONST_METHOD0(GetParentNodeFromParentTreeAsAXNode, ui::AXNode*());
private:
DISALLOW_COPY_AND_ASSIGN(MockAxTreeManager);
};
class MockAxPlatformNodeDelegate : public ui::AXPlatformNodeDelegateBase {
public:
MockAxPlatformNodeDelegate() = default;
~MockAxPlatformNodeDelegate() override = default;
MOCK_METHOD1(GetFromNodeID, ui::AXPlatformNode*(int32_t id));
private:
DISALLOW_COPY_AND_ASSIGN(MockAxPlatformNodeDelegate);
};
static constexpr base::Optional<int> kNoSelection; static constexpr base::Optional<int> kNoSelection;
} // namespace } // namespace
...@@ -137,25 +208,12 @@ class AutofillPopupControllerUnitTest : public ChromeRenderViewHostTestHarness { ...@@ -137,25 +208,12 @@ class AutofillPopupControllerUnitTest : public ChromeRenderViewHostTestHarness {
AutofillPopupControllerUnitTest() AutofillPopupControllerUnitTest()
: autofill_client_(new MockAutofillClient()), : autofill_client_(new MockAutofillClient()),
autofill_popup_controller_(NULL) {} autofill_popup_controller_(NULL) {}
~AutofillPopupControllerUnitTest() override {} ~AutofillPopupControllerUnitTest() override = default;
void SetUp() override { void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp(); ChromeRenderViewHostTestHarness::SetUp();
external_delegate_ = CreateExternalDelegate();
ContentAutofillDriverFactory::CreateForWebContentsAndDelegate( autofill_popup_view_ = std::make_unique<NiceMock<MockAutofillPopupView>>();
web_contents(), autofill_client_.get(), "en-US",
AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
// Make sure RenderFrame is created.
NavigateAndCommit(GURL("about:blank"));
ContentAutofillDriverFactory* factory =
ContentAutofillDriverFactory::FromWebContents(web_contents());
ContentAutofillDriver* driver =
factory->DriverForFrame(web_contents()->GetMainFrame());
external_delegate_.reset(
new NiceMock<MockAutofillExternalDelegate>(
driver->autofill_manager(),
driver));
autofill_popup_view_.reset(new NiceMock<MockAutofillPopupView>());
autofill_popup_controller_ = new NiceMock<TestAutofillPopupController>( autofill_popup_controller_ = new NiceMock<TestAutofillPopupController>(
external_delegate_->GetWeakPtr(), gfx::RectF()); external_delegate_->GetWeakPtr(), gfx::RectF());
autofill_popup_controller_->SetViewForTesting(autofill_popup_view()); autofill_popup_controller_->SetViewForTesting(autofill_popup_view());
...@@ -171,6 +229,21 @@ class AutofillPopupControllerUnitTest : public ChromeRenderViewHostTestHarness { ...@@ -171,6 +229,21 @@ class AutofillPopupControllerUnitTest : public ChromeRenderViewHostTestHarness {
ChromeRenderViewHostTestHarness::TearDown(); ChromeRenderViewHostTestHarness::TearDown();
} }
virtual std::unique_ptr<NiceMock<MockAutofillExternalDelegate>>
CreateExternalDelegate() {
ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
web_contents(), autofill_client_.get(), "en-US",
AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
// Make sure RenderFrame is created.
NavigateAndCommit(GURL("about:blank"));
ContentAutofillDriverFactory* factory =
ContentAutofillDriverFactory::FromWebContents(web_contents());
ContentAutofillDriver* driver =
factory->DriverForFrame(web_contents()->GetMainFrame());
return std::make_unique<NiceMock<MockAutofillExternalDelegate>>(
driver->autofill_manager(), driver);
}
TestAutofillPopupController* popup_controller() { TestAutofillPopupController* popup_controller() {
return autofill_popup_controller_; return autofill_popup_controller_;
} }
...@@ -190,6 +263,43 @@ class AutofillPopupControllerUnitTest : public ChromeRenderViewHostTestHarness { ...@@ -190,6 +263,43 @@ class AutofillPopupControllerUnitTest : public ChromeRenderViewHostTestHarness {
NiceMock<TestAutofillPopupController>* autofill_popup_controller_; NiceMock<TestAutofillPopupController>* autofill_popup_controller_;
}; };
#if !defined(OS_CHROMEOS)
class AutofillPopupControllerAccessibilityUnitTest
: public AutofillPopupControllerUnitTest {
public:
AutofillPopupControllerAccessibilityUnitTest() = default;
~AutofillPopupControllerAccessibilityUnitTest() override = default;
void SetUp() override {
AutofillPopupControllerUnitTest::SetUp();
content::BrowserAccessibilityState::GetInstance()
->AddAccessibilityModeFlags(ui::AXMode::kScreenReader);
}
void TearDown() override {
content::BrowserAccessibilityState::GetInstance()
->RemoveAccessibilityModeFlags(ui::AXMode::kScreenReader);
AutofillPopupControllerUnitTest::TearDown();
}
std::unique_ptr<NiceMock<MockAutofillExternalDelegate>>
CreateExternalDelegate() override {
autofill_driver_ = std::make_unique<NiceMock<MockAutofillDriver>>();
autofill_manager_ = std::make_unique<MockAutofillManager>(
autofill_driver_.get(), autofill_client_.get());
return std::make_unique<NiceMock<MockAutofillExternalDelegate>>(
autofill_manager_.get(), autofill_driver_.get());
}
protected:
std::unique_ptr<MockAutofillManager> autofill_manager_;
std::unique_ptr<NiceMock<MockAutofillDriver>> autofill_driver_;
private:
DISALLOW_COPY_AND_ASSIGN(AutofillPopupControllerAccessibilityUnitTest);
};
#endif
TEST_F(AutofillPopupControllerUnitTest, ChangeSelectedLine) { TEST_F(AutofillPopupControllerUnitTest, ChangeSelectedLine) {
// Set up the popup. // Set up the popup.
std::vector<Suggestion> suggestions; std::vector<Suggestion> suggestions;
...@@ -603,4 +713,111 @@ TEST_F(AutofillPopupControllerUnitTest, ElideText) { ...@@ -603,4 +713,111 @@ TEST_F(AutofillPopupControllerUnitTest, ElideText) {
} }
#endif #endif
#if !defined(OS_CHROMEOS)
TEST_F(AutofillPopupControllerAccessibilityUnitTest, FireControlsChangedEvent) {
StrictMock<MockAxTreeManager> mock_ax_tree_manager;
StrictMock<MockAxPlatformNodeDelegate> mock_ax_platform_node_delegate;
StrictMock<ui::AXPlatformNodeBase> mock_ax_platform_node;
const ui::AXTreeID& test_tree_id = ui::AXTreeID::CreateNewAXTreeID();
ui::AXTreeManagerMap::GetInstance().AddTreeManager(test_tree_id,
&mock_ax_tree_manager);
// Test for successfully firing controls changed event for popup show/hide.
{
EXPECT_CALL(*autofill_driver_, GetAxTreeId())
.Times(2)
.WillRepeatedly(testing::Return(test_tree_id));
EXPECT_CALL(*autofill_popup_view_, GetAxUniqueId)
.Times(2)
.WillRepeatedly(testing::Return(base::Optional<int32_t>(123)));
EXPECT_CALL(mock_ax_tree_manager, GetDelegate)
.Times(2)
.WillRepeatedly(testing::Return(&mock_ax_platform_node_delegate));
EXPECT_CALL(mock_ax_platform_node_delegate, GetFromNodeID)
.Times(2)
.WillRepeatedly(testing::Return(&mock_ax_platform_node));
// Fire event for popup show and active popup ax unique id is set.
autofill_popup_controller_->FireControlsChangedEvent(true);
EXPECT_EQ(123, ui::GetActivePopupAxUniqueId());
// Fire event for popup hide and active popup ax unique id is cleared.
autofill_popup_controller_->FireControlsChangedEvent(false);
EXPECT_EQ(base::nullopt, ui::GetActivePopupAxUniqueId());
}
// Test for attempting to fire controls changed event when autofill driver
// returns an invalid ax tree id therefore no associated ax tree manager.
// No event is fired and global active popup ax unique id is not set.
{
EXPECT_CALL(*autofill_driver_, GetAxTreeId())
.WillOnce(testing::Return(ui::AXTreeIDUnknown()));
EXPECT_CALL(*autofill_popup_view_, GetAxUniqueId).Times(0);
EXPECT_CALL(mock_ax_tree_manager, GetDelegate).Times(0);
EXPECT_CALL(mock_ax_platform_node_delegate, GetFromNodeID).Times(0);
// No controls changed event is fired and active popup ax unique id is not
// set.
autofill_popup_controller_->FireControlsChangedEvent(true);
EXPECT_EQ(base::nullopt, ui::GetActivePopupAxUniqueId());
}
// Test for attempting to fire controls changed event when ax tree manager
// fails to retrieve the ax platform node delegate associated with the popup.
// No event is fired and global active popup ax unique id is not set.
{
EXPECT_CALL(*autofill_driver_, GetAxTreeId())
.WillOnce(testing::Return(test_tree_id));
EXPECT_CALL(mock_ax_tree_manager, GetDelegate)
.WillOnce(testing::Return(nullptr));
EXPECT_CALL(*autofill_popup_view_, GetAxUniqueId).Times(0);
EXPECT_CALL(mock_ax_platform_node_delegate, GetFromNodeID).Times(0);
// No controls changed event is fired and active popup ax unique id is not
// set.
autofill_popup_controller_->FireControlsChangedEvent(true);
EXPECT_EQ(base::nullopt, ui::GetActivePopupAxUniqueId());
}
// Test for attempting to fire controls changed event when failing to retrieve
// the ax platform node associated with the popup.
// No event is fired and global active popup ax unique id is not set.
{
EXPECT_CALL(*autofill_driver_, GetAxTreeId())
.WillOnce(testing::Return(test_tree_id));
EXPECT_CALL(mock_ax_tree_manager, GetDelegate)
.WillOnce(testing::Return(&mock_ax_platform_node_delegate));
EXPECT_CALL(mock_ax_platform_node_delegate, GetFromNodeID)
.WillOnce(testing::Return(nullptr));
EXPECT_CALL(*autofill_popup_view_, GetAxUniqueId)
.WillOnce(testing::Return(base::Optional<int32_t>(123)));
// No controls changed event is fired and active popup ax unique id is not
// set.
autofill_popup_controller_->FireControlsChangedEvent(true);
EXPECT_EQ(base::nullopt, ui::GetActivePopupAxUniqueId());
}
// Test for attempting to fire controls changed event when failing to retrieve
// the autofill popup's ax unique id.
// No event is fired and global active popup ax unique id is not set.
{
EXPECT_CALL(*autofill_driver_, GetAxTreeId())
.WillOnce(testing::Return(test_tree_id));
EXPECT_CALL(mock_ax_tree_manager, GetDelegate)
.WillOnce(testing::Return(&mock_ax_platform_node_delegate));
EXPECT_CALL(mock_ax_platform_node_delegate, GetFromNodeID)
.WillOnce(testing::Return(&mock_ax_platform_node));
EXPECT_CALL(*autofill_popup_view_, GetAxUniqueId)
.WillOnce(testing::Return(base::nullopt));
// No controls changed event is fired and active popup ax unique id is not
// set.
autofill_popup_controller_->FireControlsChangedEvent(true);
EXPECT_EQ(base::nullopt, ui::GetActivePopupAxUniqueId());
}
}
#endif
} // namespace autofill } // namespace autofill
...@@ -286,6 +286,10 @@ AutofillDriver* AutofillExternalDelegate::GetAutofillDriver() { ...@@ -286,6 +286,10 @@ AutofillDriver* AutofillExternalDelegate::GetAutofillDriver() {
return driver_; return driver_;
} }
int32_t AutofillExternalDelegate::GetWebContentsPopupControllerAxId() const {
return query_field_.form_control_ax_id;
}
void AutofillExternalDelegate::RegisterDeletionCallback( void AutofillExternalDelegate::RegisterDeletionCallback(
base::OnceClosure deletion_callback) { base::OnceClosure deletion_callback) {
deletion_callback_ = std::move(deletion_callback); deletion_callback_ = std::move(deletion_callback);
...@@ -295,10 +299,6 @@ void AutofillExternalDelegate::Reset() { ...@@ -295,10 +299,6 @@ void AutofillExternalDelegate::Reset() {
manager_->client()->HideAutofillPopup(); manager_->client()->HideAutofillPopup();
} }
int32_t AutofillExternalDelegate::GetWebContentsPopupControllerAxId() const {
return query_field_.form_control_ax_id;
}
base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() { base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr(); return weak_ptr_factory_.GetWeakPtr();
} }
......
...@@ -57,6 +57,10 @@ class AutofillExternalDelegate : public AutofillPopupDelegate { ...@@ -57,6 +57,10 @@ class AutofillExternalDelegate : public AutofillPopupDelegate {
// popup type after call to |onQuery|. // popup type after call to |onQuery|.
PopupType GetPopupType() const override; PopupType GetPopupType() const override;
AutofillDriver* GetAutofillDriver() override; AutofillDriver* GetAutofillDriver() override;
// Returns the ax node id associated with the current web contents' element
// who has a controller relation to the current autofill popup.
int32_t GetWebContentsPopupControllerAxId() const override;
void RegisterDeletionCallback(base::OnceClosure deletion_callback) override; void RegisterDeletionCallback(base::OnceClosure deletion_callback) override;
// Records and associates a query_id with web form data. Called // Records and associates a query_id with web form data. Called
...@@ -96,10 +100,6 @@ class AutofillExternalDelegate : public AutofillPopupDelegate { ...@@ -96,10 +100,6 @@ class AutofillExternalDelegate : public AutofillPopupDelegate {
// values or settings. // values or settings.
void Reset(); void Reset();
// Returns the ax node id associated with the current web contents' element
// who has a controller relation to the current autofill popup.
int32_t GetWebContentsPopupControllerAxId() const;
const FormData& query_form() const { return query_form_; } const FormData& query_form() const { return query_form_; }
protected: protected:
......
...@@ -56,6 +56,10 @@ class AutofillPopupDelegate { ...@@ -56,6 +56,10 @@ class AutofillPopupDelegate {
// Returns the associated AutofillDriver. // Returns the associated AutofillDriver.
virtual AutofillDriver* GetAutofillDriver() = 0; virtual AutofillDriver* GetAutofillDriver() = 0;
// Returns the ax node id associated with the current web contents' element
// who has a controller relation to the current autofill popup.
virtual int32_t GetWebContentsPopupControllerAxId() const = 0;
// Sets |deletion_callback| to be called from the delegate's destructor. // Sets |deletion_callback| to be called from the delegate's destructor.
// Useful for deleting objects which cannot be owned by the delegate but // Useful for deleting objects which cannot be owned by the delegate but
// should not outlive it. // should not outlive it.
......
...@@ -260,6 +260,12 @@ autofill::AutofillDriver* PasswordAutofillManager::GetAutofillDriver() { ...@@ -260,6 +260,12 @@ autofill::AutofillDriver* PasswordAutofillManager::GetAutofillDriver() {
return password_manager_driver_->GetAutofillDriver(); return password_manager_driver_->GetAutofillDriver();
} }
int32_t PasswordAutofillManager::GetWebContentsPopupControllerAxId() const {
// TODO: Needs to be implemented once we step up accessibility features later.
NOTIMPLEMENTED_LOG_ONCE() << "See http://crbug.com/991253";
return 0;
}
void PasswordAutofillManager::RegisterDeletionCallback( void PasswordAutofillManager::RegisterDeletionCallback(
base::OnceClosure deletion_callback) { base::OnceClosure deletion_callback) {
deletion_callback_ = std::move(deletion_callback); deletion_callback_ = std::move(deletion_callback);
......
...@@ -55,6 +55,7 @@ class PasswordAutofillManager : public autofill::AutofillPopupDelegate { ...@@ -55,6 +55,7 @@ class PasswordAutofillManager : public autofill::AutofillPopupDelegate {
void ClearPreviewedForm() override; void ClearPreviewedForm() override;
autofill::PopupType GetPopupType() const override; autofill::PopupType GetPopupType() const override;
autofill::AutofillDriver* GetAutofillDriver() override; autofill::AutofillDriver* GetAutofillDriver() override;
int32_t GetWebContentsPopupControllerAxId() const override;
void RegisterDeletionCallback(base::OnceClosure deletion_callback) override; void RegisterDeletionCallback(base::OnceClosure deletion_callback) override;
// Invoked when a password mapping is added. // Invoked when a password mapping is added.
......
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