Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(746)

Unified Diff: third_party/WebKit/Source/core/page/CreateWindow.cpp

Issue 2905283003: Remove a bunch of dead code around WindowFeatures (Closed)
Patch Set: Use WebWindowFeatures everywhere Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/page/CreateWindow.cpp
diff --git a/third_party/WebKit/Source/core/page/CreateWindow.cpp b/third_party/WebKit/Source/core/page/CreateWindow.cpp
index d3a42e6f25a79cf4891a8abbea211720a194fb72..88aa2ad87b0c61d0b1801499405c0d5ef3883ee8 100644
--- a/third_party/WebKit/Source/core/page/CreateWindow.cpp
+++ b/third_party/WebKit/Source/core/page/CreateWindow.cpp
@@ -29,6 +29,7 @@
#include "bindings/core/v8/ExceptionState.h"
#include "core/dom/Document.h"
#include "core/dom/UserGestureIndicator.h"
+#include "core/events/UIEventWithKeyState.h"
#include "core/frame/FrameClient.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
@@ -37,16 +38,225 @@
#include "core/page/ChromeClient.h"
#include "core/page/FocusController.h"
#include "core/page/Page.h"
-#include "core/page/WindowFeatures.h"
#include "core/probe/CoreProbes.h"
+#include "platform/KeyboardCodes.h"
#include "platform/loader/fetch/ResourceRequest.h"
#include "platform/weborigin/KURL.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/weborigin/SecurityPolicy.h"
+#include "public/platform/WebInputEvent.h"
+#include "public/platform/WebKeyboardEvent.h"
+#include "public/platform/WebMouseEvent.h"
#include "public/platform/WebURLRequest.h"
+#include "public/web/WebWindowFeatures.h"
namespace blink {
+namespace {
+
+void UpdatePolicyForEvent(const WebInputEvent* input_event,
+ NavigationPolicy* policy) {
+ if (!input_event)
+ return;
+
+ unsigned short button_number = 0;
+ if (input_event->GetType() == WebInputEvent::kMouseUp) {
+ const WebMouseEvent* mouse_event =
+ static_cast<const WebMouseEvent*>(input_event);
+
+ switch (mouse_event->button) {
+ case WebMouseEvent::Button::kLeft:
+ button_number = 0;
+ break;
+ case WebMouseEvent::Button::kMiddle:
+ button_number = 1;
+ break;
+ case WebMouseEvent::Button::kRight:
+ button_number = 2;
+ break;
+ default:
+ return;
+ }
+ } else if ((WebInputEvent::IsKeyboardEventType(input_event->GetType()) &&
+ static_cast<const WebKeyboardEvent*>(input_event)
+ ->windows_key_code == VKEY_RETURN) ||
+ WebInputEvent::IsGestureEventType(input_event->GetType())) {
+ // Keyboard and gesture events can simulate mouse events.
+ button_number = 0;
+ } else {
+ return;
+ }
+
+ bool ctrl = input_event->GetModifiers() & WebInputEvent::kControlKey;
+ bool shift = input_event->GetModifiers() & WebInputEvent::kShiftKey;
+ bool alt = input_event->GetModifiers() & WebInputEvent::kAltKey;
+ bool meta = input_event->GetModifiers() & WebInputEvent::kMetaKey;
+
+ NavigationPolicy user_policy = *policy;
+ NavigationPolicyFromMouseEvent(button_number, ctrl, shift, alt, meta,
+ &user_policy);
+
+ // When the input event suggests a download, but the navigation was initiated
+ // by script, we should not override it.
+ if (user_policy == kNavigationPolicyDownload &&
+ *policy != kNavigationPolicyIgnore)
+ return;
+
+ // User and app agree that we want a new window; let the app override the
+ // decorations.
+ if (user_policy == kNavigationPolicyNewWindow &&
+ *policy == kNavigationPolicyNewPopup)
+ return;
+ *policy = user_policy;
+}
+
+NavigationPolicy GetNavigationPolicy(const WebInputEvent* current_event,
+ bool toolbar_visible) {
+ // If the window features didn't enable the toolbar, or this window wasn't
+ // created by a user gesture, show as a popup instead of a new tab.
+ //
+ // Note: this previously also checked that menubar, resizable, scrollbar, and
+ // statusbar are enabled too. When no feature string is specified, these
+ // features default to enabled (and the window opens as a new tab). However,
+ // when a feature string is specified, any *unspecified* features default to
+ // disabled, often causing the window to open as a popup instead.
+ //
+ // As specifying menubar, resizable, scrollbar, and statusbar have no effect
+ // on the UI, just ignore them and only consider whether or not the toolbar is
+ // enabled, which matches Firefox's behavior.
+ NavigationPolicy policy = toolbar_visible ? kNavigationPolicyNewForegroundTab
+ : kNavigationPolicyNewPopup;
+ UpdatePolicyForEvent(current_event, &policy);
+ return policy;
+}
+
+} // anonymous namespace
+
+NavigationPolicy EffectiveNavigationPolicy(NavigationPolicy policy,
+ const WebInputEvent* current_event,
+ bool toolbar_visible) {
+ if (policy == kNavigationPolicyIgnore)
+ return GetNavigationPolicy(current_event, toolbar_visible);
+ if (policy == kNavigationPolicyNewBackgroundTab &&
+ GetNavigationPolicy(current_event, toolbar_visible) !=
+ kNavigationPolicyNewBackgroundTab &&
+ !UIEventWithKeyState::NewTabModifierSetFromIsolatedWorld()) {
+ return kNavigationPolicyNewForegroundTab;
+ }
+ return policy;
+}
+
+// Though isspace() considers \t and \v to be whitespace, Win IE doesn't when
+// parsing window features.
+static bool IsWindowFeaturesSeparator(UChar c) {
+ return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' ||
+ c == ',' || c == '\0';
+}
+
+WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string) {
+ WebWindowFeatures window_features;
+
+ // The IE rule is: all features except for channelmode default
+ // to YES, but if the user specifies a feature string, all features default to
+ // NO. (There is no public standard that applies to this method.)
+ // <http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/open_0.asp>
+ if (feature_string.IsEmpty())
+ return window_features;
+
+ window_features.menu_bar_visible = false;
+ window_features.status_bar_visible = false;
+ window_features.tool_bar_visible = false;
+ window_features.scrollbars_visible = false;
+
+ // Tread lightly in this code -- it was specifically designed to mimic Win
+ // IE's parsing behavior.
+ unsigned key_begin, key_end;
+ unsigned value_begin, value_end;
+
+ String buffer = feature_string.DeprecatedLower();
+ unsigned length = buffer.length();
+ for (unsigned i = 0; i < length;) {
+ // skip to first non-separator, but don't skip past the end of the string
+ while (i < length && IsWindowFeaturesSeparator(buffer[i]))
+ i++;
+ key_begin = i;
+
+ // skip to first separator
+ while (i < length && !IsWindowFeaturesSeparator(buffer[i]))
+ i++;
+ key_end = i;
+
+ SECURITY_DCHECK(i <= length);
+
+ // skip to first '=', but don't skip past a ',' or the end of the string
+ while (i < length && buffer[i] != '=') {
+ if (buffer[i] == ',')
+ break;
+ i++;
+ }
+
+ SECURITY_DCHECK(i <= length);
+
+ // Skip to first non-separator, but don't skip past a ',' or the end of the
+ // string.
+ while (i < length && IsWindowFeaturesSeparator(buffer[i])) {
+ if (buffer[i] == ',')
+ break;
+ i++;
+ }
+ value_begin = i;
+
+ SECURITY_DCHECK(i <= length);
+
+ // skip to first separator
+ while (i < length && !IsWindowFeaturesSeparator(buffer[i]))
+ i++;
+ value_end = i;
+
+ SECURITY_DCHECK(i <= length);
+
+ String key_string(buffer.Substring(key_begin, key_end - key_begin));
+ String value_string(buffer.Substring(value_begin, value_end - value_begin));
+
+ // Listing a key with no value is shorthand for key=yes
+ int value;
+ if (value_string.IsEmpty() || value_string == "yes")
+ value = 1;
+ else
+ value = value_string.ToInt();
+
+ if (key_string == "left" || key_string == "screenx") {
+ window_features.x_set = true;
+ window_features.x = value;
+ } else if (key_string == "top" || key_string == "screeny") {
+ window_features.y_set = true;
+ window_features.y = value;
+ } else if (key_string == "width" || key_string == "innerwidth") {
+ window_features.width_set = true;
+ window_features.width = value;
+ } else if (key_string == "height" || key_string == "innerheight") {
+ window_features.height_set = true;
+ window_features.height = value;
+ } else if (key_string == "menubar") {
+ window_features.menu_bar_visible = value;
+ } else if (key_string == "toolbar" || key_string == "location") {
+ window_features.tool_bar_visible |= static_cast<bool>(value);
+ } else if (key_string == "status") {
+ window_features.status_bar_visible = value;
+ } else if (key_string == "scrollbars") {
+ window_features.scrollbars_visible = value;
+ } else if (key_string == "noopener") {
+ window_features.noopener = true;
+ } else if (key_string == "background") {
+ window_features.background = true;
+ } else if (key_string == "persistent") {
+ window_features.persistent = true;
+ }
+ }
+
+ return window_features;
+}
+
static Frame* ReuseExistingWindow(LocalFrame& active_frame,
LocalFrame& lookup_frame,
const AtomicString& frame_name,
@@ -71,13 +281,17 @@ static Frame* ReuseExistingWindow(LocalFrame& active_frame,
static Frame* CreateNewWindow(LocalFrame& opener_frame,
const FrameLoadRequest& request,
- const WindowFeatures& features,
+ const WebWindowFeatures& features,
NavigationPolicy policy,
bool& created) {
Page* old_page = opener_frame.GetPage();
if (!old_page)
return nullptr;
+ policy = EffectiveNavigationPolicy(
+ policy, old_page->GetChromeClient().GetCurrentInputEvent(),
+ features.tool_bar_visible);
+
Page* page = old_page->GetChromeClient().CreateWindow(&opener_frame, request,
features, policy);
if (!page)
@@ -92,7 +306,9 @@ static Frame* CreateNewWindow(LocalFrame& opener_frame,
if (!EqualIgnoringASCIICase(request.FrameName(), "_blank"))
frame.Tree().SetName(request.FrameName());
- page->GetChromeClient().SetWindowFeatures(features);
+ page->SetWindowFeatures(features);
+
+ frame.View()->SetCanHaveScrollbars(features.scrollbars_visible);
// 'x' and 'y' specify the location of the window, while 'width' and 'height'
// specify the size of the viewport. We can only resize the window, so adjust
@@ -130,10 +346,9 @@ static Frame* CreateWindowHelper(LocalFrame& opener_frame,
LocalFrame& active_frame,
LocalFrame& lookup_frame,
const FrameLoadRequest& request,
- const WindowFeatures& features,
+ const WebWindowFeatures& features,
NavigationPolicy policy,
bool& created) {
- DCHECK(!features.dialog || request.FrameName().IsEmpty());
DCHECK(request.GetResourceRequest().RequestorOrigin() ||
opener_frame.GetDocument()->Url().IsEmpty());
DCHECK_EQ(request.GetResourceRequest().GetFrameType(),
@@ -176,7 +391,7 @@ static Frame* CreateWindowHelper(LocalFrame& opener_frame,
DOMWindow* CreateWindow(const String& url_string,
const AtomicString& frame_name,
- const WindowFeatures& window_features,
+ const String& window_features_string,
LocalDOMWindow& calling_window,
LocalFrame& first_frame,
LocalFrame& opener_frame,
@@ -195,6 +410,9 @@ DOMWindow* CreateWindow(const String& url_string,
return nullptr;
}
+ WebWindowFeatures window_features =
+ GetWindowFeaturesFromString(window_features_string);
+
FrameLoadRequest frame_request(calling_window.document(),
ResourceRequest(completed_url), frame_name);
frame_request.SetShouldSetOpener(window_features.noopener ? kNeverSetOpener
@@ -231,7 +449,7 @@ DOMWindow* CreateWindow(const String& url_string,
return nullptr;
if (new_frame->DomWindow()->IsInsecureScriptAccess(calling_window,
completed_url))
- return new_frame->DomWindow();
+ return window_features.noopener ? nullptr : new_frame->DomWindow();
// TODO(dcheng): Special case for window.open("about:blank") to ensure it
// loads synchronously into a new window. This is our historical behavior, and
@@ -252,7 +470,7 @@ DOMWindow* CreateWindow(const String& url_string,
has_user_gesture ? UserGestureStatus::kActive
: UserGestureStatus::kNone);
}
- return new_frame->DomWindow();
+ return window_features.noopener ? nullptr : new_frame->DomWindow();
}
void CreateWindowForRequest(const FrameLoadRequest& request,
@@ -273,7 +491,7 @@ void CreateWindowForRequest(const FrameLoadRequest& request,
if (policy == kNavigationPolicyCurrentTab)
policy = kNavigationPolicyNewForegroundTab;
- WindowFeatures features;
+ WebWindowFeatures features;
features.noopener = request.GetShouldSetOpener() == kNeverSetOpener;
bool created;
Frame* new_frame =

Powered by Google App Engine
This is Rietveld 408576698