Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / page / CreateWindow.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
25  */
26
27 #include "config.h"
28 #include "core/page/CreateWindow.h"
29
30 #include "core/dom/Document.h"
31 #include "core/frame/FrameHost.h"
32 #include "core/frame/LocalFrame.h"
33 #include "core/frame/Settings.h"
34 #include "core/inspector/ConsoleMessage.h"
35 #include "core/loader/FrameLoadRequest.h"
36 #include "core/page/Chrome.h"
37 #include "core/page/ChromeClient.h"
38 #include "core/page/FocusController.h"
39 #include "core/page/Page.h"
40 #include "core/page/WindowFeatures.h"
41 #include "platform/network/ResourceRequest.h"
42 #include "platform/weborigin/KURL.h"
43 #include "platform/weborigin/SecurityOrigin.h"
44 #include "platform/weborigin/SecurityPolicy.h"
45
46 namespace blink {
47
48 static LocalFrame* createWindow(LocalFrame& openerFrame, LocalFrame& lookupFrame, const FrameLoadRequest& request, const WindowFeatures& features, NavigationPolicy policy, ShouldSendReferrer shouldSendReferrer, bool& created)
49 {
50     ASSERT(!features.dialog || request.frameName().isEmpty());
51
52     if (!request.frameName().isEmpty() && request.frameName() != "_blank" && policy == NavigationPolicyIgnore) {
53         if (LocalFrame* frame = lookupFrame.loader().findFrameForNavigation(request.frameName(), openerFrame.document())) {
54             if (request.frameName() != "_self")
55                 frame->page()->focusController().setFocusedFrame(frame);
56             created = false;
57             return frame;
58         }
59     }
60
61     // Sandboxed frames cannot open new auxiliary browsing contexts.
62     if (openerFrame.document()->isSandboxed(SandboxPopups)) {
63         // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
64         openerFrame.document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, "Blocked opening '" + request.resourceRequest().url().elidedString() + "' in a new window because the request was made in a sandboxed frame whose 'allow-popups' permission is not set."));
65         return nullptr;
66     }
67
68     if (openerFrame.settings() && !openerFrame.settings()->supportsMultipleWindows()) {
69         created = false;
70         if (!openerFrame.tree().top()->isLocalFrame())
71             return nullptr;
72         return toLocalFrame(openerFrame.tree().top());
73     }
74
75     Page* oldPage = openerFrame.page();
76     if (!oldPage)
77         return nullptr;
78
79     Page* page = oldPage->chrome().client().createWindow(&openerFrame, request, features, policy, shouldSendReferrer);
80     if (!page || !page->mainFrame()->isLocalFrame())
81         return nullptr;
82     FrameHost* host = &page->frameHost();
83
84     ASSERT(page->mainFrame());
85     LocalFrame& frame = *page->deprecatedLocalMainFrame();
86
87     if (request.frameName() != "_blank")
88         frame.tree().setName(request.frameName());
89
90     host->chrome().setWindowFeatures(features);
91
92     // 'x' and 'y' specify the location of the window, while 'width' and 'height'
93     // specify the size of the viewport. We can only resize the window, so adjust
94     // for the difference between the window size and the viewport size.
95
96     FloatRect windowRect = host->chrome().windowRect();
97     FloatSize viewportSize = host->chrome().pageRect().size();
98
99     if (features.xSet)
100         windowRect.setX(features.x);
101     if (features.ySet)
102         windowRect.setY(features.y);
103     if (features.widthSet)
104         windowRect.setWidth(features.width + (windowRect.width() - viewportSize.width()));
105     if (features.heightSet)
106         windowRect.setHeight(features.height + (windowRect.height() - viewportSize.height()));
107
108     // Ensure non-NaN values, minimum size as well as being within valid screen area.
109     FloatRect newWindowRect = LocalDOMWindow::adjustWindowRect(frame, windowRect);
110
111     host->chrome().setWindowRect(newWindowRect);
112     host->chrome().show(policy);
113
114     created = true;
115     return &frame;
116 }
117
118 LocalFrame* createWindow(const String& urlString, const AtomicString& frameName, const WindowFeatures& windowFeatures,
119     LocalDOMWindow& callingWindow, LocalFrame& firstFrame, LocalFrame& openerFrame, LocalDOMWindow::PrepareDialogFunction function, void* functionContext)
120 {
121     LocalFrame* activeFrame = callingWindow.frame();
122     ASSERT(activeFrame);
123
124     KURL completedURL = urlString.isEmpty() ? KURL(ParsedURLString, emptyString()) : firstFrame.document()->completeURL(urlString);
125     if (!completedURL.isEmpty() && !completedURL.isValid()) {
126         // Don't expose client code to invalid URLs.
127         callingWindow.printErrorMessage("Unable to open a window with invalid URL '" + completedURL.string() + "'.\n");
128         return nullptr;
129     }
130
131     FrameLoadRequest frameRequest(callingWindow.document(), completedURL, frameName);
132
133     // Normally, FrameLoader would take care of setting the referrer for a navigation that is
134     // triggered from javascript. However, creating a window goes through sufficient processing
135     // that it eventually enters FrameLoader as an embedder-initiated navigation. FrameLoader
136     // assumes no responsibility for generating an embedder-initiated navigation's referrer,
137     // so we need to ensure the proper referrer is set now.
138     frameRequest.resourceRequest().setHTTPReferrer(SecurityPolicy::generateReferrer(activeFrame->document()->referrerPolicy(), completedURL, activeFrame->document()->outgoingReferrer()));
139
140     // We pass the opener frame for the lookupFrame in case the active frame is different from
141     // the opener frame, and the name references a frame relative to the opener frame.
142     bool created;
143     LocalFrame* newFrame = createWindow(*activeFrame, openerFrame, frameRequest, windowFeatures, NavigationPolicyIgnore, MaybeSendReferrer, created);
144     if (!newFrame)
145         return nullptr;
146
147     if (newFrame != &openerFrame && newFrame != openerFrame.tree().top())
148         newFrame->loader().forceSandboxFlags(openerFrame.document()->sandboxFlags());
149
150     newFrame->loader().setOpener(&openerFrame);
151
152     if (newFrame->domWindow()->isInsecureScriptAccess(callingWindow, completedURL))
153         return newFrame;
154
155     if (function)
156         function(newFrame->domWindow(), functionContext);
157
158     if (created)
159         newFrame->loader().load(FrameLoadRequest(callingWindow.document(), completedURL));
160     else if (!urlString.isEmpty())
161         newFrame->navigationScheduler().scheduleLocationChange(callingWindow.document(), completedURL.string(), false);
162     return newFrame;
163 }
164
165 void createWindowForRequest(const FrameLoadRequest& request, LocalFrame& openerFrame, NavigationPolicy policy, ShouldSendReferrer shouldSendReferrer)
166 {
167     if (openerFrame.document()->pageDismissalEventBeingDispatched() != Document::NoDismissal)
168         return;
169
170     if (openerFrame.document() && openerFrame.document()->isSandboxed(SandboxPopups))
171         return;
172
173     if (!LocalDOMWindow::allowPopUp(openerFrame))
174         return;
175
176     if (policy == NavigationPolicyCurrentTab)
177         policy = NavigationPolicyNewForegroundTab;
178
179     WindowFeatures features;
180     bool created;
181     LocalFrame* newFrame = createWindow(openerFrame, openerFrame, request, features, policy, shouldSendReferrer, created);
182     if (!newFrame)
183         return;
184     if (shouldSendReferrer == MaybeSendReferrer) {
185         newFrame->loader().setOpener(&openerFrame);
186         newFrame->document()->setReferrerPolicy(openerFrame.document()->referrerPolicy());
187     }
188     FrameLoadRequest newRequest(0, request.resourceRequest());
189     newRequest.setFormState(request.formState());
190     newFrame->loader().load(newRequest);
191 }
192
193 } // namespace blink