chromium/content/browser/renderer_host/render_widget_host_browsertest.cc

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>
#include <vector>

#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/input/input_router_impl.h"
#include "components/input/render_widget_host_input_event_router.h"
#include "components/input/touch_action_filter.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/renderer_host/input/touch_emulator_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/content_navigation_policy.h"
#include "content/common/input/synthetic_smooth_drag_gesture.h"
#include "content/public/browser/render_widget_host_observer.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/public/common/switches.h"
#include "ui/events/base_event_utils.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/switches.h"
#include "ui/latency/latency_info.h"

#if BUILDFLAG(IS_MAC)
#include "third_party/blink/public/mojom/choosers/popup_menu.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-test-utils.h"
#endif

namespace content {

namespace {

// Test observer which waits for a visual properties update from a
// `RenderWidgetHost`.
class TestRenderWidgetHostObserver : public RenderWidgetHostObserver {};

}  // namespace

// For tests that just need a browser opened/navigated to a simple web page.
class RenderWidgetHostBrowserTest : public ContentBrowserTest {};

// This test enables --site-per-process flag.
class RenderWidgetHostSitePerProcessTest : public ContentBrowserTest {};

class TestInputEventObserver : public RenderWidgetHost::InputEventObserver {};

class RenderWidgetHostTouchEmulatorBrowserTest : public ContentBrowserTest {};

// Synthetic mouse events not allowed on Android.
#if !BUILDFLAG(IS_ANDROID)
// This test makes sure that TouchEmulator doesn't emit a GestureScrollEnd
// without a valid unique_touch_event_id when it sees a GestureFlingStart
// terminating the underlying mouse scroll sequence. If the GestureScrollEnd is
// given a unique_touch_event_id of 0, then a crash will occur.
IN_PROC_BROWSER_TEST_F(RenderWidgetHostTouchEmulatorBrowserTest,
                       TouchEmulatorPinchWithGestureFling) {}
#endif  // !BUILDFLAG(IS_ANDROID)

// Todo(crbug.com/994353): The test is flaky(crash/timeout) on MSAN, TSAN, and
// DEBUG builds.
#if (!defined(NDEBUG) || defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER))
#define MAYBE_TouchEmulator
#else
#define MAYBE_TouchEmulator
#endif
IN_PROC_BROWSER_TEST_F(RenderWidgetHostTouchEmulatorBrowserTest,
                       MAYBE_TouchEmulator) {}

// Observes the WebContents until a frame finishes loading the contents of a
// given GURL.
class DocumentLoadObserver : WebContentsObserver {};

// This test verifies that when a cross-process child frame loads, the initial
// updates for touch event handlers are sent from the renderer.
IN_PROC_BROWSER_TEST_F(RenderWidgetHostSitePerProcessTest,
                       OnHasTouchEventHandlers) {}

// The plumbing that this test is verifying is not utilized on Mac/Android,
// where popup menus don't create a popup RenderWidget, but rather they trigger
// a FrameHostMsg_ShowPopup to ask the browser to build and display the actual
// popup using native controls.
#if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID)

namespace {

// Helper to use inside a loop instead of using RunLoop::RunUntilIdle() to avoid
// the loop being a busy loop that prevents renderer from doing its job. Use
// only when there is no better way to synchronize.
void GiveItSomeTime(base::TimeDelta delta) {}

}  // namespace

IN_PROC_BROWSER_TEST_F(RenderWidgetHostSitePerProcessTest,
                       BrowserClosesSelectPopup) {}

#endif

#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)

namespace {

// Intercept PopupWidgetHost::ShowPopup to override the initial bounds
class ShowPopupInterceptor
    : public blink::mojom::PopupWidgetHostInterceptorForTesting {};

#if BUILDFLAG(IS_MAC)

// Intercepts calls to LocalFrameHost::ShowPopupMenu method(), to override
// initial bounds and hook the `PopupMenuClient`
class ShowPopupMenuInterceptor
    : public blink::mojom::LocalFrameHostInterceptorForTesting,
      public blink::mojom::PopupMenuClient {
 public:
  explicit ShowPopupMenuInterceptor(RenderFrameHostImpl* render_frame_host,
                                    const gfx::Rect& overriden_bounds)
      : overriden_bounds_(overriden_bounds),
        swapped_impl_(
            render_frame_host->local_frame_host_receiver_for_testing(),
            this) {}

  ~ShowPopupMenuInterceptor() override = default;

  LocalFrameHost* GetForwardingInterface() override {
    return swapped_impl_.old_impl();
  }

  void Wait() { run_loop_.Run(); }

  void ShowPopupMenu(
      mojo::PendingRemote<blink::mojom::PopupMenuClient> popup_client,
      const gfx::Rect& bounds,
      int32_t item_height,
      double font_size,
      int32_t selected_item,
      std::vector<blink::mojom::MenuItemPtr> menu_items,
      bool right_aligned,
      bool allow_multiple_selection) override {
    CHECK(GetForwardingInterface());
    GetForwardingInterface()->ShowPopupMenu(
        receiver_.BindNewPipeAndPassRemote(), overriden_bounds_, item_height,
        font_size, selected_item, std::move(menu_items), right_aligned,
        allow_multiple_selection);
  }

  void DidAcceptIndices(const std::vector<int32_t>& indices) override {
    receiver_.reset();
  }

  void DidCancel() override {
    is_cancelled_ = true;
    receiver_.reset();
    run_loop_.Quit();
  }

  bool is_cancelled() const { return is_cancelled_; }

 private:
  base::RunLoop run_loop_;
  bool is_cancelled_{false};
  gfx::Rect overriden_bounds_;
  mojo::test::ScopedSwapImplForTesting<blink::mojom::LocalFrameHost>
      swapped_impl_;
  mojo::Receiver<blink::mojom::PopupMenuClient> receiver_{this};
};
#endif  // BUILDFLAG(IS_MAC)

}  // namespace

IN_PROC_BROWSER_TEST_F(RenderWidgetHostSitePerProcessTest,
                       BrowserClosesPopupIntersectsPermissionPrompt) {}

#endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)

// Tests that `window.screen` dimensions match the display, not the viewport,
// while the frame is fullscreen. See crbug.com/1367416
IN_PROC_BROWSER_TEST_F(RenderWidgetHostBrowserTest, FullscreenSize) {}

class RenderWidgetHostFoldableCSSTest : public RenderWidgetHostBrowserTest {};

// Tests that when a video element goes fullscreen and uses the default
// fullscreen UA stylesheet (in blink/core/css/fullscreen.css) the viewport
// segments MQs and env variables are correctly working.
IN_PROC_BROWSER_TEST_F(RenderWidgetHostFoldableCSSTest,
                       ViewportSegmentsWorksInUAFullscreenCSS) {}

// Tests that the renderer receives the root widget's viewport segments and
// correctly exposes those via CSS.
// TODO(crbug.com/40137084) Convert this to a WPT once emulation is available
// via WebDriver.
IN_PROC_BROWSER_TEST_F(RenderWidgetHostFoldableCSSTest,
                       FoldablesCSSWithOverrides) {}

IN_PROC_BROWSER_TEST_F(RenderWidgetHostFoldableCSSTest,
                       FoldablesCSSWithReload) {}

class RenderWidgetHostDelegatedInkMetadataTest
    : public RenderWidgetHostTouchEmulatorBrowserTest {};

// Confirm that using the |updateInkTrailStartPoint| JS API results in the
// |request_points_for_delegated_ink_| flag being set on the RWHVB.
// TODO(crbug.com/40852704). Flaky on Linux.
// TODO(crbug.com/40929902): Failing on ChromesOS MSan.
#if BUILDFLAG(IS_LINUX) || (BUILDFLAG(IS_CHROMEOS) && defined(MEMORY_SANITIZER))
#define MAYBE_FlagGetsSetFromRenderFrameMetadata
#else
#define MAYBE_FlagGetsSetFromRenderFrameMetadata
#endif
IN_PROC_BROWSER_TEST_F(RenderWidgetHostDelegatedInkMetadataTest,
                       MAYBE_FlagGetsSetFromRenderFrameMetadata) {}

// If the DelegatedInkTrailPresenter creates a metadata that has the same
// timestamp as the previous one, it does not set the metadata.
IN_PROC_BROWSER_TEST_F(RenderWidgetHostDelegatedInkMetadataTest,
                       DuplicateMetadata) {}

namespace {

class LocalSurfaceIdChangedObserver
    : public RenderFrameMetadataProvider::Observer {};

}  // namespace

class RenderWidgetHostSameDocNavUpdatesLocalSurfaceIdTest
    : public RenderWidgetHostBrowserTest,
      public ::testing::WithParamInterface<bool> {};

// Assert that with `IncrementLocalSurfaceIdForMainframeSameDocNavigation`
// enabled, the `LocalSurfaceId` will be updated for same-doc navigations.
IN_PROC_BROWSER_TEST_P(RenderWidgetHostSameDocNavUpdatesLocalSurfaceIdTest,
                       SameDocNavigationUpdatesLocalSurfaceId) {}

INSTANTIATE_TEST_SUITE_P();

namespace {

enum class TestConfig {};

static std::string DescribeTest(
    const ::testing::TestParamInfo<TestConfig>& info) {}

class ItemSequenceNumberObserver : public RenderFrameMetadataProvider::Observer,
                                   public WebContentsObserver {};

class RenderWidgetHostItemSequenceNumberInRenderFrameMetadataTest
    : public RenderWidgetHostBrowserTest,
      public ::testing::WithParamInterface<TestConfig> {};

}  // namespace

// TODO(crbug.com/362200328): Re-enable test.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_ItemSequenceNumberExpected
#else
#define MAYBE_ItemSequenceNumberExpected
#endif
IN_PROC_BROWSER_TEST_P(
    RenderWidgetHostItemSequenceNumberInRenderFrameMetadataTest,
    MAYBE_ItemSequenceNumberExpected) {}

INSTANTIATE_TEST_SUITE_P();

}  // namespace content