Part 2 of removing PlatformString.h, remove PlatformString.h
[WebKit-https.git] / Source / WebKit / mac / WebCoreSupport / WebChromeClient.mm
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010 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 Computer, 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 "DOMNodeInternal.h"
34 #import "WebDefaultUIDelegate.h"
35 #import "WebDelegateImplementationCaching.h"
36 #import "WebElementDictionary.h"
37 #import "WebFrameInternal.h"
38 #import "WebFrameView.h"
39 #import "WebHTMLViewInternal.h"
40 #import "WebHistoryInternal.h"
41 #import "WebKitFullScreenListener.h"
42 #import "WebKitPrefix.h"
43 #import "WebKitSystemInterface.h"
44 #import "WebNSURLRequestExtras.h"
45 #import "WebOpenPanelResultListener.h"
46 #import "WebPlugin.h"
47 #import "WebQuotaManager.h"
48 #import "WebSecurityOriginInternal.h"
49 #import "WebUIDelegatePrivate.h"
50 #import "WebView.h"
51 #import "WebViewInternal.h"
52 #import <Foundation/Foundation.h>
53 #import <WebCore/BlockExceptions.h>
54 #import <WebCore/Console.h>
55 #import <WebCore/ContextMenu.h>
56 #import <WebCore/ContextMenuController.h>
57 #import <WebCore/Cursor.h>
58 #import <WebCore/Element.h>
59 #import <WebCore/FileChooser.h>
60 #import <WebCore/FileIconLoader.h>
61 #import <WebCore/FloatRect.h>
62 #import <WebCore/Frame.h>
63 #import <WebCore/FrameLoadRequest.h>
64 #import <WebCore/FrameView.h>
65 #import <WebCore/HTMLNames.h>
66 #import <WebCore/HitTestResult.h>
67 #import <WebCore/Icon.h>
68 #import <WebCore/IntPoint.h>
69 #import <WebCore/IntRect.h>
70 #import <WebCore/NavigationAction.h>
71 #import <WebCore/NotImplemented.h>
72 #import <WebCore/Page.h>
73 #import <WebCore/PlatformScreen.h>
74 #import <WebCore/PopupMenuMac.h>
75 #import <WebCore/ResourceRequest.h>
76 #import <WebCore/SearchPopupMenuMac.h>
77 #import <WebCore/Widget.h>
78 #import <WebCore/WindowFeatures.h>
79 #import <wtf/PassRefPtr.h>
80 #import <wtf/Vector.h>
81 #import <wtf/text/WTFString.h>
82
83 #if USE(ACCELERATED_COMPOSITING)
84 #import <WebCore/GraphicsLayer.h>
85 #endif
86
87 #if USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
88 #import "NetscapePluginHostManager.h"
89 #endif
90
91 NSString *WebConsoleMessageHTMLMessageSource = @"HTMLMessageSource";
92 NSString *WebConsoleMessageXMLMessageSource = @"XMLMessageSource";
93 NSString *WebConsoleMessageJSMessageSource = @"JSMessageSource";
94 NSString *WebConsoleMessageNetworkMessageSource = @"NetworkMessageSource";
95 NSString *WebConsoleMessageConsoleAPIMessageSource = @"ConsoleAPIMessageSource";
96 NSString *WebConsoleMessageOtherMessageSource = @"OtherMessageSource";
97
98 NSString *WebConsoleMessageLogMessageType = @"LogMessageType";
99 NSString *WebConsoleMessageDirMessageType = @"DirMessageType";
100 NSString *WebConsoleMessageDirXMLMessageType = @"DirXMLMessageType";
101 NSString *WebConsoleMessageTraceMessageType = @"TraceMessageType";
102 NSString *WebConsoleMessageStartGroupMessageType = @"StartGroupMessageType";
103 NSString *WebConsoleMessageStartGroupCollapsedMessageType = @"StartGroupCollapsedMessageType";
104 NSString *WebConsoleMessageEndGroupMessageType = @"EndGroupMessageType";
105 NSString *WebConsoleMessageAssertMessageType = @"AssertMessageType";
106
107 NSString *WebConsoleMessageTipMessageLevel = @"TipMessageLevel";
108 NSString *WebConsoleMessageLogMessageLevel = @"LogMessageLevel";
109 NSString *WebConsoleMessageWarningMessageLevel = @"WarningMessageLevel";
110 NSString *WebConsoleMessageErrorMessageLevel = @"ErrorMessageLevel";
111 NSString *WebConsoleMessageDebugMessageLevel = @"DebugMessageLevel";
112
113 @interface NSApplication (WebNSApplicationDetails)
114 - (NSCursor *)_cursorRectCursor;
115 @end
116
117 @interface NSView (WebNSViewDetails)
118 - (NSView *)_findLastViewInKeyViewLoop;
119 @end
120
121 // For compatibility with old SPI.
122 @interface NSView (WebOldWebKitPlugInDetails)
123 - (void)setIsSelected:(BOOL)isSelected;
124 @end
125
126 @interface NSWindow (AppKitSecretsIKnowAbout)
127 - (NSRect)_growBoxRect;
128 @end
129
130 using namespace WebCore;
131
132 WebChromeClient::WebChromeClient(WebView *webView) 
133     : m_webView(webView)
134 {
135 }
136
137 void WebChromeClient::chromeDestroyed()
138 {
139     delete this;
140 }
141
142 // These functions scale between window and WebView coordinates because JavaScript/DOM operations 
143 // assume that the WebView and the window share the same coordinate system.
144
145 void WebChromeClient::setWindowRect(const FloatRect& rect)
146 {
147     NSRect windowRect = toDeviceSpace(rect, [m_webView window]);
148     [[m_webView _UIDelegateForwarder] webView:m_webView setFrame:windowRect];
149 }
150
151 FloatRect WebChromeClient::windowRect()
152 {
153     NSRect windowRect = [[m_webView _UIDelegateForwarder] webViewFrame:m_webView];
154     return toUserSpace(windowRect, [m_webView window]);
155 }
156
157 // FIXME: We need to add API for setting and getting this.
158 FloatRect WebChromeClient::pageRect()
159 {
160     return [m_webView frame];
161 }
162
163 void WebChromeClient::focus()
164 {
165     [[m_webView _UIDelegateForwarder] webViewFocus:m_webView];
166 }
167
168 void WebChromeClient::unfocus()
169 {
170     [[m_webView _UIDelegateForwarder] webViewUnfocus:m_webView];
171 }
172
173 bool WebChromeClient::canTakeFocus(FocusDirection)
174 {
175     // There's unfortunately no way to determine if we will become first responder again
176     // once we give it up, so we just have to guess that we won't.
177     return true;
178 }
179
180 void WebChromeClient::takeFocus(FocusDirection direction)
181 {
182     if (direction == FocusDirectionForward) {
183         // Since we're trying to move focus out of m_webView, and because
184         // m_webView may contain subviews within it, we ask it for the next key
185         // view of the last view in its key view loop. This makes m_webView
186         // behave as if it had no subviews, which is the behavior we want.
187         NSView *lastView = [m_webView _findLastViewInKeyViewLoop];
188         // avoid triggering assertions if the WebView is the only thing in the key loop
189         if ([m_webView _becomingFirstResponderFromOutside] && m_webView == [lastView nextValidKeyView])
190             return;
191         [[m_webView window] selectKeyViewFollowingView:lastView];
192     } else {
193         // avoid triggering assertions if the WebView is the only thing in the key loop
194         if ([m_webView _becomingFirstResponderFromOutside] && m_webView == [m_webView previousValidKeyView])
195             return;
196         [[m_webView window] selectKeyViewPrecedingView:m_webView];
197     }
198 }
199
200 void WebChromeClient::focusedNodeChanged(Node*)
201 {
202 }
203
204 void WebChromeClient::focusedFrameChanged(Frame*)
205 {
206 }
207
208 Page* WebChromeClient::createWindow(Frame* frame, const FrameLoadRequest&, const WindowFeatures& features, const NavigationAction&)
209 {
210     id delegate = [m_webView UIDelegate];
211     WebView *newWebView;
212     
213     if ([delegate respondsToSelector:@selector(webView:createWebViewWithRequest:windowFeatures:)]) {
214         NSNumber *x = features.xSet ? [[NSNumber alloc] initWithFloat:features.x] : nil;
215         NSNumber *y = features.ySet ? [[NSNumber alloc] initWithFloat:features.y] : nil;
216         NSNumber *width = features.widthSet ? [[NSNumber alloc] initWithFloat:features.width] : nil;
217         NSNumber *height = features.heightSet ? [[NSNumber alloc] initWithFloat:features.height] : nil;
218         NSNumber *menuBarVisible = [[NSNumber alloc] initWithBool:features.menuBarVisible];
219         NSNumber *statusBarVisible = [[NSNumber alloc] initWithBool:features.statusBarVisible];
220         NSNumber *toolBarVisible = [[NSNumber alloc] initWithBool:features.toolBarVisible];
221         NSNumber *scrollbarsVisible = [[NSNumber alloc] initWithBool:features.scrollbarsVisible];
222         NSNumber *resizable = [[NSNumber alloc] initWithBool:features.resizable];
223         NSNumber *fullscreen = [[NSNumber alloc] initWithBool:features.fullscreen];
224         NSNumber *dialog = [[NSNumber alloc] initWithBool:features.dialog];
225         
226         NSMutableDictionary *dictFeatures = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
227                                              menuBarVisible, @"menuBarVisible", 
228                                              statusBarVisible, @"statusBarVisible",
229                                              toolBarVisible, @"toolBarVisible",
230                                              scrollbarsVisible, @"scrollbarsVisible",
231                                              resizable, @"resizable",
232                                              fullscreen, @"fullscreen",
233                                              dialog, @"dialog",
234                                              nil];
235         
236         if (x)
237             [dictFeatures setObject:x forKey:@"x"];
238         if (y)
239             [dictFeatures setObject:y forKey:@"y"];
240         if (width)
241             [dictFeatures setObject:width forKey:@"width"];
242         if (height)
243             [dictFeatures setObject:height forKey:@"height"];
244         
245         newWebView = CallUIDelegate(m_webView, @selector(webView:createWebViewWithRequest:windowFeatures:), nil, dictFeatures);
246         
247         [dictFeatures release];
248         [x release];
249         [y release];
250         [width release];
251         [height release];
252         [menuBarVisible release];
253         [statusBarVisible release];
254         [toolBarVisible release];
255         [scrollbarsVisible release];
256         [resizable release];
257         [fullscreen release];
258         [dialog release];
259     } else if (features.dialog && [delegate respondsToSelector:@selector(webView:createWebViewModalDialogWithRequest:)]) {
260         newWebView = CallUIDelegate(m_webView, @selector(webView:createWebViewModalDialogWithRequest:), nil);
261     } else {
262         newWebView = CallUIDelegate(m_webView, @selector(webView:createWebViewWithRequest:), nil);
263     }
264
265 #if USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
266     if (newWebView)
267         WebKit::NetscapePluginHostManager::shared().didCreateWindow();
268 #endif
269     
270     return core(newWebView);
271 }
272
273 void WebChromeClient::show()
274 {
275     [[m_webView _UIDelegateForwarder] webViewShow:m_webView];
276 }
277
278 bool WebChromeClient::canRunModal()
279 {
280     return [[m_webView UIDelegate] respondsToSelector:@selector(webViewRunModal:)];
281 }
282
283 void WebChromeClient::runModal()
284 {
285     CallUIDelegate(m_webView, @selector(webViewRunModal:));
286 }
287
288 void WebChromeClient::setToolbarsVisible(bool b)
289 {
290     [[m_webView _UIDelegateForwarder] webView:m_webView setToolbarsVisible:b];
291 }
292
293 bool WebChromeClient::toolbarsVisible()
294 {
295     return CallUIDelegateReturningBoolean(NO, m_webView, @selector(webViewAreToolbarsVisible:));
296 }
297
298 void WebChromeClient::setStatusbarVisible(bool b)
299 {
300     [[m_webView _UIDelegateForwarder] webView:m_webView setStatusBarVisible:b];
301 }
302
303 bool WebChromeClient::statusbarVisible()
304 {
305     return CallUIDelegateReturningBoolean(NO, m_webView, @selector(webViewIsStatusBarVisible:));
306 }
307
308 void WebChromeClient::setScrollbarsVisible(bool b)
309 {
310     [[[m_webView mainFrame] frameView] setAllowsScrolling:b];
311 }
312
313 bool WebChromeClient::scrollbarsVisible()
314 {
315     return [[[m_webView mainFrame] frameView] allowsScrolling];
316 }
317
318 void WebChromeClient::setMenubarVisible(bool)
319 {
320     // The menubar is always visible in Mac OS X.
321     return;
322 }
323
324 bool WebChromeClient::menubarVisible()
325 {
326     // The menubar is always visible in Mac OS X.
327     return true;
328 }
329
330 void WebChromeClient::setResizable(bool b)
331 {
332     [[m_webView _UIDelegateForwarder] webView:m_webView setResizable:b];
333 }
334
335 inline static NSString *stringForMessageSource(MessageSource source)
336 {
337     switch (source) {
338     case HTMLMessageSource:
339         return WebConsoleMessageHTMLMessageSource;
340     case XMLMessageSource:
341         return WebConsoleMessageXMLMessageSource;
342     case JSMessageSource:
343         return WebConsoleMessageJSMessageSource;
344     case NetworkMessageSource:
345         return WebConsoleMessageNetworkMessageSource;
346     case ConsoleAPIMessageSource:
347         return WebConsoleMessageConsoleAPIMessageSource;
348     case OtherMessageSource:
349         return WebConsoleMessageOtherMessageSource;
350     }
351     ASSERT_NOT_REACHED();
352     return @"";
353 }
354
355 inline static NSString *stringForMessageType(MessageType type)
356 {
357     switch (type) {
358     case LogMessageType:
359         return WebConsoleMessageLogMessageType;
360     case DirMessageType:
361         return WebConsoleMessageDirMessageType;
362     case DirXMLMessageType:
363         return WebConsoleMessageDirXMLMessageType;
364     case TraceMessageType:
365         return WebConsoleMessageTraceMessageType;
366     case StartGroupMessageType:
367         return WebConsoleMessageStartGroupMessageType;
368     case StartGroupCollapsedMessageType:
369         return WebConsoleMessageStartGroupCollapsedMessageType;
370     case EndGroupMessageType:
371         return WebConsoleMessageEndGroupMessageType;
372     case AssertMessageType:
373         return WebConsoleMessageAssertMessageType;
374     }
375     ASSERT_NOT_REACHED();
376     return @"";
377 }
378
379 inline static NSString *stringForMessageLevel(MessageLevel level)
380 {
381     switch (level) {
382     case TipMessageLevel:
383         return WebConsoleMessageTipMessageLevel;
384     case LogMessageLevel:
385         return WebConsoleMessageLogMessageLevel;
386     case WarningMessageLevel:
387         return WebConsoleMessageWarningMessageLevel;
388     case ErrorMessageLevel:
389         return WebConsoleMessageErrorMessageLevel;
390     case DebugMessageLevel:
391         return WebConsoleMessageDebugMessageLevel;
392     }
393     ASSERT_NOT_REACHED();
394     return @"";
395 }
396
397 void WebChromeClient::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned int lineNumber, const String& sourceURL)
398 {
399     id delegate = [m_webView UIDelegate];
400     BOOL respondsToNewSelector = NO;
401
402     SEL selector = @selector(webView:addMessageToConsole:withSource:);
403     if ([delegate respondsToSelector:selector])
404         respondsToNewSelector = YES;
405     else {
406         // The old selector only takes JSMessageSource messages.
407         if (source != JSMessageSource)
408             return;
409         selector = @selector(webView:addMessageToConsole:);
410         if (![delegate respondsToSelector:selector])
411             return;
412     }
413
414     NSString *messageSource = stringForMessageSource(source);
415     NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
416         (NSString *)message, @"message",
417         [NSNumber numberWithUnsignedInt:lineNumber], @"lineNumber",
418         (NSString *)sourceURL, @"sourceURL",
419         messageSource, @"MessageSource",
420         stringForMessageType(type), @"MessageType",
421         stringForMessageLevel(level), @"MessageLevel",
422         NULL];
423
424     if (respondsToNewSelector)
425         CallUIDelegate(m_webView, selector, dictionary, messageSource);
426     else
427         CallUIDelegate(m_webView, selector, dictionary);
428
429     [dictionary release];
430 }
431
432 bool WebChromeClient::canRunBeforeUnloadConfirmPanel()
433 {
434     return [[m_webView UIDelegate] respondsToSelector:@selector(webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:)];
435 }
436
437 bool WebChromeClient::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
438 {
439     return CallUIDelegateReturningBoolean(true, m_webView, @selector(webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:), message, kit(frame));
440 }
441
442 void WebChromeClient::closeWindowSoon()
443 {
444     // We need to remove the parent WebView from WebViewSets here, before it actually
445     // closes, to make sure that JavaScript code that executes before it closes
446     // can't find it. Otherwise, window.open will select a closed WebView instead of 
447     // opening a new one <rdar://problem/3572585>.
448
449     // We also need to stop the load to prevent further parsing or JavaScript execution
450     // after the window has torn down <rdar://problem/4161660>.
451   
452     // FIXME: This code assumes that the UI delegate will respond to a webViewClose
453     // message by actually closing the WebView. Safari guarantees this behavior, but other apps might not.
454     // This approach is an inherent limitation of not making a close execute immediately
455     // after a call to window.close.
456
457     [m_webView setGroupName:nil];
458     [m_webView stopLoading:nil];
459     [m_webView performSelector:@selector(_closeWindow) withObject:nil afterDelay:0.0];
460 }
461
462 void WebChromeClient::runJavaScriptAlert(Frame* frame, const String& message)
463 {
464     id delegate = [m_webView UIDelegate];
465     SEL selector = @selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:);
466     if ([delegate respondsToSelector:selector]) {
467         CallUIDelegate(m_webView, selector, message, kit(frame));
468         return;
469     }
470
471     // Call the old version of the delegate method if it is implemented.
472     selector = @selector(webView:runJavaScriptAlertPanelWithMessage:);
473     if ([delegate respondsToSelector:selector]) {
474         CallUIDelegate(m_webView, selector, message);
475         return;
476     }
477 }
478
479 bool WebChromeClient::runJavaScriptConfirm(Frame* frame, const String& message)
480 {
481     id delegate = [m_webView UIDelegate];
482     SEL selector = @selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:);
483     if ([delegate respondsToSelector:selector])
484         return CallUIDelegateReturningBoolean(NO, m_webView, selector, message, kit(frame));
485
486     // Call the old version of the delegate method if it is implemented.
487     selector = @selector(webView:runJavaScriptConfirmPanelWithMessage:);
488     if ([delegate respondsToSelector:selector])
489         return CallUIDelegateReturningBoolean(NO, m_webView, selector, message);
490
491     return NO;
492 }
493
494 bool WebChromeClient::runJavaScriptPrompt(Frame* frame, const String& prompt, const String& defaultText, String& result)
495 {
496     id delegate = [m_webView UIDelegate];
497     SEL selector = @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:);
498     NSString *defaultString = defaultText;
499     if ([delegate respondsToSelector:selector]) {
500         result = (NSString *)CallUIDelegate(m_webView, selector, prompt, defaultString, kit(frame));
501         return !result.isNull();
502     }
503
504     // Call the old version of the delegate method if it is implemented.
505     selector = @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:);
506     if ([delegate respondsToSelector:selector]) {
507         result = (NSString *)CallUIDelegate(m_webView, selector, prompt, defaultString);
508         return !result.isNull();
509     }
510
511     result = [[WebDefaultUIDelegate sharedUIDelegate] webView:m_webView runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultString initiatedByFrame:kit(frame)];
512     return !result.isNull();
513 }
514
515 bool WebChromeClient::shouldInterruptJavaScript()
516 {
517     return CallUIDelegateReturningBoolean(NO, m_webView, @selector(webViewShouldInterruptJavaScript:));
518 }
519
520 void WebChromeClient::setStatusbarText(const String& status)
521 {
522     // We want the temporaries allocated here to be released even before returning to the 
523     // event loop; see <http://bugs.webkit.org/show_bug.cgi?id=9880>.
524     NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init];
525     CallUIDelegate(m_webView, @selector(webView:setStatusText:), (NSString *)status);
526     [localPool drain];
527 }
528
529 IntRect WebChromeClient::windowResizerRect() const
530 {
531     return enclosingIntRect([[m_webView window] _growBoxRect]);
532 }
533
534 void WebChromeClient::invalidateRootView(const IntRect&, bool immediate)
535 {
536     if (immediate) {
537         [[m_webView window] displayIfNeeded];
538         [[m_webView window] flushWindowIfNeeded];
539     }
540 }
541
542 void WebChromeClient::invalidateContentsAndRootView(const IntRect& rect, bool immediate)
543 {
544 }
545
546 void WebChromeClient::invalidateContentsForSlowScroll(const IntRect& rect, bool immediate)
547 {
548     invalidateContentsAndRootView(rect, immediate);
549 }
550
551 void WebChromeClient::scroll(const IntSize&, const IntRect&, const IntRect&)
552 {
553 }
554
555 IntPoint WebChromeClient::screenToRootView(const IntPoint& p) const
556 {
557     // FIXME: Implement this.
558     return p;
559 }
560
561 IntRect WebChromeClient::rootViewToScreen(const IntRect& r) const
562 {
563     // FIXME: Implement this.
564     return r;
565 }
566
567 PlatformPageClient WebChromeClient::platformPageClient() const
568 {
569     return 0;
570 }
571
572 void WebChromeClient::contentsSizeChanged(Frame*, const IntSize&) const
573 {
574 }
575
576 void WebChromeClient::scrollRectIntoView(const IntRect& r) const
577 {
578     // FIXME: This scrolling behavior should be under the control of the embedding client,
579     // perhaps in a delegate method, rather than something WebKit does unconditionally.
580     NSView *coordinateView = [[[m_webView mainFrame] frameView] documentView];
581     NSRect rect = r;
582     for (NSView *view = m_webView; view; view = [view superview]) {
583         if ([view isKindOfClass:[NSClipView class]]) {
584             NSClipView *clipView = (NSClipView *)view;
585             NSView *documentView = [clipView documentView];
586             [documentView scrollRectToVisible:[documentView convertRect:rect fromView:coordinateView]];
587         }
588     }
589 }
590
591 // End host window methods.
592
593 bool WebChromeClient::shouldUnavailablePluginMessageBeButton(RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason) const
594 {
595     if (pluginUnavailabilityReason == RenderEmbeddedObject::PluginMissing)
596         return [[m_webView UIDelegate] respondsToSelector:@selector(webView:didPressMissingPluginButton:)];
597
598     return false;
599 }
600
601 void WebChromeClient::unavailablePluginButtonClicked(Element* element, RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason) const
602 {
603     ASSERT_UNUSED(pluginUnavailabilityReason, pluginUnavailabilityReason == RenderEmbeddedObject::PluginMissing);
604     CallUIDelegate(m_webView, @selector(webView:didPressMissingPluginButton:), kit(element));
605 }
606
607 void WebChromeClient::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags)
608 {
609     WebElementDictionary *element = [[WebElementDictionary alloc] initWithHitTestResult:result];
610     [m_webView _mouseDidMoveOverElement:element modifierFlags:modifierFlags];
611     [element release];
612 }
613
614 void WebChromeClient::setToolTip(const String& toolTip, TextDirection)
615 {
616     NSView<WebDocumentView> *documentView = [[[m_webView _selectedOrMainFrame] frameView] documentView];
617     if ([documentView isKindOfClass:[WebHTMLView class]])
618         [(WebHTMLView *)documentView _setToolTip:toolTip];
619 }
620
621 void WebChromeClient::print(Frame* frame)
622 {
623     WebFrame *webFrame = kit(frame);
624     if ([[m_webView UIDelegate] respondsToSelector:@selector(webView:printFrame:)])
625         CallUIDelegate(m_webView, @selector(webView:printFrame:), webFrame);
626     else
627         CallUIDelegate(m_webView, @selector(webView:printFrameView:), [webFrame frameView]);
628 }
629
630 #if ENABLE(SQL_DATABASE)
631
632 void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseName)
633 {
634     BEGIN_BLOCK_OBJC_EXCEPTIONS;
635
636     WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:frame->document()->securityOrigin()];
637     // FIXME: remove this workaround once shipping Safari has the necessary delegate implemented.
638     if (WKAppVersionCheckLessThan(@"com.apple.Safari", -1, 3.1)) {
639         const unsigned long long defaultQuota = 5 * 1024 * 1024; // 5 megabytes should hopefully be enough to test storage support.
640         [[webOrigin databaseQuotaManager] setQuota:defaultQuota];
641     } else
642         CallUIDelegate(m_webView, @selector(webView:frame:exceededDatabaseQuotaForSecurityOrigin:database:), kit(frame), webOrigin, (NSString *)databaseName);
643     [webOrigin release];
644
645     END_BLOCK_OBJC_EXCEPTIONS;
646 }
647
648 #endif
649
650 void WebChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded)
651 {
652     // FIXME: Free some space.
653 }
654
655 void WebChromeClient::reachedApplicationCacheOriginQuota(SecurityOrigin* origin, int64_t totalSpaceNeeded)
656 {
657     BEGIN_BLOCK_OBJC_EXCEPTIONS;
658
659     WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:origin];
660     CallUIDelegate(m_webView, @selector(webView:exceededApplicationCacheOriginQuotaForSecurityOrigin:totalSpaceNeeded:), webOrigin, static_cast<NSUInteger>(totalSpaceNeeded));
661     [webOrigin release];
662
663     END_BLOCK_OBJC_EXCEPTIONS;
664 }
665
666 void WebChromeClient::populateVisitedLinks()
667 {
668     if ([m_webView historyDelegate]) {
669         WebHistoryDelegateImplementationCache* implementations = WebViewGetHistoryDelegateImplementations(m_webView);
670         
671         if (implementations->populateVisitedLinksFunc)
672             CallHistoryDelegate(implementations->populateVisitedLinksFunc, m_webView, @selector(populateVisitedLinksForWebView:));
673
674         return;
675     }
676
677     BEGIN_BLOCK_OBJC_EXCEPTIONS;
678     [[WebHistory optionalSharedHistory] _addVisitedLinksToPageGroup:[m_webView page]->group()];
679     END_BLOCK_OBJC_EXCEPTIONS;
680 }
681
682 #if ENABLE(DASHBOARD_SUPPORT)
683
684 void WebChromeClient::dashboardRegionsChanged()
685 {
686     BEGIN_BLOCK_OBJC_EXCEPTIONS;
687     CallUIDelegate(m_webView, @selector(webView:dashboardRegionsChanged:), [m_webView _dashboardRegions]);
688     END_BLOCK_OBJC_EXCEPTIONS;
689 }
690
691 #endif
692
693 FloatRect WebChromeClient::customHighlightRect(Node* node, const AtomicString& type, const FloatRect& lineRect)
694 {
695     BEGIN_BLOCK_OBJC_EXCEPTIONS;
696
697     NSView *documentView = [[kit(node->document()->frame()) frameView] documentView];
698     if (![documentView isKindOfClass:[WebHTMLView class]])
699         return NSZeroRect;
700
701     WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
702     id<WebHTMLHighlighter> highlighter = [webHTMLView _highlighterForType:type];
703     return [highlighter highlightRectForLine:lineRect representedNode:kit(node)];
704
705     END_BLOCK_OBJC_EXCEPTIONS;
706
707     return NSZeroRect;
708 }
709
710 void WebChromeClient::paintCustomHighlight(Node* node, const AtomicString& type, const FloatRect& boxRect, const FloatRect& lineRect,
711     bool behindText, bool entireLine)
712 {
713     BEGIN_BLOCK_OBJC_EXCEPTIONS;
714
715     NSView *documentView = [[kit(node->document()->frame()) frameView] documentView];
716     if (![documentView isKindOfClass:[WebHTMLView class]])
717         return;
718
719     WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
720     id<WebHTMLHighlighter> highlighter = [webHTMLView _highlighterForType:type];
721     [highlighter paintHighlightForBox:boxRect onLine:lineRect behindText:behindText entireLine:entireLine representedNode:kit(node)];
722
723     END_BLOCK_OBJC_EXCEPTIONS;
724 }
725
726 void WebChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> chooser)
727 {
728     BEGIN_BLOCK_OBJC_EXCEPTIONS;
729     BOOL allowMultipleFiles = chooser->settings().allowsMultipleFiles;
730     WebOpenPanelResultListener *listener = [[WebOpenPanelResultListener alloc] initWithChooser:chooser];
731     id delegate = [m_webView UIDelegate];
732     if ([delegate respondsToSelector:@selector(webView:runOpenPanelForFileButtonWithResultListener:allowMultipleFiles:)])
733         CallUIDelegate(m_webView, @selector(webView:runOpenPanelForFileButtonWithResultListener:allowMultipleFiles:), listener, allowMultipleFiles);
734     else if ([delegate respondsToSelector:@selector(webView:runOpenPanelForFileButtonWithResultListener:)])
735         CallUIDelegate(m_webView, @selector(webView:runOpenPanelForFileButtonWithResultListener:), listener);
736     else
737         [listener cancel];
738     [listener release];
739     END_BLOCK_OBJC_EXCEPTIONS;
740 }
741
742 void WebChromeClient::loadIconForFiles(const Vector<String>& filenames, FileIconLoader* iconLoader)
743 {
744     iconLoader->notifyFinished(Icon::createIconForFiles(filenames));
745 }
746
747 void WebChromeClient::setCursor(const WebCore::Cursor& cursor)
748 {
749     if ([NSApp _cursorRectCursor])
750         return;
751
752     NSCursor *platformCursor = cursor.platformCursor();
753     if ([NSCursor currentCursor] == platformCursor)
754         return;
755     [platformCursor set];
756 }
757
758 void WebChromeClient::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
759 {
760     [NSCursor setHiddenUntilMouseMoves:hiddenUntilMouseMoves];
761 }
762
763 KeyboardUIMode WebChromeClient::keyboardUIMode()
764 {
765     BEGIN_BLOCK_OBJC_EXCEPTIONS;
766     return [m_webView _keyboardUIMode];
767     END_BLOCK_OBJC_EXCEPTIONS;
768     return KeyboardAccessDefault;
769 }
770
771 NSResponder *WebChromeClient::firstResponder()
772 {
773     BEGIN_BLOCK_OBJC_EXCEPTIONS;
774     return [[m_webView _UIDelegateForwarder] webViewFirstResponder:m_webView];
775     END_BLOCK_OBJC_EXCEPTIONS;
776     return nil;
777 }
778
779 void WebChromeClient::makeFirstResponder(NSResponder *responder)
780 {
781     BEGIN_BLOCK_OBJC_EXCEPTIONS;
782     [m_webView _pushPerformingProgrammaticFocus];
783     [[m_webView _UIDelegateForwarder] webView:m_webView makeFirstResponder:responder];
784     [m_webView _popPerformingProgrammaticFocus];
785     END_BLOCK_OBJC_EXCEPTIONS;
786 }
787
788 void WebChromeClient::willPopUpMenu(NSMenu *menu)
789 {
790     BEGIN_BLOCK_OBJC_EXCEPTIONS;
791     CallUIDelegate(m_webView, @selector(webView:willPopupMenu:), menu);
792     END_BLOCK_OBJC_EXCEPTIONS;
793 }
794
795 bool WebChromeClient::shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename)
796 {
797     NSString* filename;
798     if (![[m_webView _UIDelegateForwarder] webView:m_webView shouldReplaceUploadFile:path usingGeneratedFilename:&filename])
799         return false;
800     generatedFilename = filename;
801     return true;
802 }
803
804 String WebChromeClient::generateReplacementFile(const String& path)
805 {
806     return [[m_webView _UIDelegateForwarder] webView:m_webView generateReplacementFile:path];
807 }
808
809 void WebChromeClient::elementDidFocus(const WebCore::Node* node)
810 {
811     CallUIDelegate(m_webView, @selector(webView:formDidFocusNode:), kit(const_cast<WebCore::Node*>(node)));
812 }
813
814 void WebChromeClient::elementDidBlur(const WebCore::Node* node)
815 {
816     CallUIDelegate(m_webView, @selector(webView:formDidBlurNode:), kit(const_cast<WebCore::Node*>(node)));
817 }
818
819 bool WebChromeClient::selectItemWritingDirectionIsNatural()
820 {
821 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
822     return false;
823 #else
824     return true;
825 #endif
826 }
827
828 bool WebChromeClient::selectItemAlignmentFollowsMenuWritingDirection()
829 {
830 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
831     return true;
832 #else
833     return false;
834 #endif
835 }
836
837 bool WebChromeClient::hasOpenedPopup() const
838 {
839     notImplemented();
840     return false;
841 }
842
843 PassRefPtr<WebCore::PopupMenu> WebChromeClient::createPopupMenu(WebCore::PopupMenuClient* client) const
844 {
845     return adoptRef(new PopupMenuMac(client));
846 }
847
848 PassRefPtr<WebCore::SearchPopupMenu> WebChromeClient::createSearchPopupMenu(WebCore::PopupMenuClient* client) const
849 {
850     return adoptRef(new SearchPopupMenuMac(client));
851 }
852
853 #if USE(ACCELERATED_COMPOSITING)
854
855 void WebChromeClient::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer)
856 {
857     BEGIN_BLOCK_OBJC_EXCEPTIONS;
858
859     NSView *documentView = [[kit(frame) frameView] documentView];
860     if (![documentView isKindOfClass:[WebHTMLView class]]) {
861         // We should never be attaching when we don't have a WebHTMLView.
862         ASSERT(!graphicsLayer);
863         return;
864     }
865
866     WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
867     if (graphicsLayer)
868         [webHTMLView attachRootLayer:graphicsLayer->platformLayer()];
869     else
870         [webHTMLView detachRootLayer];
871     END_BLOCK_OBJC_EXCEPTIONS;
872 }
873
874 void WebChromeClient::setNeedsOneShotDrawingSynchronization()
875 {
876     BEGIN_BLOCK_OBJC_EXCEPTIONS;
877     [m_webView _setNeedsOneShotDrawingSynchronization:YES];
878     END_BLOCK_OBJC_EXCEPTIONS;
879 }
880
881 void WebChromeClient::scheduleCompositingLayerSync()
882 {
883     BEGIN_BLOCK_OBJC_EXCEPTIONS;
884     [m_webView _scheduleCompositingLayerSync];
885     END_BLOCK_OBJC_EXCEPTIONS;
886 }
887
888 #endif
889
890 #if ENABLE(VIDEO)
891
892 bool WebChromeClient::supportsFullscreenForNode(const Node* node)
893 {
894     return node->hasTagName(WebCore::HTMLNames::videoTag);
895 }
896
897 void WebChromeClient::enterFullscreenForNode(Node* node)
898 {
899     BEGIN_BLOCK_OBJC_EXCEPTIONS;
900     [m_webView _enterFullscreenForNode:node];
901     END_BLOCK_OBJC_EXCEPTIONS;
902 }
903
904 void WebChromeClient::exitFullscreenForNode(Node*)
905 {
906     BEGIN_BLOCK_OBJC_EXCEPTIONS;
907     [m_webView _exitFullscreen];
908     END_BLOCK_OBJC_EXCEPTIONS;    
909 }
910
911 #endif
912
913 #if ENABLE(FULLSCREEN_API)
914
915 bool WebChromeClient::supportsFullScreenForElement(const Element* element, bool withKeyboard)
916 {
917     SEL selector = @selector(webView:supportsFullScreenForElement:withKeyboard:);
918     if ([[m_webView UIDelegate] respondsToSelector:selector])
919         return CallUIDelegateReturningBoolean(false, m_webView, selector, kit(const_cast<WebCore::Element*>(element)), withKeyboard);
920     return [m_webView _supportsFullScreenForElement:const_cast<WebCore::Element*>(element) withKeyboard:withKeyboard];
921 }
922
923 void WebChromeClient::enterFullScreenForElement(Element* element)
924 {
925     SEL selector = @selector(webView:enterFullScreenForElement:listener:);
926     if ([[m_webView UIDelegate] respondsToSelector:selector]) {
927         WebKitFullScreenListener* listener = [[WebKitFullScreenListener alloc] initWithElement:element];
928         CallUIDelegate(m_webView, selector, kit(element), listener);
929         [listener release];
930     } else
931         [m_webView _enterFullScreenForElement:element];
932 }
933
934 void WebChromeClient::exitFullScreenForElement(Element* element)
935 {
936     SEL selector = @selector(webView:exitFullScreenForElement:listener:);
937     if ([[m_webView UIDelegate] respondsToSelector:selector]) {
938         WebKitFullScreenListener* listener = [[WebKitFullScreenListener alloc] initWithElement:element];
939         CallUIDelegate(m_webView, selector, kit(element), listener);
940         [listener release];
941     } else
942         [m_webView _exitFullScreenForElement:element];
943 }
944
945 void WebChromeClient::fullScreenRendererChanged(RenderBox* renderer)
946 {
947     SEL selector = @selector(webView:fullScreenRendererChanged:);
948     if ([[m_webView UIDelegate] respondsToSelector:selector])
949         CallUIDelegate(m_webView, selector, (id)renderer);
950 }
951
952 #endif