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)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
30 #import "WebChromeClient.h"
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 "WebKitPrefix.h"
42 #import "WebKitSystemInterface.h"
43 #import "WebNSURLRequestExtras.h"
45 #import "WebQuotaManager.h"
46 #import "WebSecurityOriginInternal.h"
47 #import "WebUIDelegatePrivate.h"
49 #import "WebViewInternal.h"
50 #import <Foundation/Foundation.h>
51 #import <WebCore/BlockExceptions.h>
52 #import <WebCore/Console.h>
53 #import <WebCore/Cursor.h>
54 #import <WebCore/ContextMenu.h>
55 #import <WebCore/ContextMenuController.h>
56 #import <WebCore/Element.h>
57 #import <WebCore/FileChooser.h>
58 #import <WebCore/FileIconLoader.h>
59 #import <WebCore/FloatRect.h>
60 #import <WebCore/Frame.h>
61 #import <WebCore/FrameLoadRequest.h>
62 #import <WebCore/FrameView.h>
63 #import <WebCore/HTMLNames.h>
64 #import <WebCore/HitTestResult.h>
65 #import <WebCore/Icon.h>
66 #import <WebCore/IntPoint.h>
67 #import <WebCore/IntRect.h>
68 #import <WebCore/NavigationAction.h>
69 #import <WebCore/Page.h>
70 #import <WebCore/PlatformScreen.h>
71 #import <WebCore/PlatformString.h>
72 #import <WebCore/PopupMenuMac.h>
73 #import <WebCore/ResourceRequest.h>
74 #import <WebCore/SearchPopupMenuMac.h>
75 #import <WebCore/Widget.h>
76 #import <WebCore/WindowFeatures.h>
77 #import <wtf/PassRefPtr.h>
78 #import <wtf/Vector.h>
80 #if USE(ACCELERATED_COMPOSITING)
81 #import <WebCore/GraphicsLayer.h>
84 #if USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
85 #import "NetscapePluginHostManager.h"
88 NSString *WebConsoleMessageHTMLMessageSource = @"HTMLMessageSource";
89 NSString *WebConsoleMessageXMLMessageSource = @"XMLMessageSource";
90 NSString *WebConsoleMessageJSMessageSource = @"JSMessageSource";
91 NSString *WebConsoleMessageCSSMessageSource = @"CSSMessageSource";
92 NSString *WebConsoleMessageOtherMessageSource = @"OtherMessageSource";
94 NSString *WebConsoleMessageLogMessageType = @"LogMessageType";
95 NSString *WebConsoleMessageObjectMessageType = @"ObjectMessageType";
96 NSString *WebConsoleMessageTraceMessageType = @"TraceMessageType";
97 NSString *WebConsoleMessageStartGroupMessageType = @"StartGroupMessageType";
98 NSString *WebConsoleMessageStartGroupCollapsedMessageType = @"StartGroupCollapsedMessageType";
99 NSString *WebConsoleMessageEndGroupMessageType = @"EndGroupMessageType";
100 NSString *WebConsoleMessageAssertMessageType = @"AssertMessageType";
101 NSString *WebConsoleMessageUncaughtExceptionMessageType = @"UncaughtExceptionMessageType";
102 NSString *WebConsoleMessageNetworkErrorMessageType = @"NetworkErrorMessageType";
104 NSString *WebConsoleMessageTipMessageLevel = @"TipMessageLevel";
105 NSString *WebConsoleMessageLogMessageLevel = @"LogMessageLevel";
106 NSString *WebConsoleMessageWarningMessageLevel = @"WarningMessageLevel";
107 NSString *WebConsoleMessageErrorMessageLevel = @"ErrorMessageLevel";
108 NSString *WebConsoleMessageDebugMessageLevel = @"DebugMessageLevel";
110 @interface NSApplication (WebNSApplicationDetails)
111 - (NSCursor *)_cursorRectCursor;
114 @interface NSView (WebNSViewDetails)
115 - (NSView *)_findLastViewInKeyViewLoop;
118 // For compatibility with old SPI.
119 @interface NSView (WebOldWebKitPlugInDetails)
120 - (void)setIsSelected:(BOOL)isSelected;
123 @interface NSWindow (AppKitSecretsIKnowAbout)
124 - (NSRect)_growBoxRect;
127 using namespace WebCore;
129 @interface WebOpenPanelResultListener : NSObject <WebOpenPanelResultListener>
131 FileChooser* _chooser;
133 - (id)initWithChooser:(PassRefPtr<FileChooser>)chooser;
136 #if ENABLE(FULLSCREEN_API)
138 @interface WebKitFullScreenListener : NSObject <WebKitFullScreenListener>
140 RefPtr<Element> _element;
143 - (id)initWithElement:(Element*)element;
148 WebChromeClient::WebChromeClient(WebView *webView)
153 void WebChromeClient::chromeDestroyed()
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.
161 void WebChromeClient::setWindowRect(const FloatRect& rect)
163 NSRect windowRect = toDeviceSpace(rect, [m_webView window]);
164 [[m_webView _UIDelegateForwarder] webView:m_webView setFrame:windowRect];
167 FloatRect WebChromeClient::windowRect()
169 NSRect windowRect = [[m_webView _UIDelegateForwarder] webViewFrame:m_webView];
170 return toUserSpace(windowRect, [m_webView window]);
173 // FIXME: We need to add API for setting and getting this.
174 FloatRect WebChromeClient::pageRect()
176 return [m_webView frame];
179 void WebChromeClient::focus()
181 [[m_webView _UIDelegateForwarder] webViewFocus:m_webView];
184 void WebChromeClient::unfocus()
186 [[m_webView _UIDelegateForwarder] webViewUnfocus:m_webView];
189 bool WebChromeClient::canTakeFocus(FocusDirection)
191 // There's unfortunately no way to determine if we will become first responder again
192 // once we give it up, so we just have to guess that we won't.
196 void WebChromeClient::takeFocus(FocusDirection direction)
198 if (direction == FocusDirectionForward) {
199 // Since we're trying to move focus out of m_webView, and because
200 // m_webView may contain subviews within it, we ask it for the next key
201 // view of the last view in its key view loop. This makes m_webView
202 // behave as if it had no subviews, which is the behavior we want.
203 NSView *lastView = [m_webView _findLastViewInKeyViewLoop];
204 // avoid triggering assertions if the WebView is the only thing in the key loop
205 if ([m_webView _becomingFirstResponderFromOutside] && m_webView == [lastView nextValidKeyView])
207 [[m_webView window] selectKeyViewFollowingView:lastView];
209 // avoid triggering assertions if the WebView is the only thing in the key loop
210 if ([m_webView _becomingFirstResponderFromOutside] && m_webView == [m_webView previousValidKeyView])
212 [[m_webView window] selectKeyViewPrecedingView:m_webView];
216 void WebChromeClient::focusedNodeChanged(Node*)
220 void WebChromeClient::focusedFrameChanged(Frame*)
224 Page* WebChromeClient::createWindow(Frame* frame, const FrameLoadRequest&, const WindowFeatures& features, const NavigationAction&)
226 id delegate = [m_webView UIDelegate];
229 if ([delegate respondsToSelector:@selector(webView:createWebViewWithRequest:windowFeatures:)]) {
230 NSNumber *x = features.xSet ? [[NSNumber alloc] initWithFloat:features.x] : nil;
231 NSNumber *y = features.ySet ? [[NSNumber alloc] initWithFloat:features.y] : nil;
232 NSNumber *width = features.widthSet ? [[NSNumber alloc] initWithFloat:features.width] : nil;
233 NSNumber *height = features.heightSet ? [[NSNumber alloc] initWithFloat:features.height] : nil;
234 NSNumber *menuBarVisible = [[NSNumber alloc] initWithBool:features.menuBarVisible];
235 NSNumber *statusBarVisible = [[NSNumber alloc] initWithBool:features.statusBarVisible];
236 NSNumber *toolBarVisible = [[NSNumber alloc] initWithBool:features.toolBarVisible];
237 NSNumber *scrollbarsVisible = [[NSNumber alloc] initWithBool:features.scrollbarsVisible];
238 NSNumber *resizable = [[NSNumber alloc] initWithBool:features.resizable];
239 NSNumber *fullscreen = [[NSNumber alloc] initWithBool:features.fullscreen];
240 NSNumber *dialog = [[NSNumber alloc] initWithBool:features.dialog];
242 NSMutableDictionary *dictFeatures = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
243 menuBarVisible, @"menuBarVisible",
244 statusBarVisible, @"statusBarVisible",
245 toolBarVisible, @"toolBarVisible",
246 scrollbarsVisible, @"scrollbarsVisible",
247 resizable, @"resizable",
248 fullscreen, @"fullscreen",
253 [dictFeatures setObject:x forKey:@"x"];
255 [dictFeatures setObject:y forKey:@"y"];
257 [dictFeatures setObject:width forKey:@"width"];
259 [dictFeatures setObject:height forKey:@"height"];
261 newWebView = CallUIDelegate(m_webView, @selector(webView:createWebViewWithRequest:windowFeatures:), nil, dictFeatures);
263 [dictFeatures release];
268 [menuBarVisible release];
269 [statusBarVisible release];
270 [toolBarVisible release];
271 [scrollbarsVisible release];
273 [fullscreen release];
275 } else if (features.dialog && [delegate respondsToSelector:@selector(webView:createWebViewModalDialogWithRequest:)]) {
276 newWebView = CallUIDelegate(m_webView, @selector(webView:createWebViewModalDialogWithRequest:), nil);
278 newWebView = CallUIDelegate(m_webView, @selector(webView:createWebViewWithRequest:), nil);
281 #if USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
283 WebKit::NetscapePluginHostManager::shared().didCreateWindow();
286 return core(newWebView);
289 void WebChromeClient::show()
291 [[m_webView _UIDelegateForwarder] webViewShow:m_webView];
294 bool WebChromeClient::canRunModal()
296 return [[m_webView UIDelegate] respondsToSelector:@selector(webViewRunModal:)];
299 void WebChromeClient::runModal()
301 CallUIDelegate(m_webView, @selector(webViewRunModal:));
304 void WebChromeClient::setToolbarsVisible(bool b)
306 [[m_webView _UIDelegateForwarder] webView:m_webView setToolbarsVisible:b];
309 bool WebChromeClient::toolbarsVisible()
311 return CallUIDelegateReturningBoolean(NO, m_webView, @selector(webViewAreToolbarsVisible:));
314 void WebChromeClient::setStatusbarVisible(bool b)
316 [[m_webView _UIDelegateForwarder] webView:m_webView setStatusBarVisible:b];
319 bool WebChromeClient::statusbarVisible()
321 return CallUIDelegateReturningBoolean(NO, m_webView, @selector(webViewIsStatusBarVisible:));
324 void WebChromeClient::setScrollbarsVisible(bool b)
326 [[[m_webView mainFrame] frameView] setAllowsScrolling:b];
329 bool WebChromeClient::scrollbarsVisible()
331 return [[[m_webView mainFrame] frameView] allowsScrolling];
334 void WebChromeClient::setMenubarVisible(bool)
336 // The menubar is always visible in Mac OS X.
340 bool WebChromeClient::menubarVisible()
342 // The menubar is always visible in Mac OS X.
346 void WebChromeClient::setResizable(bool b)
348 [[m_webView _UIDelegateForwarder] webView:m_webView setResizable:b];
351 inline static NSString *stringForMessageSource(MessageSource source)
354 case HTMLMessageSource:
355 return WebConsoleMessageHTMLMessageSource;
356 case XMLMessageSource:
357 return WebConsoleMessageXMLMessageSource;
358 case JSMessageSource:
359 return WebConsoleMessageJSMessageSource;
360 case CSSMessageSource:
361 return WebConsoleMessageCSSMessageSource;
362 case OtherMessageSource:
363 return WebConsoleMessageOtherMessageSource;
365 ASSERT_NOT_REACHED();
369 inline static NSString *stringForMessageType(MessageType type)
373 return WebConsoleMessageLogMessageType;
374 case ObjectMessageType:
375 return WebConsoleMessageObjectMessageType;
376 case TraceMessageType:
377 return WebConsoleMessageTraceMessageType;
378 case StartGroupMessageType:
379 return WebConsoleMessageStartGroupMessageType;
380 case StartGroupCollapsedMessageType:
381 return WebConsoleMessageStartGroupCollapsedMessageType;
382 case EndGroupMessageType:
383 return WebConsoleMessageEndGroupMessageType;
384 case AssertMessageType:
385 return WebConsoleMessageAssertMessageType;
386 case UncaughtExceptionMessageType:
387 return WebConsoleMessageUncaughtExceptionMessageType;
388 case NetworkErrorMessageType:
389 return WebConsoleMessageNetworkErrorMessageType;
391 ASSERT_NOT_REACHED();
395 inline static NSString *stringForMessageLevel(MessageLevel level)
398 case TipMessageLevel:
399 return WebConsoleMessageTipMessageLevel;
400 case LogMessageLevel:
401 return WebConsoleMessageLogMessageLevel;
402 case WarningMessageLevel:
403 return WebConsoleMessageWarningMessageLevel;
404 case ErrorMessageLevel:
405 return WebConsoleMessageErrorMessageLevel;
406 case DebugMessageLevel:
407 return WebConsoleMessageDebugMessageLevel;
409 ASSERT_NOT_REACHED();
413 void WebChromeClient::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned int lineNumber, const String& sourceURL)
415 id delegate = [m_webView UIDelegate];
416 BOOL respondsToNewSelector = NO;
418 SEL selector = @selector(webView:addMessageToConsole:withSource:);
419 if ([delegate respondsToSelector:selector])
420 respondsToNewSelector = YES;
422 // The old selector only takes JSMessageSource messages.
423 if (source != JSMessageSource)
425 selector = @selector(webView:addMessageToConsole:);
426 if (![delegate respondsToSelector:selector])
430 NSString *messageSource = stringForMessageSource(source);
431 NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
432 (NSString *)message, @"message",
433 [NSNumber numberWithUnsignedInt:lineNumber], @"lineNumber",
434 (NSString *)sourceURL, @"sourceURL",
435 messageSource, @"MessageSource",
436 stringForMessageType(type), @"MessageType",
437 stringForMessageLevel(level), @"MessageLevel",
440 if (respondsToNewSelector)
441 CallUIDelegate(m_webView, selector, dictionary, messageSource);
443 CallUIDelegate(m_webView, selector, dictionary);
445 [dictionary release];
448 bool WebChromeClient::canRunBeforeUnloadConfirmPanel()
450 return [[m_webView UIDelegate] respondsToSelector:@selector(webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:)];
453 bool WebChromeClient::runBeforeUnloadConfirmPanel(const String& message, Frame* frame)
455 return CallUIDelegateReturningBoolean(true, m_webView, @selector(webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:), message, kit(frame));
458 void WebChromeClient::closeWindowSoon()
460 // We need to remove the parent WebView from WebViewSets here, before it actually
461 // closes, to make sure that JavaScript code that executes before it closes
462 // can't find it. Otherwise, window.open will select a closed WebView instead of
463 // opening a new one <rdar://problem/3572585>.
465 // We also need to stop the load to prevent further parsing or JavaScript execution
466 // after the window has torn down <rdar://problem/4161660>.
468 // FIXME: This code assumes that the UI delegate will respond to a webViewClose
469 // message by actually closing the WebView. Safari guarantees this behavior, but other apps might not.
470 // This approach is an inherent limitation of not making a close execute immediately
471 // after a call to window.close.
473 [m_webView setGroupName:nil];
474 [m_webView stopLoading:nil];
475 [m_webView performSelector:@selector(_closeWindow) withObject:nil afterDelay:0.0];
478 void WebChromeClient::runJavaScriptAlert(Frame* frame, const String& message)
480 id delegate = [m_webView UIDelegate];
481 SEL selector = @selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:);
482 if ([delegate respondsToSelector:selector]) {
483 CallUIDelegate(m_webView, selector, message, kit(frame));
487 // Call the old version of the delegate method if it is implemented.
488 selector = @selector(webView:runJavaScriptAlertPanelWithMessage:);
489 if ([delegate respondsToSelector:selector]) {
490 CallUIDelegate(m_webView, selector, message);
495 bool WebChromeClient::runJavaScriptConfirm(Frame* frame, const String& message)
497 id delegate = [m_webView UIDelegate];
498 SEL selector = @selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:);
499 if ([delegate respondsToSelector:selector])
500 return CallUIDelegateReturningBoolean(NO, m_webView, selector, message, kit(frame));
502 // Call the old version of the delegate method if it is implemented.
503 selector = @selector(webView:runJavaScriptConfirmPanelWithMessage:);
504 if ([delegate respondsToSelector:selector])
505 return CallUIDelegateReturningBoolean(NO, m_webView, selector, message);
510 bool WebChromeClient::runJavaScriptPrompt(Frame* frame, const String& prompt, const String& defaultText, String& result)
512 id delegate = [m_webView UIDelegate];
513 SEL selector = @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:);
514 if ([delegate respondsToSelector:selector]) {
515 result = (NSString *)CallUIDelegate(m_webView, selector, prompt, defaultText, kit(frame));
516 return !result.isNull();
519 // Call the old version of the delegate method if it is implemented.
520 selector = @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:);
521 if ([delegate respondsToSelector:selector]) {
522 result = (NSString *)CallUIDelegate(m_webView, selector, prompt, defaultText);
523 return !result.isNull();
526 result = [[WebDefaultUIDelegate sharedUIDelegate] webView:m_webView runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText initiatedByFrame:kit(frame)];
527 return !result.isNull();
530 bool WebChromeClient::shouldInterruptJavaScript()
532 return CallUIDelegate(m_webView, @selector(webViewShouldInterruptJavaScript:));
535 void WebChromeClient::setStatusbarText(const String& status)
537 // We want the temporaries allocated here to be released even before returning to the
538 // event loop; see <http://bugs.webkit.org/show_bug.cgi?id=9880>.
539 NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init];
540 CallUIDelegate(m_webView, @selector(webView:setStatusText:), (NSString *)status);
544 IntRect WebChromeClient::windowResizerRect() const
546 NSRect rect = [[m_webView window] _growBoxRect];
547 if ([m_webView _usesDocumentViews])
548 return enclosingIntRect(rect);
549 return enclosingIntRect([m_webView convertRect:rect fromView:nil]);
552 void WebChromeClient::invalidateWindow(const IntRect&, bool immediate)
555 [[m_webView window] displayIfNeeded];
556 [[m_webView window] flushWindowIfNeeded];
560 void WebChromeClient::invalidateContentsAndWindow(const IntRect& rect, bool immediate)
562 if ([m_webView _usesDocumentViews])
565 [m_webView setNeedsDisplayInRect:rect];
568 [[m_webView window] displayIfNeeded];
569 [[m_webView window] flushWindowIfNeeded];
573 void WebChromeClient::invalidateContentsForSlowScroll(const IntRect& rect, bool immediate)
575 invalidateContentsAndWindow(rect, immediate);
578 void WebChromeClient::scroll(const IntSize&, const IntRect&, const IntRect&)
582 IntPoint WebChromeClient::screenToWindow(const IntPoint& p) const
584 if ([m_webView _usesDocumentViews])
586 NSPoint windowCoord = [[m_webView window] convertScreenToBase:p];
587 return IntPoint([m_webView convertPoint:windowCoord fromView:nil]);
590 IntRect WebChromeClient::windowToScreen(const IntRect& r) const
592 if ([m_webView _usesDocumentViews])
595 tempRect = [m_webView convertRect:tempRect toView:nil];
596 tempRect.origin = [[m_webView window] convertBaseToScreen:tempRect.origin];
597 return enclosingIntRect(tempRect);
600 PlatformPageClient WebChromeClient::platformPageClient() const
602 if ([m_webView _usesDocumentViews])
607 void WebChromeClient::contentsSizeChanged(Frame*, const IntSize&) const
611 void WebChromeClient::scrollRectIntoView(const IntRect& r) const
613 // FIXME: This scrolling behavior should be under the control of the embedding client,
614 // perhaps in a delegate method, rather than something WebKit does unconditionally.
615 NSView *coordinateView = [m_webView _usesDocumentViews]
616 ? (NSView *)[[[m_webView mainFrame] frameView] documentView] : m_webView;
618 for (NSView *view = m_webView; view; view = [view superview]) {
619 if ([view isKindOfClass:[NSClipView class]]) {
620 NSClipView *clipView = (NSClipView *)view;
621 NSView *documentView = [clipView documentView];
622 [documentView scrollRectToVisible:[documentView convertRect:rect fromView:coordinateView]];
627 // End host window methods.
629 bool WebChromeClient::shouldMissingPluginMessageBeButton() const
631 return [[m_webView UIDelegate] respondsToSelector:@selector(webView:didPressMissingPluginButton:)];
634 void WebChromeClient::missingPluginButtonClicked(Element* element) const
636 CallUIDelegate(m_webView, @selector(webView:didPressMissingPluginButton:), kit(element));
639 void WebChromeClient::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags)
641 WebElementDictionary *element = [[WebElementDictionary alloc] initWithHitTestResult:result];
642 [m_webView _mouseDidMoveOverElement:element modifierFlags:modifierFlags];
646 void WebChromeClient::setToolTip(const String& toolTip, TextDirection)
648 [m_webView _setToolTip:toolTip];
651 void WebChromeClient::print(Frame* frame)
653 WebFrame *webFrame = kit(frame);
654 if ([[m_webView UIDelegate] respondsToSelector:@selector(webView:printFrame:)])
655 CallUIDelegate(m_webView, @selector(webView:printFrame:), webFrame);
656 else if ([m_webView _usesDocumentViews])
657 CallUIDelegate(m_webView, @selector(webView:printFrameView:), [webFrame frameView]);
662 void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseName)
664 BEGIN_BLOCK_OBJC_EXCEPTIONS;
666 WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:frame->document()->securityOrigin()];
667 // FIXME: remove this workaround once shipping Safari has the necessary delegate implemented.
668 if (WKAppVersionCheckLessThan(@"com.apple.Safari", -1, 3.1)) {
669 const unsigned long long defaultQuota = 5 * 1024 * 1024; // 5 megabytes should hopefully be enough to test storage support.
670 [[webOrigin databaseQuotaManager] setQuota:defaultQuota];
672 CallUIDelegate(m_webView, @selector(webView:frame:exceededDatabaseQuotaForSecurityOrigin:database:), kit(frame), webOrigin, (NSString *)databaseName);
675 END_BLOCK_OBJC_EXCEPTIONS;
680 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
682 void WebChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded)
684 // FIXME: Free some space.
687 void WebChromeClient::reachedApplicationCacheOriginQuota(SecurityOrigin* origin, int64_t totalSpaceNeeded)
689 BEGIN_BLOCK_OBJC_EXCEPTIONS;
691 WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:origin];
692 CallUIDelegate(m_webView, @selector(webView:exceededApplicationCacheOriginQuotaForSecurityOrigin:totalSpaceNeeded:), webOrigin, static_cast<NSUInteger>(totalSpaceNeeded));
695 END_BLOCK_OBJC_EXCEPTIONS;
700 void WebChromeClient::populateVisitedLinks()
702 if ([m_webView historyDelegate]) {
703 WebHistoryDelegateImplementationCache* implementations = WebViewGetHistoryDelegateImplementations(m_webView);
705 if (implementations->populateVisitedLinksFunc)
706 CallHistoryDelegate(implementations->populateVisitedLinksFunc, m_webView, @selector(populateVisitedLinksForWebView:));
711 BEGIN_BLOCK_OBJC_EXCEPTIONS;
712 [[WebHistory optionalSharedHistory] _addVisitedLinksToPageGroup:[m_webView page]->group()];
713 END_BLOCK_OBJC_EXCEPTIONS;
716 #if ENABLE(DASHBOARD_SUPPORT)
718 void WebChromeClient::dashboardRegionsChanged()
720 BEGIN_BLOCK_OBJC_EXCEPTIONS;
721 CallUIDelegate(m_webView, @selector(webView:dashboardRegionsChanged:), [m_webView _dashboardRegions]);
722 END_BLOCK_OBJC_EXCEPTIONS;
727 FloatRect WebChromeClient::customHighlightRect(Node* node, const AtomicString& type, const FloatRect& lineRect)
729 BEGIN_BLOCK_OBJC_EXCEPTIONS;
731 NSView *documentView = [[kit(node->document()->frame()) frameView] documentView];
732 if (![documentView isKindOfClass:[WebHTMLView class]])
735 WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
736 id<WebHTMLHighlighter> highlighter = [webHTMLView _highlighterForType:type];
737 return [highlighter highlightRectForLine:lineRect representedNode:kit(node)];
739 END_BLOCK_OBJC_EXCEPTIONS;
744 void WebChromeClient::paintCustomHighlight(Node* node, const AtomicString& type, const FloatRect& boxRect, const FloatRect& lineRect,
745 bool behindText, bool entireLine)
747 BEGIN_BLOCK_OBJC_EXCEPTIONS;
749 NSView *documentView = [[kit(node->document()->frame()) frameView] documentView];
750 if (![documentView isKindOfClass:[WebHTMLView class]])
753 WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
754 id<WebHTMLHighlighter> highlighter = [webHTMLView _highlighterForType:type];
755 [highlighter paintHighlightForBox:boxRect onLine:lineRect behindText:behindText entireLine:entireLine representedNode:kit(node)];
757 END_BLOCK_OBJC_EXCEPTIONS;
760 void WebChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> chooser)
762 BEGIN_BLOCK_OBJC_EXCEPTIONS;
763 BOOL allowMultipleFiles = chooser->settings().allowsMultipleFiles;
764 WebOpenPanelResultListener *listener = [[WebOpenPanelResultListener alloc] initWithChooser:chooser];
765 id delegate = [m_webView UIDelegate];
766 if ([delegate respondsToSelector:@selector(webView:runOpenPanelForFileButtonWithResultListener:allowMultipleFiles:)])
767 CallUIDelegate(m_webView, @selector(webView:runOpenPanelForFileButtonWithResultListener:allowMultipleFiles:), listener, allowMultipleFiles);
769 CallUIDelegate(m_webView, @selector(webView:runOpenPanelForFileButtonWithResultListener:), listener);
771 END_BLOCK_OBJC_EXCEPTIONS;
774 void WebChromeClient::loadIconForFiles(const Vector<String>& filenames, FileIconLoader* iconLoader)
776 iconLoader->notifyFinished(Icon::createIconForFiles(filenames));
779 void WebChromeClient::setCursor(const WebCore::Cursor& cursor)
781 if ([NSApp _cursorRectCursor])
784 NSCursor *platformCursor = cursor.platformCursor();
785 if ([NSCursor currentCursor] == platformCursor)
787 [platformCursor set];
790 void WebChromeClient::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
792 [NSCursor setHiddenUntilMouseMoves:hiddenUntilMouseMoves];
795 KeyboardUIMode WebChromeClient::keyboardUIMode()
797 BEGIN_BLOCK_OBJC_EXCEPTIONS;
798 return [m_webView _keyboardUIMode];
799 END_BLOCK_OBJC_EXCEPTIONS;
800 return KeyboardAccessDefault;
803 NSResponder *WebChromeClient::firstResponder()
805 BEGIN_BLOCK_OBJC_EXCEPTIONS;
806 return [[m_webView _UIDelegateForwarder] webViewFirstResponder:m_webView];
807 END_BLOCK_OBJC_EXCEPTIONS;
811 void WebChromeClient::makeFirstResponder(NSResponder *responder)
813 BEGIN_BLOCK_OBJC_EXCEPTIONS;
814 [m_webView _pushPerformingProgrammaticFocus];
815 [[m_webView _UIDelegateForwarder] webView:m_webView makeFirstResponder:responder];
816 [m_webView _popPerformingProgrammaticFocus];
817 END_BLOCK_OBJC_EXCEPTIONS;
820 void WebChromeClient::willPopUpMenu(NSMenu *menu)
822 BEGIN_BLOCK_OBJC_EXCEPTIONS;
823 CallUIDelegate(m_webView, @selector(webView:willPopupMenu:), menu);
824 END_BLOCK_OBJC_EXCEPTIONS;
827 bool WebChromeClient::shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename)
830 if (![[m_webView _UIDelegateForwarder] webView:m_webView shouldReplaceUploadFile:path usingGeneratedFilename:&filename])
832 generatedFilename = filename;
836 String WebChromeClient::generateReplacementFile(const String& path)
838 return [[m_webView _UIDelegateForwarder] webView:m_webView generateReplacementFile:path];
841 void WebChromeClient::elementDidFocus(const WebCore::Node* node)
843 CallUIDelegate(m_webView, @selector(webView:formDidFocusNode:), kit(const_cast<WebCore::Node*>(node)));
846 void WebChromeClient::elementDidBlur(const WebCore::Node* node)
848 CallUIDelegate(m_webView, @selector(webView:formDidBlurNode:), kit(const_cast<WebCore::Node*>(node)));
851 bool WebChromeClient::selectItemWritingDirectionIsNatural()
853 #ifndef BUILDING_ON_LEOPARD
860 bool WebChromeClient::selectItemAlignmentFollowsMenuWritingDirection()
862 #ifndef BUILDING_ON_LEOPARD
869 PassRefPtr<WebCore::PopupMenu> WebChromeClient::createPopupMenu(WebCore::PopupMenuClient* client) const
871 return adoptRef(new PopupMenuMac(client));
874 PassRefPtr<WebCore::SearchPopupMenu> WebChromeClient::createSearchPopupMenu(WebCore::PopupMenuClient* client) const
876 return adoptRef(new SearchPopupMenuMac(client));
879 #if ENABLE(CONTEXT_MENUS)
880 void WebChromeClient::showContextMenu()
882 Page* page = [m_webView page];
886 ContextMenuController* controller = page->contextMenuController();
887 Node* node = controller->hitTestResult().innerNonSharedNode();
890 Frame* frame = node->document()->frame();
893 FrameView* frameView = frame->view();
896 NSView* view = frameView->documentView();
898 IntPoint point = frameView->contentsToWindow(controller->hitTestResult().point());
899 NSPoint nsScreenPoint = [view convertPoint:point toView:nil];
900 // Show the contextual menu for this event.
901 NSEvent* event = [NSEvent mouseEventWithType:NSRightMouseDown location:nsScreenPoint modifierFlags:0 timestamp:0 windowNumber:[[view window] windowNumber] context:0 eventNumber:0 clickCount:1 pressure:1];
902 NSMenu* nsMenu = [view menuForEvent:event];
904 [NSMenu popUpContextMenu:nsMenu withEvent:event forView:view];
908 #if USE(ACCELERATED_COMPOSITING)
910 void WebChromeClient::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer)
912 BEGIN_BLOCK_OBJC_EXCEPTIONS;
914 NSView *documentView = [[kit(frame) frameView] documentView];
915 if (![documentView isKindOfClass:[WebHTMLView class]]) {
916 // We should never be attaching when we don't have a WebHTMLView.
917 ASSERT(!graphicsLayer);
921 WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
923 [webHTMLView attachRootLayer:graphicsLayer->platformLayer()];
925 [webHTMLView detachRootLayer];
926 END_BLOCK_OBJC_EXCEPTIONS;
929 void WebChromeClient::setNeedsOneShotDrawingSynchronization()
931 BEGIN_BLOCK_OBJC_EXCEPTIONS;
932 [m_webView _setNeedsOneShotDrawingSynchronization:YES];
933 END_BLOCK_OBJC_EXCEPTIONS;
936 void WebChromeClient::scheduleCompositingLayerSync()
938 BEGIN_BLOCK_OBJC_EXCEPTIONS;
939 [m_webView _scheduleCompositingLayerSync];
940 END_BLOCK_OBJC_EXCEPTIONS;
947 bool WebChromeClient::supportsFullscreenForNode(const Node* node)
949 return node->hasTagName(WebCore::HTMLNames::videoTag);
952 void WebChromeClient::enterFullscreenForNode(Node* node)
954 BEGIN_BLOCK_OBJC_EXCEPTIONS;
955 [m_webView _enterFullscreenForNode:node];
956 END_BLOCK_OBJC_EXCEPTIONS;
959 void WebChromeClient::exitFullscreenForNode(Node*)
961 BEGIN_BLOCK_OBJC_EXCEPTIONS;
962 [m_webView _exitFullscreen];
963 END_BLOCK_OBJC_EXCEPTIONS;
968 #if ENABLE(FULLSCREEN_API)
970 bool WebChromeClient::supportsFullScreenForElement(const Element* element, bool withKeyboard)
972 SEL selector = @selector(webView:supportsFullScreenForElement:withKeyboard:);
973 if ([[m_webView UIDelegate] respondsToSelector:selector])
974 return CallUIDelegateReturningBoolean(false, m_webView, selector, kit(const_cast<WebCore::Element*>(element)), withKeyboard);
975 return [m_webView _supportsFullScreenForElement:const_cast<WebCore::Element*>(element) withKeyboard:withKeyboard];
978 void WebChromeClient::enterFullScreenForElement(Element* element)
980 SEL selector = @selector(webView:enterFullScreenForElement:listener:);
981 if ([[m_webView UIDelegate] respondsToSelector:selector]) {
982 WebKitFullScreenListener* listener = [[WebKitFullScreenListener alloc] initWithElement:element];
983 CallUIDelegate(m_webView, selector, kit(element), listener);
986 [m_webView _enterFullScreenForElement:element];
989 void WebChromeClient::exitFullScreenForElement(Element* element)
991 SEL selector = @selector(webView:exitFullScreenForElement:listener:);
992 if ([[m_webView UIDelegate] respondsToSelector:selector]) {
993 WebKitFullScreenListener* listener = [[WebKitFullScreenListener alloc] initWithElement:element];
994 CallUIDelegate(m_webView, selector, kit(element), listener);
997 [m_webView _exitFullScreenForElement:element];
1000 void WebChromeClient::fullScreenRendererChanged(RenderBox* renderer)
1002 SEL selector = @selector(webView:fullScreenRendererChanged:);
1003 if ([[m_webView UIDelegate] respondsToSelector:selector])
1004 CallUIDelegate(m_webView, selector, (id)renderer);
1006 [m_webView _fullScreenRendererChanged:renderer];
1011 @implementation WebOpenPanelResultListener
1013 - (id)initWithChooser:(PassRefPtr<FileChooser>)chooser
1015 self = [super init];
1018 _chooser = chooser.releaseRef();
1047 - (void)chooseFilename:(NSString *)filename
1052 _chooser->chooseFile(filename);
1057 - (void)chooseFilenames:(NSArray *)filenames
1062 int count = [filenames count];
1063 Vector<String> names(count);
1064 for (int i = 0; i < count; i++)
1065 names[i] = [filenames objectAtIndex:i];
1066 _chooser->chooseFiles(names);
1073 #if ENABLE(FULLSCREEN_API)
1075 @implementation WebKitFullScreenListener
1077 - (id)initWithElement:(Element*)element
1079 if (!(self = [super init]))
1086 - (void)webkitWillEnterFullScreen
1089 _element->document()->webkitWillEnterFullScreenForElement(_element.get());
1092 - (void)webkitDidEnterFullScreen
1095 _element->document()->webkitDidEnterFullScreenForElement(_element.get());
1098 - (void)webkitWillExitFullScreen
1101 _element->document()->webkitWillExitFullScreenForElement(_element.get());
1104 - (void)webkitDidExitFullScreen
1107 _element->document()->webkitDidExitFullScreenForElement(_element.get());