OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. |
3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 11 matching lines...) Expand all Loading... |
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 */ | 25 */ |
26 | 26 |
27 #include "core/page/CreateWindow.h" | 27 #include "core/page/CreateWindow.h" |
28 | 28 |
29 #include "bindings/core/v8/ExceptionState.h" | 29 #include "bindings/core/v8/ExceptionState.h" |
30 #include "core/dom/Document.h" | 30 #include "core/dom/Document.h" |
31 #include "core/dom/UserGestureIndicator.h" | 31 #include "core/dom/UserGestureIndicator.h" |
| 32 #include "core/events/UIEventWithKeyState.h" |
32 #include "core/frame/FrameClient.h" | 33 #include "core/frame/FrameClient.h" |
33 #include "core/frame/LocalFrame.h" | 34 #include "core/frame/LocalFrame.h" |
34 #include "core/frame/Settings.h" | 35 #include "core/frame/Settings.h" |
35 #include "core/inspector/ConsoleMessage.h" | 36 #include "core/inspector/ConsoleMessage.h" |
36 #include "core/loader/FrameLoadRequest.h" | 37 #include "core/loader/FrameLoadRequest.h" |
37 #include "core/page/ChromeClient.h" | 38 #include "core/page/ChromeClient.h" |
38 #include "core/page/FocusController.h" | 39 #include "core/page/FocusController.h" |
39 #include "core/page/Page.h" | 40 #include "core/page/Page.h" |
40 #include "core/page/WindowFeatures.h" | |
41 #include "core/probe/CoreProbes.h" | 41 #include "core/probe/CoreProbes.h" |
| 42 #include "platform/KeyboardCodes.h" |
42 #include "platform/loader/fetch/ResourceRequest.h" | 43 #include "platform/loader/fetch/ResourceRequest.h" |
43 #include "platform/weborigin/KURL.h" | 44 #include "platform/weborigin/KURL.h" |
44 #include "platform/weborigin/SecurityOrigin.h" | 45 #include "platform/weborigin/SecurityOrigin.h" |
45 #include "platform/weborigin/SecurityPolicy.h" | 46 #include "platform/weborigin/SecurityPolicy.h" |
| 47 #include "public/platform/WebInputEvent.h" |
| 48 #include "public/platform/WebKeyboardEvent.h" |
| 49 #include "public/platform/WebMouseEvent.h" |
46 #include "public/platform/WebURLRequest.h" | 50 #include "public/platform/WebURLRequest.h" |
| 51 #include "public/web/WebWindowFeatures.h" |
47 | 52 |
48 namespace blink { | 53 namespace blink { |
49 | 54 |
| 55 namespace { |
| 56 |
| 57 void UpdatePolicyForEvent(const WebInputEvent* input_event, |
| 58 NavigationPolicy* policy) { |
| 59 if (!input_event) |
| 60 return; |
| 61 |
| 62 unsigned short button_number = 0; |
| 63 if (input_event->GetType() == WebInputEvent::kMouseUp) { |
| 64 const WebMouseEvent* mouse_event = |
| 65 static_cast<const WebMouseEvent*>(input_event); |
| 66 |
| 67 switch (mouse_event->button) { |
| 68 case WebMouseEvent::Button::kLeft: |
| 69 button_number = 0; |
| 70 break; |
| 71 case WebMouseEvent::Button::kMiddle: |
| 72 button_number = 1; |
| 73 break; |
| 74 case WebMouseEvent::Button::kRight: |
| 75 button_number = 2; |
| 76 break; |
| 77 default: |
| 78 return; |
| 79 } |
| 80 } else if ((WebInputEvent::IsKeyboardEventType(input_event->GetType()) && |
| 81 static_cast<const WebKeyboardEvent*>(input_event) |
| 82 ->windows_key_code == VKEY_RETURN) || |
| 83 WebInputEvent::IsGestureEventType(input_event->GetType())) { |
| 84 // Keyboard and gesture events can simulate mouse events. |
| 85 button_number = 0; |
| 86 } else { |
| 87 return; |
| 88 } |
| 89 |
| 90 bool ctrl = input_event->GetModifiers() & WebInputEvent::kControlKey; |
| 91 bool shift = input_event->GetModifiers() & WebInputEvent::kShiftKey; |
| 92 bool alt = input_event->GetModifiers() & WebInputEvent::kAltKey; |
| 93 bool meta = input_event->GetModifiers() & WebInputEvent::kMetaKey; |
| 94 |
| 95 NavigationPolicy user_policy = *policy; |
| 96 NavigationPolicyFromMouseEvent(button_number, ctrl, shift, alt, meta, |
| 97 &user_policy); |
| 98 |
| 99 // When the input event suggests a download, but the navigation was initiated |
| 100 // by script, we should not override it. |
| 101 if (user_policy == kNavigationPolicyDownload && |
| 102 *policy != kNavigationPolicyIgnore) |
| 103 return; |
| 104 |
| 105 // User and app agree that we want a new window; let the app override the |
| 106 // decorations. |
| 107 if (user_policy == kNavigationPolicyNewWindow && |
| 108 *policy == kNavigationPolicyNewPopup) |
| 109 return; |
| 110 *policy = user_policy; |
| 111 } |
| 112 |
| 113 NavigationPolicy GetNavigationPolicy(const WebInputEvent* current_event, |
| 114 bool toolbar_visible) { |
| 115 // If the window features didn't enable the toolbar, or this window wasn't |
| 116 // created by a user gesture, show as a popup instead of a new tab. |
| 117 // |
| 118 // Note: this previously also checked that menubar, resizable, scrollbar, and |
| 119 // statusbar are enabled too. When no feature string is specified, these |
| 120 // features default to enabled (and the window opens as a new tab). However, |
| 121 // when a feature string is specified, any *unspecified* features default to |
| 122 // disabled, often causing the window to open as a popup instead. |
| 123 // |
| 124 // As specifying menubar, resizable, scrollbar, and statusbar have no effect |
| 125 // on the UI, just ignore them and only consider whether or not the toolbar is |
| 126 // enabled, which matches Firefox's behavior. |
| 127 NavigationPolicy policy = toolbar_visible ? kNavigationPolicyNewForegroundTab |
| 128 : kNavigationPolicyNewPopup; |
| 129 UpdatePolicyForEvent(current_event, &policy); |
| 130 return policy; |
| 131 } |
| 132 |
| 133 } // anonymous namespace |
| 134 |
| 135 NavigationPolicy EffectiveNavigationPolicy(NavigationPolicy policy, |
| 136 const WebInputEvent* current_event, |
| 137 bool toolbar_visible) { |
| 138 if (policy == kNavigationPolicyIgnore) |
| 139 return GetNavigationPolicy(current_event, toolbar_visible); |
| 140 if (policy == kNavigationPolicyNewBackgroundTab && |
| 141 GetNavigationPolicy(current_event, toolbar_visible) != |
| 142 kNavigationPolicyNewBackgroundTab && |
| 143 !UIEventWithKeyState::NewTabModifierSetFromIsolatedWorld()) { |
| 144 return kNavigationPolicyNewForegroundTab; |
| 145 } |
| 146 return policy; |
| 147 } |
| 148 |
| 149 // Though isspace() considers \t and \v to be whitespace, Win IE doesn't when |
| 150 // parsing window features. |
| 151 static bool IsWindowFeaturesSeparator(UChar c) { |
| 152 return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || |
| 153 c == ',' || c == '\0'; |
| 154 } |
| 155 |
| 156 WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string) { |
| 157 WebWindowFeatures window_features; |
| 158 |
| 159 // The IE rule is: all features except for channelmode default |
| 160 // to YES, but if the user specifies a feature string, all features default to |
| 161 // NO. (There is no public standard that applies to this method.) |
| 162 // <http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/open_0.a
sp> |
| 163 if (feature_string.IsEmpty()) |
| 164 return window_features; |
| 165 |
| 166 window_features.menu_bar_visible = false; |
| 167 window_features.status_bar_visible = false; |
| 168 window_features.tool_bar_visible = false; |
| 169 window_features.scrollbars_visible = false; |
| 170 |
| 171 // Tread lightly in this code -- it was specifically designed to mimic Win |
| 172 // IE's parsing behavior. |
| 173 unsigned key_begin, key_end; |
| 174 unsigned value_begin, value_end; |
| 175 |
| 176 String buffer = feature_string.DeprecatedLower(); |
| 177 unsigned length = buffer.length(); |
| 178 for (unsigned i = 0; i < length;) { |
| 179 // skip to first non-separator, but don't skip past the end of the string |
| 180 while (i < length && IsWindowFeaturesSeparator(buffer[i])) |
| 181 i++; |
| 182 key_begin = i; |
| 183 |
| 184 // skip to first separator |
| 185 while (i < length && !IsWindowFeaturesSeparator(buffer[i])) |
| 186 i++; |
| 187 key_end = i; |
| 188 |
| 189 SECURITY_DCHECK(i <= length); |
| 190 |
| 191 // skip to first '=', but don't skip past a ',' or the end of the string |
| 192 while (i < length && buffer[i] != '=') { |
| 193 if (buffer[i] == ',') |
| 194 break; |
| 195 i++; |
| 196 } |
| 197 |
| 198 SECURITY_DCHECK(i <= length); |
| 199 |
| 200 // Skip to first non-separator, but don't skip past a ',' or the end of the |
| 201 // string. |
| 202 while (i < length && IsWindowFeaturesSeparator(buffer[i])) { |
| 203 if (buffer[i] == ',') |
| 204 break; |
| 205 i++; |
| 206 } |
| 207 value_begin = i; |
| 208 |
| 209 SECURITY_DCHECK(i <= length); |
| 210 |
| 211 // skip to first separator |
| 212 while (i < length && !IsWindowFeaturesSeparator(buffer[i])) |
| 213 i++; |
| 214 value_end = i; |
| 215 |
| 216 SECURITY_DCHECK(i <= length); |
| 217 |
| 218 String key_string(buffer.Substring(key_begin, key_end - key_begin)); |
| 219 String value_string(buffer.Substring(value_begin, value_end - value_begin)); |
| 220 |
| 221 // Listing a key with no value is shorthand for key=yes |
| 222 int value; |
| 223 if (value_string.IsEmpty() || value_string == "yes") |
| 224 value = 1; |
| 225 else |
| 226 value = value_string.ToInt(); |
| 227 |
| 228 if (key_string == "left" || key_string == "screenx") { |
| 229 window_features.x_set = true; |
| 230 window_features.x = value; |
| 231 } else if (key_string == "top" || key_string == "screeny") { |
| 232 window_features.y_set = true; |
| 233 window_features.y = value; |
| 234 } else if (key_string == "width" || key_string == "innerwidth") { |
| 235 window_features.width_set = true; |
| 236 window_features.width = value; |
| 237 } else if (key_string == "height" || key_string == "innerheight") { |
| 238 window_features.height_set = true; |
| 239 window_features.height = value; |
| 240 } else if (key_string == "menubar") { |
| 241 window_features.menu_bar_visible = value; |
| 242 } else if (key_string == "toolbar" || key_string == "location") { |
| 243 window_features.tool_bar_visible |= static_cast<bool>(value); |
| 244 } else if (key_string == "status") { |
| 245 window_features.status_bar_visible = value; |
| 246 } else if (key_string == "scrollbars") { |
| 247 window_features.scrollbars_visible = value; |
| 248 } else if (key_string == "noopener") { |
| 249 window_features.noopener = true; |
| 250 } else if (key_string == "background") { |
| 251 window_features.background = true; |
| 252 } else if (key_string == "persistent") { |
| 253 window_features.persistent = true; |
| 254 } |
| 255 } |
| 256 |
| 257 return window_features; |
| 258 } |
| 259 |
50 static Frame* ReuseExistingWindow(LocalFrame& active_frame, | 260 static Frame* ReuseExistingWindow(LocalFrame& active_frame, |
51 LocalFrame& lookup_frame, | 261 LocalFrame& lookup_frame, |
52 const AtomicString& frame_name, | 262 const AtomicString& frame_name, |
53 NavigationPolicy policy) { | 263 NavigationPolicy policy) { |
54 if (!frame_name.IsEmpty() && !EqualIgnoringASCIICase(frame_name, "_blank") && | 264 if (!frame_name.IsEmpty() && !EqualIgnoringASCIICase(frame_name, "_blank") && |
55 policy == kNavigationPolicyIgnore) { | 265 policy == kNavigationPolicyIgnore) { |
56 if (Frame* frame = | 266 if (Frame* frame = |
57 lookup_frame.FindFrameForNavigation(frame_name, active_frame)) { | 267 lookup_frame.FindFrameForNavigation(frame_name, active_frame)) { |
58 if (!EqualIgnoringASCIICase(frame_name, "_self")) { | 268 if (!EqualIgnoringASCIICase(frame_name, "_self")) { |
59 if (Page* page = frame->GetPage()) { | 269 if (Page* page = frame->GetPage()) { |
60 if (page == active_frame.GetPage()) | 270 if (page == active_frame.GetPage()) |
61 page->GetFocusController().SetFocusedFrame(frame); | 271 page->GetFocusController().SetFocusedFrame(frame); |
62 else | 272 else |
63 page->GetChromeClient().Focus(); | 273 page->GetChromeClient().Focus(); |
64 } | 274 } |
65 } | 275 } |
66 return frame; | 276 return frame; |
67 } | 277 } |
68 } | 278 } |
69 return nullptr; | 279 return nullptr; |
70 } | 280 } |
71 | 281 |
72 static Frame* CreateNewWindow(LocalFrame& opener_frame, | 282 static Frame* CreateNewWindow(LocalFrame& opener_frame, |
73 const FrameLoadRequest& request, | 283 const FrameLoadRequest& request, |
74 const WindowFeatures& features, | 284 const WebWindowFeatures& features, |
75 NavigationPolicy policy, | 285 NavigationPolicy policy, |
76 bool& created) { | 286 bool& created) { |
77 Page* old_page = opener_frame.GetPage(); | 287 Page* old_page = opener_frame.GetPage(); |
78 if (!old_page) | 288 if (!old_page) |
79 return nullptr; | 289 return nullptr; |
80 | 290 |
| 291 policy = EffectiveNavigationPolicy( |
| 292 policy, old_page->GetChromeClient().GetCurrentInputEvent(), |
| 293 features.tool_bar_visible); |
| 294 |
81 Page* page = old_page->GetChromeClient().CreateWindow(&opener_frame, request, | 295 Page* page = old_page->GetChromeClient().CreateWindow(&opener_frame, request, |
82 features, policy); | 296 features, policy); |
83 if (!page) | 297 if (!page) |
84 return nullptr; | 298 return nullptr; |
85 | 299 |
86 if (page == old_page) | 300 if (page == old_page) |
87 return &opener_frame.Tree().Top(); | 301 return &opener_frame.Tree().Top(); |
88 | 302 |
89 DCHECK(page->MainFrame()); | 303 DCHECK(page->MainFrame()); |
90 LocalFrame& frame = *ToLocalFrame(page->MainFrame()); | 304 LocalFrame& frame = *ToLocalFrame(page->MainFrame()); |
91 | 305 |
92 if (!EqualIgnoringASCIICase(request.FrameName(), "_blank")) | 306 if (!EqualIgnoringASCIICase(request.FrameName(), "_blank")) |
93 frame.Tree().SetName(request.FrameName()); | 307 frame.Tree().SetName(request.FrameName()); |
94 | 308 |
95 page->GetChromeClient().SetWindowFeatures(features); | 309 page->SetWindowFeatures(features); |
| 310 |
| 311 frame.View()->SetCanHaveScrollbars(features.scrollbars_visible); |
96 | 312 |
97 // 'x' and 'y' specify the location of the window, while 'width' and 'height' | 313 // 'x' and 'y' specify the location of the window, while 'width' and 'height' |
98 // specify the size of the viewport. We can only resize the window, so adjust | 314 // specify the size of the viewport. We can only resize the window, so adjust |
99 // for the difference between the window size and the viewport size. | 315 // for the difference between the window size and the viewport size. |
100 | 316 |
101 IntRect window_rect = page->GetChromeClient().RootWindowRect(); | 317 IntRect window_rect = page->GetChromeClient().RootWindowRect(); |
102 IntSize viewport_size = page->GetChromeClient().PageRect().Size(); | 318 IntSize viewport_size = page->GetChromeClient().PageRect().Size(); |
103 | 319 |
104 if (features.x_set) | 320 if (features.x_set) |
105 window_rect.SetX(features.x); | 321 window_rect.SetX(features.x); |
(...skipping 17 matching lines...) Expand all Loading... |
123 // This call may suspend the execution by running nested run loop. | 339 // This call may suspend the execution by running nested run loop. |
124 probe::windowCreated(&opener_frame, &frame); | 340 probe::windowCreated(&opener_frame, &frame); |
125 created = true; | 341 created = true; |
126 return &frame; | 342 return &frame; |
127 } | 343 } |
128 | 344 |
129 static Frame* CreateWindowHelper(LocalFrame& opener_frame, | 345 static Frame* CreateWindowHelper(LocalFrame& opener_frame, |
130 LocalFrame& active_frame, | 346 LocalFrame& active_frame, |
131 LocalFrame& lookup_frame, | 347 LocalFrame& lookup_frame, |
132 const FrameLoadRequest& request, | 348 const FrameLoadRequest& request, |
133 const WindowFeatures& features, | 349 const WebWindowFeatures& features, |
134 NavigationPolicy policy, | 350 NavigationPolicy policy, |
135 bool& created) { | 351 bool& created) { |
136 DCHECK(!features.dialog || request.FrameName().IsEmpty()); | |
137 DCHECK(request.GetResourceRequest().RequestorOrigin() || | 352 DCHECK(request.GetResourceRequest().RequestorOrigin() || |
138 opener_frame.GetDocument()->Url().IsEmpty()); | 353 opener_frame.GetDocument()->Url().IsEmpty()); |
139 DCHECK_EQ(request.GetResourceRequest().GetFrameType(), | 354 DCHECK_EQ(request.GetResourceRequest().GetFrameType(), |
140 WebURLRequest::kFrameTypeAuxiliary); | 355 WebURLRequest::kFrameTypeAuxiliary); |
141 | 356 |
142 created = false; | 357 created = false; |
143 | 358 |
144 Frame* window = features.noopener | 359 Frame* window = features.noopener |
145 ? nullptr | 360 ? nullptr |
146 : ReuseExistingWindow(active_frame, lookup_frame, | 361 : ReuseExistingWindow(active_frame, lookup_frame, |
(...skipping 22 matching lines...) Expand all Loading... |
169 if (request.GetShouldSetOpener() == kMaybeSetOpener) | 384 if (request.GetShouldSetOpener() == kMaybeSetOpener) |
170 window->Client()->SetOpener(&opener_frame); | 385 window->Client()->SetOpener(&opener_frame); |
171 return window; | 386 return window; |
172 } | 387 } |
173 | 388 |
174 return CreateNewWindow(opener_frame, request, features, policy, created); | 389 return CreateNewWindow(opener_frame, request, features, policy, created); |
175 } | 390 } |
176 | 391 |
177 DOMWindow* CreateWindow(const String& url_string, | 392 DOMWindow* CreateWindow(const String& url_string, |
178 const AtomicString& frame_name, | 393 const AtomicString& frame_name, |
179 const WindowFeatures& window_features, | 394 const String& window_features_string, |
180 LocalDOMWindow& calling_window, | 395 LocalDOMWindow& calling_window, |
181 LocalFrame& first_frame, | 396 LocalFrame& first_frame, |
182 LocalFrame& opener_frame, | 397 LocalFrame& opener_frame, |
183 ExceptionState& exception_state) { | 398 ExceptionState& exception_state) { |
184 LocalFrame* active_frame = calling_window.GetFrame(); | 399 LocalFrame* active_frame = calling_window.GetFrame(); |
185 DCHECK(active_frame); | 400 DCHECK(active_frame); |
186 | 401 |
187 KURL completed_url = url_string.IsEmpty() | 402 KURL completed_url = url_string.IsEmpty() |
188 ? KURL(kParsedURLString, g_empty_string) | 403 ? KURL(kParsedURLString, g_empty_string) |
189 : first_frame.GetDocument()->CompleteURL(url_string); | 404 : first_frame.GetDocument()->CompleteURL(url_string); |
190 if (!completed_url.IsEmpty() && !completed_url.IsValid()) { | 405 if (!completed_url.IsEmpty() && !completed_url.IsValid()) { |
191 UseCounter::Count(active_frame, UseCounter::kWindowOpenWithInvalidURL); | 406 UseCounter::Count(active_frame, UseCounter::kWindowOpenWithInvalidURL); |
192 exception_state.ThrowDOMException( | 407 exception_state.ThrowDOMException( |
193 kSyntaxError, "Unable to open a window with invalid URL '" + | 408 kSyntaxError, "Unable to open a window with invalid URL '" + |
194 completed_url.GetString() + "'.\n"); | 409 completed_url.GetString() + "'.\n"); |
195 return nullptr; | 410 return nullptr; |
196 } | 411 } |
197 | 412 |
| 413 WebWindowFeatures window_features = |
| 414 GetWindowFeaturesFromString(window_features_string); |
| 415 |
198 FrameLoadRequest frame_request(calling_window.document(), | 416 FrameLoadRequest frame_request(calling_window.document(), |
199 ResourceRequest(completed_url), frame_name); | 417 ResourceRequest(completed_url), frame_name); |
200 frame_request.SetShouldSetOpener(window_features.noopener ? kNeverSetOpener | 418 frame_request.SetShouldSetOpener(window_features.noopener ? kNeverSetOpener |
201 : kMaybeSetOpener); | 419 : kMaybeSetOpener); |
202 frame_request.GetResourceRequest().SetFrameType( | 420 frame_request.GetResourceRequest().SetFrameType( |
203 WebURLRequest::kFrameTypeAuxiliary); | 421 WebURLRequest::kFrameTypeAuxiliary); |
204 frame_request.GetResourceRequest().SetRequestorOrigin( | 422 frame_request.GetResourceRequest().SetRequestorOrigin( |
205 SecurityOrigin::Create(active_frame->GetDocument()->Url())); | 423 SecurityOrigin::Create(active_frame->GetDocument()->Url())); |
206 | 424 |
207 // Normally, FrameLoader would take care of setting the referrer for a | 425 // Normally, FrameLoader would take care of setting the referrer for a |
(...skipping 16 matching lines...) Expand all Loading... |
224 // different from the opener frame, and the name references a frame relative | 442 // different from the opener frame, and the name references a frame relative |
225 // to the opener frame. | 443 // to the opener frame. |
226 bool created; | 444 bool created; |
227 Frame* new_frame = CreateWindowHelper( | 445 Frame* new_frame = CreateWindowHelper( |
228 opener_frame, *active_frame, opener_frame, frame_request, window_features, | 446 opener_frame, *active_frame, opener_frame, frame_request, window_features, |
229 kNavigationPolicyIgnore, created); | 447 kNavigationPolicyIgnore, created); |
230 if (!new_frame) | 448 if (!new_frame) |
231 return nullptr; | 449 return nullptr; |
232 if (new_frame->DomWindow()->IsInsecureScriptAccess(calling_window, | 450 if (new_frame->DomWindow()->IsInsecureScriptAccess(calling_window, |
233 completed_url)) | 451 completed_url)) |
234 return new_frame->DomWindow(); | 452 return window_features.noopener ? nullptr : new_frame->DomWindow(); |
235 | 453 |
236 // TODO(dcheng): Special case for window.open("about:blank") to ensure it | 454 // TODO(dcheng): Special case for window.open("about:blank") to ensure it |
237 // loads synchronously into a new window. This is our historical behavior, and | 455 // loads synchronously into a new window. This is our historical behavior, and |
238 // it's consistent with the creation of a new iframe with src="about:blank". | 456 // it's consistent with the creation of a new iframe with src="about:blank". |
239 // Perhaps we could get rid of this if we started reporting the initial empty | 457 // Perhaps we could get rid of this if we started reporting the initial empty |
240 // document's url as about:blank? See crbug.com/471239. | 458 // document's url as about:blank? See crbug.com/471239. |
241 // TODO(japhet): This special case is also necessary for behavior asserted by | 459 // TODO(japhet): This special case is also necessary for behavior asserted by |
242 // some extensions tests. Using NavigationScheduler::scheduleNavigationChange | 460 // some extensions tests. Using NavigationScheduler::scheduleNavigationChange |
243 // causes the navigation to be flagged as a client redirect, which is | 461 // causes the navigation to be flagged as a client redirect, which is |
244 // observable via the webNavigation extension api. | 462 // observable via the webNavigation extension api. |
245 if (created) { | 463 if (created) { |
246 FrameLoadRequest request(calling_window.document(), | 464 FrameLoadRequest request(calling_window.document(), |
247 ResourceRequest(completed_url)); | 465 ResourceRequest(completed_url)); |
248 request.GetResourceRequest().SetHasUserGesture(has_user_gesture); | 466 request.GetResourceRequest().SetHasUserGesture(has_user_gesture); |
249 new_frame->Navigate(request); | 467 new_frame->Navigate(request); |
250 } else if (!url_string.IsEmpty()) { | 468 } else if (!url_string.IsEmpty()) { |
251 new_frame->Navigate(*calling_window.document(), completed_url, false, | 469 new_frame->Navigate(*calling_window.document(), completed_url, false, |
252 has_user_gesture ? UserGestureStatus::kActive | 470 has_user_gesture ? UserGestureStatus::kActive |
253 : UserGestureStatus::kNone); | 471 : UserGestureStatus::kNone); |
254 } | 472 } |
255 return new_frame->DomWindow(); | 473 return window_features.noopener ? nullptr : new_frame->DomWindow(); |
256 } | 474 } |
257 | 475 |
258 void CreateWindowForRequest(const FrameLoadRequest& request, | 476 void CreateWindowForRequest(const FrameLoadRequest& request, |
259 LocalFrame& opener_frame, | 477 LocalFrame& opener_frame, |
260 NavigationPolicy policy) { | 478 NavigationPolicy policy) { |
261 DCHECK(request.GetResourceRequest().RequestorOrigin() || | 479 DCHECK(request.GetResourceRequest().RequestorOrigin() || |
262 (opener_frame.GetDocument() && | 480 (opener_frame.GetDocument() && |
263 opener_frame.GetDocument()->Url().IsEmpty())); | 481 opener_frame.GetDocument()->Url().IsEmpty())); |
264 | 482 |
265 if (opener_frame.GetDocument()->PageDismissalEventBeingDispatched() != | 483 if (opener_frame.GetDocument()->PageDismissalEventBeingDispatched() != |
266 Document::kNoDismissal) | 484 Document::kNoDismissal) |
267 return; | 485 return; |
268 | 486 |
269 if (opener_frame.GetDocument() && | 487 if (opener_frame.GetDocument() && |
270 opener_frame.GetDocument()->IsSandboxed(kSandboxPopups)) | 488 opener_frame.GetDocument()->IsSandboxed(kSandboxPopups)) |
271 return; | 489 return; |
272 | 490 |
273 if (policy == kNavigationPolicyCurrentTab) | 491 if (policy == kNavigationPolicyCurrentTab) |
274 policy = kNavigationPolicyNewForegroundTab; | 492 policy = kNavigationPolicyNewForegroundTab; |
275 | 493 |
276 WindowFeatures features; | 494 WebWindowFeatures features; |
277 features.noopener = request.GetShouldSetOpener() == kNeverSetOpener; | 495 features.noopener = request.GetShouldSetOpener() == kNeverSetOpener; |
278 bool created; | 496 bool created; |
279 Frame* new_frame = | 497 Frame* new_frame = |
280 CreateWindowHelper(opener_frame, opener_frame, opener_frame, request, | 498 CreateWindowHelper(opener_frame, opener_frame, opener_frame, request, |
281 features, policy, created); | 499 features, policy, created); |
282 if (!new_frame) | 500 if (!new_frame) |
283 return; | 501 return; |
284 if (request.GetShouldSendReferrer() == kMaybeSendReferrer) { | 502 if (request.GetShouldSendReferrer() == kMaybeSendReferrer) { |
285 // TODO(japhet): Does ReferrerPolicy need to be proagated for RemoteFrames? | 503 // TODO(japhet): Does ReferrerPolicy need to be proagated for RemoteFrames? |
286 if (new_frame->IsLocalFrame()) | 504 if (new_frame->IsLocalFrame()) |
287 ToLocalFrame(new_frame)->GetDocument()->SetReferrerPolicy( | 505 ToLocalFrame(new_frame)->GetDocument()->SetReferrerPolicy( |
288 opener_frame.GetDocument()->GetReferrerPolicy()); | 506 opener_frame.GetDocument()->GetReferrerPolicy()); |
289 } | 507 } |
290 | 508 |
291 // TODO(japhet): Form submissions on RemoteFrames don't work yet. | 509 // TODO(japhet): Form submissions on RemoteFrames don't work yet. |
292 FrameLoadRequest new_request(0, request.GetResourceRequest()); | 510 FrameLoadRequest new_request(0, request.GetResourceRequest()); |
293 new_request.SetForm(request.Form()); | 511 new_request.SetForm(request.Form()); |
294 if (new_frame->IsLocalFrame()) | 512 if (new_frame->IsLocalFrame()) |
295 ToLocalFrame(new_frame)->Loader().Load(new_request); | 513 ToLocalFrame(new_frame)->Loader().Load(new_request); |
296 } | 514 } |
297 | 515 |
298 } // namespace blink | 516 } // namespace blink |
OLD | NEW |