OSDN Git Service

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