4e40ab524c5bffedde665c11804f1569a7639400
[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/PlatformScreen.h>
58 #import <WebCore/RenderBox.h>
59 #import <WebCore/RenderObject.h>
60 #import <WebCore/RuntimeApplicationChecksIOS.h>
61 #import <WebCore/ScrollingConstraints.h>
62 #import <WebCore/WAKWindow.h>
63 #import <WebCore/WebCoreThreadMessage.h>
64
65 using namespace WebCore;
66
67 void WebChromeClientIOS::setWindowRect(const WebCore::FloatRect& r)
68 {
69     [[webView() _UIDelegateForwarder] webView:webView() setFrame:r];
70 }
71
72 FloatRect WebChromeClientIOS::windowRect()
73 {
74     CGRect windowRect = [[webView() _UIDelegateForwarder] webViewFrame:webView()];
75     return enclosingIntRect(windowRect);
76 }
77
78 void WebChromeClientIOS::focus()
79 {
80     [[webView() _UIDelegateForwarder] webViewFocus:webView()];
81 }
82
83 void WebChromeClientIOS::runJavaScriptAlert(Frame* frame, const WTF::String& message)
84 {
85     WebThreadLockPushModal();
86     [[webView() _UIDelegateForwarder] webView:webView() runJavaScriptAlertPanelWithMessage:message initiatedByFrame:kit(frame)];
87     WebThreadLockPopModal();
88 }
89
90 bool WebChromeClientIOS::runJavaScriptConfirm(Frame* frame, const WTF::String& message)
91 {
92     WebThreadLockPushModal();
93     bool result = [[webView() _UIDelegateForwarder] webView:webView() runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:kit(frame)];
94     WebThreadLockPopModal();
95     return result;
96 }
97
98 bool WebChromeClientIOS::runJavaScriptPrompt(Frame* frame, const WTF::String& prompt, const WTF::String& defaultText, WTF::String& result)
99 {
100     WebThreadLockPushModal();
101     result = [[webView() _UIDelegateForwarder] webView:webView() runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText initiatedByFrame:kit(frame)];
102     WebThreadLockPopModal();
103     return !result.isNull();
104 }
105
106 void WebChromeClientIOS::runOpenPanel(Frame*, PassRefPtr<FileChooser> chooser)
107 {
108     const FileChooserSettings& settings = chooser->settings();
109     BOOL allowMultipleFiles = settings.allowsMultipleFiles;
110     Vector<String> acceptMIMETypes = settings.acceptMIMETypes;
111     WebOpenPanelResultListener *listener = [[WebOpenPanelResultListener alloc] initWithChooser:chooser];
112
113     // Convert the accept attribute string into a list of MIME types.
114     size_t numMIMETypes = acceptMIMETypes.size();
115     NSMutableArray *mimeTypes = [NSMutableArray arrayWithCapacity:numMIMETypes];
116     for (size_t i = 0; i < numMIMETypes; ++i)
117         [mimeTypes addObject:acceptMIMETypes[i]];
118
119     if (WebThreadIsCurrent()) {
120         dispatch_async(dispatch_get_main_queue(), ^{
121             [[webView() _UIKitDelegateForwarder] webView:webView() runOpenPanelForFileButtonWithResultListener:listener allowMultipleFiles:allowMultipleFiles acceptMIMETypes:mimeTypes];
122         });
123     } else
124         [[webView() _UIKitDelegateForwarder] webView:webView() runOpenPanelForFileButtonWithResultListener:listener allowMultipleFiles:allowMultipleFiles acceptMIMETypes:mimeTypes];
125
126     [listener release];
127 }
128
129 #if ENABLE(IOS_TOUCH_EVENTS)
130 void WebChromeClientIOS::didPreventDefaultForEvent()
131 {
132     [[webView() _UIKitDelegateForwarder] webViewDidPreventDefaultForEvent:webView()];
133 }
134 #endif
135
136 void WebChromeClientIOS::didReceiveMobileDocType(bool isMobileDoctype)
137 {
138     if (isMobileDoctype)
139         [[webView() _UIKitDelegateForwarder] webViewDidReceiveMobileDocType:webView()];
140 }
141
142 void WebChromeClientIOS::setNeedsScrollNotifications(WebCore::Frame* frame, bool flag)
143 {
144     [[webView() _UIKitDelegateForwarder] webView:webView() needsScrollNotifications:[NSNumber numberWithBool:flag] forFrame:kit(frame)];
145 }
146
147 void WebChromeClientIOS::observedContentChange(WebCore::Frame* frame)
148 {
149     [[webView() _UIKitDelegateForwarder] webView:webView() didObserveDeferredContentChange:WKObservedContentChange() forFrame:kit(frame)];
150 }
151
152 void WebChromeClientIOS::clearContentChangeObservers(WebCore::Frame* frame)
153 {
154     ASSERT(WebThreadCountOfObservedContentModifiers() > 0);
155     if (WebThreadCountOfObservedContentModifiers() > 0) {
156         WebThreadClearObservedContentModifiers();
157         observedContentChange(frame);
158     }        
159 }
160
161 static inline NSDictionary* dictionaryForViewportArguments(const WebCore::ViewportArguments& arguments)
162 {
163     return @{ @"initial-scale":@(arguments.zoom),
164               @"minimum-scale":@(arguments.minZoom),
165               @"maximum-scale":@(arguments.maxZoom),
166               @"user-scalable":@(arguments.userZoom),
167               @"shrink-to-fit":@(arguments.shrinkToFit),
168               @"width":@(arguments.width),
169               @"height":@(arguments.height) };
170 }
171
172 FloatSize WebChromeClientIOS::screenSize() const
173 {
174     return FloatSize(screenSize());
175 }
176
177 FloatSize WebChromeClientIOS::availableScreenSize() const
178 {
179     // WebKit1 code should query the WAKWindow for the available screen size.
180     ASSERT_NOT_REACHED();
181     return FloatSize();
182 }
183
184 void WebChromeClientIOS::dispatchViewportPropertiesDidChange(const WebCore::ViewportArguments& arguments) const
185 {
186     [[webView() _UIKitDelegateForwarder] webView:webView() didReceiveViewportArguments:dictionaryForViewportArguments(arguments)];
187 }
188
189 void WebChromeClientIOS::notifyRevealedSelectionByScrollingFrame(WebCore::Frame* frame)
190 {
191     [[webView() _UIKitDelegateForwarder] revealedSelectionByScrollingWebFrame:kit(frame)];
192 }
193
194 bool WebChromeClientIOS::isStopping()
195 {
196     return [webView() _isStopping];
197 }
198
199 void WebChromeClientIOS::didLayout(LayoutType changeType)
200 {
201     [[webView() _UIKitDelegate] webThreadWebViewDidLayout:webView() byScrolling:(changeType == ChromeClient::Scroll)];
202 }
203
204 void WebChromeClientIOS::didStartOverflowScroll()
205 {
206     [[[webView() _UIKitDelegateForwarder] asyncForwarder] webViewDidStartOverflowScroll:webView()];
207 }
208
209 void WebChromeClientIOS::didEndOverflowScroll()
210 {
211     [[[webView() _UIKitDelegateForwarder] asyncForwarder] webViewDidEndOverflowScroll:webView()];
212 }
213
214 void WebChromeClientIOS::suppressFormNotifications() 
215 {
216     m_formNotificationSuppressions++;
217 }
218
219 void WebChromeClientIOS::restoreFormNotifications() 
220 {
221     m_formNotificationSuppressions--;
222     ASSERT(m_formNotificationSuppressions >= 0);
223     if (m_formNotificationSuppressions < 0)
224         m_formNotificationSuppressions = 0;
225 }
226
227 void WebChromeClientIOS::elementDidFocus(const WebCore::Node* node)
228 {
229     if (m_formNotificationSuppressions <= 0)
230         [[webView() _UIKitDelegateForwarder] webView:webView() elementDidFocusNode:kit(const_cast<WebCore::Node*>(node))];
231 }
232
233 void WebChromeClientIOS::elementDidBlur(const WebCore::Node* node)
234 {
235     if (m_formNotificationSuppressions <= 0)
236         [[webView() _UIKitDelegateForwarder] webView:webView() elementDidBlurNode:kit(const_cast<WebCore::Node*>(node))];
237 }
238
239 bool WebChromeClientIOS::selectItemWritingDirectionIsNatural()
240 {
241     return false;
242 }
243
244 bool WebChromeClientIOS::selectItemAlignmentFollowsMenuWritingDirection()
245 {
246     return true;
247 }
248
249 RefPtr<WebCore::PopupMenu> WebChromeClientIOS::createPopupMenu(WebCore::PopupMenuClient* client) const
250 {
251     return adoptRef(new PopupMenuIOS(client));
252 }
253
254 RefPtr<WebCore::SearchPopupMenu> WebChromeClientIOS::createSearchPopupMenu(WebCore::PopupMenuClient* client) const
255 {
256     return adoptRef(new SearchPopupMenuIOS(client));
257 }
258
259 void WebChromeClientIOS::attachRootGraphicsLayer(Frame*, GraphicsLayer* graphicsLayer)
260 {
261     // FIXME: for non-root frames we rely on RenderView positioning the root layer,
262     // which is a hack. <rdar://problem/5906146>
263     // Send the delegate message on the web thread to avoid <rdar://problem/8567677>
264     [[webView() _UIKitDelegate] _webthread_webView:webView() attachRootLayer:graphicsLayer ? graphicsLayer->platformLayer() : 0];
265 }
266
267 void WebChromeClientIOS::didFlushCompositingLayers()
268 {
269     [[[webView() _UIKitDelegateForwarder] asyncForwarder] webViewDidCommitCompositingLayerChanges:webView()];
270 }
271
272 bool WebChromeClientIOS::fetchCustomFixedPositionLayoutRect(IntRect& rect)
273 {
274     NSRect updatedRect;
275     if ([webView() _fetchCustomFixedPositionLayoutRect:&updatedRect]) {
276         rect = enclosingIntRect(updatedRect);
277         return true;
278     }
279
280     return false;
281 }
282
283 void WebChromeClientIOS::updateViewportConstrainedLayers(HashMap<PlatformLayer*, std::unique_ptr<ViewportConstraints>>& layerMap, HashMap<PlatformLayer*, PlatformLayer*>& stickyContainers)
284 {
285     [[webView() _fixedPositionContent] setViewportConstrainedLayers:layerMap stickyContainerMap:stickyContainers];
286 }
287
288 void WebChromeClientIOS::addOrUpdateScrollingLayer(Node* node, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer, const IntSize& scrollSize, bool allowHorizontalScrollbar, bool allowVerticalScrollbar)
289 {
290     DOMNode *domNode = kit(node);
291
292     [[[webView() _UIKitDelegateForwarder] asyncForwarder] webView:webView() didCreateOrUpdateScrollingLayer:scrollingLayer withContentsLayer:contentsLayer scrollSize:[NSValue valueWithSize:scrollSize] forNode:domNode
293         allowHorizontalScrollbar:allowHorizontalScrollbar allowVerticalScrollbar:allowVerticalScrollbar];
294 }
295
296 void WebChromeClientIOS::removeScrollingLayer(Node* node, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer)
297 {
298     DOMNode *domNode = kit(node);
299     [[[webView() _UIKitDelegateForwarder] asyncForwarder] webView:webView() willRemoveScrollingLayer:scrollingLayer withContentsLayer:contentsLayer forNode:domNode];
300 }
301
302 void WebChromeClientIOS::webAppOrientationsUpdated()
303 {
304     [[webView() _UIDelegateForwarder] webViewSupportedOrientationsUpdated:webView()];
305 }
306
307 void WebChromeClientIOS::focusedElementChanged(Element* element)
308 {
309     if (!is<HTMLInputElement>(element))
310         return;
311
312     HTMLInputElement& inputElement = downcast<HTMLInputElement>(*element);
313     if (!inputElement.isText())
314         return;
315
316     CallFormDelegate(webView(), @selector(didFocusTextField:inFrame:), kit(&inputElement), kit(inputElement.document().frame()));
317 }
318
319 void WebChromeClientIOS::showPlaybackTargetPicker(bool hasVideo)
320 {
321     CGPoint point = [[webView() _UIKitDelegateForwarder] interactionLocation];
322     CGRect elementRect = [[webView() mainFrame] elementRectAtPoint:point];
323     [[webView() _UIKitDelegateForwarder] showPlaybackTargetPicker:hasVideo fromRect:elementRect];
324 }
325
326 #if ENABLE(ORIENTATION_EVENTS)
327 int WebChromeClientIOS::deviceOrientation() const
328 {
329     return [[webView() _UIKitDelegateForwarder] deviceOrientation];
330 }
331 #endif
332
333 #endif // PLATFORM(IOS)