From cdad240f282dca85fb85fa3ecc809d7f34862996 Mon Sep 17 00:00:00 2001 From: Mason Freed Date: Fri, 19 Nov 2021 23:14:09 +0000 Subject: [PATCH] Change behavior of window.open w.r.t. windowPreferences and popups See [1] and [2] for more context, but this CL implements new behavior for how window.open() interprets the windowPreferences argument when deciding whether to open the window as a new tab or as a "popup", which is a separate window with minimal UI (toolbars, onmibox, etc.), and also what to return from the BarProp visible properties, e.g. window.toolbar.visible. The existing "trigger" behavior for popups will be retained by this CL, namely that a popup will be opened instead of a tab if: 1. the windowFeatures parameter is *not* empty, and 2. one of the following conditions is true: * both `location` and `toolbar` are false or missing * `menubar` is false or missing * `resizable is false or missing * `scrollbar` is false or missing * `status` is false or missing With this CL, an additional windowFeature called 'popup' is added, so that if 'popup' is present and truthy. Additionally, all BarProp properties (locationbar,menubar, personalbar,scrollbars,statusbar, and toolbar) will always return the same values, either false if a popup was opened, or true if a tab/window was opened. The spec for this behavior is part of the HTML spec: https://html.spec.whatwg.org/multipage/window-object.html#popup-window-is-requested The intent to ship is here: https://groups.google.com/a/chromium.org/g/blink-dev/c/q6ybnmxxvpE [1] https://github.com/whatwg/html/issues/5872 [2] https://github.com/whatwg/html/pull/6530 Fixed: 1192701 Change-Id: I50e745b1000d460c49085edd57d13f420b875ff3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2950386 Reviewed-by: Joey Arhar Commit-Queue: Mason Freed Cr-Commit-Position: refs/heads/main@{#943716} --- content/child/runtime_features.cc | 2 + third_party/blink/common/features.cc | 4 + third_party/blink/public/common/features.h | 1 + .../core/loader/navigation_policy_test.cc | 27 ++-- .../blink/renderer/core/page/create_window.cc | 36 +++--- .../platform/runtime_enabled_features.json5 | 5 + ...s-popup-condition_combination-expected.txt | 15 --- ...s-is-popup-condition_single-1-expected.txt | 19 --- ...s-is-popup-condition_single-2-expected.txt | 21 ---- .../support/window-open-popup-target.html | 24 ++++ .../window-open-popup-behavior.html | 51 ++++++++ .../fast/dom/Window/new-window-opener.html | 119 ------------------ .../events/window-open-after-keypress.html | 2 +- 13 files changed, 126 insertions(+), 200 deletions(-) delete mode 100644 third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-is-popup-condition_combination-expected.txt delete mode 100644 third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-is-popup-condition_single-1-expected.txt delete mode 100644 third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-is-popup-condition_single-2-expected.txt create mode 100644 third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/support/window-open-popup-target.html create mode 100644 third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/window-open-popup-behavior.html delete mode 100644 third_party/blink/web_tests/fast/dom/Window/new-window-opener.html diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 52be46b76e946..be54f2237cb46 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc @@ -398,6 +398,8 @@ void SetRuntimeFeaturesFromChromiumFeatures() { {"WebAppWindowControlsOverlay", features::kWebAppWindowControlsOverlay}, {"WebAuthenticationConditionalUI", features::kWebAuthConditionalUI}, + {"WindowOpenNewPopupBehavior", + blink::features::kWindowOpenNewPopupBehavior}, {"SyncLoadDataUrlFonts", blink::features::kSyncLoadDataUrlFonts}, {"CSSCascadeLayers", blink::features::kCSSCascadeLayers}, // TODO(crbug.com/1185950): Remove this flag when the feature is fully diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 5caff80ade22d..4e8c617ba2fa6 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc @@ -265,6 +265,10 @@ const base::Feature kPurgeRendererMemoryWhenBackgrounded { #endif }; +// Enables new behavior for window.open() and BarProp properties. +const base::Feature kWindowOpenNewPopupBehavior{ + "WindowOpenNewPopupBehavior", base::FEATURE_ENABLED_BY_DEFAULT}; + // Changes the default RTCPeerConnection constructor behavior to use Unified // Plan as the SDP semantics. When the feature is enabled, Unified Plan is used // unless the default is overridden (by passing {sdpSemantics:'plan-b'} as the diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 29e78446cb036..eb14ae92d4725 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h @@ -97,6 +97,7 @@ BLINK_COMMON_EXPORT extern const base::Feature kPreviewsResourceLoadingHintsSpecificResourceTypes; BLINK_COMMON_EXPORT extern const base::Feature kPurgeRendererMemoryWhenBackgrounded; +BLINK_COMMON_EXPORT extern const base::Feature kWindowOpenNewPopupBehavior; BLINK_COMMON_EXPORT extern const base::Feature kRTCUnifiedPlanByDefault; BLINK_COMMON_EXPORT extern const base::Feature kRTCDisallowPlanBOutsideDeprecationTrial; diff --git a/third_party/blink/renderer/core/loader/navigation_policy_test.cc b/third_party/blink/renderer/core/loader/navigation_policy_test.cc index 30a86e00f6875..ae2235ac57d3d 100644 --- a/third_party/blink/renderer/core/loader/navigation_policy_test.cc +++ b/third_party/blink/renderer/core/loader/navigation_policy_test.cc @@ -224,6 +224,14 @@ TEST_F(NavigationPolicyTest, NoOpener) { NavigationPolicy policy; } kCases[] = { {"", kNavigationPolicyNewForegroundTab}, + {"location,menubar,resizable,scrollbars,status", + kNavigationPolicyNewForegroundTab}, + {"popup,location,menubar,resizable,scrollbars,status", + kNavigationPolicyNewPopup}, + {"PoPuP,location,menubar,resizable,scrollbars,status", + kNavigationPolicyNewPopup}, + {"popupFoo,location,menubar,resizable,scrollbars,status", + kNavigationPolicyNewForegroundTab}, {"something", kNavigationPolicyNewPopup}, {"something, something", kNavigationPolicyNewPopup}, {"notnoopener", kNavigationPolicyNewPopup}, @@ -249,10 +257,13 @@ TEST_F(NavigationPolicyTest, NoOpenerAndNoReferrer) { {"", kNavigationPolicyNewForegroundTab}, {"noopener, noreferrer", kNavigationPolicyNewForegroundTab}, {"noopener, notreferrer", kNavigationPolicyNewPopup}, + {"noopener, notreferrer, popup", kNavigationPolicyNewPopup}, {"notopener, noreferrer", kNavigationPolicyNewPopup}, - {"something, noopener, noreferrer", kNavigationPolicyNewPopup}, - {"noopener, noreferrer, something", kNavigationPolicyNewPopup}, - {"noopener, something, noreferrer", kNavigationPolicyNewPopup}, + {"notopener, noreferrer, popup", kNavigationPolicyNewPopup}, + {"notopener, noreferrer, popup=0", kNavigationPolicyNewForegroundTab}, + {"popup, noopener, noreferrer", kNavigationPolicyNewPopup}, + {"noopener, noreferrer, popup", kNavigationPolicyNewPopup}, + {"noopener, popup, noreferrer", kNavigationPolicyNewPopup}, {"NoOpEnEr, NoReFeRrEr", kNavigationPolicyNewForegroundTab}, }; @@ -270,12 +281,14 @@ TEST_F(NavigationPolicyTest, NoReferrer) { NavigationPolicy policy; } kCases[] = { {"", kNavigationPolicyNewForegroundTab}, - {"something", kNavigationPolicyNewPopup}, - {"something, something", kNavigationPolicyNewPopup}, + {"popup", kNavigationPolicyNewPopup}, + {"popup, something", kNavigationPolicyNewPopup}, {"notreferrer", kNavigationPolicyNewPopup}, + {"notreferrer,popup", kNavigationPolicyNewPopup}, + {"notreferrer,popup=0", kNavigationPolicyNewForegroundTab}, {"noreferrer", kNavigationPolicyNewForegroundTab}, - {"something, noreferrer", kNavigationPolicyNewPopup}, - {"noreferrer, something", kNavigationPolicyNewPopup}, + {"popup, noreferrer", kNavigationPolicyNewPopup}, + {"noreferrer, popup", kNavigationPolicyNewPopup}, {"NoReFeRrEr", kNavigationPolicyNewForegroundTab}, }; diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc index 73d68eb8d3291..5386102c3e05a 100644 --- a/third_party/blink/renderer/core/page/create_window.cc +++ b/third_party/blink/renderer/core/page/create_window.cc @@ -81,12 +81,8 @@ WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string, return window_features; bool ui_features_were_disabled = false; - - // See crbug.com/1192701 for details, but we're working on changing the - // popup-triggering conditions for window.open. This bool represents the "new" - // state after this change. - bool is_popup_with_new_behavior = false; - + enum class PopupState { kUnknown, kPopup, kWindow }; + PopupState popup_state = PopupState::kUnknown; unsigned key_begin, key_end; unsigned value_begin, value_end; @@ -186,8 +182,9 @@ WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string, } else if (key_string == "width" || key_string == "innerwidth") { window_features.width_set = true; window_features.width = value; - // Width will be the only trigger for a popup. - is_popup_with_new_behavior = true; + } else if (key_string == "popup") { + // The 'popup' property explicitly triggers a popup. + popup_state = value ? PopupState::kPopup : PopupState::kWindow; } else if (key_string == "height" || key_string == "innerheight") { window_features.height_set = true; window_features.height = value; @@ -224,17 +221,20 @@ WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string, } } - // Existing logic from NavigationPolicy::NavigationPolicyForCreateWindow(): - if (dom_window && dom_window->document()) { - bool is_popup_with_current_behavior = !window_features.tool_bar_visible || - !window_features.status_bar_visible || - !window_features.scrollbars_visible || - !window_features.menu_bar_visible || - !window_features.resizable; - if (is_popup_with_current_behavior != is_popup_with_new_behavior) { - UseCounter::Count(dom_window->document(), - WebFeature::kWindowOpenNewPopupBehaviorMismatch); + if (RuntimeEnabledFeatures::WindowOpenNewPopupBehaviorEnabled()) { + bool is_popup = popup_state == PopupState::kPopup; + if (popup_state == PopupState::kUnknown) { + is_popup = !window_features.tool_bar_visible || + !window_features.menu_bar_visible || + !window_features.resizable || + !window_features.scrollbars_visible || + !window_features.status_bar_visible; } + // If this is a popup, set all BarProps to false, and vice versa. + window_features.tool_bar_visible = !is_popup; + window_features.menu_bar_visible = !is_popup; + window_features.scrollbars_visible = !is_popup; + window_features.status_bar_visible = !is_popup; } if (window_features.noreferrer) diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index c06e1888d549d..f675a4af12895 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5 @@ -2689,6 +2689,11 @@ depends_on: ["WebXRARModule"], status: "stable", }, + // New behavior for window.open's interpretation of the windowFeatures parameter. + { + name: "WindowOpenNewPopupBehavior", + status: "stable", + }, // Extends window placement functionality for multi-screen devices. Also // exposes requisite information about displays connected to the device. { diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-is-popup-condition_combination-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-is-popup-condition_combination-expected.txt deleted file mode 100644 index cc108eb3d4b93..0000000000000 --- a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-is-popup-condition_combination-expected.txt +++ /dev/null @@ -1,15 +0,0 @@ -This is a testharness.js-based test. -PASS "location,toolbar,menubar,resizable,scrollbars,status" should set BarProp visibility to true -PASS "location,menubar,resizable,scrollbars,status" should set BarProp visibility to true -PASS "toolbar,menubar,resizable,scrollbars,status" should set BarProp visibility to true -FAIL "resizable,scrollbars,status" should set BarProp visibility to false assert_equals: window.scrollbars.visible expected false but got true -FAIL "location=no,menubar=no,resizable,scrollbars,status" should set BarProp visibility to false assert_equals: window.scrollbars.visible expected false but got true -FAIL "location,toolbar,resizable,scrollbars,status" should set BarProp visibility to false assert_equals: window.locationbar.visible expected false but got true -PASS "location,toolbar,menubar,scrollbars,status" should set BarProp visibility to true -FAIL "location,toolbar,menubar,resizable=no,scrollbars,status" should set BarProp visibility to false assert_equals: window.locationbar.visible expected false but got true -FAIL "location,toolbar,menubar,resizable,status" should set BarProp visibility to false assert_equals: window.locationbar.visible expected false but got true -FAIL "location,toolbar,menubar,resizable,scrollbars" should set BarProp visibility to false assert_equals: window.locationbar.visible expected false but got true -FAIL "popup=1,location,toolbar,menubar,resizable,scrollbars,status" should set BarProp visibility to false assert_equals: window.locationbar.visible expected false but got true -FAIL "popup=0,location,toolbar,menubar,resizable,scrollbars" should set BarProp visibility to true assert_equals: window.statusbar.visible expected true but got false -Harness: the test ran to completion. - diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-is-popup-condition_single-1-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-is-popup-condition_single-1-expected.txt deleted file mode 100644 index 06fc00ce52b6f..0000000000000 --- a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-is-popup-condition_single-1-expected.txt +++ /dev/null @@ -1,19 +0,0 @@ -This is a testharness.js-based test. -PASS undefined should set BarProp visibility to true -PASS "popup" should set BarProp visibility to false -PASS "popup=1" should set BarProp visibility to false -FAIL "popup=0" should set BarProp visibility to true assert_equals: window.locationbar.visible expected true but got false -FAIL "location" should set BarProp visibility to false assert_equals: window.locationbar.visible expected false but got true -FAIL "location=yes" should set BarProp visibility to false assert_equals: window.locationbar.visible expected false but got true -PASS "location=no" should set BarProp visibility to false -FAIL "toolbar" should set BarProp visibility to false assert_equals: window.locationbar.visible expected false but got true -FAIL "toolbar=yes" should set BarProp visibility to false assert_equals: window.locationbar.visible expected false but got true -PASS "toolbar=no" should set BarProp visibility to false -FAIL "menubar" should set BarProp visibility to false assert_equals: window.menubar.visible expected false but got true -FAIL "menubar=yes" should set BarProp visibility to false assert_equals: window.menubar.visible expected false but got true -PASS "menubar=no" should set BarProp visibility to false -PASS "resizable" should set BarProp visibility to false -PASS "resizable=yes" should set BarProp visibility to false -PASS "resizable=no" should set BarProp visibility to false -Harness: the test ran to completion. - diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-is-popup-condition_single-2-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-is-popup-condition_single-2-expected.txt deleted file mode 100644 index 8ead92f03ff26..0000000000000 --- a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-is-popup-condition_single-2-expected.txt +++ /dev/null @@ -1,21 +0,0 @@ -This is a testharness.js-based test. -FAIL "scrollbars" should set BarProp visibility to false assert_equals: window.scrollbars.visible expected false but got true -FAIL "scrollbars=yes" should set BarProp visibility to false assert_equals: window.scrollbars.visible expected false but got true -PASS "scrollbars=no" should set BarProp visibility to false -FAIL "status" should set BarProp visibility to false assert_equals: window.statusbar.visible expected false but got true -FAIL "status=yes" should set BarProp visibility to false assert_equals: window.statusbar.visible expected false but got true -PASS "status=no" should set BarProp visibility to false -PASS "titlebar" should set BarProp visibility to false -PASS "titlebar=yes" should set BarProp visibility to false -PASS "titlebar=no" should set BarProp visibility to false -PASS "close" should set BarProp visibility to false -PASS "close=yes" should set BarProp visibility to false -PASS "close=no" should set BarProp visibility to false -PASS "minimizable" should set BarProp visibility to false -PASS "minimizable=yes" should set BarProp visibility to false -PASS "minimizable=no" should set BarProp visibility to false -PASS "personalbar" should set BarProp visibility to false -PASS "personalbar=yes" should set BarProp visibility to false -PASS "personalbar=no" should set BarProp visibility to false -Harness: the test ran to completion. - diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/support/window-open-popup-target.html b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/support/window-open-popup-target.html new file mode 100644 index 0000000000000..a0588de82970a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/support/window-open-popup-target.html @@ -0,0 +1,24 @@ + + \ No newline at end of file diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/window-open-popup-behavior.html b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/window-open-popup-behavior.html new file mode 100644 index 0000000000000..258698d94d9ad --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/window-open-popup-behavior.html @@ -0,0 +1,51 @@ + + + +Window.open popup behavior + + + + + + diff --git a/third_party/blink/web_tests/fast/dom/Window/new-window-opener.html b/third_party/blink/web_tests/fast/dom/Window/new-window-opener.html deleted file mode 100644 index 645fbd5d329c5..0000000000000 --- a/third_party/blink/web_tests/fast/dom/Window/new-window-opener.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - New Window Opener Test - - - - - - - - - diff --git a/third_party/blink/web_tests/fast/events/window-open-after-keypress.html b/third_party/blink/web_tests/fast/events/window-open-after-keypress.html index fca283e004c7d..ca01181d8043b 100644 --- a/third_party/blink/web_tests/fast/events/window-open-after-keypress.html +++ b/third_party/blink/web_tests/fast/events/window-open-after-keypress.html @@ -16,7 +16,7 @@ function key() { - window.open("about:blank", "", "status=0"); + window.open("about:blank", "", "popup"); }