#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
#include <stddef.h>
#include "base/feature_list.h"
#include "base/memory/raw_ptr.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/external_protocol/external_protocol_handler.h"
#include "chrome/browser/interstitials/security_interstitial_page_test_utils.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/ssl/typed_navigation_upgrade_throttle.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/location_bar/location_bar.h"
#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/omnibox/omnibox_popup_view_views.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/omnibox_controller.h"
#include "components/omnibox/browser/omnibox_edit_model.h"
#include "components/omnibox/browser/omnibox_triggered_feature_service.h"
#include "components/omnibox/browser/test_scheme_classifier.h"
#include "components/security_interstitials/core/omnibox_https_upgrade_metrics.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/no_renderer_crashes_assertion.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/url_loader_interceptor.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "ui/accessibility/accessibility_features.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/ime/init/input_method_factory.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/mock_input_method.h"
#include "ui/base/ime/text_edit_commands.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/test/ui_controls.h"
#include "ui/base/ui_base_switches.h"
#include "ui/display/display_switches.h"
#include "ui/events/event_processor.h"
#include "ui/events/event_utils.h"
#include "ui/events/test/event_generator.h"
#include "ui/views/accessibility/atomic_view_ax_tree_manager.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/textfield/textfield_test_api.h"
#include "ui/views/views_features.h"
#if defined(USE_AURA)
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_safearray.h"
#include "chrome/browser/ui/views/accessibility/uia_accessibility_event_waiter.h"
#include "ui/display/win/screen_win.h"
#include "ui/views/win/hwnd_util.h"
#endif
namespace {
void SetClipboardText(ui::ClipboardBuffer buffer, const std::u16string& text) { … }
}
class OmniboxViewViewsTest : public InProcessBrowserTest { … };
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, PasteAndGoDoesNotLeavePopupOpen) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, DoNotNavigateOnDrop) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, AyncDropCallback) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, DISABLED_SelectAllOnClick) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, DISABLED_SelectionClipboard) { … }
#if !BUILDFLAG(IS_MAC) || defined(USE_AURA)
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, SelectAllOnTap) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest,
DeactivateTouchEditingOnExecuteCommand) { … }
#endif
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, SelectAllOnTabToFocus) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, CloseOmniboxPopupOnTextDrag) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, MaintainCursorAfterFocusCycle) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, BackgroundIsOpaque) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, FocusedTextInputClient) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, TextElideStatus) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, FragmentUnescapedForDisplay) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, FriendlyAccessibleLabel) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, AccessiblePopup) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, DISABLED_ReloadAfterKill) { … }
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, AlwaysShowFullURLs) { … }
#if BUILDFLAG(IS_WIN)
using Microsoft::WRL::ComPtr;
class OmniboxViewViewsUIATest : public OmniboxViewViewsTest {
public:
OmniboxViewViewsUIATest() {}
void ExpectUIADoubleSafearrayEQ(
SAFEARRAY* safearray,
const std::vector<double>& expected_property_values) {
EXPECT_EQ(sizeof(V_R8(LPVARIANT(NULL))), ::SafeArrayGetElemsize(safearray));
ASSERT_EQ(1u, SafeArrayGetDim(safearray));
LONG array_lower_bound;
ASSERT_HRESULT_SUCCEEDED(
SafeArrayGetLBound(safearray, 1, &array_lower_bound));
LONG array_upper_bound;
ASSERT_HRESULT_SUCCEEDED(
SafeArrayGetUBound(safearray, 1, &array_upper_bound));
double* array_data;
ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData(
safearray, reinterpret_cast<void**>(&array_data)));
size_t count = array_upper_bound - array_lower_bound + 1;
ASSERT_EQ(expected_property_values.size(), count);
for (size_t i = 0; i < count; ++i) {
EXPECT_EQ(array_data[i], expected_property_values[i]);
}
ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(safearray));
}
private:
base::test::ScopedFeatureList scoped_feature_list_{::features::kUiaProvider};
};
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsUIATest, AccessibleOmnibox) {
OmniboxView* omnibox_view = nullptr;
ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &omnibox_view));
chrome::FocusLocationBar(browser());
std::u16string match_url = u"https://example.com";
AutocompleteMatch match(nullptr, 500, false,
AutocompleteMatchType::HISTORY_TITLE);
match.contents = match_url;
match.contents_class.push_back(
ACMatchClassification(0, ACMatchClassification::URL));
match.destination_url = GURL(match_url);
match.description = u"Example";
match.allowed_to_be_default_match = true;
EXPECT_FALSE(omnibox_view->model()->PopupIsOpen());
HWND window_handle =
browser()->window()->GetNativeWindow()->GetHost()->GetAcceleratedWidget();
UiaAccessibilityWaiterInfo info = {window_handle, L"textbox",
L"Address and search bar",
ax::mojom::Event::kControlsChanged};
UiaAccessibilityEventWaiter open_waiter(info);
AutocompleteController* autocomplete_controller =
omnibox_view->controller()->autocomplete_controller();
AutocompleteResult& results = autocomplete_controller->internal_result_;
ACMatches matches;
matches.push_back(match);
AutocompleteInput input(u"e", metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
results.AppendMatches(matches);
results.SortAndCull(
input, TemplateURLServiceFactory::GetForProfile(browser()->profile()),
triggered_feature_service());
autocomplete_controller->NotifyChanged();
open_waiter.Wait();
EXPECT_TRUE(omnibox_view->model()->PopupIsOpen());
UiaAccessibilityEventWaiter close_waiter(info);
ClickBrowserWindowCenter();
close_waiter.Wait();
EXPECT_FALSE(omnibox_view->model()->PopupIsOpen());
}
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsUIATest, GetSelectionAndBounds) {
OmniboxView* omnibox_view = nullptr;
ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &omnibox_view));
OmniboxViewViews* omnibox_view_views =
static_cast<OmniboxViewViews*>(omnibox_view);
views::AtomicViewAXTreeManager* ax_tree_manager =
omnibox_view_views->GetViewAccessibility()
.GetAtomicViewAXTreeManagerForTesting();
gfx::Range selection_range(4, 8);
omnibox_view_views->SetUserText(u"helloworld");
omnibox_view_views->SetSelectedRange(selection_range);
ui::AXPlatformNode* ax_platform_node =
ui::AXPlatformNode::FromNativeViewAccessible(
ax_tree_manager->RootDelegate()->GetNativeViewAccessible());
ComPtr<IRawElementProviderSimple> root_node_raw;
ax_platform_node->GetNativeViewAccessible()->QueryInterface(
__uuidof(IRawElementProviderSimple), &root_node_raw);
ComPtr<ITextProvider> document_provider;
ASSERT_HRESULT_SUCCEEDED(
root_node_raw->GetPatternProvider(UIA_TextPatternId, &document_provider));
CComPtr<ITextRangeProvider> selected_text_range_provider;
base::win::ScopedSafearray selection;
LONG index = 0;
document_provider->GetSelection(selection.Receive());
ASSERT_NE(nullptr, selection.Get());
ASSERT_HRESULT_SUCCEEDED(SafeArrayGetElement(selection.Get(), &index,
&selected_text_range_provider));
base::win::ScopedBstr text_content;
ASSERT_HRESULT_SUCCEEDED(
selected_text_range_provider->GetText(-1, text_content.Receive()));
EXPECT_STREQ(L"owor", text_content.Get());
base::win::ScopedSafearray safearray;
ASSERT_HRESULT_SUCCEEDED(
selected_text_range_provider->GetBoundingRectangles(safearray.Receive()));
ComPtr<IRawElementProviderFragment> textfield_fragment;
ax_platform_node->GetNativeViewAccessible()->QueryInterface(
__uuidof(IRawElementProviderFragment), &textfield_fragment);
UiaRect textfield_rect;
ASSERT_HRESULT_SUCCEEDED(
textfield_fragment->get_BoundingRectangle(&textfield_rect));
gfx::Rect bounds_in_screen = omnibox_view_views->GetContentsBounds();
omnibox_view_views->ConvertRectToScreen(omnibox_view_views,
&bounds_in_screen);
std::vector<int32_t> offsets =
ax_tree_manager->GetRoot()->GetIntListAttribute(
ax::mojom::IntListAttribute::kCharacterOffsets);
int range_start_offset = offsets[selection_range.start()];
int range_end_offset = offsets[selection_range.end()];
int left_bound =
display::win::ScreenWin::DIPToScreenRect(
HWNDForView(omnibox_view_views),
gfx::Rect(range_start_offset + bounds_in_screen.x(), 0, 0, 0))
.x();
textfield_rect.top += omnibox_view_views->GetInsets().top();
textfield_rect.height -= omnibox_view_views->GetInsets().height();
std::vector<double> expected_values = std::vector<double>{
static_cast<double>(left_bound), textfield_rect.top,
static_cast<double>(range_end_offset - range_start_offset),
textfield_rect.height};
ASSERT_NO_FATAL_FAILURE(
ExpectUIADoubleSafearrayEQ(safearray.Get(), expected_values));
}
namespace {
class OmniboxMockInputMethod : public ui::MockInputMethod {
public:
OmniboxMockInputMethod() : ui::MockInputMethod(nullptr) {}
bool IsInputLocaleCJK() const override { return input_locale_cjk_; }
void SetInputLocaleCJK(bool is_cjk) { input_locale_cjk_ = is_cjk; }
private:
bool input_locale_cjk_ = false;
};
}
class OmniboxViewViewsIMETest : public OmniboxViewViewsTest {
public:
OmniboxViewViewsIMETest() = default;
void SetUp() override {
input_method_ = new OmniboxMockInputMethod();
ui::SetUpInputMethodForTesting(input_method_);
InProcessBrowserTest::SetUp();
}
protected:
OmniboxMockInputMethod* GetInputMethod() const { return input_method_; }
private:
base::test::ScopedFeatureList scoped_feature_list_{::features::kUiaProvider};
raw_ptr<OmniboxMockInputMethod, AcrossTasksDanglingUntriaged> input_method_ =
nullptr;
};
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsIMETest, TextInputTypeChangedTest) {
chrome::FocusLocationBar(browser());
OmniboxView* view = nullptr;
ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &view));
OmniboxViewViews* omnibox_view_views = static_cast<OmniboxViewViews*>(view);
ui::InputMethod* input_method =
omnibox_view_views->GetWidget()->GetInputMethod();
EXPECT_EQ(input_method, GetInputMethod());
EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, omnibox_view_views->GetTextInputType());
GetInputMethod()->SetInputLocaleCJK(true);
omnibox_view_views->OnInputMethodChanged();
EXPECT_EQ(ui::TEXT_INPUT_TYPE_SEARCH, omnibox_view_views->GetTextInputType());
GetInputMethod()->SetInputLocaleCJK(false);
omnibox_view_views->OnInputMethodChanged();
EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, omnibox_view_views->GetTextInputType());
}
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsIMETest, TextInputTypeInitRespectsIME) {
OmniboxMockInputMethod* input_method = new OmniboxMockInputMethod();
ui::SetUpInputMethodForTesting(input_method);
input_method->SetInputLocaleCJK(true);
Browser* browser_2 = CreateBrowser(browser()->profile());
OmniboxView* view = nullptr;
ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser_2, &view));
OmniboxViewViews* omnibox_view_views = static_cast<OmniboxViewViews*>(view);
EXPECT_EQ(omnibox_view_views->GetWidget()->GetInputMethod(), input_method);
EXPECT_EQ(ui::TEXT_INPUT_TYPE_SEARCH, omnibox_view_views->GetTextInputType());
input_method->SetInputLocaleCJK(false);
omnibox_view_views->OnInputMethodChanged();
EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, omnibox_view_views->GetTextInputType());
}
#endif
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
#define MAYBE_HandleExternalProtocolURLs …
#else
#define MAYBE_HandleExternalProtocolURLs …
#endif
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, MAYBE_HandleExternalProtocolURLs) { … }
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_LACROS)
#define MAYBE_DefaultTypedNavigationsToHttps_ZeroSuggest_NoUpgrade …
#else
#define MAYBE_DefaultTypedNavigationsToHttps_ZeroSuggest_NoUpgrade …
#endif
IN_PROC_BROWSER_TEST_F(
OmniboxViewViewsTest,
MAYBE_DefaultTypedNavigationsToHttps_ZeroSuggest_NoUpgrade) { … }