diff options
author | Upstream <upstream-import@none> | 1970-01-12 13:46:40 +0000 |
---|---|---|
committer | Upstream <upstream-import@none> | 1970-01-12 13:46:40 +0000 |
commit | d8543bb6618c17b12da906afa77d216f58cf4058 (patch) | |
tree | c58dc05ed86825bd0ef8d305d58c8205106b540f /WebKit/mac/WebCoreSupport | |
download | external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.zip external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.tar.gz external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.tar.bz2 |
external/webkit r30707
Diffstat (limited to 'WebKit/mac/WebCoreSupport')
30 files changed, 6112 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..603ef96 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebChromeClient.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Trolltech ASA + * + * 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& sourceID); + + 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 addToDirtyRegion(const WebCore::IntRect&); + virtual void scrollBackingStore(int dx, int dy, const WebCore::IntRect& scrollViewRect, const WebCore::IntRect& clipRect); + virtual void updateBackingStore(); + + 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); + +private: + WebView *m_webView; +}; diff --git a/WebKit/mac/WebCoreSupport/WebChromeClient.mm b/WebKit/mac/WebCoreSupport/WebChromeClient.mm new file mode 100644 index 0000000..fcbecf4 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebChromeClient.mm @@ -0,0 +1,428 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Trolltech ASA + * + * 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 "WebDefaultUIDelegate.h" +#import "WebElementDictionary.h" +#import "WebFrameInternal.h" +#import "WebFrameView.h" +#import "WebHTMLView.h" +#import "WebHTMLViewPrivate.h" +#import "WebKitSystemInterface.h" +#import "WebNSURLRequestExtras.h" +#import "WebSecurityOriginPrivate.h" +#import "WebSecurityOriginInternal.h" +#import "WebUIDelegate.h" +#import "WebUIDelegatePrivate.h" +#import "WebView.h" +#import "WebViewInternal.h" +#import <WebCore/BlockExceptions.h> +#import <WebCore/FloatRect.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameLoadRequest.h> +#import <WebCore/HitTestResult.h> +#import <WebCore/IntRect.h> +#import <WebCore/PlatformScreen.h> +#import <WebCore/PlatformString.h> +#import <WebCore/ResourceRequest.h> +#import <WebCore/WindowFeatures.h> +#import <wtf/PassRefPtr.h> + +@interface NSView (AppKitSecretsWebBridgeKnowsAbout) +- (NSView *)_findLastViewInKeyViewLoop; +@end + +using namespace WebCore; + +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 +{ + return IntRect(); +} + +void WebChromeClient::addToDirtyRegion(const IntRect&) +{ +} + +void WebChromeClient::scrollBackingStore(int, int, const IntRect&, const IntRect&) +{ +} + +void WebChromeClient::updateBackingStore() +{ +} + +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) +{ + 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]; +} + 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..2cc7570 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebDragClient.mm @@ -0,0 +1,146 @@ +/* + * 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 "WebArchiver.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..ef54d2a --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebEditorClient.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2007 Trolltech ASA + * + * 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(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 NSData* dataForArchivedSelection(WebCore::Frame*); + 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..62a6675 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebEditorClient.mm @@ -0,0 +1,627 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2007 Trolltech ASA + * + * 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 "WebArchiver.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/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 +{ + 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(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]]; +} + +NSData* WebEditorClient::dataForArchivedSelection(Frame* frame) +{ + WebArchive *archive = [WebArchiver archiveSelectionInFrame:kit(frame)]; + return [archive data]; +} + +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 the bridge 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/WebFrameBridge.h b/WebKit/mac/WebCoreSupport/WebFrameBridge.h new file mode 100644 index 0000000..05d5bc0 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebFrameBridge.h @@ -0,0 +1,83 @@ +/* + * 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. + */ + +#import <WebCore/WebCoreFrameBridge.h> + +namespace WebCore { + class Page; +} + +@class WebFrame; +@class WebFrameView; + +@protocol WebOpenPanelResultListener; + +@interface WebFrameBridge : WebCoreFrameBridge <WebCoreFrameBridge> +{ +@public + WebFrame *_frame; + +@private + WebCore::KeyboardUIMode _keyboardUIMode; + BOOL _keyboardUIModeAccessed; + BOOL _doingClientRedirect; + BOOL _haveUndoRedoOperations; + + NSDictionary *lastDashboardRegions; +} + +- (id)initMainFrameWithPage:(WebCore::Page*)page frameName:(NSString *)name frameView:(WebFrameView *)frameView; +- (void)close; + +- (WebFrame *)webFrame; + +// The following methods can all move off the bridge; they're used on the WebKit side only. + +- (NSView *)viewForPluginWithFrame:(NSRect)frame + URL:(NSURL *)URL + attributeNames:(NSArray *)attributeNames + attributeValues:(NSArray *)attributeValues + MIMEType:(NSString *)MIMEType + DOMElement:(DOMElement *)element + loadManually:(BOOL)loadManually; +- (NSView *)viewForJavaAppletWithFrame:(NSRect)frame + attributeNames:(NSArray *)attributeNames + attributeValues:(NSArray *)attributeValues + baseURL:(NSURL *)baseURL + DOMElement:(DOMElement *)element; + +- (WebCore::Frame*)createChildFrameNamed:(NSString *)frameName withURL:(NSURL *)URL referrer:(const WebCore::String&)referrer + ownerElement:(WebCore::HTMLFrameOwnerElement *)ownerElement allowsScrolling:(BOOL)allowsScrolling marginWidth:(int)width marginHeight:(int)height; + +- (void)redirectDataToPlugin:(NSView *)pluginView; + +- (WebCore::ObjectContentType)determineObjectFromMIMEType:(NSString*)MIMEType URL:(NSURL*)URL; + +- (void)windowObjectCleared; + +@end diff --git a/WebKit/mac/WebCoreSupport/WebFrameBridge.mm b/WebKit/mac/WebCoreSupport/WebFrameBridge.mm new file mode 100644 index 0000000..8e0ba51 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebFrameBridge.mm @@ -0,0 +1,741 @@ +/* + * Copyright (C) 2005, 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 "WebFrameBridge.h" + +#import "WebBackForwardList.h" +#import "WebBaseNetscapePluginView.h" +#import "WebBasePluginPackage.h" +#import "WebDataSourceInternal.h" +#import "WebDefaultUIDelegate.h" +#import "WebEditingDelegate.h" +#import "WebFormDelegate.h" +#import "WebFrameInternal.h" +#import "WebFrameLoadDelegate.h" +#import "WebFrameLoaderClient.h" +#import "WebFrameViewInternal.h" +#import "WebHTMLRepresentationPrivate.h" +#import "WebHTMLViewInternal.h" +#import "WebHistoryItemInternal.h" +#import "WebHistoryItemPrivate.h" +#import "WebJavaPlugIn.h" +#import "WebJavaScriptTextInputPanel.h" +#import "WebKitErrorsPrivate.h" +#import "WebKitLogging.h" +#import "WebKitNSStringExtras.h" +#import "WebKitPluginContainerView.h" +#import "WebKitStatisticsPrivate.h" +#import "WebKitSystemBits.h" +#import "WebLocalizableStrings.h" +#import "WebNSObjectExtras.h" +#import "WebNSURLExtras.h" +#import "WebNSURLRequestExtras.h" +#import "WebNSViewExtras.h" +#import "WebNetscapePluginEmbeddedView.h" +#import "WebNetscapePluginPackage.h" +#import "WebNullPluginView.h" +#import "WebPlugin.h" +#import "WebPluginController.h" +#import "WebPluginDatabase.h" +#import "WebPluginPackage.h" +#import "WebPluginViewFactoryPrivate.h" +#import "WebPreferencesPrivate.h" +#import "WebResourcePrivate.h" +#import "WebScriptDebugServerPrivate.h" +#import "WebUIDelegatePrivate.h" +#import "WebViewInternal.h" +#import <Foundation/NSURLConnection.h> +#import <Foundation/NSURLRequest.h> +#import <Foundation/NSURLResponse.h> +#import <JavaScriptCore/Assertions.h> +#import <JavaScriptCore/JSLock.h> +#import <JavaScriptCore/object.h> +#import <JavaVM/jni.h> +#import <WebCore/Cache.h> +#import <WebCore/Document.h> +#import <WebCore/DocumentLoader.h> +#import <WebCore/DragController.h> +#import <WebCore/Element.h> +#import <WebCore/FoundationExtras.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameLoader.h> +#import <WebCore/FrameLoaderClient.h> +#import <WebCore/FrameTree.h> +#import <WebCore/HTMLFrameOwnerElement.h> +#import <WebCore/Page.h> +#import <WebCore/ResourceLoader.h> +#import <WebCore/SubresourceLoader.h> +#import <WebCore/WebCoreObjCExtras.h> +#import <WebKitSystemInterface.h> +#import <wtf/RefPtr.h> +#import <WebCore/MIMETypeRegistry.h> + +// For compatibility with old SPI. +@interface NSView (OldWebPlugin) +- (void)setIsSelected:(BOOL)f; +@end + +@interface NSView (JavaPluginSecrets) +- (jobject)pollForAppletInWindow:(NSWindow *)window; +@end + +using namespace WebCore; + +NSString *WebPluginBaseURLKey = @"WebPluginBaseURL"; +NSString *WebPluginAttributesKey = @"WebPluginAttributes"; +NSString *WebPluginContainerKey = @"WebPluginContainer"; + +#define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange" +#define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode") +#define UniversalAccessDomain CFSTR("com.apple.universalaccess") + +@implementation WebFrameBridge + +#ifndef BUILDING_ON_TIGER ++ (void)initialize +{ + WebCoreObjCFinalizeOnMainThread(self); +} +#endif + +- (WebView *)webView +{ + if (!m_frame) + return nil; + + return kit(m_frame->page()); +} + +- (void)finishInitializingWithPage:(Page*)page frameName:(NSString *)name frameView:(WebFrameView *)frameView ownerElement:(HTMLFrameOwnerElement*)ownerElement +{ + ++WebBridgeCount; + + WebView *webView = kit(page); + + _frame = [[WebFrame alloc] _initWithWebFrameView:frameView webView:webView bridge:self]; + + m_frame = new Frame(page, ownerElement, new WebFrameLoaderClient(_frame)); + m_frame->setBridge(self); + m_frame->tree()->setName(name); + m_frame->init(); + + [self setTextSizeMultiplier:[webView textSizeMultiplier]]; +} + +- (id)initMainFrameWithPage:(Page*)page frameName:(NSString *)name frameView:(WebFrameView *)frameView +{ + self = [super init]; + [self finishInitializingWithPage:page frameName:name frameView:frameView ownerElement:0]; + return self; +} + +- (id)initSubframeWithOwnerElement:(HTMLFrameOwnerElement*)ownerElement frameName:(NSString *)name frameView:(WebFrameView *)frameView +{ + self = [super init]; + [self finishInitializingWithPage:ownerElement->document()->frame()->page() frameName:name frameView:frameView ownerElement:ownerElement]; + return self; +} + +- (void)fini +{ + if (_keyboardUIModeAccessed) { + [[NSDistributedNotificationCenter defaultCenter] + removeObserver:self name:KeyboardUIModeDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] + removeObserver:self name:WebPreferencesChangedNotification object:nil]; + } + + ASSERT(_frame == nil); + --WebBridgeCount; +} + +- (void)dealloc +{ + [lastDashboardRegions release]; + [_frame release]; + + [self fini]; + [super dealloc]; +} + +- (void)finalize +{ + ASSERT_MAIN_THREAD(); + [self fini]; + [super finalize]; +} + +- (WebPreferences *)_preferences +{ + return [[self webView] preferences]; +} + +- (void)_retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification +{ + CFPreferencesAppSynchronize(UniversalAccessDomain); + + Boolean keyExistsAndHasValidFormat; + int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, UniversalAccessDomain, &keyExistsAndHasValidFormat); + + // The keyboard access mode is reported by two bits: + // Bit 0 is set if feature is on + // Bit 1 is set if full keyboard access works for any control, not just text boxes and lists + // We require both bits to be on. + // I do not know that we would ever get one bit on and the other off since + // checking the checkbox in system preferences which is marked as "Turn on full keyboard access" + // turns on both bits. + _keyboardUIMode = (mode & 0x2) ? KeyboardAccessFull : KeyboardAccessDefault; + + // check for tabbing to links + if ([[self _preferences] tabsToLinks]) + _keyboardUIMode = (KeyboardUIMode)(_keyboardUIMode | KeyboardAccessTabsToLinks); +} + +- (KeyboardUIMode)keyboardUIMode +{ + if (!_keyboardUIModeAccessed) { + _keyboardUIModeAccessed = YES; + [self _retrieveKeyboardUIModeFromPreferences:nil]; + + [[NSDistributedNotificationCenter defaultCenter] + addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) + name:KeyboardUIModeDidChangeNotification object:nil]; + + [[NSNotificationCenter defaultCenter] + addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) + name:WebPreferencesChangedNotification object:nil]; + } + return _keyboardUIMode; +} + +- (WebFrame *)webFrame +{ + return _frame; +} + +- (WebCoreFrameBridge *)mainFrame +{ + ASSERT(_frame != nil); + return [[[self webView] mainFrame] _bridge]; +} + +- (NSResponder *)firstResponder +{ + ASSERT(_frame != nil); + WebView *webView = [self webView]; + return [[webView _UIDelegateForwarder] webViewFirstResponder:webView]; +} + +- (void)makeFirstResponder:(NSResponder *)view +{ + ASSERT(_frame != nil); + WebView *webView = [self webView]; + ASSERT([view isKindOfClass:[NSView class]]); + ASSERT([(NSView *)view window]); + ASSERT([(NSView *)view window] == [webView window]); + [webView _pushPerformingProgrammaticFocus]; + [[webView _UIDelegateForwarder] webView:webView makeFirstResponder:view]; + [webView _popPerformingProgrammaticFocus]; +} + +- (NSWindow *)window +{ + ASSERT(_frame != nil); + return [[_frame frameView] window]; +} + +- (void)runOpenPanelForFileButtonWithResultListener:(id<WebCoreOpenPanelResultListener>)resultListener +{ + WebView *wv = [self webView]; + [[wv _UIDelegateForwarder] webView:wv runOpenPanelForFileButtonWithResultListener:(id<WebOpenPanelResultListener>)resultListener]; +} + +- (WebDataSource *)dataSource +{ + ASSERT(_frame != nil); + WebDataSource *dataSource = [_frame _dataSource]; + + ASSERT(dataSource != nil); + + return dataSource; +} + +- (void)close +{ + [super close]; + [_frame release]; + _frame = nil; +} + +- (Frame*)createChildFrameNamed:(NSString *)frameName + withURL:(NSURL *)URL + referrer:(const String&)referrer + ownerElement:(HTMLFrameOwnerElement*)ownerElement + allowsScrolling:(BOOL)allowsScrolling + marginWidth:(int)width + marginHeight:(int)height +{ + ASSERT(_frame); + + WebFrameView *childView = [[WebFrameView alloc] initWithFrame:NSMakeRect(0,0,0,0)]; + [childView setAllowsScrolling:allowsScrolling]; + [childView _setMarginWidth:width]; + [childView _setMarginHeight:height]; + + WebFrameBridge *newBridge = [[WebFrameBridge alloc] initSubframeWithOwnerElement:ownerElement frameName:frameName frameView:childView]; + [childView release]; + + if (!newBridge) + return 0; + + [_frame _addChild:[newBridge webFrame]]; + [newBridge release]; + + RefPtr<Frame> newFrame = [newBridge _frame]; + + [_frame _loadURL:URL referrer:referrer intoChild:kit(newFrame.get())]; + + // The frame's onload handler may have removed it from the document. + if (!newFrame->tree()->parent()) + return 0; + + return newFrame.get(); +} + +- (NSView *)pluginViewWithPackage:(WebPluginPackage *)pluginPackage + attributeNames:(NSArray *)attributeNames + attributeValues:(NSArray *)attributeValues + baseURL:(NSURL *)baseURL + DOMElement:(DOMElement *)element + loadManually:(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; +} + +- (NSString *)valueForKey:(NSString *)key keys:(NSArray *)keys values:(NSArray *)values +{ + unsigned count = [keys count]; + unsigned i; + for (i = 0; i < count; i++) + if ([[keys objectAtIndex:i] _webkit_isCaseInsensitiveEqualToString:key]) + return [values objectAtIndex:i]; + return nil; +} + +- (NSView *)viewForPluginWithFrame:(NSRect)frame + URL:(NSURL *)URL + attributeNames:(NSArray *)attributeNames + attributeValues:(NSArray *)attributeValues + MIMEType:(NSString *)MIMEType + DOMElement:(DOMElement *)element + loadManually:(BOOL)loadManually +{ + ASSERT([attributeNames count] == [attributeValues count]); + + WebBasePluginPackage *pluginPackage = nil; + NSView *view = nil; + int errorCode = 0; + + WebView *webView = [self webView]; + SEL selector = @selector(webView:plugInViewWithArguments:); + + if ([[webView UIDelegate] respondsToSelector:selector]) { + NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames]; + NSDictionary *arguments = [[NSDictionary alloc] initWithObjectsAndKeys: + attributes, WebPlugInAttributesKey, + [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey, + [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey, + element, WebPlugInContainingElementKey, + URL, WebPlugInBaseURLKey, // URL might be nil, so add it last + nil]; + + view = CallUIDelegate(webView, selector, arguments); + + [attributes release]; + [arguments release]; + + if (view) + return view; + } + + if ([MIMEType length] != 0) + pluginPackage = [[self webView] _pluginForMIMEType:MIMEType]; + else + MIMEType = nil; + + NSString *extension = [[URL path] pathExtension]; + if (!pluginPackage && [extension length] != 0) { + pluginPackage = [[self webView] _pluginForExtension:extension]; + if (pluginPackage) { + NSString *newMIMEType = [pluginPackage MIMETypeForExtension:extension]; + if ([newMIMEType length] != 0) + MIMEType = newMIMEType; + } + } + + NSURL *baseURL = [self baseURL]; + if (pluginPackage) { + if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) { + view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage + attributeNames:attributeNames + attributeValues:attributeValues + baseURL:baseURL + DOMElement:element + loadManually:loadManually]; + + } +#ifndef __LP64__ + else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) { + WebNetscapePluginEmbeddedView *embeddedView = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:frame + pluginPackage:(WebNetscapePluginPackage *)pluginPackage + URL:URL + baseURL:baseURL + MIMEType:MIMEType + attributeKeys:attributeNames + attributeValues:attributeValues + loadManually:loadManually + DOMElement:element] autorelease]; + view = embeddedView; + } +#endif + } else + errorCode = WebKitErrorCannotFindPlugIn; + + if (!errorCode && !view) + errorCode = WebKitErrorCannotLoadPlugIn; + + if (errorCode) { + NSString *pluginPage = [self valueForKey:@"pluginspage" keys:attributeNames values:attributeValues]; + NSURL *pluginPageURL = pluginPage != nil ? [self URLWithAttributeString:pluginPage] : nil; + NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode + contentURL:URL + pluginPageURL:pluginPageURL + pluginName:[pluginPackage name] + MIMEType:MIMEType]; + WebNullPluginView *nullView = [[[WebNullPluginView alloc] initWithFrame:frame error:error DOMElement:element] autorelease]; + view = nullView; + [error release]; + } + + ASSERT(view); + return view; +} + +- (void)redirectDataToPlugin:(NSView *)pluginView +{ + WebHTMLRepresentation *representation = (WebHTMLRepresentation *)[[_frame _dataSource] representation]; + +#ifndef __LP64__ + if ([pluginView isKindOfClass:[WebNetscapePluginEmbeddedView class]]) + [representation _redirectDataToManualLoader:(WebNetscapePluginEmbeddedView *)pluginView forPluginView:pluginView]; + else { +#else + { +#endif + WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView]; + ASSERT([docView isKindOfClass:[WebHTMLView class]]); + + WebPluginController *pluginController = [docView _pluginController]; + [representation _redirectDataToManualLoader:pluginController forPluginView:pluginView]; + } + +} + +- (NSView *)viewForJavaAppletWithFrame:(NSRect)theFrame + attributeNames:(NSArray *)attributeNames + attributeValues:(NSArray *)attributeValues + baseURL:(NSURL *)baseURL + DOMElement:(DOMElement *)element +{ + NSString *MIMEType = @"application/x-java-applet"; + WebBasePluginPackage *pluginPackage; + NSView *view = nil; + + pluginPackage = [[self 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 = [attributeNames mutableCopy]; + NSMutableArray *values = [attributeValues mutableCopy]; + if ([self valueForKey:@"width" keys:attributeNames values:attributeValues] == nil) { + [names addObject:@"width"]; + [values addObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.width]]; + } + if ([self valueForKey:@"height" keys:attributeNames values:attributeValues] == nil) { + [names addObject:@"height"]; + [values addObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.height]]; + } + view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage + attributeNames:names + attributeValues:values + baseURL:baseURL + DOMElement:element + loadManually:NO]; + [names release]; + [values release]; + + } +#ifndef __LP64__ + else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) { + view = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:theFrame + pluginPackage:(WebNetscapePluginPackage *)pluginPackage + URL:nil + baseURL:baseURL + MIMEType:MIMEType + attributeKeys:attributeNames + attributeValues:attributeValues + loadManually:NO + DOMElement: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:theFrame error:error DOMElement:element] autorelease]; + [error release]; + } + + ASSERT(view); + + return view; +} + +- (ObjectContentType)determineObjectFromMIMEType:(NSString*)MIMEType URL:(NSURL*)URL +{ + // 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 isEqualToString:@"application/x-apple-msg-attachment"]) + return ObjectContentNetscapePlugin; + + if ([MIMEType length] == 0) { + // Try to guess the MIME type based off the extension. + NSString *extension = [[URL path] pathExtension]; + if ([extension length] > 0) { + MIMEType = WKGetMIMETypeForExtension(extension); + if ([MIMEType length] == 0) { + // If no MIME type is specified, use a plug-in if we have one that can handle the extension. + if (WebBasePluginPackage *package = [[self webView] _pluginForExtension:extension]) { + if ([package isKindOfClass:[WebPluginPackage class]]) + return ObjectContentOtherPlugin; +#ifndef __LP64__ + else { + ASSERT([package isKindOfClass:[WebNetscapePluginPackage class]]); + return ObjectContentNetscapePlugin; + } +#endif + } + } + } + } + + if ([MIMEType length] == 0) + return ObjectContentFrame; // Go ahead and hope that we can display the content. + + if (MIMETypeRegistry::isSupportedImageMIMEType(MIMEType)) + return ObjectContentImage; + + if (WebBasePluginPackage *package = [[self webView] _pluginForMIMEType:MIMEType]) { + if ([package isKindOfClass:[WebPluginPackage class]]) + return ObjectContentOtherPlugin; +#ifndef __LP64__ + else { + ASSERT([package isKindOfClass:[WebNetscapePluginPackage class]]); + return ObjectContentNetscapePlugin; + } +#endif + } + + if ([WebFrameView _viewClassForMIMEType:MIMEType]) + return ObjectContentFrame; + + return ObjectContentNone; +} + +- (jobject)getAppletInView:(NSView *)view +{ + if ([view respondsToSelector:@selector(webPlugInGetApplet)]) + return [view webPlugInGetApplet]; + return [self pollForAppletInView:view]; +} + +// NOTE: pollForAppletInView: will block until the block is ready to use, or +// until a timeout is exceeded. It will return nil if the timeout is +// exceeded. +// Deprecated, use getAppletInView:. +- (jobject)pollForAppletInView:(NSView *)view +{ + if ([view respondsToSelector:@selector(pollForAppletInWindow:)]) + // The Java VM needs the containing window of the view to + // initialize. The view may not yet be in the window's view + // hierarchy, so we have to pass the window when requesting + // the applet. + return [view pollForAppletInWindow:[[self webView] window]]; + return 0; +} + +- (void)respondToChangedContents +{ + NSView <WebDocumentView> *view = [[_frame frameView] documentView]; + if ([view isKindOfClass:[WebHTMLView class]]) + [(WebHTMLView *)view _updateFontPanel]; + [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeNotification object:[self webView]]; +} + +- (NSUndoManager *)undoManager +{ + return [[self webView] undoManager]; +} + +- (void)issuePasteCommand +{ + NSView* documentView = [[_frame frameView] documentView]; + if ([documentView isKindOfClass:[WebHTMLView class]]) + [(WebHTMLView*)documentView paste:nil]; +} + +- (void)setIsSelected:(BOOL)isSelected forView:(NSView *)view +{ + if ([view respondsToSelector:@selector(webPlugInSetIsSelected:)]) + [view webPlugInSetIsSelected:isSelected]; + else if ([view respondsToSelector:@selector(setIsSelected:)]) + [view setIsSelected:isSelected]; +} + +- (void)windowObjectCleared +{ + WebView *webView = getWebView(_frame); + WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView); + if (implementations->didClearWindowObjectForFrameFunc) + CallFrameLoadDelegate(implementations->didClearWindowObjectForFrameFunc, webView, @selector(webView:didClearWindowObject:forFrame:), m_frame->windowScriptObject(), _frame); + else if (implementations->windowScriptObjectAvailableFunc) + CallFrameLoadDelegate(implementations->windowScriptObjectAvailableFunc, webView, @selector(webView:windowScriptObjectAvailable:), m_frame->windowScriptObject()); + + if ([webView scriptDebugDelegate] || [WebScriptDebugServer listenerCount]) { + [_frame _detachScriptDebugger]; + [_frame _attachScriptDebugger]; + } +} + +- (BOOL)_compareDashboardRegions:(NSDictionary *)regions +{ + return [lastDashboardRegions isEqualToDictionary:regions]; +} + +- (void)dashboardRegionsChanged:(NSMutableDictionary *)regions +{ + WebView *webView = [self webView]; + [webView _addScrollerDashboardRegions:regions]; + + if (![self _compareDashboardRegions:regions]) { + CallUIDelegate(webView, @selector(webView:dashboardRegionsChanged:), regions); + + [lastDashboardRegions release]; + lastDashboardRegions = [regions retain]; + } +} + +- (void)willPopupMenu:(NSMenu *)menu +{ + CallUIDelegate([self webView], @selector(webView:willPopupMenu:), menu); +} + +- (NSRect)customHighlightRect:(NSString*)type forLine:(NSRect)lineRect representedNode:(WebCore::Node *)node +{ + ASSERT(_frame != nil); + NSView *documentView = [[_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]; +} + +- (void)paintCustomHighlight:(NSString*)type forBox:(NSRect)boxRect onLine:(NSRect)lineRect behindText:(BOOL)text entireLine:(BOOL)line representedNode:(WebCore::Node *)node +{ + ASSERT(_frame != nil); + NSView *documentView = [[_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:text entireLine:line representedNode:kit(node)]; + else + [highlighter paintHighlightForBox:boxRect onLine:lineRect behindText:text entireLine:line]; +} + +@end diff --git a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h new file mode 100644 index 0000000..12bcc51 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h @@ -0,0 +1,219 @@ +/* + * 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/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 bool hasFrameView() const; // ditto + + 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 detachedFromParent4(); + + 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&, const WebCore::String& frameName); + virtual void dispatchDecidePolicyForNavigationAction(WebCore::FramePolicyFunction, + const WebCore::NavigationAction&, const WebCore::ResourceRequest&); + 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 void clearUnarchivingState(WebCore::DocumentLoader*); + 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 finalSetupForReplace(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 bool shouldFallBack(const WebCore::ResourceError&); + + virtual void setDefersLoading(bool); + + virtual WebCore::String userAgent(const WebCore::KURL&); + + virtual void savePlatformDataToCachedPage(WebCore::CachedPage*); + virtual void transitionToCommittedFromCachedPage(WebCore::CachedPage*); + virtual void transitionToCommittedForNewPage(); + + virtual bool willUseArchive(WebCore::ResourceLoader*, const WebCore::ResourceRequest&, const WebCore::KURL& originalURL) const; + virtual bool isArchiveLoadPending(WebCore::ResourceLoader*) const; + virtual void cancelPendingArchiveLoad(WebCore::ResourceLoader*); + virtual void clearArchivedResources(); + + 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); + + void deliverArchivedResourcesAfterDelay() const; + void deliverArchivedResources(WebCore::Timer<WebFrameLoaderClient>*); + + void setOriginalURLForDownload(WebDownload *, const WebCore::ResourceRequest&) const; + + RetainPtr<WebFramePolicyListener> setUpPolicyListener(WebCore::FramePolicyFunction); + + NSDictionary *actionDictionary(const WebCore::NavigationAction&) const; + + virtual bool canCachePage() const; + + RetainPtr<WebFrame> m_webFrame; + + RetainPtr<WebFramePolicyListener> m_policyListener; + WebCore::FramePolicyFunction m_policyFunction; + + mutable ResourceMap m_pendingArchivedResources; + mutable WebCore::Timer<WebFrameLoaderClient> m_archivedResourcesDeliveryTimer; +}; diff --git a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm new file mode 100644 index 0000000..d77fd89 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm @@ -0,0 +1,1276 @@ +/* + * 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 "WebPolicyDelegatePrivate.h" +#import "WebDocumentInternal.h" +#import "WebDocumentLoaderMac.h" +#import "WebDownloadInternal.h" +#import "WebDynamicScrollBarsView.h" +#import "WebElementDictionary.h" +#import "WebFormDelegate.h" +#import "WebFrameBridge.h" +#import "WebFrameInternal.h" +#import "WebFrameLoadDelegate.h" +#import "WebFrameViewInternal.h" +#import "WebHTMLRepresentation.h" +#import "WebHTMLView.h" +#import "WebHistoryItemInternal.h" +#import "WebHistoryItemPrivate.h" +#import "WebHistoryPrivate.h" +#import "WebIconDatabaseInternal.h" +#import "WebKitErrorsPrivate.h" +#import "WebKitLogging.h" +#import "WebKitNSStringExtras.h" +#import "WebNSURLExtras.h" +#import "WebPanelAuthenticationHandler.h" +#import "WebPolicyDelegate.h" +#import "WebPreferences.h" +#import "WebResourceLoadDelegate.h" +#import "WebResourcePrivate.h" +#import "WebScriptDebugServerPrivate.h" +#import "WebUIDelegate.h" +#import "WebUIDelegatePrivate.h" +#import "WebViewInternal.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/FrameLoader.h> +#import <WebCore/FrameLoaderTypes.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameTree.h> +#import <WebCore/HistoryItem.h> +#import <WebCore/HitTestResult.h> +#import <WebCore/HTMLFormElement.h> +#import <WebCore/IconDatabase.h> +#import <WebCore/LoaderNSURLExtras.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/WebCoreFrameBridge.h> +#import <WebCore/WebCoreObjCExtras.h> +#import <WebCore/SharedBuffer.h> +#import <WebCore/Widget.h> +#import <WebKit/DOMElement.h> +#import <WebKit/DOMHTMLFormElement.h> +#import <wtf/PassRefPtr.h> + +using namespace WebCore; + +// SPI for NSURLDownload +// Needed for <rdar://problem/5121850> +@interface NSURLDownload (NSURLDownloadPrivate) +- (void)_setOriginatingURL:(NSURL *)originatingURL; +@end + +@interface WebHistoryItem (WebHistoryItemPrivate) +- (BOOL)_wasUserGesture; +@end + +@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) + , m_archivedResourcesDeliveryTimer(this, &WebFrameLoaderClient::deliverArchivedResources) +{ +} + +void WebFrameLoaderClient::frameLoaderDestroyed() +{ + delete this; +} + +bool WebFrameLoaderClient::hasWebView() const +{ + return [m_webFrame.get() webView] != nil; +} + +bool WebFrameLoaderClient::hasFrameView() const +{ + return m_webFrame->_private->webFrameView != 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; + 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() +{ + [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::detachedFromParent4() +{ + m_webFrame->_private->bridge = 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++) { + WebHistoryItem *currentItem = [history itemAtIndex:-backIndex]; + if (![currentItem respondsToSelector:@selector(_wasUserGesture)] || [currentItem _wasUserGesture]) + originalURL = [currentItem 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() +{ + ASSERT([m_webFrame.get() _isMainFrame]); + WebView *webView = getWebView(m_webFrame.get()); + + [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); + + 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, const String& frameName) +{ + WebView *webView = getWebView(m_webFrame.get()); + [[webView _policyDelegateForwarder] webView:webView + decidePolicyForNewWindowAction:actionDictionary(action) + request:request.nsURLRequest() + newFrameName:frameName + decisionListener:setUpPolicyListener(function).get()]; +} + +void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, + const NavigationAction& action, const ResourceRequest& request) +{ + WebView *webView = getWebView(m_webFrame.get()); + [[webView _policyDelegateForwarder] webView:webView + decidePolicyForNavigationAction:actionDictionary(action) + 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) +{ + if ([WebScriptDebugServer listenerCount]) + [[WebScriptDebugServer sharedScriptDebugServer] webView:getWebView(m_webFrame.get()) didLoadMainResourceForDataSource:dataSource(loader)]; +} + +void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader* loader) +{ + [dataSource(loader) _revertToProvisionalState]; +} + +void WebFrameLoaderClient::setMainDocumentError(DocumentLoader* loader, const ResourceError& error) +{ + [dataSource(loader) _setMainDocumentError:error]; +} + +void WebFrameLoaderClient::clearUnarchivingState(DocumentLoader* loader) +{ + [dataSource(loader) _clearUnarchivingState]; +} + +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::finalSetupForReplace(DocumentLoader* loader) +{ + [dataSource(loader) _clearUnarchivingState]; +} + +void WebFrameLoaderClient::updateGlobalHistory(const KURL& url) +{ + NSURL *cocoaURL = url; + WebHistoryItem *entry = [[WebHistory optionalSharedHistory] addItemForURL:cocoaURL]; + const String& pageTitle = core(m_webFrame.get())->loader()->documentLoader()->title(); + if (!pageTitle.isEmpty()) + [entry setTitle: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()]; +} + +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; +} + +void WebFrameLoaderClient::setDefersLoading(bool defers) +{ + if (!defers) + deliverArchivedResourcesAfterDelay(); +} + +bool WebFrameLoaderClient::willUseArchive(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL) const +{ + if (request.url() != originalURL) + return false; + + WebResource *resource = [dataSource(core(m_webFrame.get())->loader()->activeDocumentLoader()) _archivedSubresourceForURL:originalURL]; + if (!resource) + return false; + + m_pendingArchivedResources.set(loader, resource); + // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method. + deliverArchivedResourcesAfterDelay(); + + return true; +} + +bool WebFrameLoaderClient::isArchiveLoadPending(ResourceLoader* loader) const +{ + return m_pendingArchivedResources.contains(loader); +} + +void WebFrameLoaderClient::cancelPendingArchiveLoad(ResourceLoader* loader) +{ + if (m_pendingArchivedResources.isEmpty()) + return; + m_pendingArchivedResources.remove(loader); + if (m_pendingArchivedResources.isEmpty()) + m_archivedResourcesDeliveryTimer.stop(); +} + +void WebFrameLoaderClient::clearArchivedResources() +{ + m_pendingArchivedResources.clear(); + m_archivedResourcesDeliveryTimer.stop(); +} + +bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest& request) const +{ + return [WebView _canHandleRequest:request.nsURLRequest()]; +} + +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 bridge, 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 = new WebDocumentLoaderMac(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::deliverArchivedResourcesAfterDelay() const +{ + if (m_pendingArchivedResources.isEmpty()) + return; + if (core(m_webFrame.get())->page()->defersLoading()) + return; + if (!m_archivedResourcesDeliveryTimer.isActive()) + m_archivedResourcesDeliveryTimer.startOneShot(0); +} + +void WebFrameLoaderClient::deliverArchivedResources(Timer<WebFrameLoaderClient>*) +{ + if (m_pendingArchivedResources.isEmpty()) + return; + if (core(m_webFrame.get())->page()->defersLoading()) + return; + + const ResourceMap copy = m_pendingArchivedResources; + m_pendingArchivedResources.clear(); + + ResourceMap::const_iterator end = copy.end(); + for (ResourceMap::const_iterator it = copy.begin(); it != end; ++it) { + RefPtr<ResourceLoader> loader = it->first; + WebResource *resource = it->second.get(); + NSData *data = [[resource data] retain]; + loader->didReceiveResponse([resource _response]); + loader->didReceiveData((const char*)[data bytes], [data length], [data length], true); + [data release]; + loader->didFinishLoading(); + } +} + +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())]; + [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 = [m_webFrame.get() _frameLoader]->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]; + + NSView <WebDocumentView> *documentView = [v _makeDocumentViewForDataSource:ds]; + if (!documentView) + return; + + WebFrameBridge *bridge = m_webFrame->_private->bridge; + + // FIXME: We could save work and not do this for a top-level view that is not a WebHTMLView. + [bridge createFrameViewWithNSView:documentView marginWidth:[v _marginWidth] marginHeight:[v _marginHeight]]; + [m_webFrame.get() _updateBackground]; + [bridge installInFrame:[v _scrollView]]; + + // 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]; +} + +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) +{ + return [getWebView(m_webFrame.get()) _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) 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(); + 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)]; + NSDictionary *result = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey, + element, WebActionElementKey, + [NSNumber numberWithInt:mouseEvent->button()], WebActionButtonKey, + [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey, + originalURL, WebActionOriginalURLKey, + nil]; + [element release]; + return result; + } + return [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey, + [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey, + originalURL, WebActionOriginalURLKey, + nil]; +} + +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) +{ + WebFrameBridge* bridge = m_webFrame->_private->bridge; + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + return [bridge createChildFrameNamed:name + withURL:url + referrer:referrer + ownerElement:ownerElement + allowsScrolling:allowsScrolling + marginWidth:marginWidth + marginHeight:marginHeight]; + + END_BLOCK_OBJC_EXCEPTIONS; + return 0; +} + +ObjectContentType WebFrameLoaderClient::objectContentType(const KURL& url, const String& mimeType) +{ + WebFrameBridge* bridge = m_webFrame->_private->bridge; + BEGIN_BLOCK_OBJC_EXCEPTIONS; + return [bridge determineObjectFromMIMEType:mimeType URL:url]; + END_BLOCK_OBJC_EXCEPTIONS; + return ObjectContentNone; +} + +static NSArray* nsArray(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; +} + +Widget* WebFrameLoaderClient::createPlugin(const IntSize& size, Element* element, const KURL& url, const Vector<String>& paramNames, + const Vector<String>& paramValues, const String& mimeType, bool loadManually) +{ + WebFrameBridge* bridge = m_webFrame->_private->bridge; + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + return new Widget([bridge viewForPluginWithFrame:NSMakeRect(0, 0, size.width(), size.height()) + URL:url + attributeNames:nsArray(paramNames) + attributeValues:nsArray(paramValues) + MIMEType:mimeType + DOMElement:[DOMElement _wrapElement:element] + loadManually:loadManually]); + END_BLOCK_OBJC_EXCEPTIONS; + + return 0; +} + +void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + [m_webFrame->_private->bridge redirectDataToPlugin:pluginWidget->getView()]; + END_BLOCK_OBJC_EXCEPTIONS; +} + +Widget* WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, Element* element, const KURL& baseURL, + const Vector<String>& paramNames, const Vector<String>& paramValues) +{ + Widget* result = new Widget; + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + WebFrameBridge* bridge = m_webFrame->_private->bridge; + result->setView([bridge viewForJavaAppletWithFrame:NSMakeRect(0, 0, size.width(), size.height()) + attributeNames:nsArray(paramNames) + attributeValues:nsArray(paramValues) + baseURL:baseURL + DOMElement:[DOMElement _wrapElement:element]]); + END_BLOCK_OBJC_EXCEPTIONS; + + return result; +} + +String WebFrameLoaderClient::overrideMediaType() const +{ + NSString* overrideType = [getWebView(m_webFrame.get()) mediaStyle]; + if (overrideType) + return overrideType; + return String(); +} + +void WebFrameLoaderClient::windowObjectCleared() +{ + [m_webFrame->_private->bridge windowObjectCleared]; +} + +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]; +} + +@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 (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..45cd1f9 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebInspectorClient.h @@ -0,0 +1,62 @@ +/* + * 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> + +@class WebInspectorWindowController; +@class WebView; + +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 highlight(WebCore::Node*); + virtual void hideHighlight(); + virtual void inspectedURLChanged(const WebCore::String& newURL); + +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..255e51e --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebInspectorClient.mm @@ -0,0 +1,535 @@ +/* + * 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 "WebInspectorClient.h" + +#import "WebFrameInternal.h" +#import "WebFrameView.h" +#import "WebLocalizableStrings.h" +#import "WebNodeHighlight.h" +#import "WebPreferences.h" +#import "WebTypesInternal.h" +#import "WebView.h" +#import "WebViewInternal.h" +#import "WebViewPrivate.h" + +#import <AppKit/NSWindowController.h> + +#import <WebCore/InspectorController.h> +#import <WebCore/Page.h> + +#import <WebKit/DOMCore.h> +#import <WebKit/DOMExtensions.h> +#import <WebKit/WebUIDelegate.h> + +#import <WebKitSystemInterface.h> + +using namespace WebCore; + +@interface WebInspectorWindowController : NSWindowController { +@private + WebView *_inspectedWebView; + WebView *_webView; + NSImageView *_shadowView; + WebNodeHighlight *_currentHighlight; + BOOL _attachedToInspectedWebView; + BOOL _shouldAttach; + BOOL _visible; + BOOL _movingWindows; +} +- (id)initWithInspectedWebView:(WebView *)webView; +- (BOOL)inspectorVisible; +- (WebView *)webView; +- (void)attach; +- (void)detach; +- (void)highlightAndScrollToNode:(DOMNode *)node; +- (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:@"InspectorLocalizedStrings" 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::highlight(Node* node) +{ + [m_windowController.get() highlightAndScrollToNode: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 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]; + + 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 +{ + [_shadowView release]; + [_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:YES]; + [window setDelegate:self]; + [window setMinSize:NSMakeSize(400.0, 400.0)]; + +#ifndef BUILDING_ON_TIGER + [window setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge]; + [window setContentBorderThickness:40. 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); + + [_currentHighlight detachHighlight]; + [_currentHighlight setDelegate:nil]; + [_currentHighlight release]; + _currentHighlight = nil; + + return YES; +} + +- (void)close +{ + if (!_visible) + return; + + _visible = NO; + + [_inspectedWebView page]->inspectorController()->setWindowVisible(false); + + if (!_movingWindows) { + [_currentHighlight detachHighlight]; + [_currentHighlight setDelegate:nil]; + [_currentHighlight release]; + _currentHighlight = nil; + } + + if (_attachedToInspectedWebView) { + if ([_inspectedWebView _isClosed]) + return; + + WebFrameView *frameView = [[_inspectedWebView mainFrame] frameView]; + + NSRect frameViewRect = [frameView frame]; + NSRect finalFrameViewRect = NSMakeRect(0, 0, NSWidth(frameViewRect), NSHeight([_inspectedWebView frame])); + NSMutableDictionary *frameViewAnimationInfo = [[NSMutableDictionary alloc] init]; + [frameViewAnimationInfo setObject:frameView forKey:NSViewAnimationTargetKey]; + [frameViewAnimationInfo setObject:[NSValue valueWithRect:finalFrameViewRect] forKey:NSViewAnimationEndFrameKey]; + + ASSERT(_shadowView); + NSRect shadowFrame = [_shadowView frame]; + shadowFrame = NSMakeRect(0, NSMinY(frameViewRect) - NSHeight(shadowFrame), NSWidth(frameViewRect), NSHeight(shadowFrame)); + [_shadowView setFrame:shadowFrame]; + + [_shadowView removeFromSuperview]; + [_inspectedWebView addSubview:_shadowView positioned:NSWindowAbove relativeTo:_webView]; + + NSRect finalShadowRect = NSMakeRect(0, -NSHeight(shadowFrame), NSWidth(shadowFrame), NSHeight(shadowFrame)); + NSMutableDictionary *shadowAnimationInfo = [[NSMutableDictionary alloc] init]; + [shadowAnimationInfo setObject:_shadowView forKey:NSViewAnimationTargetKey]; + [shadowAnimationInfo setObject:[NSValue valueWithRect:finalShadowRect] forKey:NSViewAnimationEndFrameKey]; + + NSArray *animationInfo = [[NSArray alloc] initWithObjects:frameViewAnimationInfo, shadowAnimationInfo, nil]; + [frameViewAnimationInfo release]; + [shadowAnimationInfo release]; + + NSViewAnimation *slideAnimation = [[NSViewAnimation alloc] initWithViewAnimations:animationInfo]; // released in animationDidEnd + [animationInfo release]; + + [slideAnimation setAnimationBlockingMode:NSAnimationBlocking]; + [slideAnimation setDelegate:self]; + + [[_inspectedWebView window] display]; // display once to make sure we start in a good state + [slideAnimation startAnimation]; + } 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; + + [_inspectedWebView page]->inspectorController()->setWindowVisible(true); + + if (_shouldAttach) { + WebFrameView *frameView = [[_inspectedWebView mainFrame] frameView]; + + NSRect frameViewRect = [frameView frame]; + float attachedHeight = [[NSUserDefaults standardUserDefaults] integerForKey:WebKitInspectorAttachedViewHeightKey]; + attachedHeight = MAX(300.0, MIN(attachedHeight, (NSHeight(frameViewRect) * 0.6))); + + [_webView removeFromSuperview]; + [_inspectedWebView addSubview:_webView positioned:NSWindowBelow relativeTo:(NSView*)frameView]; + [_webView setFrame:NSMakeRect(0, 0, NSWidth(frameViewRect), attachedHeight)]; + [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable | NSViewMaxYMargin)]; + + [frameView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable | NSViewMinYMargin)]; + + NSRect finalFrameViewRect = NSMakeRect(0, attachedHeight, NSWidth(frameViewRect), NSHeight(frameViewRect) - attachedHeight); + NSMutableDictionary *frameViewAnimationInfo = [[NSMutableDictionary alloc] init]; + [frameViewAnimationInfo setObject:frameView forKey:NSViewAnimationTargetKey]; + [frameViewAnimationInfo setObject:[NSValue valueWithRect:finalFrameViewRect] forKey:NSViewAnimationEndFrameKey]; + + if (!_shadowView) { + NSString *imagePath = [[NSBundle bundleWithIdentifier:@"com.apple.WebCore"] pathForResource:@"attachedShadow" ofType:@"png" inDirectory:@"inspector/Images"]; + NSImage *image = [[NSImage alloc] initWithContentsOfFile:imagePath]; + _shadowView = [[NSImageView alloc] initWithFrame:NSMakeRect(0, -[image size].height, NSWidth(frameViewRect), [image size].height)]; + [_shadowView setImage:image]; + [_shadowView setImageScaling:NSScaleToFit]; + [_shadowView setImageFrameStyle:NSImageFrameNone]; + [_shadowView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable | NSViewMaxYMargin)]; + } + + NSRect shadowFrame = [_shadowView frame]; + shadowFrame = NSMakeRect(0, -NSHeight(shadowFrame), NSWidth(frameViewRect), NSHeight(shadowFrame)); + [_shadowView setFrame:shadowFrame]; + + [_shadowView removeFromSuperview]; + [_inspectedWebView addSubview:_shadowView positioned:NSWindowAbove relativeTo:_webView]; + + NSRect finalShadowRect = NSMakeRect(0, attachedHeight - NSHeight(shadowFrame), NSWidth(shadowFrame), NSHeight(shadowFrame)); + NSMutableDictionary *shadowAnimationInfo = [[NSMutableDictionary alloc] init]; + [shadowAnimationInfo setObject:_shadowView forKey:NSViewAnimationTargetKey]; + [shadowAnimationInfo setObject:[NSValue valueWithRect:finalShadowRect] forKey:NSViewAnimationEndFrameKey]; + + NSArray *animationInfo = [[NSArray alloc] initWithObjects:frameViewAnimationInfo, shadowAnimationInfo, nil]; + [frameViewAnimationInfo release]; + [shadowAnimationInfo release]; + + NSViewAnimation *slideAnimation = [[NSViewAnimation alloc] initWithViewAnimations:animationInfo]; // released in animationDidEnd + [animationInfo release]; + + [slideAnimation setAnimationBlockingMode:NSAnimationBlocking]; + [slideAnimation setDelegate:self]; + + _attachedToInspectedWebView = YES; + + [[_inspectedWebView window] display]; // display once to make sure we start in a good state + [slideAnimation startAnimation]; + } else { + _attachedToInspectedWebView = NO; + + NSView *contentView = [[self window] contentView]; + [_webView setFrame:[contentView frame]]; + [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [_webView removeFromSuperview]; + [contentView addSubview:_webView]; + + [super showWindow:nil]; + } +} + +#pragma mark - + +- (void)attach +{ + if (_attachedToInspectedWebView) + return; + + _shouldAttach = YES; + + if (_visible) { + _movingWindows = YES; + [self close]; + _movingWindows = NO; + } + + [self showWindow:nil]; +} + +- (void)detach +{ + if (!_attachedToInspectedWebView) + return; + + _shouldAttach = NO; + + if (_visible) { + _movingWindows = YES; // set back to NO in animationDidEnd + [self close]; + } else { + [self showWindow:nil]; + } +} + +#pragma mark - + +- (void)highlightAndScrollToNode:(DOMNode *)node +{ + NSRect bounds = [node boundingBox]; + if (!NSIsEmptyRect(bounds)) { + // FIXME: this needs to use the frame the node coordinates are in + NSRect visible = [[[[_inspectedWebView mainFrame] frameView] documentView] visibleRect]; + BOOL needsScroll = !NSContainsRect(visible, bounds) && !NSContainsRect(bounds, visible); + + // only scroll if the bounds isn't in the visible rect and dosen't contain the visible rect + if (needsScroll) { + // scroll to the parent element if we aren't focused on an element + DOMElement *element; + if ([node isKindOfClass:[DOMElement class]]) + element = (DOMElement *)node; + else + element = (DOMElement *)[node parentNode]; + [element scrollIntoViewIfNeeded:YES]; + + // give time for the scroll to happen + [self performSelector:@selector(highlightNode:) withObject:node afterDelay:0.25]; + } else + [self highlightNode:node]; + } +} + +- (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]; + [_currentHighlight setDelegate:self]; + [_currentHighlight attachHighlight]; + } + + [_currentHighlight show]; + + [_currentHighlight setHighlightedNode:node]; + + // FIXME: this is a hack until we hook up a didDraw and didScroll call in WebHTMLView + [[_currentHighlight highlightView] setNeedsDisplay:YES]; +} + +- (void)hideHighlight +{ + if (!_currentHighlight) + return; + [_currentHighlight hide]; + [_currentHighlight setHighlightedNode:nil]; +} + +#pragma mark - +#pragma mark Animation delegate + +- (void)animationDidEnd:(NSAnimation*)animation +{ + [animation release]; + + [_shadowView removeFromSuperview]; + + if (_movingWindows) { + _movingWindows = NO; + [self showWindow:nil]; + } +} + +#pragma mark - +#pragma mark UI delegate + +- (unsigned)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 page]->inspectorController()->show(); +} + +- (void)showErrorConsole:(id)sender +{ + [_inspectedWebView page]->inspectorController()->showConsole(); +} + +- (void)showNetworkTimeline:(id)sender +{ + [_inspectedWebView page]->inspectorController()->showTimeline(); +} + +@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..573dc84 --- /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 <JavaScriptCore/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..782a6f4 --- /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 <JavaScriptCore/Assertions.h> +#import <WebKit/WebLocalizableStrings.h> +#import <WebKitSystemInterface.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/WebNetscapePlugInStreamLoaderClient.h b/WebKit/mac/WebCoreSupport/WebNetscapePlugInStreamLoaderClient.h new file mode 100644 index 0000000..3f74097 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebNetscapePlugInStreamLoaderClient.h @@ -0,0 +1,50 @@ +/* + * 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 <WebKit/WebPlugInStreamLoaderDelegate.h> +#import <WebCore/NetscapePlugInStreamLoader.h> +#import <wtf/RetainPtr.h> + +namespace WebCore { + class NetscapePlugInStreamLoader; + class ResourceResponse; +}; + +typedef id <WebPlugInStreamLoaderDelegate> PlugInStreamLoaderDelegate; + +class WebNetscapePlugInStreamLoaderClient : public WebCore::NetscapePlugInStreamLoaderClient { +public: + WebNetscapePlugInStreamLoaderClient(PlugInStreamLoaderDelegate delegate) : m_stream(delegate) { } + virtual void didReceiveResponse(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceResponse&); + virtual void didReceiveData(WebCore::NetscapePlugInStreamLoader*, const char*, int); + virtual void didFail(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceError&); + virtual void didFinishLoading(WebCore::NetscapePlugInStreamLoader*); + +private: + RetainPtr<PlugInStreamLoaderDelegate> m_stream; +}; diff --git a/WebKit/mac/WebCoreSupport/WebNetscapePlugInStreamLoaderClient.mm b/WebKit/mac/WebCoreSupport/WebNetscapePlugInStreamLoaderClient.mm new file mode 100644 index 0000000..fcb3fbe --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebNetscapePlugInStreamLoaderClient.mm @@ -0,0 +1,57 @@ +/* + * 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 <WebKit/WebNetscapePlugInStreamLoaderClient.h> +#import <WebCore/NetscapePlugInStreamLoader.h> +#import <WebCore/ResourceResponse.h> + +using namespace WebCore; + +void WebNetscapePlugInStreamLoaderClient::didReceiveResponse(NetscapePlugInStreamLoader*, const ResourceResponse& theResponse) +{ + [m_stream.get() startStreamWithResponse:theResponse.nsURLResponse()]; +} + +void WebNetscapePlugInStreamLoaderClient::didReceiveData(NetscapePlugInStreamLoader*, const char* data, int length) +{ + NSData *nsData = [[NSData alloc] initWithBytesNoCopy:(void*)data length:length freeWhenDone:NO]; + [m_stream.get() receivedData:nsData]; + [nsData release]; +} + +void WebNetscapePlugInStreamLoaderClient::didFail(NetscapePlugInStreamLoader*, const ResourceError& error) +{ + [m_stream.get() destroyStreamWithError:error]; + m_stream = 0; +} + +void WebNetscapePlugInStreamLoaderClient::didFinishLoading(NetscapePlugInStreamLoader*) +{ + [m_stream.get() finishedLoading]; + m_stream = 0; +} 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..2e8376c --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebSystemInterface.m @@ -0,0 +1,99 @@ +/* + * 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(CGContextGetShouldSmoothFonts); + INIT(ClearGlyphVector); + INIT(ConvertCharToGlyphs); + 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(FontSmoothingModeIsLCD); + INIT(GetATSStyleGroup); + INIT(GetCGFontFromNSFont); + INIT(GetExtensionsForMIMEType); + INIT(GetFontInLanguageForCharacter); + INIT(GetFontInLanguageForRange); + INIT(GetGlyphTransformedAdvances); + INIT(GetGlyphVectorFirstRecord); + INIT(GetGlyphVectorNumGlyphs); + INIT(GetGlyphVectorRecordSize); + INIT(GetMIMETypeForExtension); + INIT(GetNSFontATSUFontId); + INIT(GetNSURLResponseLastModifiedDate); + INIT(GetPreferredExtensionForMIMEType); + INIT(GetWheelEventDeltas); + INIT(InitializeGlyphVector); + INIT(PopupMenu); + INIT(ReleaseStyleGroup); + 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); + +#ifdef BUILDING_ON_TIGER + INIT(GetFontMetrics); + 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..c524b4b --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebViewFactory.mm @@ -0,0 +1,487 @@ +/* + * 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 <JavaScriptCore/Assertions.h> +#import <WebKit/WebFrameBridge.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> + +@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]; +} + +- (NSString *)pluginNameForMIMEType:(NSString *)MIMEType +{ + return [[[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType] name]; +} + +- (void)refreshPlugins:(BOOL)reloadPages +{ + [[WebPluginDatabase sharedDatabase] refresh]; + if (reloadPages) { + [WebView _makeAllWebViewsPerformSelector:@selector(_reloadForPluginChanges)]; + } +} + +- (BOOL)pluginSupportsMIMEType:(NSString *)MIMEType +{ + return [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType] != nil; +} + +- (WebCoreFrameBridge *)bridgeForView:(NSView *)v +{ + NSView *aView = [v superview]; + + while (aView) { + if ([aView isKindOfClass:[WebHTMLView class]]) { + return [[[(WebHTMLView *)aView _frame] _dataSource] _bridge]; + } + aView = [aView superview]; + } + return nil; +} + +- (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("web area", "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 *)unknownFileSizeText +{ + return UI_STRING("Unknown", "Unknown filesize FTP directory listing item"); +} + +- (NSString*)imageTitleForFilename:(NSString*)filename size:(NSSize)size +{ + return [NSString stringWithFormat:UI_STRING("%@ %.0f×%.0f pixels", "window title for a standalone image (uses multiplication symbol, not x)"), filename, size.width, size.height]; +} + +@end |