chromium/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc

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

#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h"
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
#include "chrome/browser/web_applications/test/os_integration_test_override_impl.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/blocked_content/popup_blocker_tab_helper.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/metrics/content/subprocess_metrics_provider.h"
#include "components/permissions/permission_request_manager.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/frame/user_activation_state.h"
#include "third_party/blink/public/common/switches.h"
#include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom.h"
#include "ui/display/screen_base.h"
#include "ui/display/test/test_screen.h"
#include "ui/display/test/virtual_display_util.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/shell.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/test/display_manager_test_api.h"  // nogncheck
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

#if BUILDFLAG(IS_LINUX) && BUILDFLAG(IS_OZONE)
#include "ui/ozone/public/ozone_platform.h"
#endif  // BUILDFLAG(IS_LINUX) && BUILDFLAG(IS_OZONE)

#if BUILDFLAG(IS_MAC)
#include "ui/base/cocoa/nswindow_test_util.h"
#endif  // BUILDFLAG(IS_MAC)

#if defined(USE_AURA)
#include "ui/aura/window.h"
#endif  // USE_AURA

WebContents;

namespace {

const base::FilePath::CharType* kSimpleFile =);

}  // namespace

class FullscreenControllerInteractiveTest : public ExclusiveAccessTest {};

void FullscreenControllerInteractiveTest::ToggleTabFullscreen(
    bool enter_fullscreen) {}

// |ToggleTabFullscreen| should not need to tolerate the transition failing.
// Most fullscreen tests run sharded in fullscreen_controller_browsertest.cc
// and some flakiness has occurred when calling |ToggleTabFullscreen|, so that
// method has been made robust by retrying if the transition fails.
// The root cause of that flakiness should still be tracked down, see
// http://crbug.com/133831. In the mean time, this method
// allows a fullscreen_controller_interactive_browsertest.cc test to verify
// that when running serially there is no flakiness in the transition.
void FullscreenControllerInteractiveTest::ToggleTabFullscreenNoRetries(
    bool enter_fullscreen) {}

void FullscreenControllerInteractiveTest::ToggleBrowserFullscreen(
    bool enter_fullscreen) {}

void FullscreenControllerInteractiveTest::ToggleTabFullscreen_Internal(
    bool enter_fullscreen, bool retry_until_success) {}

// Tests ///////////////////////////////////////////////////////////////////////

// Tests that while in fullscreen creating a new tab will exit fullscreen.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       TestNewTabExitsFullscreen) {}

// Tests a tab exiting fullscreen will bring the browser out of fullscreen.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       TestTabExitsItselfFromFullscreen) {}

// Tests that the closure provided to RunOrDeferUntilTransitionIsComplete is
// run. Some platforms may be synchronous (lambda is executed immediately) and
// others (e.g. Mac) will run it asynchronously (after the transition).
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       RunOrDeferClosureDuringTransition) {}

// Tests Fullscreen entered in Browser, then Tab mode, then exited via Browser.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       BrowserFullscreenExit) {}

// Tests Browser Fullscreen remains active after Tab mode entered and exited.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       BrowserFullscreenAfterTabFSExit) {}

// Tests fullscreen entered without permision prompt for file:// urls.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest, FullscreenFileURL) {}

// Tests fullscreen is exited on page navigation.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       TestTabExitsFullscreenOnNavigation) {}

// Test is flaky on all platforms: https://crbug.com/1234337
// Tests fullscreen is exited when navigating back.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       DISABLED_TestTabExitsFullscreenOnGoBack) {}

// Tests fullscreen is not exited on sub frame navigation.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       TestTabDoesntExitFullscreenOnSubFrameNavigation) {}

// Test is flaky on all platforms: https://crbug.com/1234337
// Tests tab fullscreen exits, but browser fullscreen remains, on navigation.
IN_PROC_BROWSER_TEST_F(
    FullscreenControllerInteractiveTest,
    DISABLED_TestFullscreenFromTabWhenAlreadyInBrowserFullscreenWorks) {}

// TODO(crbug.com/40779265) Flaky on Linux-ozone, Lacros and MacOS.
#if (BUILDFLAG(IS_LINUX) && BUILDFLAG(IS_OZONE)) || \
    BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_MAC)
#define MAYBE_TabEntersPresentationModeFromWindowed
#else
#define MAYBE_TabEntersPresentationModeFromWindowed
#endif
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       MAYBE_TabEntersPresentationModeFromWindowed) {}

// Tests pointer lock can be escaped with ESC key.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       EscapingPointerLock) {}

// Tests pointer lock and fullscreen modes can be escaped with ESC key.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       EscapingPointerLockAndFullscreen) {}

// Tests pointer lock then fullscreen.
// TODO(crbug.com/40835508): Re-enable this test
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS)
#define MAYBE_PointerLockThenFullscreen
#else
#define MAYBE_PointerLockThenFullscreen
#endif
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       MAYBE_PointerLockThenFullscreen) {}

// Disabled on all due to issue with code under test: http://crbug.com/1255610.
//
// Was also disabled on platforms before:
// Times out sometimes on Linux. http://crbug.com/135115
// Mac: http://crbug.com/103912
// Tests pointer lock then fullscreen in same request.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       DISABLED_PointerLockAndFullscreen) {}

// Tests pointer lock can be exited and re-entered by an application silently
// with no UI distraction for users.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       PointerLockSilentAfterTargetUnlock) {}

// TODO: crbug.com/336428594 - Flaky on Lacros.
#if BUILDFLAG(IS_CHROMEOS_LACROS)
#define MAYBE_SecondPointerLockShowsBubble
#else
#define MAYBE_SecondPointerLockShowsBubble
#endif
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       MAYBE_SecondPointerLockShowsBubble) {}

// Tests pointer lock is exited on page navigation.
#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && defined(USE_AURA)
// https://crbug.com/1191964
#define MAYBE_TestTabExitsPointerLockOnNavigation
#else
#define MAYBE_TestTabExitsPointerLockOnNavigation
#endif
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       MAYBE_TestTabExitsPointerLockOnNavigation) {}

// Tests pointer lock is exited when navigating back.
#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && defined(USE_AURA)
// https://crbug.com/1192097
#define MAYBE_TestTabExitsPointerLockOnGoBack
#else
#define MAYBE_TestTabExitsPointerLockOnGoBack
#endif
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       MAYBE_TestTabExitsPointerLockOnGoBack) {}

#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \
        defined(USE_AURA) ||                                  \
    BUILDFLAG(IS_WIN) && defined(NDEBUG)
// TODO(erg): linux_aura bringup: http://crbug.com/163931
// Test is flaky on Windows: https://crbug.com/1124492
#define MAYBE_TestTabDoesntExitPointerLockOnSubFrameNavigation
#else
#define MAYBE_TestTabDoesntExitPointerLockOnSubFrameNavigation
#endif

// Tests pointer lock is not exited on sub frame navigation.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       MAYBE_TestTabDoesntExitPointerLockOnSubFrameNavigation) {}

IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       ReloadExitsPointerLockAndFullscreen) {}

// Tests ToggleFullscreenModeForTab always causes window to change.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       ToggleFullscreenModeForTab) {}

IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       OpeningPopupExitsFullscreen) {}

IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       BlockingContentsExitsFullscreen) {}

IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       CapturedContentEntersFullscreenWithinTab) {}

IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       OpeningPopupDoesNotExitFullscreenWithinTab) {}

IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
                       BlockingContentsDoesNotExitFullscreenWithinTab) {}

// Tests the automatic fullscreen content setting in IWA and non-IWA contexts.
class AutomaticFullscreenTest : public FullscreenControllerInteractiveTest,
                                public testing::WithParamInterface<bool> {};

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, RequestFullscreenNoGesture) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, ImmediatelyAfterExit) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, WithGestureAfterExit) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, EventuallyAfterExit) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, Popup) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, PopupImmediatelyAfterExit) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, PopupEventuallyAfterExit) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, ImmediatelyAfterPopupExit) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, EventuallyAfterPopupExit) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, BlockingContentsDoesNotExit) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, QueryPermissionWithGesture) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, QueryPermissionWithoutGesture) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, CrossOriginIFrameDenied) {}

IN_PROC_BROWSER_TEST_P(AutomaticFullscreenTest, CrossOriginIFrameGranted) {}

INSTANTIATE_TEST_SUITE_P();

// Configures a two-display screen environment for testing of multi-screen
// fullscreen behavior.
class TestScreenEnvironment {};

// Tests fullscreen with multi-screen features from the Window Management API.
// Sites with the Window Management permission can request fullscreen on a
// specific screen, move fullscreen windows to different displays, and more.
// Tests must run in series to manage virtual displays on supported platforms.
// Use 2+ physical displays to run locally with --gtest_also_run_disabled_tests.
// See: //docs/ui/display/multiscreen_testing.md
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
#define MAYBE_MultiScreenFullscreenControllerInteractiveTest
#else
#define MAYBE_MultiScreenFullscreenControllerInteractiveTest
#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC)
class MAYBE_MultiScreenFullscreenControllerInteractiveTest
    : public FullscreenControllerInteractiveTest {};

// TODO(crbug.com/40111905): Disabled on Windows, where views::FullscreenHandler
// implements fullscreen by directly obtaining MONITORINFO, ignoring the mocked
// display::Screen configuration used in this test. Disabled on Linux, where the
// window server's async handling of the fullscreen window state may transition
// the window into fullscreen on the actual (non-mocked) display bounds before
// or after the window bounds checks, yielding flaky results.
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC)
#define MAYBE_SeparateDisplay
#else
#define MAYBE_SeparateDisplay
#endif
// Test requesting fullscreen on a separate display.
IN_PROC_BROWSER_TEST_F(MAYBE_MultiScreenFullscreenControllerInteractiveTest,
                       MAYBE_SeparateDisplay) {}

// TODO(crbug.com/40111905): Disabled on Windows, where views::FullscreenHandler
// implements fullscreen by directly obtaining MONITORINFO, ignoring the mocked
// display::Screen configuration used in this test. Disabled on Linux, where the
// window server's async handling of the fullscreen window state may transition
// the window into fullscreen on the actual (non-mocked) display bounds before
// or after the window bounds checks, yielding flaky results.
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC)
#define MAYBE_SeparateDisplayMaximized
#else
#define MAYBE_SeparateDisplayMaximized
#endif
// Test requesting fullscreen on a separate display from a maximized window.
IN_PROC_BROWSER_TEST_F(MAYBE_MultiScreenFullscreenControllerInteractiveTest,
                       MAYBE_SeparateDisplayMaximized) {}

// TODO(crbug.com/40111905): Disabled on Windows, where views::FullscreenHandler
// implements fullscreen by directly obtaining MONITORINFO, ignoring the mocked
// display::Screen configuration used in this test. Disabled on Linux, where the
// window server's async handling of the fullscreen window state may transition
// the window into fullscreen on the actual (non-mocked) display bounds before
// or after the window bounds checks, yielding flaky results.
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC)
#define MAYBE_SameDisplayAndSwap
#else
#define MAYBE_SameDisplayAndSwap
#endif
// Test requesting fullscreen on the current display and then swapping displays.
IN_PROC_BROWSER_TEST_F(MAYBE_MultiScreenFullscreenControllerInteractiveTest,
                       MAYBE_SameDisplayAndSwap) {}

// TODO(crbug.com/40111905): Disabled on Windows, where views::FullscreenHandler
// implements fullscreen by directly obtaining MONITORINFO, ignoring the mocked
// display::Screen configuration used in this test. Disabled on Linux, where the
// window server's async handling of the fullscreen window state may transition
// the window into fullscreen on the actual (non-mocked) display bounds before
// or after the window bounds checks, yielding flaky results.
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC)
#define MAYBE_SameDisplayAndSwapMaximized
#else
#define MAYBE_SameDisplayAndSwapMaximized
#endif
// Test requesting fullscreen on the current display and then swapping displays
// from a maximized window.
IN_PROC_BROWSER_TEST_F(MAYBE_MultiScreenFullscreenControllerInteractiveTest,
                       MAYBE_SameDisplayAndSwapMaximized) {}

// TODO(crbug.com/40111905): Disabled on Windows, where views::FullscreenHandler
// implements fullscreen by directly obtaining MONITORINFO, ignoring the mocked
// display::Screen configuration used in this test. Disabled on Linux, where the
// window server's async handling of the fullscreen window state may transition
// the window into fullscreen on the actual (non-mocked) display bounds before
// or after the window bounds checks, yielding flaky results.
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC)
#define MAYBE_BrowserFullscreenContentFullscreenSwapDisplay
#else
#define MAYBE_BrowserFullscreenContentFullscreenSwapDisplay
#endif
// Test requesting browser fullscreen on current display, launching
// tab-fullscreen on a different display, and then closing tab-fullscreen to
// restore browser-fullscreen on the original display.
IN_PROC_BROWSER_TEST_F(MAYBE_MultiScreenFullscreenControllerInteractiveTest,
                       MAYBE_BrowserFullscreenContentFullscreenSwapDisplay) {}

// TODO(crbug.com/40111905): Disabled on Windows, where views::FullscreenHandler
// implements fullscreen by directly obtaining MONITORINFO, ignoring the mocked
// display::Screen configuration used in this test. Disabled on Linux, where the
// window server's async handling of the fullscreen window state may transition
// the window into fullscreen on the actual (non-mocked) display bounds before
// or after the window bounds checks, yielding flaky results.
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC)
#define MAYBE_SeparateDisplayAndSwap
#else
#define MAYBE_SeparateDisplayAndSwap
#endif
// Test requesting fullscreen on a separate display and then swapping displays.
IN_PROC_BROWSER_TEST_F(MAYBE_MultiScreenFullscreenControllerInteractiveTest,
                       MAYBE_SeparateDisplayAndSwap) {}

// TODO(crbug.com/40111905): Disabled on Windows, where views::FullscreenHandler
// implements fullscreen by directly obtaining MONITORINFO, ignoring the mocked
// display::Screen configuration used in this test. Disabled on Linux, where the
// window server's async handling of the fullscreen window state may transition
// the window into fullscreen on the actual (non-mocked) display bounds before
// or after the window bounds checks, yielding flaky results.
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC)
#define MAYBE_SwapShowsBubble
#else
#define MAYBE_SwapShowsBubble
#endif
// Test requesting fullscreen on the current display and then swapping displays.
IN_PROC_BROWSER_TEST_F(MAYBE_MultiScreenFullscreenControllerInteractiveTest,
                       MAYBE_SwapShowsBubble) {}

// TODO(crbug.com/40723237): Disabled on Windows, where RenderWidgetHostViewAura
// blindly casts display::Screen::GetScreen() to display::win::ScreenWin*.
#if BUILDFLAG(IS_WIN)
#define MAYBE_FullscreenOnPermissionGrant
#else
#define MAYBE_FullscreenOnPermissionGrant
#endif
// Test requesting fullscreen using the permission grant's transient activation.
IN_PROC_BROWSER_TEST_F(MAYBE_MultiScreenFullscreenControllerInteractiveTest,
                       MAYBE_FullscreenOnPermissionGrant) {}

// TODO(crbug.com/40111905): Disabled on Windows, where views::FullscreenHandler
// implements fullscreen by directly obtaining MONITORINFO, ignoring the mocked
// display::Screen configuration used in this test. Disabled on Mac and Linux,
// where the window server's async handling of the fullscreen window state may
// transition the window into fullscreen on the actual (non-mocked) display
// bounds before or after the window bounds checks, yielding flaky results.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
#define MAYBE_OpenPopupWhileFullscreen
#else
#define MAYBE_OpenPopupWhileFullscreen
#endif
// Test opening a popup on a separate display while fullscreen.
IN_PROC_BROWSER_TEST_F(MAYBE_MultiScreenFullscreenControllerInteractiveTest,
                       MAYBE_OpenPopupWhileFullscreen) {}

// TODO(crbug.com/40111905): Disabled on Windows, where views::FullscreenHandler
// implements fullscreen by directly obtaining MONITORINFO, ignoring the mocked
// display::Screen configuration used in this test. Disabled on Mac and Linux,
// where the window server's async handling of the fullscreen window state may
// transition the window into fullscreen on the actual (non-mocked) display
// bounds before or after the window bounds checks, yielding flaky results.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
#define MAYBE_FullscreenCompanionWindow
#else
#define MAYBE_FullscreenCompanionWindow
#endif
// Test requesting fullscreen on a specific screen and opening a cross-screen
// popup window from one gesture. Check the expected window activation pattern.
// https://w3c.github.io/window-management/#usage-overview-initiate-multi-screen-experiences
IN_PROC_BROWSER_TEST_F(MAYBE_MultiScreenFullscreenControllerInteractiveTest,
                       MAYBE_FullscreenCompanionWindow) {}