Unreviewed, rolling out r191902.
[WebKit-https.git] / Source / WebKit / ios / WebCoreSupport / WebChromeClientIOS.mm
1 /*
2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #if PLATFORM(IOS)
27 #import "WebChromeClientIOS.h"
28
29 #import "DOMNodeInternal.h"
30 #import "PopupMenuIOS.h"
31 #import "SearchPopupMenuIOS.h"
32 #import "WebDelegateImplementationCaching.h"
33 #import "WebFixedPositionContent.h"
34 #import "WebFixedPositionContentInternal.h"
35 #import "WebFormDelegate.h"
36 #import "WebFrameIOS.h"
37 #import "WebFrameInternal.h"
38 #import "WebKitSystemInterface.h"
39 #import "WebOpenPanelResultListener.h"
40 #import "WebUIDelegate.h"
41 #import "WebUIDelegatePrivate.h"
42 #import "WebView.h"
43 #import "WebViewInternal.h"
44 #import "WebViewPrivate.h"
45 #import "WebUIKitDelegate.h"
46
47 #import <wtf/HashMap.h>
48 #import <wtf/RefPtr.h>
49 #import <WebCore/FileChooser.h>
50 #import <WebCore/FloatRect.h>
51 #import <WebCore/Frame.h>
52 #import <WebCore/GraphicsLayer.h>
53 #import <WebCore/HTMLInputElement.h>
54 #import <WebCore/HTMLNames.h>
55 #import <WebCore/IntRect.h>
56 #import <WebCore/Node.h>
57 #import <WebCore/RenderBox.h>
58 #import <WebCore/RenderObject.h>
59 #import <WebCore/RuntimeApplicationChecksIOS.h>
60 #import <WebCore/ScrollingConstraints.h>
61 #import <WebCore/WAKWindow.h>
62 #import <WebCore/WebCoreThreadMessage.h>
63
64 #if PLATFORM(IOS)
65 #include "WebKitSystemInterface.h"
66 #endif
67
68 using namespace WebCore;
69
70 void WebChromeClientIOS::setWindowRect(const WebCore::FloatRect& r)
71 {
72     [[webView() _UIDelegateForwarder] webView:webView() setFrame:r];
73 }
74
75 FloatRect WebChromeClientIOS::windowRect()
76 {
77     CGRect windowRect = [[webView() _UIDelegateForwarder] webViewFrame:webView()];
78     return enclosingIntRect(windowRect);
79 }
80
81 void WebChromeClientIOS::focus()
82 {
83     [[webView() _UIDelegateForwarder] webViewFocus:webView()];
84 }
85
86 void WebChromeClientIOS::runJavaScriptAlert(Frame* frame, const WTF::String& message)
87 {
88     WebThreadLockPushModal();
89     [[webView() _UIDelegateForwarder] webView:webView() runJavaScriptAlertPanelWithMessage:message initiatedByFrame:kit(frame)];
90     WebThreadLockPopModal();
91 }
92
93 bool WebChromeClientIOS::runJavaScriptConfirm(Frame* frame, const WTF::String& message)
94 {
95     WebThreadLockPushModal();
96     bool result = [[webView() _UIDelegateForwarder] webView:webView() runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:kit(frame)];
97     WebThreadLockPopModal();
98     return result;
99 }
100
101 bool WebChromeClientIOS::runJavaScriptPrompt(Frame* frame, const WTF::String& prompt, const WTF::String& defaultText, WTF::String& result)
102 {
103     WebThreadLockPushModal();
104     result = [[webView() _UIDelegateForwarder] webView:webView() runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText initiatedByFrame:kit(frame)];
105     WebThreadLockPopModal();
106     return !result.isNull();
107 }
108
109 void WebChromeClientIOS::runOpenPanel(Frame*, PassRefPtr<FileChooser> chooser)
110 {
111     const FileChooserSettings& settings = chooser->settings();
112     BOOL allowMultipleFiles = settings.allowsMultipleFiles;
113     Vector<String> acceptMIMETypes = settings.acceptMIMETypes;
114     WebOpenPanelResultListener *listener = [[WebOpenPanelResultListener alloc] initWithChooser:chooser];
115
116     // Convert the accept attribute string into a list of MIME types.
117     size_t numMIMETypes = acceptMIMETypes.size();
118     NSMutableArray *mimeTypes = [NSMutableArray arrayWithCapacity:numMIMETypes];
119     for (size_t i = 0; i < numMIMETypes; ++i)
120         [mimeTypes addObject:acceptMIMETypes[i]];
121
122     if (WebThreadIsCurrent()) {
123         dispatch_async(dispatch_get_main_queue(), ^{
124             [[webView() _UIKitDelegateForwarder] webView:webView() runOpenPanelForFileButtonWithResultListener:listener allowMultipleFiles:allowMultipleFiles acceptMIMETypes:mimeTypes];
125         });
126     } else
127         [[webView() _UIKitDelegateForwarder] webView:webView() runOpenPanelForFileButtonWithResultListener:listener allowMultipleFiles:allowMultipleFiles acceptMIMETypes:mimeTypes];
128
129     [listener release];
130 }
131
132 #if ENABLE(IOS_TOUCH_EVENTS)
133 void WebChromeClientIOS::didPreventDefaultForEvent()
134 {
135     [[webView() _UIKitDelegateForwarder] webViewDidPreventDefaultForEvent:webView()];
136 }
137 #endif
138
139 void WebChromeClientIOS::didReceiveMobileDocType(bool isMobileDoctype)
140 {
141     if (isMobileDoctype)
142         [[webView() _UIKitDelegateForwarder] webViewDidReceiveMobileDocType:webView()];
143 }
144
145 void WebChromeClientIOS::setNeedsScrollNotifications(WebCore::Frame* frame, bool flag)
146 {
147     [[webView() _UIKitDelegateForwarder] webView:webView() needsScrollNotifications:[NSNumber numberWithBool:flag] forFrame:kit(frame)];
148 }
149
150 void WebChromeClientIOS::observedContentChange(WebCore::Frame* frame)
151 {
152     [[webView() _UIKitDelegateForwarder] webView:webView() didObserveDeferredContentChange:WKObservedContentChange() forFrame:kit(frame)];
153 }
154
155 void WebChromeClientIOS::clearContentChangeObservers(WebCore::Frame* frame)
156 {
157     ASSERT(WebThreadCountOfObservedContentModifiers() > 0);
158     if (WebThreadCountOfObservedContentModifiers() > 0) {
159         WebThreadClearObservedContentModifiers();
160         observedContentChange(frame);
161     }        
162 }
163
164 static inline NSDictionary* dictionaryForViewportArguments(const WebCore::ViewportArguments& arguments)
165 {
166     return @{ @"initial-scale":@(arguments.zoom),
167               @"minimum-scale":@(arguments.minZoom),
168               @"maximum-scale":@(arguments.maxZoom),
169               @"user-scalable":@(arguments.userZoom),
170               @"shrink-to-fit":@(arguments.shrinkToFit),
171               @"width":@(arguments.width),
172               @"height":@(arguments.height) };
173 }
174
175 FloatSize WebChromeClientIOS::screenSize() const
176 {
177     return FloatSize(WKGetScreenSize());
178 }
179
180 FloatSize WebChromeClientIOS::availableScreenSize() const
181 {
182     // WebKit1 code should query the WAKWindow for the available screen size.
183     ASSERT_NOT_REACHED();
184     return FloatSize();
185 }
186
187 void WebChromeClientIOS::dispatchViewportPropertiesDidChange(const WebCore::ViewportArguments& arguments) const
188 {
189     [[webView() _UIKitDelegateForwarder] webView:webView() didReceiveViewportArguments:dictionaryForViewportArguments(arguments)];
190 }
191
192 void WebChromeClientIOS::notifyRevealedSelectionByScrollingFrame(WebCore::Frame* frame)
193 {
194     [[webView() _UIKitDelegateForwarder] revealedSelectionByScrollingWebFrame:kit(frame)];
195 }
196
197 bool WebChromeClientIOS::isStopping()
198 {
199     return [webView() _isStopping];
200 }
201
202 void WebChromeClientIOS::didLayout(LayoutType changeType)
203 {
204     [[webView() _UIKitDelegate] webThreadWebViewDidLayout:webView() byScrolling:(changeType == ChromeClient::Scroll)];
205 }
206
207 void WebChromeClientIOS::didStartOverflowScroll()
208 {
209     [[[webView() _UIKitDelegateForwarder] asyncForwarder] webViewDidStartOverflowScroll:webView()];
210 }
211
212 void WebChromeClientIOS::didEndOverflowScroll()
213 {
214     [[[webView() _UIKitDelegateForwarder] asyncForwarder] webViewDidEndOverflowScroll:webView()];
215 }
216
217 void WebChromeClientIOS::suppressFormNotifications() 
218 {
219     m_formNotificationSuppressions++;
220 }
221
222 void WebChromeClientIOS::restoreFormNotifications() 
223 {
224     m_formNotificationSuppressions--;
225     ASSERT(m_formNotificationSuppressions >= 0);
226     if (m_formNotificationSuppressions < 0)
227         m_formNotificationSuppressions = 0;
228 }
229
230 void WebChromeClientIOS::elementDidFocus(const WebCore::Node* node)
231 {
232     if (m_formNotificationSuppressions <= 0)
233         [[webView() _UIKitDelegateForwarder] webView:webView() elementDidFocusNode:kit(const_cast<WebCore::Node*>(node))];
234 }
235
236 void WebChromeClientIOS::elementDidBlur(const WebCore::Node* node)
237 {
238     if (m_formNotificationSuppressions <= 0)
239         [[webView() _UIKitDelegateForwarder] webView:webView() elementDidBlurNode:kit(const_cast<WebCore::Node*>(node))];
240 }
241
242 bool WebChromeClientIOS::selectItemWritingDirectionIsNatural()
243 {
244     return false;
245 }
246
247 bool WebChromeClientIOS::selectItemAlignmentFollowsMenuWritingDirection()
248 {
249     return true;
250 }
251
252 RefPtr<WebCore::PopupMenu> WebChromeClientIOS::createPopupMenu(WebCore::PopupMenuClient* client) const
253 {
254     return adoptRef(new PopupMenuIOS(client));
255 }
256
257 RefPtr<WebCore::SearchPopupMenu> WebChromeClientIOS::createSearchPopupMenu(WebCore::PopupMenuClient* client) const
258 {
259     return adoptRef(new SearchPopupMenuIOS(client));
260 }
261
262 void WebChromeClientIOS::attachRootGraphicsLayer(Frame*, GraphicsLayer* graphicsLayer)
263 {
264     // FIXME: for non-root frames we rely on RenderView positioning the root layer,
265     // which is a hack. <rdar://problem/5906146>
266     // Send the delegate message on the web thread to avoid <rdar://problem/8567677>
267     [[webView() _UIKitDelegate] _webthread_webView:webView() attachRootLayer:graphicsLayer ? graphicsLayer->platformLayer() : 0];
268 }
269
270 void WebChromeClientIOS::didFlushCompositingLayers()
271 {
272     [[[webView() _UIKitDelegateForwarder] asyncForwarder] webViewDidCommitCompositingLayerChanges:webView()];
273 }
274
275 bool WebChromeClientIOS::fetchCustomFixedPositionLayoutRect(IntRect& rect)
276 {
277     NSRect updatedRect;
278     if ([webView() _fetchCustomFixedPositionLayoutRect:&updatedRect]) {
279         rect = enclosingIntRect(updatedRect);
280         return true;
281     }
282
283     return false;
284 }
285
286 void WebChromeClientIOS::updateViewportConstrainedLayers(HashMap<PlatformLayer*, std::unique_ptr<ViewportConstraints>>& layerMap, HashMap<PlatformLayer*, PlatformLayer*>& stickyContainers)
287 {
288     [[webView() _fixedPositionContent] setViewportConstrainedLayers:layerMap stickyContainerMap:stickyContainers];
289 }
290
291 void WebChromeClientIOS::addOrUpdateScrollingLayer(Node* node, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer, const IntSize& scrollSize, bool allowHorizontalScrollbar, bool allowVerticalScrollbar)
292 {
293     DOMNode *domNode = kit(node);
294
295     [[[webView() _UIKitDelegateForwarder] asyncForwarder] webView:webView() didCreateOrUpdateScrollingLayer:scrollingLayer withContentsLayer:contentsLayer scrollSize:[NSValue valueWithSize:scrollSize] forNode:domNode
296         allowHorizontalScrollbar:allowHorizontalScrollbar allowVerticalScrollbar:allowVerticalScrollbar];
297 }
298
299 void WebChromeClientIOS::removeScrollingLayer(Node* node, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer)
300 {
301     DOMNode *domNode = kit(node);
302     [[[webView() _UIKitDelegateForwarder] asyncForwarder] webView:webView() willRemoveScrollingLayer:scrollingLayer withContentsLayer:contentsLayer forNode:domNode];
303 }
304
305 void WebChromeClientIOS::webAppOrientationsUpdated()
306 {
307     [[webView() _UIDelegateForwarder] webViewSupportedOrientationsUpdated:webView()];
308 }
309
310 void WebChromeClientIOS::focusedElementChanged(Element* element)
311 {
312     if (!is<HTMLInputElement>(element))
313         return;
314
315     HTMLInputElement& inputElement = downcast<HTMLInputElement>(*element);
316     if (!inputElement.isText())
317         return;
318
319     CallFormDelegate(webView(), @selector(didFocusTextField:inFrame:), kit(&inputElement), kit(inputElement.document().frame()));
320 }
321
322 void WebChromeClientIOS::showPlaybackTargetPicker(bool hasVideo)
323 {
324     CGPoint point = [[webView() _UIKitDelegateForwarder] interactionLocation];
325     CGRect elementRect = [[webView() mainFrame] elementRectAtPoint:point];
326     [[webView() _UIKitDelegateForwarder] showPlaybackTargetPicker:hasVideo fromRect:elementRect];
327 }
328
329 #if ENABLE(ORIENTATION_EVENTS)
330 int WebChromeClientIOS::deviceOrientation() const
331 {
332     return [[webView() _UIKitDelegateForwarder] deviceOrientation];
333 }
334 #endif
335
336 #endif // PLATFORM(IOS)