chromium/third_party/blink/renderer/core/exported/web_view_test.cc

/*
 * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "third_party/blink/public/web/web_view.h"

#include <limits>
#include <memory>
#include <optional>
#include <string>

#include "base/functional/callback_helpers.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "cc/test/test_ukm_recorder_factory.h"
#include "cc/trees/layer_tree_host.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "gin/wrappable.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "third_party/blink/public/common/page/drag_operation.h"
#include "third_party/blink/public/common/page/page_zoom.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/common/widget/device_emulation_params.h"
#include "third_party/blink/public/mojom/frame/tree_scope_type.mojom-blink.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/public/mojom/input/touch_event.mojom-blink.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/platform/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_drag_data.h"
#include "third_party/blink/public/public_buildflags.h"
#include "third_party/blink/public/test/test_web_frame_content_dumper.h"
#include "third_party/blink/public/web/web_autofill_client.h"
#include "third_party/blink/public/web/web_console_message.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_frame.h"
#include "third_party/blink/public/web/web_hit_test_result.h"
#include "third_party/blink/public/web/web_input_method_controller.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_non_composited_widget_client.h"
#include "third_party/blink/public/web/web_print_params.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/public/web/web_widget.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_document.h"
#include "third_party/blink/renderer/core/css/css_default_style_sheets.h"
#include "third_party/blink/renderer/core/css/css_style_declaration.h"
#include "third_party/blink/renderer/core/css/media_query_list_listener.h"
#include "third_party/blink/renderer/core/css/media_query_matcher.h"
#include "third_party/blink/renderer/core/css/properties/longhands.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/focus_params.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
#include "third_party/blink/renderer/core/exported/web_page_popup_impl.h"
#include "third_party/blink/renderer/core/exported/web_settings_impl.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/html/forms/external_date_time_chooser.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
#include "third_party/blink/renderer/core/html/forms/internal_popup_menu.h"
#include "third_party/blink/renderer/core/html/html_document.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/html/html_object_element.h"
#include "third_party/blink/renderer/core/html/html_span_element.h"
#include "third_party/blink/renderer/core/inspector/dev_tools_emulator.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/empty_clients.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/loader/interactive_detector.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/context_menu_controller.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/page_hidden_state.h"
#include "third_party/blink/renderer/core/page/page_popup_client.h"
#include "third_party/blink/renderer/core/page/print_context.h"
#include "third_party/blink/renderer/core/page/scoped_browsing_context_group_pauser.h"
#include "third_party/blink/renderer/core/page/scoped_page_pauser.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
#include "third_party/blink/renderer/core/testing/color_scheme_helper.h"
#include "third_party/blink/renderer/core/testing/fake_web_plugin.h"
#include "third_party/blink/renderer/core/testing/mock_clipboard_host.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/event_timing.h"
#include "third_party/blink/renderer/core/timing/window_performance.h"
#include "third_party/blink/renderer/platform/cursors.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
#include "third_party/blink/renderer/platform/heap/thread_state.h"
#include "third_party/blink/renderer/platform/keyboard_codes.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/task_environment.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_loader_mock_factory.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-blink.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-blink.h"
#include "ui/base/mojom/ui_base_types.mojom-shared.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "v8/include/v8.h"

#if BUILDFLAG(ENABLE_UNHANDLED_TAP)
#include "third_party/blink/public/mojom/unhandled_tap_notifier/unhandled_tap_notifier.mojom-blink.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
#endif  // BUILDFLAG(ENABLE_UNHANDLED_TAP)

LoadFrame;
RunPendingTasks;
RegisterMockedURLLoad;
ToKURL;

namespace blink {

enum HorizontalScrollbarState {};

enum VerticalScrollbarState {};

class TestData {};

class AutoResizeWebViewClient : public WebViewClient {};

class WebViewTest : public testing::Test {};

static bool HitTestIsContentEditable(WebView* view, int x, int y) {}

static std::string HitTestElementId(WebView* view, int x, int y) {}

static Color OutlineColor(Element* element) {}

TEST_F(WebViewTest, HitTestContentEditableImageMaps) {}

static std::string HitTestAbsoluteUrl(WebView* view, int x, int y) {}

static WebElement HitTestUrlElement(WebView* view, int x, int y) {}

TEST_F(WebViewTest, ImageMapUrls) {}

TEST_F(WebViewTest, BrokenImage) {}

TEST_F(WebViewTest, BrokenInputImage) {}

TEST_F(WebViewTest, SetBaseBackgroundColor) {}

TEST_F(WebViewTest, SetBaseBackgroundColorBeforeMainFrame) {}

TEST_F(WebViewTest, SetBaseBackgroundColorAndBlendWithExistingContent) {}

TEST_F(WebViewTest, SetBaseBackgroundColorWithColorScheme) {}

TEST_F(WebViewTest, FocusIsInactive) {}

TEST_F(WebViewTest, DocumentHasFocus) {}

TEST_F(WebViewTest, PlatformColorsChangedOnDeviceEmulation) {}

TEST_F(WebViewTest, ActiveState) {}

TEST_F(WebViewTest, HitTestResultAtWithPageScale) {}

TEST_F(WebViewTest, HitTestResultAtWithPageScaleAndPan) {}

TEST_F(WebViewTest, HitTestResultForTapWithTapArea) {}

TEST_F(WebViewTest, HitTestResultForTapWithTapAreaPageScaleAndPan) {}

void WebViewTest::TestAutoResize(
    const gfx::Size& min_auto_resize,
    const gfx::Size& max_auto_resize,
    const std::string& page_width,
    const std::string& page_height,
    int expected_width,
    int expected_height,
    HorizontalScrollbarState expected_horizontal_state,
    VerticalScrollbarState expected_vertical_state) {}

TEST_F(WebViewTest, AutoResizeMinimumSize) {}

TEST_F(WebViewTest, AutoResizeHeightOverflowAndFixedWidth) {}

TEST_F(WebViewTest, AutoResizeFixedHeightAndWidthOverflow) {}

// Next three tests disabled for https://bugs.webkit.org/show_bug.cgi?id=92318 .
// It seems we can run three AutoResize tests, then the next one breaks.
TEST_F(WebViewTest, AutoResizeInBetweenSizes) {}

TEST_F(WebViewTest, AutoResizeOverflowSizes) {}

TEST_F(WebViewTest, AutoResizeMaxSize) {}

void WebViewTest::TestTextInputType(WebTextInputType expected_type,
                                    const std::string& html_file) {}

TEST_F(WebViewTest, TextInputType) {}

TEST_F(WebViewTest, TextInputInfoUpdateStyleAndLayout) {}

void WebViewTest::TestInputMode(WebTextInputMode expected_input_mode,
                                const std::string& html_file) {}

TEST_F(WebViewTest, InputMode) {}

void WebViewTest::TestInputAction(ui::TextInputAction expected_input_action,
                                  const std::string& html_file) {}

TEST_F(WebViewTest, TextInputAction) {}

TEST_F(WebViewTest, TextInputInfoWithReplacedElements) {}

TEST_F(WebViewTest, SetEditableSelectionOffsetsAndTextInputInfo) {}

// Regression test for crbug.com/663645
TEST_F(WebViewTest, FinishComposingTextDoesNotAssert) {}

// Regression test for https://crbug.com/873999
TEST_F(WebViewTest, LongPressOutsideInputShouldNotSelectPlaceholderText) {}

TEST_F(WebViewTest, FinishComposingTextCursorPositionChange) {}

TEST_F(WebViewTest, SetCompositionForNewCaretPositions) {}

TEST_F(WebViewTest, SetCompositionWithEmptyText) {}

TEST_F(WebViewTest, CommitTextForNewCaretPositions) {}

TEST_F(WebViewTest, CommitTextWhileComposing) {}

TEST_F(WebViewTest, FinishCompositionDoesNotRevealSelection) {}

TEST_F(WebViewTest, InsertNewLinePlacementAfterFinishComposingText) {}

TEST_F(WebViewTest, ExtendSelectionAndDelete) {}

TEST_F(WebViewTest, EditContextExtendSelectionAndDelete) {}

TEST_F(WebViewTest, DeleteSurroundingText) {}

TEST_F(WebViewTest, SetCompositionFromExistingText) {}

TEST_F(WebViewTest, SetCompositionFromExistingTextInTextArea) {}

TEST_F(WebViewTest, SetCompositionFromExistingTextInRichText) {}

TEST_F(WebViewTest, SetEditableSelectionOffsetsKeepsComposition) {}

TEST_F(WebViewTest, IsSelectionAnchorFirst) {}

TEST_F(
    WebViewTest,
    MoveFocusToNextFocusableElementForImeAndAutofillWithKeyEventListenersAndNonEditableElements) {}

TEST_F(
    WebViewTest,
    MoveFocusToNextFocusableElementForImeAndAutofillWithNonEditableNonFormControlElements) {}

TEST_F(WebViewTest,
       MoveFocusToNextFocusableElementForImeAndAutofillWithTabIndexElements) {}

TEST_F(
    WebViewTest,
    MoveFocusToNextFocusableElementForImeAndAutofillWithDisabledAndReadonlyElements) {}

TEST_F(WebViewTest, ExitingDeviceEmulationResetsPageScale) {}

TEST_F(WebViewTest, HistoryResetScrollAndScaleState) {}

TEST_F(WebViewTest, BackForwardRestoreScroll) {}

// Tests that scroll offset modified during fullscreen is preserved when
// exiting fullscreen.
TEST_F(WebViewTest, FullscreenNoResetScroll) {}

// Tests that background color is read from the backdrop on fullscreen.
TEST_F(WebViewTest, FullscreenBackgroundColor) {}

static void ExitFullscreen(Document& document) {}

// Tests that the removal from the top layer is scheduled.
TEST_F(WebViewTest, FullscreenRemovalTiming) {}

class PrintWebFrameClient : public frame_test_helpers::TestWebFrameClient {};

TEST_F(WebViewTest, PrintWithXHRInFlight) {}

static void DragAndDropURL(WebViewImpl* web_view, const std::string& url) {}

TEST_F(WebViewTest, DragDropURL) {}

bool WebViewTest::SimulateGestureAtElement(WebInputEvent::Type type,
                                           Element* element) {}

bool WebViewTest::SimulateGestureAtElementById(WebInputEvent::Type type,
                                               const WebString& id) {}

WebGestureEvent WebViewTest::BuildTapEvent(
    WebInputEvent::Type type,
    int tap_event_count,
    const gfx::PointF& position_in_widget) {}

bool WebViewTest::SimulateTapEventAtElement(WebInputEvent::Type type,
                                            int tap_event_count,
                                            Element* element) {}

bool WebViewTest::SimulateTapEventAtElementById(WebInputEvent::Type type,
                                                int tap_event_count,
                                                const WebString& id) {}

ExternalDateTimeChooser* WebViewTest::GetExternalDateTimeChooser(
    WebViewImpl* web_view_impl) {}

TEST_F(WebViewTest, ClientTapHandlingNullWebViewClient) {}

TEST_F(WebViewTest, LongPressEmptyDiv) {}

TEST_F(WebViewTest, LongPressEmptyDivAlwaysShow) {}

TEST_F(WebViewTest, LongPressObject) {}

TEST_F(WebViewTest, LongPressObjectFallback) {}

TEST_F(WebViewTest, LongPressImage) {}

TEST_F(WebViewTest, LongPressVideo) {}

TEST_F(WebViewTest, LongPressLink) {}

// Tests that we send touchcancel when drag start by long press.
TEST_F(WebViewTest, TouchCancelOnStartDragging) {}

// Tests that a touch drag context menu is enabled, a dragend shows a context
// menu when there is no drag.
TEST_F(WebViewTest, TouchDragContextMenuWithoutDrag) {}

// Tests that a dragend does not show a context menu after a drag when
// touch-drag-context-menu is enabled.
TEST_F(WebViewTest, TouchDragContextMenuAtDragEnd) {}

TEST_F(WebViewTest, ContextMenuOnLinkAndImageLongPress) {}

TEST_F(WebViewTest, ContextMenuAndDragOnImageLongPress) {}

TEST_F(WebViewTest, ContextMenuAndDragOnLinkLongPress) {}

TEST_F(WebViewTest, LongPressEmptyEditableSelection) {}

TEST_F(WebViewTest, LongPressEmptyNonEditableSelection) {}

TEST_F(WebViewTest, LongPressSelection) {}

TEST_F(WebViewTest, DoublePressSelection) {}

TEST_F(WebViewTest, DoublePressSelectionOnSelectStartFalse) {}

TEST_F(WebViewTest, DoublePressSelectionPreventDefaultMouseDown) {}

TEST_F(WebViewTest, FinishComposingTextDoesNotDismissHandles) {}

#if !BUILDFLAG(IS_MAC)
TEST_F(WebViewTest, TouchDoesntSelectEmptyTextarea) {}
#endif

TEST_F(WebViewTest, LongPressImageTextarea) {}

TEST_F(WebViewTest, BlinkCaretAfterLongPress) {}

TEST_F(WebViewTest, BlinkCaretOnClosingContextMenu) {}

TEST_F(WebViewTest, SelectionOnReadOnlyInput) {}

TEST_F(WebViewTest, KeyDownScrollsHandled) {}

class MiddleClickAutoscrollWebFrameWidget
    : public frame_test_helpers::TestWebFrameWidget {};

class MiddleClickWebViewTest : public WebViewTest {};

TEST_F(MiddleClickWebViewTest, MiddleClickAutoscrollCursor) {}

TEST_F(WebViewTest, ShowPressOnTransformedLink) {}

class MockAutofillClient : public WebAutofillClient {};

TEST_F(WebViewTest, LosingFocusDoesNotTriggerAutofillTextChange) {}

static void VerifySelectionAndComposition(WebViewImpl* web_view,
                                          int selection_start,
                                          int selection_end,
                                          int composition_start,
                                          int composition_end,
                                          const char* fail_message) {}

TEST_F(WebViewTest, CompositionNotCancelledByBackspace) {}

TEST_F(WebViewTest, FinishComposingTextDoesntTriggerAutofillTextChange) {}

TEST_F(WebViewTest,
       SetCompositionFromExistingTextDoesntTriggerAutofillTextChange) {}

class ViewCreatingWebFrameClient
    : public frame_test_helpers::TestWebFrameClient {};

class ViewCreatingWebViewClient : public WebViewClient {};

TEST_F(WebViewTest, DoNotFocusCurrentFrameOnNavigateFromLocalFrame) {}

TEST_F(WebViewTest, FocusExistingFrameOnNavigate) {}

class ViewReusingWebFrameClient
    : public frame_test_helpers::TestWebFrameClient {};

TEST_F(WebViewTest,
       ReuseExistingWindowOnCreateViewUsesCorrectNavigationPolicy) {}

TEST_F(WebViewTest, DispatchesFocusOutFocusInOnViewToggleFocus) {}

TEST_F(WebViewTest, DispatchesDomFocusOutDomFocusInOnViewToggleFocus) {}

static void OpenDateTimeChooser(WebView* web_view,
                                HTMLInputElement* input_element) {}

TEST_F(WebViewTest, ChooseValueFromDateTimeChooser) {}

TEST_F(WebViewTest, DispatchesFocusBlurOnViewToggle) {}

class CreateChildCounterFrameClient
    : public frame_test_helpers::TestWebFrameClient {};

WebLocalFrame* CreateChildCounterFrameClient::CreateChildFrame(
    mojom::blink::TreeScopeType scope,
    const WebString& name,
    const WebString& fallback_name,
    const FramePolicy& frame_policy,
    const WebFrameOwnerProperties& frame_owner_properties,
    FrameOwnerElementType frame_owner_element_type,
    WebPolicyContainerBindParams policy_container_bind_params,
    ukm::SourceId document_ukm_source_id,
    base::FunctionRef<void(
        WebLocalFrame*,
        const DocumentToken&,
        CrossVariantMojoRemote<mojom::BrowserInterfaceBrokerInterfaceBase>)>
        complete_initialization) {}

TEST_F(WebViewTest, ChangeDisplayMode) {}

TEST_F(WebViewTest, ChangeDisplayModeChildFrame) {}

TEST_F(WebViewTest, ChangeDisplayModeAlertsListener) {}

TEST_F(WebViewTest, ChangeDisplayModeChildFrameAlertsListener) {}

TEST_F(WebViewTest, AddFrameInCloseUnload) {}

TEST_F(WebViewTest, AddFrameInCloseURLUnload) {}

TEST_F(WebViewTest, AddFrameInNavigateUnload) {}

TEST_F(WebViewTest, AddFrameInChildInNavigateUnload) {}

class TouchEventConsumersWebFrameWidgetHost
    : public frame_test_helpers::TestWebFrameWidgetHost {};

class TouchEventConsumersWebFrameWidget
    : public frame_test_helpers::TestWebFrameWidget {};

class TouchEventConsumersWebViewTest : public WebViewTest {};

// This test verifies that FrameWidgetHost::SetHasTouchEventConsumers is called
// accordingly for various calls to EventHandlerRegistry::did{Add|Remove|
// RemoveAll}EventHandler(..., TouchEvent). Verifying that those calls are made
// correctly is the job of web_tests/fast/events/event-handler-count.html.
TEST_F(TouchEventConsumersWebViewTest, SetHasTouchEventConsumers) {}

// This test checks that deleting nodes which have only non-JS-registered touch
// handlers also removes them from the event handler registry. Note that this
// is different from detaching and re-attaching the same node, which is covered
// by web tests under fast/events/.
TEST_F(WebViewTest, DeleteElementWithRegisteredHandler) {}

// This test verifies the text input flags are correctly exposed to script.
TEST_F(WebViewTest, TextInputFlags) {}

// Check that the WebAutofillClient is correctly notified about first user
// gestures after load, following various input events.
TEST_F(WebViewTest, FirstUserGestureObservedKeyEvent) {}

TEST_F(WebViewTest, FirstUserGestureObservedMouseEvent) {}

TEST_F(WebViewTest, CompositionIsUserGesture) {}

// Currently, SelectionAsText() is built upon TextIterator, but
// TestWebFrameContentDumper is built upon TextDumperForTests. Their results can
// be different, making the test fail.
// TODO(crbug.com/781434): Build a selection serializer upon TextDumperForTests.
TEST_F(WebViewTest, DISABLED_CompareSelectAllToContentAsText) {}

TEST_F(WebViewTest, AutoResizeSubtreeLayout) {}

TEST_F(WebViewTest, PreferredSize) {}

TEST_F(WebViewTest, PreferredMinimumSizeQuirksMode) {}

TEST_F(WebViewTest, PreferredSizeWithGrid) {}

TEST_F(WebViewTest, PreferredSizeWithNGGridSkipped) {}

TEST_F(WebViewTest, PreferredSizeWithGridMinWidth) {}

TEST_F(WebViewTest, PreferredSizeWithGridMinWidthFlexibleTracks) {}

#if BUILDFLAG(ENABLE_UNHANDLED_TAP)

// Helps set up any test that uses a mock Mojo implementation.
class MojoTestHelper {
 public:
  MojoTestHelper(const String& test_file,
                 frame_test_helpers::WebViewHelper& web_view_helper)
      : web_view_helper_(web_view_helper) {
    web_view_ =
        web_view_helper.InitializeAndLoad(test_file.Utf8(), &web_frame_client_);
  }

  ~MojoTestHelper() {
    web_view_helper_.Reset();  // Remove dependency on locally scoped client.
  }

  WebViewImpl* WebView() const { return web_view_; }

 private:
  WebViewImpl* web_view_;
  frame_test_helpers::WebViewHelper& web_view_helper_;
  frame_test_helpers::TestWebFrameClient web_frame_client_;
};

// Mock implementation of the UnhandledTapNotifier Mojo receiver, for testing
// the ShowUnhandledTapUIIfNeeded notification.
class MockUnhandledTapNotifierImpl : public mojom::blink::UnhandledTapNotifier {
 public:
  MockUnhandledTapNotifierImpl() = default;
  ~MockUnhandledTapNotifierImpl() override = default;

  void Bind(mojo::ScopedMessagePipeHandle handle) {
    receiver_.Bind(mojo::PendingReceiver<mojom::blink::UnhandledTapNotifier>(
        std::move(handle)));
  }

  void ShowUnhandledTapUIIfNeeded(
      mojom::blink::UnhandledTapInfoPtr unhandled_tap_info) override {
    was_unhandled_tap_ = true;
    tapped_position_ = unhandled_tap_info->tapped_position_in_viewport;
  }
  bool WasUnhandledTap() const { return was_unhandled_tap_; }
  int GetTappedXPos() const { return tapped_position_.x(); }
  int GetTappedYPos() const { return tapped_position_.y(); }
  void Reset() {
    was_unhandled_tap_ = false;
    tapped_position_ = gfx::Point();
    receiver_.reset();
  }

 private:
  bool was_unhandled_tap_ = false;
  gfx::Point tapped_position_;

  mojo::Receiver<mojom::blink::UnhandledTapNotifier> receiver_{this};
};

// A Test Fixture for testing ShowUnhandledTapUIIfNeeded usages.
class ShowUnhandledTapTest : public WebViewTest {
 public:
  void SetUp() override {
    WebViewTest::SetUp();
    std::string test_file = "show_unhandled_tap.html";
    RegisterMockedHttpURLLoad("Ahem.ttf");
    RegisterMockedHttpURLLoad(test_file);

    mojo_test_helper_ = std::make_unique<MojoTestHelper>(
        WebString::FromUTF8(base_url_ + test_file), web_view_helper_);

    web_view_ = mojo_test_helper_->WebView();
    web_view_->MainFrameViewWidget()->Resize(gfx::Size(500, 300));
    web_view_->MainFrameWidget()->UpdateAllLifecyclePhases(
        DocumentUpdateReason::kTest);
    RunPendingTasks();

    WebLocalFrameImpl* web_local_frame = web_view_->MainFrameImpl();
    web_local_frame->GetFrame()
        ->GetBrowserInterfaceBroker()
        .SetBinderForTesting(
            mojom::blink::UnhandledTapNotifier::Name_,
            WTF::BindRepeating(&MockUnhandledTapNotifierImpl::Bind,
                               WTF::Unretained(&mock_notifier_)));
  }

  void TearDown() override {
    WebLocalFrameImpl* web_local_frame = web_view_->MainFrameImpl();
    web_local_frame->GetFrame()
        ->GetBrowserInterfaceBroker()
        .SetBinderForTesting(mojom::blink::UnhandledTapNotifier::Name_, {});

    WebViewTest::TearDown();
  }

 protected:
  // Tap on the given element by ID.
  void Tap(const String& element_id) {
    mock_notifier_.Reset();
    EXPECT_TRUE(SimulateGestureAtElementById(WebInputEvent::Type::kGestureTap,
                                             element_id));
  }

  // Set up a test script for the given |operation| with the given |handler|.
  void SetTestScript(const String& operation, const String& handler) {
    String test_key = operation + "-" + handler;
    web_view_->MainFrameImpl()->ExecuteScript(
        WebScriptSource(String("setTest('" + test_key + "');")));
  }

  // Test each mouse event combination with the given |handler|, and verify the
  // |expected| outcome.
  void TestEachMouseEvent(const String& handler, bool expected) {
    SetTestScript("mousedown", handler);
    Tap("target");
    EXPECT_EQ(expected, mock_notifier_.WasUnhandledTap());

    SetTestScript("mouseup", handler);
    Tap("target");
    EXPECT_EQ(expected, mock_notifier_.WasUnhandledTap());

    SetTestScript("click", handler);
    Tap("target");
    EXPECT_EQ(expected, mock_notifier_.WasUnhandledTap());
  }

  WebViewImpl* web_view_;
  MockUnhandledTapNotifierImpl mock_notifier_;

 private:
  std::unique_ptr<MojoTestHelper> mojo_test_helper_;
};

TEST_F(ShowUnhandledTapTest, ShowUnhandledTapUIIfNeeded) {
  // Scroll the bottom into view so we can distinguish window coordinates from
  // document coordinates.
  Tap("bottom");
  EXPECT_TRUE(mock_notifier_.WasUnhandledTap());
  EXPECT_EQ(64, mock_notifier_.GetTappedXPos());
  EXPECT_EQ(278, mock_notifier_.GetTappedYPos());

  // Test basic tap handling and notification.
  Tap("target");
  EXPECT_TRUE(mock_notifier_.WasUnhandledTap());
  EXPECT_EQ(144, mock_notifier_.GetTappedXPos());
  EXPECT_EQ(82, mock_notifier_.GetTappedYPos());

  // Test correct conversion of coordinates to viewport space under pinch-zoom.
  constexpr float scale = 1.5f;
  constexpr float visual_x = 6.f;
  constexpr float visual_y = 10.f;

  web_view_->SetPageScaleFactor(scale);
  web_view_->SetVisualViewportOffset(gfx::PointF(visual_x, visual_y));

  Tap("target");

  // Ensure position didn't change as a result of scroll into view.
  ASSERT_EQ(visual_x, web_view_->VisualViewportOffset().x());
  ASSERT_EQ(visual_y, web_view_->VisualViewportOffset().y());

  EXPECT_TRUE(mock_notifier_.WasUnhandledTap());

  constexpr float expected_x = 144 * scale - (scale * visual_x);
  constexpr float expected_y = 82 * scale - (scale * visual_y);
  EXPECT_EQ(expected_x, mock_notifier_.GetTappedXPos());
  EXPECT_EQ(expected_y, mock_notifier_.GetTappedYPos());
}

TEST_F(ShowUnhandledTapTest, ShowUnhandledTapUIIfNeededWithMutateDom) {
  // Test dom mutation.
  TestEachMouseEvent("mutateDom", false);

  // Test without any DOM mutation.
  TestEachMouseEvent("none", true);
}

TEST_F(ShowUnhandledTapTest, ShowUnhandledTapUIIfNeededWithMutateStyle) {
  // Test style mutation.
  TestEachMouseEvent("mutateStyle", false);

  // Test checkbox:indeterminate style mutation.
  TestEachMouseEvent("mutateIndeterminate", false);

  // Test click div with :active style.
  Tap("style_active");
  EXPECT_FALSE(mock_notifier_.WasUnhandledTap());
}

TEST_F(ShowUnhandledTapTest, ShowUnhandledTapUIIfNeededWithPreventDefault) {
  // Test swallowing.
  TestEachMouseEvent("preventDefault", false);

  // Test without any preventDefault.
  TestEachMouseEvent("none", true);
}

TEST_F(ShowUnhandledTapTest, ShowUnhandledTapUIIfNeededWithNonTriggeringNodes) {
  Tap("image");
  EXPECT_FALSE(mock_notifier_.WasUnhandledTap());

  Tap("editable");
  EXPECT_FALSE(mock_notifier_.WasUnhandledTap());

  Tap("focusable");
  EXPECT_FALSE(mock_notifier_.WasUnhandledTap());
}

#endif  // BUILDFLAG(ENABLE_UNHANDLED_TAP)

TEST_F(WebViewTest, ShouldSuppressKeyboardForPasswordField) {}

TEST_F(WebViewTest, PasswordFieldEditingIsUserGesture) {}

// Verify that a WebView created with a ScopedPagePauser already on the
// stack defers its loads.
TEST_F(WebViewTest, CreatedDuringPagePause) {}

// Similar to CreatedDuringPagePause, but pauses only pages that belong to the
// same browsing context group.
TEST_F(WebViewTest, CreatedDuringBrowsingContextGroupPause) {}

// Make sure the SubframeBeforeUnloadUseCounter is only incremented on subframe
// unloads. crbug.com/635029.
TEST_F(WebViewTest, SubframeBeforeUnloadUseCounter) {}

// Verify that page loads are deferred until all ScopedPagePausers are
// destroyed.
TEST_F(WebViewTest, NestedPagePauses) {}

// Similar to NestedPagePauses but uses ScopedBrowsingContextGroupPauser
// instead.
TEST_F(WebViewTest, NestedPagePausesPerBrowsingContextGroup) {}

TEST_F(WebViewTest, ClosingPageIsPaused) {}

TEST_F(WebViewTest, ForceAndResetViewport) {}

TEST_F(WebViewTest, ViewportOverrideIntegratesDeviceMetricsOffsetAndScale) {}

TEST_F(WebViewTest, ViewportOverrideAdaptsToScaleAndScroll) {}

TEST_F(WebViewTest, ResizeForPrintingViewportUnits) {}

TEST_F(WebViewTest, WidthMediaQueryWithPageZoomAfterPrinting) {}

TEST_F(WebViewTest, ViewportUnitsPrintingWithPageZoom) {}

TEST_F(WebViewTest, ResizeWithFixedPosCrash) {}

TEST_F(WebViewTest, DeviceEmulationResetScrollbars) {}

TEST_F(WebViewTest, SetZoomLevelWhilePluginFocused) {}

// Tests that a layout update that detaches a plugin doesn't crash if the
// plugin tries to execute script while being destroyed.
TEST_F(WebViewTest, DetachPluginInLayout) {}

// Check that first input delay is correctly reported to the document.
TEST_F(WebViewTest, FirstInputDelayReported) {}

TEST_F(WebViewTest, InputDelayReported) {}

// TODO(npm): Improve this test to receive real input sequences and avoid hacks.
// Check that first input delay is correctly reported to the document when the
// first input is a pointer down event, and we receive a pointer up event.
TEST_F(WebViewTest, PointerDownUpFirstInputDelay) {}

// We need a way for JS to advance the mock clock. Hook into console.log, so
// that logging advances the clock by |event_handling_delay| seconds.
class MockClockAdvancingWebFrameClient
    : public frame_test_helpers::TestWebFrameClient {};

// Check that the input delay is correctly reported to the document.
TEST_F(WebViewTest, FirstInputDelayExcludesProcessingTime) {}

TEST_F(WebViewTest, RootLayerAttachment) {}

TEST_F(WebViewTest, ForceDarkModeInvalidatesPaint) {}

// Regression test for https://crbug.com/1012068
TEST_F(WebViewTest, LongPressImageAndThenLongTapImage) {}

// Regression test for http://crbug.com/41562
TEST_F(WebViewTest, UpdateTargetURLWithInvalidURL) {}

// Regression test for https://crbug.com/1112987
TEST_F(WebViewTest, LongPressThenLongTapLinkInIframeStartsContextMenu) {}

TEST_F(WebViewTest, SetHistoryLengthAndOffset) {}

// PopupWidgetImpl should inherit emulation params from the parent.
TEST_F(WebViewTest, EmulatingPopupRect) {}

TEST_F(WebViewTest, HiddenButPaintingIsSentToObservers) {}

TEST_F(WebViewTest, HiddenButPaintingPageIsntThrottled) {}

TEST_F(WebViewTest, HiddenVisibilityTransitionsDontDispatchEvents) {}

}  // namespace blink