0

Remove fullscreen popups experimental feature.

Removes the fullscreen popups feature. This is mainly a revert of
crrev.com/c/4072455 and some followup CLs. Removes feature flag,
tests, UMA metrics and all of the navigation "is_fullscreen" plumbing to support the feature.

See: https://chromestatus.com/feature/6002307972464640

Bug: 345222811
Change-Id: I7994a18a8473407050ae5ec0a732df4d73732776
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5617224
Reviewed-by: Mike Wasserman <msw@chromium.org>
Reviewed-by: Avi Drissman <avi@chromium.org>
Reviewed-by: Robert Kaplow <rkaplow@chromium.org>
Reviewed-by: Nate Chapin <japhet@chromium.org>
Commit-Queue: Brad Triebwasser <btriebw@chromium.org>
Reviewed-by: Elly FJ <ellyjones@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1313712}
This commit is contained in:
Brad Triebwasser
2024-06-11 22:21:21 +00:00
committed by Chromium LUCI CQ
parent 5eb78da36f
commit e0f300d7b7
44 changed files with 26 additions and 852 deletions

@ -8529,11 +8529,6 @@ const FeatureEntry kFeatureEntries[] = {
FEATURE_VALUE_TYPE(display::features::kPanelSelfRefresh2)},
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
{"fullscreen-popup-windows", flag_descriptions::kFullscreenPopupWindowsName,
flag_descriptions::kFullscreenPopupWindowsDescription,
kOsDesktop | kOsAndroid,
FEATURE_VALUE_TYPE(blink::features::kFullscreenPopupWindows)},
{"automatic-fullscreen-content-setting",
flag_descriptions::kAutomaticFullscreenContentSettingName,
flag_descriptions::kAutomaticFullscreenContentSettingDescription,

@ -1874,12 +1874,6 @@ const char kForgotPasswordFormSupportName[] = "Forgot Password Form Support";
const char kForgotPasswordFormSupportDescription[] =
"Detect and fill usernames in forgot password forms.";
const char kFullscreenPopupWindowsName[] = "Fullscreen popup windows";
const char kFullscreenPopupWindowsDescription[] =
"Enables sites with Window Management permission to open fullscreen popup "
"windows with a `fullscreen` window.open() features parameter. See "
"https://chromestatus.com/feature/6002307972464640 for more information.";
const char kGalleryAppLensName[] = "Gallery App Lens";
const char kGalleryAppLensDescription[] =
"Enable Gallery App lens integration.";

@ -1067,9 +1067,6 @@ extern const char kForceUiDirectionDescription[];
extern const char kForgotPasswordFormSupportName[];
extern const char kForgotPasswordFormSupportDescription[];
extern const char kFullscreenPopupWindowsName[];
extern const char kFullscreenPopupWindowsDescription[];
extern const char kGalleryAppLensName[];
extern const char kGalleryAppLensDescription[];

@ -1,419 +0,0 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include "base/test/metrics/histogram_tester.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_finder.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
#include "chrome/browser/ui/test/fullscreen_test_util.h"
#include "chrome/browser/ui/test/popup_test_base.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/metrics/content/subprocess_metrics_provider.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "third_party/blink/public/common/features_generated.h"
#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom.h"
namespace {
// Log filter on messages ignoring a fullscreen [popup] request.
bool FullscreenRequestIgnoredMessageFilter(
const content::WebContentsConsoleObserver::Message& message) {
return message.message.starts_with(u"Fullscreen request ignored:");
}
// Log filter on messages indicating fullscreen permission policy is denied.
bool FullscreenPermissionPolicyViolationMessageFilter(
const content::WebContentsConsoleObserver::Message& message) {
return message.message.starts_with(
u"Permissions policy violation: fullscreen is not allowed");
}
// Base class for fullscreen popup tests.
class PopupFullscreenTestBase : public PopupTestBase {
public:
PopupFullscreenTestBase() {
scoped_feature_list_.InitWithFeatures(
{blink::features::kFullscreenPopupWindows}, {});
}
void SetUpOnMainThread() override {
content::SetupCrossSiteRedirector(embedded_test_server());
host_resolver()->AddRule("*", "127.0.0.1");
ASSERT_TRUE(embedded_test_server()->Start());
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(NavigateToURL(web_contents,
embedded_test_server()->GetURL("/simple.html")));
EXPECT_TRUE(WaitForRenderFrameReady(web_contents->GetPrimaryMainFrame()));
console_observer_ = std::make_unique<content::WebContentsConsoleObserver>(
browser()->tab_strip_model()->GetActiveWebContents());
console_observer_->SetFilter(
base::BindRepeating(&FullscreenRequestIgnoredMessageFilter));
}
protected:
std::unique_ptr<content::WebContentsConsoleObserver> console_observer_;
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
// Tests opening popups as fullscreen windows.
// See https://chromestatus.com/feature/6002307972464640 for more information.
// Tests are run with and without the requisite Window Management permission.
class PopupFullscreenTest
: public PopupFullscreenTestBase,
public ::testing::WithParamInterface<std::tuple<bool, bool>> {
public:
void SetUpOnMainThread() override {
PopupFullscreenTestBase::SetUpOnMainThread();
if (ShouldTestWindowManagement()) {
SetUpWindowManagement(browser());
// The permission prompt creates a user gesture. If we are trying to test
// without a user gesture, wait for the existing one to expire.
if (!ShouldTestWithUserGesture()) {
WaitForUserActivationExpiry(browser());
}
}
}
protected:
bool IsFullscreenExpected() {
return ShouldTestWithUserGesture() && ShouldTestWindowManagement();
}
bool ShouldTestWithUserGesture() { return std::get<0>(GetParam()); }
bool ShouldTestWindowManagement() { return std::get<1>(GetParam()); }
};
INSTANTIATE_TEST_SUITE_P(,
PopupFullscreenTest,
::testing::Combine(::testing::Bool(),
::testing::Bool()));
IN_PROC_BROWSER_TEST_P(PopupFullscreenTest, BasicFullscreen) {
// UMA Key for tracking duration of fullscreen popups.
static constexpr char kFullscreenDurationMetricKeyPopup[] =
"Blink.Element.Fullscreen.DurationUpTo1H.Popup";
base::HistogramTester histogram_tester;
Browser* popup =
OpenPopup(browser(), "open('/simple.html', '_blank', 'popup,fullscreen')",
ShouldTestWithUserGesture());
content::WebContents* popup_contents =
popup->tab_strip_model()->GetActiveWebContents();
if (IsFullscreenExpected()) {
content::WaitForHTMLFullscreen(popup_contents);
} else {
ASSERT_TRUE(console_observer_->Wait());
}
EXPECT_EQ(EvalJs(popup_contents,
"!!document.fullscreenElement && "
"document.fullscreenElement == document.documentElement")
.ExtractBool(),
IsFullscreenExpected());
FullscreenController* fullscreen_controller =
popup->exclusive_access_manager()->fullscreen_controller();
EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser());
EXPECT_EQ(fullscreen_controller->IsTabFullscreen(), IsFullscreenExpected());
// Expect no UMA samples logged yet for the popups fullscreen duration.
histogram_tester.ExpectTotalCount(kFullscreenDurationMetricKeyPopup, 0);
EXPECT_EQ(EvalJs(popup_contents, "document.exitFullscreen()").error.empty(),
IsFullscreenExpected());
EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser());
EXPECT_FALSE(fullscreen_controller->IsTabFullscreen());
// Test that a navigation doesn't re-trigger fullscreen.
EXPECT_TRUE(EvalJs(popup_contents,
"window.location.href = '" +
embedded_test_server()->GetURL("/title1.html").spec() +
"'")
.error.empty());
EXPECT_TRUE(content::WaitForLoadStop(popup_contents));
EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser());
EXPECT_FALSE(fullscreen_controller->IsTabFullscreen());
// Expect exactly 1 UMA sample logged if fullscreen was entered & exited.
metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
histogram_tester.ExpectTotalCount(kFullscreenDurationMetricKeyPopup,
IsFullscreenExpected() ? 1 : 0);
}
#if BUILDFLAG(IS_CHROMEOS_LACROS)
#define MAYBE_AboutBlankFullscreen DISABLED_AboutBlankFullscreen
#else
#define MAYBE_AboutBlankFullscreen AboutBlankFullscreen
#endif
IN_PROC_BROWSER_TEST_P(PopupFullscreenTest, MAYBE_AboutBlankFullscreen) {
Browser* popup =
OpenPopup(browser(), "open('about:blank', '_blank', 'popup,fullscreen')",
ShouldTestWithUserGesture());
content::WebContents* popup_contents =
popup->tab_strip_model()->GetActiveWebContents();
if (IsFullscreenExpected()) {
content::WaitForHTMLFullscreen(popup_contents);
} else {
ASSERT_TRUE(console_observer_->Wait());
}
EXPECT_EQ(EvalJs(popup_contents,
"!!document.fullscreenElement && "
"document.fullscreenElement == document.documentElement")
.ExtractBool(),
IsFullscreenExpected());
FullscreenController* fullscreen_controller =
popup->exclusive_access_manager()->fullscreen_controller();
EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser());
EXPECT_EQ(fullscreen_controller->IsTabFullscreen(), IsFullscreenExpected());
EXPECT_EQ(EvalJs(popup_contents, "document.exitFullscreen()").error.empty(),
IsFullscreenExpected());
EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser());
EXPECT_FALSE(fullscreen_controller->IsTabFullscreen());
// Test that a navigation doesn't re-trigger fullscreen.
EXPECT_TRUE(EvalJs(popup_contents,
"window.location.href = '" +
embedded_test_server()->GetURL("/title1.html").spec() +
"'")
.error.empty());
EXPECT_TRUE(content::WaitForLoadStop(popup_contents));
EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser());
EXPECT_FALSE(fullscreen_controller->IsTabFullscreen());
}
IN_PROC_BROWSER_TEST_P(PopupFullscreenTest, FullscreenWithBounds) {
Browser* popup =
OpenPopup(browser(),
"open('/simple.html', '_blank', "
"'height=200,width=200,top=100,left=100,fullscreen')",
ShouldTestWithUserGesture());
content::WebContents* popup_contents =
popup->tab_strip_model()->GetActiveWebContents();
if (IsFullscreenExpected()) {
content::WaitForHTMLFullscreen(popup_contents);
} else {
ASSERT_TRUE(console_observer_->Wait());
}
EXPECT_EQ(EvalJs(popup_contents,
"!!document.fullscreenElement && "
"document.fullscreenElement == document.documentElement")
.ExtractBool(),
IsFullscreenExpected());
FullscreenController* fullscreen_controller =
popup->exclusive_access_manager()->fullscreen_controller();
EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser());
EXPECT_EQ(fullscreen_controller->IsTabFullscreen(), IsFullscreenExpected());
}
// Tests that a fullscreen popup consumes a user gesture even with "popups &
// redirects" enabled and therefore a second fullscreen popup without a gesture
// will not transition to fullscreen.
IN_PROC_BROWSER_TEST_P(PopupFullscreenTest, ConsumesGesture) {
if (!IsFullscreenExpected()) {
// This test is only applicable when testing the normal use case.
GTEST_SKIP();
}
// Enable Popups & Redirects.
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
HostContentSettingsMapFactory::GetForProfile(browser()->profile())
->SetContentSettingDefaultScope(web_contents->GetURL(), GURL(),
ContentSettingsType::POPUPS,
CONTENT_SETTING_ALLOW);
// Open a fullscreen popup with a gesture and validate.
Browser* popup = OpenPopup(
browser(), "open('/simple.html', '_blank', 'popup,fullscreen')");
content::WebContents* popup_contents =
popup->tab_strip_model()->GetActiveWebContents();
content::WaitForHTMLFullscreen(popup_contents);
EXPECT_TRUE(EvalJs(popup_contents,
"!!document.fullscreenElement && "
"document.fullscreenElement == document.documentElement")
.ExtractBool());
// Open another fullscreen popup without a gesture. The popup should open but
// the fullscreen should be ignored since the user activation was consumed.
popup =
OpenPopup(browser(), "open('/simple.html', '_blank', 'popup,fullscreen')",
/*user_gesture=*/false);
popup_contents = popup->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(console_observer_->Wait());
EXPECT_FALSE(EvalJs(popup_contents,
"!!document.fullscreenElement && "
"document.fullscreenElement == document.documentElement")
.ExtractBool());
}
// Fullscreen should not work if the new window is not specified as a popup.
IN_PROC_BROWSER_TEST_P(PopupFullscreenTest, FullscreenRequiresPopupFeature) {
// OpenPopup() cannot be used here since it waits for a new browser which
// would not open in this case.
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(
EvalJs(web_contents, "open('/simple.html', '_blank', 'fullscreen')")
.error.empty());
EXPECT_EQ(console_observer_->messages().size(), 1u);
EXPECT_FALSE(
EvalJs(web_contents, "!!document.fullscreenElement").ExtractBool());
FullscreenController* fullscreen_controller =
browser()->exclusive_access_manager()->fullscreen_controller();
EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser());
EXPECT_FALSE(fullscreen_controller->IsTabFullscreen());
}
// Tests that the fullscreen flag is ignored if the window.open() does not
// result in a new window.
IN_PROC_BROWSER_TEST_P(PopupFullscreenTest, FullscreenRequiresNewWindow) {
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(NavigateToURL(web_contents, embedded_test_server()->GetURL(
"/iframe_about_blank.html")));
EXPECT_TRUE(WaitForRenderFrameReady(web_contents->GetPrimaryMainFrame()));
// OpenPopup() cannot be used here since it waits for a new browser which
// would not open in this case. open() targeting a frame named "test" in
// "iframe.html" will not create a new window.
EXPECT_TRUE(
EvalJs(web_contents,
"open('/simple.html', 'about_blank_iframe', 'popup,fullscreen')")
.error.empty());
EXPECT_EQ(console_observer_->messages().size(), 1u);
EXPECT_EQ(browser()->tab_strip_model()->count(), 1);
EXPECT_FALSE(
EvalJs(web_contents, "!!document.fullscreenElement").ExtractBool());
FullscreenController* fullscreen_controller =
browser()->exclusive_access_manager()->fullscreen_controller();
EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser());
EXPECT_FALSE(fullscreen_controller->IsTabFullscreen());
}
struct PopupFullscreenPermissionPolicyTestParams {
enum ExpectedFullscreenState { Allowed, BlockedByOpener, BlockedByOpened };
std::string test_name;
std::string opener_permission_policy_header;
std::string opened_permission_policy_header;
ExpectedFullscreenState fullscreen_expected;
bool is_fullscreen_expected_allowed() const {
return fullscreen_expected == ExpectedFullscreenState::Allowed;
}
};
constexpr char kOpenerPath[] = "/simple.html";
constexpr char kOpenedPath[] = "/title1.html";
std::unique_ptr<net::test_server::HttpResponse> SetPermissionsPolicyHeader(
std::string opener_header,
std::string opened_header,
const net::test_server::HttpRequest& request) {
const GURL& url = request.GetURL();
auto response = std::make_unique<net::test_server::BasicHttpResponse>();
// The hostname is always 127.0.0.1 here regardless of hostname used in the
// browser request. The path is used to differentiate between the opener and
// opened frame.
if (url.path() == kOpenerPath && !opener_header.empty()) {
response->AddCustomHeader("Permissions-Policy", opener_header);
}
if (url.path() == kOpenedPath && !opened_header.empty()) {
response->AddCustomHeader("Permissions-Policy", opened_header);
}
return response;
}
// Tests fullscreen popup functionality with `fullscreen` permission policy
// being allowed or blocked in the opener (initiator) and/or opened frame.
class PopupFullscreenPermissionPolicyTest
: public PopupFullscreenTestBase,
public ::testing::WithParamInterface<
PopupFullscreenPermissionPolicyTestParams> {
public:
void SetUpOnMainThread() override {
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&SetPermissionsPolicyHeader, GetParam().opener_permission_policy_header,
GetParam().opened_permission_policy_header));
PopupFullscreenTestBase::SetUpOnMainThread();
SetUpWindowManagement(browser());
}
};
using ExpectedState =
PopupFullscreenPermissionPolicyTestParams::ExpectedFullscreenState;
INSTANTIATE_TEST_SUITE_P(
,
PopupFullscreenPermissionPolicyTest,
testing::ValuesIn(std::vector<PopupFullscreenPermissionPolicyTestParams>{
{.test_name = "DefaultOpener_DefaultOpened",
.opener_permission_policy_header = "",
.opened_permission_policy_header = "",
.fullscreen_expected = ExpectedState::Allowed},
{.test_name = "DefaultOpener_SelfOpened",
.opener_permission_policy_header = "",
.opened_permission_policy_header = "fullscreen=(self)",
.fullscreen_expected = ExpectedState::Allowed},
{.test_name = "SelfOpener_DefaultOpened",
.opener_permission_policy_header = "fullscreen=(self)",
.opened_permission_policy_header = "",
.fullscreen_expected = ExpectedState::Allowed},
{.test_name = "SelfOpener_SelfOpened",
.opener_permission_policy_header = "fullscreen=(self)",
.opened_permission_policy_header = "fullscreen=(self)",
.fullscreen_expected = ExpectedState::Allowed},
{.test_name = "BlockedOpener_SelfOpened",
.opener_permission_policy_header = "fullscreen=()",
.opened_permission_policy_header = "fullscreen=(self)",
.fullscreen_expected = ExpectedState::BlockedByOpener},
{.test_name = "SelfOpener_BlockedOpened",
.opener_permission_policy_header = "fullscreen=(self)",
.opened_permission_policy_header = "fullscreen=()",
.fullscreen_expected = ExpectedState::BlockedByOpened},
{.test_name = "BlockedOpener_BlockedOpened",
.opener_permission_policy_header = "fullscreen=()",
.opened_permission_policy_header = "fullscreen=()",
.fullscreen_expected = ExpectedState::BlockedByOpener}}),
[](const testing::TestParamInfo<PopupFullscreenPermissionPolicyTestParams>&
info) { return info.param.test_name; });
// Opens a fullscreen popup and checks if fullscreen is granted based on the
// expected result for the given permission policy configurations in the test
// parameters.
IN_PROC_BROWSER_TEST_P(PopupFullscreenPermissionPolicyTest,
PermissionPolicyTest) {
std::string url =
embedded_test_server()->GetURL("cross-origin.com", kOpenedPath).spec();
Browser* popup =
OpenPopup(browser(), "open('" + url + "', '_blank', 'popup,fullscreen')");
content::WebContents* popup_contents =
popup->tab_strip_model()->GetActiveWebContents();
if (GetParam().fullscreen_expected == ExpectedState::BlockedByOpened) {
// In cases where fullscreen is blocked by the *opened* frame:
// Switch the console observer to the opened window.
console_observer_ =
std::make_unique<content::WebContentsConsoleObserver>(popup_contents);
console_observer_->SetFilter(
base::BindRepeating(&FullscreenPermissionPolicyViolationMessageFilter));
}
if (GetParam().is_fullscreen_expected_allowed()) {
content::WaitForHTMLFullscreen(popup_contents);
} else {
ASSERT_TRUE(console_observer_->Wait());
}
EXPECT_EQ(EvalJs(popup_contents,
"!!document.fullscreenElement && "
"document.fullscreenElement == document.documentElement")
.ExtractBool(),
GetParam().is_fullscreen_expected_allowed());
FullscreenController* fullscreen_controller =
popup->exclusive_access_manager()->fullscreen_controller();
EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser());
EXPECT_EQ(fullscreen_controller->IsTabFullscreen(),
GetParam().is_fullscreen_expected_allowed());
}
} // namespace

@ -6,7 +6,6 @@
#include "base/command_line.h"
#include "base/test/run_until.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@ -16,7 +15,6 @@
#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
#include "chrome/browser/ui/test/fullscreen_test_util.h"
#include "chrome/browser/ui/test/popup_test_base.h"
#include "chrome/browser/ui/views/exclusive_access_bubble_views.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "content/public/test/browser_test.h"
@ -36,33 +34,6 @@
namespace {
// Time to wait for exit bubble transitions.
static constexpr int kExitBubbleTransitionTimeMs = 500;
// Async function which opens a fullscreen popup on another screen.
// Falls back to opening a popup on the current screen in testing scenarios
// where window management is not granted in SetUpWindowManagement().
static constexpr char kFullscreenPopupOtherScreenScript[] = R"JS(
(() =>
{
otherScreen = (!!window.screenDetails && screenDetails.screens
.find(s => s != screenDetails.currentScreen)) || window.screen;
return open('/simple.html', '_blank',
`top=${otherScreen.availTop},
left=${otherScreen.availLeft},
height=200,
width=200,
popup,
fullscreen`);
})()
)JS";
// Return the exclusive access bubble view for a specified browser.
ExclusiveAccessBubbleViews* GetExclusiveAccessBubble(Browser* browser) {
BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
return browser_view->exclusive_access_bubble();
}
// Tests popups with multi-screen features from the Window Management API.
// Tests are run with and without the requisite Window Management permission.
// Tests must run in series to manage virtual displays on supported platforms.
@ -75,11 +46,6 @@ ExclusiveAccessBubbleViews* GetExclusiveAccessBubble(Browser* browser) {
class MAYBE_PopupMultiScreenTest : public PopupTestBase,
public ::testing::WithParamInterface<bool> {
public:
MAYBE_PopupMultiScreenTest() {
scoped_feature_list_.InitWithFeatures(
{blink::features::kFullscreenPopupWindows}, {});
}
void SetUpCommandLine(base::CommandLine* command_line) override {
PopupTestBase::SetUpCommandLine(command_line);
command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
@ -132,7 +98,6 @@ class MAYBE_PopupMultiScreenTest : public PopupTestBase,
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<display::test::VirtualDisplayUtil> virtual_display_util_;
};
@ -322,72 +287,4 @@ IN_PROC_BROWSER_TEST_P(MAYBE_PopupMultiScreenTest, CrossOriginIFrame) {
}
}
// Tests opening a fullscreen popup on another display, when permitted.
IN_PROC_BROWSER_TEST_P(MAYBE_PopupMultiScreenTest, FullscreenDifferentScreen) {
Browser* popup = OpenPopup(browser(), kFullscreenPopupOtherScreenScript);
content::WebContents* popup_contents =
popup->tab_strip_model()->GetActiveWebContents();
if (ShouldTestWindowManagement()) {
content::WaitForHTMLFullscreen(popup_contents);
}
EXPECT_EQ(EvalJs(popup_contents,
"!!document.fullscreenElement && "
"document.fullscreenElement == document.documentElement")
.ExtractBool(),
ShouldTestWindowManagement());
EXPECT_TRUE(EvalJs(popup_contents,
"screen.availLeft == opener.otherScreen.availLeft && "
"screen.availTop == opener.otherScreen.availTop")
.ExtractBool());
FullscreenController* fullscreen_controller =
popup->exclusive_access_manager()->fullscreen_controller();
EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser());
EXPECT_EQ(fullscreen_controller->IsTabFullscreen(),
ShouldTestWindowManagement());
}
// Similar to FullscreenDifferentScreen, but focuses on exit bubble behavior.
// Tests that the fullscreen exit bubble is reshown when the cursor initially
// enters the screen where a fullscreen popup was opened.
IN_PROC_BROWSER_TEST_P(MAYBE_PopupMultiScreenTest,
FullscreenDifferentScreenExitBubble) {
if (!ShouldTestWindowManagement()) {
GTEST_SKIP() << "Test not applicable with window management disabled.";
}
Browser* popup = OpenPopup(browser(), kFullscreenPopupOtherScreenScript);
content::WebContents* popup_contents =
popup->tab_strip_model()->GetActiveWebContents();
WaitForHTMLFullscreen(popup_contents);
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetExclusiveAccessBubble(popup) != nullptr; }));
ExclusiveAccessBubbleViews* bubble = GetExclusiveAccessBubble(popup);
auto wait_for_visible = [&](bool visible) {
return base::test::RunUntil(
[&]() { return bubble->IsVisibleForTesting() == visible; });
};
// Wait for the exit bubble to become visible.
ASSERT_TRUE(wait_for_visible(true));
// Wait for the exit bubble to auto-hide.
ASSERT_TRUE(wait_for_visible(false));
// Simulate user input on the exclusive context.
display::Screen::GetScreen()->SetCursorScreenPointForTesting(
popup->window()->GetBounds().CenterPoint());
bubble->OnUserInput();
// Wait for bubble to re-appear.
ASSERT_TRUE(wait_for_visible(true));
// Wait for the bubble to auto-hide again.
ASSERT_TRUE(wait_for_visible(false));
// Simulate input and ensure the exit bubble doesn't show again.
bubble->OnUserInput();
// Wait a short amount of time (for any transition), and ensure the exit
// bubble is not visible.
base::Time now = base::Time::Now();
ASSERT_TRUE(base::test::RunUntil([&]() {
return (base::Time::Now() - now).InMilliseconds() >
kExitBubbleTransitionTimeMs;
}));
EXPECT_FALSE(bubble->IsVisibleForTesting());
}
} // namespace

@ -2853,7 +2853,6 @@ if (!is_android) {
"../browser/ui/test/fullscreen_test_util.cc",
"../browser/ui/test/fullscreen_test_util.h",
"../browser/ui/test/popup_browsertest.cc",
"../browser/ui/test/popup_fullscreen_browsertest.cc",
"../browser/ui/test/test_browser_dialog.cc",
"../browser/ui/test/test_browser_dialog.h",
"../browser/ui/test/test_infobar.cc",

@ -305,7 +305,6 @@ UseCounterMetricsRecorder::GetAllowedUkmFeatures() {
WebFeature::kURLPatternReliantOnLaterComponentFromBaseURL,
WebFeature::kV8Window_GetScreenDetails_Method,
WebFeature::kV8Window_ShowSaveFilePicker_Method,
WebFeature::kFullscreenAllowedByWindowOpen,
WebFeature::kChromeCSIUnknown,
WebFeature::kChromeCSIOnloadT,
WebFeature::kChromeCSIPageT,

@ -325,8 +325,8 @@ enum BadMessageReason {
BIBI_BIND_PRESSURE_MANAGER_BLOCKED_BY_PERMISSIONS_POLICY = 297,
RFSCI_BROWSER_VALIDATION_BAD_ORIGIN_TRIAL_TOKEN = 298,
RFH_RECEIVED_INVALID_BROWSING_TOPICS_ATTRIBUTE = 299,
RFHI_FULLSCREEN_NAV_INVALID_INITIAL_DOCUMENT = 300,
RFHI_FULLSCREEN_NAV_NOT_OUTERMOST_MAIN_FRAME = 301,
OBSOLETE_RFHI_FULLSCREEN_NAV_INVALID_INITIAL_DOCUMENT = 300,
OBSOLETE_RFHI_FULLSCREEN_NAV_NOT_OUTERMOST_MAIN_FRAME = 301,
MH_MIDI_PERMISSION = 302,
RFH_CAN_ACCESS_FILES_OF_PAGE_STATE_AT_COMMIT = 303,
PSI_REQUEST_EMBEDDED_PERMISSION_WITHOUT_FEATURE = 304,

@ -243,9 +243,7 @@ class NavigationURLLoaderImplTest : public testing::Test {
base::TimeTicks() /* renderer_before_unload_end */,
blink::mojom::NavigationInitiatorActivationAndAdStatus::
kDidNotStartWithTransientActivation,
false /* is_container_initiated */,
false /* is_fullscreen_requested */,
false /* has_storage_access */);
false /* is_container_initiated */, false /* has_storage_access */);
auto common_params = blink::CreateCommonNavigationParams();
common_params->url = url;

@ -98,9 +98,7 @@ class NavigationURLLoaderTest : public testing::Test {
base::TimeTicks() /* renderer_before_unload_end */,
blink::mojom::NavigationInitiatorActivationAndAdStatus::
kDidNotStartWithTransientActivation,
false /* is_container_initiated */,
false /* is_fullscreen_requested */,
false /* has_storage_access */);
false /* is_container_initiated */, false /* has_storage_access */);
auto common_params = blink::CreateCommonNavigationParams();
common_params->url = url;
common_params->initiator_origin = url::Origin::Create(url);

@ -1266,7 +1266,7 @@ std::unique_ptr<NavigationRequest> NavigationRequest::Create(
base::TimeTicks() /* renderer_before_unload_start */,
base::TimeTicks() /* renderer_before_unload_end */,
initiator_activation_and_ad_status, is_container_initiated,
false /* is_fullscreen_requested */, false /* has_storage_access */);
false /* has_storage_access */);
// Shift-Reload forces bypassing caches and service workers.
if (common_params->navigation_type ==

@ -240,7 +240,6 @@
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/features_generated.h"
#include "third_party/blink/public/common/fenced_frame/fenced_frame_utils.h"
#include "third_party/blink/public/common/frame/fenced_frame_sandbox_flags.h"
#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
@ -273,7 +272,6 @@
#include "third_party/blink/public/mojom/navigation/renderer_eviction_reason.mojom.h"
#include "third_party/blink/public/mojom/opengraph/metadata.mojom.h"
#include "third_party/blink/public/mojom/page/draggable_region.mojom.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom.h"
#include "third_party/blink/public/mojom/storage_key/ancestor_chain_bit.mojom.h"
#include "third_party/blink/public/mojom/timing/resource_timing.mojom.h"
@ -7032,17 +7030,6 @@ void RenderFrameHostImpl::MainDocumentElementAvailable(
delegate_->PrimaryMainDocumentElementAvailable();
if (base::FeatureList::IsEnabled(blink::features::kFullscreenPopupWindows) &&
fullscreen_document_on_document_element_ready_ &&
(*fullscreen_document_on_document_element_ready_) == GetDocumentToken()) {
fullscreen_document_on_document_element_ready_ = std::nullopt;
// Create a fullscreen request token to waive the user activation
// requirement when the request is received back to the browser in
// `EnterFullscreen`.
fullscreen_request_token_.Activate();
GetAssociatedLocalFrame()->RequestFullscreenDocumentElement();
}
if (!uses_temporary_zoom_level)
return;
@ -9783,49 +9770,6 @@ void RenderFrameHostImpl::BeginNavigation(
}
}
if (begin_params->is_fullscreen_requested) {
// Fullscreen requests on navigation are only allowed from initial empty
// documents that are the outermost main frame.
if (!is_initial_empty_document()) {
bad_message::ReceivedBadMessage(
GetProcess(),
bad_message::RFHI_FULLSCREEN_NAV_INVALID_INITIAL_DOCUMENT);
return;
}
if (!IsOutermostMainFrame()) {
bad_message::ReceivedBadMessage(
GetProcess(),
bad_message::RFHI_FULLSCREEN_NAV_NOT_OUTERMOST_MAIN_FRAME);
return;
}
RenderFrameHostImpl* initiator_render_frame_host =
begin_params->initiator_frame_token
? RenderFrameHostImpl::FromFrameToken(
initiator_process_id,
begin_params->initiator_frame_token.value())
: nullptr;
// The initiator needs window-management permission, window-management and
// fullscreen permission policies, and a user gesture or other allowance,
// otherwise the fullscreen bit is dropped.
if (!initiator_render_frame_host ||
!(validated_common_params->has_user_gesture ||
!initiator_render_frame_host->delegate_
->IsTransientActivationRequiredForHtmlFullscreen()) ||
!IsWindowManagementGranted(initiator_render_frame_host) ||
!initiator_render_frame_host->permissions_policy()->IsFeatureEnabled(
blink::mojom::PermissionsPolicyFeature::kFullscreen) ||
!initiator_render_frame_host->permissions_policy()->IsFeatureEnabled(
blink::mojom::PermissionsPolicyFeature::kWindowManagement)) {
if (initiator_render_frame_host) {
initiator_render_frame_host->AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kWarning,
"Fullscreen request ignored: Insufficient permissions "
"or user activation.");
}
begin_params->is_fullscreen_requested = false;
}
}
GetProcess()->FilterURL(true, &begin_params->searchable_form_url);
// If the request was for a blob URL, but the validated URL is no longer a
@ -14250,19 +14194,6 @@ void RenderFrameHostImpl::TakeNewDocumentPropertiesFromNavigation(
early_hints_manager_ = navigation_request->TakeEarlyHintsManager();
// If fullscreen was requested on the navigation, then set a signal to trigger
// a fullscreen request when the document element is ready. If a previous
// navigation was committed without a call to `MainDocumentElementAvailable`
// before the current navigation then this value is overwritten by the current
// navigation.
fullscreen_document_on_document_element_ready_.reset();
if (navigation_request->begin_params().is_fullscreen_requested) {
fullscreen_document_on_document_element_ready_ =
navigation_request->GetDocumentToken();
}
CHECK(!fullscreen_document_on_document_element_ready_ ||
IsOutermostMainFrame());
// Only take some properties if this is not the synchronous initial
// `about:blank` navigation, because the values set at construction time
// should remain unmodified.

@ -5154,14 +5154,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
// `cookie_change_listener_` in `NavigationRequest`.
std::unique_ptr<CookieChangeListener> cookie_change_listener_;
// Contains a document token to fullscreen when the document element is ready.
// Set when a committed navigation requested fullscreen (e.g. Fullscreen popup
// window) and triggers a fullscreen on the document element once it is ready
// (`MainDocumentElementAvailable` dispatched).
// See: https://chromestatus.com/feature/6002307972464640
std::optional<blink::DocumentToken>
fullscreen_document_on_document_element_ready_ = std::nullopt;
// If true, the renderer side widget is created after the navigation is
// committed.
bool waiting_for_renderer_widget_creation_after_commit_ = false;

@ -1661,8 +1661,7 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitViaDisabledWebSecurityTest,
base::TimeTicks() /* renderer_before_unload_end */,
blink::mojom::NavigationInitiatorActivationAndAdStatus::
kDidNotStartWithTransientActivation,
false /* is_container_initiated */,
false /* is_fullscreen_requested */, false /* has_storage_access */);
false /* is_container_initiated */, false /* has_storage_access */);
// Receiving the invalid IPC message should lead to renderer process
// termination.
@ -1696,39 +1695,6 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitViaDisabledWebSecurityTest,
EXPECT_TRUE(result.empty());
}
// Test to verify that an exploited renderer process trying to specify a
// a fullscreen request should not work from a non-initially-empty document.
IN_PROC_BROWSER_TEST_F(SecurityExploitViaDisabledWebSecurityTest,
FullscreenRequestMustBeFromEmptyDocument) {
GURL start_url(embedded_test_server()->GetURL("/title1.html"));
EXPECT_TRUE(NavigateToURL(shell(), start_url));
RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
shell()->web_contents()->GetPrimaryMainFrame());
// Setup a BeginNavigate IPC with is_fullscreen_requested set to true.
blink::mojom::CommonNavigationParamsPtr common_params =
blink::mojom::CommonNavigationParams::New();
common_params->url = GetTestUrl("", "simple_page.html"),
common_params->initiator_origin = url::Origin::Create(start_url);
blink::mojom::BeginNavigationParamsPtr begin_params =
blink::mojom::BeginNavigationParams::New();
begin_params->is_fullscreen_requested = true;
// Receiving the invalid IPC message should lead to renderer process
// termination.
RenderProcessHostBadIpcMessageWaiter process_kill_waiter(rfh->GetProcess());
mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client;
auto navigation_client_receiver =
navigation_client.InitWithNewEndpointAndPassReceiver();
rfh->frame_host_receiver_for_testing().impl()->BeginNavigation(
std::move(common_params), std::move(begin_params), mojo::NullRemote(),
std::move(navigation_client), mojo::NullRemote(), mojo::NullReceiver());
EXPECT_EQ(bad_message::RFHI_FULLSCREEN_NAV_INVALID_INITIAL_DOCUMENT,
process_kill_waiter.Wait());
}
// Tests what happens when a web renderer asks to begin navigating to a file
// url.
IN_PROC_BROWSER_TEST_F(SecurityExploitViaDisabledWebSecurityTest,

@ -24,7 +24,6 @@ blink::mojom::WindowFeaturesPtr ConvertWebWindowFeaturesToMojoWindowFeatures(
result->bounds.set_height(web_window_features.height);
result->has_height = web_window_features.height_set;
result->is_popup = web_window_features.is_popup;
result->is_fullscreen = web_window_features.is_fullscreen;
return result;
}
@ -40,7 +39,6 @@ blink::WebWindowFeatures ConvertMojoWindowFeaturesToWebWindowFeatures(
result.height = window_features.bounds.height();
result.height_set = window_features.has_height;
result.is_popup = window_features.is_popup;
result.is_fullscreen = window_features.is_fullscreen;
return result;
}

@ -227,8 +227,6 @@ void FakeLocalFrame::AddResourceTimingEntryForFailedSubframeNavigation(
const std::string& normalized_server_timing,
const ::network::URLLoaderCompletionStatus& completion_status) {}
void FakeLocalFrame::RequestFullscreenDocumentElement() {}
void FakeLocalFrame::BindFrameHostReceiver(
mojo::ScopedInterfaceEndpointHandle handle) {
receiver_.Bind(mojo::PendingAssociatedReceiver<blink::mojom::LocalFrame>(

@ -175,7 +175,6 @@ class FakeLocalFrame : public blink::mojom::LocalFrame {
bool is_validated,
const std::string& normalized_server_timing,
const ::network::URLLoaderCompletionStatus& completion_status) override;
void RequestFullscreenDocumentElement() override;
void UpdatePrerenderURL(const ::GURL& matched_url,
UpdatePrerenderURLCallback callback) override;

@ -5597,9 +5597,6 @@ void RenderFrameImpl::BeginNavigation(
// If this is a subframe history navigation that should be sent to the
// browser, don't commit it synchronously.
!is_history_navigation_in_new_child_frame &&
// Fullscreen navigation requests must go to the browser (for permission
// checks and other security measures).
!info->is_fullscreen_requested &&
// Synchronous about:blank commits on iframes should only be triggered
// when first creating the iframe with an unset/about:blank URL, which
// means the origin should inherit from the parent.
@ -6148,8 +6145,7 @@ void RenderFrameImpl::BeginNavigationInternal(
: nullptr,
info->impression, renderer_before_unload_start,
renderer_before_unload_end, initiator_activation_and_ad_status,
info->is_container_initiated, info->is_fullscreen_requested,
info->has_storage_access);
info->is_container_initiated, info->has_storage_access);
mojo::PendingAssociatedRemote<mojom::NavigationClient>
navigation_client_remote;

@ -1361,8 +1361,7 @@ bool NavigationSimulatorImpl::SimulateRendererInitiatedStart() {
kStartedWithTransientActivationFromNonAd
: blink::mojom::NavigationInitiatorActivationAndAdStatus::
kDidNotStartWithTransientActivation,
false /* is_container_initiated */,
false /* is_fullscreen_requested */, false /* has_storage_access */);
false /* is_container_initiated */, false /* has_storage_access */);
auto common_params = blink::CreateCommonNavigationParams();
common_params->navigation_start =
navigation_start_.is_null() ? base::TimeTicks::Now() : navigation_start_;

@ -454,8 +454,7 @@ void TestRenderFrameHost::SendRendererInitiatedNavigationRequest(
base::TimeTicks() /* renderer_before_unload_end */,
blink::mojom::NavigationInitiatorActivationAndAdStatus::
kDidNotStartWithTransientActivation,
false /* is_container_initiated */,
false /* is_fullscreen_requested */, false /* has_storage_access */);
false /* is_container_initiated */, false /* has_storage_access */);
auto common_params = blink::CreateCommonNavigationParams();
common_params->url = url;
common_params->initiator_origin = GetLastCommittedOrigin();

@ -1169,10 +1169,6 @@ interface LocalFrame {
string normalized_server_timing,
network.mojom.URLLoaderCompletionStatus completion_status
);
// The browser requests the renderer to fullscreen the document element.
// See: https://chromestatus.com/feature/6002307972464640
RequestFullscreenDocumentElement();
};
// Implemented in Blink, this interface defines main-frame-specific methods that

@ -183,10 +183,6 @@ struct BeginNavigationParams {
// TODO(https://github.com/whatwg/html/issues/8846): clarify this further.
bool is_container_initiated = false;
// True if the initiator requested the tab become fullscreen after navigation.
// See: https://chromestatus.com/feature/6002307972464640
bool is_fullscreen_requested = false;
// Whether this navigation can include cookies via the Storage Access API,
// according to the renderer. Note that this is not trusted; cookies will not
// actually be attached unless there is also a matching permission grant

@ -3867,8 +3867,8 @@ enum WebFeature {
kHtmlClipboardApiUnsanitizedRead = 4522,
kHtmlClipboardApiUnsanitizedWrite = 4523,
kAsyncClipboardAPIUnsanitizedRead = 4524,
kWindowOpenFullscreenRequested = 4525,
kFullscreenAllowedByWindowOpen = 4526,
kOBSOLETE_WindowOpenFullscreenRequested = 4525,
kOBSOLETE_FullscreenAllowedByWindowOpen = 4526,
// The items above roughly this point are available in the M113 branch.
kAttributeValueContainsLtOrGt = 4527,

@ -17,9 +17,4 @@ struct WindowFeatures {
bool has_height = false;
bool is_popup = false;
// True if the new window was requested to be shown fullscreen.
// Window management permission must be granted on the opener.
// See: https://chromestatus.com/feature/6002307972464640
bool is_fullscreen = false;
};

@ -199,11 +199,6 @@ struct BLINK_EXPORT WebNavigationInfo {
// src. Only container-initiated navigation report resource timing to the
// parent.
bool is_container_initiated = false;
// True if the initiator requested that the tab become fullscreen
// after navigation (e.g. the initial navigation of a fullscreen popup).
// See: https://chromestatus.com/feature/6002307972464640
bool is_fullscreen_requested = false;
};
// This structure holds all information provided by the embedder that is

@ -50,11 +50,6 @@ struct WebWindowFeatures {
bool is_popup = false;
// True if the new window was requested to be shown fullscreen.
// Window management permission must be granted on the opener.
// See: https://chromestatus.com/feature/6002307972464640
bool is_fullscreen = false;
// The members above this line are transferred through mojo
// in the form of |struct WindowFeatures| defined in window_features.mojom,
// to be used across process boundaries.

@ -2297,20 +2297,6 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
if (!result.frame)
return nullptr;
// If the resulting frame didn't create a new window and fullscreen was
// requested, reset the flag to prevent making a pre-existing frame
// fullscreen.
if (window_features.is_fullscreen &&
(!result.new_window || !window_features.is_popup)) {
window_features.is_fullscreen = false;
GetFrameConsole()->AddMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kJavaScript,
mojom::blink::ConsoleMessageLevel::kWarning,
"Fullscreen request ignored: 'fullscreen' "
"windowFeature flag requires a new popup window."));
frame_request.SetFeaturesForWindowOpen(window_features);
}
if (window_features.x_set || window_features.y_set) {
// This runs after FindOrCreateFrameForNavigation() so blocked popups are
// not counted.

@ -192,8 +192,7 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
std::unique_ptr<SourceLocation> source_location,
mojo::PendingRemote<mojom::blink::NavigationStateKeepAliveHandle>
initiator_navigation_state_keep_alive_handle,
bool is_container_initiated,
bool is_fullscreen_requested) = 0;
bool is_container_initiated) = 0;
virtual void DispatchWillSendSubmitEvent(HTMLFormElement*) = 0;

@ -588,8 +588,7 @@ void LocalFrameClientImpl::BeginNavigation(
std::unique_ptr<SourceLocation> source_location,
mojo::PendingRemote<mojom::blink::NavigationStateKeepAliveHandle>
initiator_navigation_state_keep_alive_handle,
bool is_container_initiated,
bool is_fullscreen_requested) {
bool is_container_initiated) {
if (!web_frame_->Client())
return;
@ -641,15 +640,6 @@ void LocalFrameClientImpl::BeginNavigation(
}
navigation_info->impression = impression;
navigation_info->is_fullscreen_requested = is_fullscreen_requested;
// TODO(crbug.com/1142516): Enforce requirements here, before IPC to browser?
if (is_fullscreen_requested && !request.HasUserGesture() && origin_frame &&
origin_frame->GetSettings() &&
!origin_frame->GetSettings()
->GetRequireTransientActivationForHtmlFullscreen()) {
UseCounter::Count(origin_frame->GetDocument(),
WebFeature::kFullscreenAllowedByContentSetting);
}
// Allow cookie access via Storage Access API during the navigation, if the
// initiator has obtained storage access. Note that the network service still

@ -141,8 +141,7 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
std::unique_ptr<SourceLocation> source_location,
mojo::PendingRemote<mojom::blink::NavigationStateKeepAliveHandle>
initiator_navigation_state_keep_alive_handle,
bool is_container_initiated,
bool is_fullscreen_requested) override;
bool is_container_initiated) override;
void DispatchWillSendSubmitEvent(HTMLFormElement*) override;
void DidStartLoading() override;
void DidStopLoading() override;

@ -32,7 +32,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_fullscreen_options.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/focus_params.h"
#include "third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h"
@ -52,7 +51,6 @@
#include "third_party/blink/renderer/core/frame/savable_resources.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/fullscreen/scoped_allow_fullscreen.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html/html_embed_element.h"
#include "third_party/blink/renderer/core/html/html_link_element.h"
@ -1405,23 +1403,6 @@ void LocalFrameMojoHandler::AddResourceTimingEntryForFailedSubframeNavigation(
subframe->Owner()->AddResourceTiming(std::move(info));
}
void LocalFrameMojoHandler::RequestFullscreenDocumentElement() {
// Bail early and report failure if fullscreen is not enabled.
if (!Fullscreen::FullscreenEnabled(*frame_->GetDocument(),
ReportOptions::kReportOnFailure)) {
return;
}
if (auto* document_element = frame_->GetDocument()->documentElement()) {
// `kWindowOpen` assumes this function is only invoked for newly created
// windows (e.g. fullscreen popups). Update this if additional callers are
// added. See: https://chromestatus.com/feature/6002307972464640
ScopedAllowFullscreen allow_fullscreen(ScopedAllowFullscreen::kWindowOpen);
Fullscreen::RequestFullscreen(*document_element,
FullscreenOptions::Create(),
FullscreenRequestType::kForWindowOpen);
}
}
void LocalFrameMojoHandler::RequestFullscreenVideoElement() {
// Find the first video element of the frame.
for (auto* child = frame_->GetDocument()->documentElement(); child;

@ -234,7 +234,6 @@ class LocalFrameMojoHandler
bool is_validated,
const WTF::String& normalized_server_timing,
const ::network::URLLoaderCompletionStatus& completion_status) final;
void RequestFullscreenDocumentElement() final;
// blink::mojom::LocalMainFrame overrides:
void AnimateDoubleTapZoom(const gfx::Point& point,

@ -370,16 +370,6 @@ bool AllowedToRequestFullscreen(Document& document) {
return true;
}
// The algorithm is triggered by a browser initiated fullscreen of the
// frame's document element. Used in cases like fullscreen popups where the
// browser triggers fullscreen after a navigation. See:
// https://chromestatus.com/feature/6002307972464640
if (ScopedAllowFullscreen::FullscreenAllowedReason() ==
ScopedAllowFullscreen::kWindowOpen) {
UseCounter::Count(document, WebFeature::kFullscreenAllowedByWindowOpen);
return true;
}
// The algorithm is triggered by another event with transient affordances,
// e.g. permission-gated events for user-generated screens changes.
if (RuntimeEnabledFeatures::WindowPlacementFullscreenOnScreensChangeEnabled(

@ -16,7 +16,7 @@ class CORE_EXPORT ScopedAllowFullscreen {
STACK_ALLOCATED();
public:
enum Reason { kOrientationChange, kXrOverlay, kXrSession, kWindowOpen };
enum Reason { kOrientationChange, kXrOverlay, kXrSession };
static std::optional<Reason> FullscreenAllowedReason();
explicit ScopedAllowFullscreen(Reason);

@ -129,8 +129,7 @@ void EmptyLocalFrameClient::BeginNavigation(
const LocalFrameToken* initiator_frame_token,
std::unique_ptr<SourceLocation>,
mojo::PendingRemote<mojom::blink::NavigationStateKeepAliveHandle>,
bool is_container_initiated,
bool is_fullscreen_requested) {}
bool is_container_initiated) {}
void EmptyLocalFrameClient::DispatchWillSendSubmitEvent(HTMLFormElement*) {}

@ -353,8 +353,7 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
const LocalFrameToken* initiator_frame_token,
std::unique_ptr<SourceLocation>,
mojo::PendingRemote<mojom::blink::NavigationStateKeepAliveHandle>,
bool is_container_initiated,
bool is_fullscreen_requested) override;
bool is_container_initiated) override;
void DispatchWillSendSubmitEvent(HTMLFormElement*) override;

@ -210,13 +210,6 @@ struct CORE_EXPORT FrameLoadRequest {
return force_history_push_;
}
bool IsFullscreenRequested() const {
// If the window was requested as fullscreen and a popup, then the loaded
// frame should enter fullscreen.
// See: https://chromestatus.com/feature/6002307972464640
return GetWindowFeatures().is_fullscreen && GetWindowFeatures().is_popup;
}
// This function is meant to be used in HTML/SVG attributes where dangling
// markup injection occurs. See https://github.com/whatwg/html/pull/9309.
const AtomicString& CleanNavigationTarget(const AtomicString& target) const;

@ -919,7 +919,7 @@ void FrameLoader::StartNavigation(FrameLoadRequest& request,
request.Impression(), request.GetInitiatorFrameToken(),
request.TakeSourceLocation(),
request.TakeInitiatorNavigationStateKeepAliveHandle(),
request.IsContainerInitiated(), request.IsFullscreenRequested());
request.IsContainerInitiated());
}
static void FillStaticResponseIfNeeded(WebNavigationParams* params,

@ -166,7 +166,7 @@ WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string,
}
if (!ui_features_were_disabled && key_string != "noopener" &&
key_string != "noreferrer" && key_string != "fullscreen" &&
key_string != "noreferrer" &&
(!attribution_reporting_enabled || key_string != "attributionsrc")) {
ui_features_were_disabled = true;
menu_bar = false;
@ -208,14 +208,6 @@ WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string,
window_features.background = true;
} else if (key_string == "persistent") {
window_features.persistent = true;
} else if (key_string == "fullscreen" &&
RuntimeEnabledFeatures::FullscreenPopupWindowsEnabled(
dom_window)) {
// TODO(crbug.com/1142516): Add permission check to give earlier
// feedback / console warning if permission isn't granted, and/or just
// silently drop the flag. Currently the browser will block the popup
// entirely if this flag is set and permission is not granted.
window_features.is_fullscreen = value;
} else if (attribution_reporting_enabled &&
key_string == "attributionsrc") {
if (!window_features.attribution_srcs.has_value()) {
@ -250,11 +242,6 @@ WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string,
if (window_features.noreferrer)
window_features.noopener = true;
if (window_features.is_fullscreen) {
UseCounter::Count(dom_window->document(),
WebFeature::kWindowOpenFullscreenRequested);
}
return window_features;
}

@ -1924,15 +1924,6 @@
name: "FreezeFramesOnVisibility",
status: "experimental",
},
{
// Enables `fullscreen` windowFeatures parameter in window.open().
name: "FullscreenPopupWindows",
status: "experimental",
base_feature_status: "enabled",
copied_from_base_feature_if: "overridden",
origin_trial_feature_name: "FullscreenPopupWindows",
origin_trial_os: ["win", "mac", "linux", "chromeos"],
},
{
name: "GamepadButtonAxisEvents",
status: "experimental",

@ -1,51 +0,0 @@
<!DOCTYPE html>
<meta name="timeout" content="long">
<!-- user agents are not required to support open features other than `noopener`
and on some platforms position and size features don't make sense -->
<meta name="flags" content="may">
<title>Window Management test: Fullscreen popups with window.open()</title>
<link rel="help" href="https://w3c.github.io/window-management/">
Tests the ability to open a fullscreen popup window on each screen.<br>
The host device must have 2+ screens to test cross-screen fullscreen popups.
<br><br>
<button id="closeButton" onclick="closePopups">Close popups</button><br>
<input id="autoClose" type="checkbox" checked=true>Auto-close popups</input>
<ul id="list"></ul>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="resources/helpers.js"></script>
<script>
'use strict';
let popups = [];
function closePopups() {
popups.forEach(p => p.close());
popups = [];
}
promise_test(async setUpTest => {
await setUpWindowManagement(setUpTest);
for (const [i, s] of window.screenDetails.screens.entries()) {
const name = `Open a fullscreen popup on '${s.label || i}'`;
await promise_test(async test => {
await buttonClick(test, name);
const popup = await openPopupOnScreen(s, /*assertPlacement=*/false,
/*fullscreen=*/true);
popups.push(popup);
await poll(() => {
return popup.document.fullscreenElement ==
popup.document.documentElement
});
const context = `popup: ${windowLog(popup)}, ${screenLog(screen)}`;
assert_equals(popup.screenLeft, s.availLeft, context)
assert_equals(popup.screenRight, s.availRight, context);
assert_equals(popup.screen.availHeight, s.availHeight, context);
assert_equals(popup.screen.availWidth, s.availWidth, context);
if (autoClose.checked)
closePopups();
}, name);
}
}, 'Use multi-screen details to open a fullscreen popup window on each screen');
</script>

@ -65,13 +65,10 @@ async function poll(condition, interval = 100, duration = 3000) {
}
// Open and return a popup on `screen`, optionally asserting placement.
async function openPopupOnScreen(screen, assertPlacement = true, fullscreen = false) {
async function openPopupOnScreen(screen, assertPlacement = true) {
const left = screen.availLeft + Math.floor(screen.availWidth / 2) - 150;
const top = screen.availTop + Math.floor(screen.availHeight / 2) - 50;
let features = `left=${left},top=${top},width=300,height=100`;
if (fullscreen) {
features += ",fullscreen";
}
log(`Opening a popup with features '${features}' on ${screenLog(screen)}`);
// Window.open() synchronously returns a Window with estimated screenLeft|Top,
// which may be clamped to the opener's screen or incompletely initialized.

@ -10488,8 +10488,8 @@ Called by update_use_counter_feature_enum.py.-->
<int value="4522" label="HtmlClipboardApiUnsanitizedRead"/>
<int value="4523" label="HtmlClipboardApiUnsanitizedWrite"/>
<int value="4524" label="AsyncClipboardAPIUnsanitizedRead"/>
<int value="4525" label="WindowOpenFullscreenRequested"/>
<int value="4526" label="FullscreenAllowedByWindowOpen"/>
<int value="4525" label="OBSOLETE_WindowOpenFullscreenRequested"/>
<int value="4526" label="OBSOLETE_FullscreenAllowedByWindowOpen"/>
<int value="4527" label="AttributeValueContainsLtOrGt"/>
<int value="4528" label="OBSOLETE_V8ImportAssertionDeprecatedSyntax"/>
<int value="4529" label="ImageCaptureBackgroundBlur"/>

@ -452,8 +452,10 @@ Called by update_bad_message_reasons.py.-->
label="BIBI_BIND_PRESSURE_MANAGER_BLOCKED_BY_PERMISSIONS_POLICY"/>
<int value="298" label="RFSCI_BROWSER_VALIDATION_BAD_ORIGIN_TRIAL_TOKEN"/>
<int value="299" label="RFH_RECEIVED_INVALID_BROWSING_TOPICS_ATTRIBUTE"/>
<int value="300" label="RFHI_FULLSCREEN_NAV_INVALID_INITIAL_DOCUMENT"/>
<int value="301" label="RFHI_FULLSCREEN_NAV_NOT_OUTERMOST_MAIN_FRAME"/>
<int value="300"
label="OBSOLETE_RFHI_FULLSCREEN_NAV_INVALID_INITIAL_DOCUMENT"/>
<int value="301"
label="OBSOLETE_RFHI_FULLSCREEN_NAV_NOT_OUTERMOST_MAIN_FRAME"/>
<int value="302" label="MH_MIDI_PERMISSION"/>
<int value="303" label="RFH_CAN_ACCESS_FILES_OF_PAGE_STATE_AT_COMMIT"/>
<int value="304" label="PSI_REQUEST_EMBEDDED_PERMISSION_WITHOUT_FEATURE"/>