Add MSE logging configuration
[WebKit-https.git] / Source / WebKitLegacy / mac / WebCoreSupport / WebChromeClient.mm
1 /*
2  * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
3  * Copyright (C) 2008, 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  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #import "WebChromeClient.h"
31
32 #import "DOMElementInternal.h"
33 #import "DOMHTMLInputElementInternal.h"
34 #import "DOMNodeInternal.h"
35 #import "PopupMenuMac.h"
36 #import "SearchPopupMenuMac.h"
37 #import "WebBasePluginPackage.h"
38 #import "WebDefaultUIDelegate.h"
39 #import "WebDelegateImplementationCaching.h"
40 #import "WebElementDictionary.h"
41 #import "WebFormDelegate.h"
42 #import "WebFrameInternal.h"
43 #import "WebFrameView.h"
44 #import "WebHTMLViewInternal.h"
45 #import "WebHistoryInternal.h"
46 #import "WebKitFullScreenListener.h"
47 #import "WebKitPrefix.h"
48 #import "WebNSURLRequestExtras.h"
49 #import "WebOpenPanelResultListener.h"
50 #import "WebPlugin.h"
51 #import "WebQuotaManager.h"
52 #import "WebSecurityOriginInternal.h"
53 #import "WebSelectionServiceController.h"
54 #import "WebUIDelegatePrivate.h"
55 #import "WebView.h"
56 #import "WebViewInternal.h"
57 #import <Foundation/Foundation.h>
58 #import <WebCore/ColorChooser.h>
59 #import <WebCore/ContextMenu.h>
60 #import <WebCore/ContextMenuController.h>
61 #import <WebCore/Cursor.h>
62 #import <WebCore/DataListSuggestionPicker.h>
63 #import <WebCore/DeprecatedGlobalSettings.h>
64 #import <WebCore/Element.h>
65 #import <WebCore/FileChooser.h>
66 #import <WebCore/FileIconLoader.h>
67 #import <WebCore/FloatRect.h>
68 #import <WebCore/Frame.h>
69 #import <WebCore/FrameLoadRequest.h>
70 #import <WebCore/FrameView.h>
71 #import <WebCore/GraphicsLayer.h>
72 #import <WebCore/HTMLInputElement.h>
73 #import <WebCore/HTMLNames.h>
74 #import <WebCore/HTMLPlugInImageElement.h>
75 #import <WebCore/HitTestResult.h>
76 #import <WebCore/Icon.h>
77 #import <WebCore/IntPoint.h>
78 #import <WebCore/IntRect.h>
79 #import <WebCore/NavigationAction.h>
80 #import <WebCore/NotImplemented.h>
81 #import <WebCore/Page.h>
82 #import <WebCore/PlatformScreen.h>
83 #import <WebCore/ResourceRequest.h>
84 #import <WebCore/SSLKeyGenerator.h>
85 #import <WebCore/SerializedCryptoKeyWrap.h>
86 #import <WebCore/Widget.h>
87 #import <WebCore/WindowFeatures.h>
88 #import <pal/spi/mac/NSViewSPI.h>
89 #import <wtf/BlockObjCExceptions.h>
90 #import <wtf/RefPtr.h>
91 #import <wtf/Vector.h>
92 #import <wtf/text/WTFString.h>
93
94 #if USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
95 #import "NetscapePluginHostManager.h"
96 #endif
97
98 #if PLATFORM(IOS_FAMILY) && ENABLE(GEOLOCATION)
99 #import <WebCore/Geolocation.h>
100 #endif
101
102 #if ENABLE(POINTER_LOCK)
103 #import <WebCore/PointerLockController.h>
104 #endif
105
106 #if PLATFORM(IOS_FAMILY)
107 #import <WebCore/WAKClipView.h>
108 #import <WebCore/WAKWindow.h>
109 #import <WebCore/WebCoreThreadMessage.h>
110 #endif
111
112 NSString *WebConsoleMessageXMLMessageSource = @"XMLMessageSource";
113 NSString *WebConsoleMessageJSMessageSource = @"JSMessageSource";
114 NSString *WebConsoleMessageNetworkMessageSource = @"NetworkMessageSource";
115 NSString *WebConsoleMessageConsoleAPIMessageSource = @"ConsoleAPIMessageSource";
116 NSString *WebConsoleMessageStorageMessageSource = @"StorageMessageSource";
117 NSString *WebConsoleMessageAppCacheMessageSource = @"AppCacheMessageSource";
118 NSString *WebConsoleMessageRenderingMessageSource = @"RenderingMessageSource";
119 NSString *WebConsoleMessageCSSMessageSource = @"CSSMessageSource";
120 NSString *WebConsoleMessageSecurityMessageSource = @"SecurityMessageSource";
121 NSString *WebConsoleMessageContentBlockerMessageSource = @"ContentBlockerMessageSource";
122 NSString *WebConsoleMessageOtherMessageSource = @"OtherMessageSource";
123 NSString *WebConsoleMessageMediaMessageSource = @"MediaMessageSource";
124 NSString *WebConsoleMessageWebRTCMessageSource = @"WebRTCMessageSource";
125 NSString *WebConsoleMessageMediaSourceMessageSource = @"MediaSourceMessageSource";
126
127 NSString *WebConsoleMessageDebugMessageLevel = @"DebugMessageLevel";
128 NSString *WebConsoleMessageLogMessageLevel = @"LogMessageLevel";
129 NSString *WebConsoleMessageInfoMessageLevel = @"InfoMessageLevel";
130 NSString *WebConsoleMessageWarningMessageLevel = @"WarningMessageLevel";
131 NSString *WebConsoleMessageErrorMessageLevel = @"ErrorMessageLevel";
132
133
134 #if !PLATFORM(IOS_FAMILY)
135 @interface NSApplication (WebNSApplicationDetails)
136 - (NSCursor *)_cursorRectCursor;
137 @end
138 #endif
139
140 // For compatibility with old SPI.
141 @interface NSView (WebOldWebKitPlugInDetails)
142 - (void)setIsSelected:(BOOL)isSelected;
143 @end
144
145 using namespace WebCore;
146 using namespace HTMLNames;
147
148 WebChromeClient::WebChromeClient(WebView *webView) 
149     : m_webView(webView)
150 {
151 }
152
153 void WebChromeClient::chromeDestroyed()
154 {
155     delete this;
156 }
157
158 // These functions scale between window and WebView coordinates because JavaScript/DOM operations 
159 // assume that the WebView and the window share the same coordinate system.
160
161 void WebChromeClient::setWindowRect(const FloatRect& rect)
162 {
163 #if !PLATFORM(IOS_FAMILY)
164     NSRect windowRect = toDeviceSpace(rect, [m_webView window]);
165     [[m_webView _UIDelegateForwarder] webView:m_webView setFrame:windowRect];
166 #endif
167 }
168
169 FloatRect WebChromeClient::windowRect()
170 {
171 #if !PLATFORM(IOS_FAMILY)
172     NSRect windowRect = [[m_webView _UIDelegateForwarder] webViewFrame:m_webView];
173     return toUserSpace(windowRect, [m_webView window]);
174 #else
175     return FloatRect();
176 #endif
177 }
178
179 // FIXME: We need to add API for setting and getting this.
180 FloatRect WebChromeClient::pageRect()
181 {
182     return [m_webView frame];
183 }
184
185 void WebChromeClient::focus()
186 {
187     [[m_webView _UIDelegateForwarder] webViewFocus:m_webView];
188 }
189
190 void WebChromeClient::unfocus()
191 {
192     [[m_webView _UIDelegateForwarder] webViewUnfocus:m_webView];
193 }
194
195 bool WebChromeClient::canTakeFocus(FocusDirection)
196 {
197     // There's unfortunately no way to determine if we will become first responder again
198     // once we give it up, so we just have to guess that we won't.
199     return true;
200 }
201
202 void WebChromeClient::takeFocus(FocusDirection direction)
203 {
204 #if !PLATFORM(IOS_FAMILY)
205     if (direction == FocusDirectionForward) {
206         // Since we're trying to move focus out of m_webView, and because
207         // m_webView may contain subviews within it, we ask it for the next key
208         // view of the last view in its key view loop. This makes m_webView
209         // behave as if it had no subviews, which is the behavior we want.
210         NSView *lastView = [m_webView _findLastViewInKeyViewLoop];
211         // avoid triggering assertions if the WebView is the only thing in the key loop
212         if ([m_webView _becomingFirstResponderFromOutside] && m_webView == [lastView nextValidKeyView])
213             return;
214         [[m_webView window] selectKeyViewFollowingView:lastView];
215     } else {
216         // avoid triggering assertions if the WebView is the only thing in the key loop
217         if ([m_webView _becomingFirstResponderFromOutside] && m_webView == [m_webView previousValidKeyView])
218             return;
219         [[m_webView window] selectKeyViewPrecedingView:m_webView];
220     }
221 #endif
222 }
223
224 void WebChromeClient::focusedElementChanged(Element* element)
225 {
226     if (!is<HTMLInputElement>(element))
227         return;
228
229     auto& inputElement = downcast<HTMLInputElement>(*element);
230     if (!inputElement.isText())
231         return;
232
233     CallFormDelegate(m_webView, @selector(didFocusTextField:inFrame:), kit(&inputElement), kit(inputElement.document().frame()));
234 }
235
236 void WebChromeClient::focusedFrameChanged(Frame*)
237 {
238 }
239
240 Page* WebChromeClient::createWindow(Frame& frame, const FrameLoadRequest&, const WindowFeatures& features, const NavigationAction&)
241 {
242     id delegate = [m_webView UIDelegate];
243     WebView *newWebView;
244
245 #if ENABLE(FULLSCREEN_API)
246     if (frame.document() && frame.document()->webkitCurrentFullScreenElement())
247         frame.document()->webkitCancelFullScreen();
248 #endif
249     
250     if ([delegate respondsToSelector:@selector(webView:createWebViewWithRequest:windowFeatures:)]) {
251         NSNumber *x = features.x ? [[NSNumber alloc] initWithFloat:*features.x] : nil;
252         NSNumber *y = features.y ? [[NSNumber alloc] initWithFloat:*features.y] : nil;
253         NSNumber *width = features.width ? [[NSNumber alloc] initWithFloat:*features.width] : nil;
254         NSNumber *height = features.height ? [[NSNumber alloc] initWithFloat:*features.height] : nil;
255         NSNumber *menuBarVisible = [[NSNumber alloc] initWithBool:features.menuBarVisible];
256         NSNumber *statusBarVisible = [[NSNumber alloc] initWithBool:features.statusBarVisible];
257         NSNumber *toolBarVisible = [[NSNumber alloc] initWithBool:features.toolBarVisible];
258         NSNumber *scrollbarsVisible = [[NSNumber alloc] initWithBool:features.scrollbarsVisible];
259         NSNumber *resizable = [[NSNumber alloc] initWithBool:features.resizable];
260         NSNumber *fullscreen = [[NSNumber alloc] initWithBool:features.fullscreen];
261         NSNumber *dialog = [[NSNumber alloc] initWithBool:features.dialog];
262         
263         NSMutableDictionary *dictFeatures = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
264                                              menuBarVisible, @"menuBarVisible", 
265                                              statusBarVisible, @"statusBarVisible",
266                                              toolBarVisible, @"toolBarVisible",
267                                              scrollbarsVisible, @"scrollbarsVisible",
268                                              resizable, @"resizable",
269                                              fullscreen, @"fullscreen",
270                                              dialog, @"dialog",
271                                              nil];
272         
273         if (x)
274             [dictFeatures setObject:x forKey:@"x"];
275         if (y)
276             [dictFeatures setObject:y forKey:@"y"];
277         if (width)
278             [dictFeatures setObject:width forKey:@"width"];
279         if (height)
280             [dictFeatures setObject:height forKey:@"height"];
281         
282         newWebView = CallUIDelegate(m_webView, @selector(webView:createWebViewWithRequest:windowFeatures:), nil, dictFeatures);
283         
284         [dictFeatures release];
285         [x release];
286         [y release];
287         [width release];
288         [height release];
289         [menuBarVisible release];
290         [statusBarVisible release];
291         [toolBarVisible release];
292         [scrollbarsVisible release];
293         [resizable release];
294         [fullscreen release];
295         [dialog release];
296     } else if (features.dialog && [delegate respondsToSelector:@selector(webView:createWebViewModalDialogWithRequest:)]) {
297         newWebView = CallUIDelegate(m_webView, @selector(webView:createWebViewModalDialogWithRequest:), nil);
298     } else {
299         newWebView = CallUIDelegate(m_webView, @selector(webView:createWebViewWithRequest:), nil);
300     }
301
302 #if USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
303     if (newWebView)
304         WebKit::NetscapePluginHostManager::singleton().didCreateWindow();
305 #endif
306     
307     return core(newWebView);
308 }
309
310 void WebChromeClient::show()
311 {
312     [[m_webView _UIDelegateForwarder] webViewShow:m_webView];
313 }
314
315 bool WebChromeClient::canRunModal()
316 {
317     return [[m_webView UIDelegate] respondsToSelector:@selector(webViewRunModal:)];
318 }
319
320 void WebChromeClient::runModal()
321 {
322     CallUIDelegate(m_webView, @selector(webViewRunModal:));
323 }
324
325 void WebChromeClient::setToolbarsVisible(bool b)
326 {
327     [[m_webView _UIDelegateForwarder] webView:m_webView setToolbarsVisible:b];
328 }
329
330 bool WebChromeClient::toolbarsVisible()
331 {
332     return CallUIDelegateReturningBoolean(NO, m_webView, @selector(webViewAreToolbarsVisible:));
333 }
334
335 void WebChromeClient::setStatusbarVisible(bool b)
336 {
337     [[m_webView _UIDelegateForwarder] webView:m_webView setStatusBarVisible:b];
338 }
339
340 bool WebChromeClient::statusbarVisible()
341 {
342     return CallUIDelegateReturningBoolean(NO, m_webView, @selector(webViewIsStatusBarVisible:));
343 }
344
345 void WebChromeClient::setScrollbarsVisible(bool b)
346 {
347     [[[m_webView mainFrame] frameView] setAllowsScrolling:b];
348 }
349
350 bool WebChromeClient::scrollbarsVisible()
351 {
352     return [[[m_webView mainFrame] frameView] allowsScrolling];
353 }
354
355 void WebChromeClient::setMenubarVisible(bool)
356 {
357     // The menubar is always visible in Mac OS X.
358     return;
359 }
360
361 bool WebChromeClient::menubarVisible()
362 {
363     // The menubar is always visible in Mac OS X.
364     return true;
365 }
366
367 void WebChromeClient::setResizable(bool b)
368 {
369     [[m_webView _UIDelegateForwarder] webView:m_webView setResizable:b];
370 }
371
372 inline static NSString *stringForMessageSource(MessageSource source)
373 {
374     switch (source) {
375     case MessageSource::XML:
376         return WebConsoleMessageXMLMessageSource;
377     case MessageSource::JS:
378         return WebConsoleMessageJSMessageSource;
379     case MessageSource::Network:
380         return WebConsoleMessageNetworkMessageSource;
381     case MessageSource::ConsoleAPI:
382         return WebConsoleMessageConsoleAPIMessageSource;
383     case MessageSource::Storage:
384         return WebConsoleMessageStorageMessageSource;
385     case MessageSource::AppCache:
386         return WebConsoleMessageAppCacheMessageSource;
387     case MessageSource::Rendering:
388         return WebConsoleMessageRenderingMessageSource;
389     case MessageSource::CSS:
390         return WebConsoleMessageCSSMessageSource;
391     case MessageSource::Security:
392         return WebConsoleMessageSecurityMessageSource;
393     case MessageSource::ContentBlocker:
394         return WebConsoleMessageContentBlockerMessageSource;
395     case MessageSource::Other:
396         return WebConsoleMessageOtherMessageSource;
397     case MessageSource::Media:
398         return WebConsoleMessageMediaMessageSource;
399     case MessageSource::WebRTC:
400         return WebConsoleMessageWebRTCMessageSource;
401     case MessageSource::MediaSource:
402         return WebConsoleMessageMediaSourceMessageSource;
403     }
404     ASSERT_NOT_REACHED();
405     return @"";
406 }
407
408 inline static NSString *stringForMessageLevel(MessageLevel level)
409 {
410     switch (level) {
411     case MessageLevel::Debug:
412         return WebConsoleMessageDebugMessageLevel;
413     case MessageLevel::Log:
414         return WebConsoleMessageLogMessageLevel;
415     case MessageLevel::Info:
416         return WebConsoleMessageInfoMessageLevel;
417     case MessageLevel::Warning:
418         return WebConsoleMessageWarningMessageLevel;
419     case MessageLevel::Error:
420         return WebConsoleMessageErrorMessageLevel;
421     }
422     ASSERT_NOT_REACHED();
423     return @"";
424 }
425
426 void WebChromeClient::addMessageToConsole(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, unsigned columnNumber, const String& sourceURL)
427 {
428 #if !PLATFORM(IOS_FAMILY)
429     id delegate = [m_webView UIDelegate];
430 #else
431     if (![m_webView _allowsMessaging])
432         return;
433
434     id delegate = [m_webView _UIKitDelegate];
435     // No delegate means nothing to send this data to so bail.
436     if (!delegate)
437         return;
438 #endif
439
440     BOOL respondsToNewSelector = NO;
441
442     SEL selector = @selector(webView:addMessageToConsole:withSource:);
443     if ([delegate respondsToSelector:selector])
444         respondsToNewSelector = YES;
445     else {
446         // The old selector only takes JSMessageSource messages.
447         if (source != MessageSource::JS)
448             return;
449         selector = @selector(webView:addMessageToConsole:);
450         if (![delegate respondsToSelector:selector])
451             return;
452     }
453
454     NSString *messageSource = stringForMessageSource(source);
455     NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
456         (NSString *)message, @"message",
457         [NSNumber numberWithUnsignedInt:lineNumber], @"lineNumber",
458         [NSNumber numberWithUnsignedInt:columnNumber], @"columnNumber",
459         (NSString *)sourceURL, @"sourceURL",
460         messageSource, @"MessageSource",
461         stringForMessageLevel(level), @"MessageLevel",
462         NULL];
463
464 #if PLATFORM(IOS_FAMILY)
465     [[[m_webView _UIKitDelegateForwarder] asyncForwarder] webView:m_webView addMessageToConsole:dictionary withSource:messageSource];
466 #else
467     if (respondsToNewSelector)
468         CallUIDelegate(m_webView, selector, dictionary, messageSource);
469     else
470         CallUIDelegate(m_webView, selector, dictionary);
471 #endif
472
473     [dictionary release];
474 }
475
476 bool WebChromeClient::canRunBeforeUnloadConfirmPanel()
477 {
478     return [[m_webView UIDelegate] respondsToSelector:@selector(webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:)];
479 }
480
481 bool WebChromeClient::runBeforeUnloadConfirmPanel(const String& message, Frame& frame)
482 {
483     return CallUIDelegateReturningBoolean(true, m_webView, @selector(webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:), message, kit(&frame));
484 }
485
486 void WebChromeClient::closeWindowSoon()
487 {
488     // We need to remove the parent WebView from WebViewSets here, before it actually
489     // closes, to make sure that JavaScript code that executes before it closes
490     // can't find it. Otherwise, window.open will select a closed WebView instead of 
491     // opening a new one <rdar://problem/3572585>.
492
493     // We also need to stop the load to prevent further parsing or JavaScript execution
494     // after the window has torn down <rdar://problem/4161660>.
495   
496     // FIXME: This code assumes that the UI delegate will respond to a webViewClose
497     // message by actually closing the WebView. Safari guarantees this behavior, but other apps might not.
498     // This approach is an inherent limitation of not making a close execute immediately
499     // after a call to window.close.
500
501     [m_webView setGroupName:nil];
502     [m_webView stopLoading:nil];
503     [m_webView performSelector:@selector(_closeWindow) withObject:nil afterDelay:0.0];
504 }
505
506 void WebChromeClient::runJavaScriptAlert(Frame& frame, const String& message)
507 {
508     id delegate = [m_webView UIDelegate];
509     SEL selector = @selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:);
510     if ([delegate respondsToSelector:selector]) {
511         CallUIDelegate(m_webView, selector, message, kit(&frame));
512         return;
513     }
514
515     // Call the old version of the delegate method if it is implemented.
516     selector = @selector(webView:runJavaScriptAlertPanelWithMessage:);
517     if ([delegate respondsToSelector:selector]) {
518         CallUIDelegate(m_webView, selector, message);
519         return;
520     }
521 }
522
523 bool WebChromeClient::runJavaScriptConfirm(Frame& frame, const String& message)
524 {
525     id delegate = [m_webView UIDelegate];
526     SEL selector = @selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:);
527     if ([delegate respondsToSelector:selector])
528         return CallUIDelegateReturningBoolean(NO, m_webView, selector, message, kit(&frame));
529
530     // Call the old version of the delegate method if it is implemented.
531     selector = @selector(webView:runJavaScriptConfirmPanelWithMessage:);
532     if ([delegate respondsToSelector:selector])
533         return CallUIDelegateReturningBoolean(NO, m_webView, selector, message);
534
535     return NO;
536 }
537
538 bool WebChromeClient::runJavaScriptPrompt(Frame& frame, const String& prompt, const String& defaultText, String& result)
539 {
540     id delegate = [m_webView UIDelegate];
541     SEL selector = @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:);
542     NSString *defaultString = defaultText;
543     if ([delegate respondsToSelector:selector]) {
544         result = (NSString *)CallUIDelegate(m_webView, selector, prompt, defaultString, kit(&frame));
545         return !result.isNull();
546     }
547
548     // Call the old version of the delegate method if it is implemented.
549     selector = @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:);
550     if ([delegate respondsToSelector:selector]) {
551         result = (NSString *)CallUIDelegate(m_webView, selector, prompt, defaultString);
552         return !result.isNull();
553     }
554
555     result = [[WebDefaultUIDelegate sharedUIDelegate] webView:m_webView runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultString initiatedByFrame:kit(&frame)];
556     return !result.isNull();
557 }
558
559 void WebChromeClient::setStatusbarText(const String& status)
560 {
561     // We want the temporaries allocated here to be released even before returning to the 
562     // event loop; see <http://bugs.webkit.org/show_bug.cgi?id=9880>.
563     @autoreleasepool {
564         CallUIDelegate(m_webView, @selector(webView:setStatusText:), (NSString *)status);
565     }
566 }
567
568 bool WebChromeClient::supportsImmediateInvalidation()
569 {
570     return true;
571 }
572
573 void WebChromeClient::invalidateRootView(const IntRect&)
574 {
575 }
576
577 void WebChromeClient::invalidateContentsAndRootView(const IntRect& rect)
578 {
579 }
580
581 void WebChromeClient::invalidateContentsForSlowScroll(const IntRect& rect)
582 {
583     invalidateContentsAndRootView(rect);
584 }
585
586 void WebChromeClient::scroll(const IntSize&, const IntRect&, const IntRect&)
587 {
588 }
589
590 IntPoint WebChromeClient::screenToRootView(const IntPoint& p) const
591 {
592     // FIXME: Implement this.
593     return p;
594 }
595
596 IntRect WebChromeClient::rootViewToScreen(const IntRect& r) const
597 {
598     // FIXME: Implement this.
599     return r;
600 }
601
602 IntPoint WebChromeClient::accessibilityScreenToRootView(const IntPoint& p) const
603 {
604     return screenToRootView(p);
605 }
606
607 IntRect WebChromeClient::rootViewToAccessibilityScreen(const IntRect& r) const
608 {
609     return rootViewToScreen(r);
610 }
611
612 PlatformPageClient WebChromeClient::platformPageClient() const
613 {
614     return 0;
615 }
616
617 void WebChromeClient::contentsSizeChanged(Frame&, const IntSize&) const
618 {
619 }
620
621 void WebChromeClient::scrollRectIntoView(const IntRect& r) const
622 {
623     // FIXME: This scrolling behavior should be under the control of the embedding client,
624     // perhaps in a delegate method, rather than something WebKit does unconditionally.
625     NSView *coordinateView = [[[m_webView mainFrame] frameView] documentView];
626     NSRect rect = r;
627     for (NSView *view = m_webView; view; view = [view superview]) {
628         if ([view isKindOfClass:[NSClipView class]]) {
629             NSClipView *clipView = (NSClipView *)view;
630             NSView *documentView = [clipView documentView];
631             [documentView scrollRectToVisible:[documentView convertRect:rect fromView:coordinateView]];
632         }
633     }
634 }
635
636 // End host window methods.
637
638 bool WebChromeClient::shouldUnavailablePluginMessageBeButton(RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason) const
639 {
640     if (pluginUnavailabilityReason == RenderEmbeddedObject::PluginMissing)
641         return [[m_webView UIDelegate] respondsToSelector:@selector(webView:didPressMissingPluginButton:)];
642
643     return false;
644 }
645
646 void WebChromeClient::unavailablePluginButtonClicked(Element& element, RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason) const
647 {
648     ASSERT(element.hasTagName(objectTag) || element.hasTagName(embedTag) || element.hasTagName(appletTag));
649
650     ASSERT(pluginUnavailabilityReason == RenderEmbeddedObject::PluginMissing);
651     CallUIDelegate(m_webView, @selector(webView:didPressMissingPluginButton:), kit(&element));
652 }
653
654 void WebChromeClient::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags)
655 {
656     WebElementDictionary *element = [[WebElementDictionary alloc] initWithHitTestResult:result];
657     [m_webView _mouseDidMoveOverElement:element modifierFlags:modifierFlags];
658     [element release];
659 }
660
661 void WebChromeClient::setToolTip(const String& toolTip, TextDirection)
662 {
663     NSView<WebDocumentView> *documentView = [[[m_webView _selectedOrMainFrame] frameView] documentView];
664     if ([documentView isKindOfClass:[WebHTMLView class]])
665         [(WebHTMLView *)documentView _setToolTip:toolTip];
666 }
667
668 void WebChromeClient::print(Frame& frame)
669 {
670     WebFrame *webFrame = kit(&frame);
671     if ([[m_webView UIDelegate] respondsToSelector:@selector(webView:printFrame:)])
672         CallUIDelegate(m_webView, @selector(webView:printFrame:), webFrame);
673     else
674         CallUIDelegate(m_webView, @selector(webView:printFrameView:), [webFrame frameView]);
675 }
676
677 void WebChromeClient::exceededDatabaseQuota(Frame& frame, const String& databaseName, DatabaseDetails)
678 {
679     BEGIN_BLOCK_OBJC_EXCEPTIONS;
680
681     WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:&frame.document()->securityOrigin()];
682     CallUIDelegate(m_webView, @selector(webView:frame:exceededDatabaseQuotaForSecurityOrigin:database:), kit(&frame), webOrigin, (NSString *)databaseName);
683     [webOrigin release];
684
685     END_BLOCK_OBJC_EXCEPTIONS;
686 }
687
688 void WebChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded)
689 {
690     // FIXME: Free some space.
691 }
692
693 void WebChromeClient::reachedApplicationCacheOriginQuota(SecurityOrigin& origin, int64_t totalSpaceNeeded)
694 {
695     BEGIN_BLOCK_OBJC_EXCEPTIONS;
696
697     WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:&origin];
698     CallUIDelegate(m_webView, @selector(webView:exceededApplicationCacheOriginQuotaForSecurityOrigin:totalSpaceNeeded:), webOrigin, static_cast<NSUInteger>(totalSpaceNeeded));
699     [webOrigin release];
700
701     END_BLOCK_OBJC_EXCEPTIONS;
702 }
703
704 #if ENABLE(DASHBOARD_SUPPORT)
705
706 void WebChromeClient::annotatedRegionsChanged()
707 {
708     BEGIN_BLOCK_OBJC_EXCEPTIONS;
709     CallUIDelegate(m_webView, @selector(webView:dashboardRegionsChanged:), [m_webView _dashboardRegions]);
710     END_BLOCK_OBJC_EXCEPTIONS;
711 }
712
713 #endif
714
715 #if ENABLE(INPUT_TYPE_COLOR)
716
717 std::unique_ptr<ColorChooser> WebChromeClient::createColorChooser(ColorChooserClient& client, const Color& initialColor)
718 {
719     // FIXME: Implement <input type='color'> for WK1 (Bug 119094).
720     ASSERT_NOT_REACHED();
721     return nullptr;
722 }
723
724 #endif
725
726 #if ENABLE(DATALIST_ELEMENT)
727 std::unique_ptr<DataListSuggestionPicker> WebChromeClient::createDataListSuggestionPicker(DataListSuggestionsClient& client)
728 {
729     ASSERT_NOT_REACHED();
730     return nullptr;
731 }
732 #endif
733
734 #if ENABLE(POINTER_LOCK)
735 bool WebChromeClient::requestPointerLock()
736 {
737 #if PLATFORM(MAC)
738     if (![m_webView page])
739         return false;
740
741     CGDisplayHideCursor(CGMainDisplayID());
742     CGAssociateMouseAndMouseCursorPosition(false);
743     [m_webView page]->pointerLockController().didAcquirePointerLock();
744     
745     return true;
746 #else
747     return false;
748 #endif
749 }
750
751 void WebChromeClient::requestPointerUnlock()
752 {
753 #if PLATFORM(MAC)
754     CGAssociateMouseAndMouseCursorPosition(true);
755     CGDisplayShowCursor(CGMainDisplayID());
756     if ([m_webView page])
757         [m_webView page]->pointerLockController().didLosePointerLock();
758 #endif
759 }
760 #endif
761
762 void WebChromeClient::runOpenPanel(Frame&, FileChooser& chooser)
763 {
764     BEGIN_BLOCK_OBJC_EXCEPTIONS;
765     BOOL allowMultipleFiles = chooser.settings().allowsMultipleFiles;
766     WebOpenPanelResultListener *listener = [[WebOpenPanelResultListener alloc] initWithChooser:chooser];
767     id delegate = [m_webView UIDelegate];
768     if ([delegate respondsToSelector:@selector(webView:runOpenPanelForFileButtonWithResultListener:allowMultipleFiles:)])
769         CallUIDelegate(m_webView, @selector(webView:runOpenPanelForFileButtonWithResultListener:allowMultipleFiles:), listener, allowMultipleFiles);
770     else if ([delegate respondsToSelector:@selector(webView:runOpenPanelForFileButtonWithResultListener:)])
771         CallUIDelegate(m_webView, @selector(webView:runOpenPanelForFileButtonWithResultListener:), listener);
772     else
773         [listener cancel];
774     [listener release];
775     END_BLOCK_OBJC_EXCEPTIONS;
776 }
777
778 void WebChromeClient::showShareSheet(ShareDataWithParsedURL&, CompletionHandler<void(bool)>&&)
779 {
780 }
781
782 void WebChromeClient::loadIconForFiles(const Vector<String>& filenames, FileIconLoader& iconLoader)
783 {
784     iconLoader.iconLoaded(createIconForFiles(filenames));
785 }
786
787 RefPtr<Icon> WebChromeClient::createIconForFiles(const Vector<String>& filenames)
788 {
789     return Icon::createIconForFiles(filenames);
790 }
791
792 #if !PLATFORM(IOS_FAMILY)
793
794 void WebChromeClient::setCursor(const WebCore::Cursor& cursor)
795 {
796     // FIXME: Would be nice to share this code with WebKit2's PageClientImpl.
797
798     if ([NSApp _cursorRectCursor])
799         return;
800
801     if (!m_webView)
802         return;
803
804     NSWindow *window = [m_webView window];
805     if (!window)
806         return;
807
808     if ([window windowNumber] != [NSWindow windowNumberAtPoint:[NSEvent mouseLocation] belowWindowWithWindowNumber:0])
809         return;
810
811     NSCursor *platformCursor = cursor.platformCursor();
812     if ([NSCursor currentCursor] == platformCursor)
813         return;
814
815     [platformCursor set];
816 }
817
818 void WebChromeClient::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
819 {
820     [NSCursor setHiddenUntilMouseMoves:hiddenUntilMouseMoves];
821 }
822
823 #endif
824
825 KeyboardUIMode WebChromeClient::keyboardUIMode()
826 {
827     BEGIN_BLOCK_OBJC_EXCEPTIONS;
828     return [m_webView _keyboardUIMode];
829     END_BLOCK_OBJC_EXCEPTIONS;
830     return KeyboardAccessDefault;
831 }
832
833 NSResponder *WebChromeClient::firstResponder()
834 {
835     BEGIN_BLOCK_OBJC_EXCEPTIONS;
836     return [[m_webView _UIDelegateForwarder] webViewFirstResponder:m_webView];
837     END_BLOCK_OBJC_EXCEPTIONS;
838     return nil;
839 }
840
841 void WebChromeClient::makeFirstResponder(NSResponder *responder)
842 {
843     BEGIN_BLOCK_OBJC_EXCEPTIONS;
844     [m_webView _pushPerformingProgrammaticFocus];
845     [[m_webView _UIDelegateForwarder] webView:m_webView makeFirstResponder:responder];
846     [m_webView _popPerformingProgrammaticFocus];
847     END_BLOCK_OBJC_EXCEPTIONS;
848 }
849
850 void WebChromeClient::enableSuddenTermination()
851 {
852 #if !PLATFORM(IOS_FAMILY)
853     [[NSProcessInfo processInfo] enableSuddenTermination];
854 #endif
855 }
856
857 void WebChromeClient::disableSuddenTermination()
858 {
859 #if !PLATFORM(IOS_FAMILY)
860     [[NSProcessInfo processInfo] disableSuddenTermination];
861 #endif
862 }
863
864 bool WebChromeClient::shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename)
865 {
866     NSString* filename;
867     if (![[m_webView _UIDelegateForwarder] webView:m_webView shouldReplaceUploadFile:path usingGeneratedFilename:&filename])
868         return false;
869     generatedFilename = filename;
870     return true;
871 }
872
873 String WebChromeClient::generateReplacementFile(const String& path)
874 {
875     return [[m_webView _UIDelegateForwarder] webView:m_webView generateReplacementFile:path];
876 }
877
878 #if !PLATFORM(IOS_FAMILY)
879 void WebChromeClient::elementDidFocus(WebCore::Element& element)
880 {
881     CallUIDelegate(m_webView, @selector(webView:formDidFocusNode:), kit(&element));
882 }
883
884 void WebChromeClient::elementDidBlur(WebCore::Element& element)
885 {
886     CallUIDelegate(m_webView, @selector(webView:formDidBlurNode:), kit(&element));
887 }
888 #endif
889
890 bool WebChromeClient::selectItemWritingDirectionIsNatural()
891 {
892     return false;
893 }
894
895 bool WebChromeClient::selectItemAlignmentFollowsMenuWritingDirection()
896 {
897     return true;
898 }
899
900 RefPtr<WebCore::PopupMenu> WebChromeClient::createPopupMenu(WebCore::PopupMenuClient& client) const
901 {
902 #if !PLATFORM(IOS_FAMILY)
903     return adoptRef(*new PopupMenuMac(&client));
904 #else
905     return nullptr;
906 #endif
907 }
908
909 RefPtr<WebCore::SearchPopupMenu> WebChromeClient::createSearchPopupMenu(WebCore::PopupMenuClient& client) const
910 {
911 #if !PLATFORM(IOS_FAMILY)
912     return adoptRef(*new SearchPopupMenuMac(&client));
913 #else
914     return nullptr;
915 #endif
916 }
917
918 bool WebChromeClient::shouldPaintEntireContents() const
919 {
920 #if PLATFORM(IOS_FAMILY)
921     return false;
922 #else
923     NSView *documentView = [[[m_webView mainFrame] frameView] documentView];
924     return [documentView layer];
925 #endif
926 }
927
928 void WebChromeClient::attachRootGraphicsLayer(Frame& frame, GraphicsLayer* graphicsLayer)
929 {
930 #if !PLATFORM(MAC)
931     UNUSED_PARAM(frame);
932     UNUSED_PARAM(graphicsLayer);
933 #else
934     BEGIN_BLOCK_OBJC_EXCEPTIONS;
935
936     NSView *documentView = [[kit(&frame) frameView] documentView];
937     if (![documentView isKindOfClass:[WebHTMLView class]]) {
938         // We should never be attaching when we don't have a WebHTMLView.
939         ASSERT(!graphicsLayer);
940         return;
941     }
942
943     WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
944     if (graphicsLayer)
945         [webHTMLView attachRootLayer:graphicsLayer->platformLayer()];
946     else
947         [webHTMLView detachRootLayer];
948     END_BLOCK_OBJC_EXCEPTIONS;
949 #endif
950 }
951
952 void WebChromeClient::attachViewOverlayGraphicsLayer(GraphicsLayer*)
953 {
954     // FIXME: If we want view-relative page overlays in Legacy WebKit, this would be the place to hook them up.
955 }
956
957 void WebChromeClient::setNeedsOneShotDrawingSynchronization()
958 {
959     BEGIN_BLOCK_OBJC_EXCEPTIONS;
960     [m_webView _setNeedsOneShotDrawingSynchronization:YES];
961     END_BLOCK_OBJC_EXCEPTIONS;
962 }
963
964 void WebChromeClient::scheduleCompositingLayerFlush()
965 {
966     BEGIN_BLOCK_OBJC_EXCEPTIONS;
967     [m_webView _scheduleCompositingLayerFlush];
968     END_BLOCK_OBJC_EXCEPTIONS;
969 }
970
971 #if ENABLE(VIDEO)
972
973 bool WebChromeClient::supportsVideoFullscreen(HTMLMediaElementEnums::VideoFullscreenMode)
974 {
975 #if PLATFORM(IOS_FAMILY)
976     if (!DeprecatedGlobalSettings::avKitEnabled())
977         return false;
978 #endif
979     return true;
980 }
981
982 void WebChromeClient::enterVideoFullscreenForVideoElement(HTMLVideoElement& videoElement, HTMLMediaElementEnums::VideoFullscreenMode mode, bool standby)
983 {
984     ASSERT_UNUSED(standby, !standby);
985     ASSERT(mode != HTMLMediaElementEnums::VideoFullscreenModeNone);
986     BEGIN_BLOCK_OBJC_EXCEPTIONS;
987     [m_webView _enterVideoFullscreenForVideoElement:&videoElement mode:mode];
988     END_BLOCK_OBJC_EXCEPTIONS;
989 }
990
991 void WebChromeClient::exitVideoFullscreenForVideoElement(WebCore::HTMLVideoElement&)
992 {
993     BEGIN_BLOCK_OBJC_EXCEPTIONS;
994     [m_webView _exitVideoFullscreen];
995     END_BLOCK_OBJC_EXCEPTIONS;    
996 }
997
998 void WebChromeClient::exitVideoFullscreenToModeWithoutAnimation(HTMLVideoElement& videoElement, HTMLMediaElementEnums::VideoFullscreenMode targetMode)
999 {
1000     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1001     [m_webView _exitVideoFullscreen];
1002     END_BLOCK_OBJC_EXCEPTIONS;
1003 }
1004
1005 #endif // ENABLE(VIDEO)
1006
1007 #if ENABLE(VIDEO) && PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
1008
1009 void WebChromeClient::setUpPlaybackControlsManager(HTMLMediaElement& element)
1010 {
1011     [m_webView _setUpPlaybackControlsManagerForMediaElement:element];
1012 }
1013
1014 void WebChromeClient::clearPlaybackControlsManager()
1015 {
1016     [m_webView _clearPlaybackControlsManager];
1017 }
1018
1019 #endif
1020
1021 #if ENABLE(FULLSCREEN_API)
1022
1023 bool WebChromeClient::supportsFullScreenForElement(const Element& element, bool withKeyboard)
1024 {
1025     SEL selector = @selector(webView:supportsFullScreenForElement:withKeyboard:);
1026     if ([[m_webView UIDelegate] respondsToSelector:selector])
1027         return CallUIDelegateReturningBoolean(false, m_webView, selector, kit(const_cast<WebCore::Element*>(&element)), withKeyboard);
1028 #if !PLATFORM(IOS_FAMILY)
1029     return [m_webView _supportsFullScreenForElement:const_cast<WebCore::Element*>(&element) withKeyboard:withKeyboard];
1030 #else
1031     return NO;
1032 #endif
1033 }
1034
1035 void WebChromeClient::enterFullScreenForElement(Element& element)
1036 {
1037     SEL selector = @selector(webView:enterFullScreenForElement:listener:);
1038     if ([[m_webView UIDelegate] respondsToSelector:selector]) {
1039         WebKitFullScreenListener* listener = [[WebKitFullScreenListener alloc] initWithElement:&element];
1040         CallUIDelegate(m_webView, selector, kit(&element), listener);
1041         [listener release];
1042     }
1043 #if !PLATFORM(IOS_FAMILY)
1044     else
1045         [m_webView _enterFullScreenForElement:&element];
1046 #endif
1047 }
1048
1049 void WebChromeClient::exitFullScreenForElement(Element* element)
1050 {
1051     SEL selector = @selector(webView:exitFullScreenForElement:listener:);
1052     if ([[m_webView UIDelegate] respondsToSelector:selector]) {
1053         WebKitFullScreenListener* listener = [[WebKitFullScreenListener alloc] initWithElement:element];
1054         CallUIDelegate(m_webView, selector, kit(element), listener);
1055         [listener release];
1056     }
1057 #if !PLATFORM(IOS_FAMILY)
1058     else
1059         [m_webView _exitFullScreenForElement:element];
1060 #endif
1061 }
1062
1063 #endif // ENABLE(FULLSCREEN_API)
1064
1065 #if ENABLE(WEB_CRYPTO)
1066
1067 bool WebChromeClient::wrapCryptoKey(const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey) const
1068 {
1069     Vector<uint8_t> masterKey;
1070     SEL selector = @selector(webCryptoMasterKeyForWebView:);
1071     if ([[m_webView UIDelegate] respondsToSelector:selector]) {
1072         NSData *keyData = CallUIDelegate(m_webView, selector);
1073         masterKey.append(static_cast<uint8_t*>(const_cast<void*>([keyData bytes])), [keyData length]);
1074     } else if (!getDefaultWebCryptoMasterKey(masterKey))
1075         return false;
1076
1077     return wrapSerializedCryptoKey(masterKey, key, wrappedKey);
1078 }
1079
1080 bool WebChromeClient::unwrapCryptoKey(const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key) const
1081 {
1082     Vector<uint8_t> masterKey;
1083     SEL selector = @selector(webCryptoMasterKeyForWebView:);
1084     if ([[m_webView UIDelegate] respondsToSelector:selector]) {
1085         NSData *keyData = CallUIDelegate(m_webView, selector);
1086         masterKey.append(static_cast<uint8_t*>(const_cast<void*>([keyData bytes])), [keyData length]);
1087     } else if (!getDefaultWebCryptoMasterKey(masterKey))
1088         return false;
1089
1090     return unwrapSerializedCryptoKey(masterKey, wrappedKey, key);
1091 }
1092
1093 #endif
1094
1095 #if ENABLE(SERVICE_CONTROLS)
1096
1097 void WebChromeClient::handleSelectionServiceClick(WebCore::FrameSelection& selection, const Vector<String>& telephoneNumbers, const WebCore::IntPoint& point)
1098 {
1099     [m_webView _selectionServiceController].handleSelectionServiceClick(selection, telephoneNumbers, point);
1100 }
1101
1102 bool WebChromeClient::hasRelevantSelectionServices(bool isTextOnly) const
1103 {
1104     return [m_webView _selectionServiceController].hasRelevantSelectionServices(isTextOnly);
1105 }
1106
1107 #endif
1108
1109 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
1110
1111 void WebChromeClient::addPlaybackTargetPickerClient(uint64_t contextId)
1112 {
1113     [m_webView _addPlaybackTargetPickerClient:contextId];
1114 }
1115
1116 void WebChromeClient::removePlaybackTargetPickerClient(uint64_t contextId)
1117 {
1118     [m_webView _removePlaybackTargetPickerClient:contextId];
1119 }
1120
1121 void WebChromeClient::showPlaybackTargetPicker(uint64_t contextId, const WebCore::IntPoint& location, bool hasVideo)
1122 {
1123     [m_webView _showPlaybackTargetPicker:contextId location:location hasVideo:hasVideo];
1124 }
1125
1126 void WebChromeClient::playbackTargetPickerClientStateDidChange(uint64_t contextId, MediaProducer::MediaStateFlags state)
1127 {
1128     [m_webView _playbackTargetPickerClientStateDidChange:contextId state:state];
1129 }
1130
1131 void WebChromeClient::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
1132 {
1133     [m_webView _setMockMediaPlaybackTargetPickerEnabled:enabled];
1134 }
1135
1136 void WebChromeClient::setMockMediaPlaybackTargetPickerState(const String& name, MediaPlaybackTargetContext::State state)
1137 {
1138     [m_webView _setMockMediaPlaybackTargetPickerName:name state:state];
1139 }
1140
1141 #endif
1142
1143 String WebChromeClient::signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String& challengeString, const URL& url) const
1144 {
1145     SEL selector = @selector(signedPublicKeyAndChallengeStringForWebView:);
1146     if ([[m_webView UIDelegate] respondsToSelector:selector])
1147         return CallUIDelegate(m_webView, selector);
1148     return WebCore::signedPublicKeyAndChallengeString(keySizeIndex, challengeString, url);
1149 }