diff options
Diffstat (limited to 'WebKit/mac/WebCoreSupport')
26 files changed, 5750 insertions, 0 deletions
diff --git a/WebKit/mac/WebCoreSupport/WebCachedPagePlatformData.h b/WebKit/mac/WebCoreSupport/WebCachedPagePlatformData.h new file mode 100644 index 0000000..3b0ab32 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebCachedPagePlatformData.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <objc/objc-runtime.h> +#import <WebCore/CachedPagePlatformData.h> +#import <wtf/RetainPtr.h> + +class WebCachedPagePlatformData : public WebCore::CachedPagePlatformData { +public: + WebCachedPagePlatformData(id webDocumentView) : m_webDocumentView(webDocumentView) { } + + virtual void clear() { objc_msgSend(m_webDocumentView.get(), @selector(closeIfNotCurrentView)); } + + id webDocumentView() { return m_webDocumentView.get(); } +private: + RetainPtr<id> m_webDocumentView; +}; + diff --git a/WebKit/mac/WebCoreSupport/WebChromeClient.h b/WebKit/mac/WebCoreSupport/WebChromeClient.h new file mode 100644 index 0000000..f6a6efb --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebChromeClient.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <WebCore/ChromeClient.h> +#import <WebCore/FocusDirection.h> +#import <wtf/Forward.h> + +@class WebView; + +class WebChromeClient : public WebCore::ChromeClient { +public: + WebChromeClient(WebView *webView); + WebView *webView() { return m_webView; } + + virtual void chromeDestroyed(); + + virtual void setWindowRect(const WebCore::FloatRect&); + virtual WebCore::FloatRect windowRect(); + + virtual WebCore::FloatRect pageRect(); + + virtual float scaleFactor(); + + virtual void focus(); + virtual void unfocus(); + + virtual bool canTakeFocus(WebCore::FocusDirection); + virtual void takeFocus(WebCore::FocusDirection); + + virtual WebCore::Page* createWindow(WebCore::Frame*, const WebCore::FrameLoadRequest&, const WebCore::WindowFeatures&); + virtual void show(); + + virtual bool canRunModal(); + virtual void runModal(); + + virtual void setToolbarsVisible(bool); + virtual bool toolbarsVisible(); + + virtual void setStatusbarVisible(bool); + virtual bool statusbarVisible(); + + virtual void setScrollbarsVisible(bool); + virtual bool scrollbarsVisible(); + + virtual void setMenubarVisible(bool); + virtual bool menubarVisible(); + + virtual void setResizable(bool); + + virtual void addMessageToConsole(const WebCore::String& message, unsigned int lineNumber, const WebCore::String& sourceURL); + + virtual bool canRunBeforeUnloadConfirmPanel(); + virtual bool runBeforeUnloadConfirmPanel(const WebCore::String& message, WebCore::Frame* frame); + + virtual void closeWindowSoon(); + + virtual void runJavaScriptAlert(WebCore::Frame*, const WebCore::String&); + virtual bool runJavaScriptConfirm(WebCore::Frame*, const WebCore::String&); + virtual bool runJavaScriptPrompt(WebCore::Frame*, const WebCore::String& message, const WebCore::String& defaultValue, WebCore::String& result); + virtual bool shouldInterruptJavaScript(); + + virtual bool tabsToLinks() const; + + virtual WebCore::IntRect windowResizerRect() const; + + virtual void repaint(const WebCore::IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false); + virtual void scroll(const WebCore::IntSize& scrollDelta, const WebCore::IntRect& rectToScroll, const WebCore::IntRect& clipRect); + virtual WebCore::IntPoint screenToWindow(const WebCore::IntPoint&) const; + virtual WebCore::IntRect windowToScreen(const WebCore::IntRect&) const; + virtual PlatformWidget platformWindow() const; + + virtual void setStatusbarText(const WebCore::String&); + + virtual void mouseDidMoveOverElement(const WebCore::HitTestResult&, unsigned modifierFlags); + + virtual void setToolTip(const WebCore::String&); + + virtual void print(WebCore::Frame*); + + virtual void exceededDatabaseQuota(WebCore::Frame*, const WebCore::String& databaseName); + + virtual void populateVisitedLinks(); + +#if ENABLE(DASHBOARD_SUPPORT) + virtual void dashboardRegionsChanged(); +#endif + + virtual void runOpenPanel(WebCore::Frame*, PassRefPtr<WebCore::FileChooser>); + + virtual WebCore::FloatRect customHighlightRect(WebCore::Node*, const WebCore::AtomicString& type, + const WebCore::FloatRect& lineRect); + virtual void paintCustomHighlight(WebCore::Node*, const WebCore::AtomicString& type, + const WebCore::FloatRect& boxRect, const WebCore::FloatRect& lineRect, + bool behindText, bool entireLine); + + virtual WebCore::KeyboardUIMode keyboardUIMode(); + + virtual NSResponder *firstResponder(); + virtual void makeFirstResponder(NSResponder *); + + virtual void willPopUpMenu(NSMenu *); + + virtual bool shouldReplaceWithGeneratedFileForUpload(const WebCore::String& path, WebCore::String &generatedFilename); + virtual WebCore::String generateReplacementFile(const WebCore::String& path); + + virtual void enableSuddenTermination(); + virtual void disableSuddenTermination(); + +private: + WebView *m_webView; +}; diff --git a/WebKit/mac/WebCoreSupport/WebChromeClient.mm b/WebKit/mac/WebCoreSupport/WebChromeClient.mm new file mode 100644 index 0000000..f864367 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebChromeClient.mm @@ -0,0 +1,681 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebChromeClient.h" + +#import <Foundation/Foundation.h> +#import "WebDefaultUIDelegate.h" +#import "WebElementDictionary.h" +#import "WebFrameInternal.h" +#import "WebFrameView.h" +#import "WebHTMLViewInternal.h" +#import "WebHistoryInternal.h" +#import "WebKitSystemInterface.h" +#import "WebKitPrefix.h" +#import "WebNSURLRequestExtras.h" +#import "WebPlugin.h" +#import "WebSecurityOriginInternal.h" +#import "WebUIDelegatePrivate.h" +#import "WebView.h" +#import "WebViewInternal.h" +#import <WebCore/BlockExceptions.h> +#import <WebCore/FileChooser.h> +#import <WebCore/FloatRect.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameLoadRequest.h> +#import <WebCore/HitTestResult.h> +#import <WebCore/IntRect.h> +#import <WebCore/Page.h> +#import <WebCore/PlatformScreen.h> +#import <WebCore/PlatformString.h> +#import <WebCore/ResourceRequest.h> +#import <WebCore/Widget.h> +#import <WebCore/WindowFeatures.h> +#import <wtf/PassRefPtr.h> +#import <wtf/Vector.h> + +@interface NSView (WebNSViewDetails) +- (NSView *)_findLastViewInKeyViewLoop; +@end + +// For compatibility with old SPI. +@interface NSView (WebOldWebKitPlugInDetails) +- (void)setIsSelected:(BOOL)isSelected; +@end + +@interface NSWindow (AppKitSecretsIKnowAbout) +- (NSRect)_growBoxRect; +@end + +using namespace WebCore; + +@interface WebOpenPanelResultListener : NSObject <WebOpenPanelResultListener> { + FileChooser* _chooser; +} +- (id)initWithChooser:(PassRefPtr<FileChooser>)chooser; +@end + +WebChromeClient::WebChromeClient(WebView *webView) + : m_webView(webView) +{ +} + +void WebChromeClient::chromeDestroyed() +{ + delete this; +} + +// These functions scale between window and WebView coordinates because JavaScript/DOM operations +// assume that the WebView and the window share the same coordinate system. + +void WebChromeClient::setWindowRect(const FloatRect& rect) +{ + NSRect windowRect = toDeviceSpace(rect, [m_webView window]); + [[m_webView _UIDelegateForwarder] webView:m_webView setFrame:windowRect]; +} + +FloatRect WebChromeClient::windowRect() +{ + NSRect windowRect = [[m_webView _UIDelegateForwarder] webViewFrame:m_webView]; + return toUserSpace(windowRect, [m_webView window]); +} + +// FIXME: We need to add API for setting and getting this. +FloatRect WebChromeClient::pageRect() +{ + return [m_webView frame]; +} + +float WebChromeClient::scaleFactor() +{ + if (NSWindow *window = [m_webView window]) + return [window userSpaceScaleFactor]; + return [[NSScreen mainScreen] userSpaceScaleFactor]; +} + +void WebChromeClient::focus() +{ + [[m_webView _UIDelegateForwarder] webViewFocus:m_webView]; +} + +void WebChromeClient::unfocus() +{ + [[m_webView _UIDelegateForwarder] webViewUnfocus:m_webView]; +} + +bool WebChromeClient::canTakeFocus(FocusDirection) +{ + // There's unfortunately no way to determine if we will become first responder again + // once we give it up, so we just have to guess that we won't. + return true; +} + +void WebChromeClient::takeFocus(FocusDirection direction) +{ + if (direction == FocusDirectionForward) { + // Since we're trying to move focus out of m_webView, and because + // m_webView may contain subviews within it, we ask it for the next key + // view of the last view in its key view loop. This makes m_webView + // behave as if it had no subviews, which is the behavior we want. + NSView *lastView = [m_webView _findLastViewInKeyViewLoop]; + // avoid triggering assertions if the WebView is the only thing in the key loop + if ([m_webView _becomingFirstResponderFromOutside] && m_webView == [lastView nextValidKeyView]) + return; + [[m_webView window] selectKeyViewFollowingView:lastView]; + } else { + // avoid triggering assertions if the WebView is the only thing in the key loop + if ([m_webView _becomingFirstResponderFromOutside] && m_webView == [m_webView previousValidKeyView]) + return; + [[m_webView window] selectKeyViewPrecedingView:m_webView]; + } +} + +Page* WebChromeClient::createWindow(Frame* frame, const FrameLoadRequest& request, const WindowFeatures& features) +{ + NSURLRequest *URLRequest = nil; + if (!request.isEmpty()) + URLRequest = request.resourceRequest().nsURLRequest(); + + id delegate = [m_webView UIDelegate]; + WebView *newWebView; + + if ([delegate respondsToSelector:@selector(webView:createWebViewWithRequest:windowFeatures:)]) { + NSNumber *x = features.xSet ? [[NSNumber alloc] initWithFloat:features.x] : nil; + NSNumber *y = features.ySet ? [[NSNumber alloc] initWithFloat:features.y] : nil; + NSNumber *width = features.widthSet ? [[NSNumber alloc] initWithFloat:features.width] : nil; + NSNumber *height = features.heightSet ? [[NSNumber alloc] initWithFloat:features.height] : nil; + NSNumber *menuBarVisible = [[NSNumber alloc] initWithBool:features.menuBarVisible]; + NSNumber *statusBarVisible = [[NSNumber alloc] initWithBool:features.statusBarVisible]; + NSNumber *toolBarVisible = [[NSNumber alloc] initWithBool:features.toolBarVisible]; + NSNumber *scrollbarsVisible = [[NSNumber alloc] initWithBool:features.scrollbarsVisible]; + NSNumber *resizable = [[NSNumber alloc] initWithBool:features.resizable]; + NSNumber *fullscreen = [[NSNumber alloc] initWithBool:features.fullscreen]; + NSNumber *dialog = [[NSNumber alloc] initWithBool:features.dialog]; + + NSMutableDictionary *dictFeatures = [[NSMutableDictionary alloc] initWithObjectsAndKeys: + menuBarVisible, @"menuBarVisible", + statusBarVisible, @"statusBarVisible", + toolBarVisible, @"toolBarVisible", + scrollbarsVisible, @"scrollbarsVisible", + resizable, @"resizable", + fullscreen, @"fullscreen", + dialog, @"dialog", + nil]; + + if (x) + [dictFeatures setObject:x forKey:@"x"]; + if (y) + [dictFeatures setObject:y forKey:@"y"]; + if (width) + [dictFeatures setObject:width forKey:@"width"]; + if (height) + [dictFeatures setObject:height forKey:@"height"]; + + newWebView = CallUIDelegate(m_webView, @selector(webView:createWebViewWithRequest:windowFeatures:), URLRequest, dictFeatures); + + [dictFeatures release]; + [x release]; + [y release]; + [width release]; + [height release]; + [menuBarVisible release]; + [statusBarVisible release]; + [toolBarVisible release]; + [scrollbarsVisible release]; + [resizable release]; + [fullscreen release]; + [dialog release]; + } else if (features.dialog && [delegate respondsToSelector:@selector(webView:createWebViewModalDialogWithRequest:)]) { + newWebView = CallUIDelegate(m_webView, @selector(webView:createWebViewModalDialogWithRequest:), URLRequest); + } else { + newWebView = CallUIDelegate(m_webView, @selector(webView:createWebViewWithRequest:), URLRequest); + } + + return core(newWebView); +} + +void WebChromeClient::show() +{ + [[m_webView _UIDelegateForwarder] webViewShow:m_webView]; +} + +bool WebChromeClient::canRunModal() +{ + return [[m_webView UIDelegate] respondsToSelector:@selector(webViewRunModal:)]; +} + +void WebChromeClient::runModal() +{ + CallUIDelegate(m_webView, @selector(webViewRunModal:)); +} + +void WebChromeClient::setToolbarsVisible(bool b) +{ + [[m_webView _UIDelegateForwarder] webView:m_webView setToolbarsVisible:b]; +} + +bool WebChromeClient::toolbarsVisible() +{ + return CallUIDelegateReturningBoolean(NO, m_webView, @selector(webViewAreToolbarsVisible:)); +} + +void WebChromeClient::setStatusbarVisible(bool b) +{ + [[m_webView _UIDelegateForwarder] webView:m_webView setStatusBarVisible:b]; +} + +bool WebChromeClient::statusbarVisible() +{ + return CallUIDelegateReturningBoolean(NO, m_webView, @selector(webViewIsStatusBarVisible:)); +} + +void WebChromeClient::setScrollbarsVisible(bool b) +{ + [[[m_webView mainFrame] frameView] setAllowsScrolling:b]; +} + +bool WebChromeClient::scrollbarsVisible() +{ + return [[[m_webView mainFrame] frameView] allowsScrolling]; +} + +void WebChromeClient::setMenubarVisible(bool) +{ + // The menubar is always visible in Mac OS X. + return; +} + +bool WebChromeClient::menubarVisible() +{ + // The menubar is always visible in Mac OS X. + return true; +} + +void WebChromeClient::setResizable(bool b) +{ + [[m_webView _UIDelegateForwarder] webView:m_webView setResizable:b]; +} + +void WebChromeClient::addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceURL) +{ + id delegate = [m_webView UIDelegate]; + SEL selector = @selector(webView:addMessageToConsole:); + if (![delegate respondsToSelector:selector]) + return; + + NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys: + (NSString *)message, @"message", [NSNumber numberWithUnsignedInt:lineNumber], @"lineNumber", + (NSString *)sourceURL, @"sourceURL", NULL]; + + CallUIDelegate(m_webView, selector, dictionary); + + [dictionary release]; +} + +bool WebChromeClient::canRunBeforeUnloadConfirmPanel() +{ + return [[m_webView UIDelegate] respondsToSelector:@selector(webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:)]; +} + +bool WebChromeClient::runBeforeUnloadConfirmPanel(const String& message, Frame* frame) +{ + return CallUIDelegateReturningBoolean(true, m_webView, @selector(webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:), message, kit(frame)); +} + +void WebChromeClient::closeWindowSoon() +{ + // We need to remove the parent WebView from WebViewSets here, before it actually + // closes, to make sure that JavaScript code that executes before it closes + // can't find it. Otherwise, window.open will select a closed WebView instead of + // opening a new one <rdar://problem/3572585>. + + // We also need to stop the load to prevent further parsing or JavaScript execution + // after the window has torn down <rdar://problem/4161660>. + + // FIXME: This code assumes that the UI delegate will respond to a webViewClose + // message by actually closing the WebView. Safari guarantees this behavior, but other apps might not. + // This approach is an inherent limitation of not making a close execute immediately + // after a call to window.close. + + [m_webView setGroupName:nil]; + [m_webView stopLoading:nil]; + [m_webView performSelector:@selector(_closeWindow) withObject:nil afterDelay:0.0]; +} + +void WebChromeClient::runJavaScriptAlert(Frame* frame, const String& message) +{ + id delegate = [m_webView UIDelegate]; + SEL selector = @selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:); + if ([delegate respondsToSelector:selector]) { + CallUIDelegate(m_webView, selector, message, kit(frame)); + return; + } + + // Call the old version of the delegate method if it is implemented. + selector = @selector(webView:runJavaScriptAlertPanelWithMessage:); + if ([delegate respondsToSelector:selector]) { + CallUIDelegate(m_webView, selector, message); + return; + } +} + +bool WebChromeClient::runJavaScriptConfirm(Frame* frame, const String& message) +{ + id delegate = [m_webView UIDelegate]; + SEL selector = @selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:); + if ([delegate respondsToSelector:selector]) + return CallUIDelegateReturningBoolean(NO, m_webView, selector, message, kit(frame)); + + // Call the old version of the delegate method if it is implemented. + selector = @selector(webView:runJavaScriptConfirmPanelWithMessage:); + if ([delegate respondsToSelector:selector]) + return CallUIDelegateReturningBoolean(NO, m_webView, selector, message); + + return NO; +} + +bool WebChromeClient::runJavaScriptPrompt(Frame* frame, const String& prompt, const String& defaultText, String& result) +{ + id delegate = [m_webView UIDelegate]; + SEL selector = @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:); + if ([delegate respondsToSelector:selector]) { + result = (NSString *)CallUIDelegate(m_webView, selector, prompt, defaultText, kit(frame)); + return !result.isNull(); + } + + // Call the old version of the delegate method if it is implemented. + selector = @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:); + if ([delegate respondsToSelector:selector]) { + result = (NSString *)CallUIDelegate(m_webView, selector, prompt, defaultText); + return !result.isNull(); + } + + result = [[WebDefaultUIDelegate sharedUIDelegate] webView:m_webView runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText initiatedByFrame:kit(frame)]; + return !result.isNull(); +} + +bool WebChromeClient::shouldInterruptJavaScript() +{ + return CallUIDelegate(m_webView, @selector(webViewShouldInterruptJavaScript:)); +} + +void WebChromeClient::setStatusbarText(const String& status) +{ + // We want the temporaries allocated here to be released even before returning to the + // event loop; see <http://bugs.webkit.org/show_bug.cgi?id=9880>. + NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init]; + CallUIDelegate(m_webView, @selector(webView:setStatusText:), (NSString *)status); + [localPool drain]; +} + +bool WebChromeClient::tabsToLinks() const +{ + return [[m_webView preferences] tabsToLinks]; +} + +IntRect WebChromeClient::windowResizerRect() const +{ + NSRect rect = [[m_webView window] _growBoxRect]; + if ([m_webView _usesDocumentViews]) + return enclosingIntRect(rect); + return enclosingIntRect([m_webView convertRect:rect fromView:nil]); +} + +void WebChromeClient::repaint(const IntRect& rect, bool contentChanged, bool immediate, bool repaintContentOnly) +{ + if ([m_webView _usesDocumentViews]) + return; + + if (contentChanged) + [m_webView setNeedsDisplayInRect:rect]; + + if (immediate) { + [[m_webView window] displayIfNeeded]; + [[m_webView window] flushWindowIfNeeded]; + } +} + +void WebChromeClient::scroll(const IntSize&, const IntRect&, const IntRect&) +{ +} + +IntPoint WebChromeClient::screenToWindow(const IntPoint& p) const +{ + if ([m_webView _usesDocumentViews]) + return p; + NSPoint windowCoord = [[m_webView window] convertScreenToBase:p]; + return IntPoint([m_webView convertPoint:windowCoord fromView:nil]); +} + +IntRect WebChromeClient::windowToScreen(const IntRect& r) const +{ + if ([m_webView _usesDocumentViews]) + return r; + NSRect tempRect = r; + tempRect = [m_webView convertRect:tempRect toView:nil]; + tempRect.origin = [[m_webView window] convertBaseToScreen:tempRect.origin]; + return enclosingIntRect(tempRect); +} + +PlatformWidget WebChromeClient::platformWindow() const +{ + if ([m_webView _usesDocumentViews]) + return 0; + return m_webView; +} +// End host window methods. + +void WebChromeClient::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags) +{ + WebElementDictionary *element = [[WebElementDictionary alloc] initWithHitTestResult:result]; + [m_webView _mouseDidMoveOverElement:element modifierFlags:modifierFlags]; + [element release]; +} + +void WebChromeClient::setToolTip(const String& toolTip) +{ + [(WebHTMLView *)[[[m_webView mainFrame] frameView] documentView] _setToolTip:toolTip]; +} + +void WebChromeClient::print(Frame* frame) +{ + WebFrameView* frameView = [kit(frame) frameView]; + CallUIDelegate(m_webView, @selector(webView:printFrameView:), frameView); +} + +void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseName) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:frame->document()->securityOrigin()]; + // FIXME: remove this workaround once shipping Safari has the necessary delegate implemented. + if (WKAppVersionCheckLessThan(@"com.apple.Safari", -1, 3.1)) { + const unsigned long long defaultQuota = 5 * 1024 * 1024; // 5 megabytes should hopefully be enough to test storage support. + [webOrigin setQuota:defaultQuota]; + } else + CallUIDelegate(m_webView, @selector(webView:frame:exceededDatabaseQuotaForSecurityOrigin:database:), kit(frame), webOrigin, (NSString *)databaseName); + [webOrigin release]; + + END_BLOCK_OBJC_EXCEPTIONS; +} + +void WebChromeClient::populateVisitedLinks() +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + [[WebHistory optionalSharedHistory] _addVisitedLinksToPageGroup:[m_webView page]->group()]; + END_BLOCK_OBJC_EXCEPTIONS; +} + +#if ENABLE(DASHBOARD_SUPPORT) +void WebChromeClient::dashboardRegionsChanged() +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + NSMutableDictionary *regions = core([m_webView mainFrame])->dashboardRegionsDictionary(); + [m_webView _addScrollerDashboardRegions:regions]; + + CallUIDelegate(m_webView, @selector(webView:dashboardRegionsChanged:), regions); + + END_BLOCK_OBJC_EXCEPTIONS; +} +#endif + +FloatRect WebChromeClient::customHighlightRect(Node* node, const AtomicString& type, const FloatRect& lineRect) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + NSView *documentView = [[kit(node->document()->frame()) frameView] documentView]; + if (![documentView isKindOfClass:[WebHTMLView class]]) + return NSZeroRect; + + WebHTMLView *webHTMLView = (WebHTMLView *)documentView; + id<WebHTMLHighlighter> highlighter = [webHTMLView _highlighterForType:type]; + if ([(NSObject *)highlighter respondsToSelector:@selector(highlightRectForLine:representedNode:)]) + return [highlighter highlightRectForLine:lineRect representedNode:kit(node)]; + return [highlighter highlightRectForLine:lineRect]; + + END_BLOCK_OBJC_EXCEPTIONS; + + return NSZeroRect; +} + +void WebChromeClient::paintCustomHighlight(Node* node, const AtomicString& type, const FloatRect& boxRect, const FloatRect& lineRect, + bool behindText, bool entireLine) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + NSView *documentView = [[kit(node->document()->frame()) frameView] documentView]; + if (![documentView isKindOfClass:[WebHTMLView class]]) + return; + + WebHTMLView *webHTMLView = (WebHTMLView *)documentView; + id<WebHTMLHighlighter> highlighter = [webHTMLView _highlighterForType:type]; + if ([(NSObject *)highlighter respondsToSelector:@selector(paintHighlightForBox:onLine:behindText:entireLine:representedNode:)]) + [highlighter paintHighlightForBox:boxRect onLine:lineRect behindText:behindText entireLine:entireLine representedNode:kit(node)]; + else + [highlighter paintHighlightForBox:boxRect onLine:lineRect behindText:behindText entireLine:entireLine]; + + END_BLOCK_OBJC_EXCEPTIONS; +} + +void WebChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> chooser) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + BOOL allowMultipleFiles = chooser->allowsMultipleFiles(); + WebOpenPanelResultListener *listener = [[WebOpenPanelResultListener alloc] initWithChooser:chooser]; + id delegate = [m_webView UIDelegate]; + if ([delegate respondsToSelector:@selector(webView:runOpenPanelForFileButtonWithResultListener:allowMultipleFiles:)]) + CallUIDelegate(m_webView, @selector(webView:runOpenPanelForFileButtonWithResultListener:allowMultipleFiles:), listener, allowMultipleFiles); + else + CallUIDelegate(m_webView, @selector(webView:runOpenPanelForFileButtonWithResultListener:), listener); + [listener release]; + END_BLOCK_OBJC_EXCEPTIONS; +} + +KeyboardUIMode WebChromeClient::keyboardUIMode() +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + return [m_webView _keyboardUIMode]; + END_BLOCK_OBJC_EXCEPTIONS; + return KeyboardAccessDefault; +} + +NSResponder *WebChromeClient::firstResponder() +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + return [[m_webView _UIDelegateForwarder] webViewFirstResponder:m_webView]; + END_BLOCK_OBJC_EXCEPTIONS; + return nil; +} + +void WebChromeClient::makeFirstResponder(NSResponder *responder) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + [m_webView _pushPerformingProgrammaticFocus]; + [[m_webView _UIDelegateForwarder] webView:m_webView makeFirstResponder:responder]; + [m_webView _popPerformingProgrammaticFocus]; + END_BLOCK_OBJC_EXCEPTIONS; +} + +void WebChromeClient::willPopUpMenu(NSMenu *menu) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + CallUIDelegate(m_webView, @selector(webView:willPopupMenu:), menu); + END_BLOCK_OBJC_EXCEPTIONS; +} + +bool WebChromeClient::shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename) +{ + NSString* filename; + if (![[m_webView _UIDelegateForwarder] webView:m_webView shouldReplaceUploadFile:path usingGeneratedFilename:&filename]) + return false; + generatedFilename = filename; + return true; +} + +String WebChromeClient::generateReplacementFile(const String& path) +{ + return [[m_webView _UIDelegateForwarder] webView:m_webView generateReplacementFile:path]; +} + +void WebChromeClient::disableSuddenTermination() +{ +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + [[NSProcessInfo processInfo] disableSuddenTermination]; +#endif +} + +void WebChromeClient::enableSuddenTermination() +{ +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + [[NSProcessInfo processInfo] enableSuddenTermination]; +#endif +} + +@implementation WebOpenPanelResultListener + +- (id)initWithChooser:(PassRefPtr<FileChooser>)chooser +{ + self = [super init]; + if (!self) + return nil; + _chooser = chooser.releaseRef(); + return self; +} + +#ifndef NDEBUG + +- (void)dealloc +{ + ASSERT(!_chooser); + [super dealloc]; +} + +- (void)finalize +{ + ASSERT(!_chooser); + [super finalize]; +} + +#endif + +- (void)cancel +{ + ASSERT(_chooser); + if (!_chooser) + return; + _chooser->deref(); + _chooser = 0; +} + +- (void)chooseFilename:(NSString *)filename +{ + ASSERT(_chooser); + if (!_chooser) + return; + _chooser->chooseFile(filename); + _chooser->deref(); + _chooser = 0; +} + +- (void)chooseFilenames:(NSArray *)filenames +{ + ASSERT(_chooser); + if (!_chooser) + return; + int count = [filenames count]; + Vector<String> names(count); + for (int i = 0; i < count; i++) + names[i] = [filenames objectAtIndex:i]; + _chooser->chooseFiles(names); + _chooser->deref(); + _chooser = 0; +} + +@end diff --git a/WebKit/mac/WebCoreSupport/WebContextMenuClient.h b/WebKit/mac/WebCoreSupport/WebContextMenuClient.h new file mode 100644 index 0000000..7ab68a2 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebContextMenuClient.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <WebCore/ContextMenuClient.h> + +@class WebView; + +class WebContextMenuClient : public WebCore::ContextMenuClient { +public: + WebContextMenuClient(WebView *webView); + + virtual void contextMenuDestroyed(); + + virtual NSMutableArray* getCustomMenuFromDefaultItems(WebCore::ContextMenu*); + virtual void contextMenuItemSelected(WebCore::ContextMenuItem*, const WebCore::ContextMenu*); + + virtual void downloadURL(const WebCore::KURL&); + virtual void searchWithGoogle(const WebCore::Frame*); + virtual void lookUpInDictionary(WebCore::Frame*); + virtual void speak(const WebCore::String&); + virtual void stopSpeaking(); + virtual void searchWithSpotlight(); + + WebView *webView() { return m_webView; } + +private: + WebView *m_webView; +}; diff --git a/WebKit/mac/WebCoreSupport/WebContextMenuClient.mm b/WebKit/mac/WebCoreSupport/WebContextMenuClient.mm new file mode 100644 index 0000000..6b5ad14 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebContextMenuClient.mm @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebContextMenuClient.h" + +#import "WebElementDictionary.h" +#import "WebFrame.h" +#import "WebFrameInternal.h" +#import "WebHTMLView.h" +#import "WebHTMLViewInternal.h" +#import "WebKitVersionChecks.h" +#import "WebNSPasteboardExtras.h" +#import "WebUIDelegate.h" +#import "WebUIDelegatePrivate.h" +#import "WebView.h" +#import "WebViewFactory.h" +#import "WebViewInternal.h" +#import <WebCore/ContextMenu.h> +#import <WebCore/KURL.h> +#import <WebKit/DOMPrivate.h> + +using namespace WebCore; + +@interface NSApplication (AppKitSecretsIKnowAbout) +- (void)speakString:(NSString *)string; +@end + +WebContextMenuClient::WebContextMenuClient(WebView *webView) + : m_webView(webView) +{ +} + +void WebContextMenuClient::contextMenuDestroyed() +{ + delete this; +} + +static BOOL isAppleMail(void) +{ + return [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.mail"]; +} + +static BOOL isPreVersion3Client(void) +{ + static BOOL preVersion3Client = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_3_0_CONTEXT_MENU_TAGS); + return preVersion3Client; +} + +static BOOL isPreInspectElementTagClient(void) +{ + static BOOL preInspectElementTagClient = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_INSPECT_ELEMENT_MENU_TAG); + return preInspectElementTagClient; +} + +static NSMutableArray *fixMenusToSendToOldClients(NSMutableArray *defaultMenuItems) +{ + NSMutableArray *savedItems = nil; + + unsigned defaultItemsCount = [defaultMenuItems count]; + + if (isPreInspectElementTagClient() && defaultItemsCount >= 2) { + NSMenuItem *secondToLastItem = [defaultMenuItems objectAtIndex:defaultItemsCount - 2]; + NSMenuItem *lastItem = [defaultMenuItems objectAtIndex:defaultItemsCount - 1]; + + if ([secondToLastItem isSeparatorItem] && [lastItem tag] == WebMenuItemTagInspectElement) { + savedItems = [NSMutableArray arrayWithCapacity:2]; + [savedItems addObject:secondToLastItem]; + [savedItems addObject:lastItem]; + + [defaultMenuItems removeObject:secondToLastItem]; + [defaultMenuItems removeObject:lastItem]; + defaultItemsCount -= 2; + } + } + + BOOL preVersion3Client = isPreVersion3Client(); + if (!preVersion3Client) + return savedItems; + + BOOL isMail = isAppleMail(); + for (unsigned i = 0; i < defaultItemsCount; ++i) { + NSMenuItem *item = [defaultMenuItems objectAtIndex:i]; + int tag = [item tag]; + int oldStyleTag = tag; + + if (preVersion3Client && isMail && tag == WebMenuItemTagOpenLink) { + // Tiger Mail changes our "Open Link in New Window" item to "Open Link" + // and doesn't expect us to include an "Open Link" item at all. (5011905) + [defaultMenuItems removeObjectAtIndex:i]; + i--; + defaultItemsCount--; + continue; + } + + if (tag >= WEBMENUITEMTAG_WEBKIT_3_0_SPI_START) { + // Change all editing-related SPI tags listed in WebUIDelegatePrivate.h to WebMenuItemTagOther + // to match our old WebKit context menu behavior. + oldStyleTag = WebMenuItemTagOther; + } else { + // All items are expected to have useful tags coming into this method. + ASSERT(tag != WebMenuItemTagOther); + + // Use the pre-3.0 tags for the few items that changed tags as they moved from SPI to API. We + // do this only for old clients; new Mail already expects the new symbols in this case. + if (preVersion3Client) { + switch (tag) { + case WebMenuItemTagSearchInSpotlight: + oldStyleTag = OldWebMenuItemTagSearchInSpotlight; + break; + case WebMenuItemTagSearchWeb: + oldStyleTag = OldWebMenuItemTagSearchWeb; + break; + case WebMenuItemTagLookUpInDictionary: + oldStyleTag = OldWebMenuItemTagLookUpInDictionary; + break; + default: + break; + } + } + } + + if (oldStyleTag != tag) + [item setTag:oldStyleTag]; + } + + return savedItems; +} + +static void fixMenusReceivedFromOldClients(NSMutableArray *newMenuItems, NSMutableArray *savedItems) +{ + if (savedItems) + [newMenuItems addObjectsFromArray:savedItems]; + + BOOL preVersion3Client = isPreVersion3Client(); + if (!preVersion3Client) + return; + + // Restore the modern tags to the menu items whose tags we altered in fixMenusToSendToOldClients. + unsigned newItemsCount = [newMenuItems count]; + for (unsigned i = 0; i < newItemsCount; ++i) { + NSMenuItem *item = [newMenuItems objectAtIndex:i]; + + int tag = [item tag]; + int modernTag = tag; + + if (tag == WebMenuItemTagOther) { + // Restore the specific tag for items on which we temporarily set WebMenuItemTagOther to match old behavior. + NSString *title = [item title]; + if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagOpenLink]]) + modernTag = WebMenuItemTagOpenLink; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagIgnoreGrammar]]) + modernTag = WebMenuItemTagIgnoreGrammar; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagSpellingMenu]]) + modernTag = WebMenuItemTagSpellingMenu; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagShowSpellingPanel:true]] + || [title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagShowSpellingPanel:false]]) + modernTag = WebMenuItemTagShowSpellingPanel; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagCheckSpelling]]) + modernTag = WebMenuItemTagCheckSpelling; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagCheckSpellingWhileTyping]]) + modernTag = WebMenuItemTagCheckSpellingWhileTyping; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagCheckGrammarWithSpelling]]) + modernTag = WebMenuItemTagCheckGrammarWithSpelling; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagFontMenu]]) + modernTag = WebMenuItemTagFontMenu; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagShowFonts]]) + modernTag = WebMenuItemTagShowFonts; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagBold]]) + modernTag = WebMenuItemTagBold; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagItalic]]) + modernTag = WebMenuItemTagItalic; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagUnderline]]) + modernTag = WebMenuItemTagUnderline; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagOutline]]) + modernTag = WebMenuItemTagOutline; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagStyles]]) + modernTag = WebMenuItemTagStyles; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagShowColors]]) + modernTag = WebMenuItemTagShowColors; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagSpeechMenu]]) + modernTag = WebMenuItemTagSpeechMenu; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagStartSpeaking]]) + modernTag = WebMenuItemTagStartSpeaking; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagStopSpeaking]]) + modernTag = WebMenuItemTagStopSpeaking; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagWritingDirectionMenu]]) + modernTag = WebMenuItemTagWritingDirectionMenu; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagDefaultDirection]]) + modernTag = WebMenuItemTagDefaultDirection; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagLeftToRight]]) + modernTag = WebMenuItemTagLeftToRight; + else if ([title isEqualToString:[[WebViewFactory sharedFactory] contextMenuItemTagRightToLeft]]) + modernTag = WebMenuItemTagRightToLeft; + else { + // We don't expect WebMenuItemTagOther for any items other than the ones we explicitly handle. + // There's nothing to prevent an app from applying this tag, but they are supposed to only + // use tags in the range starting with WebMenuItemBaseApplicationTag=10000 + ASSERT_NOT_REACHED(); + } + } else if (preVersion3Client) { + // Restore the new API tag for items on which we temporarily set the old SPI tag. The old SPI tag was + // needed to avoid confusing clients linked against earlier WebKits; the new API tag is needed for + // WebCore to handle the menu items appropriately (without needing to know about the old SPI tags). + switch (tag) { + case OldWebMenuItemTagSearchInSpotlight: + modernTag = WebMenuItemTagSearchInSpotlight; + break; + case OldWebMenuItemTagSearchWeb: + modernTag = WebMenuItemTagSearchWeb; + break; + case OldWebMenuItemTagLookUpInDictionary: + modernTag = WebMenuItemTagLookUpInDictionary; + break; + default: + break; + } + } + + if (modernTag != tag) + [item setTag:modernTag]; + } +} + +NSMutableArray* WebContextMenuClient::getCustomMenuFromDefaultItems(ContextMenu* defaultMenu) +{ + id delegate = [m_webView UIDelegate]; + SEL selector = @selector(webView:contextMenuItemsForElement:defaultMenuItems:); + if (![delegate respondsToSelector:selector]) + return defaultMenu->platformDescription(); + + NSDictionary *element = [[[WebElementDictionary alloc] initWithHitTestResult:defaultMenu->hitTestResult()] autorelease]; + + BOOL preVersion3Client = isPreVersion3Client(); + if (preVersion3Client) { + DOMNode *node = [element objectForKey:WebElementDOMNodeKey]; + if ([node isKindOfClass:[DOMHTMLInputElement class]] && [(DOMHTMLInputElement *)node _isTextField]) + return defaultMenu->platformDescription(); + if ([node isKindOfClass:[DOMHTMLTextAreaElement class]]) + return defaultMenu->platformDescription(); + } + + NSMutableArray *defaultMenuItems = defaultMenu->platformDescription(); + + unsigned defaultItemsCount = [defaultMenuItems count]; + for (unsigned i = 0; i < defaultItemsCount; ++i) + [[defaultMenuItems objectAtIndex:i] setRepresentedObject:element]; + + NSMutableArray *savedItems = [fixMenusToSendToOldClients(defaultMenuItems) retain]; + NSArray *delegateSuppliedItems = CallUIDelegate(m_webView, selector, element, defaultMenuItems); + NSMutableArray *newMenuItems = [delegateSuppliedItems mutableCopy]; + fixMenusReceivedFromOldClients(newMenuItems, savedItems); + [savedItems release]; + return [newMenuItems autorelease]; +} + +void WebContextMenuClient::contextMenuItemSelected(ContextMenuItem* item, const ContextMenu* parentMenu) +{ + id delegate = [m_webView UIDelegate]; + SEL selector = @selector(webView:contextMenuItemSelected:forElement:); + if ([delegate respondsToSelector:selector]) { + NSDictionary *element = [[WebElementDictionary alloc] initWithHitTestResult:parentMenu->hitTestResult()]; + NSMenuItem *platformItem = item->releasePlatformDescription(); + + CallUIDelegate(m_webView, selector, platformItem, element); + + [element release]; + [platformItem release]; + } +} + +void WebContextMenuClient::downloadURL(const KURL& url) +{ + [m_webView _downloadURL:url]; +} + +void WebContextMenuClient::searchWithSpotlight() +{ + [m_webView _searchWithSpotlightFromMenu:nil]; +} + +void WebContextMenuClient::searchWithGoogle(const Frame*) +{ + [m_webView _searchWithGoogleFromMenu:nil]; +} + +void WebContextMenuClient::lookUpInDictionary(Frame* frame) +{ + WebHTMLView* htmlView = (WebHTMLView*)[[kit(frame) frameView] documentView]; + if(![htmlView isKindOfClass:[WebHTMLView class]]) + return; + [htmlView _lookUpInDictionaryFromMenu:nil]; +} + +void WebContextMenuClient::speak(const String& string) +{ + [NSApp speakString:[[(NSString*)string copy] autorelease]]; +} + +void WebContextMenuClient::stopSpeaking() +{ + [NSApp stopSpeaking]; +} diff --git a/WebKit/mac/WebCoreSupport/WebDragClient.h b/WebKit/mac/WebCoreSupport/WebDragClient.h new file mode 100644 index 0000000..234090e --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebDragClient.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <WebCore/DragClient.h> + +@class WebView; + +class WebDragClient : public WebCore::DragClient { +public: + WebDragClient(WebView*); + virtual void willPerformDragDestinationAction(WebCore::DragDestinationAction, WebCore::DragData*); + virtual void willPerformDragSourceAction(WebCore::DragSourceAction, const WebCore::IntPoint&, WebCore::Clipboard*); + virtual WebCore::DragDestinationAction actionMaskForDrag(WebCore::DragData*); + virtual void dragControllerDestroyed(); + virtual WebCore::DragSourceAction dragSourceActionMaskForPoint(const WebCore::IntPoint& windowPoint); + virtual void startDrag(WebCore::DragImageRef dragImage, const WebCore::IntPoint& dragPos, const WebCore::IntPoint& eventPos, WebCore::Clipboard*, WebCore::Frame*, bool linkDrag); + virtual WebCore::DragImageRef createDragImageForLink(WebCore::KURL& url, const WebCore::String& label, WebCore::Frame*); + virtual void declareAndWriteDragImage(NSPasteboard*, DOMElement*, NSURL*, NSString*, WebCore::Frame*); +private: + WebView* m_webView; +}; diff --git a/WebKit/mac/WebCoreSupport/WebDragClient.mm b/WebKit/mac/WebCoreSupport/WebDragClient.mm new file mode 100644 index 0000000..42c3d33 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebDragClient.mm @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebDragClient.h" + +#import "WebArchive.h" +#import "WebDOMOperations.h" +#import "WebFrame.h" +#import "WebFrameInternal.h" +#import "WebHTMLViewInternal.h" +#import "WebHTMLViewPrivate.h" +#import "WebKitLogging.h" +#import "WebNSPasteboardExtras.h" +#import "WebNSURLExtras.h" +#import "WebUIDelegate.h" +#import "WebUIDelegatePrivate.h" +#import "WebViewInternal.h" +#import <WebCore/ClipboardMac.h> +#import <WebCore/DragData.h> +#import <WebCore/EventHandler.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameView.h> +#import <WebCore/Image.h> +#import <WebCore/Page.h> + +using namespace WebCore; + +WebDragClient::WebDragClient(WebView* webView) + : m_webView(webView) +{ +} + +static WebHTMLView *getTopHTMLView(Frame* frame) +{ + ASSERT(frame); + ASSERT(frame->page()); + return (WebHTMLView*)[[kit(frame->page()->mainFrame()) frameView] documentView]; +} + +WebCore::DragDestinationAction WebDragClient::actionMaskForDrag(WebCore::DragData* dragData) +{ + return (WebCore::DragDestinationAction)[[m_webView _UIDelegateForwarder] webView:m_webView dragDestinationActionMaskForDraggingInfo:dragData->platformData()]; +} + +void WebDragClient::willPerformDragDestinationAction(WebCore::DragDestinationAction action, WebCore::DragData* dragData) +{ + [[m_webView _UIDelegateForwarder] webView:m_webView willPerformDragDestinationAction:(WebDragDestinationAction)action forDraggingInfo:dragData->platformData()]; +} + + +WebCore::DragSourceAction WebDragClient::dragSourceActionMaskForPoint(const IntPoint& windowPoint) +{ + NSPoint viewPoint = [m_webView convertPoint:windowPoint fromView:nil]; + return (DragSourceAction)[[m_webView _UIDelegateForwarder] webView:m_webView dragSourceActionMaskForPoint:viewPoint]; +} + +void WebDragClient::willPerformDragSourceAction(WebCore::DragSourceAction action, const WebCore::IntPoint& mouseDownPoint, WebCore::Clipboard* clipboard) +{ + ASSERT(clipboard); + [[m_webView _UIDelegateForwarder] webView:m_webView willPerformDragSourceAction:(WebDragSourceAction)action fromPoint:mouseDownPoint withPasteboard:static_cast<WebCore::ClipboardMac*>(clipboard)->pasteboard()]; +} + +void WebDragClient::startDrag(DragImageRef dragImage, const IntPoint& at, const IntPoint& eventPos, Clipboard* clipboard, Frame* frame, bool linkDrag) +{ + if (!frame) + return; + ASSERT(clipboard); + RetainPtr<WebHTMLView> htmlView = (WebHTMLView*)[[kit(frame) frameView] documentView]; + if (![htmlView.get() isKindOfClass:[WebHTMLView class]]) + return; + + NSEvent *event = linkDrag ? frame->eventHandler()->currentNSEvent() : [htmlView.get() _mouseDownEvent]; + WebHTMLView* topHTMLView = getTopHTMLView(frame); + RetainPtr<WebHTMLView> topViewProtector = topHTMLView; + + [topHTMLView _stopAutoscrollTimer]; + NSPasteboard *pasteboard = static_cast<ClipboardMac*>(clipboard)->pasteboard(); + + NSImage *dragNSImage = dragImage.get(); + WebHTMLView *sourceHTMLView = htmlView.get(); + + id delegate = [m_webView UIDelegate]; + SEL selector = @selector(webView:dragImage:at:offset:event:pasteboard:source:slideBack:forView:); + if ([delegate respondsToSelector:selector]) { + if ([m_webView _catchesDelegateExceptions]) { + @try { + [delegate webView:m_webView dragImage:dragNSImage at:at offset:NSZeroSize event:event pasteboard:pasteboard source:sourceHTMLView slideBack:YES forView:topHTMLView]; + } @catch (id exception) { + ReportDiscardedDelegateException(selector, exception); + } + } else + [delegate webView:m_webView dragImage:dragNSImage at:at offset:NSZeroSize event:event pasteboard:pasteboard source:sourceHTMLView slideBack:YES forView:topHTMLView]; + } else + [topHTMLView dragImage:dragNSImage at:at offset:NSZeroSize event:event pasteboard:pasteboard source:sourceHTMLView slideBack:YES]; +} + +DragImageRef WebDragClient::createDragImageForLink(KURL& url, const String& title, Frame* frame) +{ + if (!frame) + return nil; + WebHTMLView *htmlView = (WebHTMLView *)[[kit(frame) frameView] documentView]; + NSString *label = 0; + if (!title.isEmpty()) + label = title; + NSURL *cocoaURL = url; + return [htmlView _dragImageForURL:[cocoaURL _web_userVisibleString] withLabel:label]; +} + + +void WebDragClient::declareAndWriteDragImage(NSPasteboard* pasteboard, DOMElement* element, NSURL* URL, NSString* title, WebCore::Frame* frame) +{ + ASSERT(pasteboard); + ASSERT(element); + WebHTMLView *source = getTopHTMLView(frame); + WebArchive *archive = [element webArchive]; + + [pasteboard _web_declareAndWriteDragImageForElement:element URL:URL title:title archive:archive source:source]; +} + +void WebDragClient::dragControllerDestroyed() +{ + delete this; +} diff --git a/WebKit/mac/WebCoreSupport/WebEditorClient.h b/WebKit/mac/WebCoreSupport/WebEditorClient.h new file mode 100644 index 0000000..245e575 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebEditorClient.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <WebCore/EditorClient.h> +#import <wtf/RetainPtr.h> +#import <wtf/Forward.h> +#import <wtf/Vector.h> + +@class WebView; +@class WebEditorUndoTarget; + +class WebEditorClient : public WebCore::EditorClient { +public: + WebEditorClient(WebView *); + + virtual void pageDestroyed(); + + virtual bool isGrammarCheckingEnabled(); + virtual void toggleGrammarChecking(); + virtual bool isContinuousSpellCheckingEnabled(); + virtual void toggleContinuousSpellChecking(); + virtual int spellCheckerDocumentTag(); + + virtual bool smartInsertDeleteEnabled(); + virtual bool isEditable(); + + virtual bool shouldDeleteRange(WebCore::Range*); + virtual bool shouldShowDeleteInterface(WebCore::HTMLElement*); + + virtual bool shouldBeginEditing(WebCore::Range*); + virtual bool shouldEndEditing(WebCore::Range*); + virtual bool shouldInsertNode(WebCore::Node*, WebCore::Range*, WebCore::EditorInsertAction); + virtual bool shouldInsertText(const WebCore::String&, WebCore::Range*, WebCore::EditorInsertAction); + virtual bool shouldChangeSelectedRange(WebCore::Range* fromRange, WebCore::Range* toRange, WebCore::EAffinity, bool stillSelecting); + + virtual bool shouldApplyStyle(WebCore::CSSStyleDeclaration*, WebCore::Range*); + + virtual bool shouldMoveRangeAfterDelete(WebCore::Range* range, WebCore::Range* rangeToBeReplaced); + + virtual void didBeginEditing(); + virtual void didEndEditing(); + virtual void didWriteSelectionToPasteboard(); + virtual void didSetSelectionTypesForPasteboard(); + + virtual NSString* userVisibleString(NSURL*); +#ifdef BUILDING_ON_TIGER + virtual NSArray* pasteboardTypesForSelection(WebCore::Frame*); +#endif + + virtual void respondToChangedContents(); + virtual void respondToChangedSelection(); + + virtual void registerCommandForUndo(PassRefPtr<WebCore::EditCommand>); + virtual void registerCommandForRedo(PassRefPtr<WebCore::EditCommand>); + virtual void clearUndoRedoOperations(); + + virtual bool canUndo() const; + virtual bool canRedo() const; + + virtual void undo(); + virtual void redo(); + + virtual void handleKeyboardEvent(WebCore::KeyboardEvent*); + virtual void handleInputMethodKeydown(WebCore::KeyboardEvent*); + + virtual void textFieldDidBeginEditing(WebCore::Element*); + virtual void textFieldDidEndEditing(WebCore::Element*); + virtual void textDidChangeInTextField(WebCore::Element*); + virtual bool doTextFieldCommandFromEvent(WebCore::Element*, WebCore::KeyboardEvent*); + virtual void textWillBeDeletedInTextField(WebCore::Element*); + virtual void textDidChangeInTextArea(WebCore::Element*); + + virtual void ignoreWordInSpellDocument(const WebCore::String&); + virtual void learnWord(const WebCore::String&); + virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength); + virtual void checkGrammarOfString(const UChar*, int length, WTF::Vector<WebCore::GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength); + virtual void updateSpellingUIWithGrammarString(const WebCore::String&, const WebCore::GrammarDetail&); + virtual void updateSpellingUIWithMisspelledWord(const WebCore::String&); + virtual void showSpellingUI(bool show); + virtual bool spellingUIIsShowing(); + virtual void getGuessesForWord(const WebCore::String&, WTF::Vector<WebCore::String>& guesses); + virtual void setInputMethodState(bool enabled); +private: + void registerCommandForUndoOrRedo(PassRefPtr<WebCore::EditCommand>, bool isRedo); + WebEditorClient(); + + WebView *m_webView; + RetainPtr<WebEditorUndoTarget> m_undoTarget; + + bool m_haveUndoRedoOperations; +}; diff --git a/WebKit/mac/WebCoreSupport/WebEditorClient.mm b/WebKit/mac/WebCoreSupport/WebEditorClient.mm new file mode 100644 index 0000000..f2ed480 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebEditorClient.mm @@ -0,0 +1,624 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebEditorClient.h" + +#import "DOMHTMLInputElementInternal.h" +#import "DOMHTMLTextAreaElementInternal.h" +#import "DOMRangeInternal.h" +#import "WebArchive.h" +#import "WebDataSourceInternal.h" +#import "WebDocument.h" +#import "WebEditingDelegatePrivate.h" +#import "WebFormDelegate.h" +#import "WebFrameInternal.h" +#import "WebHTMLView.h" +#import "WebHTMLViewInternal.h" +#import "WebKitLogging.h" +#import "WebKitVersionChecks.h" +#import "WebLocalizableStrings.h" +#import "WebNSURLExtras.h" +#import "WebViewInternal.h" +#import <WebCore/Document.h> +#import <WebCore/EditAction.h> +#import <WebCore/EditCommand.h> +#import <WebCore/KeyboardEvent.h> +#import <WebCore/LegacyWebArchive.h> +#import <WebCore/PlatformKeyboardEvent.h> +#import <WebCore/PlatformString.h> +#import <WebCore/WebCoreObjCExtras.h> +#import <wtf/PassRefPtr.h> + +using namespace WebCore; +using namespace WTF; + +EditorInsertAction core(WebViewInsertAction); +WebViewInsertAction kit(EditorInsertAction); + +EditorInsertAction core(WebViewInsertAction kitAction) +{ + return static_cast<EditorInsertAction>(kitAction); +} + +WebViewInsertAction kit(EditorInsertAction coreAction) +{ + return static_cast<WebViewInsertAction>(coreAction); +} + +#ifdef BUILDING_ON_TIGER +@interface NSSpellChecker (NotYetPublicMethods) +- (void)learnWord:(NSString *)word; +@end +#endif + +@interface WebEditCommand : NSObject +{ + EditCommand *m_command; +} + ++ (WebEditCommand *)commandWithEditCommand:(PassRefPtr<EditCommand>)command; +- (EditCommand *)command; + +@end + +@implementation WebEditCommand + +#ifndef BUILDING_ON_TIGER ++ (void)initialize +{ + WebCoreObjCFinalizeOnMainThread(self); +} +#endif + +- (id)initWithEditCommand:(PassRefPtr<EditCommand>)command +{ + ASSERT(command); + [super init]; + m_command = command.releaseRef(); + return self; +} + +- (void)dealloc +{ + if (WebCoreObjCScheduleDeallocateOnMainThread([WebEditCommand class], self)) + return; + + m_command->deref(); + [super dealloc]; +} + +- (void)finalize +{ + ASSERT_MAIN_THREAD(); + m_command->deref(); + [super finalize]; +} + ++ (WebEditCommand *)commandWithEditCommand:(PassRefPtr<EditCommand>)command +{ + return [[[WebEditCommand alloc] initWithEditCommand:command] autorelease]; +} + +- (EditCommand *)command; +{ + return m_command; +} + +@end + +@interface WebEditorUndoTarget : NSObject +{ +} + +- (void)undoEditing:(id)arg; +- (void)redoEditing:(id)arg; + +@end + +@implementation WebEditorUndoTarget + +- (void)undoEditing:(id)arg +{ + ASSERT([arg isKindOfClass:[WebEditCommand class]]); + [arg command]->unapply(); +} + +- (void)redoEditing:(id)arg +{ + ASSERT([arg isKindOfClass:[WebEditCommand class]]); + [arg command]->reapply(); +} + +@end + +void WebEditorClient::pageDestroyed() +{ + delete this; +} + +WebEditorClient::WebEditorClient(WebView *webView) + : m_webView(webView) + , m_undoTarget([[[WebEditorUndoTarget alloc] init] autorelease]) + , m_haveUndoRedoOperations(false) +{ +} + +bool WebEditorClient::isContinuousSpellCheckingEnabled() +{ + return [m_webView isContinuousSpellCheckingEnabled]; +} + +void WebEditorClient::toggleContinuousSpellChecking() +{ + [m_webView toggleContinuousSpellChecking:nil]; +} + +bool WebEditorClient::isGrammarCheckingEnabled() +{ +#ifdef BUILDING_ON_TIGER + return false; +#else + return [m_webView isGrammarCheckingEnabled]; +#endif +} + +void WebEditorClient::toggleGrammarChecking() +{ +#ifndef BUILDING_ON_TIGER + [m_webView toggleGrammarChecking:nil]; +#endif +} + +int WebEditorClient::spellCheckerDocumentTag() +{ + return [m_webView spellCheckerDocumentTag]; +} + +bool WebEditorClient::isEditable() +{ + return [m_webView isEditable]; +} + +bool WebEditorClient::shouldDeleteRange(Range* range) +{ + return [[m_webView _editingDelegateForwarder] webView:m_webView + shouldDeleteDOMRange:kit(range)]; +} + +bool WebEditorClient::shouldShowDeleteInterface(HTMLElement* element) +{ + return [[m_webView _editingDelegateForwarder] webView:m_webView + shouldShowDeleteInterfaceForElement:kit(element)]; +} + +bool WebEditorClient::smartInsertDeleteEnabled() +{ + return [m_webView smartInsertDeleteEnabled]; +} + +bool WebEditorClient::shouldApplyStyle(CSSStyleDeclaration* style, Range* range) +{ + return [[m_webView _editingDelegateForwarder] webView:m_webView + shouldApplyStyle:kit(style) toElementsInDOMRange:kit(range)]; +} + +bool WebEditorClient::shouldMoveRangeAfterDelete(Range* range, Range* rangeToBeReplaced) +{ + return [[m_webView _editingDelegateForwarder] webView:m_webView + shouldMoveRangeAfterDelete:kit(range) replacingRange:kit(rangeToBeReplaced)]; +} + +bool WebEditorClient::shouldBeginEditing(Range* range) +{ + return [[m_webView _editingDelegateForwarder] webView:m_webView + shouldBeginEditingInDOMRange:kit(range)]; + + return false; +} + +bool WebEditorClient::shouldEndEditing(Range* range) +{ + return [[m_webView _editingDelegateForwarder] webView:m_webView + shouldEndEditingInDOMRange:kit(range)]; +} + +bool WebEditorClient::shouldInsertText(const String& text, Range* range, EditorInsertAction action) +{ + WebView* webView = m_webView; + return [[webView _editingDelegateForwarder] webView:webView shouldInsertText:text replacingDOMRange:kit(range) givenAction:kit(action)]; +} + +bool WebEditorClient::shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity selectionAffinity, bool stillSelecting) +{ + return [m_webView _shouldChangeSelectedDOMRange:kit(fromRange) toDOMRange:kit(toRange) affinity:kit(selectionAffinity) stillSelecting:stillSelecting]; +} + +void WebEditorClient::didBeginEditing() +{ + [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidBeginEditingNotification object:m_webView]; +} + +void WebEditorClient::respondToChangedContents() +{ + NSView <WebDocumentView> *view = [[[m_webView selectedFrame] frameView] documentView]; + if ([view isKindOfClass:[WebHTMLView class]]) + [(WebHTMLView *)view _updateFontPanel]; + [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeNotification object:m_webView]; +} + +void WebEditorClient::respondToChangedSelection() +{ + NSView <WebDocumentView> *view = [[[m_webView selectedFrame] frameView] documentView]; + if ([view isKindOfClass:[WebHTMLView class]]) + [(WebHTMLView *)view _selectionChanged]; + + // FIXME: This quirk is needed due to <rdar://problem/5009625> - We can phase it out once Aperture can adopt the new behavior on their end + if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"]) + return; + + [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeSelectionNotification object:m_webView]; +} + +void WebEditorClient::didEndEditing() +{ + [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidEndEditingNotification object:m_webView]; +} + +void WebEditorClient::didWriteSelectionToPasteboard() +{ + [[m_webView _editingDelegateForwarder] webView:m_webView didWriteSelectionToPasteboard:[NSPasteboard generalPasteboard]]; +} + +void WebEditorClient::didSetSelectionTypesForPasteboard() +{ + [[m_webView _editingDelegateForwarder] webView:m_webView didSetSelectionTypesForPasteboard:[NSPasteboard generalPasteboard]]; +} + +NSString* WebEditorClient::userVisibleString(NSURL *URL) +{ + return [URL _web_userVisibleString]; +} + +#ifdef BUILDING_ON_TIGER +NSArray* WebEditorClient::pasteboardTypesForSelection(Frame* selectedFrame) +{ + WebFrame* frame = kit(selectedFrame); + return [[[frame frameView] documentView] pasteboardTypesForSelection]; +} +#endif + +bool WebEditorClient::shouldInsertNode(Node *node, Range* replacingRange, EditorInsertAction givenAction) +{ + return [[m_webView _editingDelegateForwarder] webView:m_webView shouldInsertNode:kit(node) replacingDOMRange:kit(replacingRange) givenAction:(WebViewInsertAction)givenAction]; +} + +static NSString* undoNameForEditAction(EditAction editAction) +{ + switch (editAction) { + case EditActionUnspecified: return nil; + case EditActionSetColor: return UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name"); + case EditActionSetBackgroundColor: return UI_STRING_KEY("Set Background Color", "Set Background Color (Undo action name)", "Undo action name"); + case EditActionTurnOffKerning: return UI_STRING_KEY("Turn Off Kerning", "Turn Off Kerning (Undo action name)", "Undo action name"); + case EditActionTightenKerning: return UI_STRING_KEY("Tighten Kerning", "Tighten Kerning (Undo action name)", "Undo action name"); + case EditActionLoosenKerning: return UI_STRING_KEY("Loosen Kerning", "Loosen Kerning (Undo action name)", "Undo action name"); + case EditActionUseStandardKerning: return UI_STRING_KEY("Use Standard Kerning", "Use Standard Kerning (Undo action name)", "Undo action name"); + case EditActionTurnOffLigatures: return UI_STRING_KEY("Turn Off Ligatures", "Turn Off Ligatures (Undo action name)", "Undo action name"); + case EditActionUseStandardLigatures: return UI_STRING_KEY("Use Standard Ligatures", "Use Standard Ligatures (Undo action name)", "Undo action name"); + case EditActionUseAllLigatures: return UI_STRING_KEY("Use All Ligatures", "Use All Ligatures (Undo action name)", "Undo action name"); + case EditActionRaiseBaseline: return UI_STRING_KEY("Raise Baseline", "Raise Baseline (Undo action name)", "Undo action name"); + case EditActionLowerBaseline: return UI_STRING_KEY("Lower Baseline", "Lower Baseline (Undo action name)", "Undo action name"); + case EditActionSetTraditionalCharacterShape: return UI_STRING_KEY("Set Traditional Character Shape", "Set Traditional Character Shape (Undo action name)", "Undo action name"); + case EditActionSetFont: return UI_STRING_KEY("Set Font", "Set Font (Undo action name)", "Undo action name"); + case EditActionChangeAttributes: return UI_STRING_KEY("Change Attributes", "Change Attributes (Undo action name)", "Undo action name"); + case EditActionAlignLeft: return UI_STRING_KEY("Align Left", "Align Left (Undo action name)", "Undo action name"); + case EditActionAlignRight: return UI_STRING_KEY("Align Right", "Align Right (Undo action name)", "Undo action name"); + case EditActionCenter: return UI_STRING_KEY("Center", "Center (Undo action name)", "Undo action name"); + case EditActionJustify: return UI_STRING_KEY("Justify", "Justify (Undo action name)", "Undo action name"); + case EditActionSetWritingDirection: return UI_STRING_KEY("Set Writing Direction", "Set Writing Direction (Undo action name)", "Undo action name"); + case EditActionSubscript: return UI_STRING_KEY("Subscript", "Subscript (Undo action name)", "Undo action name"); + case EditActionSuperscript: return UI_STRING_KEY("Superscript", "Superscript (Undo action name)", "Undo action name"); + case EditActionUnderline: return UI_STRING_KEY("Underline", "Underline (Undo action name)", "Undo action name"); + case EditActionOutline: return UI_STRING_KEY("Outline", "Outline (Undo action name)", "Undo action name"); + case EditActionUnscript: return UI_STRING_KEY("Unscript", "Unscript (Undo action name)", "Undo action name"); + case EditActionDrag: return UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name"); + case EditActionCut: return UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name"); + case EditActionPaste: return UI_STRING_KEY("Paste", "Paste (Undo action name)", "Undo action name"); + case EditActionPasteFont: return UI_STRING_KEY("Paste Font", "Paste Font (Undo action name)", "Undo action name"); + case EditActionPasteRuler: return UI_STRING_KEY("Paste Ruler", "Paste Ruler (Undo action name)", "Undo action name"); + case EditActionTyping: return UI_STRING_KEY("Typing", "Typing (Undo action name)", "Undo action name"); + case EditActionCreateLink: return UI_STRING_KEY("Create Link", "Create Link (Undo action name)", "Undo action name"); + case EditActionUnlink: return UI_STRING_KEY("Unlink", "Unlink (Undo action name)", "Undo action name"); + case EditActionInsertList: return UI_STRING_KEY("Insert List", "Insert List (Undo action name)", "Undo action name"); + case EditActionFormatBlock: return UI_STRING_KEY("Formatting", "Format Block (Undo action name)", "Undo action name"); + case EditActionIndent: return UI_STRING_KEY("Indent", "Indent (Undo action name)", "Undo action name"); + case EditActionOutdent: return UI_STRING_KEY("Outdent", "Outdent (Undo action name)", "Undo action name"); + } + return nil; +} + +void WebEditorClient::registerCommandForUndoOrRedo(PassRefPtr<EditCommand> cmd, bool isRedo) +{ + ASSERT(cmd); + + NSUndoManager *undoManager = [m_webView undoManager]; + NSString *actionName = undoNameForEditAction(cmd->editingAction()); + WebEditCommand *command = [WebEditCommand commandWithEditCommand:cmd]; + [undoManager registerUndoWithTarget:m_undoTarget.get() selector:(isRedo ? @selector(redoEditing:) : @selector(undoEditing:)) object:command]; + if (actionName) + [undoManager setActionName:actionName]; + m_haveUndoRedoOperations = YES; +} + +void WebEditorClient::registerCommandForUndo(PassRefPtr<EditCommand> cmd) +{ + registerCommandForUndoOrRedo(cmd, false); +} + +void WebEditorClient::registerCommandForRedo(PassRefPtr<EditCommand> cmd) +{ + registerCommandForUndoOrRedo(cmd, true); +} + +void WebEditorClient::clearUndoRedoOperations() +{ + if (m_haveUndoRedoOperations) { + // workaround for <rdar://problem/4645507> NSUndoManager dies + // with uncaught exception when undo items cleared while + // groups are open + NSUndoManager *undoManager = [m_webView undoManager]; + int groupingLevel = [undoManager groupingLevel]; + for (int i = 0; i < groupingLevel; ++i) + [undoManager endUndoGrouping]; + + [undoManager removeAllActionsWithTarget:m_undoTarget.get()]; + + for (int i = 0; i < groupingLevel; ++i) + [undoManager beginUndoGrouping]; + + m_haveUndoRedoOperations = NO; + } +} + +bool WebEditorClient::canUndo() const +{ + return [[m_webView undoManager] canUndo]; +} + +bool WebEditorClient::canRedo() const +{ + return [[m_webView undoManager] canRedo]; +} + +void WebEditorClient::undo() +{ + if (canUndo()) + [[m_webView undoManager] undo]; +} + +void WebEditorClient::redo() +{ + if (canRedo()) + [[m_webView undoManager] redo]; +} + +void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event) +{ + Frame* frame = event->target()->toNode()->document()->frame(); + WebHTMLView *webHTMLView = [[kit(frame) frameView] documentView]; + if ([webHTMLView _interceptEditingKeyEvent:event shouldSaveCommand:NO]) + event->setDefaultHandled(); +} + +void WebEditorClient::handleInputMethodKeydown(KeyboardEvent* event) +{ + Frame* frame = event->target()->toNode()->document()->frame(); + WebHTMLView *webHTMLView = [[kit(frame) frameView] documentView]; + if ([webHTMLView _interceptEditingKeyEvent:event shouldSaveCommand:YES]) + event->setDefaultHandled(); +} + +#define FormDelegateLog(ctrl) LOG(FormDelegate, "control=%@", ctrl) + +void WebEditorClient::textFieldDidBeginEditing(Element* element) +{ + DOMHTMLInputElement* inputElement = [DOMHTMLInputElement _wrapHTMLInputElement:(HTMLInputElement*)element]; + FormDelegateLog(inputElement); + CallFormDelegate(m_webView, @selector(textFieldDidBeginEditing:inFrame:), inputElement, kit(element->document()->frame())); +} + +void WebEditorClient::textFieldDidEndEditing(Element* element) +{ + DOMHTMLInputElement* inputElement = [DOMHTMLInputElement _wrapHTMLInputElement:(HTMLInputElement*)element]; + FormDelegateLog(inputElement); + CallFormDelegate(m_webView, @selector(textFieldDidEndEditing:inFrame:), inputElement, kit(element->document()->frame())); +} + +void WebEditorClient::textDidChangeInTextField(Element* element) +{ + DOMHTMLInputElement* inputElement = [DOMHTMLInputElement _wrapHTMLInputElement:(HTMLInputElement*)element]; + FormDelegateLog(inputElement); + CallFormDelegate(m_webView, @selector(textDidChangeInTextField:inFrame:), inputElement, kit(element->document()->frame())); +} + +static SEL selectorForKeyEvent(KeyboardEvent* event) +{ + // FIXME: This helper function is for the auto-fill code so we can pass a selector to the form delegate. + // Eventually, we should move all of the auto-fill code down to WebKit and remove the need for this function by + // not relying on the selector in the new implementation. + // The key identifiers are from <http://www.w3.org/TR/DOM-Level-3-Events/keyset.html#KeySet-Set> + String key = event->keyIdentifier(); + if (key == "Up") + return @selector(moveUp:); + if (key == "Down") + return @selector(moveDown:); + if (key == "U+001B") + return @selector(cancel:); + if (key == "U+0009") { + if (event->shiftKey()) + return @selector(insertBacktab:); + return @selector(insertTab:); + } + if (key == "Enter") + return @selector(insertNewline:); + return 0; +} + +bool WebEditorClient::doTextFieldCommandFromEvent(Element* element, KeyboardEvent* event) +{ + DOMHTMLInputElement* inputElement = [DOMHTMLInputElement _wrapHTMLInputElement:(HTMLInputElement*)element]; + FormDelegateLog(inputElement); + if (SEL commandSelector = selectorForKeyEvent(event)) + return CallFormDelegateReturningBoolean(NO, m_webView, @selector(textField:doCommandBySelector:inFrame:), inputElement, commandSelector, kit(element->document()->frame())); + return NO; +} + +void WebEditorClient::textWillBeDeletedInTextField(Element* element) +{ + DOMHTMLInputElement* inputElement = [DOMHTMLInputElement _wrapHTMLInputElement:(HTMLInputElement*)element]; + FormDelegateLog(inputElement); + // We're using the deleteBackward selector for all deletion operations since the autofill code treats all deletions the same way. + CallFormDelegateReturningBoolean(NO, m_webView, @selector(textField:doCommandBySelector:inFrame:), inputElement, @selector(deleteBackward:), kit(element->document()->frame())); +} + +void WebEditorClient::textDidChangeInTextArea(Element* element) +{ + DOMHTMLTextAreaElement* textAreaElement = [DOMHTMLTextAreaElement _wrapHTMLTextAreaElement:(HTMLTextAreaElement*)element]; + FormDelegateLog(textAreaElement); + CallFormDelegate(m_webView, @selector(textDidChangeInTextArea:inFrame:), textAreaElement, kit(element->document()->frame())); +} + +void WebEditorClient::ignoreWordInSpellDocument(const String& text) +{ + [[NSSpellChecker sharedSpellChecker] ignoreWord:text + inSpellDocumentWithTag:spellCheckerDocumentTag()]; +} + +void WebEditorClient::learnWord(const String& text) +{ + [[NSSpellChecker sharedSpellChecker] learnWord:text]; +} + +void WebEditorClient::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength) +{ + NSString* textString = [[NSString alloc] initWithCharactersNoCopy:const_cast<UChar*>(text) length:length freeWhenDone:NO]; + NSRange range = [[NSSpellChecker sharedSpellChecker] checkSpellingOfString:textString startingAt:0 language:nil wrap:NO inSpellDocumentWithTag:spellCheckerDocumentTag() wordCount:NULL]; + [textString release]; + if (misspellingLocation) { + // WebCore expects -1 to represent "not found" + if (range.location == NSNotFound) + *misspellingLocation = -1; + else + *misspellingLocation = range.location; + } + + if (misspellingLength) + *misspellingLength = range.length; +} + +void WebEditorClient::checkGrammarOfString(const UChar* text, int length, Vector<GrammarDetail>& details, int* badGrammarLocation, int* badGrammarLength) +{ +#ifndef BUILDING_ON_TIGER + NSArray *grammarDetails; + NSString* textString = [[NSString alloc] initWithCharactersNoCopy:const_cast<UChar*>(text) length:length freeWhenDone:NO]; + NSRange range = [[NSSpellChecker sharedSpellChecker] checkGrammarOfString:textString startingAt:0 language:nil wrap:NO inSpellDocumentWithTag:spellCheckerDocumentTag() details:&grammarDetails]; + [textString release]; + if (badGrammarLocation) + // WebCore expects -1 to represent "not found" + *badGrammarLocation = (range.location == NSNotFound) ? -1 : range.location; + if (badGrammarLength) + *badGrammarLength = range.length; + for (NSDictionary *detail in grammarDetails) { + ASSERT(detail); + GrammarDetail grammarDetail; + NSValue *detailRangeAsNSValue = [detail objectForKey:NSGrammarRange]; + ASSERT(detailRangeAsNSValue); + NSRange detailNSRange = [detailRangeAsNSValue rangeValue]; + ASSERT(detailNSRange.location != NSNotFound && detailNSRange.length > 0); + grammarDetail.location = detailNSRange.location; + grammarDetail.length = detailNSRange.length; + grammarDetail.userDescription = [detail objectForKey:NSGrammarUserDescription]; + NSArray *guesses = [detail objectForKey:NSGrammarCorrections]; + for (NSString *guess in guesses) + grammarDetail.guesses.append(String(guess)); + details.append(grammarDetail); + } +#endif +} + +void WebEditorClient::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail) +{ +#ifndef BUILDING_ON_TIGER + NSMutableArray* corrections = [NSMutableArray array]; + for (unsigned i = 0; i < grammarDetail.guesses.size(); i++) { + NSString* guess = grammarDetail.guesses[i]; + [corrections addObject:guess]; + } + NSRange grammarRange = NSMakeRange(grammarDetail.location, grammarDetail.length); + NSString* grammarUserDescription = grammarDetail.userDescription; + NSMutableDictionary* grammarDetailDict = [NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithRange:grammarRange], NSGrammarRange, grammarUserDescription, NSGrammarUserDescription, corrections, NSGrammarCorrections, nil]; + + [[NSSpellChecker sharedSpellChecker] updateSpellingPanelWithGrammarString:badGrammarPhrase detail:grammarDetailDict]; +#endif +} + +void WebEditorClient::updateSpellingUIWithMisspelledWord(const String& misspelledWord) +{ + [[NSSpellChecker sharedSpellChecker] updateSpellingPanelWithMisspelledWord:misspelledWord]; +} + +void WebEditorClient::showSpellingUI(bool show) +{ + NSPanel *spellingPanel = [[NSSpellChecker sharedSpellChecker] spellingPanel]; + if (show) + [spellingPanel orderFront:nil]; + else + [spellingPanel orderOut:nil]; +} + +bool WebEditorClient::spellingUIIsShowing() +{ + return [[[NSSpellChecker sharedSpellChecker] spellingPanel] isVisible]; +} + +void WebEditorClient::getGuessesForWord(const String& word, WTF::Vector<String>& guesses) +{ + NSArray* stringsArray = [[NSSpellChecker sharedSpellChecker] guessesForWord:word]; + unsigned count = [stringsArray count]; + guesses.clear(); + if (count > 0) { + NSEnumerator* enumerator = [stringsArray objectEnumerator]; + NSString* string; + while ((string = [enumerator nextObject]) != nil) + guesses.append(string); + } +} + +void WebEditorClient::setInputMethodState(bool) +{ +} diff --git a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h new file mode 100644 index 0000000..2730765 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <WebCore/FrameLoaderClient.h> +#import <WebCore/Timer.h> +#import <wtf/Forward.h> +#import <wtf/HashMap.h> +#import <wtf/RetainPtr.h> + +@class WebDownload; +@class WebFrame; +@class WebFramePolicyListener; +@class WebHistoryItem; +@class WebResource; + +namespace WebCore { + class AuthenticationChallenge; + class CachedPage; + class HistoryItem; + class String; + class ResourceLoader; + class ResourceRequest; +} + +typedef HashMap<RefPtr<WebCore::ResourceLoader>, RetainPtr<WebResource> > ResourceMap; + +class WebFrameLoaderClient : public WebCore::FrameLoaderClient { +public: + WebFrameLoaderClient(WebFrame*); + + WebFrame* webFrame() const { return m_webFrame.get(); } + + virtual void frameLoaderDestroyed(); + void receivedPolicyDecison(WebCore::PolicyAction); + +private: + virtual bool hasWebView() const; // mainly for assertions + + virtual void makeRepresentation(WebCore::DocumentLoader*); + virtual bool hasHTMLView() const; + virtual void forceLayout(); + virtual void forceLayoutForNonHTML(); + + virtual void setCopiesOnScroll(); + + virtual void detachedFromParent2(); + virtual void detachedFromParent3(); + + virtual void download(WebCore::ResourceHandle*, const WebCore::ResourceRequest&, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&); + + virtual void assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader*, const WebCore::ResourceRequest&); + + virtual void dispatchWillSendRequest(WebCore::DocumentLoader*, unsigned long identifier, WebCore::ResourceRequest&, const WebCore::ResourceResponse& redirectResponse); + virtual void dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::AuthenticationChallenge&); + virtual void dispatchDidCancelAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::AuthenticationChallenge&); + virtual void dispatchDidReceiveResponse(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::ResourceResponse&); + virtual void dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int lengthReceived); + virtual void dispatchDidFinishLoading(WebCore::DocumentLoader*, unsigned long identifier); + virtual void dispatchDidFailLoading(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::ResourceError&); + + virtual NSCachedURLResponse* willCacheResponse(WebCore::DocumentLoader*, unsigned long identifier, NSCachedURLResponse*) const; + + virtual void dispatchDidHandleOnloadEvents(); + virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(); + virtual void dispatchDidCancelClientRedirect(); + virtual void dispatchWillPerformClientRedirect(const WebCore::KURL&, double interval, double fireDate); + virtual void dispatchDidChangeLocationWithinPage(); + virtual void dispatchWillClose(); + virtual void dispatchDidReceiveIcon(); + virtual void dispatchDidStartProvisionalLoad(); + virtual void dispatchDidReceiveTitle(const WebCore::String& title); + virtual void dispatchDidCommitLoad(); + virtual void dispatchDidFailProvisionalLoad(const WebCore::ResourceError&); + virtual void dispatchDidFailLoad(const WebCore::ResourceError&); + virtual void dispatchDidFinishDocumentLoad(); + virtual void dispatchDidFinishLoad(); + virtual void dispatchDidFirstLayout(); + + virtual WebCore::Frame* dispatchCreatePage(); + virtual void dispatchShow(); + + virtual void dispatchDecidePolicyForMIMEType(WebCore::FramePolicyFunction, + const WebCore::String& MIMEType, const WebCore::ResourceRequest&); + virtual void dispatchDecidePolicyForNewWindowAction(WebCore::FramePolicyFunction, + const WebCore::NavigationAction&, const WebCore::ResourceRequest&, PassRefPtr<WebCore::FormState>, const WebCore::String& frameName); + virtual void dispatchDecidePolicyForNavigationAction(WebCore::FramePolicyFunction, + const WebCore::NavigationAction&, const WebCore::ResourceRequest&, PassRefPtr<WebCore::FormState>); + virtual void cancelPolicyCheck(); + + virtual void dispatchUnableToImplementPolicy(const WebCore::ResourceError&); + + virtual void dispatchWillSubmitForm(WebCore::FramePolicyFunction, PassRefPtr<WebCore::FormState>); + + virtual void dispatchDidLoadMainResource(WebCore::DocumentLoader*); + virtual void revertToProvisionalState(WebCore::DocumentLoader*); + virtual void setMainDocumentError(WebCore::DocumentLoader*, const WebCore::ResourceError&); + virtual bool dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, int length); + + virtual void willChangeEstimatedProgress(); + virtual void didChangeEstimatedProgress(); + virtual void postProgressStartedNotification(); + virtual void postProgressEstimateChangedNotification(); + virtual void postProgressFinishedNotification(); + + virtual void setMainFrameDocumentReady(bool); + + virtual void startDownload(const WebCore::ResourceRequest&); + + virtual void willChangeTitle(WebCore::DocumentLoader*); + virtual void didChangeTitle(WebCore::DocumentLoader*); + + virtual void committedLoad(WebCore::DocumentLoader*, const char*, int); + virtual void finishedLoading(WebCore::DocumentLoader*); + virtual void updateGlobalHistory(const WebCore::KURL&); + virtual bool shouldGoToHistoryItem(WebCore::HistoryItem*) const; + + virtual WebCore::ResourceError cancelledError(const WebCore::ResourceRequest&); + virtual WebCore::ResourceError blockedError(const WebCore::ResourceRequest&); + virtual WebCore::ResourceError cannotShowURLError(const WebCore::ResourceRequest&); + virtual WebCore::ResourceError interruptForPolicyChangeError(const WebCore::ResourceRequest&); + + virtual WebCore::ResourceError cannotShowMIMETypeError(const WebCore::ResourceResponse&); + virtual WebCore::ResourceError fileDoesNotExistError(const WebCore::ResourceResponse&); + virtual WebCore::ResourceError pluginWillHandleLoadError(const WebCore::ResourceResponse&); + + virtual bool shouldFallBack(const WebCore::ResourceError&); + + virtual WebCore::String userAgent(const WebCore::KURL&); + + virtual void savePlatformDataToCachedPage(WebCore::CachedPage*); + virtual void transitionToCommittedFromCachedPage(WebCore::CachedPage*); + virtual void transitionToCommittedForNewPage(); + + virtual bool canHandleRequest(const WebCore::ResourceRequest&) const; + virtual bool canShowMIMEType(const WebCore::String& MIMEType) const; + virtual bool representationExistsForURLScheme(const WebCore::String& URLScheme) const; + virtual WebCore::String generatedMIMETypeForURLScheme(const WebCore::String& URLScheme) const; + + virtual void frameLoadCompleted(); + virtual void saveViewStateToItem(WebCore::HistoryItem*); + virtual void restoreViewState(); + virtual void provisionalLoadStarted(); + virtual void didFinishLoad(); + virtual void prepareForDataSourceReplacement(); + virtual PassRefPtr<WebCore::DocumentLoader> createDocumentLoader(const WebCore::ResourceRequest&, const WebCore::SubstituteData&); + + virtual void setTitle(const WebCore::String& title, const WebCore::KURL&); + + virtual PassRefPtr<WebCore::Frame> createFrame(const WebCore::KURL& url, const WebCore::String& name, WebCore::HTMLFrameOwnerElement*, + const WebCore::String& referrer, bool allowsScrolling, int marginWidth, int marginHeight); + virtual WebCore::Widget* createPlugin(const WebCore::IntSize&, WebCore::Element*, const WebCore::KURL&, const Vector<WebCore::String>&, + const Vector<WebCore::String>&, const WebCore::String&, bool); + virtual void redirectDataToPlugin(WebCore::Widget* pluginWidget); + + virtual WebCore::Widget* createJavaAppletWidget(const WebCore::IntSize&, WebCore::Element*, const WebCore::KURL& baseURL, + const Vector<WebCore::String>& paramNames, const Vector<WebCore::String>& paramValues); + + virtual WebCore::ObjectContentType objectContentType(const WebCore::KURL& url, const WebCore::String& mimeType); + virtual WebCore::String overrideMediaType() const; + + virtual void windowObjectCleared(); + virtual void didPerformFirstNavigation() const; + + virtual void registerForIconNotification(bool listen); + +#if ENABLE(MAC_JAVA_BRIDGE) + virtual jobject javaApplet(NSView*); +#endif + + void setOriginalURLForDownload(WebDownload *, const WebCore::ResourceRequest&) const; + + RetainPtr<WebFramePolicyListener> setUpPolicyListener(WebCore::FramePolicyFunction); + + NSDictionary *actionDictionary(const WebCore::NavigationAction&, PassRefPtr<WebCore::FormState>) const; + + virtual bool canCachePage() const; + + RetainPtr<WebFrame> m_webFrame; + + RetainPtr<WebFramePolicyListener> m_policyListener; + WebCore::FramePolicyFunction m_policyFunction; +}; diff --git a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm new file mode 100644 index 0000000..eb538e0 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm @@ -0,0 +1,1599 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebFrameLoaderClient.h" + +// Terrible hack; lets us get at the WebFrame private structure. +#define private public +#import "WebFrame.h" +#undef private + +#import "DOMElementInternal.h" +#import "WebBackForwardList.h" +#import "WebCachedPagePlatformData.h" +#import "WebChromeClient.h" +#import "WebDataSourceInternal.h" +#import "WebDocumentInternal.h" +#import "WebDocumentLoaderMac.h" +#import "WebDownloadInternal.h" +#import "WebDynamicScrollBarsViewInternal.h" +#import "WebElementDictionary.h" +#import "WebFormDelegate.h" +#import "WebFrameInternal.h" +#import "WebFrameLoadDelegate.h" +#import "WebFrameViewInternal.h" +#import "WebHTMLRepresentationPrivate.h" +#import "WebHTMLViewInternal.h" +#import "WebHistoryItemInternal.h" +#import "WebHistoryInternal.h" +#import "WebIconDatabaseInternal.h" +#import "WebKitErrorsPrivate.h" +#import "WebKitLogging.h" +#import "WebKitNSStringExtras.h" +#import "WebNSURLExtras.h" +#import "WebBaseNetscapePluginView.h" +#import "WebNetscapePluginPackage.h" +#import "WebNullPluginView.h" +#import "WebPanelAuthenticationHandler.h" +#import "WebPluginController.h" +#import "WebPluginPackage.h" +#import "WebPluginViewFactoryPrivate.h" +#import "WebPolicyDelegate.h" +#import "WebPolicyDelegatePrivate.h" +#import "WebPreferences.h" +#import "WebResourceLoadDelegate.h" +#import "WebResourcePrivate.h" +#import "WebUIDelegate.h" +#import "WebUIDelegatePrivate.h" +#import "WebViewInternal.h" +#import <WebKitSystemInterface.h> +#import <WebCore/AuthenticationMac.h> +#import <WebCore/BlockExceptions.h> +#import <WebCore/CachedPage.h> +#import <WebCore/Chrome.h> +#import <WebCore/Document.h> +#import <WebCore/DocumentLoader.h> +#import <WebCore/EventHandler.h> +#import <WebCore/FormState.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameLoader.h> +#import <WebCore/FrameLoaderTypes.h> +#import <WebCore/FrameTree.h> +#import <WebCore/FrameView.h> +#import <WebCore/HTMLFormElement.h> +#import <WebCore/HTMLFrameElement.h> +#import <WebCore/HTMLFrameOwnerElement.h> +#import <WebCore/HTMLNames.h> +#import <WebCore/HistoryItem.h> +#import <WebCore/HitTestResult.h> +#import <WebCore/IconDatabase.h> +#import <WebCore/LoaderNSURLExtras.h> +#import <WebCore/MIMETypeRegistry.h> +#import <WebCore/MouseEvent.h> +#import <WebCore/Page.h> +#import <WebCore/PlatformString.h> +#import <WebCore/ResourceError.h> +#import <WebCore/ResourceHandle.h> +#import <WebCore/ResourceLoader.h> +#import <WebCore/ResourceRequest.h> +#import <WebCore/ScriptController.h> +#import <WebCore/SharedBuffer.h> +#import <WebCore/WebCoreObjCExtras.h> +#import <WebCore/Widget.h> +#import <WebKit/DOMElement.h> +#import <WebKit/DOMHTMLFormElement.h> +#import <wtf/PassRefPtr.h> + +#if ENABLE(MAC_JAVA_BRIDGE) +#import "WebJavaPlugIn.h" +#endif + +using namespace WebCore; +using namespace HTMLNames; + +#if ENABLE(MAC_JAVA_BRIDGE) +@interface NSView (WebJavaPluginDetails) +- (jobject)pollForAppletInWindow:(NSWindow *)window; +@end +#endif + +@interface NSURLDownload (WebNSURLDownloadDetails) +- (void)_setOriginatingURL:(NSURL *)originatingURL; +@end + +// For backwards compatibility with older WebKit plug-ins. +NSString *WebPluginBaseURLKey = @"WebPluginBaseURL"; +NSString *WebPluginAttributesKey = @"WebPluginAttributes"; +NSString *WebPluginContainerKey = @"WebPluginContainer"; + +@interface WebFramePolicyListener : NSObject <WebPolicyDecisionListener, WebFormSubmissionListener> { + Frame* m_frame; +} +- (id)initWithWebCoreFrame:(Frame*)frame; +- (void)invalidate; +@end + +static inline WebDataSource *dataSource(DocumentLoader* loader) +{ + return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil; +} + +WebFrameLoaderClient::WebFrameLoaderClient(WebFrame *webFrame) + : m_webFrame(webFrame) + , m_policyFunction(0) +{ +} + +void WebFrameLoaderClient::frameLoaderDestroyed() +{ + [m_webFrame.get() _clearCoreFrame]; + delete this; +} + +bool WebFrameLoaderClient::hasWebView() const +{ + return [m_webFrame.get() webView] != nil; +} + +void WebFrameLoaderClient::makeRepresentation(DocumentLoader* loader) +{ + [dataSource(loader) _makeRepresentation]; +} + +bool WebFrameLoaderClient::hasHTMLView() const +{ + NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView]; + return [view isKindOfClass:[WebHTMLView class]]; +} + +void WebFrameLoaderClient::forceLayout() +{ + NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView]; + if ([view isKindOfClass:[WebHTMLView class]]) + [(WebHTMLView *)view setNeedsToApplyStyles:YES]; + [view setNeedsLayout:YES]; + [view layout]; +} + +void WebFrameLoaderClient::forceLayoutForNonHTML() +{ + WebFrameView *thisView = m_webFrame->_private->webFrameView; + if (!thisView) // Viewless mode. + return; + NSView <WebDocumentView> *thisDocumentView = [thisView documentView]; + ASSERT(thisDocumentView != nil); + + // Tell the just loaded document to layout. This may be necessary + // for non-html content that needs a layout message. + if (!([[m_webFrame.get() _dataSource] _isDocumentHTML])) { + [thisDocumentView setNeedsLayout:YES]; + [thisDocumentView layout]; + [thisDocumentView setNeedsDisplay:YES]; + } +} + +void WebFrameLoaderClient::setCopiesOnScroll() +{ + [[[m_webFrame->_private->webFrameView _scrollView] contentView] setCopiesOnScroll:YES]; +} + +void WebFrameLoaderClient::detachedFromParent2() +{ + //remove any NetScape plugins that are children of this frame because they are about to be detached + WebView *webView = getWebView(m_webFrame.get()); + [webView removePluginInstanceViewsFor:(m_webFrame.get())]; + [m_webFrame->_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior +} + +void WebFrameLoaderClient::detachedFromParent3() +{ + [m_webFrame->_private->webFrameView release]; + m_webFrame->_private->webFrameView = nil; +} + +void WebFrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest& initialRequest, const ResourceResponse& response) +{ + id proxy = handle->releaseProxy(); + ASSERT(proxy); + + WebView *webView = getWebView(m_webFrame.get()); + WebDownload *download = [WebDownload _downloadWithLoadingConnection:handle->connection() + request:request.nsURLRequest() + response:response.nsURLResponse() + delegate:[webView downloadDelegate] + proxy:proxy]; + + setOriginalURLForDownload(download, initialRequest); +} + +void WebFrameLoaderClient::setOriginalURLForDownload(WebDownload *download, const ResourceRequest& initialRequest) const +{ + NSURLRequest *initialURLRequest = initialRequest.nsURLRequest(); + NSURL *originalURL = nil; + + // If there was no referrer, don't traverse the back/forward history + // since this download was initiated directly. <rdar://problem/5294691> + if ([initialURLRequest valueForHTTPHeaderField:@"Referer"]) { + // find the first item in the history that was originated by the user + WebView *webView = getWebView(m_webFrame.get()); + WebBackForwardList *history = [webView backForwardList]; + int backListCount = [history backListCount]; + for (int backIndex = 0; backIndex <= backListCount && !originalURL; backIndex++) { + // FIXME: At one point we had code here to check a "was user gesture" flag. + // Do we need to restore that logic? + originalURL = [[history itemAtIndex:-backIndex] URL]; + } + } + + if (!originalURL) + originalURL = [initialURLRequest URL]; + + if ([download respondsToSelector:@selector(_setOriginatingURL:)]) { + NSString *scheme = [originalURL scheme]; + NSString *host = [originalURL host]; + if (scheme && host && [scheme length] && [host length]) { + NSNumber *port = [originalURL port]; + if (port && [port intValue] < 0) + port = nil; + NSString *hostOnlyURLString; + if (port) + hostOnlyURLString = [[NSString alloc] initWithFormat:@"%@://%@:%d", scheme, host, [port intValue]]; + else + hostOnlyURLString = [[NSString alloc] initWithFormat:@"%@://%@", scheme, host]; + NSURL *hostOnlyURL = [[NSURL alloc] initWithString:hostOnlyURLString]; + [hostOnlyURLString release]; + [download _setOriginatingURL:hostOnlyURL]; + [hostOnlyURL release]; + } + } +} + +bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader* loader, const ResourceRequest& request, const ResourceResponse& response, int length) +{ + WebView *webView = getWebView(m_webFrame.get()); + WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView); + if (!implementations->didLoadResourceFromMemoryCacheFunc) + return false; + + CallResourceLoadDelegate(implementations->didLoadResourceFromMemoryCacheFunc, webView, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:), request.nsURLRequest(), response.nsURLResponse(), length, dataSource(loader)); + return true; +} + +void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request) +{ + WebView *webView = getWebView(m_webFrame.get()); + WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView); + + id object = nil; + BOOL shouldRelease = NO; + if (implementations->identifierForRequestFunc) + object = CallResourceLoadDelegate(implementations->identifierForRequestFunc, webView, @selector(webView:identifierForInitialRequest:fromDataSource:), request.nsURLRequest(), dataSource(loader)); + else { + object = [[NSObject alloc] init]; + shouldRelease = YES; + } + + [webView _addObject:object forIdentifier:identifier]; + + if (shouldRelease) + [object release]; +} + +void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) +{ + WebView *webView = getWebView(m_webFrame.get()); + WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView); + + if (redirectResponse.isNull()) + static_cast<WebDocumentLoaderMac*>(loader)->increaseLoadCount(identifier); + + if (implementations->willSendRequestFunc) + request = (NSURLRequest *)CallResourceLoadDelegate(implementations->willSendRequestFunc, webView, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:), [webView _objectForIdentifier:identifier], request.nsURLRequest(), redirectResponse.nsURLResponse(), dataSource(loader)); +} + +void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge) +{ + WebView *webView = getWebView(m_webFrame.get()); + WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView); + + NSURLAuthenticationChallenge *webChallenge = mac(challenge); + + if (implementations->didReceiveAuthenticationChallengeFunc) { + if (id resource = [webView _objectForIdentifier:identifier]) { + CallResourceLoadDelegate(implementations->didReceiveAuthenticationChallengeFunc, webView, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:), resource, webChallenge, dataSource(loader)); + return; + } + } + + NSWindow *window = [webView hostWindow] ? [webView hostWindow] : [webView window]; + [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:webChallenge window:window]; +} + +void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge&challenge) +{ + WebView *webView = getWebView(m_webFrame.get()); + WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView); + NSURLAuthenticationChallenge *webChallenge = mac(challenge); + + if (implementations->didCancelAuthenticationChallengeFunc) { + if (id resource = [webView _objectForIdentifier:identifier]) { + CallResourceLoadDelegate(implementations->didCancelAuthenticationChallengeFunc, webView, @selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:), resource, webChallenge, dataSource(loader)); + return; + } + } + + [(WebPanelAuthenticationHandler *)[WebPanelAuthenticationHandler sharedHandler] cancelAuthentication:webChallenge]; +} + +void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response) +{ + WebView *webView = getWebView(m_webFrame.get()); + WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView); + if (implementations->didReceiveResponseFunc) { + if (id resource = [webView _objectForIdentifier:identifier]) + CallResourceLoadDelegate(implementations->didReceiveResponseFunc, webView, @selector(webView:resource:didReceiveResponse:fromDataSource:), resource, response.nsURLResponse(), dataSource(loader)); + } +} + +NSCachedURLResponse* WebFrameLoaderClient::willCacheResponse(DocumentLoader* loader, unsigned long identifier, NSCachedURLResponse* response) const +{ + WebView *webView = getWebView(m_webFrame.get()); + WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView); + + if (implementations->willCacheResponseFunc) { + if (id resource = [webView _objectForIdentifier:identifier]) + return CallResourceLoadDelegate(implementations->willCacheResponseFunc, webView, @selector(webView:resource:willCacheResponse:fromDataSource:), resource, response, dataSource(loader)); + } + + return response; +} + +void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int lengthReceived) +{ + WebView *webView = getWebView(m_webFrame.get()); + WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView); + if (implementations->didReceiveContentLengthFunc) { + if (id resource = [webView _objectForIdentifier:identifier]) + CallResourceLoadDelegate(implementations->didReceiveContentLengthFunc, webView, @selector(webView:resource:didReceiveContentLength:fromDataSource:), resource, (NSInteger)lengthReceived, dataSource(loader)); + } +} + +void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier) +{ + WebView *webView = getWebView(m_webFrame.get()); + WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView); + + if (implementations->didFinishLoadingFromDataSourceFunc) { + if (id resource = [webView _objectForIdentifier:identifier]) + CallResourceLoadDelegate(implementations->didFinishLoadingFromDataSourceFunc, webView, @selector(webView:resource:didFinishLoadingFromDataSource:), resource, dataSource(loader)); + } + + [webView _removeObjectForIdentifier:identifier]; + + static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier); +} + +void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error) +{ + WebView *webView = getWebView(m_webFrame.get()); + WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView); + + if (implementations->didFailLoadingWithErrorFromDataSourceFunc) { + if (id resource = [webView _objectForIdentifier:identifier]) + CallResourceLoadDelegate(implementations->didFailLoadingWithErrorFromDataSourceFunc, webView, @selector(webView:resource:didFailLoadingWithError:fromDataSource:), resource, (NSError *)error, dataSource(loader)); + } + + [webView _removeObjectForIdentifier:identifier]; + + static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier); +} + +void WebFrameLoaderClient::dispatchDidHandleOnloadEvents() +{ + WebView *webView = getWebView(m_webFrame.get()); + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didHandleOnloadEventsForFrameFunc) + CallFrameLoadDelegate(implementations->didHandleOnloadEventsForFrameFunc, webView, @selector(webView:didHandleOnloadEventsForFrame:), m_webFrame.get()); +} + +void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad() +{ + WebView *webView = getWebView(m_webFrame.get()); + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didReceiveServerRedirectForProvisionalLoadForFrameFunc) + CallFrameLoadDelegate(implementations->didReceiveServerRedirectForProvisionalLoadForFrameFunc, webView, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:), m_webFrame.get()); +} + +void WebFrameLoaderClient::dispatchDidCancelClientRedirect() +{ + WebView *webView = getWebView(m_webFrame.get()); + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didCancelClientRedirectForFrameFunc) + CallFrameLoadDelegate(implementations->didCancelClientRedirectForFrameFunc, webView, @selector(webView:didCancelClientRedirectForFrame:), m_webFrame.get()); +} + +void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& url, double delay, double fireDate) +{ + WebView *webView = getWebView(m_webFrame.get()); + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->willPerformClientRedirectToURLDelayFireDateForFrameFunc) { + NSURL *cocoaURL = url; + CallFrameLoadDelegate(implementations->willPerformClientRedirectToURLDelayFireDateForFrameFunc, webView, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:), cocoaURL, delay, [NSDate dateWithTimeIntervalSince1970:fireDate], m_webFrame.get()); + } +} + +void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage() +{ + WebView *webView = getWebView(m_webFrame.get()); + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didChangeLocationWithinPageForFrameFunc) + CallFrameLoadDelegate(implementations->didChangeLocationWithinPageForFrameFunc, webView, @selector(webView:didChangeLocationWithinPageForFrame:), m_webFrame.get()); +} + +void WebFrameLoaderClient::dispatchWillClose() +{ + WebView *webView = getWebView(m_webFrame.get()); + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->willCloseFrameFunc) + CallFrameLoadDelegate(implementations->willCloseFrameFunc, webView, @selector(webView:willCloseFrame:), m_webFrame.get()); +} + +void WebFrameLoaderClient::dispatchDidReceiveIcon() +{ + WebView *webView = getWebView(m_webFrame.get()); + ASSERT(m_webFrame == [webView mainFrame]); + [webView _dispatchDidReceiveIconFromWebFrame:m_webFrame.get()]; +} + +void WebFrameLoaderClient::dispatchDidStartProvisionalLoad() +{ + WebView *webView = getWebView(m_webFrame.get()); + [webView _didStartProvisionalLoadForFrame:m_webFrame.get()]; + + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didStartProvisionalLoadForFrameFunc) + CallFrameLoadDelegate(implementations->didStartProvisionalLoadForFrameFunc, webView, @selector(webView:didStartProvisionalLoadForFrame:), m_webFrame.get()); +} + +void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title) +{ + WebView *webView = getWebView(m_webFrame.get()); + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didReceiveTitleForFrameFunc) + CallFrameLoadDelegate(implementations->didReceiveTitleForFrameFunc, webView, @selector(webView:didReceiveTitle:forFrame:), (NSString *)title, m_webFrame.get()); +} + +void WebFrameLoaderClient::dispatchDidCommitLoad() +{ + // Tell the client we've committed this URL. + ASSERT([m_webFrame->_private->webFrameView documentView] != nil || ![getWebView(m_webFrame.get()) _usesDocumentViews]); + + WebView *webView = getWebView(m_webFrame.get()); + [webView _didCommitLoadForFrame:m_webFrame.get()]; + + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didCommitLoadForFrameFunc) + CallFrameLoadDelegate(implementations->didCommitLoadForFrameFunc, webView, @selector(webView:didCommitLoadForFrame:), m_webFrame.get()); +} + +void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error) +{ + WebView *webView = getWebView(m_webFrame.get()); + [webView _didFailProvisionalLoadWithError:error forFrame:m_webFrame.get()]; + + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didFailProvisionalLoadWithErrorForFrameFunc) + CallFrameLoadDelegate(implementations->didFailProvisionalLoadWithErrorForFrameFunc, webView, @selector(webView:didFailProvisionalLoadWithError:forFrame:), (NSError *)error, m_webFrame.get()); + + [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error]; +} + +void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error) +{ + WebView *webView = getWebView(m_webFrame.get()); + [webView _didFailLoadWithError:error forFrame:m_webFrame.get()]; + + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didFailLoadWithErrorForFrameFunc) + CallFrameLoadDelegate(implementations->didFailLoadWithErrorForFrameFunc, webView, @selector(webView:didFailLoadWithError:forFrame:), (NSError *)error, m_webFrame.get()); + + [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error]; +} + +void WebFrameLoaderClient::dispatchDidFinishDocumentLoad() +{ + WebView *webView = getWebView(m_webFrame.get()); + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didFinishDocumentLoadForFrameFunc) + CallFrameLoadDelegate(implementations->didFinishDocumentLoadForFrameFunc, webView, @selector(webView:didFinishDocumentLoadForFrame:), m_webFrame.get()); +} + +void WebFrameLoaderClient::dispatchDidFinishLoad() +{ + WebView *webView = getWebView(m_webFrame.get()); + [webView _didFinishLoadForFrame:m_webFrame.get()]; + + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didFinishLoadForFrameFunc) + CallFrameLoadDelegate(implementations->didFinishLoadForFrameFunc, webView, @selector(webView:didFinishLoadForFrame:), m_webFrame.get()); + + [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil]; +} + +void WebFrameLoaderClient::dispatchDidFirstLayout() +{ + WebView *webView = getWebView(m_webFrame.get()); + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didFirstLayoutInFrameFunc) + CallFrameLoadDelegate(implementations->didFirstLayoutInFrameFunc, webView, @selector(webView:didFirstLayoutInFrame:), m_webFrame.get()); +} + +Frame* WebFrameLoaderClient::dispatchCreatePage() +{ + WebView *currentWebView = getWebView(m_webFrame.get()); + NSDictionary *features = [[NSDictionary alloc] init]; + WebView *newWebView = [[currentWebView _UIDelegateForwarder] webView:currentWebView + createWebViewWithRequest:nil + windowFeatures:features]; + [features release]; + return core([newWebView mainFrame]); +} + +void WebFrameLoaderClient::dispatchShow() +{ + WebView *webView = getWebView(m_webFrame.get()); + [[webView _UIDelegateForwarder] webViewShow:webView]; +} + +void WebFrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction function, + const String& MIMEType, const ResourceRequest& request) +{ + WebView *webView = getWebView(m_webFrame.get()); + + [[webView _policyDelegateForwarder] webView:webView + decidePolicyForMIMEType:MIMEType + request:request.nsURLRequest() + frame:m_webFrame.get() + decisionListener:setUpPolicyListener(function).get()]; +} + +void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, + const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName) +{ + WebView *webView = getWebView(m_webFrame.get()); + [[webView _policyDelegateForwarder] webView:webView + decidePolicyForNewWindowAction:actionDictionary(action, formState) + request:request.nsURLRequest() + newFrameName:frameName + decisionListener:setUpPolicyListener(function).get()]; +} + +void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, + const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState) +{ + WebView *webView = getWebView(m_webFrame.get()); + [[webView _policyDelegateForwarder] webView:webView + decidePolicyForNavigationAction:actionDictionary(action, formState) + request:request.nsURLRequest() + frame:m_webFrame.get() + decisionListener:setUpPolicyListener(function).get()]; +} + +void WebFrameLoaderClient::cancelPolicyCheck() +{ + [m_policyListener.get() invalidate]; + m_policyListener = nil; + m_policyFunction = 0; +} + +void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error) +{ + WebView *webView = getWebView(m_webFrame.get()); + [[webView _policyDelegateForwarder] webView:webView unableToImplementPolicyWithError:error frame:m_webFrame.get()]; +} + +void WebFrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState) +{ + id <WebFormDelegate> formDelegate = [getWebView(m_webFrame.get()) _formDelegate]; + if (!formDelegate) { + (core(m_webFrame.get())->loader()->*function)(PolicyUse); + return; + } + + NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:formState->values().size()]; + HashMap<String, String>::const_iterator end = formState->values().end(); + for (HashMap<String, String>::const_iterator it = formState->values().begin(); it != end; ++it) + [dictionary setObject:it->second forKey:it->first]; + + CallFormDelegate(getWebView(m_webFrame.get()), @selector(frame:sourceFrame:willSubmitForm:withValues:submissionListener:), m_webFrame.get(), kit(formState->sourceFrame()), kit(formState->form()), dictionary, setUpPolicyListener(function).get()); + + [dictionary release]; +} + +void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader* loader) +{ +} + +void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader* loader) +{ + [dataSource(loader) _revertToProvisionalState]; +} + +void WebFrameLoaderClient::setMainDocumentError(DocumentLoader* loader, const ResourceError& error) +{ + [dataSource(loader) _setMainDocumentError:error]; +} + +void WebFrameLoaderClient::willChangeEstimatedProgress() +{ + [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebEstimatedProgressKey]; +} + +void WebFrameLoaderClient::didChangeEstimatedProgress() +{ + [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebEstimatedProgressKey]; +} + +void WebFrameLoaderClient::postProgressStartedNotification() +{ + [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressStartedNotification object:getWebView(m_webFrame.get())]; +} + +void WebFrameLoaderClient::postProgressEstimateChangedNotification() +{ + [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:getWebView(m_webFrame.get())]; +} + +void WebFrameLoaderClient::postProgressFinishedNotification() +{ + [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressFinishedNotification object:getWebView(m_webFrame.get())]; +} + +void WebFrameLoaderClient::setMainFrameDocumentReady(bool ready) +{ + [getWebView(m_webFrame.get()) setMainFrameDocumentReady:ready]; +} + +void WebFrameLoaderClient::startDownload(const ResourceRequest& request) +{ + // FIXME: Should download full request. + WebDownload *download = [getWebView(m_webFrame.get()) _downloadURL:request.url()]; + + setOriginalURLForDownload(download, request); +} + +void WebFrameLoaderClient::willChangeTitle(DocumentLoader* loader) +{ + // FIXME: Should do this only in main frame case, right? + [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebMainFrameTitleKey]; +} + +void WebFrameLoaderClient::didChangeTitle(DocumentLoader* loader) +{ + // FIXME: Should do this only in main frame case, right? + [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebMainFrameTitleKey]; +} + +void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length) +{ + NSData *nsData = [[NSData alloc] initWithBytesNoCopy:(void*)data length:length freeWhenDone:NO]; + [dataSource(loader) _receivedData:nsData]; + [nsData release]; +} + +void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader) +{ + [dataSource(loader) _finishedLoading]; +} + +void WebFrameLoaderClient::updateGlobalHistory(const KURL& url) +{ + NSURL *cocoaURL = url; + const String& pageTitle = core(m_webFrame.get())->loader()->documentLoader()->title(); + [[WebHistory optionalSharedHistory] _addItemForURL:cocoaURL title:pageTitle]; +} + +bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const +{ + WebView* view = getWebView(m_webFrame.get()); + WebHistoryItem *webItem = kit(item); + + return [[view _policyDelegateForwarder] webView:view shouldGoToHistoryItem:webItem]; +} + +ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request) +{ + return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:request.url()]; +} + +ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request) +{ + return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotUseRestrictedPort URL:request.url()]; +} + +ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request) +{ + return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotShowURL URL:request.url()]; +} + +ResourceError WebFrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request) +{ + return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorFrameLoadInterruptedByPolicyChange URL:request.url()]; +} + +ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response) +{ + return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:WebKitErrorCannotShowMIMEType URL:response.url()]; +} + +ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response) +{ + return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist URL:response.url()]; +} + +ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response) +{ + NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorPlugInWillHandleLoad + contentURL:response.url() + pluginPageURL:nil + pluginName:nil + MIMEType:response.mimeType()]; + return [error autorelease]; +} + +bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error) +{ + // FIXME: Needs to check domain. + // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent + // loading plugin content twice. See <rdar://problem/4258008> + return error.errorCode() != NSURLErrorCancelled && error.errorCode() != WebKitErrorPlugInWillHandleLoad; +} + +bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest& request) const +{ + Frame* frame = core(m_webFrame.get()); + Page* page = frame->page(); + BOOL forMainFrame = page && page->mainFrame() == frame; + return [WebView _canHandleRequest:request.nsURLRequest() forMainFrame:forMainFrame]; +} + +bool WebFrameLoaderClient::canShowMIMEType(const String& MIMEType) const +{ + return [WebView canShowMIMEType:MIMEType]; +} + +bool WebFrameLoaderClient::representationExistsForURLScheme(const String& URLScheme) const +{ + return [WebView _representationExistsForURLScheme:URLScheme]; +} + +String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& URLScheme) const +{ + return [WebView _generatedMIMETypeForURLScheme:URLScheme]; +} + +void WebFrameLoaderClient::frameLoadCompleted() +{ + // Note: Can be called multiple times. + // Even if already complete, we might have set a previous item on a frame that + // didn't do any data loading on the past transaction. Make sure to clear these out. + NSScrollView *sv = [m_webFrame->_private->webFrameView _scrollView]; + if ([getWebView(m_webFrame.get()) drawsBackground]) + [sv setDrawsBackground:YES]; + core(m_webFrame.get())->loader()->setPreviousHistoryItem(0); +} + + +void WebFrameLoaderClient::saveViewStateToItem(HistoryItem* item) +{ + if (!item) + return; + + NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView]; + + // we might already be detached when this is called from detachFromParent, in which + // case we don't want to override real data earlier gathered with (0,0) + if ([docView superview] && [docView conformsToProtocol:@protocol(_WebDocumentViewState)]) + item->setViewState([(id <_WebDocumentViewState>)docView viewState]); +} + +void WebFrameLoaderClient::restoreViewState() +{ + HistoryItem* currentItem = core(m_webFrame.get())->loader()->currentHistoryItem(); + ASSERT(currentItem); + + // FIXME: As the ASSERT attests, it seems we should always have a currentItem here. + // One counterexample is <rdar://problem/4917290> + // For now, to cover this issue in release builds, there is no technical harm to returning + // early and from a user standpoint - as in the above radar - the previous page load failed + // so there *is* no scroll state to restore! + if (!currentItem) + return; + + NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView]; + if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) { + id state = currentItem->viewState(); + if (state) { + [(id <_WebDocumentViewState>)docView setViewState:state]; + } + } +} + +void WebFrameLoaderClient::provisionalLoadStarted() +{ + // FIXME: This is OK as long as no one resizes the window, + // but in the case where someone does, it means garbage outside + // the occupied part of the scroll view. + [[m_webFrame->_private->webFrameView _scrollView] setDrawsBackground:NO]; +} + +void WebFrameLoaderClient::didFinishLoad() +{ + [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil]; +} + +void WebFrameLoaderClient::prepareForDataSourceReplacement() +{ + if (![m_webFrame.get() _dataSource]) { + ASSERT(!core(m_webFrame.get())->tree()->childCount()); + return; + } + + // Make sure that any work that is triggered by resigning first reponder can get done. + // The main example where this came up is the textDidEndEditing that is sent to the + // FormsDelegate (3223413). We need to do this before _detachChildren, since that will + // remove the views as a side-effect of freeing the frame, at which point we can't + // post the FormDelegate messages. + // + // Note that this can also take FirstResponder away from a child of our frameView that + // is not in a child frame's view. This is OK because we are in the process + // of loading new content, which will blow away all editors in this top frame, and if + // a non-editor is firstReponder it will not be affected by endEditingFor:. + // Potentially one day someone could write a DocView whose editors were not all + // replaced by loading new content, but that does not apply currently. + NSView *frameView = m_webFrame->_private->webFrameView; + NSWindow *window = [frameView window]; + NSResponder *firstResp = [window firstResponder]; + if ([firstResp isKindOfClass:[NSView class]] && [(NSView *)firstResp isDescendantOf:frameView]) + [window endEditingFor:firstResp]; +} + +PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData) +{ + RefPtr<WebDocumentLoaderMac> loader = WebDocumentLoaderMac::create(request, substituteData); + + WebDataSource *dataSource = [[WebDataSource alloc] _initWithDocumentLoader:loader.get()]; + loader->setDataSource(dataSource, getWebView(m_webFrame.get())); + [dataSource release]; + + return loader.release(); +} + +// FIXME: <rdar://problem/4880065> - Push Global History into WebCore +// Once that task is complete, this will go away +void WebFrameLoaderClient::setTitle(const String& title, const KURL& URL) +{ + NSURL* nsURL = URL; + nsURL = [nsURL _webkit_canonicalize]; + if(!nsURL) + return; + NSString *titleNSString = title; + [[[WebHistory optionalSharedHistory] itemForURL:nsURL] setTitle:titleNSString]; +} + +void WebFrameLoaderClient::savePlatformDataToCachedPage(CachedPage* cachedPage) +{ + WebCachedPagePlatformData* webPlatformData = new WebCachedPagePlatformData([m_webFrame->_private->webFrameView documentView]); + cachedPage->setCachedPagePlatformData(webPlatformData); +} + +void WebFrameLoaderClient::transitionToCommittedFromCachedPage(CachedPage* cachedPage) +{ + WebCachedPagePlatformData* platformData = reinterpret_cast<WebCachedPagePlatformData*>(cachedPage->cachedPagePlatformData()); + NSView <WebDocumentView> *cachedView = platformData->webDocumentView(); + ASSERT(cachedView != nil); + ASSERT(cachedPage->documentLoader()); + [cachedView setDataSource:dataSource(cachedPage->documentLoader())]; + + // clean up webkit plugin instances before WebHTMLView gets freed. + WebView *webView = getWebView(m_webFrame.get()); + [webView removePluginInstanceViewsFor:(m_webFrame.get())]; + + [m_webFrame->_private->webFrameView _setDocumentView:cachedView]; +} + +void WebFrameLoaderClient::transitionToCommittedForNewPage() +{ + WebFrameView *v = m_webFrame->_private->webFrameView; + WebDataSource *ds = [m_webFrame.get() _dataSource]; + + bool willProduceHTMLView = [[WebFrameView class] _viewClassForMIMEType:[ds _responseMIMEType]] == [WebHTMLView class]; + bool canSkipCreation = core(m_webFrame.get())->loader()->committingFirstRealLoad() && willProduceHTMLView; + if (canSkipCreation) { + [[v documentView] setDataSource:ds]; + return; + } + + // Don't suppress scrollbars before the view creation if we're making the view for a non-HTML view. + if (!willProduceHTMLView) + [[v _scrollView] setScrollBarsSuppressed:NO repaintOnUnsuppress:NO]; + + // clean up webkit plugin instances before WebHTMLView gets freed. + WebView *webView = getWebView(m_webFrame.get()); + [webView removePluginInstanceViewsFor:(m_webFrame.get())]; + + BOOL useDocumentViews = [webView _usesDocumentViews]; + NSView <WebDocumentView> *documentView = nil; + if (useDocumentViews) { + documentView = [v _makeDocumentViewForDataSource:ds]; + if (!documentView) + return; + } + + // FIXME: Could we skip some of this work for a top-level view that is not a WebHTMLView? + + // If we own the view, delete the old one - otherwise the render m_frame will take care of deleting the view. + Frame* coreFrame = core(m_webFrame.get()); + Page* page = coreFrame->page(); + bool isMainFrame = coreFrame == page->mainFrame(); + if (isMainFrame && coreFrame->view()) + coreFrame->view()->setParentVisible(false); + coreFrame->setView(0); + FrameView* coreView; + if (useDocumentViews) + coreView = new FrameView(coreFrame); + else + coreView = new FrameView(coreFrame, IntSize([webView bounds].size)); + coreFrame->setView(coreView); + coreView->deref(); // FIXME: Eliminate this crazy refcounting! + + [m_webFrame.get() _updateBackgroundAndUpdatesWhileOffscreen]; + + [v _install]; + + if (isMainFrame) + coreView->setParentVisible(true); + + // Call setDataSource on the document view after it has been placed in the view hierarchy. + // This what we for the top-level view, so should do this for views in subframes as well. + [documentView setDataSource:ds]; + + if (HTMLFrameOwnerElement* owner = coreFrame->ownerElement()) + coreFrame->view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); + +} + +RetainPtr<WebFramePolicyListener> WebFrameLoaderClient::setUpPolicyListener(FramePolicyFunction function) +{ + // FIXME: <rdar://5634381> We need to support multiple active policy listeners. + + [m_policyListener.get() invalidate]; + + WebFramePolicyListener *listener = [[WebFramePolicyListener alloc] initWithWebCoreFrame:core(m_webFrame.get())]; + m_policyListener = listener; + [listener release]; + m_policyFunction = function; + + return listener; +} + +void WebFrameLoaderClient::receivedPolicyDecison(PolicyAction action) +{ + ASSERT(m_policyListener); + ASSERT(m_policyFunction); + + FramePolicyFunction function = m_policyFunction; + + m_policyListener = nil; + m_policyFunction = 0; + + (core(m_webFrame.get())->loader()->*function)(action); +} + +String WebFrameLoaderClient::userAgent(const KURL& url) +{ + WebView *webView = getWebView(m_webFrame.get()); + ASSERT(webView); + + // We should never get here with nil for the WebView unless there is a bug somewhere else. + // But if we do, it's better to return the empty string than just crashing on the spot. + // Most other call sites are tolerant of nil because of Objective-C behavior, but this one + // is not because the return value of _userAgentForURL is a const KURL&. + if (!webView) + return String(""); + + return [webView _userAgentForURL:url]; +} + +static const MouseEvent* findMouseEvent(const Event* event) +{ + for (const Event* e = event; e; e = e->underlyingEvent()) + if (e->isMouseEvent()) + return static_cast<const MouseEvent*>(e); + return 0; +} + +NSDictionary *WebFrameLoaderClient::actionDictionary(const NavigationAction& action, PassRefPtr<FormState> formState) const +{ + unsigned modifierFlags = 0; + const Event* event = action.event(); + if (const UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event))) { + if (keyStateEvent->ctrlKey()) + modifierFlags |= NSControlKeyMask; + if (keyStateEvent->altKey()) + modifierFlags |= NSAlternateKeyMask; + if (keyStateEvent->shiftKey()) + modifierFlags |= NSShiftKeyMask; + if (keyStateEvent->metaKey()) + modifierFlags |= NSCommandKeyMask; + } + + NSURL *originalURL = action.url(); + + NSMutableDictionary *result = [NSMutableDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey, + [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey, + originalURL, WebActionOriginalURLKey, + nil]; + + if (const MouseEvent* mouseEvent = findMouseEvent(event)) { + IntPoint point(mouseEvent->pageX(), mouseEvent->pageY()); + WebElementDictionary *element = [[WebElementDictionary alloc] + initWithHitTestResult:core(m_webFrame.get())->eventHandler()->hitTestResultAtPoint(point, false)]; + [result setObject:element forKey:WebActionElementKey]; + [element release]; + + [result setObject:[NSNumber numberWithInt:mouseEvent->button()] forKey:WebActionButtonKey]; + } + + if (formState) { + ASSERT(formState->form()); + [result setObject:kit(formState->form()) forKey:WebActionFormKey]; + } + + return result; +} + +bool WebFrameLoaderClient::canCachePage() const +{ + // We can only cache HTML pages right now + return [[[m_webFrame.get() _dataSource] representation] isKindOfClass:[WebHTMLRepresentation class]]; +} + +PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, + const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + ASSERT(m_webFrame); + + WebFrameView *childView = [getWebView(m_webFrame.get()) _usesDocumentViews] ? [[WebFrameView alloc] init] : nil; + + RefPtr<Frame> result = [WebFrame _createSubframeWithOwnerElement:ownerElement frameName:name frameView:childView]; + [childView release]; + + WebFrame *newFrame = kit(result.get()); + + if ([newFrame _dataSource]) + [[newFrame _dataSource] _documentLoader]->setOverrideEncoding([[m_webFrame.get() _dataSource] _documentLoader]->overrideEncoding()); + + // The creation of the frame may have run arbitrary JavaScript that removed it from the page already. + if (!result->page()) + return 0; + + core(m_webFrame.get())->loader()->loadURLIntoChildFrame(url, referrer, result.get()); + + // The frame's onload handler may have removed it from the document. + if (!result->tree()->parent()) + return 0; + + return result.release(); + + END_BLOCK_OBJC_EXCEPTIONS; + + return 0; +} + +ObjectContentType WebFrameLoaderClient::objectContentType(const KURL& url, const String& mimeType) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + // This is a quirk that ensures Tiger Mail's WebKit plug-in will load during layout + // and not attach time. (5520541) + static BOOL isTigerMail = WKAppVersionCheckLessThan(@"com.apple.mail", -1, 3.0); + if (isTigerMail && mimeType == "application/x-apple-msg-attachment") + return ObjectContentNetscapePlugin; + + String type = mimeType; + + if (type.isEmpty()) { + // Try to guess the MIME type based off the extension. + NSURL *URL = url; + NSString *extension = [[URL path] pathExtension]; + if ([extension length] > 0) { + type = WKGetMIMETypeForExtension(extension); + if (type.isEmpty()) { + // If no MIME type is specified, use a plug-in if we have one that can handle the extension. + if (WebBasePluginPackage *package = [getWebView(m_webFrame.get()) _pluginForExtension:extension]) { + if ([package isKindOfClass:[WebPluginPackage class]]) + return ObjectContentOtherPlugin; +#if ENABLE(NETSCAPE_PLUGIN_API) + else { + ASSERT([package isKindOfClass:[WebNetscapePluginPackage class]]); + return ObjectContentNetscapePlugin; + } +#endif + } + } + } + } + + if (type.isEmpty()) + return ObjectContentFrame; // Go ahead and hope that we can display the content. + + if (MIMETypeRegistry::isSupportedImageMIMEType(type)) + return ObjectContentImage; + + WebBasePluginPackage *package = [getWebView(m_webFrame.get()) _pluginForMIMEType:type]; + if (package) { +#if ENABLE(NETSCAPE_PLUGIN_API) + if ([package isKindOfClass:[WebNetscapePluginPackage class]]) + return ObjectContentNetscapePlugin; +#endif + ASSERT([package isKindOfClass:[WebPluginPackage class]]); + return ObjectContentOtherPlugin; + } + + if ([WebFrameView _viewClassForMIMEType:type]) + return ObjectContentFrame; + + return ObjectContentNone; + + END_BLOCK_OBJC_EXCEPTIONS; + + return ObjectContentNone; +} + +static NSMutableArray* kit(const Vector<String>& vector) +{ + unsigned len = vector.size(); + NSMutableArray* array = [NSMutableArray arrayWithCapacity:len]; + for (unsigned x = 0; x < len; x++) + [array addObject:vector[x]]; + return array; +} + +static String parameterValue(const Vector<String>& paramNames, const Vector<String>& paramValues, const String& name) +{ + size_t size = paramNames.size(); + ASSERT(size == paramValues.size()); + for (size_t i = 0; i < size; ++i) { + if (equalIgnoringCase(paramNames[i], name)) + return paramValues[i]; + } + return String(); +} + +static NSView *pluginView(WebFrame *frame, WebPluginPackage *pluginPackage, + NSArray *attributeNames, NSArray *attributeValues, NSURL *baseURL, + DOMElement *element, BOOL loadManually) +{ + WebHTMLView *docView = (WebHTMLView *)[[frame frameView] documentView]; + ASSERT([docView isKindOfClass:[WebHTMLView class]]); + + WebPluginController *pluginController = [docView _pluginController]; + + // Store attributes in a dictionary so they can be passed to WebPlugins. + NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames]; + + [pluginPackage load]; + Class viewFactory = [pluginPackage viewFactory]; + + NSView *view = nil; + NSDictionary *arguments = nil; + + if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) { + arguments = [NSDictionary dictionaryWithObjectsAndKeys: + baseURL, WebPlugInBaseURLKey, + attributes, WebPlugInAttributesKey, + pluginController, WebPlugInContainerKey, + [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey, + [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey, + element, WebPlugInContainingElementKey, + nil]; + LOG(Plugins, "arguments:\n%@", arguments); + } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) { + arguments = [NSDictionary dictionaryWithObjectsAndKeys: + baseURL, WebPluginBaseURLKey, + attributes, WebPluginAttributesKey, + pluginController, WebPluginContainerKey, + element, WebPlugInContainingElementKey, + nil]; + LOG(Plugins, "arguments:\n%@", arguments); + } + + view = [WebPluginController plugInViewWithArguments:arguments fromPluginPackage:pluginPackage]; + [attributes release]; + return view; +} + +class PluginWidget : public Widget { +public: + PluginWidget(NSView *view = 0) + : Widget(view) + { + } + + virtual void invalidateRect(const IntRect& rect) + { + [platformWidget() setNeedsDisplayInRect:rect]; + } +}; + +#if ENABLE(NETSCAPE_PLUGIN_API) + +class NetscapePluginWidget : public PluginWidget { +public: + NetscapePluginWidget(WebBaseNetscapePluginView *view) + : PluginWidget(view) + { + } + + virtual void handleEvent(Event*) + { + Frame* frame = Frame::frameForWidget(this); + if (!frame) + return; + + NSEvent* event = frame->eventHandler()->currentNSEvent(); + if ([event type] == NSMouseMoved) + [(WebBaseNetscapePluginView *)platformWidget() handleMouseMoved:event]; + } + +}; + +#endif // ENABLE(NETSCAPE_PLUGIN_API) + +Widget* WebFrameLoaderClient::createPlugin(const IntSize& size, Element* element, const KURL& url, + const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + ASSERT(paramNames.size() == paramValues.size()); + + int errorCode = 0; + + WebView *webView = getWebView(m_webFrame.get()); + SEL selector = @selector(webView:plugInViewWithArguments:); + NSURL *URL = url; + + if ([[webView UIDelegate] respondsToSelector:selector]) { + NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:kit(paramValues) forKeys:kit(paramNames)]; + NSDictionary *arguments = [[NSDictionary alloc] initWithObjectsAndKeys: + attributes, WebPlugInAttributesKey, + [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey, + [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey, + kit(element), WebPlugInContainingElementKey, + URL, WebPlugInBaseURLKey, // URL might be nil, so add it last + nil]; + + NSView *view = CallUIDelegate(webView, selector, arguments); + + [attributes release]; + [arguments release]; + + if (view) + return new PluginWidget(view); + } + + NSString *MIMEType; + WebBasePluginPackage *pluginPackage; + if (mimeType.isEmpty()) { + MIMEType = nil; + pluginPackage = nil; + } else { + MIMEType = mimeType; + pluginPackage = [webView _pluginForMIMEType:mimeType]; + } + + NSString *extension = [[URL path] pathExtension]; + if (!pluginPackage && [extension length] != 0) { + pluginPackage = [webView _pluginForExtension:extension]; + if (pluginPackage) { + NSString *newMIMEType = [pluginPackage MIMETypeForExtension:extension]; + if ([newMIMEType length] != 0) + MIMEType = newMIMEType; + } + } + + NSView *view = nil; + + Document* document = core(m_webFrame.get())->document(); + NSURL *baseURL = document->baseURL(); + if (pluginPackage) { + if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) + view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, kit(paramNames), kit(paramValues), baseURL, kit(element), loadManually); + +#if ENABLE(NETSCAPE_PLUGIN_API) + else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) { + WebBaseNetscapePluginView *embeddedView = [[[WebBaseNetscapePluginView alloc] + initWithFrame:NSMakeRect(0, 0, size.width(), size.height()) + pluginPackage:(WebNetscapePluginPackage *)pluginPackage + URL:URL + baseURL:baseURL + MIMEType:MIMEType + attributeKeys:kit(paramNames) + attributeValues:kit(paramValues) + loadManually:loadManually + DOMElement:kit(element)] autorelease]; + + return new NetscapePluginWidget(embeddedView); + } +#endif + } else + errorCode = WebKitErrorCannotFindPlugIn; + + if (!errorCode && !view) + errorCode = WebKitErrorCannotLoadPlugIn; + + if (errorCode) { + NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode + contentURL:URL + pluginPageURL:document->completeURL(parseURL(parameterValue(paramNames, paramValues, "pluginspage"))) + pluginName:[pluginPackage name] + MIMEType:MIMEType]; + WebNullPluginView *nullView = [[[WebNullPluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height()) + error:error DOMElement:kit(element)] autorelease]; + view = nullView; + [error release]; + } + + ASSERT(view); + return new PluginWidget(view); + + END_BLOCK_OBJC_EXCEPTIONS; + + return 0; +} + +void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + WebHTMLRepresentation *representation = (WebHTMLRepresentation *)[[m_webFrame.get() _dataSource] representation]; + + NSView *pluginView = pluginWidget->platformWidget(); + +#if ENABLE(NETSCAPE_PLUGIN_API) + if ([pluginView isKindOfClass:[WebBaseNetscapePluginView class]]) + [representation _redirectDataToManualLoader:(WebBaseNetscapePluginView *)pluginView forPluginView:pluginView]; + else { +#else + { +#endif + WebHTMLView *documentView = (WebHTMLView *)[[m_webFrame.get() frameView] documentView]; + ASSERT([documentView isKindOfClass:[WebHTMLView class]]); + [representation _redirectDataToManualLoader:[documentView _pluginController] forPluginView:pluginView]; + } + + END_BLOCK_OBJC_EXCEPTIONS; +} + +Widget* WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, Element* element, const KURL& baseURL, + const Vector<String>& paramNames, const Vector<String>& paramValues) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + NSView *view = nil; + + NSString *MIMEType = @"application/x-java-applet"; + + WebView *webView = getWebView(m_webFrame.get()); + + WebBasePluginPackage *pluginPackage = [webView _pluginForMIMEType:MIMEType]; + + if (pluginPackage) { + if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) { + // For some reason, the Java plug-in requires that we pass the dimension of the plug-in as attributes. + NSMutableArray *names = kit(paramNames); + NSMutableArray *values = kit(paramValues); + if (parameterValue(paramNames, paramValues, "width").isNull()) { + [names addObject:@"width"]; + [values addObject:[NSString stringWithFormat:@"%d", size.width()]]; + } + if (parameterValue(paramNames, paramValues, "height").isNull()) { + [names addObject:@"height"]; + [values addObject:[NSString stringWithFormat:@"%d", size.width()]]; + } + view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, names, values, baseURL, kit(element), NO); + } +#if ENABLE(NETSCAPE_PLUGIN_API) + else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) { + view = [[[WebBaseNetscapePluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height()) + pluginPackage:(WebNetscapePluginPackage *)pluginPackage + URL:nil + baseURL:baseURL + MIMEType:MIMEType + attributeKeys:kit(paramNames) + attributeValues:kit(paramValues) + loadManually:NO + DOMElement:kit(element)] autorelease]; + } else { + ASSERT_NOT_REACHED(); + } +#endif + } + + if (!view) { + NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorJavaUnavailable + contentURL:nil + pluginPageURL:nil + pluginName:[pluginPackage name] + MIMEType:MIMEType]; + view = [[[WebNullPluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height()) + error:error DOMElement:kit(element)] autorelease]; + [error release]; + } + + ASSERT(view); + return new PluginWidget(view); + + END_BLOCK_OBJC_EXCEPTIONS; + + return new PluginWidget; +} + +String WebFrameLoaderClient::overrideMediaType() const +{ + NSString* overrideType = [getWebView(m_webFrame.get()) mediaStyle]; + if (overrideType) + return overrideType; + return String(); +} + +void WebFrameLoaderClient::windowObjectCleared() +{ + Frame *frame = core(m_webFrame.get()); + ScriptController *script = frame->script(); + WebView *webView = getWebView(m_webFrame.get()); + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didClearWindowObjectForFrameFunc) { + CallFrameLoadDelegate(implementations->didClearWindowObjectForFrameFunc, webView, @selector(webView:didClearWindowObject:forFrame:), + script->windowScriptObject(), m_webFrame.get()); + } else if (implementations->windowScriptObjectAvailableFunc) { + CallFrameLoadDelegate(implementations->windowScriptObjectAvailableFunc, webView, @selector(webView:windowScriptObjectAvailable:), + script->windowScriptObject()); + } + + if ([webView scriptDebugDelegate]) { + [m_webFrame.get() _detachScriptDebugger]; + [m_webFrame.get() _attachScriptDebugger]; + } +} + +void WebFrameLoaderClient::registerForIconNotification(bool listen) +{ + [[m_webFrame.get() webView] _registerForIconNotification:listen]; +} + +void WebFrameLoaderClient::didPerformFirstNavigation() const +{ + WebPreferences *preferences = [[m_webFrame.get() webView] preferences]; + if ([preferences automaticallyDetectsCacheModel] && [preferences cacheModel] < WebCacheModelDocumentBrowser) + [preferences setCacheModel:WebCacheModelDocumentBrowser]; +} + +#if ENABLE(MAC_JAVA_BRIDGE) +jobject WebFrameLoaderClient::javaApplet(NSView* view) +{ + if ([view respondsToSelector:@selector(webPlugInGetApplet)]) + return [view webPlugInGetApplet]; + + // Compatibility with older versions of Java. + // FIXME: Do we still need this? + if ([view respondsToSelector:@selector(pollForAppletInWindow:)]) + return [view pollForAppletInWindow:[[m_webFrame.get() frameView] window]]; + + return 0; +} +#endif + +@implementation WebFramePolicyListener + +#ifndef BUILDING_ON_TIGER ++ (void)initialize +{ + WebCoreObjCFinalizeOnMainThread(self); +} +#endif + +- (id)initWithWebCoreFrame:(Frame*)frame +{ + self = [self init]; + if (!self) + return nil; + frame->ref(); + m_frame = frame; + return self; +} + +- (void)invalidate +{ + if (m_frame) { + m_frame->deref(); + m_frame = 0; + } +} + +- (void)dealloc +{ + if (WebCoreObjCScheduleDeallocateOnMainThread([WebFramePolicyListener class], self)) + return; + + if (m_frame) + m_frame->deref(); + [super dealloc]; +} + +- (void)finalize +{ + ASSERT_MAIN_THREAD(); + if (m_frame) + m_frame->deref(); + [super finalize]; +} + +- (void)receivedPolicyDecision:(PolicyAction)action +{ + RefPtr<Frame> frame = adoptRef(m_frame); + m_frame = 0; + if (frame) + static_cast<WebFrameLoaderClient*>(frame->loader()->client())->receivedPolicyDecison(action); +} + +- (void)ignore +{ + [self receivedPolicyDecision:PolicyIgnore]; +} + +- (void)download +{ + [self receivedPolicyDecision:PolicyDownload]; +} + +- (void)use +{ + [self receivedPolicyDecision:PolicyUse]; +} + +- (void)continue +{ + [self receivedPolicyDecision:PolicyUse]; +} + +@end diff --git a/WebKit/mac/WebCoreSupport/WebIconDatabaseClient.h b/WebKit/mac/WebCoreSupport/WebIconDatabaseClient.h new file mode 100644 index 0000000..e908242 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebIconDatabaseClient.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <WebCore/IconDatabaseClient.h> + +namespace WebCore { + class String; +} + +class WebIconDatabaseClient : public WebCore::IconDatabaseClient { +public: + virtual bool performImport(); + virtual void dispatchDidRemoveAllIcons(); + virtual void dispatchDidAddIconForPageURL(const WebCore::String& pageURL); +}; diff --git a/WebKit/mac/WebCoreSupport/WebIconDatabaseClient.mm b/WebKit/mac/WebCoreSupport/WebIconDatabaseClient.mm new file mode 100644 index 0000000..43202b0 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebIconDatabaseClient.mm @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebIconDatabaseClient.h" + +#import "WebIconDatabaseInternal.h" + +#import <WebCore/FoundationExtras.h> +#import <WebCore/PlatformString.h> + + +bool WebIconDatabaseClient::performImport() +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + bool result = importToWebCoreFormat(); + [pool drain]; + return result; +} + +void WebIconDatabaseClient::dispatchDidRemoveAllIcons() +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [[WebIconDatabase sharedIconDatabase] _sendDidRemoveAllIconsNotification]; + [pool drain]; +} + +void WebIconDatabaseClient::dispatchDidAddIconForPageURL(const WebCore::String& pageURL) +{ + // This is a quick notification that is likely to fire in a rapidly iterating loop + // Therefore we let WebCore handle autorelease by draining its pool "from time to time" + // instead of us doing it every iteration + [[WebIconDatabase sharedIconDatabase] _sendNotificationForURL:pageURL]; +} diff --git a/WebKit/mac/WebCoreSupport/WebImageRendererFactory.m b/WebKit/mac/WebCoreSupport/WebImageRendererFactory.m new file mode 100644 index 0000000..36e25b7 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebImageRendererFactory.m @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Have to leave this class with these two methods in because versions of Safari up to 3.0.4 +// call the methods from the Debug menu. Once we don't need compatibility with those versions +// of Safari, we can remove this. + +@interface WebImageRendererFactory : NSObject +@end + +@implementation WebImageRendererFactory + ++ (BOOL)shouldUseThreadedDecoding +{ + return NO; +} + ++ (void)setShouldUseThreadedDecoding:(BOOL)threadedDecode +{ +} + +@end diff --git a/WebKit/mac/WebCoreSupport/WebInspectorClient.h b/WebKit/mac/WebCoreSupport/WebInspectorClient.h new file mode 100644 index 0000000..6a807c7 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebInspectorClient.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <WebCore/InspectorClient.h> +#import <WebCore/PlatformString.h> + +#import <wtf/RetainPtr.h> + +#ifdef __OBJC__ +@class WebInspectorWindowController; +@class WebView; +#else +class WebInspectorWindowController; +class WebView; +#endif + +class WebInspectorClient : public WebCore::InspectorClient { +public: + WebInspectorClient(WebView *); + + virtual void inspectorDestroyed(); + + virtual WebCore::Page* createPage(); + virtual WebCore::String localizedStringsURL(); + + virtual void showWindow(); + virtual void closeWindow(); + + virtual void attachWindow(); + virtual void detachWindow(); + + virtual void setAttachedWindowHeight(unsigned height); + + virtual void highlight(WebCore::Node*); + virtual void hideHighlight(); + virtual void inspectedURLChanged(const WebCore::String& newURL); + + virtual void populateSetting(const WebCore::String& key, WebCore::InspectorController::Setting&); + virtual void storeSetting(const WebCore::String& key, const WebCore::InspectorController::Setting&); + virtual void removeSetting(const WebCore::String& key); + +private: + void updateWindowTitle() const; + + WebView *m_webView; + RetainPtr<WebInspectorWindowController> m_windowController; + WebCore::String m_inspectedURL; +}; diff --git a/WebKit/mac/WebCoreSupport/WebInspectorClient.mm b/WebKit/mac/WebCoreSupport/WebInspectorClient.mm new file mode 100644 index 0000000..03d85ae --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebInspectorClient.mm @@ -0,0 +1,483 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebInspectorClient.h" + +#import "WebFrameInternal.h" +#import "WebFrameView.h" +#import "WebInspector.h" +#import "WebLocalizableStrings.h" +#import "WebNodeHighlight.h" +#import "WebUIDelegate.h" +#import "WebViewInternal.h" + +#import <WebCore/InspectorController.h> +#import <WebCore/Page.h> + +#import <WebKit/DOMExtensions.h> + +#import <WebKitSystemInterface.h> + +using namespace WebCore; + +@interface WebInspectorWindowController : NSWindowController <NSWindowDelegate> { +@private + WebView *_inspectedWebView; + WebView *_webView; + WebNodeHighlight *_currentHighlight; + BOOL _attachedToInspectedWebView; + BOOL _shouldAttach; + BOOL _visible; + BOOL _movingWindows; +} +- (id)initWithInspectedWebView:(WebView *)webView; +- (BOOL)inspectorVisible; +- (WebView *)webView; +- (void)attach; +- (void)detach; +- (void)setAttachedWindowHeight:(unsigned)height; +- (void)highlightNode:(DOMNode *)node; +- (void)hideHighlight; +@end + +#pragma mark - + +WebInspectorClient::WebInspectorClient(WebView *webView) +: m_webView(webView) +{ +} + +void WebInspectorClient::inspectorDestroyed() +{ + [[m_windowController.get() webView] close]; + delete this; +} + +Page* WebInspectorClient::createPage() +{ + if (!m_windowController) + m_windowController.adoptNS([[WebInspectorWindowController alloc] initWithInspectedWebView:m_webView]); + + return core([m_windowController.get() webView]); +} + +String WebInspectorClient::localizedStringsURL() +{ + NSString *path = [[NSBundle bundleWithIdentifier:@"com.apple.WebCore"] pathForResource:@"localizedStrings" ofType:@"js"]; + if (path) + return [[NSURL fileURLWithPath:path] absoluteString]; + return String(); +} + +void WebInspectorClient::showWindow() +{ + updateWindowTitle(); + [m_windowController.get() showWindow:nil]; +} + +void WebInspectorClient::closeWindow() +{ + [m_windowController.get() close]; +} + +void WebInspectorClient::attachWindow() +{ + [m_windowController.get() attach]; +} + +void WebInspectorClient::detachWindow() +{ + [m_windowController.get() detach]; +} + +void WebInspectorClient::setAttachedWindowHeight(unsigned height) +{ + [m_windowController.get() setAttachedWindowHeight:height]; +} + +void WebInspectorClient::highlight(Node* node) +{ + [m_windowController.get() highlightNode:kit(node)]; +} + +void WebInspectorClient::hideHighlight() +{ + [m_windowController.get() hideHighlight]; +} + +void WebInspectorClient::inspectedURLChanged(const String& newURL) +{ + m_inspectedURL = newURL; + updateWindowTitle(); +} + +void WebInspectorClient::updateWindowTitle() const +{ + NSString *title = [NSString stringWithFormat:UI_STRING("Web Inspector — %@", "Web Inspector window title"), (NSString *)m_inspectedURL]; + [[m_windowController.get() window] setTitle:title]; +} + +#pragma mark - + +#define WebKitInspectorAttachedKey @"WebKitInspectorAttached" +#define WebKitInspectorAttachedViewHeightKey @"WebKitInspectorAttachedViewHeight" + +@implementation WebInspectorWindowController +- (id)init +{ + if (![super initWithWindow:nil]) + return nil; + + // Keep preferences separate from the rest of the client, making sure we are using expected preference values. + // One reason this is good is that it keeps the inspector out of history via "private browsing". + + WebPreferences *preferences = [[WebPreferences alloc] init]; + [preferences setAutosaves:NO]; + [preferences setPrivateBrowsingEnabled:YES]; + [preferences setLoadsImagesAutomatically:YES]; + [preferences setAuthorAndUserStylesEnabled:YES]; + [preferences setJavaScriptEnabled:YES]; + [preferences setAllowsAnimatedImages:YES]; + [preferences setPlugInsEnabled:NO]; + [preferences setJavaEnabled:NO]; + [preferences setUserStyleSheetEnabled:NO]; + [preferences setTabsToLinks:NO]; + [preferences setMinimumFontSize:0]; + [preferences setMinimumLogicalFontSize:9]; + + _webView = [[WebView alloc] init]; + [_webView setPreferences:preferences]; + [_webView setDrawsBackground:NO]; + [_webView setProhibitsMainFrameScrolling:YES]; + [_webView setUIDelegate:self]; + + [preferences release]; + + NSNumber *attached = [[NSUserDefaults standardUserDefaults] objectForKey:WebKitInspectorAttachedKey]; + ASSERT(!attached || [attached isKindOfClass:[NSNumber class]]); + _shouldAttach = attached ? [attached boolValue] : YES; + + NSString *path = [[NSBundle bundleWithIdentifier:@"com.apple.WebCore"] pathForResource:@"inspector" ofType:@"html" inDirectory:@"inspector"]; + NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL fileURLWithPath:path]]; + [[_webView mainFrame] loadRequest:request]; + [request release]; + + [self setWindowFrameAutosaveName:@"Web Inspector 2"]; + return self; +} + +- (id)initWithInspectedWebView:(WebView *)webView +{ + if (![self init]) + return nil; + + // Don't retain to avoid a circular reference + _inspectedWebView = webView; + return self; +} + +- (void)dealloc +{ + ASSERT(!_currentHighlight); + [_webView release]; + [super dealloc]; +} + +#pragma mark - + +- (BOOL)inspectorVisible +{ + return _visible; +} + +- (WebView *)webView +{ + return _webView; +} + +- (NSWindow *)window +{ + NSWindow *window = [super window]; + if (window) + return window; + + NSUInteger styleMask = (NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask); + +#ifndef BUILDING_ON_TIGER + styleMask |= NSTexturedBackgroundWindowMask; +#endif + + window = [[NSWindow alloc] initWithContentRect:NSMakeRect(60.0, 200.0, 750.0, 650.0) styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]; + [window setDelegate:self]; + [window setMinSize:NSMakeSize(400.0, 400.0)]; + +#ifndef BUILDING_ON_TIGER + [window setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge]; + [window setContentBorderThickness:55. forEdge:NSMaxYEdge]; + + WKNSWindowMakeBottomCornersSquare(window); +#endif + + [self setWindow:window]; + [window release]; + + return window; +} + +#pragma mark - + +- (BOOL)windowShouldClose:(id)sender +{ + _visible = NO; + + [_inspectedWebView page]->inspectorController()->setWindowVisible(false); + + [self hideHighlight]; + + return YES; +} + +- (void)close +{ + if (!_visible) + return; + + _visible = NO; + + if (!_movingWindows) + [_inspectedWebView page]->inspectorController()->setWindowVisible(false); + + [self hideHighlight]; + + if (_attachedToInspectedWebView) { + if ([_inspectedWebView _isClosed]) + return; + + [_webView removeFromSuperview]; + + WebFrameView *frameView = [[_inspectedWebView mainFrame] frameView]; + NSRect frameViewRect = [frameView frame]; + + // Setting the height based on the previous height is done to work with + // Safari's find banner. This assumes the previous height is the Y origin. + frameViewRect.size.height += NSMinY(frameViewRect); + frameViewRect.origin.y = 0.0; + + [frameView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [frameView setFrame:frameViewRect]; + + [_inspectedWebView displayIfNeeded]; + } else + [super close]; +} + +- (IBAction)showWindow:(id)sender +{ + if (_visible) { + if (!_attachedToInspectedWebView) + [super showWindow:sender]; // call super so the window will be ordered front if needed + return; + } + + _visible = YES; + + if (_shouldAttach) { + WebFrameView *frameView = [[_inspectedWebView mainFrame] frameView]; + + [_webView removeFromSuperview]; + [_inspectedWebView addSubview:_webView positioned:NSWindowBelow relativeTo:(NSView *)frameView]; + + [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable | NSViewMaxYMargin)]; + [frameView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable | NSViewMinYMargin)]; + + _attachedToInspectedWebView = YES; + + [self setAttachedWindowHeight:[[NSUserDefaults standardUserDefaults] integerForKey:WebKitInspectorAttachedViewHeightKey]]; + } else { + _attachedToInspectedWebView = NO; + + NSView *contentView = [[self window] contentView]; + [_webView setFrame:[contentView frame]]; + [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [_webView removeFromSuperview]; + [contentView addSubview:_webView]; + + [super showWindow:nil]; + } + + [_inspectedWebView page]->inspectorController()->setWindowVisible(true, _shouldAttach); +} + +#pragma mark - + +- (void)attach +{ + if (_attachedToInspectedWebView) + return; + + _shouldAttach = YES; + _movingWindows = YES; + + [self close]; + [self showWindow:nil]; + + _movingWindows = NO; + + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:WebKitInspectorAttachedKey]; +} + +- (void)detach +{ + if (!_attachedToInspectedWebView) + return; + + _shouldAttach = NO; + _movingWindows = YES; + + [self close]; + [self showWindow:nil]; + + _movingWindows = NO; + + [[NSUserDefaults standardUserDefaults] setBool:NO forKey:WebKitInspectorAttachedKey]; +} + +- (void)setAttachedWindowHeight:(unsigned)height +{ + [[NSUserDefaults standardUserDefaults] setInteger:height forKey:WebKitInspectorAttachedViewHeightKey]; + + if (!_attachedToInspectedWebView) + return; + + WebFrameView *frameView = [[_inspectedWebView mainFrame] frameView]; + NSRect frameViewRect = [frameView frame]; + + CGFloat attachedHeight = round(MAX(250.0, MIN(height, (NSHeight([_inspectedWebView frame]) * 0.75)))); + + // Setting the height based on the difference is done to work with + // Safari's find banner. This assumes the previous height is the Y origin. + CGFloat heightDifference = (NSMinY(frameViewRect) - attachedHeight); + frameViewRect.size.height += heightDifference; + frameViewRect.origin.y = attachedHeight; + + [_webView setFrame:NSMakeRect(0.0, 0.0, NSWidth(frameViewRect), attachedHeight)]; + [frameView setFrame:frameViewRect]; +} + +#pragma mark - + +- (void)highlightNode:(DOMNode *)node +{ + // The scrollview's content view stays around between page navigations, so target it + NSView *view = [[[[[_inspectedWebView mainFrame] frameView] documentView] enclosingScrollView] contentView]; + if (![view window]) + return; // skip the highlight if we have no window (e.g. hidden tab) + + if (!_currentHighlight) { + _currentHighlight = [[WebNodeHighlight alloc] initWithTargetView:view inspectorController:[_inspectedWebView page]->inspectorController()]; + [_currentHighlight setDelegate:self]; + [_currentHighlight attach]; + } else + [[_currentHighlight highlightView] setNeedsDisplay:YES]; +} + +- (void)hideHighlight +{ + [_currentHighlight detach]; + [_currentHighlight setDelegate:nil]; + [_currentHighlight release]; + _currentHighlight = nil; +} + +#pragma mark - +#pragma mark WebNodeHighlight delegate + +- (void)didAttachWebNodeHighlight:(WebNodeHighlight *)highlight +{ + [_inspectedWebView setCurrentNodeHighlight:highlight]; +} + +- (void)willDetachWebNodeHighlight:(WebNodeHighlight *)highlight +{ + [_inspectedWebView setCurrentNodeHighlight:nil]; +} + +#pragma mark - +#pragma mark UI delegate + +- (NSUInteger)webView:(WebView *)sender dragDestinationActionMaskForDraggingInfo:(id <NSDraggingInfo>)draggingInfo +{ + return WebDragDestinationActionNone; +} + +#pragma mark - + +// These methods can be used by UI elements such as menu items and toolbar buttons when the inspector is the key window. + +// This method is really only implemented to keep any UI elements enabled. +- (void)showWebInspector:(id)sender +{ + [[_inspectedWebView inspector] show:sender]; +} + +- (void)showErrorConsole:(id)sender +{ + [[_inspectedWebView inspector] showConsole:sender]; +} + +- (void)toggleDebuggingJavaScript:(id)sender +{ + [[_inspectedWebView inspector] toggleDebuggingJavaScript:sender]; +} + +- (void)toggleProfilingJavaScript:(id)sender +{ + [[_inspectedWebView inspector] toggleProfilingJavaScript:sender]; +} + +- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item +{ + BOOL isMenuItem = [(id)item isKindOfClass:[NSMenuItem class]]; + if ([item action] == @selector(toggleDebuggingJavaScript:) && isMenuItem) { + NSMenuItem *menuItem = (NSMenuItem *)item; + if ([[_inspectedWebView inspector] isDebuggingJavaScript]) + [menuItem setTitle:UI_STRING("Stop Debugging JavaScript", "title for Stop Debugging JavaScript menu item")]; + else + [menuItem setTitle:UI_STRING("Start Debugging JavaScript", "title for Start Debugging JavaScript menu item")]; + } else if ([item action] == @selector(toggleProfilingJavaScript:) && isMenuItem) { + NSMenuItem *menuItem = (NSMenuItem *)item; + if ([[_inspectedWebView inspector] isProfilingJavaScript]) + [menuItem setTitle:UI_STRING("Stop Profiling JavaScript", "title for Stop Profiling JavaScript menu item")]; + else + [menuItem setTitle:UI_STRING("Start Profiling JavaScript", "title for Start Profiling JavaScript menu item")]; + } + + return YES; +} + +@end diff --git a/WebKit/mac/WebCoreSupport/WebJavaScriptTextInputPanel.h b/WebKit/mac/WebCoreSupport/WebJavaScriptTextInputPanel.h new file mode 100644 index 0000000..1dfd2e4 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebJavaScriptTextInputPanel.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <Cocoa/Cocoa.h> + +@interface WebJavaScriptTextInputPanel : NSWindowController +{ + IBOutlet NSTextField *prompt; + IBOutlet NSTextField *textInput; +} + +- (id)initWithPrompt:(NSString *)prompt text:(NSString *)text; +- (NSString *)text; + +- (IBAction)pressedCancel:(id)sender; +- (IBAction)pressedOK:(id)sender; + +@end diff --git a/WebKit/mac/WebCoreSupport/WebJavaScriptTextInputPanel.m b/WebKit/mac/WebCoreSupport/WebJavaScriptTextInputPanel.m new file mode 100644 index 0000000..bd1a601 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebJavaScriptTextInputPanel.m @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebJavaScriptTextInputPanel.h" + +#import <wtf/Assertions.h> + +#import <WebKit/WebNSControlExtras.h> +#import <WebKit/WebNSWindowExtras.h> + +@implementation WebJavaScriptTextInputPanel + +- (id)initWithPrompt:(NSString *)p text:(NSString *)t +{ + [self initWithWindowNibName:@"WebJavaScriptTextInputPanel"]; + NSWindow *window = [self window]; + + // This must be done after the call to [self window], because + // until then, prompt and textInput will be nil. + ASSERT(prompt); + ASSERT(textInput); + [prompt setStringValue:p]; + [textInput setStringValue:t]; + + [prompt sizeToFitAndAdjustWindowHeight]; + [window centerOverMainWindow]; + + return self; +} + +- (NSString *)text +{ + return [textInput stringValue]; +} + +- (IBAction)pressedCancel:(id)sender +{ + [NSApp stopModalWithCode:NO]; +} + +- (IBAction)pressedOK:(id)sender +{ + [NSApp stopModalWithCode:YES]; +} + +@end diff --git a/WebKit/mac/WebCoreSupport/WebKeyGenerator.h b/WebKit/mac/WebCoreSupport/WebKeyGenerator.h new file mode 100644 index 0000000..ed2ff77 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebKeyGenerator.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +typedef enum { + WebCertificateParseResultSucceeded = 0, + WebCertificateParseResultFailed = 1, + WebCertificateParseResultPKCS7 = 2, +} WebCertificateParseResult; + +#ifdef __OBJC__ + +#import <WebCore/WebCoreKeyGenerator.h> + +@interface WebKeyGenerator : WebCoreKeyGenerator +{ + NSArray *strengthMenuItemTitles; +} ++ (void)createSharedGenerator; +- (WebCertificateParseResult)addCertificatesToKeychainFromData:(NSData *)data; +@end + +#endif diff --git a/WebKit/mac/WebCoreSupport/WebKeyGenerator.m b/WebKit/mac/WebCoreSupport/WebKeyGenerator.m new file mode 100644 index 0000000..454175e --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebKeyGenerator.m @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <WebKit/WebKeyGenerator.h> + +#import <WebKit/WebLocalizableStrings.h> +#import <WebKitSystemInterface.h> +#import <wtf/Assertions.h> + +@implementation WebKeyGenerator + ++ (void)createSharedGenerator +{ + if (![self sharedGenerator]) { + [[[self alloc] init] release]; + } + ASSERT([[self sharedGenerator] isKindOfClass:self]); +} + +- (void)dealloc +{ + [strengthMenuItemTitles release]; + [super dealloc]; +} + +- (NSArray *)strengthMenuItemTitles +{ + if (!strengthMenuItemTitles) { + strengthMenuItemTitles = [[NSArray alloc] initWithObjects: + UI_STRING("2048 (High Grade)", "Menu item title for KEYGEN pop-up menu"), + UI_STRING("1024 (Medium Grade)", "Menu item title for KEYGEN pop-up menu"), + UI_STRING("512 (Low Grade)", "Menu item title for KEYGEN pop-up menu"), nil]; + } + return strengthMenuItemTitles; +} + +- (NSString *)signedPublicKeyAndChallengeStringWithStrengthIndex:(unsigned)index challenge:(NSString *)challenge pageURL:(NSURL *)pageURL +{ + // This switch statement must always be synced with the UI strings returned by strengthMenuItemTitles. + UInt32 keySize; + switch (index) { + case 0: + keySize = 2048; + break; + case 1: + keySize = 1024; + break; + case 2: + keySize = 512; + break; + default: + return nil; + } + + NSString *keyDescription = [NSString stringWithFormat:UI_STRING("Key from %@", "name of keychain key generated by the KEYGEN tag"), [pageURL host]]; + return [(NSString *)WKSignedPublicKeyAndChallengeString(keySize, (CFStringRef)challenge, (CFStringRef)keyDescription) autorelease]; +} + +- (WebCertificateParseResult)addCertificatesToKeychainFromData:(NSData *)data +{ + return WKAddCertificatesToKeychainFromData([data bytes], [data length]); +} + +@end diff --git a/WebKit/mac/WebCoreSupport/WebPasteboardHelper.h b/WebKit/mac/WebCoreSupport/WebPasteboardHelper.h new file mode 100644 index 0000000..94ff676 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebPasteboardHelper.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebPasteboardHelper_h +#define WebPasteboardHelper_h + +#import <WebCore/PasteboardHelper.h> + +@class WebHTMLView; + +class WebPasteboardHelper : public WebCore::PasteboardHelper +{ +public: + WebPasteboardHelper(WebHTMLView* view) : m_view(view) {} + virtual WebCore::String urlFromPasteboard(const NSPasteboard*, WebCore::String* title) const; + virtual WebCore::String plainTextFromPasteboard(const NSPasteboard*) const; + virtual DOMDocumentFragment* fragmentFromPasteboard(const NSPasteboard*) const; + virtual NSArray* insertablePasteboardTypes() const; + private: + WebHTMLView* m_view; +}; + +#endif diff --git a/WebKit/mac/WebCoreSupport/WebPasteboardHelper.mm b/WebKit/mac/WebCoreSupport/WebPasteboardHelper.mm new file mode 100644 index 0000000..2da6654 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebPasteboardHelper.mm @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebArchive.h" +#import "WebHTMLViewInternal.h" +#import "WebNSPasteboardExtras.h" +#import "WebNSURLExtras.h" +#import "WebPasteboardHelper.h" + +#import <WebCore/DOMDocument.h> +#import <WebCore/DOMDocumentFragment.h> +#import <WebCore/PlatformString.h> +#import <wtf/RetainPtr.h> + +using namespace WebCore; + +String WebPasteboardHelper::urlFromPasteboard(const NSPasteboard* pasteboard, String* title) const +{ + NSURL *URL = [pasteboard _web_bestURL]; + if (title) { + if (NSString *URLTitleString = [pasteboard stringForType:WebURLNamePboardType]) + *title = URLTitleString; + } + + return [URL _web_originalDataAsString]; +} + +String WebPasteboardHelper::plainTextFromPasteboard(const NSPasteboard *pasteboard) const +{ + NSArray *types = [pasteboard types]; + + if ([types containsObject:NSStringPboardType]) + return [pasteboard stringForType:NSStringPboardType]; + + NSAttributedString *attributedString = nil; + NSString *string; + + if ([types containsObject:NSRTFDPboardType]) + attributedString = [[NSAttributedString alloc] initWithRTFD:[pasteboard dataForType:NSRTFDPboardType] documentAttributes:nil]; + if (!attributedString && [types containsObject:NSRTFPboardType]) + attributedString = [[NSAttributedString alloc] initWithRTF:[pasteboard dataForType:NSRTFPboardType] documentAttributes:nil]; + if (attributedString) { + string = [[attributedString string] copy]; + [attributedString release]; + return [string autorelease]; + } + + if ([types containsObject:NSFilenamesPboardType]) { + string = [[pasteboard propertyListForType:NSFilenamesPboardType] componentsJoinedByString:@"\n"]; + if (string) + return string; + } + + NSURL *URL; + + if ((URL = [NSURL URLFromPasteboard:pasteboard])) { + string = [URL _web_userVisibleString]; + if ([string length] > 0) + return string; + } + + return String(); +} + +DOMDocumentFragment *WebPasteboardHelper::fragmentFromPasteboard(const NSPasteboard *pasteboard) const +{ + return [m_view _documentFragmentFromPasteboard:pasteboard]; +} + +NSArray *WebPasteboardHelper::insertablePasteboardTypes() const +{ + static RetainPtr<NSArray> types = [[NSArray alloc] initWithObjects:WebArchivePboardType, NSHTMLPboardType, + NSFilenamesPboardType, NSTIFFPboardType, NSPICTPboardType, NSURLPboardType, + NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, NSColorPboardType, nil]; + + return types.get(); +} diff --git a/WebKit/mac/WebCoreSupport/WebSystemInterface.h b/WebKit/mac/WebCoreSupport/WebSystemInterface.h new file mode 100644 index 0000000..6e20279 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebSystemInterface.h @@ -0,0 +1,37 @@ +/* + * Copyright 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +void InitWebCoreSystemInterface(void); + +#ifdef __cplusplus +} +#endif diff --git a/WebKit/mac/WebCoreSupport/WebSystemInterface.m b/WebKit/mac/WebCoreSupport/WebSystemInterface.m new file mode 100644 index 0000000..417f668 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebSystemInterface.m @@ -0,0 +1,102 @@ +/* + * Copyright 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebSystemInterface.h" + +#import <WebCore/WebCoreSystemInterface.h> +#import <WebKitSystemInterface.h> + +#define INIT(function) wk##function = WK##function + +void InitWebCoreSystemInterface(void) +{ + static bool didInit; + if (didInit) + return; + + INIT(AdvanceDefaultButtonPulseAnimation); + INIT(CGContextGetShouldSmoothFonts); + INIT(CreateCustomCFReadStream); + INIT(CreateNSURLConnectionDelegateProxy); + INIT(DrawCapsLockIndicator); + INIT(DrawBezeledTextArea); + INIT(DrawBezeledTextFieldCell); + INIT(DrawFocusRing); + INIT(DrawMediaFullscreenButton); + INIT(DrawMediaMuteButton); + INIT(DrawMediaPauseButton); + INIT(DrawMediaPlayButton); + INIT(DrawMediaSeekBackButton); + INIT(DrawMediaSeekForwardButton); + INIT(DrawMediaSliderTrack); + INIT(DrawMediaSliderThumb); + INIT(DrawMediaUnMuteButton); + INIT(DrawTextFieldCellFocusRing); + INIT(GetExtensionsForMIMEType); + INIT(GetFontInLanguageForCharacter); + INIT(GetFontInLanguageForRange); + INIT(GetGlyphTransformedAdvances); + INIT(GetMIMETypeForExtension); + INIT(GetNSURLResponseLastModifiedDate); + INIT(GetPreferredExtensionForMIMEType); + INIT(GetWheelEventDeltas); + INIT(PopupMenu); + INIT(SetCGFontRenderingMode); + INIT(SetDragImage); + INIT(SetNSURLConnectionDefersCallbacks); + INIT(SetNSURLRequestShouldContentSniff); + INIT(SetPatternBaseCTM); + INIT(SetPatternPhaseInUserSpace); + INIT(SetUpFontCache); + INIT(SignalCFReadStreamEnd); + INIT(SignalCFReadStreamError); + INIT(SignalCFReadStreamHasBytes); + INIT(QTMovieDataRate); + INIT(QTMovieMaxTimeLoaded); + INIT(QTMovieViewSetDrawSynchronously); + +#ifndef BUILDING_ON_TIGER + INIT(GetGlyphsForCharacters); +#else + INIT(ClearGlyphVector); + INIT(ConvertCharToGlyphs); + INIT(CopyFullFontName); + INIT(GetATSStyleGroup); + INIT(GetCGFontFromNSFont); + INIT(GetFontMetrics); + INIT(GetGlyphVectorFirstRecord); + INIT(GetGlyphVectorNumGlyphs); + INIT(GetGlyphVectorRecordSize); + INIT(GetNSFontATSUFontId); + INIT(InitializeGlyphVector); + INIT(ReleaseStyleGroup); + INIT(SupportsMultipartXMixedReplace); +#endif + + didInit = true; +} diff --git a/WebKit/mac/WebCoreSupport/WebViewFactory.h b/WebKit/mac/WebCoreSupport/WebViewFactory.h new file mode 100644 index 0000000..4030a10 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebViewFactory.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <WebCore/WebCoreViewFactory.h> + +@interface WebViewFactory : WebCoreViewFactory <WebCoreViewFactory> + ++ (void)createSharedFactory; + +@end diff --git a/WebKit/mac/WebCoreSupport/WebViewFactory.mm b/WebKit/mac/WebCoreSupport/WebViewFactory.mm new file mode 100644 index 0000000..e9cd746 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebViewFactory.mm @@ -0,0 +1,505 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <WebKit/WebViewFactory.h> + +#import <WebKit/WebFrameInternal.h> +#import <WebKit/WebViewInternal.h> +#import <WebKit/WebHTMLViewInternal.h> +#import <WebKit/WebLocalizableStrings.h> +#import <WebKit/WebNSUserDefaultsExtras.h> +#import <WebKit/WebNSObjectExtras.h> +#import <WebKit/WebNSViewExtras.h> +#import <WebKit/WebPluginDatabase.h> +#import <WebKitSystemInterface.h> +#import <wtf/Assertions.h> + +@interface NSMenu (WebViewFactoryAdditions) +- (NSMenuItem *)addItemWithTitle:(NSString *)title action:(SEL)action tag:(int)tag; +@end + +@implementation NSMenu (WebViewFactoryAdditions) + +- (NSMenuItem *)addItemWithTitle:(NSString *)title action:(SEL)action tag:(int)tag +{ + NSMenuItem *item = [[[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:@""] autorelease]; + [item setTag:tag]; + [self addItem:item]; + return item; +} + +@end + +@implementation WebViewFactory + ++ (void)createSharedFactory +{ + if (![self sharedFactory]) { + [[[self alloc] init] release]; + } + ASSERT([[self sharedFactory] isKindOfClass:self]); +} + +- (NSArray *)pluginsInfo +{ + return [[WebPluginDatabase sharedDatabase] plugins]; +} + +- (void)refreshPlugins +{ + [[WebPluginDatabase sharedDatabase] refresh]; +} + +- (NSString *)inputElementAltText +{ + return UI_STRING_KEY("Submit", "Submit (input element)", "alt text for <input> elements with no alt, title, or value"); +} + +- (NSString *)resetButtonDefaultLabel +{ + return UI_STRING("Reset", "default label for Reset buttons in forms on web pages"); +} + +- (NSString *)searchableIndexIntroduction +{ + return UI_STRING("This is a searchable index. Enter search keywords: ", + "text that appears at the start of nearly-obsolete web pages in the form of a 'searchable index'"); +} + +- (NSString *)submitButtonDefaultLabel +{ + return UI_STRING("Submit", "default label for Submit buttons in forms on web pages"); +} + +- (NSString *)fileButtonChooseFileLabel +{ + return UI_STRING("Choose File", "title for file button used in HTML forms"); +} + +- (NSString *)fileButtonNoFileSelectedLabel +{ + return UI_STRING("no file selected", "text to display in file button used in HTML forms when no file is selected"); +} + +- (NSString *)copyImageUnknownFileLabel +{ + return UI_STRING("unknown", "Unknown filename"); +} + +- (NSString *)searchMenuNoRecentSearchesText +{ + return UI_STRING("No recent searches", "Label for only item in menu that appears when clicking on the search field image, when no searches have been performed"); +} + +- (NSString *)searchMenuRecentSearchesText +{ + return UI_STRING("Recent Searches", "label for first item in the menu that appears when clicking on the search field image, used as embedded menu title"); +} + +- (NSString *)searchMenuClearRecentSearchesText +{ + return UI_STRING("Clear Recent Searches", "menu item in Recent Searches menu that empties menu's contents"); +} + +- (NSString *)defaultLanguageCode +{ + return [NSUserDefaults _webkit_preferredLanguageCode]; +} + +- (NSString *)contextMenuItemTagOpenLinkInNewWindow +{ + return UI_STRING("Open Link in New Window", "Open in New Window context menu item"); +} + +- (NSString *)contextMenuItemTagDownloadLinkToDisk +{ + return UI_STRING("Download Linked File", "Download Linked File context menu item"); +} + +- (NSString *)contextMenuItemTagCopyLinkToClipboard +{ + return UI_STRING("Copy Link", "Copy Link context menu item"); +} + +- (NSString *)contextMenuItemTagOpenImageInNewWindow +{ + return UI_STRING("Open Image in New Window", "Open Image in New Window context menu item"); +} + +- (NSString *)contextMenuItemTagDownloadImageToDisk +{ + return UI_STRING("Download Image", "Download Image context menu item"); +} + +- (NSString *)contextMenuItemTagCopyImageToClipboard +{ + return UI_STRING("Copy Image", "Copy Image context menu item"); +} + +- (NSString *)contextMenuItemTagOpenFrameInNewWindow +{ + return UI_STRING("Open Frame in New Window", "Open Frame in New Window context menu item"); +} + +- (NSString *)contextMenuItemTagCopy +{ + return UI_STRING("Copy", "Copy context menu item"); +} + +- (NSString *)contextMenuItemTagGoBack +{ + return UI_STRING("Back", "Back context menu item"); +} + +- (NSString *)contextMenuItemTagGoForward +{ + return UI_STRING("Forward", "Forward context menu item"); +} + +- (NSString *)contextMenuItemTagStop +{ + return UI_STRING("Stop", "Stop context menu item"); +} + +- (NSString *)contextMenuItemTagReload +{ + return UI_STRING("Reload", "Reload context menu item"); +} + +- (NSString *)contextMenuItemTagCut +{ + return UI_STRING("Cut", "Cut context menu item"); +} + +- (NSString *)contextMenuItemTagPaste +{ + return UI_STRING("Paste", "Paste context menu item"); +} + +- (NSString *)contextMenuItemTagNoGuessesFound +{ + return UI_STRING("No Guesses Found", "No Guesses Found context menu item"); +} + +- (NSString *)contextMenuItemTagIgnoreSpelling +{ + return UI_STRING("Ignore Spelling", "Ignore Spelling context menu item"); +} + +- (NSString *)contextMenuItemTagLearnSpelling +{ + return UI_STRING("Learn Spelling", "Learn Spelling context menu item"); +} + +- (NSString *)contextMenuItemTagSearchInSpotlight +{ + return UI_STRING("Search in Spotlight", "Search in Spotlight context menu item"); +} + +- (NSString *)contextMenuItemTagSearchWeb +{ + return UI_STRING("Search in Google", "Search in Google context menu item"); +} + +- (NSString *)contextMenuItemTagLookUpInDictionary +{ + return UI_STRING("Look Up in Dictionary", "Look Up in Dictionary context menu item"); +} + +- (NSString *)contextMenuItemTagOpenLink +{ + return UI_STRING("Open Link", "Open Link context menu item"); +} + +- (NSString *)contextMenuItemTagIgnoreGrammar +{ + return UI_STRING("Ignore Grammar", "Ignore Grammar context menu item"); +} + +- (NSString *)contextMenuItemTagSpellingMenu +{ +#ifndef BUILDING_ON_TIGER + return UI_STRING("Spelling and Grammar", "Spelling and Grammar context sub-menu item"); +#else + return UI_STRING("Spelling", "Spelling context sub-menu item"); +#endif +} + +- (NSString *)contextMenuItemTagShowSpellingPanel:(bool)show +{ +#ifndef BUILDING_ON_TIGER + if (show) + return UI_STRING("Show Spelling and Grammar", "menu item title"); + return UI_STRING("Hide Spelling and Grammar", "menu item title"); +#else + return UI_STRING("Spelling...", "menu item title"); +#endif +} + +- (NSString *)contextMenuItemTagCheckSpelling +{ +#ifndef BUILDING_ON_TIGER + return UI_STRING("Check Document Now", "Check spelling context menu item"); +#else + return UI_STRING("Check Spelling", "Check spelling context menu item"); +#endif +} + +- (NSString *)contextMenuItemTagCheckSpellingWhileTyping +{ +#ifndef BUILDING_ON_TIGER + return UI_STRING("Check Spelling While Typing", "Check spelling while typing context menu item"); +#else + return UI_STRING("Check Spelling as You Type", "Check spelling while typing context menu item"); +#endif +} + +- (NSString *)contextMenuItemTagCheckGrammarWithSpelling +{ + return UI_STRING("Check Grammar With Spelling", "Check grammar with spelling context menu item"); +} + +- (NSString *)contextMenuItemTagFontMenu +{ + return UI_STRING("Font", "Font context sub-menu item"); +} + +- (NSString *)contextMenuItemTagShowFonts +{ + return UI_STRING("Show Fonts", "Show fonts context menu item"); +} + +- (NSString *)contextMenuItemTagBold +{ + return UI_STRING("Bold", "Bold context menu item"); +} + +- (NSString *)contextMenuItemTagItalic +{ + return UI_STRING("Italic", "Italic context menu item"); +} + +- (NSString *)contextMenuItemTagUnderline +{ + return UI_STRING("Underline", "Underline context menu item"); +} + +- (NSString *)contextMenuItemTagOutline +{ + return UI_STRING("Outline", "Outline context menu item"); +} + +- (NSString *)contextMenuItemTagStyles +{ + return UI_STRING("Styles...", "Styles context menu item"); +} + +- (NSString *)contextMenuItemTagShowColors +{ + return UI_STRING("Show colors", "Show colors context menu item"); +} + +- (NSString *)contextMenuItemTagSpeechMenu +{ + return UI_STRING("Speech", "Speech context sub-menu item"); +} + +- (NSString *)contextMenuItemTagStartSpeaking +{ + return UI_STRING("Start Speaking", "Start speaking context menu item"); +} + +- (NSString *)contextMenuItemTagStopSpeaking +{ + return UI_STRING("Stop Speaking", "Stop speaking context menu item"); +} + +- (NSString *)contextMenuItemTagWritingDirectionMenu +{ + return UI_STRING("Writing Direction", "Writing direction context sub-menu item"); +} + +- (NSString *)contextMenuItemTagDefaultDirection +{ + return UI_STRING("Default", "Default writing direction context menu item"); +} + +- (NSString *)contextMenuItemTagLeftToRight +{ + return UI_STRING("Left to Right", "Left to Right context menu item"); +} + +- (NSString *)contextMenuItemTagRightToLeft +{ + return UI_STRING("Right to Left", "Right to Left context menu item"); +} + +- (NSString *)contextMenuItemTagInspectElement +{ + return UI_STRING("Inspect Element", "Inspect Element context menu item"); +} + +- (BOOL)objectIsTextMarker:(id)object +{ + return object != nil && CFGetTypeID(object) == WKGetAXTextMarkerTypeID(); +} + +- (BOOL)objectIsTextMarkerRange:(id)object +{ + return object != nil && CFGetTypeID(object) == WKGetAXTextMarkerRangeTypeID(); +} + +- (WebCoreTextMarker *)textMarkerWithBytes:(const void *)bytes length:(size_t)length +{ + return WebCFAutorelease(WKCreateAXTextMarker(bytes, length)); +} + +- (BOOL)getBytes:(void *)bytes fromTextMarker:(WebCoreTextMarker *)textMarker length:(size_t)length +{ + return WKGetBytesFromAXTextMarker(textMarker, bytes, length); +} + +- (WebCoreTextMarkerRange *)textMarkerRangeWithStart:(WebCoreTextMarker *)start end:(WebCoreTextMarker *)end +{ + ASSERT(start != nil); + ASSERT(end != nil); + ASSERT(CFGetTypeID(start) == WKGetAXTextMarkerTypeID()); + ASSERT(CFGetTypeID(end) == WKGetAXTextMarkerTypeID()); + return WebCFAutorelease(WKCreateAXTextMarkerRange(start, end)); +} + +- (WebCoreTextMarker *)startOfTextMarkerRange:(WebCoreTextMarkerRange *)range +{ + ASSERT(range != nil); + ASSERT(CFGetTypeID(range) == WKGetAXTextMarkerRangeTypeID()); + return WebCFAutorelease(WKCopyAXTextMarkerRangeStart(range)); +} + +- (WebCoreTextMarker *)endOfTextMarkerRange:(WebCoreTextMarkerRange *)range +{ + ASSERT(range != nil); + ASSERT(CFGetTypeID(range) == WKGetAXTextMarkerRangeTypeID()); + return WebCFAutorelease(WKCopyAXTextMarkerRangeEnd(range)); +} + +- (void)accessibilityHandleFocusChanged +{ + WKAccessibilityHandleFocusChanged(); +} + +- (AXUIElementRef)AXUIElementForElement:(id)element +{ + return WKCreateAXUIElementRef(element); +} + +- (void)unregisterUniqueIdForUIElement:(id)element +{ + WKUnregisterUniqueIdForElement(element); +} + +- (NSString *)AXWebAreaText +{ + return UI_STRING("HTML content", "accessibility role description for web area"); +} + +- (NSString *)AXLinkText +{ + return UI_STRING("link", "accessibility role description for link"); +} + +- (NSString *)AXListMarkerText +{ + return UI_STRING("list marker", "accessibility role description for list marker"); +} + +- (NSString *)AXImageMapText +{ + return UI_STRING("image map", "accessibility role description for image map"); +} + +- (NSString *)AXHeadingText +{ + return UI_STRING("heading", "accessibility role description for headings"); +} + +- (NSString *)AXDefinitionListTermText +{ + return UI_STRING("term", "term word of a definition"); +} + +- (NSString *)AXDefinitionListDefinitionText +{ + return UI_STRING("definition", "definition phrase"); +} + +- (NSString *)AXButtonActionVerb +{ + return UI_STRING("press", "Verb stating the action that will occur when a button is pressed, as used by accessibility"); +} + +- (NSString *)AXRadioButtonActionVerb +{ + return UI_STRING("select", "Verb stating the action that will occur when a radio button is clicked, as used by accessibility"); +} + +- (NSString *)AXTextFieldActionVerb +{ + return UI_STRING("activate", "Verb stating the action that will occur when a text field is selected, as used by accessibility"); +} + +- (NSString *)AXCheckedCheckBoxActionVerb +{ + return UI_STRING("uncheck", "Verb stating the action that will occur when a checked checkbox is clicked, as used by accessibility"); +} + +- (NSString *)AXUncheckedCheckBoxActionVerb +{ + return UI_STRING("check", "Verb stating the action that will occur when an unchecked checkbox is clicked, as used by accessibility"); +} + +- (NSString *)AXLinkActionVerb +{ + return UI_STRING("jump", "Verb stating the action that will occur when a link is clicked, as used by accessibility"); +} + +- (NSString *)multipleFileUploadTextForNumberOfFiles:(unsigned)numberOfFiles +{ + return [NSString stringWithFormat:UI_STRING("%d files", "Label to describe the number of files selected in a file upload control that allows multiple files"), numberOfFiles]; +} + +- (NSString *)unknownFileSizeText +{ + return UI_STRING("Unknown", "Unknown filesize FTP directory listing item"); +} + +- (NSString*)imageTitleForFilename:(NSString*)filename width:(int)width height:(int)height +{ + return [NSString stringWithFormat:UI_STRING("%@ %d×%d pixels", "window title for a standalone image (uses multiplication symbol, not x)"), filename, width, height]; +} + +@end |