webengine/osswebengine/WebKit/WebView/WebView.mm
changeset 0 dd21522fd290
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebKit/WebView/WebView.mm	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,4576 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
+ *
+ * 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 "WebViewInternal.h"
+
+#import "DOMRangeInternal.h"
+#import "WebBackForwardList.h"
+#import "WebBackForwardListInternal.h"
+#import "WebBaseNetscapePluginView.h"
+#import "WebChromeClient.h"
+#import "WebContextMenuClient.h"
+#import "WebDOMOperationsPrivate.h"
+#import "WebDashboardRegion.h"
+#import "WebDataSourceInternal.h"
+#import "WebDefaultEditingDelegate.h"
+#import "WebDefaultPolicyDelegate.h"
+#import "WebDefaultScriptDebugDelegate.h"
+#import "WebDefaultUIDelegate.h"
+#import "WebDocument.h"
+#import "WebDocumentInternal.h"
+#import "WebDownload.h"
+#import "WebDownloadInternal.h"
+#import "WebDragClient.h"
+#import "WebDynamicScrollBarsView.h"
+#import "WebEditingDelegate.h"
+#import "WebEditorClient.h"
+#import "WebFormDelegatePrivate.h"
+#import "WebFrameBridge.h"
+#import "WebFrameInternal.h"
+#import "WebFrameViewInternal.h"
+#import "WebHTMLRepresentation.h"
+#import "WebHTMLViewInternal.h"
+#import "WebHistoryItemInternal.h"
+#import "WebIconDatabase.h"
+#import "WebIconDatabaseInternal.h"
+#import "WebInspectorClient.h"
+#import "WebKitErrors.h"
+#import "WebKitLogging.h"
+#import "WebKitNSStringExtras.h"
+#import "WebKitStatisticsPrivate.h"
+#import "WebKitSystemBits.h"
+#import "WebKitVersionChecks.h"
+#import "WebLocalizableStrings.h"
+#import "WebNSDataExtras.h"
+#import "WebNSDataExtrasPrivate.h"
+#import "WebNSDictionaryExtras.h"
+#import "WebNSEventExtras.h"
+#import "WebNSObjectExtras.h"
+#import "WebNSPasteboardExtras.h"
+#import "WebNSPrintOperationExtras.h"
+#import "WebNSURLExtras.h"
+#import "WebNSURLRequestExtras.h"
+#import "WebNSUserDefaultsExtras.h"
+#import "WebNSViewExtras.h"
+#import "WebPanelAuthenticationHandler.h"
+#import "WebPasteboardHelper.h"
+#import "WebPDFView.h"
+#import "WebPluginDatabase.h"
+#import "WebPolicyDelegate.h"
+#import "WebPreferenceKeysPrivate.h"
+#import "WebPreferencesPrivate.h"
+#import "WebScriptDebugDelegatePrivate.h"
+#import "WebScriptDebugServerPrivate.h"
+#import "WebUIDelegate.h"
+#import "WebUIDelegatePrivate.h"
+#import <CoreFoundation/CFSet.h>
+#import <Foundation/NSURLConnection.h>
+#import <JavaScriptCore/Assertions.h>
+#import <WebCore/Cache.h>
+#import <WebCore/ColorMac.h>
+#import <WebCore/Document.h>
+#import <WebCore/DocumentLoader.h>
+#import <WebCore/DragController.h>
+#import <WebCore/DragData.h>
+#import <WebCore/Editor.h>
+#import <WebCore/ExceptionHandlers.h>
+#import <WebCore/Frame.h>
+#import <WebCore/FrameLoader.h>
+#import <WebCore/FrameTree.h>
+#import <WebCore/HTMLNames.h>
+#import <WebCore/HistoryItem.h>
+#import <WebCore/Logging.h>
+#import <WebCore/MIMETypeRegistry.h>
+#import <WebCore/Page.h>
+#import <WebCore/PageCache.h>
+#import <WebCore/PlatformMouseEvent.h>
+#import <WebCore/ProgressTracker.h>
+#import <WebCore/SelectionController.h>
+#import <WebCore/Settings.h>
+#import <WebCore/TextResourceDecoder.h>
+#import <WebCore/WebCoreFrameBridge.h>
+#import <WebCore/WebCoreObjCExtras.h>
+#import <WebCore/WebCoreTextRenderer.h>
+#import <WebCore/WebCoreView.h>
+#import <WebKit/DOM.h>
+#import <WebKit/DOMExtensions.h>
+#import <WebKit/DOMPrivate.h>
+#import <WebKitSystemInterface.h>
+#import <mach-o/dyld.h>
+#import <objc/objc-runtime.h>
+#import <wtf/RefPtr.h>
+#import <wtf/HashTraits.h>
+
+using namespace WebCore;
+
+#if defined(__ppc__) || defined(__ppc64__)
+#define PROCESSOR "PPC"
+#elif defined(__i386__) || defined(__x86_64__)
+#define PROCESSOR "Intel"
+#else
+#error Unknown architecture
+#endif
+
+#define FOR_EACH_RESPONDER_SELECTOR(macro) \
+macro(alignCenter) \
+macro(alignJustified) \
+macro(alignLeft) \
+macro(alignRight) \
+macro(capitalizeWord) \
+macro(centerSelectionInVisibleArea) \
+macro(changeAttributes) \
+macro(changeColor) \
+macro(changeDocumentBackgroundColor) \
+macro(changeFont) \
+macro(checkSpelling) \
+macro(complete) \
+macro(copy) \
+macro(copyFont) \
+macro(cut) \
+macro(delete) \
+macro(deleteBackward) \
+macro(deleteBackwardByDecomposingPreviousCharacter) \
+macro(deleteForward) \
+macro(deleteToBeginningOfLine) \
+macro(deleteToBeginningOfParagraph) \
+macro(deleteToEndOfLine) \
+macro(deleteToEndOfParagraph) \
+macro(deleteWordBackward) \
+macro(deleteWordForward) \
+macro(ignoreSpelling) \
+macro(indent) \
+macro(insertBacktab) \
+macro(insertNewline) \
+macro(insertNewlineIgnoringFieldEditor) \
+macro(insertParagraphSeparator) \
+macro(insertTab) \
+macro(insertTabIgnoringFieldEditor) \
+macro(lowercaseWord) \
+macro(moveBackward) \
+macro(moveBackwardAndModifySelection) \
+macro(moveDown) \
+macro(moveDownAndModifySelection) \
+macro(moveForward) \
+macro(moveForwardAndModifySelection) \
+macro(moveLeft) \
+macro(moveLeftAndModifySelection) \
+macro(moveRight) \
+macro(moveRightAndModifySelection) \
+macro(moveToBeginningOfDocument) \
+macro(moveToBeginningOfDocumentAndModifySelection) \
+macro(moveToBeginningOfSentence) \
+macro(moveToBeginningOfSentenceAndModifySelection) \
+macro(moveToBeginningOfLine) \
+macro(moveToBeginningOfLineAndModifySelection) \
+macro(moveToBeginningOfParagraph) \
+macro(moveToBeginningOfParagraphAndModifySelection) \
+macro(moveToEndOfDocument) \
+macro(moveToEndOfDocumentAndModifySelection) \
+macro(moveToEndOfLine) \
+macro(moveToEndOfLineAndModifySelection) \
+macro(moveToEndOfParagraph) \
+macro(moveToEndOfParagraphAndModifySelection) \
+macro(moveToEndOfSentence) \
+macro(moveToEndOfSentenceAndModifySelection) \
+macro(moveUp) \
+macro(moveUpAndModifySelection) \
+macro(moveWordBackward) \
+macro(moveWordBackwardAndModifySelection) \
+macro(moveWordForward) \
+macro(moveWordForwardAndModifySelection) \
+macro(moveWordLeft) \
+macro(moveWordLeftAndModifySelection) \
+macro(moveWordRight) \
+macro(moveWordRightAndModifySelection) \
+macro(outdent) \
+macro(pageDown) \
+macro(pageUp) \
+macro(paste) \
+macro(pasteAsPlainText) \
+macro(pasteAsRichText) \
+macro(pasteFont) \
+macro(performFindPanelAction) \
+macro(scrollLineDown) \
+macro(scrollLineUp) \
+macro(scrollPageDown) \
+macro(scrollPageUp) \
+macro(scrollToBeginningOfDocument) \
+macro(scrollToEndOfDocument) \
+macro(selectAll) \
+macro(selectWord) \
+macro(selectSentence) \
+macro(selectLine) \
+macro(selectParagraph) \
+macro(showGuessPanel) \
+macro(startSpeaking) \
+macro(stopSpeaking) \
+macro(subscript) \
+macro(superscript) \
+macro(underline) \
+macro(unscript) \
+macro(uppercaseWord) \
+macro(yank) \
+macro(yankAndSelect) \
+
+#define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
+#define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
+
+static BOOL s_didSetCacheModel;
+static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
+
+static BOOL applicationIsTerminating;
+static int pluginDatabaseClientCount = 0;
+
+@interface NSSpellChecker (AppKitSecretsIKnow)
+- (void)_preflightChosenSpellServer;
+@end
+
+@interface NSView (AppKitSecretsIKnow)
+- (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
+- (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
+- (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
+@end
+
+@interface NSWindow (AppKitSecretsIKnow) 
+- (id)_oldFirstResponderBeforeBecoming;
+@end
+
+@interface NSObject (ValidateWithoutDelegate)
+- (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
+@end
+
+@interface _WebSafeForwarder : NSObject
+{
+    id target; // Non-retained. Don't retain delegates.
+    id defaultTarget;
+    BOOL catchExceptions;
+}
+- (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions;
+@end
+
+@interface WebViewPrivate : NSObject
+{
+@public
+    Page* page;
+    
+    id UIDelegate;
+    id UIDelegateForwarder;
+    id resourceProgressDelegate;
+    id downloadDelegate;
+    id policyDelegate;
+    id policyDelegateForwarder;
+    id frameLoadDelegate;
+    id frameLoadDelegateForwarder;
+    id <WebFormDelegate> formDelegate;
+    id editingDelegate;
+    id editingDelegateForwarder;
+    id scriptDebugDelegate;
+    id scriptDebugDelegateForwarder;
+
+    BOOL allowsUndo;
+        
+    float textSizeMultiplier;
+
+    NSString *applicationNameForUserAgent;
+    String* userAgent;
+    BOOL userAgentOverridden;
+    
+    WebPreferences *preferences;
+    BOOL useSiteSpecificSpoofing;
+
+    NSWindow *hostWindow;
+
+    int programmaticFocusCount;
+    
+    WebResourceDelegateImplementationCache resourceLoadDelegateImplementations;
+    WebFrameLoadDelegateImplementationCache frameLoadDelegateImplementations;
+
+    void *observationInfo;
+    
+    BOOL closed;
+    BOOL shouldCloseWithWindow;
+    BOOL mainFrameDocumentReady;
+    BOOL drawsBackground;
+    BOOL editable;
+    BOOL tabKeyCyclesThroughElementsChanged;
+    BOOL becomingFirstResponder;
+    BOOL becomingFirstResponderFromOutside;
+    BOOL hoverFeedbackSuspended;
+    BOOL usesPageCache;
+    BOOL catchesDelegateExceptions;
+
+    NSColor *backgroundColor;
+
+    NSString *mediaStyle;
+    
+    BOOL hasSpellCheckerDocumentTag;
+    NSInteger spellCheckerDocumentTag;
+
+    BOOL smartInsertDeleteEnabled;
+        
+    BOOL dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
+    BOOL dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
+    BOOL dashboardBehaviorAlwaysAcceptsFirstMouse;
+    BOOL dashboardBehaviorAllowWheelScrolling;
+    
+    // WebKit has both a global plug-in database and a separate, per WebView plug-in database. Dashboard uses the per WebView database.
+    WebPluginDatabase *pluginDatabase;
+    
+    HashMap<unsigned long, RetainPtr<id> >* identifierMap;
+}
+@end
+
+@interface WebView (WebFileInternal)
++ (void)_setCacheModel:(WebCacheModel)cacheModel;
++ (WebCacheModel)_cacheModel;
+- (WebFrame *)_selectedOrMainFrame;
+- (WebFrameBridge *)_bridgeForSelectedOrMainFrame;
+- (BOOL)_isLoading;
+- (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
+- (WebFrame *)_focusedFrame;
++ (void)_preflightSpellChecker;
+- (BOOL)_continuousCheckingAllowed;
+- (NSResponder *)_responderForResponderOperations;
+- (BOOL)_performTextSizingSelector:(SEL)sel withObject:(id)arg onTrackingDocs:(BOOL)doTrackingViews selForNonTrackingDocs:(SEL)testSel newScaleFactor:(float)newScaleFactor;
+- (void)_notifyTextSizeMultiplierChanged;
+@end
+
+@interface WebView (WebCallDelegateFunctions)
+@end
+
+NSString *WebElementDOMNodeKey =            @"WebElementDOMNode";
+NSString *WebElementFrameKey =              @"WebElementFrame";
+NSString *WebElementImageKey =              @"WebElementImage";
+NSString *WebElementImageAltStringKey =     @"WebElementImageAltString";
+NSString *WebElementImageRectKey =          @"WebElementImageRect";
+NSString *WebElementImageURLKey =           @"WebElementImageURL";
+NSString *WebElementIsSelectedKey =         @"WebElementIsSelected";
+NSString *WebElementLinkLabelKey =          @"WebElementLinkLabel";
+NSString *WebElementLinkTargetFrameKey =    @"WebElementTargetFrame";
+NSString *WebElementLinkTitleKey =          @"WebElementLinkTitle";
+NSString *WebElementLinkURLKey =            @"WebElementLinkURL";
+NSString *WebElementSpellingToolTipKey =    @"WebElementSpellingToolTip";
+NSString *WebElementTitleKey =              @"WebElementTitle";
+NSString *WebElementLinkIsLiveKey =         @"WebElementLinkIsLive";
+NSString *WebElementIsContentEditableKey =  @"WebElementIsContentEditableKey";
+
+NSString *WebViewProgressStartedNotification =          @"WebProgressStartedNotification";
+NSString *WebViewProgressEstimateChangedNotification =  @"WebProgressEstimateChangedNotification";
+NSString *WebViewProgressFinishedNotification =         @"WebProgressFinishedNotification";
+
+NSString * const WebViewDidBeginEditingNotification =         @"WebViewDidBeginEditingNotification";
+NSString * const WebViewDidChangeNotification =               @"WebViewDidChangeNotification";
+NSString * const WebViewDidEndEditingNotification =           @"WebViewDidEndEditingNotification";
+NSString * const WebViewDidChangeTypingStyleNotification =    @"WebViewDidChangeTypingStyleNotification";
+NSString * const WebViewDidChangeSelectionNotification =      @"WebViewDidChangeSelectionNotification";
+
+enum { WebViewVersion = 4 };
+
+#define timedLayoutSize 4096
+
+static NSMutableSet *schemesWithRepresentationsSet;
+
+NSString *_WebCanGoBackKey =            @"canGoBack";
+NSString *_WebCanGoForwardKey =         @"canGoForward";
+NSString *_WebEstimatedProgressKey =    @"estimatedProgress";
+NSString *_WebIsLoadingKey =            @"isLoading";
+NSString *_WebMainFrameIconKey =        @"mainFrameIcon";
+NSString *_WebMainFrameTitleKey =       @"mainFrameTitle";
+NSString *_WebMainFrameURLKey =         @"mainFrameURL";
+NSString *_WebMainFrameDocumentKey =    @"mainFrameDocument";
+
+@interface WebProgressItem : NSObject
+{
+@public
+    long long bytesReceived;
+    long long estimatedLength;
+}
+@end
+
+@implementation WebProgressItem
+@end
+
+static BOOL continuousSpellCheckingEnabled;
+#ifndef BUILDING_ON_TIGER
+static BOOL grammarCheckingEnabled;
+#endif
+
+@implementation WebViewPrivate
+
+#ifndef BUILDING_ON_TIGER
++ (void)initialize
+{
+    WebCoreObjCFinalizeOnMainThread(self);
+}
+#endif
+
+- init 
+{
+    self = [super init];
+    if (!self)
+        return nil;
+    allowsUndo = YES;
+    textSizeMultiplier = 1;
+    dashboardBehaviorAllowWheelScrolling = YES;
+    shouldCloseWithWindow = objc_collecting_enabled();
+    continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
+
+#ifndef BUILDING_ON_TIGER
+    grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
+#endif
+    userAgent = new String;
+    
+    usesPageCache = YES;
+    
+    identifierMap = new HashMap<unsigned long, RetainPtr<id> >();
+    pluginDatabaseClientCount++;
+
+    return self;
+}
+
+- (void)dealloc
+{
+    ASSERT(!page);
+    ASSERT(!preferences);
+
+    delete userAgent;
+    delete identifierMap;
+    
+    [applicationNameForUserAgent release];
+    [backgroundColor release];
+    
+    [hostWindow release];
+
+    [policyDelegateForwarder release];
+    [UIDelegateForwarder release];
+    [frameLoadDelegateForwarder release];
+    [editingDelegateForwarder release];
+    [scriptDebugDelegateForwarder release];
+    
+    [mediaStyle release];
+    
+    [super dealloc];
+}
+
+- (void)finalize
+{
+    ASSERT_MAIN_THREAD();
+
+    delete userAgent;
+    delete identifierMap;
+
+    [super finalize];
+}
+
+@end
+
+@implementation WebView (AllWebViews)
+
+static CFSetCallBacks NonRetainingSetCallbacks = {
+    0,
+    NULL,
+    NULL,
+    CFCopyDescription,
+    CFEqual,
+    CFHash
+};
+
+static CFMutableSetRef allWebViewsSet;
+
++ (void)_makeAllWebViewsPerformSelector:(SEL)selector
+{
+    if (!allWebViewsSet)
+        return;
+
+    [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
+}
+
+- (void)_removeFromAllWebViewsSet
+{
+    if (allWebViewsSet)
+        CFSetRemoveValue(allWebViewsSet, self);
+}
+
+- (void)_addToAllWebViewsSet
+{
+    if (!allWebViewsSet)
+        allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
+
+    CFSetSetValue(allWebViewsSet, self);
+}
+
+@end
+
+@implementation WebView (WebPrivate)
+
+#ifdef DEBUG_WIDGET_DRAWING
+static bool debugWidget = true;
+- (void)drawRect:(NSRect)rect
+{
+    [[NSColor blueColor] set];
+    NSRectFill (rect);
+    
+    NSRect htmlViewRect = [[[[self mainFrame] frameView] documentView] frame];
+
+    if (debugWidget) {
+        while (debugWidget) {
+            sleep (1);
+        }
+    }
+
+    NSLog (@"%s:   rect:  (%0.f,%0.f) %0.f %0.f, htmlViewRect:  (%0.f,%0.f) %0.f %0.f\n", 
+        __PRETTY_FUNCTION__, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height,
+        htmlViewRect.origin.x, htmlViewRect.origin.y, htmlViewRect.size.width, htmlViewRect.size.height
+    );
+
+    [super drawRect:rect];
+}
+#endif
+
++ (BOOL)_developerExtrasEnabled
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    if ([defaults boolForKey:@"DisableWebKitDeveloperExtras"])
+        return NO;
+#ifdef NDEBUG
+    BOOL enableDebugger = [defaults boolForKey:@"WebKitDeveloperExtras"];
+    if (!enableDebugger)
+        enableDebugger = [defaults boolForKey:@"IncludeDebugMenu"];
+    return enableDebugger;
+#else
+    return YES; // always enable in debug builds
+#endif
+}
+
++ (BOOL)_scriptDebuggerEnabled
+{
+#ifdef NDEBUG
+    return [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitScriptDebuggerEnabled"];
+#else
+    return YES; // always enable in debug builds
+#endif
+}
+
++ (NSArray *)_supportedMIMETypes
+{
+    // Load the plug-in DB allowing plug-ins to install types.
+    [WebPluginDatabase sharedDatabase];
+    return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
+}
+
++ (NSArray *)_supportedFileExtensions
+{
+    NSMutableSet *extensions = [[NSMutableSet alloc] init];
+    NSArray *MIMETypes = [self _supportedMIMETypes];
+    NSEnumerator *enumerator = [MIMETypes objectEnumerator];
+    NSString *MIMEType;
+    while ((MIMEType = [enumerator nextObject]) != nil) {
+        NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
+        if (extensionsForType) {
+            [extensions addObjectsFromArray:extensionsForType];
+        }
+    }
+    NSArray *uniqueExtensions = [extensions allObjects];
+    [extensions release];
+    return uniqueExtensions;
+}
+
++ (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType;
+{
+    MIMEType = [MIMEType lowercaseString];
+    Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
+    Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
+    
+    if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
+        // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
+        // Load the plug-in DB allowing plug-ins to install types.
+        [WebPluginDatabase sharedDatabase];
+            
+        // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
+        viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
+        repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
+    }
+    
+    if (viewClass && repClass) {
+        // Special-case WebHTMLView for text types that shouldn't be shown.
+        if (viewClass == [WebHTMLView class] &&
+            repClass == [WebHTMLRepresentation class] &&
+            [[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) {
+            return NO;
+        }
+        if (vClass)
+            *vClass = viewClass;
+        if (rClass)
+            *rClass = repClass;
+        return YES;
+    }
+    
+    return NO;
+}
+
+- (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType;
+{
+    if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType])
+        return YES;
+
+    if (_private->pluginDatabase) {
+        WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
+        if (pluginPackage) {
+            if (vClass)
+                *vClass = [WebHTMLView class];
+            if (rClass)
+                *rClass = [WebHTMLRepresentation class];
+            return YES;
+        }
+    }
+    
+    return NO;
+}
+
++ (void)_setAlwaysUseATSU:(BOOL)f
+{
+    WebCoreSetAlwaysUseATSU(f);
+}
+
++ (BOOL)canShowFile:(NSString *)path
+{
+    return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
+}
+
++ (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
+{
+    return WKGetPreferredExtensionForMIMEType(type);
+}
+
+- (BOOL)_isClosed
+{
+    if (!_private || _private->closed)
+        return YES;
+    return NO;
+}
+
+- (void)_close
+{
+    if (!_private || _private->closed)
+        return;
+
+    FrameLoader* mainFrameLoader = [[self mainFrame] _frameLoader];
+    if (mainFrameLoader)
+        mainFrameLoader->detachFromParent();
+
+    [self _removeFromAllWebViewsSet];
+    [self setGroupName:nil];
+    [self setHostWindow:nil];
+
+    [self setDownloadDelegate:nil];
+    [self setEditingDelegate:nil];
+    [self setFrameLoadDelegate:nil];
+    [self setPolicyDelegate:nil];
+    [self setResourceLoadDelegate:nil];
+    [self setScriptDebugDelegate:nil];
+    [self setUIDelegate:nil];
+    
+    // setHostWindow:nil must be called before this value is set (see 5408186)
+    _private->closed = YES;
+
+    // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
+    [self removeDragCaret];
+
+    // Deleteing the WebCore::Page will clear the page cache so we call destroy on 
+    // all the plug-ins in the page cache to break any retain cycles.
+    // See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
+    delete _private->page;
+    _private->page = 0;
+
+    if (_private->hasSpellCheckerDocumentTag) {
+        [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
+        _private->hasSpellCheckerDocumentTag = NO;
+    }
+    
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+    [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
+
+    WebPreferences *preferences = _private->preferences;
+    _private->preferences = nil;
+    [preferences didRemoveFromWebView];
+    [preferences release];
+
+    pluginDatabaseClientCount--;
+    
+    // Make sure to close both sets of plug-ins databases because plug-ins need an opportunity to clean up files, etc.
+    
+    // Unload the WebView local plug-in database. 
+    if (_private->pluginDatabase) {
+        [_private->pluginDatabase close];
+        [_private->pluginDatabase release];
+        _private->pluginDatabase = nil;
+    }
+    
+    // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
+    if (!pluginDatabaseClientCount && applicationIsTerminating)
+        [WebPluginDatabase closeSharedDatabase];
+}
+
++ (NSString *)_MIMETypeForFile:(NSString *)path
+{
+    NSString *extension = [path pathExtension];
+    NSString *MIMEType = nil;
+
+    // Get the MIME type from the extension.
+    if ([extension length] != 0) {
+        MIMEType = WKGetMIMETypeForExtension(extension);
+    }
+
+    // If we can't get a known MIME type from the extension, sniff.
+    if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
+        NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
+        NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
+        [handle closeFile];
+        if ([data length] != 0) {
+            MIMEType = [data _webkit_guessedMIMEType];
+        }
+        if ([MIMEType length] == 0) {
+            MIMEType = @"application/octet-stream";
+        }
+    }
+
+    return MIMEType;
+}
+
+- (WebDownload *)_downloadURL:(NSURL *)URL
+{
+    ASSERT(URL);
+    
+    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
+    WebDownload *download = [WebDownload _downloadWithRequest:request
+                                                     delegate:_private->downloadDelegate
+                                                    directory:nil];
+    [request release];
+    
+    return download;
+}
+
+- (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
+{
+    WebView *newWindowWebView = CallUIDelegate(self, @selector(webView:createWebViewWithRequest:), request);
+    if (!newWindowWebView)
+        return nil;
+
+    CallUIDelegate(newWindowWebView, @selector(webViewShow:));
+    return newWindowWebView;
+}
+
+- (WebCore::Page*)page
+{
+    return _private->page;
+}
+
+- (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
+{
+    NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
+
+    NSArray *menuItems = CallUIDelegate(self, @selector(webView:contextMenuItemsForElement:defaultMenuItems:), element, defaultMenuItems);
+    if (!menuItems)
+        return nil;
+
+    unsigned count = [menuItems count];
+    if (!count)
+        return nil;
+
+    NSMenu *menu = [[NSMenu alloc] init];
+    for (unsigned i = 0; i < count; i++)
+        [menu addItem:[menuItems objectAtIndex:i]];
+
+    return [menu autorelease];
+}
+
+- (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
+{
+    // We originally intended to call this delegate method sometimes with a nil dictionary, but due to
+    // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
+    // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
+    if (!dictionary)
+        return;
+    CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
+}
+
+- (void)_loadBackForwardListFromOtherView:(WebView *)otherView
+{
+    if (!_private->page)
+        return;
+    
+    if (!otherView->_private->page)
+        return;
+    
+    // It turns out the right combination of behavior is done with the back/forward load
+    // type.  (See behavior matrix at the top of WebFramePrivate.)  So we copy all the items
+    // in the back forward list, and go to the current one.
+
+    BackForwardList* backForwardList = _private->page->backForwardList();
+    ASSERT(!backForwardList->currentItem()); // destination list should be empty
+
+    BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList();
+    if (!otherBackForwardList->currentItem())
+        return; // empty back forward list, bail
+    
+    HistoryItem* newItemToGoTo = 0;
+
+    int lastItemIndex = otherBackForwardList->forwardListCount();
+    for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
+        if (i == 0) {
+            // If this item is showing , save away its current scroll and form state,
+            // since that might have changed since loading and it is normally not saved
+            // until we leave that page.
+            otherView->_private->page->mainFrame()->loader()->saveDocumentAndScrollState();
+        }
+        RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
+        if (i == 0) 
+            newItemToGoTo = newItem.get();
+        backForwardList->addItem(newItem.release());
+    }
+    
+    ASSERT(newItemToGoTo);
+    _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
+}
+
+- (void)_setFormDelegate: (id<WebFormDelegate>)delegate
+{
+    _private->formDelegate = delegate;
+}
+
+- (id<WebFormDelegate>)_formDelegate
+{
+    return _private->formDelegate;
+}
+
+- (BOOL)_needsAdobeFrameReloadingQuirk
+{
+    static BOOL checked = NO;
+    static BOOL needsQuirk = NO;
+
+    if (checked)
+        return needsQuirk;
+
+    needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
+        || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
+        || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
+        || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
+        || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
+        || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
+        || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
+        || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
+        || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
+        || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
+
+    return needsQuirk;
+}
+
+- (void)_preferencesChangedNotification:(NSNotification *)notification
+{
+    WebPreferences *preferences = (WebPreferences *)[notification object];
+    ASSERT(preferences == [self preferences]);
+
+    if (!_private->userAgentOverridden)
+        *_private->userAgent = String();
+
+    // Cache this value so we don't have to read NSUserDefaults on each page load
+    _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
+
+    // Update corresponding WebCore Settings object.
+    if (!_private->page)
+        return;
+    
+    Settings* settings = _private->page->settings();
+    
+    settings->setCursiveFontFamily([preferences cursiveFontFamily]);
+    settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]);
+    settings->setDefaultFontSize([preferences defaultFontSize]);
+    settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]);
+    settings->setFantasyFontFamily([preferences fantasyFontFamily]);
+    settings->setFixedFontFamily([preferences fixedFontFamily]);
+    settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
+    settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
+    settings->setJavaEnabled([preferences isJavaEnabled]);
+    settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]);
+    settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
+    settings->setMinimumFontSize([preferences minimumFontSize]);
+    settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
+    settings->setPluginsEnabled([preferences arePlugInsEnabled]);
+    settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]);
+    settings->setSansSerifFontFamily([preferences sansSerifFontFamily]);
+    settings->setSerifFontFamily([preferences serifFontFamily]);
+    settings->setStandardFontFamily([preferences standardFontFamily]);
+    settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
+    settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
+    settings->setTextAreasAreResizable([preferences textAreasAreResizable]);
+    settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
+    settings->setEditableLinkBehavior(core([preferences editableLinkBehavior]));
+    settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]);
+    settings->setUsesPageCache([self usesPageCache]);
+    settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]);
+    settings->setDeveloperExtrasEnabled([WebView _developerExtrasEnabled]);
+    if ([preferences userStyleSheetEnabled]) {
+        NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
+        settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
+    } else
+        settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
+    settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
+}
+
+static inline IMP getMethod(id o, SEL s)
+{
+    return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
+}
+
+- (void)_cacheResourceLoadDelegateImplementations
+{
+    WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
+    id delegate = _private->resourceProgressDelegate;
+
+    cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
+    cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
+    cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
+    cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
+    cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
+    cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
+    cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
+    cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
+    cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
+    cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
+    cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
+}
+
+WebResourceDelegateImplementationCache WebViewGetResourceLoadDelegateImplementations(WebView *webView)
+{
+    return webView->_private->resourceLoadDelegateImplementations;
+}
+
+- (void)_cacheFrameLoadDelegateImplementations
+{
+    WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
+    id delegate = _private->frameLoadDelegate;
+
+    cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
+    cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
+    cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
+    cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
+    cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
+    cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
+    cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
+    cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
+    cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
+    cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
+    cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
+    cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
+    cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
+    cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
+    cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
+    cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
+    cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
+}
+
+WebFrameLoadDelegateImplementationCache WebViewGetFrameLoadDelegateImplementations(WebView *webView)
+{
+    return webView->_private->frameLoadDelegateImplementations;
+}
+
+- (id)_policyDelegateForwarder
+{
+    if (!_private->policyDelegateForwarder)
+        _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions];
+    return _private->policyDelegateForwarder;
+}
+
+- (id)_UIDelegateForwarder
+{
+    if (!_private->UIDelegateForwarder)
+        _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions];
+    return _private->UIDelegateForwarder;
+}
+
+- (id)_editingDelegateForwarder
+{
+    // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
+    // Not sure if that is a bug or not.
+    if (!_private)
+        return nil;
+
+    if (!_private->editingDelegateForwarder)
+        _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions];
+    return _private->editingDelegateForwarder;
+}
+
+- (id)_scriptDebugDelegateForwarder
+{
+    if (!_private->scriptDebugDelegateForwarder)
+        _private->scriptDebugDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->scriptDebugDelegate defaultTarget:[WebDefaultScriptDebugDelegate sharedScriptDebugDelegate] catchExceptions:_private->catchesDelegateExceptions];
+    return _private->scriptDebugDelegateForwarder;
+}
+
+- (void)_closeWindow
+{
+    [[self _UIDelegateForwarder] webViewClose:self];
+}
+
++ (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType;
+{
+    [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
+    [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
+    
+    // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
+    // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
+    // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
+    MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
+}
+
++ (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme;
+{
+    NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
+    [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
+
+    // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
+    // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
+    // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
+    if ([viewClass class] == [WebHTMLView class])
+        MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
+    
+    // This is used to make _representationExistsForURLScheme faster.
+    // Without this set, we'd have to create the MIME type each time.
+    if (schemesWithRepresentationsSet == nil) {
+        schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
+    }
+    [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
+}
+
++ (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
+{
+    return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
+}
+
++ (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
+{
+    return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
+}
+
++ (BOOL)_canHandleRequest:(NSURLRequest *)request
+{
+    // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed
+    if (!request)
+        return NO;
+
+    if ([NSURLConnection canHandleRequest:request])
+        return YES;
+
+    NSString *scheme = [[request URL] scheme];
+
+    if ([self _representationExistsForURLScheme:scheme])
+        return YES;
+        
+    return ([scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"]);
+}
+
++ (NSString *)_decodeData:(NSData *)data
+{
+    HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
+    RefPtr<TextResourceDecoder> decoder = new TextResourceDecoder("text/html"); // bookmark files are HTML
+    String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
+    result += decoder->flush();
+    return result;
+}
+
+- (void)_pushPerformingProgrammaticFocus
+{
+    _private->programmaticFocusCount++;
+}
+
+- (void)_popPerformingProgrammaticFocus
+{
+    _private->programmaticFocusCount--;
+}
+
+- (BOOL)_isPerformingProgrammaticFocus
+{
+    return _private->programmaticFocusCount != 0;
+}
+
+- (void)_didChangeValueForKey: (NSString *)key
+{
+    LOG (Bindings, "calling didChangeValueForKey: %@", key);
+    [self didChangeValueForKey: key];
+}
+
+- (void)_willChangeValueForKey: (NSString *)key
+{
+    LOG (Bindings, "calling willChangeValueForKey: %@", key);
+    [self willChangeValueForKey: key];
+}
+
++ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
+    static NSSet *manualNotifyKeys = nil;
+    if (!manualNotifyKeys)
+        manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
+            _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
+    if ([manualNotifyKeys containsObject:key])
+        return NO;
+    return YES;
+}
+
+- (NSArray *)_declaredKeys {
+    static NSArray *declaredKeys = nil;
+    if (!declaredKeys)
+        declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
+            _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
+    return declaredKeys;
+}
+
+- (void)setObservationInfo:(void *)info
+{
+    _private->observationInfo = info;
+}
+
+- (void *)observationInfo
+{
+    return _private->observationInfo;
+}
+
+- (void)_willChangeBackForwardKeys
+{
+    [self _willChangeValueForKey: _WebCanGoBackKey];
+    [self _willChangeValueForKey: _WebCanGoForwardKey];
+}
+
+- (void)_didChangeBackForwardKeys
+{
+    [self _didChangeValueForKey: _WebCanGoBackKey];
+    [self _didChangeValueForKey: _WebCanGoForwardKey];
+}
+
+- (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
+{
+    [self _willChangeBackForwardKeys];
+    if (frame == [self mainFrame]){
+        // Force an observer update by sending a will/did.
+        [self _willChangeValueForKey: _WebIsLoadingKey];
+        [self _didChangeValueForKey: _WebIsLoadingKey];
+
+        [self _willChangeValueForKey: _WebMainFrameURLKey];
+    }
+
+    [NSApp setWindowsNeedUpdate:YES];
+}
+
+- (void)_didCommitLoadForFrame:(WebFrame *)frame
+{
+    if (frame == [self mainFrame])
+        [self _didChangeValueForKey: _WebMainFrameURLKey];
+    [NSApp setWindowsNeedUpdate:YES];
+}
+
+- (void)_didFinishLoadForFrame:(WebFrame *)frame
+{
+    [self _didChangeBackForwardKeys];
+    if (frame == [self mainFrame]){
+        // Force an observer update by sending a will/did.
+        [self _willChangeValueForKey: _WebIsLoadingKey];
+        [self _didChangeValueForKey: _WebIsLoadingKey];
+    }
+    [NSApp setWindowsNeedUpdate:YES];
+}
+
+- (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
+{
+    [self _didChangeBackForwardKeys];
+    if (frame == [self mainFrame]){
+        // Force an observer update by sending a will/did.
+        [self _willChangeValueForKey: _WebIsLoadingKey];
+        [self _didChangeValueForKey: _WebIsLoadingKey];
+    }
+    [NSApp setWindowsNeedUpdate:YES];
+}
+
+- (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
+{
+    [self _didChangeBackForwardKeys];
+    if (frame == [self mainFrame]){
+        // Force an observer update by sending a will/did.
+        [self _willChangeValueForKey: _WebIsLoadingKey];
+        [self _didChangeValueForKey: _WebIsLoadingKey];
+        
+        [self _didChangeValueForKey: _WebMainFrameURLKey];
+    }
+    [NSApp setWindowsNeedUpdate:YES];
+}
+
+- (void)_reloadForPluginChanges
+{
+    [[self mainFrame] _reloadForPluginChanges];
+}
+
+- (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
+{
+    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
+    [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
+    NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
+    [request release];
+    return cachedResponse;
+}
+
+- (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
+{
+    NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
+    DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
+    [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
+                        element:domElement
+                            URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
+                          title:[element objectForKey:WebElementImageAltStringKey] 
+                        archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
+                          types:types
+                         source:nil];
+}
+
+- (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
+{
+    [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
+                     andTitle:[element objectForKey:WebElementLinkLabelKey]
+                        types:types];
+}
+
+- (void)_setInitiatedDrag:(BOOL)initiatedDrag
+{
+    if (!_private->page)
+        return;
+    _private->page->dragController()->setDidInitiateDrag(initiatedDrag);
+}
+
+#define DASHBOARD_CONTROL_LABEL @"control"
+
+- (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
+{
+    // Add scroller regions for NSScroller and KWQScrollBar
+    int i, count = [views count];
+    
+    for (i = 0; i < count; i++) {
+        NSView *aView = [views objectAtIndex:i];
+        
+        if ([aView isKindOfClass:[NSScroller class]] ||
+            [aView isKindOfClass:NSClassFromString (@"KWQScrollBar")]) {
+            NSRect bounds = [aView bounds];
+            NSRect adjustedBounds;
+            adjustedBounds.origin = [self convertPoint:bounds.origin fromView:aView];
+            adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
+            
+            // AppKit has horrible hack of placing absent scrollers at -100,-100
+            if (adjustedBounds.origin.y == -100)
+                continue;
+            adjustedBounds.size = bounds.size;
+            NSRect clip = [aView visibleRect];
+            NSRect adjustedClip;
+            adjustedClip.origin = [self convertPoint:clip.origin fromView:aView];
+            adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
+            adjustedClip.size = clip.size;
+            WebDashboardRegion *aRegion = 
+                        [[[WebDashboardRegion alloc] initWithRect:adjustedBounds 
+                                    clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle] autorelease];
+            NSMutableArray *scrollerRegions;
+            scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
+            if (!scrollerRegions) {
+                scrollerRegions = [NSMutableArray array];
+                [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
+            }
+            [scrollerRegions addObject:aRegion];
+        }
+        [self _addScrollerDashboardRegions:regions from:[aView subviews]];
+    }
+}
+
+- (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
+{
+    [self _addScrollerDashboardRegions:regions from:[self subviews]];
+}
+
+- (NSDictionary *)_dashboardRegions
+{
+    // Only return regions from main frame.
+    Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
+    if (!mainFrame)
+        return nil;
+    NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary();
+    [self _addScrollerDashboardRegions:regions];
+    return regions;
+}
+
+- (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
+{
+    // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement 
+    // specific support for the backward compatibility mode flag.
+    if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
+        _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
+    
+    switch (behavior) {
+        case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
+            _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
+            break;
+        }
+        case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
+            _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
+            break;
+        }
+        case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
+            _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
+            break;
+        }
+        case WebDashboardBehaviorAllowWheelScrolling: {
+            _private->dashboardBehaviorAllowWheelScrolling = flag;
+            break;
+        }
+        case WebDashboardBehaviorUseBackwardCompatibilityMode: {
+            if (_private->page)
+                _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
+            break;
+        }
+    }
+}
+
+- (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
+{
+    switch (behavior) {
+        case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
+            return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
+        }
+        case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
+            return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
+        }
+        case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
+            return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
+        }
+        case WebDashboardBehaviorAllowWheelScrolling: {
+            return _private->dashboardBehaviorAllowWheelScrolling;
+        }
+        case WebDashboardBehaviorUseBackwardCompatibilityMode: {
+            return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
+        }
+    }
+    return NO;
+}
+
++ (void)_setShouldUseFontSmoothing:(BOOL)f
+{
+    WebCoreSetShouldUseFontSmoothing(f);
+}
+
++ (BOOL)_shouldUseFontSmoothing
+{
+    return WebCoreShouldUseFontSmoothing();
+}
+
++ (void)_setUsesTestModeFocusRingColor:(BOOL)f
+{
+    setUsesTestModeFocusRingColor(f);
+}
+
++ (BOOL)_usesTestModeFocusRingColor
+{
+    return usesTestModeFocusRingColor();
+}
+
+// This is only used by older versions of Safari and should be removed in a future release. 
++ (NSString *)_minimumRequiredSafariBuildNumber
+{
+    return @"420+";
+}
+
+- (void)setAlwaysShowVerticalScroller:(BOOL)flag
+{
+    WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
+    if (flag) {
+        [scrollview setVerticalScrollingMode:WebCoreScrollbarAlwaysOn andLock:YES];
+    } else {
+        [scrollview setVerticalScrollingModeLocked:NO];
+        [scrollview setVerticalScrollingMode:WebCoreScrollbarAuto];
+    }
+}
+
+- (BOOL)alwaysShowVerticalScroller
+{
+    WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
+    return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == WebCoreScrollbarAlwaysOn;
+}
+
+- (void)setAlwaysShowHorizontalScroller:(BOOL)flag
+{
+    WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
+    if (flag) {
+        [scrollview setHorizontalScrollingMode:WebCoreScrollbarAlwaysOn andLock:YES];
+    } else {
+        [scrollview setHorizontalScrollingModeLocked:NO];
+        [scrollview setHorizontalScrollingMode:WebCoreScrollbarAuto];
+    }
+}
+
+- (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
+{
+    Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
+    if (mainFrame)
+        mainFrame->setProhibitsScrolling(prohibits);
+}
+
+- (BOOL)alwaysShowHorizontalScroller
+{
+    WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
+    return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == WebCoreScrollbarAlwaysOn;
+}
+
+- (void)_setInViewSourceMode:(BOOL)flag
+{
+    Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
+    if (mainFrame)
+        mainFrame->setInViewSourceMode(flag);
+}
+
+- (BOOL)_inViewSourceMode
+{
+    Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
+    return mainFrame && mainFrame->inViewSourceMode();
+}
+
+- (void)_setUseFastImageScalingMode:(BOOL)flag
+{
+    if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
+        _private->page->setInLowQualityImageInterpolationMode(flag);
+        [self setNeedsDisplay:YES];
+    }
+}
+
+- (BOOL)_inFastImageScalingMode
+{
+    if (_private->page)
+        return _private->page->inLowQualityImageInterpolationMode();
+    return NO;
+}
+
+- (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
+{
+    if (!_private->pluginDatabase)
+        _private->pluginDatabase = [[WebPluginDatabase alloc] init];
+        
+    [_private->pluginDatabase setPlugInPaths:newPaths];
+    [_private->pluginDatabase refresh];
+}
+
+- (void)_attachScriptDebuggerToAllFrames
+{
+    for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
+        [kit(frame) _attachScriptDebugger];
+}
+
+- (void)_detachScriptDebuggerFromAllFrames
+{
+    for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
+        [kit(frame) _detachScriptDebugger];
+}
+
+- (void)setBackgroundColor:(NSColor *)backgroundColor
+{
+    if ([_private->backgroundColor isEqual:backgroundColor])
+        return;
+
+    id old = _private->backgroundColor;
+    _private->backgroundColor = [backgroundColor retain];
+    [old release];
+
+    [[self mainFrame] _updateBackground];
+}
+
+- (NSColor *)backgroundColor
+{
+    return _private->backgroundColor;
+}
+
+- (BOOL)defersCallbacks
+{
+    if (!_private->page)
+        return NO;
+    return _private->page->defersLoading();
+}
+
+- (void)setDefersCallbacks:(BOOL)defer
+{
+    if (!_private->page)
+        return;
+    return _private->page->setDefersLoading(defer);
+}
+
+// For backwards compatibility with the WebBackForwardList API, we honor both
+// a per-WebView and a per-preferences setting for whether to use the page cache.
+
+- (BOOL)usesPageCache
+{
+    return _private->usesPageCache && [[self preferences] usesPageCache];
+}
+
+- (void)setUsesPageCache:(BOOL)usesPageCache
+{
+    _private->usesPageCache = usesPageCache;
+
+    // Post a notification so the WebCore settings update.
+    [[self preferences] _postPreferencesChangesNotification];
+}
+
+- (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource 
+{
+    NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window]; 
+    [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window]; 
+} 
+
+- (void)_clearUndoRedoOperations
+{
+    if (!_private->page)
+        return;
+    _private->page->clearUndoRedoOperations();
+}
+
+- (void)_setCatchesDelegateExceptions:(BOOL)f
+{
+    _private->catchesDelegateExceptions = f;
+}
+
+- (BOOL)_catchesDelegateExceptions
+{
+    return _private->catchesDelegateExceptions;
+}
+
+@end
+
+@implementation _WebSafeForwarder
+
+// Used to send messages to delegates that implement informal protocols.
+
+- (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c
+{
+    self = [super init];
+    if (!self)
+        return nil;
+    target = t; // Non retained.
+    defaultTarget = dt;
+    catchExceptions = c;
+    return self;
+}
+
+- (void)forwardInvocation:(NSInvocation *)invocation
+{
+    if ([target respondsToSelector:[invocation selector]]) {
+        if (catchExceptions) {
+            @try {
+                [invocation invokeWithTarget:target];
+            } @catch(id exception) {
+                ReportDiscardedDelegateException([invocation selector], exception);
+            }
+        } else
+            [invocation invokeWithTarget:target];
+        return;
+    }
+
+    if ([defaultTarget respondsToSelector:[invocation selector]])
+        [invocation invokeWithTarget:defaultTarget];
+
+    // Do nothing quietly if method not implemented.
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
+{
+    return [defaultTarget methodSignatureForSelector:aSelector];
+}
+
+@end
+
+@implementation WebView
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+    if (initialized)
+        return;
+    initialized = YES;
+
+#ifdef REMOVE_SAFARI_DOM_TREE_DEBUG_ITEM
+    // This prevents open source users from crashing when using the Show DOM Tree menu item in Safari 2.
+    // FIXME: remove this when we no longer need to support Safari 2.
+    if ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"] && [[NSUserDefaults standardUserDefaults] boolForKey:@"IncludeDebugMenu"])
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_finishedLaunching) name:NSApplicationDidFinishLaunchingNotification object:NSApp];
+#endif
+
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];
+}
+
++ (void)_applicationWillTerminate
+{   
+    applicationIsTerminating = YES;
+    if (!pluginDatabaseClientCount)
+        [WebPluginDatabase closeSharedDatabase];
+}
+
+#ifdef REMOVE_SAFARI_DOM_TREE_DEBUG_ITEM
+// FIXME: remove this when it is no longer needed to prevent Safari from crashing
++ (void)_finishedLaunching
+{
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_removeDOMTreeMenuItem:) name:NSMenuDidAddItemNotification object:[NSApp mainMenu]];
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidFinishLaunchingNotification object:NSApp];
+}
+
++(void)_removeDOMTreeMenuItem:(NSNotification *)notification
+{
+    NSMenu *debugMenu = [[[[NSApp mainMenu] itemArray] lastObject] submenu];
+    NSMenuItem *domTree = [debugMenu itemWithTitle:@"Show DOM Tree"];
+    if (domTree)
+        [debugMenu removeItem:domTree];
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMenuDidAddItemNotification object:[NSApp mainMenu]];
+}
+#endif
+
++ (BOOL)canShowMIMEType:(NSString *)MIMEType
+{
+    return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType];
+}
+
+- (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
+{
+    WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
+    if (pluginPackage)
+        return pluginPackage;
+    
+    if (_private->pluginDatabase)
+        return [_private->pluginDatabase pluginForMIMEType:MIMEType];
+    
+    return nil;
+}
+
+- (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
+{
+    WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
+    if (pluginPackage)
+        return pluginPackage;
+    
+    if (_private->pluginDatabase)
+        return [_private->pluginDatabase pluginForExtension:extension];
+    
+    return nil;
+}
+
+- (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
+{
+    if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
+        return YES;
+        
+    if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
+        return YES;
+    
+    return NO;
+}
+
++ (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
+{
+    return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
+}
+
++ (NSArray *)MIMETypesShownAsHTML
+{
+    NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
+    NSEnumerator *enumerator = [viewTypes keyEnumerator];
+    id key;
+    NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
+    
+    while ((key = [enumerator nextObject])) {
+        if ([viewTypes objectForKey:key] == [WebHTMLView class])
+            [array addObject:key];
+    }
+    
+    return array;
+}
+
++ (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
+{
+    NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
+    NSEnumerator *enumerator = [viewTypes keyEnumerator];
+    id key;
+    while ((key = [enumerator nextObject])) {
+        if ([viewTypes objectForKey:key] == [WebHTMLView class])
+            [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
+    }
+    
+    int i, count = [MIMETypes count];
+    for (i = 0; i < count; i++) {
+        [WebView registerViewClass:[WebHTMLView class] 
+                representationClass:[WebHTMLRepresentation class] 
+                forMIMEType:[MIMETypes objectAtIndex:i]];
+    }
+    [viewTypes release];
+}
+
++ (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
+{
+    return [pasteboard _web_bestURL];
+}
+
++ (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
+{
+    return [pasteboard stringForType:WebURLNamePboardType];
+}
+
++ (void)registerURLSchemeAsLocal:(NSString *)protocol
+{
+    FrameLoader::registerURLSchemeAsLocal(protocol);
+}
+
+- (void)_registerDraggedTypes
+{
+    NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
+    NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
+    NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
+    [types addObjectsFromArray:URLTypes];
+    [self registerForDraggedTypes:[types allObjects]];
+    [types release];
+}
+
+- (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName
+{
+    WebPreferences *standardPreferences = [WebPreferences standardPreferences];
+    [standardPreferences willAddToWebView];
+
+    _private->preferences = [standardPreferences retain];
+    _private->catchesDelegateExceptions = YES;
+    _private->mainFrameDocumentReady = NO;
+    _private->drawsBackground = YES;
+    _private->smartInsertDeleteEnabled = YES;
+    _private->backgroundColor = [[NSColor whiteColor] retain];
+
+    NSRect f = [self frame];
+    WebFrameView *frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
+    [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+    [self addSubview:frameView];
+    [frameView release];
+
+    WebKitInitializeLoggingChannelsIfNecessary();
+    WebCore::InitializeLoggingChannelsIfNecessary();
+    [WebHistoryItem initWindowWatcherIfNecessary];
+
+    _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self));
+    [[[WebFrameBridge alloc] initMainFrameWithPage:_private->page frameName:frameName frameView:frameView] release];
+
+    [self _addToAllWebViewsSet];
+    [self setGroupName:groupName];
+    
+    // If there's already a next key view (e.g., from a nib), wire it up to our
+    // contained frame view. In any case, wire our next key view up to the our
+    // contained frame view. This works together with our becomeFirstResponder 
+    // and setNextKeyView overrides.
+    NSView *nextKeyView = [self nextKeyView];
+    if (nextKeyView != nil && nextKeyView != frameView) {
+        [frameView setNextKeyView:nextKeyView];
+    }
+    [super setNextKeyView:frameView];
+
+    ++WebViewCount;
+
+    [self _registerDraggedTypes];
+
+    // initialize WebScriptDebugServer here so listeners can register before any pages are loaded.
+    if ([WebView _scriptDebuggerEnabled])
+        [WebScriptDebugServer sharedScriptDebugServer];
+
+    WebPreferences *prefs = [self preferences];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
+                                                 name:WebPreferencesChangedNotification object:prefs];
+
+    // Post a notification so the WebCore settings update.
+    [[self preferences] _postPreferencesChangesNotification];
+
+    if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION))
+        FrameLoader::setRestrictAccessToLocal(true);
+}
+
+- (id)initWithFrame:(NSRect)f
+{
+    return [self initWithFrame:f frameName:nil groupName:nil];
+}
+
+- (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName;
+{
+    self = [super initWithFrame:f];
+    if (!self)
+        return nil;
+
+#ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
+    // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
+    // may not work with other WebKit applications.  Unsetting DYLD_FRAMEWORK_PATH removes the
+    // need for Safari to unset it to prevent it from being passed to applications it launches.
+    // Unsetting it when a WebView is first created is as good a place as any.
+    // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
+    if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
+        unsetenv("DYLD_FRAMEWORK_PATH");
+        unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
+    }
+#endif
+
+    _private = [[WebViewPrivate alloc] init];
+    [self _commonInitializationWithFrameName:frameName groupName:groupName];
+    [self setMaintainsBackForwardList: YES];
+    return self;
+}
+
+- (id)initWithCoder:(NSCoder *)decoder
+{
+    WebView *result = nil;
+
+NS_DURING
+
+    NSString *frameName;
+    NSString *groupName;
+    WebPreferences *preferences;
+    BOOL useBackForwardList = NO;
+    BOOL allowsUndo = YES;
+    
+    result = [super initWithCoder:decoder];
+    result->_private = [[WebViewPrivate alloc] init];
+
+    // We don't want any of the archived subviews. The subviews will always
+    // be created in _commonInitializationFrameName:groupName:.
+    [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
+
+    if ([decoder allowsKeyedCoding]) {
+        frameName = [decoder decodeObjectForKey:@"FrameName"];
+        groupName = [decoder decodeObjectForKey:@"GroupName"];
+        preferences = [decoder decodeObjectForKey:@"Preferences"];
+        useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
+        if ([decoder containsValueForKey:@"AllowsUndo"])
+            allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
+    } else {
+        int version;
+        [decoder decodeValueOfObjCType:@encode(int) at:&version];
+        frameName = [decoder decodeObject];
+        groupName = [decoder decodeObject];
+        preferences = [decoder decodeObject];
+        if (version > 1)
+            [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
+        // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
+        // version 3 NIBs that have this field encoded, we still need to read it in.
+        if (version == 3)
+            [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
+    }
+
+    if (![frameName isKindOfClass:[NSString class]])
+        frameName = nil;
+    if (![groupName isKindOfClass:[NSString class]])
+        groupName = nil;
+    if (![preferences isKindOfClass:[WebPreferences class]])
+        preferences = nil;
+
+    LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
+    [result _commonInitializationWithFrameName:frameName groupName:groupName];
+    [result page]->backForwardList()->setEnabled(useBackForwardList);
+    result->_private->allowsUndo = allowsUndo;
+    if (preferences)
+        [result setPreferences:preferences];
+
+NS_HANDLER
+
+    result = nil;
+    [self release];
+
+NS_ENDHANDLER
+
+    return result;
+}
+
+- (void)encodeWithCoder:(NSCoder *)encoder
+{
+    // Set asside the subviews before we archive. We don't want to archive any subviews.
+    // The subviews will always be created in _commonInitializationFrameName:groupName:.
+    id originalSubviews = _subviews;
+    _subviews = nil;
+
+    [super encodeWithCoder:encoder];
+
+    // Restore the subviews we set aside.
+    _subviews = originalSubviews;
+
+    BOOL useBackForwardList = _private->page && _private->page->backForwardList()->enabled();
+    if ([encoder allowsKeyedCoding]) {
+        [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
+        [encoder encodeObject:[self groupName] forKey:@"GroupName"];
+        [encoder encodeObject:[self preferences] forKey:@"Preferences"];
+        [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"];
+        [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"];
+    } else {
+        int version = WebViewVersion;
+        [encoder encodeValueOfObjCType:@encode(int) at:&version];
+        [encoder encodeObject:[[self mainFrame] name]];
+        [encoder encodeObject:[self groupName]];
+        [encoder encodeObject:[self preferences]];
+        [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList];
+        // DO NOT encode any new fields here, doing so will break older WebKit releases.
+    }
+
+    LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList);
+}
+
+- (void)dealloc
+{
+    // call close to ensure we tear-down completely
+    // this maintains our old behavior for existing applications
+    [self _close];
+
+    --WebViewCount;
+    
+    [_private release];
+    // [super dealloc] can end up dispatching against _private (3466082)
+    _private = nil;
+
+    [super dealloc];
+}
+
+- (void)finalize
+{
+    ASSERT(_private->closed);
+
+    --WebViewCount;
+
+    [super finalize];
+}
+
+- (void)close
+{
+    [self _close];
+}
+
+- (void)setShouldCloseWithWindow:(BOOL)close
+{
+    _private->shouldCloseWithWindow = close;
+}
+
+- (BOOL)shouldCloseWithWindow
+{
+    return _private->shouldCloseWithWindow;
+}
+
+- (void)viewWillMoveToWindow:(NSWindow *)window
+{
+    // Don't do anything if we aren't initialized.  This happens when decoding a WebView.
+    if (!_private)
+        return;
+    
+    if ([self window])
+        [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
+
+    if (window) {
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
+
+        // Ensure that we will receive the events that WebHTMLView (at least) needs. It's expensive enough
+        // that we don't want to call it over and over.
+        [window setAcceptsMouseMovedEvents:YES];
+        WKSetNSWindowShouldPostEventNotifications(window, YES);
+    }
+}
+
+- (void)_windowWillClose:(NSNotification *)notification
+{
+    if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
+        [self _close];
+}
+
+- (void)setPreferences:(WebPreferences *)prefs
+{
+    if (!prefs)
+        prefs = [WebPreferences standardPreferences];
+
+    if (_private->preferences == prefs)
+        return;
+
+    [prefs willAddToWebView];
+
+    WebPreferences *oldPrefs = _private->preferences;
+
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
+    [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
+
+    _private->preferences = [prefs retain];
+
+    // After registering for the notification, post it so the WebCore settings update.
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
+        name:WebPreferencesChangedNotification object:[self preferences]];
+    [[self preferences] _postPreferencesChangesNotification];
+
+    [oldPrefs didRemoveFromWebView];
+    [oldPrefs release];
+}
+
+- (WebPreferences *)preferences
+{
+    return _private->preferences;
+}
+
+- (void)setPreferencesIdentifier:(NSString *)anIdentifier
+{
+    if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
+        WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
+        [self setPreferences:prefs];
+        [prefs release];
+    }
+}
+
+- (NSString *)preferencesIdentifier
+{
+    return [[self preferences] identifier];
+}
+
+
+- (void)setUIDelegate:delegate
+{
+    _private->UIDelegate = delegate;
+    [_private->UIDelegateForwarder release];
+    _private->UIDelegateForwarder = nil;
+}
+
+- UIDelegate
+{
+    return _private->UIDelegate;
+}
+
+- (void)setResourceLoadDelegate: delegate
+{
+    _private->resourceProgressDelegate = delegate;
+    [self _cacheResourceLoadDelegateImplementations];
+}
+
+- resourceLoadDelegate
+{
+    return _private->resourceProgressDelegate;
+}
+
+- (void)setDownloadDelegate: delegate
+{
+    _private->downloadDelegate = delegate;
+}
+
+
+- downloadDelegate
+{
+    return _private->downloadDelegate;
+}
+
+- (void)setPolicyDelegate:delegate
+{
+    _private->policyDelegate = delegate;
+    [_private->policyDelegateForwarder release];
+    _private->policyDelegateForwarder = nil;
+}
+
+- policyDelegate
+{
+    return _private->policyDelegate;
+}
+
+- (void)setFrameLoadDelegate:delegate
+{
+    _private->frameLoadDelegate = delegate;
+    [self _cacheFrameLoadDelegateImplementations];
+}
+
+- frameLoadDelegate
+{
+    return _private->frameLoadDelegate;
+}
+
+- (WebFrame *)mainFrame
+{
+    // This can be called in initialization, before _private has been set up (3465613)
+    if (!_private)
+        return nil;
+    if (!_private->page)
+        return nil;
+    return kit(_private->page->mainFrame());
+}
+
+- (WebFrame *)selectedFrame
+{
+    // If the first responder is a view in our tree, we get the frame containing the first responder.
+    // This is faster than searching the frame hierarchy, and will give us a result even in the case
+    // where the focused frame doesn't actually contain a selection.
+    WebFrame *focusedFrame = [self _focusedFrame];
+    if (focusedFrame)
+        return focusedFrame;
+    
+    // If the first responder is outside of our view tree, we search for a frame containing a selection.
+    // There should be at most only one of these.
+    return [[self mainFrame] _findFrameWithSelection];
+}
+
+- (WebBackForwardList *)backForwardList
+{
+    if (!_private->page)
+        return nil;
+    if (!_private->page->backForwardList()->enabled())
+        return nil;
+    return kit(_private->page->backForwardList());
+}
+
+- (void)setMaintainsBackForwardList: (BOOL)flag
+{
+    if (!_private->page)
+        return;
+    _private->page->backForwardList()->setEnabled(flag);
+}
+
+- (BOOL)goBack
+{
+    if (!_private->page)
+        return NO;
+    
+    return _private->page->goBack();
+}
+
+- (BOOL)goForward
+{
+    if (!_private->page)
+        return NO;
+
+    return _private->page->goForward();
+}
+
+- (BOOL)goToBackForwardItem:(WebHistoryItem *)item
+{
+    if (!_private->page)
+        return NO;
+
+    _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward);
+    return YES;
+}
+
+- (void)setTextSizeMultiplier:(float)m
+{
+    // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>)
+    if (_private->textSizeMultiplier == m)
+        return;
+
+    _private->textSizeMultiplier = m;
+    [self _notifyTextSizeMultiplierChanged];
+}
+
+- (float)textSizeMultiplier
+{
+    return _private->textSizeMultiplier;
+}
+
+- (void)setApplicationNameForUserAgent:(NSString *)applicationName
+{
+    NSString *name = [applicationName copy];
+    [_private->applicationNameForUserAgent release];
+    _private->applicationNameForUserAgent = name;
+    if (!_private->userAgentOverridden)
+        *_private->userAgent = String();
+}
+
+- (NSString *)applicationNameForUserAgent
+{
+    return [[_private->applicationNameForUserAgent retain] autorelease];
+}
+
+- (void)setCustomUserAgent:(NSString *)userAgentString
+{
+    *_private->userAgent = userAgentString;
+    _private->userAgentOverridden = userAgentString != nil;
+}
+
+- (NSString *)customUserAgent
+{
+    if (!_private->userAgentOverridden)
+        return nil;
+    return *_private->userAgent;
+}
+
+- (void)setMediaStyle:(NSString *)mediaStyle
+{
+    if (_private->mediaStyle != mediaStyle) {
+        [_private->mediaStyle release];
+        _private->mediaStyle = [mediaStyle copy];
+    }
+}
+
+- (NSString *)mediaStyle
+{
+    return _private->mediaStyle;
+}
+
+- (BOOL)supportsTextEncoding
+{
+    id documentView = [[[self mainFrame] frameView] documentView];
+    return [documentView conformsToProtocol:@protocol(WebDocumentText)]
+        && [documentView supportsTextEncoding];
+}
+
+- (void)setCustomTextEncodingName:(NSString *)encoding
+{
+    NSString *oldEncoding = [self customTextEncodingName];
+    if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
+        return;
+    FrameLoader* mainFrameLoader = [[self mainFrame] _frameLoader];
+    if (mainFrameLoader)
+        mainFrameLoader->reloadAllowingStaleData(encoding);
+}
+
+- (NSString *)_mainFrameOverrideEncoding
+{
+    WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
+    if (dataSource == nil)
+        dataSource = [[self mainFrame] _dataSource];
+    if (dataSource == nil)
+        return nil;
+    return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding());
+}
+
+- (NSString *)customTextEncodingName
+{
+    return [self _mainFrameOverrideEncoding];
+}
+
+- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
+{
+    // FIXME: We can remove this workaround for VitalSource Bookshelf when they update
+    // their code so that it no longer calls stringByEvaluatingJavaScriptFromString with a return statement.
+    // Return statements are only valid in a function.  See <rdar://problem/5095515> for the evangelism bug.
+    if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_VITALSOURCE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.vitalsource.bookshelf"]) {
+        NSRange returnStringRange = [script rangeOfString:@"return "];
+        if (returnStringRange.length != 0 && returnStringRange.location == 0)
+            script = [script substringFromIndex: returnStringRange.location + returnStringRange.length];
+    }
+    
+    NSString *result = [[[self mainFrame] _bridge] stringByEvaluatingJavaScriptFromString:script];
+    // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script
+    // Since there's no way to get rid of the main frame, result will never ever be nil here.
+    ASSERT(result);
+    
+    return result;
+}
+
+- (WebScriptObject *)windowScriptObject
+{
+    Frame* coreFrame = core([self mainFrame]);
+    if (!coreFrame)
+        return nil;
+    return coreFrame->windowScriptObject();
+}
+
+// Get the appropriate user-agent string for a particular URL.
+- (NSString *)userAgentForURL:(NSURL *)url
+{
+    return [self _userAgentForURL:KURL([url absoluteURL])];
+}
+
+- (void)setHostWindow:(NSWindow *)hostWindow
+{
+    if (!_private->closed && hostWindow != _private->hostWindow) {
+        [[self mainFrame] _viewWillMoveToHostWindow:hostWindow];
+        if (_private->hostWindow)
+            [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
+        if (hostWindow)
+            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
+        [_private->hostWindow release];
+        _private->hostWindow = [hostWindow retain];
+        [[self mainFrame] _viewDidMoveToHostWindow];
+    }
+}
+
+- (NSWindow *)hostWindow
+{
+    return _private->hostWindow;
+}
+
+- (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
+{
+    return [[self _frameViewAtWindowPoint:point] documentView];
+}
+
+- (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
+{
+    WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
+    if (!frameView)
+        return nil;
+    NSView <WebDocumentView> *documentView = [frameView documentView];
+    if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
+        NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
+        return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
+    }
+    return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
+}
+
+- (NSDictionary *)elementAtPoint:(NSPoint)point
+{
+    return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
+}
+
+// The following 2 internal NSView methods are called on the drag destination by make scrolling while dragging work.
+// Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination. 
+// When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination. 
+// Forward these calls to the document subview to make its scroll view scroll.
+- (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
+{
+    NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
+    [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
+}
+
+- (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
+{
+    NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
+    return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
+{
+    NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
+    WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
+    IntPoint client([draggingInfo draggingLocation]);
+    IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
+    DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
+    return core(self)->dragController()->dragEntered(&dragData);
+}
+
+- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
+{
+    NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
+    WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
+    IntPoint client([draggingInfo draggingLocation]);
+    IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
+    DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
+    return core(self)->dragController()->dragUpdated(&dragData);
+}
+
+- (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
+{
+    NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
+    WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
+    IntPoint client([draggingInfo draggingLocation]);
+    IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
+    DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
+    core(self)->dragController()->dragExited(&dragData);
+}
+
+- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
+{
+    return YES;
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
+{
+    NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
+    WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]]? (WebHTMLView*)view : nil);
+    IntPoint client([draggingInfo draggingLocation]);
+    IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
+    DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
+    return core(self)->dragController()->performDrag(&dragData);
+}
+
+- (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types
+{
+    NSView *hitView = [super _hitTest:aPoint dragTypes:types];
+    if (!hitView && [[self superview] mouse:*aPoint inRect:[self frame]]) {
+        return self;
+    } else {
+        return hitView;
+    }
+}
+
+- (BOOL)acceptsFirstResponder
+{
+    return [[[self mainFrame] frameView] acceptsFirstResponder];
+}
+
+- (BOOL)becomeFirstResponder
+{
+    if (_private->becomingFirstResponder) {
+        // Fix for unrepro infinite recursion reported in radar 4448181. If we hit this assert on
+        // a debug build, we should figure out what causes the problem and do a better fix.
+        ASSERT_NOT_REACHED();
+        return NO;
+    }
+    
+    // This works together with setNextKeyView to splice the WebView into
+    // the key loop similar to the way NSScrollView does this. Note that
+    // WebFrameView has very similar code.
+    NSWindow *window = [self window];
+    WebFrameView *mainFrameView = [[self mainFrame] frameView];
+
+    NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
+    BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
+    
+    if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
+        NSView *previousValidKeyView = [self previousValidKeyView];
+        if ((previousValidKeyView != self) && (previousValidKeyView != mainFrameView)) {
+            _private->becomingFirstResponder = YES;
+            _private->becomingFirstResponderFromOutside = fromOutside;
+            [window makeFirstResponder:previousValidKeyView];
+            _private->becomingFirstResponderFromOutside = NO;
+            _private->becomingFirstResponder = NO;
+            return YES;
+        } else {
+            return NO;
+        }
+    }
+    
+    if ([mainFrameView acceptsFirstResponder]) {
+        _private->becomingFirstResponder = YES;
+        _private->becomingFirstResponderFromOutside = fromOutside;
+        [window makeFirstResponder:mainFrameView];
+        _private->becomingFirstResponderFromOutside = NO;
+        _private->becomingFirstResponder = NO;
+        return YES;
+    } 
+    
+    return NO;
+}
+
+- (NSView *)_webcore_effectiveFirstResponder
+{
+    WebFrameView *frameView = [[self mainFrame] frameView];
+    return frameView ? [frameView _webcore_effectiveFirstResponder] : [super _webcore_effectiveFirstResponder];
+}
+
+- (void)setNextKeyView:(NSView *)aView
+{
+    // This works together with becomeFirstResponder to splice the WebView into
+    // the key loop similar to the way NSScrollView does this. Note that
+    // WebFrameView has very similar code.
+    WebFrameView *mainFrameView = [[self mainFrame] frameView];
+    if (mainFrameView != nil) {
+        [mainFrameView setNextKeyView:aView];
+    } else {
+        [super setNextKeyView:aView];
+    }
+}
+
+static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
+{
+    Frame* coreFrame = core(curr);
+    return kit(forward
+        ? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
+        : coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
+}
+
+- (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
+{
+    return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
+}
+
++ (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
+{
+    [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
+    [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
+    
+    // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
+    // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
+    // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
+    if ([viewClass class] == [WebHTMLView class])
+        MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
+}
+
+- (void)setGroupName:(NSString *)groupName
+{
+    if (!_private->page)
+        return;
+    _private->page->setGroupName(groupName);
+}
+
+- (NSString *)groupName
+{
+    if (!_private->page)
+        return nil;
+    return _private->page->groupName();
+}
+
+- (double)estimatedProgress
+{
+    if (!_private->page)
+        return 0.0;
+
+    return _private->page->progress()->estimatedProgress();
+}
+
+- (NSArray *)pasteboardTypesForSelection
+{
+    NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
+    if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
+        return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
+    }
+    return [NSArray array];
+}
+
+- (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
+{
+    WebFrame *frame = [self _selectedOrMainFrame];
+    if (frame && [frame _hasSelection]) {
+        NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
+        if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)])
+            [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
+    }
+}
+
+- (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
+{
+    if ([element objectForKey:WebElementImageURLKey] != nil) {
+        return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
+    } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
+        return [NSPasteboard _web_writableTypesForURL];
+    } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
+        return [self pasteboardTypesForSelection];
+    }
+    return [NSArray array];
+}
+
+- (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
+{
+    if ([element objectForKey:WebElementImageURLKey] != nil) {
+        [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
+    } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
+        [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
+    } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
+        [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
+    }
+}
+
+- (void)moveDragCaretToPoint:(NSPoint)point
+{
+    if (Page* page = core(self))
+        page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil]));
+}
+
+- (void)removeDragCaret
+{
+    if (Page* page = core(self))
+        page->dragController()->dragEnded();
+}
+
+- (void)setMainFrameURL:(NSString *)URLString
+{
+    [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
+}
+
+- (NSString *)mainFrameURL
+{
+    WebDataSource *ds;
+    ds = [[self mainFrame] provisionalDataSource];
+    if (!ds)
+        ds = [[self mainFrame] _dataSource];
+    return [[[ds request] URL] _web_originalDataAsString];
+}
+
+- (BOOL)isLoading
+{
+    LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
+    return [self _isLoading];
+}
+
+- (NSString *)mainFrameTitle
+{
+    NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle];
+    return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
+}
+
+- (NSImage *)mainFrameIcon
+{
+    return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
+}
+
+- (DOMDocument *)mainFrameDocument
+{
+    // only return the actual value if the state we're in gives NSTreeController
+    // enough time to release its observers on the old model
+    if (_private->mainFrameDocumentReady)
+        return [[self mainFrame] DOMDocument];
+    return nil;
+}
+
+- (void)setDrawsBackground:(BOOL)drawsBackground
+{
+    if (_private->drawsBackground == drawsBackground)
+        return;
+    _private->drawsBackground = drawsBackground;
+    [[self mainFrame] _updateBackground];
+}
+
+- (BOOL)drawsBackground
+{
+    return _private->drawsBackground;
+}
+
+@end
+
+@implementation WebView (WebIBActions)
+
+- (IBAction)takeStringURLFrom: sender
+{
+    NSString *URLString = [sender stringValue];
+    
+    [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
+}
+
+- (BOOL)canGoBack
+{
+    if (!_private->page)
+        return NO;
+
+    return !!_private->page->backForwardList()->backItem();
+}
+
+- (BOOL)canGoForward
+{
+    if (!_private->page)
+        return NO;
+
+    return !!_private->page->backForwardList()->forwardItem();
+}
+
+- (IBAction)goBack:(id)sender
+{
+    [self goBack];
+}
+
+- (IBAction)goForward:(id)sender
+{
+    [self goForward];
+}
+
+- (IBAction)stopLoading:(id)sender
+{
+    [[self mainFrame] stopLoading];
+}
+
+- (IBAction)reload:(id)sender
+{
+    [[self mainFrame] reload];
+}
+
+#define MinimumTextSizeMultiplier       0.5f
+#define MaximumTextSizeMultiplier       3.0f
+#define TextSizeMultiplierRatio         1.2f
+
+- (BOOL)canMakeTextSmaller
+{
+    BOOL canShrinkMore = _private->textSizeMultiplier/TextSizeMultiplierRatio > MinimumTextSizeMultiplier;
+    return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:canShrinkMore selForNonTrackingDocs:@selector(_canMakeTextSmaller) newScaleFactor:0];
+}
+
+- (BOOL)canMakeTextLarger
+{
+    BOOL canGrowMore = _private->textSizeMultiplier*TextSizeMultiplierRatio < MaximumTextSizeMultiplier;
+    return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:canGrowMore selForNonTrackingDocs:@selector(_canMakeTextLarger) newScaleFactor:0];
+}
+
+- (IBAction)makeTextSmaller:(id)sender
+{
+    float newScale = _private->textSizeMultiplier / TextSizeMultiplierRatio;
+    BOOL canShrinkMore = newScale > MinimumTextSizeMultiplier;
+    [self _performTextSizingSelector:@selector(_makeTextSmaller:) withObject:sender onTrackingDocs:canShrinkMore selForNonTrackingDocs:@selector(_canMakeTextSmaller) newScaleFactor:newScale];
+}
+
+- (IBAction)makeTextLarger:(id)sender
+{
+    float newScale = _private->textSizeMultiplier*TextSizeMultiplierRatio;
+    BOOL canGrowMore = newScale < MaximumTextSizeMultiplier;
+    [self _performTextSizingSelector:@selector(_makeTextLarger:) withObject:sender onTrackingDocs:canGrowMore selForNonTrackingDocs:@selector(_canMakeTextLarger) newScaleFactor:newScale];
+}
+
+- (IBAction)toggleSmartInsertDelete:(id)sender
+{
+    [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
+}
+
+- (IBAction)toggleContinuousSpellChecking:(id)sender
+{
+    [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
+}
+
+- (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
+{
+    id responder = [self _responderForResponderOperations];
+    if (responder != self && [responder respondsToSelector:[item action]]) {
+        if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)])
+            return [responder validateUserInterfaceItemWithoutDelegate:item];
+        if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)])
+            return [responder validateUserInterfaceItem:item];
+        return YES;
+    }
+    return NO;
+}
+
+- (BOOL)canMakeTextStandardSize
+{
+    BOOL notAlreadyStandard = _private->textSizeMultiplier != 1.0f;
+    return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:notAlreadyStandard selForNonTrackingDocs:@selector(_canMakeTextStandardSize) newScaleFactor:0.0f];
+}
+
+- (IBAction)makeTextStandardSize:(id)sender
+{
+    BOOL notAlreadyStandard = _private->textSizeMultiplier != 1.0f;
+    [self _performTextSizingSelector:@selector(_makeTextStandardSize:) withObject:sender onTrackingDocs:notAlreadyStandard selForNonTrackingDocs:@selector(_canMakeTextStandardSize) newScaleFactor:1.0f];
+}
+
+#define VALIDATE(name) \
+    else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
+
+- (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
+{
+    SEL action = [item action];
+
+    if (action == @selector(goBack:)) {
+        return [self canGoBack];
+    } else if (action == @selector(goForward:)) {
+        return [self canGoForward];
+    } else if (action == @selector(makeTextLarger:)) {
+        return [self canMakeTextLarger];
+    } else if (action == @selector(makeTextSmaller:)) {
+        return [self canMakeTextSmaller];
+    } else if (action == @selector(makeTextStandardSize:)) {
+        return [self canMakeTextStandardSize];
+    } else if (action == @selector(reload:)) {
+        return [[self mainFrame] _dataSource] != nil;
+    } else if (action == @selector(stopLoading:)) {
+        return [self _isLoading];
+    } else if (action == @selector(toggleContinuousSpellChecking:)) {
+        BOOL checkMark = NO;
+        BOOL retVal = NO;
+        if ([self _continuousCheckingAllowed]) {
+            checkMark = [self isContinuousSpellCheckingEnabled];
+            retVal = YES;
+        }
+        if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
+            NSMenuItem *menuItem = (NSMenuItem *)item;
+            [menuItem setState:checkMark ? NSOnState : NSOffState];
+        }
+        return retVal;
+#ifndef BUILDING_ON_TIGER
+    } else if (action == @selector(toggleGrammarChecking:)) {
+        BOOL checkMark = [self isGrammarCheckingEnabled];
+        if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
+            NSMenuItem *menuItem = (NSMenuItem *)item;
+            [menuItem setState:checkMark ? NSOnState : NSOffState];
+        }
+        return YES;
+#endif
+    }
+    FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
+
+    return YES;
+}
+
+- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
+{
+    BOOL result = [self validateUserInterfaceItemWithoutDelegate:item];
+    return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);
+}
+
+@end
+
+@implementation WebView (WebPendingPublic)
+
+- (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
+{
+    if (_private->closed)
+        return NO;
+    
+    // Get the frame holding the selection, or start with the main frame
+    WebFrame *startFrame = [self _selectedOrMainFrame];
+    
+    // Search the first frame, then all the other frames, in order
+    NSView <WebDocumentSearching> *startSearchView = nil;
+    WebFrame *frame = startFrame;
+    do {
+        WebFrame *nextFrame = incrementFrame(frame, forward, wrapFlag);
+        
+        BOOL onlyOneFrame = (frame == nextFrame);
+        ASSERT(!onlyOneFrame || frame == startFrame);
+        
+        id <WebDocumentView> view = [[frame frameView] documentView];
+        if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
+            NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
+            
+            if (frame == startFrame)
+                startSearchView = searchView;
+            
+            BOOL foundString;
+            // In some cases we have to search some content twice; see comment later in this method.
+            // We can avoid ever doing this in the common one-frame case by passing YES for wrapFlag 
+            // here, and then bailing out before we get to the code that would search again in the
+            // same content.
+            BOOL wrapOnThisPass = wrapFlag && onlyOneFrame;
+            if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
+                foundString = [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass startInSelection:startInSelection];
+            else
+                foundString = [searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass];
+            
+            if (foundString) {
+                if (frame != startFrame)
+                    [startFrame _clearSelection];
+                [[self window] makeFirstResponder:searchView];
+                return YES;
+            }
+            
+            if (onlyOneFrame)
+                return NO;
+        }
+        frame = nextFrame;
+    } while (frame && frame != startFrame);
+    
+    // If there are multiple frames and wrapFlag is true and we've visited each one without finding a result, we still need to search in the 
+    // first-searched frame up to the selection. However, the API doesn't provide a way to search only up to a particular point. The only 
+    // way to make sure the entire frame is searched is to pass YES for the wrapFlag. When there are no matches, this will search again
+    // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice.
+    // To fix this, we'd need to add a mechanism to specify a range in which to search.
+    if (wrapFlag && startSearchView) {
+        BOOL foundString;
+        if ([startSearchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
+            foundString = [(NSView <WebDocumentIncrementalSearching> *)startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES startInSelection:startInSelection];
+        else
+            foundString = [startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES];
+        if (foundString) {
+            [[self window] makeFirstResponder:startSearchView];
+            return YES;
+        }
+    }
+    return NO;
+}
+
+- (void)setHoverFeedbackSuspended:(BOOL)newValue
+{
+    if (_private->hoverFeedbackSuspended == newValue)
+        return;
+    
+    _private->hoverFeedbackSuspended = newValue;
+    id <WebDocumentView> documentView = [[[self mainFrame] frameView] documentView];
+    // FIXME: in a perfect world we'd do this in a general way that worked with any document view,
+    // such as by calling a protocol method or using respondsToSelector or sending a notification.
+    // But until there is any need for these more general solutions, we'll just hardwire it to work
+    // with WebHTMLView.
+    // Note that _hoverFeedbackSuspendedChanged needs to be called only on the main WebHTMLView, not
+    // on each subframe separately.
+    if ([documentView isKindOfClass:[WebHTMLView class]])
+        [(WebHTMLView *)documentView _hoverFeedbackSuspendedChanged];
+}
+
+- (BOOL)isHoverFeedbackSuspended
+{
+    return _private->hoverFeedbackSuspended;
+}
+
+- (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady
+{
+    // by setting this to NO, calls to mainFrameDocument are forced to return nil
+    // setting this to YES lets it return the actual DOMDocument value
+    // we use this to tell NSTreeController to reset its observers and clear its state
+    if (_private->mainFrameDocumentReady == mainFrameDocumentReady)
+        return;
+    [self _willChangeValueForKey:_WebMainFrameDocumentKey];
+    _private->mainFrameDocumentReady = mainFrameDocumentReady;
+    [self _didChangeValueForKey:_WebMainFrameDocumentKey];
+    // this will cause observers to call mainFrameDocument where this flag will be checked
+}
+
+// This method name is used by Mail on Tiger (but not post-Tiger), so we shouldn't delete it 
+// until the day comes when we're no longer supporting Mail on Tiger.
+- (WebFrame *)_frameForCurrentSelection
+{
+    return [self _selectedOrMainFrame];
+}
+
+- (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements
+{
+    _private->tabKeyCyclesThroughElementsChanged = YES;
+    if (_private->page)
+        _private->page->setTabKeyCyclesThroughElements(cyclesElements);
+}
+
+- (BOOL)tabKeyCyclesThroughElements
+{
+    return _private->page && _private->page->tabKeyCyclesThroughElements();
+}
+
+- (void)setScriptDebugDelegate:(id)delegate
+{
+    _private->scriptDebugDelegate = delegate;
+    [_private->scriptDebugDelegateForwarder release];
+    _private->scriptDebugDelegateForwarder = nil;
+    if (delegate)
+        [self _attachScriptDebuggerToAllFrames];
+    else
+        [self _detachScriptDebuggerFromAllFrames];
+}
+
+- (id)scriptDebugDelegate
+{
+    return _private->scriptDebugDelegate;
+}
+
+- (BOOL)shouldClose
+{
+    Frame* coreFrame = core([self mainFrame]);
+    if (!coreFrame)
+        return YES;
+    return coreFrame->shouldClose();
+}
+
+- (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script
+{
+    return [[[self mainFrame] _bridge] aeDescByEvaluatingJavaScriptFromString:script];
+}
+
+- (BOOL)canMarkAllTextMatches
+{
+    WebFrame *frame = [self mainFrame];
+    do {
+        id <WebDocumentView> view = [[frame frameView] documentView];
+        if (view && ![view conformsToProtocol:@protocol(WebMultipleTextMatches)])
+            return NO;
+        
+        frame = incrementFrame(frame, YES, NO);
+    } while (frame);
+    
+    return YES;
+}
+
+- (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit
+{
+    WebFrame *frame = [self mainFrame];
+    unsigned matchCount = 0;
+    do {
+        id <WebDocumentView> view = [[frame frameView] documentView];
+        if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
+            [(NSView <WebMultipleTextMatches>*)view  setMarkedTextMatchesAreHighlighted:highlight];
+        
+            ASSERT(limit == 0 || matchCount < limit);
+            matchCount += [(NSView <WebMultipleTextMatches>*)view markAllMatchesForText:string caseSensitive:caseFlag limit:limit == 0 ? 0 : limit - matchCount];
+
+            // Stop looking if we've reached the limit. A limit of 0 means no limit.
+            if (limit > 0 && matchCount >= limit)
+                break;
+        }
+        
+        frame = incrementFrame(frame, YES, NO);
+    } while (frame);
+    
+    return matchCount;
+}
+
+- (void)unmarkAllTextMatches
+{
+    WebFrame *frame = [self mainFrame];
+    do {
+        id <WebDocumentView> view = [[frame frameView] documentView];
+        if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)])
+            [(NSView <WebMultipleTextMatches>*)view unmarkAllTextMatches];
+        
+        frame = incrementFrame(frame, YES, NO);
+    } while (frame);
+}
+
+- (NSArray *)rectsForTextMatches
+{
+    NSMutableArray *result = [NSMutableArray array];
+    WebFrame *frame = [self mainFrame];
+    do {
+        id <WebDocumentView> view = [[frame frameView] documentView];
+        if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
+            NSView <WebMultipleTextMatches> *documentView = (NSView <WebMultipleTextMatches> *)view;
+            NSRect documentViewVisibleRect = [documentView visibleRect];
+            NSArray *originalRects = [documentView rectsForTextMatches];
+            unsigned rectCount = [originalRects count];
+            unsigned rectIndex;
+            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+            for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
+                NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue];
+                // Clip rect to document view's visible rect so rect is confined to subframe
+                r = NSIntersectionRect(r, documentViewVisibleRect);
+                if (NSIsEmptyRect(r))
+                    continue;
+                
+                // Convert rect to our coordinate system
+                r = [documentView convertRect:r toView:self];
+                [result addObject:[NSValue valueWithRect:r]];
+                if (rectIndex % 10 == 0) {
+                    [pool drain];
+                    pool = [[NSAutoreleasePool alloc] init];
+                }
+            }
+            [pool drain];
+        }
+        
+        frame = incrementFrame(frame, YES, NO);
+    } while (frame);
+    
+    return result;
+}
+
+- (void)scrollDOMRangeToVisible:(DOMRange *)range
+{
+    [[[range startContainer] _bridge] scrollDOMRangeToVisible:range];
+}
+
+- (BOOL)allowsUndo
+{
+    return _private->allowsUndo;
+}
+
+- (void)setAllowsUndo:(BOOL)flag
+{
+    _private->allowsUndo = flag;
+}
+
+@end
+
+@implementation WebView (WebViewPrintingPrivate)
+
+- (float)_headerHeight
+{
+    return CallUIDelegateReturningFloat(self, @selector(webViewHeaderHeight:));
+}
+
+- (float)_footerHeight
+{
+    return CallUIDelegateReturningFloat(self, @selector(webViewFooterHeight:));
+}
+
+- (void)_drawHeaderInRect:(NSRect)rect
+{
+#ifdef DEBUG_HEADER_AND_FOOTER
+    NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
+    [currentContext saveGraphicsState];
+    [[NSColor yellowColor] set];
+    NSRectFill(rect);
+    [currentContext restoreGraphicsState];
+#endif
+
+    SEL selector = @selector(webView:drawHeaderInRect:);
+    if (![_private->UIDelegate respondsToSelector:selector])
+        return;
+
+    NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
+    [currentContext saveGraphicsState];
+
+    NSRectClip(rect);
+    CallUIDelegate(self, selector, rect);
+
+    [currentContext restoreGraphicsState];
+}
+
+- (void)_drawFooterInRect:(NSRect)rect
+{
+#ifdef DEBUG_HEADER_AND_FOOTER
+    NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
+    [currentContext saveGraphicsState];
+    [[NSColor cyanColor] set];
+    NSRectFill(rect);
+    [currentContext restoreGraphicsState];
+#endif
+    
+    SEL selector = @selector(webView:drawFooterInRect:);
+    if (![_private->UIDelegate respondsToSelector:selector])
+        return;
+
+    NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
+    [currentContext saveGraphicsState];
+
+    NSRectClip(rect);
+    CallUIDelegate(self, selector, rect);
+
+    [currentContext restoreGraphicsState];
+}
+
+- (void)_adjustPrintingMarginsForHeaderAndFooter
+{
+    NSPrintOperation *op = [NSPrintOperation currentOperation];
+    NSPrintInfo *info = [op printInfo];
+    NSMutableDictionary *infoDictionary = [info dictionary];
+    
+    // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the
+    // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087),
+    // we stash away the unmodified top and bottom margins the first time this method is called, and we read from
+    // those stashed-away values on subsequent calls.
+    float originalTopMargin;
+    float originalBottomMargin;
+    NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey];
+    if (!originalTopMarginNumber) {
+        ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]);
+        originalTopMargin = [info topMargin];
+        originalBottomMargin = [info bottomMargin];
+        [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey];
+        [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey];
+    } else {
+        ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]);
+        ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]);
+        originalTopMargin = [originalTopMarginNumber floatValue];
+        originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue];
+    }
+    
+    float scale = [op _web_pageSetupScaleFactor];
+    [info setTopMargin:originalTopMargin + [self _headerHeight] * scale];
+    [info setBottomMargin:originalBottomMargin + [self _footerHeight] * scale];
+}
+
+- (void)_drawHeaderAndFooter
+{
+    // The header and footer rect height scales with the page, but the width is always
+    // all the way across the printed page (inset by printing margins).
+    NSPrintOperation *op = [NSPrintOperation currentOperation];
+    float scale = [op _web_pageSetupScaleFactor];
+    NSPrintInfo *printInfo = [op printInfo];
+    NSSize paperSize = [printInfo paperSize];
+    float headerFooterLeft = [printInfo leftMargin]/scale;
+    float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale;
+    NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] , 
+                                   headerFooterWidth, [self _footerHeight]);
+    NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale, 
+                                   headerFooterWidth, [self _headerHeight]);
+    
+    [self _drawHeaderInRect:headerRect];
+    [self _drawFooterInRect:footerRect];
+}
+@end
+
+@implementation WebView (WebDebugBinding)
+
+- (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
+{
+    LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context);
+    [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
+}
+
+- (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
+{
+    LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath);
+    [super removeObserver:anObserver forKeyPath:keyPath];
+}
+
+@end
+
+//==========================================================================================
+// Editing
+
+@implementation WebView (WebViewCSS)
+
+- (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement
+{
+    // FIXME: is this the best level for this conversion?
+    if (pseudoElement == nil) {
+        pseudoElement = @"";
+    }
+    return [[element ownerDocument] getComputedStyle:element pseudoElement:pseudoElement];
+}
+
+@end
+
+@implementation WebView (WebViewEditing)
+
+- (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
+{
+    Page* page = core(self);
+    if (!page)
+        return nil;
+    return kit(page->mainFrame()->editor()->rangeForPoint(IntPoint([self convertPoint:point toView:nil])).get());
+}
+
+- (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag;
+{
+    // FIXME: This quirk is needed due to <rdar://problem/4985321> - 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 YES;
+    return [[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag];
+}
+
+- (BOOL)maintainsInactiveSelection
+{
+    return NO;
+}
+
+- (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity
+{
+    Frame* coreFrame = core([self _selectedOrMainFrame]);
+    if (!coreFrame)
+        return;
+
+    if (range == nil)
+        coreFrame->selectionController()->clear();
+    else {
+        // Derive the frame to use from the range passed in.
+        // Using _bridgeForSelectedOrMainFrame could give us a different document than
+        // the one the range uses.
+        coreFrame = core([range startContainer])->document()->frame();
+        if (!coreFrame)
+            return;
+
+        ExceptionCode ec = 0;
+        coreFrame->selectionController()->setSelectedRange([range _range], core(selectionAffinity), true, ec);
+    }
+}
+
+- (DOMRange *)selectedDOMRange
+{
+    Frame* coreFrame = core([self _selectedOrMainFrame]);
+    if (!coreFrame)
+        return nil;
+    return kit(coreFrame->selectionController()->toRange().get());
+}
+
+- (NSSelectionAffinity)selectionAffinity
+{
+    Frame* coreFrame = core([self _selectedOrMainFrame]);
+    if (!coreFrame)
+        return NSSelectionAffinityDownstream;
+    return kit(coreFrame->selectionController()->affinity());
+}
+
+- (void)setEditable:(BOOL)flag
+{
+    if (_private->editable != flag) {
+        _private->editable = flag;
+        if (!_private->tabKeyCyclesThroughElementsChanged && _private->page)
+            _private->page->setTabKeyCyclesThroughElements(!flag);
+        Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
+        if (mainFrame) {
+            if (flag) {
+                mainFrame->applyEditingStyleToBodyElement();
+                // If the WebView is made editable and the selection is empty, set it to something.
+                if (![self selectedDOMRange])
+                    mainFrame->setSelectionFromNone();
+            } else
+                mainFrame->removeEditingStyleFromBodyElement();
+        }
+    }
+}
+
+- (BOOL)isEditable
+{
+    return _private->editable;
+}
+
+- (void)setTypingStyle:(DOMCSSStyleDeclaration *)style
+{
+    // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
+    // change the API to allow this.
+    [[self _bridgeForSelectedOrMainFrame] setTypingStyle:style withUndoAction:EditActionUnspecified];
+}
+
+- (DOMCSSStyleDeclaration *)typingStyle
+{
+    return [[self _bridgeForSelectedOrMainFrame] typingStyle];
+}
+
+- (void)setSmartInsertDeleteEnabled:(BOOL)flag
+{
+    _private->smartInsertDeleteEnabled = flag;
+}
+
+- (BOOL)smartInsertDeleteEnabled
+{
+    return _private->smartInsertDeleteEnabled;
+}
+
+- (void)setContinuousSpellCheckingEnabled:(BOOL)flag
+{
+    if (continuousSpellCheckingEnabled != flag) {
+        continuousSpellCheckingEnabled = flag;
+        [[NSUserDefaults standardUserDefaults] setBool:continuousSpellCheckingEnabled forKey:WebContinuousSpellCheckingEnabled];
+    }
+    
+    if ([self isContinuousSpellCheckingEnabled]) {
+        [[self class] _preflightSpellChecker];
+    } else {
+        [[self mainFrame] _unmarkAllMisspellings];
+    }
+}
+
+- (BOOL)isContinuousSpellCheckingEnabled
+{
+    return (continuousSpellCheckingEnabled && [self _continuousCheckingAllowed]);
+}
+
+- (NSInteger)spellCheckerDocumentTag
+{
+    if (!_private->hasSpellCheckerDocumentTag) {
+        _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag];
+        _private->hasSpellCheckerDocumentTag = YES;
+    }
+    return _private->spellCheckerDocumentTag;
+}
+
+- (NSUndoManager *)undoManager
+{
+    if (!_private->allowsUndo)
+        return nil;
+
+    NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self];
+    if (undoManager)
+        return undoManager;
+
+    return [super undoManager];
+}
+
+- (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector
+{
+    NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
+    if ([_private->editingDelegate respondsToSelector:selector])
+        [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self];
+}
+
+- (void)setEditingDelegate:(id)delegate
+{
+    if (_private->editingDelegate == delegate)
+        return;
+
+    NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
+
+    // remove notifications from current delegate
+    [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidBeginEditingNotification object:self];
+    [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeNotification object:self];
+    [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidEndEditingNotification object:self];
+    [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeTypingStyleNotification object:self];
+    [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeSelectionNotification object:self];
+    
+    _private->editingDelegate = delegate;
+    [_private->editingDelegateForwarder release];
+    _private->editingDelegateForwarder = nil;
+    
+    // add notifications for new delegate
+    [self registerForEditingDelegateNotification:WebViewDidBeginEditingNotification selector:@selector(webViewDidBeginEditing:)];
+    [self registerForEditingDelegateNotification:WebViewDidChangeNotification selector:@selector(webViewDidChange:)];
+    [self registerForEditingDelegateNotification:WebViewDidEndEditingNotification selector:@selector(webViewDidEndEditing:)];
+    [self registerForEditingDelegateNotification:WebViewDidChangeTypingStyleNotification selector:@selector(webViewDidChangeTypingStyle:)];
+    [self registerForEditingDelegateNotification:WebViewDidChangeSelectionNotification selector:@selector(webViewDidChangeSelection:)];
+}
+
+- (id)editingDelegate
+{
+    return _private->editingDelegate;
+}
+
+- (DOMCSSStyleDeclaration *)styleDeclarationWithText:(NSString *)text
+{
+    // FIXME: Should this really be attached to the document with the current selection?
+    DOMCSSStyleDeclaration *decl = [[[self _selectedOrMainFrame] DOMDocument] createCSSStyleDeclaration];
+    [decl setCssText:text];
+    return decl;
+}
+
+@end
+
+@implementation WebView (WebViewGrammarChecking)
+
+// FIXME: This method should be merged into WebViewEditing when we're not in API freeze
+- (BOOL)isGrammarCheckingEnabled
+{
+#ifdef BUILDING_ON_TIGER
+    return NO;
+#else
+    return grammarCheckingEnabled;
+#endif
+}
+
+#ifndef BUILDING_ON_TIGER
+// FIXME: This method should be merged into WebViewEditing when we're not in API freeze
+- (void)setGrammarCheckingEnabled:(BOOL)flag
+{
+    if (grammarCheckingEnabled == flag)
+        return;
+    
+    grammarCheckingEnabled = flag;
+    [[NSUserDefaults standardUserDefaults] setBool:grammarCheckingEnabled forKey:WebGrammarCheckingEnabled];    
+    
+    // FIXME 4811447: workaround for lack of API
+    NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker];
+    if ([spellChecker respondsToSelector:@selector(_updateGrammar)])
+        [spellChecker performSelector:@selector(_updateGrammar)];
+    
+    // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
+    // because grammar checking only occurs on code paths that already preflight spell checking appropriately.
+    
+    if (![self isGrammarCheckingEnabled])
+        [[self mainFrame] _unmarkAllBadGrammar];
+}
+
+// FIXME: This method should be merged into WebIBActions when we're not in API freeze
+- (void)toggleGrammarChecking:(id)sender
+{
+    [self setGrammarCheckingEnabled:![self isGrammarCheckingEnabled]];
+}
+#endif
+
+@end
+
+@implementation WebView (WebViewUndoableEditing)
+
+- (void)replaceSelectionWithNode:(DOMNode *)node
+{
+    [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:NO];
+}    
+
+- (void)replaceSelectionWithText:(NSString *)text
+{
+    [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithText:text selectReplacement:YES smartReplace:NO];
+}
+
+- (void)replaceSelectionWithMarkupString:(NSString *)markupString
+{
+    [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithMarkupString:markupString baseURLString:nil selectReplacement:YES smartReplace:NO];
+}
+
+- (void)replaceSelectionWithArchive:(WebArchive *)archive
+{
+    [[[[self _bridgeForSelectedOrMainFrame] webFrame] _dataSource] _replaceSelectionWithArchive:archive selectReplacement:YES];
+}
+
+- (void)deleteSelection
+{
+    WebFrame *webFrame = [self _selectedOrMainFrame];
+    Frame* coreFrame = core(webFrame);
+    if (coreFrame)
+        coreFrame->editor()->deleteSelectionWithSmartDelete([(WebHTMLView *)[[webFrame frameView] documentView] _canSmartCopyOrDelete]);
+}
+    
+- (void)applyStyle:(DOMCSSStyleDeclaration *)style
+{
+    // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
+    // change the API to allow this.
+    WebFrame *webFrame = [self _selectedOrMainFrame];
+    Frame* coreFrame = core(webFrame);
+    if (coreFrame)
+        coreFrame->editor()->applyStyle(core(style));
+}
+
+@end
+
+@implementation WebView (WebViewEditingActions)
+
+- (void)_performResponderOperation:(SEL)selector with:(id)parameter
+{
+    static BOOL reentered = NO;
+    if (reentered) {
+        [[self nextResponder] tryToPerform:selector with:parameter];
+        return;
+    }
+
+    // There are two possibilities here.
+    //
+    // One is that WebView has been called in its role as part of the responder chain.
+    // In that case, it's fine to call the first responder and end up calling down the
+    // responder chain again. Later we will return here with reentered = YES and continue
+    // past the WebView.
+    //
+    // The other is that we are being called directly, in which case we want to pass the
+    // selector down to the view inside us that can handle it, and continue down the
+    // responder chain as usual.
+
+    // Pass this selector down to the first responder.
+    NSResponder *responder = [self _responderForResponderOperations];
+    reentered = YES;
+    [responder tryToPerform:selector with:parameter];
+    reentered = NO;
+}
+
+#define FORWARD(name) \
+    - (void)name:(id)sender { [self _performResponderOperation:_cmd with:sender]; }
+
+FOR_EACH_RESPONDER_SELECTOR(FORWARD)
+
+- (void)insertText:(NSString *)text
+{
+    [self _performResponderOperation:_cmd with:text];
+}
+
+@end
+
+@implementation WebView (WebViewEditingInMail)
+
+- (void)_insertNewlineInQuotedContent;
+{
+    [[self _bridgeForSelectedOrMainFrame] insertParagraphSeparatorInQuotedContent];
+}
+
+- (void)_replaceSelectionWithNode:(DOMNode *)node matchStyle:(BOOL)matchStyle
+{
+    [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:matchStyle];
+}
+
+@end
+
+static WebFrameView *containingFrameView(NSView *view)
+{
+    while (view && ![view isKindOfClass:[WebFrameView class]])
+        view = [view superview];
+    return (WebFrameView *)view;    
+}
+
+@implementation WebView (WebFileInternal)
+
++ (void)_setCacheModel:(WebCacheModel)cacheModel
+{
+    if (s_didSetCacheModel && cacheModel == s_cacheModel)
+        return;
+
+    NSString *nsurlCacheDirectory = [(NSString *)WKCopyFoundationCacheDirectory() autorelease];
+    if (!nsurlCacheDirectory)
+        nsurlCacheDirectory = NSHomeDirectory();
+
+    // As a fudge factor, use 1000 instead of 1024, in case the reported byte 
+    // count doesn't align exactly to a megabyte boundary.
+    vm_size_t memSize = WebMemorySize() / 1024 / 1000;
+    unsigned long long diskFreeSize = WebVolumeFreeSize(nsurlCacheDirectory) / 1024 / 1000;
+    NSURLCache *nsurlCache = [NSURLCache sharedURLCache];
+
+    unsigned cacheTotalCapacity = 0;
+    unsigned cacheMinDeadCapacity = 0;
+    unsigned cacheMaxDeadCapacity = 0;
+
+    unsigned pageCacheCapacity = 0;
+
+    NSUInteger nsurlCacheMemoryCapacity = 0;
+    NSUInteger nsurlCacheDiskCapacity = 0;
+
+    switch (cacheModel) {
+    case WebCacheModelDocumentViewer: {
+        // Page cache capacity (in pages)
+        pageCacheCapacity = 0;
+
+        // Object cache capacities (in bytes)
+        if (memSize >= 4096)
+            cacheTotalCapacity = 256 * 1024 * 1024;
+        else if (memSize >= 3072)
+            cacheTotalCapacity = 192 * 1024 * 1024;
+        else if (memSize >= 2048)
+            cacheTotalCapacity = 128 * 1024 * 1024;
+        else if (memSize >= 1536)
+            cacheTotalCapacity = 86 * 1024 * 1024;
+        else if (memSize >= 1024)
+            cacheTotalCapacity = 64 * 1024 * 1024;
+        else if (memSize >= 512)
+            cacheTotalCapacity = 32 * 1024 * 1024;
+        else if (memSize >= 256)
+            cacheTotalCapacity = 16 * 1024 * 1024; 
+
+        cacheMinDeadCapacity = 0;
+        cacheMaxDeadCapacity = 0;
+
+        // Foundation memory cache capacity (in bytes)
+        nsurlCacheMemoryCapacity = 0;
+
+        // Foundation disk cache capacity (in bytes)
+        nsurlCacheDiskCapacity = [nsurlCache diskCapacity];
+
+        break;
+    }
+    case WebCacheModelDocumentBrowser: {
+        // Page cache capacity (in pages)
+        if (memSize >= 1024)
+            pageCacheCapacity = 3;
+        else if (memSize >= 512)
+            pageCacheCapacity = 2;
+        else if (memSize >= 256)
+            pageCacheCapacity = 1;
+        else
+            pageCacheCapacity = 0;
+
+        // Object cache capacities (in bytes)
+        if (memSize >= 4096)
+            cacheTotalCapacity = 256 * 1024 * 1024;
+        else if (memSize >= 3072)
+            cacheTotalCapacity = 192 * 1024 * 1024;
+        else if (memSize >= 2048)
+            cacheTotalCapacity = 128 * 1024 * 1024;
+        else if (memSize >= 1536)
+            cacheTotalCapacity = 86 * 1024 * 1024;
+        else if (memSize >= 1024)
+            cacheTotalCapacity = 64 * 1024 * 1024;
+        else if (memSize >= 512)
+            cacheTotalCapacity = 32 * 1024 * 1024;
+        else if (memSize >= 256)
+            cacheTotalCapacity = 16 * 1024 * 1024; 
+
+        cacheMinDeadCapacity = cacheTotalCapacity / 8;
+        cacheMaxDeadCapacity = cacheTotalCapacity / 4;
+
+        // Foundation memory cache capacity (in bytes)
+        if (memSize >= 2048)
+            nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
+        else if (memSize >= 1024)
+            nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
+        else if (memSize >= 512)
+            nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
+        else
+            nsurlCacheMemoryCapacity =      512 * 1024; 
+
+        // Foundation disk cache capacity (in bytes)
+        if (diskFreeSize >= 16384)
+            nsurlCacheDiskCapacity = 50 * 1024 * 1024;
+        else if (diskFreeSize >= 8192)
+            nsurlCacheDiskCapacity = 40 * 1024 * 1024;
+        else if (diskFreeSize >= 4096)
+            nsurlCacheDiskCapacity = 30 * 1024 * 1024;
+        else
+            nsurlCacheDiskCapacity = 20 * 1024 * 1024;
+
+        break;
+    }
+    case WebCacheModelPrimaryWebBrowser: {
+        // Page cache capacity (in pages)
+        // (Research indicates that value / page drops substantially after 3 pages.)
+        if (memSize >= 8192)
+            pageCacheCapacity = 7;
+        if (memSize >= 4096)
+            pageCacheCapacity = 6;
+        else if (memSize >= 2048)
+            pageCacheCapacity = 5;
+        else if (memSize >= 1024)
+            pageCacheCapacity = 4;
+        else if (memSize >= 512)
+            pageCacheCapacity = 3;
+        else if (memSize >= 256)
+            pageCacheCapacity = 2;
+        else
+            pageCacheCapacity = 1;
+
+        // Object cache capacities (in bytes)
+        // (Testing indicates that value / MB depends heavily on content and
+        // browsing pattern. Even growth above 128MB can have substantial 
+        // value / MB for some content / browsing patterns.)
+        if (memSize >= 4096)
+            cacheTotalCapacity = 512 * 1024 * 1024;
+        else if (memSize >= 3072)
+            cacheTotalCapacity = 384 * 1024 * 1024;
+        else if (memSize >= 2048)
+            cacheTotalCapacity = 256 * 1024 * 1024;
+        else if (memSize >= 1536)
+            cacheTotalCapacity = 172 * 1024 * 1024;
+        else if (memSize >= 1024)
+            cacheTotalCapacity = 128 * 1024 * 1024;
+        else if (memSize >= 512)
+            cacheTotalCapacity = 64 * 1024 * 1024;
+        else if (memSize >= 256)
+            cacheTotalCapacity = 32 * 1024 * 1024; 
+
+        cacheMinDeadCapacity = cacheTotalCapacity / 4;
+        cacheMaxDeadCapacity = cacheTotalCapacity / 2;
+
+        // This code is here to avoid a PLT regression. We can remove it if we
+        // can prove that the overall system gain would justify the regression.
+        cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity);
+
+        // Foundation memory cache capacity (in bytes)
+        // (These values are small because WebCore does most caching itself.)
+        if (memSize >= 1024)
+            nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
+        else if (memSize >= 512)
+            nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
+        else if (memSize >= 256)
+            nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
+        else
+            nsurlCacheMemoryCapacity =      512 * 1024; 
+
+        // Foundation disk cache capacity (in bytes)
+        if (diskFreeSize >= 16384)
+            nsurlCacheDiskCapacity = 175 * 1024 * 1024;
+        else if (diskFreeSize >= 8192)
+            nsurlCacheDiskCapacity = 150 * 1024 * 1024;
+        else if (diskFreeSize >= 4096)
+            nsurlCacheDiskCapacity = 125 * 1024 * 1024;
+        else if (diskFreeSize >= 2048)
+            nsurlCacheDiskCapacity = 100 * 1024 * 1024;
+        else if (diskFreeSize >= 1024)
+            nsurlCacheDiskCapacity = 75 * 1024 * 1024;
+        else
+            nsurlCacheDiskCapacity = 50 * 1024 * 1024;
+
+        break;
+    }
+    default:
+        ASSERT_NOT_REACHED();
+    };
+
+#ifdef BUILDING_ON_TIGER
+    // Don't use a big Foundation disk cache on Tiger because, according to the 
+    // PLT, the Foundation disk cache on Tiger is slower than the network. 
+    nsurlCacheDiskCapacity = [[NSURLCache sharedURLCache] diskCapacity];
+#else
+    // Don't use a big Foundation disk cache on older versions of Leopard because
+    // doing so causes a SPOD on launch (<rdar://problem/5465260>).
+    if (NSVersionOfRunTimeLibrary("CFNetwork") < WEBKIT_FIRST_CFNETWORK_VERSION_WITH_LARGE_DISK_CACHE_FIX)
+        nsurlCacheDiskCapacity = [[NSURLCache sharedURLCache] diskCapacity];
+#endif
+
+    // Don't shrink a big disk cache, since that would cause churn.
+    nsurlCacheDiskCapacity = max(nsurlCacheDiskCapacity, [nsurlCache diskCapacity]);
+
+    cache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
+    pageCache()->setCapacity(pageCacheCapacity);
+    [nsurlCache setMemoryCapacity:nsurlCacheMemoryCapacity];
+    [nsurlCache setDiskCapacity:nsurlCacheDiskCapacity];
+
+    s_cacheModel = cacheModel;
+    s_didSetCacheModel = YES;
+}
+
++ (WebCacheModel)_cacheModel
+{
+    return s_cacheModel;
+}
+
++ (WebCacheModel)_didSetCacheModel
+{
+    return s_didSetCacheModel;
+}
+
++ (WebCacheModel)_maxCacheModelInAnyInstance
+{
+    WebCacheModel cacheModel = WebCacheModelDocumentViewer;
+    NSEnumerator *enumerator = [(NSMutableSet *)allWebViewsSet objectEnumerator];
+    while (WebPreferences *preferences = [[enumerator nextObject] preferences])
+        cacheModel = max(cacheModel, [preferences cacheModel]);
+    return cacheModel;
+}
+
++ (void)_preferencesChangedNotification:(NSNotification *)notification
+{
+    WebPreferences *preferences = (WebPreferences *)[notification object];
+    ASSERT([preferences isKindOfClass:[WebPreferences class]]);
+
+    WebCacheModel cacheModel = [preferences cacheModel];
+    if (![self _didSetCacheModel] || cacheModel > [self _cacheModel])
+        [self _setCacheModel:cacheModel];
+    else if (cacheModel < [self _cacheModel])
+        [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])];
+}
+
++ (void)_preferencesRemovedNotification:(NSNotification *)notification
+{
+    WebPreferences *preferences = (WebPreferences *)[notification object];
+    ASSERT([preferences isKindOfClass:[WebPreferences class]]);
+
+    if ([preferences cacheModel] == [self _cacheModel])
+        [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])];
+}
+
+- (WebFrame *)_focusedFrame
+{
+    NSResponder *resp = [[self window] firstResponder];
+    if (resp && [resp isKindOfClass:[NSView class]] && [(NSView *)resp isDescendantOf:[[self mainFrame] frameView]]) {
+        WebFrameView *frameView = containingFrameView((NSView *)resp);
+        ASSERT(frameView != nil);
+        return [frameView webFrame];
+    }
+    
+    return nil;
+}
+
+- (WebFrame *)_selectedOrMainFrame
+{
+    WebFrame *result = [self selectedFrame];
+    if (result == nil)
+        result = [self mainFrame];
+    return result;
+}
+
+- (WebFrameBridge *)_bridgeForSelectedOrMainFrame
+{
+    return [[self _selectedOrMainFrame] _bridge];
+}
+
+- (BOOL)_isLoading
+{
+    WebFrame *mainFrame = [self mainFrame];
+    return [[mainFrame _dataSource] isLoading]
+        || [[mainFrame provisionalDataSource] isLoading];
+}
+
+- (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point
+{
+    if (_private->closed)
+        return nil;
+    NSView *view = [self hitTest:[[self superview] convertPoint:point fromView:nil]];
+    if (![view isDescendantOf:[[self mainFrame] frameView]])
+        return nil;
+    WebFrameView *frameView = containingFrameView(view);
+    ASSERT(frameView);
+    return frameView;
+}
+
++ (void)_preflightSpellCheckerNow:(id)sender
+{
+    [[NSSpellChecker sharedSpellChecker] _preflightChosenSpellServer];
+}
+
++ (void)_preflightSpellChecker
+{
+    // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
+    if ([NSSpellChecker sharedSpellCheckerExists]) {
+        [self _preflightSpellCheckerNow:self];
+    } else {
+        [self performSelector:@selector(_preflightSpellCheckerNow:) withObject:self afterDelay:2.0];
+    }
+}
+
+- (BOOL)_continuousCheckingAllowed
+{
+    static BOOL allowContinuousSpellChecking = YES;
+    static BOOL readAllowContinuousSpellCheckingDefault = NO;
+    if (!readAllowContinuousSpellCheckingDefault) {
+        if ([[NSUserDefaults standardUserDefaults] objectForKey:@"NSAllowContinuousSpellChecking"]) {
+            allowContinuousSpellChecking = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSAllowContinuousSpellChecking"];
+        }
+        readAllowContinuousSpellCheckingDefault = YES;
+    }
+    return allowContinuousSpellChecking;
+}
+
+- (NSResponder *)_responderForResponderOperations
+{
+    NSResponder *responder = [[self window] firstResponder];
+    WebFrameView *mainFrameView = [[self mainFrame] frameView];
+    
+    // If the current responder is outside of the webview, use our main frameView or its
+    // document view. We also do this for subviews of self that are siblings of the main
+    // frameView since clients might insert non-webview-related views there (see 4552713).
+    if (responder != self && ![mainFrameView _web_firstResponderIsSelfOrDescendantView]) {
+        responder = [mainFrameView documentView];
+        if (!responder)
+            responder = mainFrameView;
+    }
+    return responder;
+}
+
+- (void)_openFrameInNewWindowFromMenu:(NSMenuItem *)sender
+{
+    ASSERT_ARG(sender, [sender isKindOfClass:[NSMenuItem class]]);
+
+    NSDictionary *element = [sender representedObject];
+    ASSERT([element isKindOfClass:[NSDictionary class]]);
+    
+    NSURLRequest *request = [[[[element objectForKey:WebElementFrameKey] dataSource] request] copy];
+    ASSERT(request);
+    
+    [self _openNewWindowWithRequest:request];
+    [request release];
+}
+
+- (void)_searchWithGoogleFromMenu:(id)sender
+{
+    id documentView = [[[self selectedFrame] frameView] documentView];
+    if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) {
+        return;
+    }
+    
+    NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
+    if ([selectedString length] == 0) {
+        return;
+    }
+    
+    NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
+    [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
+    NSMutableString *s = [selectedString mutableCopy];
+    const unichar nonBreakingSpaceCharacter = 0xA0;
+    NSString *nonBreakingSpaceString = [NSString stringWithCharacters:&nonBreakingSpaceCharacter length:1];
+    [s replaceOccurrencesOfString:nonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
+    [pasteboard setString:s forType:NSStringPboardType];
+    [s release];
+    
+    // FIXME: seems fragile to use the service by name, but this is what AppKit does
+    NSPerformService(@"Search With Google", pasteboard);
+}
+
+- (void)_searchWithSpotlightFromMenu:(id)sender
+{
+    id documentView = [[[self selectedFrame] frameView] documentView];
+    if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) {
+        return;
+    }
+    
+    NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
+    if ([selectedString length] == 0) {
+        return;
+    }
+
+    (void)HISearchWindowShow((CFStringRef)selectedString, kNilOptions);
+}
+
+// Slightly funky method that lets us have one copy of the logic for finding docViews that can do
+// text sizing.  It returns whether it found any "suitable" doc views.  It sends sel to any suitable
+// doc views, or if sel==0 we do nothing to them.  For doc views that track our size factor, they are
+// suitable if doTrackingViews==YES (which in practice means that our size factor isn't at its max or
+// min).  For doc views that don't track it, we send them testSel to determine suitablility.  If we
+// do find any suitable tracking doc views and newScaleFactor!=0, we will set the common scale factor
+// to that new factor before we send sel to any of them. 
+- (BOOL)_performTextSizingSelector:(SEL)sel withObject:(id)arg onTrackingDocs:(BOOL)doTrackingViews selForNonTrackingDocs:(SEL)testSel newScaleFactor:(float)newScaleFactor
+{
+    if ([[self mainFrame] _dataSource] == nil)
+        return NO;
+    
+    BOOL foundSome = NO;
+    NSArray *docViews = [[self mainFrame] _documentViews];
+    for (int i = [docViews count]-1; i >= 0; i--) {
+        id docView = [docViews objectAtIndex:i];
+        if ([docView conformsToProtocol:@protocol(_WebDocumentTextSizing)]) {
+            id <_WebDocumentTextSizing> sizingDocView = (id <_WebDocumentTextSizing>)docView;
+            BOOL isSuitable;
+            if ([sizingDocView _tracksCommonSizeFactor]) {
+                isSuitable = doTrackingViews;
+                if (isSuitable && newScaleFactor != 0)
+                    _private->textSizeMultiplier = newScaleFactor;
+            } else {
+                // Incantation to perform a selector returning a BOOL.
+                isSuitable = ((BOOL(*)(id, SEL))objc_msgSend)(sizingDocView, testSel);
+            }
+            
+            if (isSuitable) {
+                if (sel != 0) {
+                    foundSome = YES;
+                    [sizingDocView performSelector:sel withObject:arg];
+                } else {
+                    // if we're just called for the benefit of the return value, we can return at first match
+                    return YES;
+                }
+            }
+        }
+    }
+    
+    return foundSome;
+}
+
+- (void)_notifyTextSizeMultiplierChanged
+{
+    if ([[self mainFrame] _dataSource] == nil)
+        return;
+
+    NSArray *docViews = [[self mainFrame] _documentViews];
+    for (int i = [docViews count]-1; i >= 0; i--) {
+        id docView = [docViews objectAtIndex:i];
+        if ([docView conformsToProtocol:@protocol(_WebDocumentTextSizing)] == NO)
+            continue;
+
+        id <_WebDocumentTextSizing> sizingDocView = (id <_WebDocumentTextSizing>)docView;
+        if ([sizingDocView _tracksCommonSizeFactor])
+            [sizingDocView _textSizeMultiplierChanged];
+    }
+
+}
+
+@end
+
+@implementation WebView (WebViewInternal)
+
+- (BOOL)_becomingFirstResponderFromOutside
+{
+    return _private->becomingFirstResponderFromOutside;
+}
+
+- (void)_receivedIconChangedNotification:(NSNotification *)notification
+{
+    // Get the URL for this notification
+    NSDictionary *userInfo = [notification userInfo];
+    ASSERT([userInfo isKindOfClass:[NSDictionary class]]);
+    NSString *urlString = [userInfo objectForKey:WebIconNotificationUserInfoURLKey];
+    ASSERT([urlString isKindOfClass:[NSString class]]);
+    
+    // If that URL matches the current main frame, dispatch the delegate call, which will also unregister
+    // us for this notification
+    if ([[self mainFrameURL] isEqualTo:urlString])
+        [self _dispatchDidReceiveIconFromWebFrame:[self mainFrame]];
+}
+
+- (void)_registerForIconNotification:(BOOL)listen
+{
+    if (listen)
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_receivedIconChangedNotification:) name:WebIconDatabaseDidAddIconNotification object:nil];        
+    else
+        [[NSNotificationCenter defaultCenter] removeObserver:self name:WebIconDatabaseDidAddIconNotification object:nil];
+}
+
+- (void)_dispatchDidReceiveIconFromWebFrame:(WebFrame *)webFrame
+{
+    // FIXME: This willChangeValueForKey call is too late, because the icon has already changed by now.
+    [self _willChangeValueForKey:_WebMainFrameIconKey];
+    
+    // Since we definitely have an icon and are about to send out the delegate call for that, this WebView doesn't need to listen for the general
+    // notification any longer
+    [self _registerForIconNotification:NO];
+
+    WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(self);
+    if (implementations.didReceiveIconForFrameFunc) {
+        Image* image = iconDatabase()->iconForPageURL(core(webFrame)->loader()->url().url(), IntSize(16, 16));
+        if (NSImage *icon = webGetNSImage(image, NSMakeSize(16, 16)))
+            CallFrameLoadDelegate(implementations.didReceiveIconForFrameFunc, self, @selector(webView:didReceiveIcon:forFrame:), icon, webFrame);
+    }
+
+    [self _didChangeValueForKey:_WebMainFrameIconKey];
+}
+
+- (NSString *)_userVisibleBundleVersionFromFullVersion:(NSString *)fullVersion
+{
+    // If the version is 4 digits long or longer, then the first digit represents
+    // the version of the OS. Our user agent string should not include this first digit,
+    // so strip it off and report the rest as the version. <rdar://problem/4997547>
+    NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
+    if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4)
+        return [fullVersion substringFromIndex:1];
+    if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4)
+        return [fullVersion substringFromIndex:1];
+    return fullVersion;
+}
+
+- (NSString *)_userAgentWithApplicationName:(NSString *)applicationName andWebKitVersion:(NSString *)version
+{
+    NSString *language = [NSUserDefaults _webkit_preferredLanguageCode];
+    if ([applicationName length])
+        return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X; %@) AppleWebKit/%@ (KHTML, like Gecko) %@", language, version, applicationName];
+    return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X; %@) AppleWebKit/%@ (KHTML, like Gecko)", language, version];
+}
+
+// Get the appropriate user-agent string for a particular URL.
+- (WebCore::String)_userAgentForURL:(const WebCore::KURL&)url
+{
+    if (_private->useSiteSpecificSpoofing) {
+        // FIXME: Make this a hash table lookup if more domains need spoofing.
+        // FIXME: Remove yahoo.com once <rdar://problem/5057117> is fixed.
+        if (url.host().endsWith("yahoo.com")) {
+            static String yahooUserAgent([self _userAgentWithApplicationName:_private->applicationNameForUserAgent andWebKitVersion:@"422"]);
+            return yahooUserAgent;
+        }
+        
+        // FIXME: Remove flickr.com workaround once <rdar://problem/5084872> is fixed
+        if (url.host().endsWith("flickr.com")) {
+            // Safari 2.0.4's user agent string works here
+            static String safari204UserAgent([self _userAgentWithApplicationName:@"Safari/419.3" andWebKitVersion:@"419"]);
+            return safari204UserAgent;
+        }
+    }
+    
+    if (_private->userAgent->isNull()) {
+        NSString *sourceVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
+        sourceVersion = [self _userVisibleBundleVersionFromFullVersion:sourceVersion];
+        *_private->userAgent = [self _userAgentWithApplicationName:_private->applicationNameForUserAgent andWebKitVersion:sourceVersion];
+    }
+
+    return *_private->userAgent;
+}
+
+- (void)_addObject:(id)object forIdentifier:(unsigned long)identifier
+{
+    ASSERT(!_private->identifierMap->contains(identifier));
+
+    // If the identifier map is initially empty it means we're starting a load
+    // of something. The semantic is that the web view should be around as long 
+    // as something is loading. Because of that we retain the web view.
+    if (_private->identifierMap->isEmpty())
+        CFRetain(self);
+    
+    _private->identifierMap->set(identifier, object);
+}
+
+- (id)_objectForIdentifier:(unsigned long)identifier
+{
+    return _private->identifierMap->get(identifier).get();
+}
+
+- (void)_removeObjectForIdentifier:(unsigned long)identifier
+{
+    HashMap<unsigned long, RetainPtr<id> >::iterator it = _private->identifierMap->find(identifier);
+    
+    // FIXME: This is currently needed because of a bug that causes didFail to be sent twice 
+    // sometimes, see <rdar://problem/5009627> for more information.
+    if (it == _private->identifierMap->end())
+        return;
+    
+    _private->identifierMap->remove(it);
+    
+    // If the identifier map is now empty it means we're no longer loading anything
+    // and we should release the web view.
+    if (_private->identifierMap->isEmpty())
+        CFRelease(self);
+}
+
+@end
+
+// We use these functions to call the delegates and block exceptions. These functions are
+// declared inside a WebView category to get direct access to the delegate data memebers,
+// preventing more ObjC message dispatch and compensating for the expense of the @try/@catch.
+
+@implementation WebView (WebCallDelegateFunctions)
+
+#if !(defined(__i386__) || defined(__x86_64__))
+typedef double (*ObjCMsgSendFPRet)(id, SEL, ...);
+static const ObjCMsgSendFPRet objc_msgSend_fpret = reinterpret_cast<ObjCMsgSendFPRet>(objc_msgSend);
+#endif
+
+static inline id CallDelegate(WebView *self, id delegate, SEL selector)
+{
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return objc_msgSend(delegate, selector, self);
+    @try {
+        return objc_msgSend(delegate, selector, self);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object)
+{
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return objc_msgSend(delegate, selector, self, object);
+    @try {
+        return objc_msgSend(delegate, selector, self, object);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(WebView *self, id delegate, SEL selector, NSRect rect)
+{
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return reinterpret_cast<id (*)(id, SEL, WebView *, NSRect)>(objc_msgSend)(delegate, selector, self, rect);
+    @try {
+        return reinterpret_cast<id (*)(id, SEL, WebView *, NSRect)>(objc_msgSend)(delegate, selector, self, rect);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object1, id object2)
+{
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return objc_msgSend(delegate, selector, self, object1, object2);
+    @try {
+        return objc_msgSend(delegate, selector, self, object1, object2);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object, BOOL boolean)
+{
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return objc_msgSend(delegate, selector, self, object, boolean);
+    @try {
+        return objc_msgSend(delegate, selector, self, object, boolean);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object1, id object2, id object3)
+{
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return objc_msgSend(delegate, selector, self, object1, object2, object3);
+    @try {
+        return objc_msgSend(delegate, selector, self, object1, object2, object3);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object, NSUInteger integer)
+{
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return objc_msgSend(delegate, selector, self, object, integer);
+    @try {
+        return objc_msgSend(delegate, selector, self, object, integer);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline float CallDelegateReturningFloat(WebView *self, id delegate, SEL selector)
+{
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return 0.0f;
+    if (!self->_private->catchesDelegateExceptions)
+        return static_cast<float>(objc_msgSend_fpret(delegate, selector, self));
+    @try {
+        return static_cast<float>(objc_msgSend_fpret(delegate, selector, self));
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return 0.0f;
+}
+
+static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector)
+{
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return result;
+    if (!self->_private->catchesDelegateExceptions)
+        return reinterpret_cast<BOOL (*)(id, SEL, WebView *)>(objc_msgSend)(delegate, selector, self);
+    @try {
+        return reinterpret_cast<BOOL (*)(id, SEL, WebView *)>(objc_msgSend)(delegate, selector, self);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return result;
+}
+
+static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object)
+{
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return result;
+    if (!self->_private->catchesDelegateExceptions)
+        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(delegate, selector, self, object);
+    @try {
+        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(delegate, selector, self, object);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return result;
+}
+
+static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object, BOOL boolean)
+{
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return result;
+    if (!self->_private->catchesDelegateExceptions)
+        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL)>(objc_msgSend)(delegate, selector, self, object, boolean);
+    @try {
+        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL)>(objc_msgSend)(delegate, selector, self, object, boolean);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return result;
+}
+
+static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object1, id object2)
+{
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return result;
+    if (!self->_private->catchesDelegateExceptions)
+        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(delegate, selector, self, object1, object2);
+    @try {
+        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(delegate, selector, self, object1, object2);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return result;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector)
+{
+    if (!delegate)
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return implementation(delegate, selector, self);
+    @try {
+        return implementation(delegate, selector, self);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object)
+{
+    if (!delegate)
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return implementation(delegate, selector, self, object);
+    @try {
+        return implementation(delegate, selector, self, object);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2)
+{
+    if (!delegate)
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return implementation(delegate, selector, self, object1, object2);
+    @try {
+        return implementation(delegate, selector, self, object1, object2);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, id object3)
+{
+    if (!delegate)
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return implementation(delegate, selector, self, object1, object2, object3);
+    @try {
+        return implementation(delegate, selector, self, object1, object2, object3);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, id object3, id object4)
+{
+    if (!delegate)
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return implementation(delegate, selector, self, object1, object2, object3, object4);
+    @try {
+        return implementation(delegate, selector, self, object1, object2, object3, object4);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer, id object2)
+{
+    if (!delegate)
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return implementation(delegate, selector, self, object1, integer, object2);
+    @try {
+        return implementation(delegate, selector, self, object1, integer, object2);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, NSInteger integer, id object3)
+{
+    if (!delegate)
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return implementation(delegate, selector, self, object1, object2, integer, object3);
+    @try {
+        return implementation(delegate, selector, self, object1, object2, integer, object3);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSTimeInterval interval, id object2, id object3)
+{
+    if (!delegate)
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return implementation(delegate, selector, self, object1, interval, object2, object3);
+    @try {
+        return implementation(delegate, selector, self, object1, interval, object2, object3);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+id CallUIDelegate(WebView *self, SEL selector)
+{
+    return CallDelegate(self, self->_private->UIDelegate, selector);
+}
+
+id CallUIDelegate(WebView *self, SEL selector, id object)
+{
+    return CallDelegate(self, self->_private->UIDelegate, selector, object);
+}
+
+id CallUIDelegate(WebView *self, SEL selector, id object, BOOL boolean)
+{
+    return CallDelegate(self, self->_private->UIDelegate, selector, object, boolean);
+}
+
+id CallUIDelegate(WebView *self, SEL selector, NSRect rect)
+{
+    return CallDelegate(self, self->_private->UIDelegate, selector, rect);
+}
+
+id CallUIDelegate(WebView *self, SEL selector, id object1, id object2)
+{
+    return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2);
+}
+
+id CallUIDelegate(WebView *self, SEL selector, id object1, id object2, id object3)
+{
+    return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2, object3);
+}
+
+id CallUIDelegate(WebView *self, SEL selector, id object, NSUInteger integer)
+{
+    return CallDelegate(self, self->_private->UIDelegate, selector, object, integer);
+}
+
+float CallUIDelegateReturningFloat(WebView *self, SEL selector)
+{
+    return CallDelegateReturningFloat(self, self->_private->UIDelegate, selector);
+}
+
+BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector)
+{
+    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector);
+}
+
+BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object)
+{
+    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object);
+}
+
+BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object, BOOL boolean)
+{
+    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object, boolean);
+}
+
+BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, id object2)
+{
+    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object1, object2);
+}
+
+id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector)
+{
+    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector);
+}
+
+id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object)
+{
+    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object);
+}
+
+id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
+{
+    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2);
+}
+
+id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
+{
+    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3);
+}
+
+id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
+{
+    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3, object4);
+}
+
+id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSTimeInterval interval, id object2, id object3)
+{
+    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, interval, object2, object3);
+}
+
+id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
+{
+    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2);
+}
+
+id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
+{
+    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3);
+}
+
+id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
+{
+    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3, object4);
+}
+
+id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2)
+{
+    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, integer, object2);
+}
+
+id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3)
+{
+    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, integer, object3);
+}
+
+// The form delegate needs to have it's own implementation, because the first argument is never the WebView
+
+id CallFormDelegate(WebView *self, SEL selector, id object1, id object2)
+{
+    id delegate = self->_private->formDelegate;
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return objc_msgSend(delegate, selector, object1, object2);
+    @try {
+        return objc_msgSend(delegate, selector, object1, object2);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+id CallFormDelegate(WebView *self, SEL selector, id object1, id object2, id object3, id object4, id object5)
+{
+    id delegate = self->_private->formDelegate;
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return nil;
+    if (!self->_private->catchesDelegateExceptions)
+        return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5);
+    @try {
+        return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return nil;
+}
+
+BOOL CallFormDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, SEL selectorArg, id object2)
+{
+    id delegate = self->_private->formDelegate;
+    if (!delegate || ![delegate respondsToSelector:selector])
+        return result;
+    if (!self->_private->catchesDelegateExceptions)
+        return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2);
+    @try {
+        return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2);
+    } @catch(id exception) {
+        ReportDiscardedDelegateException(selector, exception);
+    }
+    return result;
+}
+
+@end