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 10 matching lines...) Expand all Loading... |
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
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 "config.h" | 27 #include "config.h" |
28 #include "core/page/CreateWindow.h" | 28 #include "core/page/CreateWindow.h" |
29 | 29 |
30 #include "core/dom/Document.h" | 30 #include "core/dom/Document.h" |
31 #include "core/frame/FrameClient.h" | |
32 #include "core/frame/FrameHost.h" | 31 #include "core/frame/FrameHost.h" |
33 #include "core/frame/LocalFrame.h" | 32 #include "core/frame/LocalFrame.h" |
34 #include "core/frame/Settings.h" | 33 #include "core/frame/Settings.h" |
35 #include "core/inspector/ConsoleMessage.h" | 34 #include "core/inspector/ConsoleMessage.h" |
36 #include "core/loader/FrameLoadRequest.h" | 35 #include "core/loader/FrameLoadRequest.h" |
37 #include "core/page/Chrome.h" | 36 #include "core/page/Chrome.h" |
38 #include "core/page/ChromeClient.h" | 37 #include "core/page/ChromeClient.h" |
39 #include "core/page/FocusController.h" | 38 #include "core/page/FocusController.h" |
40 #include "core/page/Page.h" | 39 #include "core/page/Page.h" |
41 #include "core/page/WindowFeatures.h" | 40 #include "core/page/WindowFeatures.h" |
42 #include "platform/UserGestureIndicator.h" | 41 #include "platform/UserGestureIndicator.h" |
43 #include "platform/network/ResourceRequest.h" | 42 #include "platform/network/ResourceRequest.h" |
44 #include "platform/weborigin/KURL.h" | 43 #include "platform/weborigin/KURL.h" |
45 #include "platform/weborigin/SecurityOrigin.h" | 44 #include "platform/weborigin/SecurityOrigin.h" |
46 #include "platform/weborigin/SecurityPolicy.h" | 45 #include "platform/weborigin/SecurityPolicy.h" |
47 #include "public/platform/WebURLRequest.h" | 46 #include "public/platform/WebURLRequest.h" |
48 | 47 |
49 namespace blink { | 48 namespace blink { |
50 | 49 |
51 static Frame* createWindow(LocalFrame& openerFrame, LocalFrame& lookupFrame, con
st FrameLoadRequest& request, const WindowFeatures& features, NavigationPolicy p
olicy, ShouldSendReferrer shouldSendReferrer) | 50 static LocalFrame* createWindow(LocalFrame& openerFrame, LocalFrame& lookupFrame
, const FrameLoadRequest& request, const WindowFeatures& features, NavigationPol
icy policy, ShouldSendReferrer shouldSendReferrer, bool& created) |
52 { | 51 { |
53 ASSERT(!features.dialog || request.frameName().isEmpty()); | 52 ASSERT(!features.dialog || request.frameName().isEmpty()); |
54 ASSERT(request.resourceRequest().frameType() == WebURLRequest::FrameTypeAuxi
liary); | 53 ASSERT(request.resourceRequest().frameType() == WebURLRequest::FrameTypeAuxi
liary); |
55 | 54 |
56 if (!request.frameName().isEmpty() && request.frameName() != "_blank" && pol
icy == NavigationPolicyIgnore) { | 55 if (!request.frameName().isEmpty() && request.frameName() != "_blank" && pol
icy == NavigationPolicyIgnore) { |
57 if (Frame* frame = lookupFrame.findFrameForNavigation(request.frameName(
), openerFrame)) { | 56 if (Frame* frame = lookupFrame.findFrameForNavigation(request.frameName(
), openerFrame)) { |
58 if (request.frameName() != "_self") { | 57 if (request.frameName() != "_self") { |
59 if (FrameHost* host = frame->host()) { | 58 if (FrameHost* host = frame->host()) { |
60 if (host == openerFrame.host()) | 59 if (host == openerFrame.host()) |
61 frame->page()->focusController().setFocusedFrame(frame); | 60 frame->page()->focusController().setFocusedFrame(frame); |
62 else | 61 else |
63 host->chrome().focus(); | 62 host->chrome().focus(); |
64 } | 63 } |
65 } | 64 } |
66 return frame; | 65 created = false; |
| 66 // FIXME: Make this work with RemoteFrames. |
| 67 return frame->isLocalFrame() ? toLocalFrame(frame) : nullptr; |
67 } | 68 } |
68 } | 69 } |
69 | 70 |
70 // Sandboxed frames cannot open new auxiliary browsing contexts. | 71 // Sandboxed frames cannot open new auxiliary browsing contexts. |
71 if (openerFrame.document()->isSandboxed(SandboxPopups)) { | 72 if (openerFrame.document()->isSandboxed(SandboxPopups)) { |
72 // FIXME: This message should be moved off the console once a solution t
o https://bugs.webkit.org/show_bug.cgi?id=103274 exists. | 73 // FIXME: This message should be moved off the console once a solution t
o https://bugs.webkit.org/show_bug.cgi?id=103274 exists. |
73 openerFrame.document()->addConsoleMessage(ConsoleMessage::create(Securit
yMessageSource, ErrorMessageLevel, "Blocked opening '" + request.resourceRequest
().url().elidedString() + "' in a new window because the request was made in a s
andboxed frame whose 'allow-popups' permission is not set.")); | 74 openerFrame.document()->addConsoleMessage(ConsoleMessage::create(Securit
yMessageSource, ErrorMessageLevel, "Blocked opening '" + request.resourceRequest
().url().elidedString() + "' in a new window because the request was made in a s
andboxed frame whose 'allow-popups' permission is not set.")); |
74 return nullptr; | 75 return nullptr; |
75 } | 76 } |
76 | 77 |
77 if (openerFrame.settings() && !openerFrame.settings()->supportsMultipleWindo
ws()) | 78 if (openerFrame.settings() && !openerFrame.settings()->supportsMultipleWindo
ws()) { |
78 return openerFrame.tree().top(); | 79 created = false; |
| 80 if (!openerFrame.tree().top()->isLocalFrame()) |
| 81 return nullptr; |
| 82 return toLocalFrame(openerFrame.tree().top()); |
| 83 } |
79 | 84 |
80 FrameHost* oldHost = openerFrame.host(); | 85 Page* oldPage = openerFrame.page(); |
81 if (!oldHost) | 86 if (!oldPage) |
82 return nullptr; | 87 return nullptr; |
83 | 88 |
84 Page* page = oldHost->chrome().client().createWindow(&openerFrame, request,
features, policy, shouldSendReferrer); | 89 Page* page = oldPage->chrome().client().createWindow(&openerFrame, request,
features, policy, shouldSendReferrer); |
85 if (!page) | 90 if (!page || !page->mainFrame()->isLocalFrame()) |
86 return nullptr; | 91 return nullptr; |
87 FrameHost* host = &page->frameHost(); | 92 FrameHost* host = &page->frameHost(); |
88 | 93 |
89 ASSERT(page->mainFrame()); | 94 ASSERT(page->mainFrame()); |
90 Frame& frame = *page->mainFrame(); | 95 LocalFrame& frame = *page->deprecatedLocalMainFrame(); |
91 | 96 |
92 if (request.frameName() != "_blank") | 97 if (request.frameName() != "_blank") |
93 frame.tree().setName(request.frameName()); | 98 frame.tree().setName(request.frameName()); |
94 | 99 |
95 host->chrome().setWindowFeatures(features); | 100 host->chrome().setWindowFeatures(features); |
96 | 101 |
97 // 'x' and 'y' specify the location of the window, while 'width' and 'height
' | 102 // '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 adjus
t | 103 // specify the size of the viewport. We can only resize the window, so adjus
t |
99 // for the difference between the window size and the viewport size. | 104 // for the difference between the window size and the viewport size. |
100 | 105 |
101 IntRect windowRect = host->chrome().windowRect(); | 106 IntRect windowRect = host->chrome().windowRect(); |
102 IntSize viewportSize = host->chrome().pageRect().size(); | 107 IntSize viewportSize = host->chrome().pageRect().size(); |
103 | 108 |
104 if (features.xSet) | 109 if (features.xSet) |
105 windowRect.setX(features.x); | 110 windowRect.setX(features.x); |
106 if (features.ySet) | 111 if (features.ySet) |
107 windowRect.setY(features.y); | 112 windowRect.setY(features.y); |
108 if (features.widthSet) | 113 if (features.widthSet) |
109 windowRect.setWidth(features.width + (windowRect.width() - viewportSize.
width())); | 114 windowRect.setWidth(features.width + (windowRect.width() - viewportSize.
width())); |
110 if (features.heightSet) | 115 if (features.heightSet) |
111 windowRect.setHeight(features.height + (windowRect.height() - viewportSi
ze.height())); | 116 windowRect.setHeight(features.height + (windowRect.height() - viewportSi
ze.height())); |
112 | 117 |
113 host->chrome().setWindowRect(windowRect); | 118 // Ensure minimum size as well as being within valid screen area. |
| 119 IntRect newWindowRect = LocalDOMWindow::adjustWindowRect(frame, windowRect); |
| 120 |
| 121 host->chrome().setWindowRect(newWindowRect); |
114 host->chrome().show(policy); | 122 host->chrome().show(policy); |
115 | 123 |
116 // TODO(japhet): There's currently no way to set sandbox flags on a RemoteFr
ame and have it propagate | 124 frame.loader().forceSandboxFlags(openerFrame.document()->sandboxFlags()); |
117 // to the real frame in a different process. See crbug.com/483584. | |
118 if (frame.isLocalFrame()) | |
119 toLocalFrame(&frame)->loader().forceSandboxFlags(openerFrame.document()-
>sandboxFlags()); | |
120 | 125 |
| 126 created = true; |
121 return &frame; | 127 return &frame; |
122 } | 128 } |
123 | 129 |
124 Frame* createWindow(const String& urlString, const AtomicString& frameName, cons
t WindowFeatures& windowFeatures, | 130 LocalFrame* createWindow(const String& urlString, const AtomicString& frameName,
const WindowFeatures& windowFeatures, |
125 LocalDOMWindow& callingWindow, LocalFrame& firstFrame, LocalFrame& openerFra
me) | 131 LocalDOMWindow& callingWindow, LocalFrame& firstFrame, LocalFrame& openerFra
me) |
126 { | 132 { |
127 LocalFrame* activeFrame = callingWindow.frame(); | 133 LocalFrame* activeFrame = callingWindow.frame(); |
128 ASSERT(activeFrame); | 134 ASSERT(activeFrame); |
129 | 135 |
130 KURL completedURL = urlString.isEmpty() ? KURL(ParsedURLString, emptyString(
)) : firstFrame.document()->completeURL(urlString); | 136 KURL completedURL = urlString.isEmpty() ? KURL(ParsedURLString, emptyString(
)) : firstFrame.document()->completeURL(urlString); |
131 if (!completedURL.isEmpty() && !completedURL.isValid()) { | 137 if (!completedURL.isEmpty() && !completedURL.isValid()) { |
132 // Don't expose client code to invalid URLs. | 138 // Don't expose client code to invalid URLs. |
133 callingWindow.printErrorMessage("Unable to open a window with invalid UR
L '" + completedURL.string() + "'.\n"); | 139 callingWindow.printErrorMessage("Unable to open a window with invalid UR
L '" + completedURL.string() + "'.\n"); |
134 return nullptr; | 140 return nullptr; |
135 } | 141 } |
136 | 142 |
137 FrameLoadRequest frameRequest(callingWindow.document(), completedURL, frameN
ame); | 143 FrameLoadRequest frameRequest(callingWindow.document(), completedURL, frameN
ame); |
138 frameRequest.resourceRequest().setFrameType(WebURLRequest::FrameTypeAuxiliar
y); | 144 frameRequest.resourceRequest().setFrameType(WebURLRequest::FrameTypeAuxiliar
y); |
139 | 145 |
140 // Normally, FrameLoader would take care of setting the referrer for a navig
ation that is | 146 // Normally, FrameLoader would take care of setting the referrer for a navig
ation that is |
141 // triggered from javascript. However, creating a window goes through suffic
ient processing | 147 // triggered from javascript. However, creating a window goes through suffic
ient processing |
142 // that it eventually enters FrameLoader as an embedder-initiated navigation
. FrameLoader | 148 // that it eventually enters FrameLoader as an embedder-initiated navigation
. FrameLoader |
143 // assumes no responsibility for generating an embedder-initiated navigation
's referrer, | 149 // assumes no responsibility for generating an embedder-initiated navigation
's referrer, |
144 // so we need to ensure the proper referrer is set now. | 150 // so we need to ensure the proper referrer is set now. |
145 frameRequest.resourceRequest().setHTTPReferrer(SecurityPolicy::generateRefer
rer(activeFrame->document()->referrerPolicy(), completedURL, activeFrame->docume
nt()->outgoingReferrer())); | 151 frameRequest.resourceRequest().setHTTPReferrer(SecurityPolicy::generateRefer
rer(activeFrame->document()->referrerPolicy(), completedURL, activeFrame->docume
nt()->outgoingReferrer())); |
146 | 152 |
| 153 bool hasUserGesture = UserGestureIndicator::processingUserGesture(); |
| 154 |
147 // We pass the opener frame for the lookupFrame in case the active frame is
different from | 155 // We pass the opener frame for the lookupFrame in case the active frame is
different from |
148 // the opener frame, and the name references a frame relative to the opener
frame. | 156 // the opener frame, and the name references a frame relative to the opener
frame. |
149 Frame* newFrame = createWindow(*activeFrame, openerFrame, frameRequest, wind
owFeatures, NavigationPolicyIgnore, MaybeSendReferrer); | 157 bool created; |
| 158 LocalFrame* newFrame = createWindow(*activeFrame, openerFrame, frameRequest,
windowFeatures, NavigationPolicyIgnore, MaybeSendReferrer, created); |
150 if (!newFrame) | 159 if (!newFrame) |
151 return nullptr; | 160 return nullptr; |
152 | 161 |
153 newFrame->client()->setOpener(&openerFrame); | 162 newFrame->loader().setOpener(&openerFrame); |
154 | 163 |
155 if (newFrame->domWindow()->isInsecureScriptAccess(callingWindow, completedUR
L)) | 164 if (newFrame->localDOMWindow()->isInsecureScriptAccess(callingWindow, comple
tedURL)) |
156 return newFrame; | 165 return newFrame; |
157 | 166 |
158 // TODO(dcheng): Special case for window.open("about:blank") to ensure it lo
ads synchronously into | 167 if (created) { |
159 // a new window. This is our historical behavior, and it's consistent with t
he creation of | 168 FrameLoadRequest request(callingWindow.document(), completedURL); |
160 // a new iframe with src="about:blank". Perhaps we could get rid of this if
we started reporting | 169 request.resourceRequest().setHasUserGesture(hasUserGesture); |
161 // the initial empty document's url as about:blank? See crbug.com/471239. | 170 newFrame->loader().load(request); |
162 if (newFrame->isLocalFrame() && newFrame->isMainFrame() && !toLocalFrame(new
Frame)->loader().stateMachine()->committedFirstRealDocumentLoad() && (completedU
RL.isEmpty() || completedURL.isAboutBlankURL())) | 171 } else if (!urlString.isEmpty()) { |
163 toLocalFrame(newFrame)->loader().load(FrameLoadRequest(callingWindow.doc
ument(), completedURL)); | |
164 else | |
165 newFrame->navigate(*callingWindow.document(), completedURL, false); | 172 newFrame->navigate(*callingWindow.document(), completedURL, false); |
| 173 } |
166 return newFrame; | 174 return newFrame; |
167 } | 175 } |
168 | 176 |
169 void createWindowForRequest(const FrameLoadRequest& request, LocalFrame& openerF
rame, NavigationPolicy policy, ShouldSendReferrer shouldSendReferrer) | 177 void createWindowForRequest(const FrameLoadRequest& request, LocalFrame& openerF
rame, NavigationPolicy policy, ShouldSendReferrer shouldSendReferrer) |
170 { | 178 { |
171 if (openerFrame.document()->pageDismissalEventBeingDispatched() != Document:
:NoDismissal) | 179 if (openerFrame.document()->pageDismissalEventBeingDispatched() != Document:
:NoDismissal) |
172 return; | 180 return; |
173 | 181 |
174 if (openerFrame.document() && openerFrame.document()->isSandboxed(SandboxPop
ups)) | 182 if (openerFrame.document() && openerFrame.document()->isSandboxed(SandboxPop
ups)) |
175 return; | 183 return; |
176 | 184 |
177 if (!LocalDOMWindow::allowPopUp(openerFrame)) | 185 if (!LocalDOMWindow::allowPopUp(openerFrame)) |
178 return; | 186 return; |
179 | 187 |
180 if (policy == NavigationPolicyCurrentTab) | 188 if (policy == NavigationPolicyCurrentTab) |
181 policy = NavigationPolicyNewForegroundTab; | 189 policy = NavigationPolicyNewForegroundTab; |
182 | 190 |
183 WindowFeatures features; | 191 WindowFeatures features; |
184 Frame* newFrame = createWindow(openerFrame, openerFrame, request, features,
policy, shouldSendReferrer); | 192 bool created; |
| 193 LocalFrame* newFrame = createWindow(openerFrame, openerFrame, request, featu
res, policy, shouldSendReferrer, created); |
185 if (!newFrame) | 194 if (!newFrame) |
186 return; | 195 return; |
187 if (shouldSendReferrer == MaybeSendReferrer) | 196 if (shouldSendReferrer == MaybeSendReferrer) { |
188 newFrame->client()->setOpener(&openerFrame); | 197 newFrame->loader().setOpener(&openerFrame); |
189 | 198 newFrame->document()->setReferrerPolicy(openerFrame.document()->referrer
Policy()); |
190 // TODO(japhet): Form submissions on RemoteFrames don't work yet. | 199 } |
191 FrameLoadRequest newRequest(0, request.resourceRequest()); | 200 FrameLoadRequest newRequest(0, request.resourceRequest()); |
192 newRequest.setFormState(request.formState()); | 201 newRequest.setFormState(request.formState()); |
193 if (newFrame->isLocalFrame()) | 202 newFrame->loader().load(newRequest); |
194 toLocalFrame(newFrame)->loader().load(newRequest); | |
195 } | 203 } |
196 | 204 |
197 } // namespace blink | 205 } // namespace blink |
OLD | NEW |