webengine/osswebengine/WebKit/WebView/WebView.mm
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
       
     3  * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
       
     4  *
       
     5  * Redistribution and use in source and binary forms, with or without
       
     6  * modification, are permitted provided that the following conditions
       
     7  * are met:
       
     8  *
       
     9  * 1.  Redistributions of source code must retain the above copyright
       
    10  *     notice, this list of conditions and the following disclaimer. 
       
    11  * 2.  Redistributions in binary form must reproduce the above copyright
       
    12  *     notice, this list of conditions and the following disclaimer in the
       
    13  *     documentation and/or other materials provided with the distribution. 
       
    14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
       
    15  *     its contributors may be used to endorse or promote products derived
       
    16  *     from this software without specific prior written permission. 
       
    17  *
       
    18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
       
    19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       
    21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
       
    22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
       
    23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
       
    24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       
    25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
       
    27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    28  */
       
    29 
       
    30 #import "WebViewInternal.h"
       
    31 
       
    32 #import "DOMRangeInternal.h"
       
    33 #import "WebBackForwardList.h"
       
    34 #import "WebBackForwardListInternal.h"
       
    35 #import "WebBaseNetscapePluginView.h"
       
    36 #import "WebChromeClient.h"
       
    37 #import "WebContextMenuClient.h"
       
    38 #import "WebDOMOperationsPrivate.h"
       
    39 #import "WebDashboardRegion.h"
       
    40 #import "WebDataSourceInternal.h"
       
    41 #import "WebDefaultEditingDelegate.h"
       
    42 #import "WebDefaultPolicyDelegate.h"
       
    43 #import "WebDefaultScriptDebugDelegate.h"
       
    44 #import "WebDefaultUIDelegate.h"
       
    45 #import "WebDocument.h"
       
    46 #import "WebDocumentInternal.h"
       
    47 #import "WebDownload.h"
       
    48 #import "WebDownloadInternal.h"
       
    49 #import "WebDragClient.h"
       
    50 #import "WebDynamicScrollBarsView.h"
       
    51 #import "WebEditingDelegate.h"
       
    52 #import "WebEditorClient.h"
       
    53 #import "WebFormDelegatePrivate.h"
       
    54 #import "WebFrameBridge.h"
       
    55 #import "WebFrameInternal.h"
       
    56 #import "WebFrameViewInternal.h"
       
    57 #import "WebHTMLRepresentation.h"
       
    58 #import "WebHTMLViewInternal.h"
       
    59 #import "WebHistoryItemInternal.h"
       
    60 #import "WebIconDatabase.h"
       
    61 #import "WebIconDatabaseInternal.h"
       
    62 #import "WebInspectorClient.h"
       
    63 #import "WebKitErrors.h"
       
    64 #import "WebKitLogging.h"
       
    65 #import "WebKitNSStringExtras.h"
       
    66 #import "WebKitStatisticsPrivate.h"
       
    67 #import "WebKitSystemBits.h"
       
    68 #import "WebKitVersionChecks.h"
       
    69 #import "WebLocalizableStrings.h"
       
    70 #import "WebNSDataExtras.h"
       
    71 #import "WebNSDataExtrasPrivate.h"
       
    72 #import "WebNSDictionaryExtras.h"
       
    73 #import "WebNSEventExtras.h"
       
    74 #import "WebNSObjectExtras.h"
       
    75 #import "WebNSPasteboardExtras.h"
       
    76 #import "WebNSPrintOperationExtras.h"
       
    77 #import "WebNSURLExtras.h"
       
    78 #import "WebNSURLRequestExtras.h"
       
    79 #import "WebNSUserDefaultsExtras.h"
       
    80 #import "WebNSViewExtras.h"
       
    81 #import "WebPanelAuthenticationHandler.h"
       
    82 #import "WebPasteboardHelper.h"
       
    83 #import "WebPDFView.h"
       
    84 #import "WebPluginDatabase.h"
       
    85 #import "WebPolicyDelegate.h"
       
    86 #import "WebPreferenceKeysPrivate.h"
       
    87 #import "WebPreferencesPrivate.h"
       
    88 #import "WebScriptDebugDelegatePrivate.h"
       
    89 #import "WebScriptDebugServerPrivate.h"
       
    90 #import "WebUIDelegate.h"
       
    91 #import "WebUIDelegatePrivate.h"
       
    92 #import <CoreFoundation/CFSet.h>
       
    93 #import <Foundation/NSURLConnection.h>
       
    94 #import <JavaScriptCore/Assertions.h>
       
    95 #import <WebCore/Cache.h>
       
    96 #import <WebCore/ColorMac.h>
       
    97 #import <WebCore/Document.h>
       
    98 #import <WebCore/DocumentLoader.h>
       
    99 #import <WebCore/DragController.h>
       
   100 #import <WebCore/DragData.h>
       
   101 #import <WebCore/Editor.h>
       
   102 #import <WebCore/ExceptionHandlers.h>
       
   103 #import <WebCore/Frame.h>
       
   104 #import <WebCore/FrameLoader.h>
       
   105 #import <WebCore/FrameTree.h>
       
   106 #import <WebCore/HTMLNames.h>
       
   107 #import <WebCore/HistoryItem.h>
       
   108 #import <WebCore/Logging.h>
       
   109 #import <WebCore/MIMETypeRegistry.h>
       
   110 #import <WebCore/Page.h>
       
   111 #import <WebCore/PageCache.h>
       
   112 #import <WebCore/PlatformMouseEvent.h>
       
   113 #import <WebCore/ProgressTracker.h>
       
   114 #import <WebCore/SelectionController.h>
       
   115 #import <WebCore/Settings.h>
       
   116 #import <WebCore/TextResourceDecoder.h>
       
   117 #import <WebCore/WebCoreFrameBridge.h>
       
   118 #import <WebCore/WebCoreObjCExtras.h>
       
   119 #import <WebCore/WebCoreTextRenderer.h>
       
   120 #import <WebCore/WebCoreView.h>
       
   121 #import <WebKit/DOM.h>
       
   122 #import <WebKit/DOMExtensions.h>
       
   123 #import <WebKit/DOMPrivate.h>
       
   124 #import <WebKitSystemInterface.h>
       
   125 #import <mach-o/dyld.h>
       
   126 #import <objc/objc-runtime.h>
       
   127 #import <wtf/RefPtr.h>
       
   128 #import <wtf/HashTraits.h>
       
   129 
       
   130 using namespace WebCore;
       
   131 
       
   132 #if defined(__ppc__) || defined(__ppc64__)
       
   133 #define PROCESSOR "PPC"
       
   134 #elif defined(__i386__) || defined(__x86_64__)
       
   135 #define PROCESSOR "Intel"
       
   136 #else
       
   137 #error Unknown architecture
       
   138 #endif
       
   139 
       
   140 #define FOR_EACH_RESPONDER_SELECTOR(macro) \
       
   141 macro(alignCenter) \
       
   142 macro(alignJustified) \
       
   143 macro(alignLeft) \
       
   144 macro(alignRight) \
       
   145 macro(capitalizeWord) \
       
   146 macro(centerSelectionInVisibleArea) \
       
   147 macro(changeAttributes) \
       
   148 macro(changeColor) \
       
   149 macro(changeDocumentBackgroundColor) \
       
   150 macro(changeFont) \
       
   151 macro(checkSpelling) \
       
   152 macro(complete) \
       
   153 macro(copy) \
       
   154 macro(copyFont) \
       
   155 macro(cut) \
       
   156 macro(delete) \
       
   157 macro(deleteBackward) \
       
   158 macro(deleteBackwardByDecomposingPreviousCharacter) \
       
   159 macro(deleteForward) \
       
   160 macro(deleteToBeginningOfLine) \
       
   161 macro(deleteToBeginningOfParagraph) \
       
   162 macro(deleteToEndOfLine) \
       
   163 macro(deleteToEndOfParagraph) \
       
   164 macro(deleteWordBackward) \
       
   165 macro(deleteWordForward) \
       
   166 macro(ignoreSpelling) \
       
   167 macro(indent) \
       
   168 macro(insertBacktab) \
       
   169 macro(insertNewline) \
       
   170 macro(insertNewlineIgnoringFieldEditor) \
       
   171 macro(insertParagraphSeparator) \
       
   172 macro(insertTab) \
       
   173 macro(insertTabIgnoringFieldEditor) \
       
   174 macro(lowercaseWord) \
       
   175 macro(moveBackward) \
       
   176 macro(moveBackwardAndModifySelection) \
       
   177 macro(moveDown) \
       
   178 macro(moveDownAndModifySelection) \
       
   179 macro(moveForward) \
       
   180 macro(moveForwardAndModifySelection) \
       
   181 macro(moveLeft) \
       
   182 macro(moveLeftAndModifySelection) \
       
   183 macro(moveRight) \
       
   184 macro(moveRightAndModifySelection) \
       
   185 macro(moveToBeginningOfDocument) \
       
   186 macro(moveToBeginningOfDocumentAndModifySelection) \
       
   187 macro(moveToBeginningOfSentence) \
       
   188 macro(moveToBeginningOfSentenceAndModifySelection) \
       
   189 macro(moveToBeginningOfLine) \
       
   190 macro(moveToBeginningOfLineAndModifySelection) \
       
   191 macro(moveToBeginningOfParagraph) \
       
   192 macro(moveToBeginningOfParagraphAndModifySelection) \
       
   193 macro(moveToEndOfDocument) \
       
   194 macro(moveToEndOfDocumentAndModifySelection) \
       
   195 macro(moveToEndOfLine) \
       
   196 macro(moveToEndOfLineAndModifySelection) \
       
   197 macro(moveToEndOfParagraph) \
       
   198 macro(moveToEndOfParagraphAndModifySelection) \
       
   199 macro(moveToEndOfSentence) \
       
   200 macro(moveToEndOfSentenceAndModifySelection) \
       
   201 macro(moveUp) \
       
   202 macro(moveUpAndModifySelection) \
       
   203 macro(moveWordBackward) \
       
   204 macro(moveWordBackwardAndModifySelection) \
       
   205 macro(moveWordForward) \
       
   206 macro(moveWordForwardAndModifySelection) \
       
   207 macro(moveWordLeft) \
       
   208 macro(moveWordLeftAndModifySelection) \
       
   209 macro(moveWordRight) \
       
   210 macro(moveWordRightAndModifySelection) \
       
   211 macro(outdent) \
       
   212 macro(pageDown) \
       
   213 macro(pageUp) \
       
   214 macro(paste) \
       
   215 macro(pasteAsPlainText) \
       
   216 macro(pasteAsRichText) \
       
   217 macro(pasteFont) \
       
   218 macro(performFindPanelAction) \
       
   219 macro(scrollLineDown) \
       
   220 macro(scrollLineUp) \
       
   221 macro(scrollPageDown) \
       
   222 macro(scrollPageUp) \
       
   223 macro(scrollToBeginningOfDocument) \
       
   224 macro(scrollToEndOfDocument) \
       
   225 macro(selectAll) \
       
   226 macro(selectWord) \
       
   227 macro(selectSentence) \
       
   228 macro(selectLine) \
       
   229 macro(selectParagraph) \
       
   230 macro(showGuessPanel) \
       
   231 macro(startSpeaking) \
       
   232 macro(stopSpeaking) \
       
   233 macro(subscript) \
       
   234 macro(superscript) \
       
   235 macro(underline) \
       
   236 macro(unscript) \
       
   237 macro(uppercaseWord) \
       
   238 macro(yank) \
       
   239 macro(yankAndSelect) \
       
   240 
       
   241 #define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin"
       
   242 #define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin"
       
   243 
       
   244 static BOOL s_didSetCacheModel;
       
   245 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer;
       
   246 
       
   247 static BOOL applicationIsTerminating;
       
   248 static int pluginDatabaseClientCount = 0;
       
   249 
       
   250 @interface NSSpellChecker (AppKitSecretsIKnow)
       
   251 - (void)_preflightChosenSpellServer;
       
   252 @end
       
   253 
       
   254 @interface NSView (AppKitSecretsIKnow)
       
   255 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types;
       
   256 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta;
       
   257 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo;
       
   258 @end
       
   259 
       
   260 @interface NSWindow (AppKitSecretsIKnow) 
       
   261 - (id)_oldFirstResponderBeforeBecoming;
       
   262 @end
       
   263 
       
   264 @interface NSObject (ValidateWithoutDelegate)
       
   265 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item;
       
   266 @end
       
   267 
       
   268 @interface _WebSafeForwarder : NSObject
       
   269 {
       
   270     id target; // Non-retained. Don't retain delegates.
       
   271     id defaultTarget;
       
   272     BOOL catchExceptions;
       
   273 }
       
   274 - (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions;
       
   275 @end
       
   276 
       
   277 @interface WebViewPrivate : NSObject
       
   278 {
       
   279 @public
       
   280     Page* page;
       
   281     
       
   282     id UIDelegate;
       
   283     id UIDelegateForwarder;
       
   284     id resourceProgressDelegate;
       
   285     id downloadDelegate;
       
   286     id policyDelegate;
       
   287     id policyDelegateForwarder;
       
   288     id frameLoadDelegate;
       
   289     id frameLoadDelegateForwarder;
       
   290     id <WebFormDelegate> formDelegate;
       
   291     id editingDelegate;
       
   292     id editingDelegateForwarder;
       
   293     id scriptDebugDelegate;
       
   294     id scriptDebugDelegateForwarder;
       
   295 
       
   296     BOOL allowsUndo;
       
   297         
       
   298     float textSizeMultiplier;
       
   299 
       
   300     NSString *applicationNameForUserAgent;
       
   301     String* userAgent;
       
   302     BOOL userAgentOverridden;
       
   303     
       
   304     WebPreferences *preferences;
       
   305     BOOL useSiteSpecificSpoofing;
       
   306 
       
   307     NSWindow *hostWindow;
       
   308 
       
   309     int programmaticFocusCount;
       
   310     
       
   311     WebResourceDelegateImplementationCache resourceLoadDelegateImplementations;
       
   312     WebFrameLoadDelegateImplementationCache frameLoadDelegateImplementations;
       
   313 
       
   314     void *observationInfo;
       
   315     
       
   316     BOOL closed;
       
   317     BOOL shouldCloseWithWindow;
       
   318     BOOL mainFrameDocumentReady;
       
   319     BOOL drawsBackground;
       
   320     BOOL editable;
       
   321     BOOL tabKeyCyclesThroughElementsChanged;
       
   322     BOOL becomingFirstResponder;
       
   323     BOOL becomingFirstResponderFromOutside;
       
   324     BOOL hoverFeedbackSuspended;
       
   325     BOOL usesPageCache;
       
   326     BOOL catchesDelegateExceptions;
       
   327 
       
   328     NSColor *backgroundColor;
       
   329 
       
   330     NSString *mediaStyle;
       
   331     
       
   332     BOOL hasSpellCheckerDocumentTag;
       
   333     NSInteger spellCheckerDocumentTag;
       
   334 
       
   335     BOOL smartInsertDeleteEnabled;
       
   336         
       
   337     BOOL dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
       
   338     BOOL dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
       
   339     BOOL dashboardBehaviorAlwaysAcceptsFirstMouse;
       
   340     BOOL dashboardBehaviorAllowWheelScrolling;
       
   341     
       
   342     // WebKit has both a global plug-in database and a separate, per WebView plug-in database. Dashboard uses the per WebView database.
       
   343     WebPluginDatabase *pluginDatabase;
       
   344     
       
   345     HashMap<unsigned long, RetainPtr<id> >* identifierMap;
       
   346 }
       
   347 @end
       
   348 
       
   349 @interface WebView (WebFileInternal)
       
   350 + (void)_setCacheModel:(WebCacheModel)cacheModel;
       
   351 + (WebCacheModel)_cacheModel;
       
   352 - (WebFrame *)_selectedOrMainFrame;
       
   353 - (WebFrameBridge *)_bridgeForSelectedOrMainFrame;
       
   354 - (BOOL)_isLoading;
       
   355 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point;
       
   356 - (WebFrame *)_focusedFrame;
       
   357 + (void)_preflightSpellChecker;
       
   358 - (BOOL)_continuousCheckingAllowed;
       
   359 - (NSResponder *)_responderForResponderOperations;
       
   360 - (BOOL)_performTextSizingSelector:(SEL)sel withObject:(id)arg onTrackingDocs:(BOOL)doTrackingViews selForNonTrackingDocs:(SEL)testSel newScaleFactor:(float)newScaleFactor;
       
   361 - (void)_notifyTextSizeMultiplierChanged;
       
   362 @end
       
   363 
       
   364 @interface WebView (WebCallDelegateFunctions)
       
   365 @end
       
   366 
       
   367 NSString *WebElementDOMNodeKey =            @"WebElementDOMNode";
       
   368 NSString *WebElementFrameKey =              @"WebElementFrame";
       
   369 NSString *WebElementImageKey =              @"WebElementImage";
       
   370 NSString *WebElementImageAltStringKey =     @"WebElementImageAltString";
       
   371 NSString *WebElementImageRectKey =          @"WebElementImageRect";
       
   372 NSString *WebElementImageURLKey =           @"WebElementImageURL";
       
   373 NSString *WebElementIsSelectedKey =         @"WebElementIsSelected";
       
   374 NSString *WebElementLinkLabelKey =          @"WebElementLinkLabel";
       
   375 NSString *WebElementLinkTargetFrameKey =    @"WebElementTargetFrame";
       
   376 NSString *WebElementLinkTitleKey =          @"WebElementLinkTitle";
       
   377 NSString *WebElementLinkURLKey =            @"WebElementLinkURL";
       
   378 NSString *WebElementSpellingToolTipKey =    @"WebElementSpellingToolTip";
       
   379 NSString *WebElementTitleKey =              @"WebElementTitle";
       
   380 NSString *WebElementLinkIsLiveKey =         @"WebElementLinkIsLive";
       
   381 NSString *WebElementIsContentEditableKey =  @"WebElementIsContentEditableKey";
       
   382 
       
   383 NSString *WebViewProgressStartedNotification =          @"WebProgressStartedNotification";
       
   384 NSString *WebViewProgressEstimateChangedNotification =  @"WebProgressEstimateChangedNotification";
       
   385 NSString *WebViewProgressFinishedNotification =         @"WebProgressFinishedNotification";
       
   386 
       
   387 NSString * const WebViewDidBeginEditingNotification =         @"WebViewDidBeginEditingNotification";
       
   388 NSString * const WebViewDidChangeNotification =               @"WebViewDidChangeNotification";
       
   389 NSString * const WebViewDidEndEditingNotification =           @"WebViewDidEndEditingNotification";
       
   390 NSString * const WebViewDidChangeTypingStyleNotification =    @"WebViewDidChangeTypingStyleNotification";
       
   391 NSString * const WebViewDidChangeSelectionNotification =      @"WebViewDidChangeSelectionNotification";
       
   392 
       
   393 enum { WebViewVersion = 4 };
       
   394 
       
   395 #define timedLayoutSize 4096
       
   396 
       
   397 static NSMutableSet *schemesWithRepresentationsSet;
       
   398 
       
   399 NSString *_WebCanGoBackKey =            @"canGoBack";
       
   400 NSString *_WebCanGoForwardKey =         @"canGoForward";
       
   401 NSString *_WebEstimatedProgressKey =    @"estimatedProgress";
       
   402 NSString *_WebIsLoadingKey =            @"isLoading";
       
   403 NSString *_WebMainFrameIconKey =        @"mainFrameIcon";
       
   404 NSString *_WebMainFrameTitleKey =       @"mainFrameTitle";
       
   405 NSString *_WebMainFrameURLKey =         @"mainFrameURL";
       
   406 NSString *_WebMainFrameDocumentKey =    @"mainFrameDocument";
       
   407 
       
   408 @interface WebProgressItem : NSObject
       
   409 {
       
   410 @public
       
   411     long long bytesReceived;
       
   412     long long estimatedLength;
       
   413 }
       
   414 @end
       
   415 
       
   416 @implementation WebProgressItem
       
   417 @end
       
   418 
       
   419 static BOOL continuousSpellCheckingEnabled;
       
   420 #ifndef BUILDING_ON_TIGER
       
   421 static BOOL grammarCheckingEnabled;
       
   422 #endif
       
   423 
       
   424 @implementation WebViewPrivate
       
   425 
       
   426 #ifndef BUILDING_ON_TIGER
       
   427 + (void)initialize
       
   428 {
       
   429     WebCoreObjCFinalizeOnMainThread(self);
       
   430 }
       
   431 #endif
       
   432 
       
   433 - init 
       
   434 {
       
   435     self = [super init];
       
   436     if (!self)
       
   437         return nil;
       
   438     allowsUndo = YES;
       
   439     textSizeMultiplier = 1;
       
   440     dashboardBehaviorAllowWheelScrolling = YES;
       
   441     shouldCloseWithWindow = objc_collecting_enabled();
       
   442     continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled];
       
   443 
       
   444 #ifndef BUILDING_ON_TIGER
       
   445     grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled];
       
   446 #endif
       
   447     userAgent = new String;
       
   448     
       
   449     usesPageCache = YES;
       
   450     
       
   451     identifierMap = new HashMap<unsigned long, RetainPtr<id> >();
       
   452     pluginDatabaseClientCount++;
       
   453 
       
   454     return self;
       
   455 }
       
   456 
       
   457 - (void)dealloc
       
   458 {
       
   459     ASSERT(!page);
       
   460     ASSERT(!preferences);
       
   461 
       
   462     delete userAgent;
       
   463     delete identifierMap;
       
   464     
       
   465     [applicationNameForUserAgent release];
       
   466     [backgroundColor release];
       
   467     
       
   468     [hostWindow release];
       
   469 
       
   470     [policyDelegateForwarder release];
       
   471     [UIDelegateForwarder release];
       
   472     [frameLoadDelegateForwarder release];
       
   473     [editingDelegateForwarder release];
       
   474     [scriptDebugDelegateForwarder release];
       
   475     
       
   476     [mediaStyle release];
       
   477     
       
   478     [super dealloc];
       
   479 }
       
   480 
       
   481 - (void)finalize
       
   482 {
       
   483     ASSERT_MAIN_THREAD();
       
   484 
       
   485     delete userAgent;
       
   486     delete identifierMap;
       
   487 
       
   488     [super finalize];
       
   489 }
       
   490 
       
   491 @end
       
   492 
       
   493 @implementation WebView (AllWebViews)
       
   494 
       
   495 static CFSetCallBacks NonRetainingSetCallbacks = {
       
   496     0,
       
   497     NULL,
       
   498     NULL,
       
   499     CFCopyDescription,
       
   500     CFEqual,
       
   501     CFHash
       
   502 };
       
   503 
       
   504 static CFMutableSetRef allWebViewsSet;
       
   505 
       
   506 + (void)_makeAllWebViewsPerformSelector:(SEL)selector
       
   507 {
       
   508     if (!allWebViewsSet)
       
   509         return;
       
   510 
       
   511     [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector];
       
   512 }
       
   513 
       
   514 - (void)_removeFromAllWebViewsSet
       
   515 {
       
   516     if (allWebViewsSet)
       
   517         CFSetRemoveValue(allWebViewsSet, self);
       
   518 }
       
   519 
       
   520 - (void)_addToAllWebViewsSet
       
   521 {
       
   522     if (!allWebViewsSet)
       
   523         allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks);
       
   524 
       
   525     CFSetSetValue(allWebViewsSet, self);
       
   526 }
       
   527 
       
   528 @end
       
   529 
       
   530 @implementation WebView (WebPrivate)
       
   531 
       
   532 #ifdef DEBUG_WIDGET_DRAWING
       
   533 static bool debugWidget = true;
       
   534 - (void)drawRect:(NSRect)rect
       
   535 {
       
   536     [[NSColor blueColor] set];
       
   537     NSRectFill (rect);
       
   538     
       
   539     NSRect htmlViewRect = [[[[self mainFrame] frameView] documentView] frame];
       
   540 
       
   541     if (debugWidget) {
       
   542         while (debugWidget) {
       
   543             sleep (1);
       
   544         }
       
   545     }
       
   546 
       
   547     NSLog (@"%s:   rect:  (%0.f,%0.f) %0.f %0.f, htmlViewRect:  (%0.f,%0.f) %0.f %0.f\n", 
       
   548         __PRETTY_FUNCTION__, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height,
       
   549         htmlViewRect.origin.x, htmlViewRect.origin.y, htmlViewRect.size.width, htmlViewRect.size.height
       
   550     );
       
   551 
       
   552     [super drawRect:rect];
       
   553 }
       
   554 #endif
       
   555 
       
   556 + (BOOL)_developerExtrasEnabled
       
   557 {
       
   558     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
       
   559     if ([defaults boolForKey:@"DisableWebKitDeveloperExtras"])
       
   560         return NO;
       
   561 #ifdef NDEBUG
       
   562     BOOL enableDebugger = [defaults boolForKey:@"WebKitDeveloperExtras"];
       
   563     if (!enableDebugger)
       
   564         enableDebugger = [defaults boolForKey:@"IncludeDebugMenu"];
       
   565     return enableDebugger;
       
   566 #else
       
   567     return YES; // always enable in debug builds
       
   568 #endif
       
   569 }
       
   570 
       
   571 + (BOOL)_scriptDebuggerEnabled
       
   572 {
       
   573 #ifdef NDEBUG
       
   574     return [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitScriptDebuggerEnabled"];
       
   575 #else
       
   576     return YES; // always enable in debug builds
       
   577 #endif
       
   578 }
       
   579 
       
   580 + (NSArray *)_supportedMIMETypes
       
   581 {
       
   582     // Load the plug-in DB allowing plug-ins to install types.
       
   583     [WebPluginDatabase sharedDatabase];
       
   584     return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys];
       
   585 }
       
   586 
       
   587 + (NSArray *)_supportedFileExtensions
       
   588 {
       
   589     NSMutableSet *extensions = [[NSMutableSet alloc] init];
       
   590     NSArray *MIMETypes = [self _supportedMIMETypes];
       
   591     NSEnumerator *enumerator = [MIMETypes objectEnumerator];
       
   592     NSString *MIMEType;
       
   593     while ((MIMEType = [enumerator nextObject]) != nil) {
       
   594         NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType);
       
   595         if (extensionsForType) {
       
   596             [extensions addObjectsFromArray:extensionsForType];
       
   597         }
       
   598     }
       
   599     NSArray *uniqueExtensions = [extensions allObjects];
       
   600     [extensions release];
       
   601     return uniqueExtensions;
       
   602 }
       
   603 
       
   604 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType;
       
   605 {
       
   606     MIMEType = [MIMEType lowercaseString];
       
   607     Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
       
   608     Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType];
       
   609     
       
   610     if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) {
       
   611         // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed.
       
   612         // Load the plug-in DB allowing plug-ins to install types.
       
   613         [WebPluginDatabase sharedDatabase];
       
   614             
       
   615         // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types.
       
   616         viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
       
   617         repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType];
       
   618     }
       
   619     
       
   620     if (viewClass && repClass) {
       
   621         // Special-case WebHTMLView for text types that shouldn't be shown.
       
   622         if (viewClass == [WebHTMLView class] &&
       
   623             repClass == [WebHTMLRepresentation class] &&
       
   624             [[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) {
       
   625             return NO;
       
   626         }
       
   627         if (vClass)
       
   628             *vClass = viewClass;
       
   629         if (rClass)
       
   630             *rClass = repClass;
       
   631         return YES;
       
   632     }
       
   633     
       
   634     return NO;
       
   635 }
       
   636 
       
   637 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType;
       
   638 {
       
   639     if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType])
       
   640         return YES;
       
   641 
       
   642     if (_private->pluginDatabase) {
       
   643         WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType];
       
   644         if (pluginPackage) {
       
   645             if (vClass)
       
   646                 *vClass = [WebHTMLView class];
       
   647             if (rClass)
       
   648                 *rClass = [WebHTMLRepresentation class];
       
   649             return YES;
       
   650         }
       
   651     }
       
   652     
       
   653     return NO;
       
   654 }
       
   655 
       
   656 + (void)_setAlwaysUseATSU:(BOOL)f
       
   657 {
       
   658     WebCoreSetAlwaysUseATSU(f);
       
   659 }
       
   660 
       
   661 + (BOOL)canShowFile:(NSString *)path
       
   662 {
       
   663     return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]];
       
   664 }
       
   665 
       
   666 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type
       
   667 {
       
   668     return WKGetPreferredExtensionForMIMEType(type);
       
   669 }
       
   670 
       
   671 - (BOOL)_isClosed
       
   672 {
       
   673     if (!_private || _private->closed)
       
   674         return YES;
       
   675     return NO;
       
   676 }
       
   677 
       
   678 - (void)_close
       
   679 {
       
   680     if (!_private || _private->closed)
       
   681         return;
       
   682 
       
   683     FrameLoader* mainFrameLoader = [[self mainFrame] _frameLoader];
       
   684     if (mainFrameLoader)
       
   685         mainFrameLoader->detachFromParent();
       
   686 
       
   687     [self _removeFromAllWebViewsSet];
       
   688     [self setGroupName:nil];
       
   689     [self setHostWindow:nil];
       
   690 
       
   691     [self setDownloadDelegate:nil];
       
   692     [self setEditingDelegate:nil];
       
   693     [self setFrameLoadDelegate:nil];
       
   694     [self setPolicyDelegate:nil];
       
   695     [self setResourceLoadDelegate:nil];
       
   696     [self setScriptDebugDelegate:nil];
       
   697     [self setUIDelegate:nil];
       
   698     
       
   699     // setHostWindow:nil must be called before this value is set (see 5408186)
       
   700     _private->closed = YES;
       
   701 
       
   702     // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint.
       
   703     [self removeDragCaret];
       
   704 
       
   705     // Deleteing the WebCore::Page will clear the page cache so we call destroy on 
       
   706     // all the plug-ins in the page cache to break any retain cycles.
       
   707     // See comment in HistoryItem::releaseAllPendingPageCaches() for more information.
       
   708     delete _private->page;
       
   709     _private->page = 0;
       
   710 
       
   711     if (_private->hasSpellCheckerDocumentTag) {
       
   712         [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag];
       
   713         _private->hasSpellCheckerDocumentTag = NO;
       
   714     }
       
   715     
       
   716     [[NSNotificationCenter defaultCenter] removeObserver:self];
       
   717 
       
   718     [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]];
       
   719 
       
   720     WebPreferences *preferences = _private->preferences;
       
   721     _private->preferences = nil;
       
   722     [preferences didRemoveFromWebView];
       
   723     [preferences release];
       
   724 
       
   725     pluginDatabaseClientCount--;
       
   726     
       
   727     // Make sure to close both sets of plug-ins databases because plug-ins need an opportunity to clean up files, etc.
       
   728     
       
   729     // Unload the WebView local plug-in database. 
       
   730     if (_private->pluginDatabase) {
       
   731         [_private->pluginDatabase close];
       
   732         [_private->pluginDatabase release];
       
   733         _private->pluginDatabase = nil;
       
   734     }
       
   735     
       
   736     // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles.
       
   737     if (!pluginDatabaseClientCount && applicationIsTerminating)
       
   738         [WebPluginDatabase closeSharedDatabase];
       
   739 }
       
   740 
       
   741 + (NSString *)_MIMETypeForFile:(NSString *)path
       
   742 {
       
   743     NSString *extension = [path pathExtension];
       
   744     NSString *MIMEType = nil;
       
   745 
       
   746     // Get the MIME type from the extension.
       
   747     if ([extension length] != 0) {
       
   748         MIMEType = WKGetMIMETypeForExtension(extension);
       
   749     }
       
   750 
       
   751     // If we can't get a known MIME type from the extension, sniff.
       
   752     if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) {
       
   753         NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
       
   754         NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH];
       
   755         [handle closeFile];
       
   756         if ([data length] != 0) {
       
   757             MIMEType = [data _webkit_guessedMIMEType];
       
   758         }
       
   759         if ([MIMEType length] == 0) {
       
   760             MIMEType = @"application/octet-stream";
       
   761         }
       
   762     }
       
   763 
       
   764     return MIMEType;
       
   765 }
       
   766 
       
   767 - (WebDownload *)_downloadURL:(NSURL *)URL
       
   768 {
       
   769     ASSERT(URL);
       
   770     
       
   771     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
       
   772     WebDownload *download = [WebDownload _downloadWithRequest:request
       
   773                                                      delegate:_private->downloadDelegate
       
   774                                                     directory:nil];
       
   775     [request release];
       
   776     
       
   777     return download;
       
   778 }
       
   779 
       
   780 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request
       
   781 {
       
   782     WebView *newWindowWebView = CallUIDelegate(self, @selector(webView:createWebViewWithRequest:), request);
       
   783     if (!newWindowWebView)
       
   784         return nil;
       
   785 
       
   786     CallUIDelegate(newWindowWebView, @selector(webViewShow:));
       
   787     return newWindowWebView;
       
   788 }
       
   789 
       
   790 - (WebCore::Page*)page
       
   791 {
       
   792     return _private->page;
       
   793 }
       
   794 
       
   795 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
       
   796 {
       
   797     NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items];
       
   798 
       
   799     NSArray *menuItems = CallUIDelegate(self, @selector(webView:contextMenuItemsForElement:defaultMenuItems:), element, defaultMenuItems);
       
   800     if (!menuItems)
       
   801         return nil;
       
   802 
       
   803     unsigned count = [menuItems count];
       
   804     if (!count)
       
   805         return nil;
       
   806 
       
   807     NSMenu *menu = [[NSMenu alloc] init];
       
   808     for (unsigned i = 0; i < count; i++)
       
   809         [menu addItem:[menuItems objectAtIndex:i]];
       
   810 
       
   811     return [menu autorelease];
       
   812 }
       
   813 
       
   814 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags
       
   815 {
       
   816     // We originally intended to call this delegate method sometimes with a nil dictionary, but due to
       
   817     // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't
       
   818     // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients.
       
   819     if (!dictionary)
       
   820         return;
       
   821     CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags);
       
   822 }
       
   823 
       
   824 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView
       
   825 {
       
   826     if (!_private->page)
       
   827         return;
       
   828     
       
   829     if (!otherView->_private->page)
       
   830         return;
       
   831     
       
   832     // It turns out the right combination of behavior is done with the back/forward load
       
   833     // type.  (See behavior matrix at the top of WebFramePrivate.)  So we copy all the items
       
   834     // in the back forward list, and go to the current one.
       
   835 
       
   836     BackForwardList* backForwardList = _private->page->backForwardList();
       
   837     ASSERT(!backForwardList->currentItem()); // destination list should be empty
       
   838 
       
   839     BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList();
       
   840     if (!otherBackForwardList->currentItem())
       
   841         return; // empty back forward list, bail
       
   842     
       
   843     HistoryItem* newItemToGoTo = 0;
       
   844 
       
   845     int lastItemIndex = otherBackForwardList->forwardListCount();
       
   846     for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) {
       
   847         if (i == 0) {
       
   848             // If this item is showing , save away its current scroll and form state,
       
   849             // since that might have changed since loading and it is normally not saved
       
   850             // until we leave that page.
       
   851             otherView->_private->page->mainFrame()->loader()->saveDocumentAndScrollState();
       
   852         }
       
   853         RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy();
       
   854         if (i == 0) 
       
   855             newItemToGoTo = newItem.get();
       
   856         backForwardList->addItem(newItem.release());
       
   857     }
       
   858     
       
   859     ASSERT(newItemToGoTo);
       
   860     _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward);
       
   861 }
       
   862 
       
   863 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate
       
   864 {
       
   865     _private->formDelegate = delegate;
       
   866 }
       
   867 
       
   868 - (id<WebFormDelegate>)_formDelegate
       
   869 {
       
   870     return _private->formDelegate;
       
   871 }
       
   872 
       
   873 - (BOOL)_needsAdobeFrameReloadingQuirk
       
   874 {
       
   875     static BOOL checked = NO;
       
   876     static BOOL needsQuirk = NO;
       
   877 
       
   878     if (checked)
       
   879         return needsQuirk;
       
   880 
       
   881     needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0)
       
   882         || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0)
       
   883         || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0)
       
   884         || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0)
       
   885         || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2)
       
   886         || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1)
       
   887         || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1)
       
   888         || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1)
       
   889         || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1)
       
   890         || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2);
       
   891 
       
   892     return needsQuirk;
       
   893 }
       
   894 
       
   895 - (void)_preferencesChangedNotification:(NSNotification *)notification
       
   896 {
       
   897     WebPreferences *preferences = (WebPreferences *)[notification object];
       
   898     ASSERT(preferences == [self preferences]);
       
   899 
       
   900     if (!_private->userAgentOverridden)
       
   901         *_private->userAgent = String();
       
   902 
       
   903     // Cache this value so we don't have to read NSUserDefaults on each page load
       
   904     _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing];
       
   905 
       
   906     // Update corresponding WebCore Settings object.
       
   907     if (!_private->page)
       
   908         return;
       
   909     
       
   910     Settings* settings = _private->page->settings();
       
   911     
       
   912     settings->setCursiveFontFamily([preferences cursiveFontFamily]);
       
   913     settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]);
       
   914     settings->setDefaultFontSize([preferences defaultFontSize]);
       
   915     settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]);
       
   916     settings->setFantasyFontFamily([preferences fantasyFontFamily]);
       
   917     settings->setFixedFontFamily([preferences fixedFontFamily]);
       
   918     settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]);
       
   919     settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]);
       
   920     settings->setJavaEnabled([preferences isJavaEnabled]);
       
   921     settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]);
       
   922     settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]);
       
   923     settings->setMinimumFontSize([preferences minimumFontSize]);
       
   924     settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]);
       
   925     settings->setPluginsEnabled([preferences arePlugInsEnabled]);
       
   926     settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]);
       
   927     settings->setSansSerifFontFamily([preferences sansSerifFontFamily]);
       
   928     settings->setSerifFontFamily([preferences serifFontFamily]);
       
   929     settings->setStandardFontFamily([preferences standardFontFamily]);
       
   930     settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]);
       
   931     settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]);
       
   932     settings->setTextAreasAreResizable([preferences textAreasAreResizable]);
       
   933     settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]);
       
   934     settings->setEditableLinkBehavior(core([preferences editableLinkBehavior]));
       
   935     settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]);
       
   936     settings->setUsesPageCache([self usesPageCache]);
       
   937     settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]);
       
   938     settings->setDeveloperExtrasEnabled([WebView _developerExtrasEnabled]);
       
   939     if ([preferences userStyleSheetEnabled]) {
       
   940         NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString];
       
   941         settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]);
       
   942     } else
       
   943         settings->setUserStyleSheetLocation([NSURL URLWithString:@""]);
       
   944     settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]);
       
   945 }
       
   946 
       
   947 static inline IMP getMethod(id o, SEL s)
       
   948 {
       
   949     return [o respondsToSelector:s] ? [o methodForSelector:s] : 0;
       
   950 }
       
   951 
       
   952 - (void)_cacheResourceLoadDelegateImplementations
       
   953 {
       
   954     WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations;
       
   955     id delegate = _private->resourceProgressDelegate;
       
   956 
       
   957     cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
       
   958     cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:));
       
   959     cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:));
       
   960     cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:));
       
   961     cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:));
       
   962     cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:));
       
   963     cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:));
       
   964     cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:));
       
   965     cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:));
       
   966     cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:));
       
   967     cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:));
       
   968 }
       
   969 
       
   970 WebResourceDelegateImplementationCache WebViewGetResourceLoadDelegateImplementations(WebView *webView)
       
   971 {
       
   972     return webView->_private->resourceLoadDelegateImplementations;
       
   973 }
       
   974 
       
   975 - (void)_cacheFrameLoadDelegateImplementations
       
   976 {
       
   977     WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations;
       
   978     id delegate = _private->frameLoadDelegate;
       
   979 
       
   980     cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:));
       
   981     cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:));
       
   982     cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:));
       
   983     cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:));
       
   984     cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:));
       
   985     cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:));
       
   986     cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:));
       
   987     cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:));
       
   988     cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:));
       
   989     cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:));
       
   990     cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:));
       
   991     cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:));
       
   992     cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:));
       
   993     cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:));
       
   994     cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:));
       
   995     cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:));
       
   996     cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:));
       
   997 }
       
   998 
       
   999 WebFrameLoadDelegateImplementationCache WebViewGetFrameLoadDelegateImplementations(WebView *webView)
       
  1000 {
       
  1001     return webView->_private->frameLoadDelegateImplementations;
       
  1002 }
       
  1003 
       
  1004 - (id)_policyDelegateForwarder
       
  1005 {
       
  1006     if (!_private->policyDelegateForwarder)
       
  1007         _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions];
       
  1008     return _private->policyDelegateForwarder;
       
  1009 }
       
  1010 
       
  1011 - (id)_UIDelegateForwarder
       
  1012 {
       
  1013     if (!_private->UIDelegateForwarder)
       
  1014         _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions];
       
  1015     return _private->UIDelegateForwarder;
       
  1016 }
       
  1017 
       
  1018 - (id)_editingDelegateForwarder
       
  1019 {
       
  1020     // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in.
       
  1021     // Not sure if that is a bug or not.
       
  1022     if (!_private)
       
  1023         return nil;
       
  1024 
       
  1025     if (!_private->editingDelegateForwarder)
       
  1026         _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions];
       
  1027     return _private->editingDelegateForwarder;
       
  1028 }
       
  1029 
       
  1030 - (id)_scriptDebugDelegateForwarder
       
  1031 {
       
  1032     if (!_private->scriptDebugDelegateForwarder)
       
  1033         _private->scriptDebugDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->scriptDebugDelegate defaultTarget:[WebDefaultScriptDebugDelegate sharedScriptDebugDelegate] catchExceptions:_private->catchesDelegateExceptions];
       
  1034     return _private->scriptDebugDelegateForwarder;
       
  1035 }
       
  1036 
       
  1037 - (void)_closeWindow
       
  1038 {
       
  1039     [[self _UIDelegateForwarder] webViewClose:self];
       
  1040 }
       
  1041 
       
  1042 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType;
       
  1043 {
       
  1044     [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
       
  1045     [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType];
       
  1046     
       
  1047     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
       
  1048     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
       
  1049     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
       
  1050     MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType);
       
  1051 }
       
  1052 
       
  1053 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme;
       
  1054 {
       
  1055     NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme];
       
  1056     [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType];
       
  1057 
       
  1058     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
       
  1059     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
       
  1060     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
       
  1061     if ([viewClass class] == [WebHTMLView class])
       
  1062         MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
       
  1063     
       
  1064     // This is used to make _representationExistsForURLScheme faster.
       
  1065     // Without this set, we'd have to create the MIME type each time.
       
  1066     if (schemesWithRepresentationsSet == nil) {
       
  1067         schemesWithRepresentationsSet = [[NSMutableSet alloc] init];
       
  1068     }
       
  1069     [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]];
       
  1070 }
       
  1071 
       
  1072 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme
       
  1073 {
       
  1074     return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]];
       
  1075 }
       
  1076 
       
  1077 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme
       
  1078 {
       
  1079     return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]];
       
  1080 }
       
  1081 
       
  1082 + (BOOL)_canHandleRequest:(NSURLRequest *)request
       
  1083 {
       
  1084     // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed
       
  1085     if (!request)
       
  1086         return NO;
       
  1087 
       
  1088     if ([NSURLConnection canHandleRequest:request])
       
  1089         return YES;
       
  1090 
       
  1091     NSString *scheme = [[request URL] scheme];
       
  1092 
       
  1093     if ([self _representationExistsForURLScheme:scheme])
       
  1094         return YES;
       
  1095         
       
  1096     return ([scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"]);
       
  1097 }
       
  1098 
       
  1099 + (NSString *)_decodeData:(NSData *)data
       
  1100 {
       
  1101     HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet
       
  1102     RefPtr<TextResourceDecoder> decoder = new TextResourceDecoder("text/html"); // bookmark files are HTML
       
  1103     String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]);
       
  1104     result += decoder->flush();
       
  1105     return result;
       
  1106 }
       
  1107 
       
  1108 - (void)_pushPerformingProgrammaticFocus
       
  1109 {
       
  1110     _private->programmaticFocusCount++;
       
  1111 }
       
  1112 
       
  1113 - (void)_popPerformingProgrammaticFocus
       
  1114 {
       
  1115     _private->programmaticFocusCount--;
       
  1116 }
       
  1117 
       
  1118 - (BOOL)_isPerformingProgrammaticFocus
       
  1119 {
       
  1120     return _private->programmaticFocusCount != 0;
       
  1121 }
       
  1122 
       
  1123 - (void)_didChangeValueForKey: (NSString *)key
       
  1124 {
       
  1125     LOG (Bindings, "calling didChangeValueForKey: %@", key);
       
  1126     [self didChangeValueForKey: key];
       
  1127 }
       
  1128 
       
  1129 - (void)_willChangeValueForKey: (NSString *)key
       
  1130 {
       
  1131     LOG (Bindings, "calling willChangeValueForKey: %@", key);
       
  1132     [self willChangeValueForKey: key];
       
  1133 }
       
  1134 
       
  1135 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
       
  1136     static NSSet *manualNotifyKeys = nil;
       
  1137     if (!manualNotifyKeys)
       
  1138         manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
       
  1139             _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
       
  1140     if ([manualNotifyKeys containsObject:key])
       
  1141         return NO;
       
  1142     return YES;
       
  1143 }
       
  1144 
       
  1145 - (NSArray *)_declaredKeys {
       
  1146     static NSArray *declaredKeys = nil;
       
  1147     if (!declaredKeys)
       
  1148         declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey,
       
  1149             _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
       
  1150     return declaredKeys;
       
  1151 }
       
  1152 
       
  1153 - (void)setObservationInfo:(void *)info
       
  1154 {
       
  1155     _private->observationInfo = info;
       
  1156 }
       
  1157 
       
  1158 - (void *)observationInfo
       
  1159 {
       
  1160     return _private->observationInfo;
       
  1161 }
       
  1162 
       
  1163 - (void)_willChangeBackForwardKeys
       
  1164 {
       
  1165     [self _willChangeValueForKey: _WebCanGoBackKey];
       
  1166     [self _willChangeValueForKey: _WebCanGoForwardKey];
       
  1167 }
       
  1168 
       
  1169 - (void)_didChangeBackForwardKeys
       
  1170 {
       
  1171     [self _didChangeValueForKey: _WebCanGoBackKey];
       
  1172     [self _didChangeValueForKey: _WebCanGoForwardKey];
       
  1173 }
       
  1174 
       
  1175 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame
       
  1176 {
       
  1177     [self _willChangeBackForwardKeys];
       
  1178     if (frame == [self mainFrame]){
       
  1179         // Force an observer update by sending a will/did.
       
  1180         [self _willChangeValueForKey: _WebIsLoadingKey];
       
  1181         [self _didChangeValueForKey: _WebIsLoadingKey];
       
  1182 
       
  1183         [self _willChangeValueForKey: _WebMainFrameURLKey];
       
  1184     }
       
  1185 
       
  1186     [NSApp setWindowsNeedUpdate:YES];
       
  1187 }
       
  1188 
       
  1189 - (void)_didCommitLoadForFrame:(WebFrame *)frame
       
  1190 {
       
  1191     if (frame == [self mainFrame])
       
  1192         [self _didChangeValueForKey: _WebMainFrameURLKey];
       
  1193     [NSApp setWindowsNeedUpdate:YES];
       
  1194 }
       
  1195 
       
  1196 - (void)_didFinishLoadForFrame:(WebFrame *)frame
       
  1197 {
       
  1198     [self _didChangeBackForwardKeys];
       
  1199     if (frame == [self mainFrame]){
       
  1200         // Force an observer update by sending a will/did.
       
  1201         [self _willChangeValueForKey: _WebIsLoadingKey];
       
  1202         [self _didChangeValueForKey: _WebIsLoadingKey];
       
  1203     }
       
  1204     [NSApp setWindowsNeedUpdate:YES];
       
  1205 }
       
  1206 
       
  1207 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
       
  1208 {
       
  1209     [self _didChangeBackForwardKeys];
       
  1210     if (frame == [self mainFrame]){
       
  1211         // Force an observer update by sending a will/did.
       
  1212         [self _willChangeValueForKey: _WebIsLoadingKey];
       
  1213         [self _didChangeValueForKey: _WebIsLoadingKey];
       
  1214     }
       
  1215     [NSApp setWindowsNeedUpdate:YES];
       
  1216 }
       
  1217 
       
  1218 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
       
  1219 {
       
  1220     [self _didChangeBackForwardKeys];
       
  1221     if (frame == [self mainFrame]){
       
  1222         // Force an observer update by sending a will/did.
       
  1223         [self _willChangeValueForKey: _WebIsLoadingKey];
       
  1224         [self _didChangeValueForKey: _WebIsLoadingKey];
       
  1225         
       
  1226         [self _didChangeValueForKey: _WebMainFrameURLKey];
       
  1227     }
       
  1228     [NSApp setWindowsNeedUpdate:YES];
       
  1229 }
       
  1230 
       
  1231 - (void)_reloadForPluginChanges
       
  1232 {
       
  1233     [[self mainFrame] _reloadForPluginChanges];
       
  1234 }
       
  1235 
       
  1236 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL
       
  1237 {
       
  1238     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
       
  1239     [request _web_setHTTPUserAgent:[self userAgentForURL:URL]];
       
  1240     NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
       
  1241     [request release];
       
  1242     return cachedResponse;
       
  1243 }
       
  1244 
       
  1245 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
       
  1246 {
       
  1247     NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
       
  1248     DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey];
       
  1249     [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey])
       
  1250                         element:domElement
       
  1251                             URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey]
       
  1252                           title:[element objectForKey:WebElementImageAltStringKey] 
       
  1253                         archive:[[element objectForKey:WebElementDOMNodeKey] webArchive]
       
  1254                           types:types
       
  1255                          source:nil];
       
  1256 }
       
  1257 
       
  1258 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
       
  1259 {
       
  1260     [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey]
       
  1261                      andTitle:[element objectForKey:WebElementLinkLabelKey]
       
  1262                         types:types];
       
  1263 }
       
  1264 
       
  1265 - (void)_setInitiatedDrag:(BOOL)initiatedDrag
       
  1266 {
       
  1267     if (!_private->page)
       
  1268         return;
       
  1269     _private->page->dragController()->setDidInitiateDrag(initiatedDrag);
       
  1270 }
       
  1271 
       
  1272 #define DASHBOARD_CONTROL_LABEL @"control"
       
  1273 
       
  1274 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views
       
  1275 {
       
  1276     // Add scroller regions for NSScroller and KWQScrollBar
       
  1277     int i, count = [views count];
       
  1278     
       
  1279     for (i = 0; i < count; i++) {
       
  1280         NSView *aView = [views objectAtIndex:i];
       
  1281         
       
  1282         if ([aView isKindOfClass:[NSScroller class]] ||
       
  1283             [aView isKindOfClass:NSClassFromString (@"KWQScrollBar")]) {
       
  1284             NSRect bounds = [aView bounds];
       
  1285             NSRect adjustedBounds;
       
  1286             adjustedBounds.origin = [self convertPoint:bounds.origin fromView:aView];
       
  1287             adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y;
       
  1288             
       
  1289             // AppKit has horrible hack of placing absent scrollers at -100,-100
       
  1290             if (adjustedBounds.origin.y == -100)
       
  1291                 continue;
       
  1292             adjustedBounds.size = bounds.size;
       
  1293             NSRect clip = [aView visibleRect];
       
  1294             NSRect adjustedClip;
       
  1295             adjustedClip.origin = [self convertPoint:clip.origin fromView:aView];
       
  1296             adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y;
       
  1297             adjustedClip.size = clip.size;
       
  1298             WebDashboardRegion *aRegion = 
       
  1299                         [[[WebDashboardRegion alloc] initWithRect:adjustedBounds 
       
  1300                                     clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle] autorelease];
       
  1301             NSMutableArray *scrollerRegions;
       
  1302             scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL];
       
  1303             if (!scrollerRegions) {
       
  1304                 scrollerRegions = [NSMutableArray array];
       
  1305                 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL];
       
  1306             }
       
  1307             [scrollerRegions addObject:aRegion];
       
  1308         }
       
  1309         [self _addScrollerDashboardRegions:regions from:[aView subviews]];
       
  1310     }
       
  1311 }
       
  1312 
       
  1313 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions
       
  1314 {
       
  1315     [self _addScrollerDashboardRegions:regions from:[self subviews]];
       
  1316 }
       
  1317 
       
  1318 - (NSDictionary *)_dashboardRegions
       
  1319 {
       
  1320     // Only return regions from main frame.
       
  1321     Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
       
  1322     if (!mainFrame)
       
  1323         return nil;
       
  1324     NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary();
       
  1325     [self _addScrollerDashboardRegions:regions];
       
  1326     return regions;
       
  1327 }
       
  1328 
       
  1329 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag
       
  1330 {
       
  1331     // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement 
       
  1332     // specific support for the backward compatibility mode flag.
       
  1333     if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page)
       
  1334         _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true);
       
  1335     
       
  1336     switch (behavior) {
       
  1337         case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
       
  1338             _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag;
       
  1339             break;
       
  1340         }
       
  1341         case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
       
  1342             _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag;
       
  1343             break;
       
  1344         }
       
  1345         case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
       
  1346             _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag;
       
  1347             break;
       
  1348         }
       
  1349         case WebDashboardBehaviorAllowWheelScrolling: {
       
  1350             _private->dashboardBehaviorAllowWheelScrolling = flag;
       
  1351             break;
       
  1352         }
       
  1353         case WebDashboardBehaviorUseBackwardCompatibilityMode: {
       
  1354             if (_private->page)
       
  1355                 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag);
       
  1356             break;
       
  1357         }
       
  1358     }
       
  1359 }
       
  1360 
       
  1361 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior
       
  1362 {
       
  1363     switch (behavior) {
       
  1364         case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: {
       
  1365             return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows;
       
  1366         }
       
  1367         case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: {
       
  1368             return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns;
       
  1369         }
       
  1370         case WebDashboardBehaviorAlwaysAcceptsFirstMouse: {
       
  1371             return _private->dashboardBehaviorAlwaysAcceptsFirstMouse;
       
  1372         }
       
  1373         case WebDashboardBehaviorAllowWheelScrolling: {
       
  1374             return _private->dashboardBehaviorAllowWheelScrolling;
       
  1375         }
       
  1376         case WebDashboardBehaviorUseBackwardCompatibilityMode: {
       
  1377             return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode();
       
  1378         }
       
  1379     }
       
  1380     return NO;
       
  1381 }
       
  1382 
       
  1383 + (void)_setShouldUseFontSmoothing:(BOOL)f
       
  1384 {
       
  1385     WebCoreSetShouldUseFontSmoothing(f);
       
  1386 }
       
  1387 
       
  1388 + (BOOL)_shouldUseFontSmoothing
       
  1389 {
       
  1390     return WebCoreShouldUseFontSmoothing();
       
  1391 }
       
  1392 
       
  1393 + (void)_setUsesTestModeFocusRingColor:(BOOL)f
       
  1394 {
       
  1395     setUsesTestModeFocusRingColor(f);
       
  1396 }
       
  1397 
       
  1398 + (BOOL)_usesTestModeFocusRingColor
       
  1399 {
       
  1400     return usesTestModeFocusRingColor();
       
  1401 }
       
  1402 
       
  1403 // This is only used by older versions of Safari and should be removed in a future release. 
       
  1404 + (NSString *)_minimumRequiredSafariBuildNumber
       
  1405 {
       
  1406     return @"420+";
       
  1407 }
       
  1408 
       
  1409 - (void)setAlwaysShowVerticalScroller:(BOOL)flag
       
  1410 {
       
  1411     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
       
  1412     if (flag) {
       
  1413         [scrollview setVerticalScrollingMode:WebCoreScrollbarAlwaysOn andLock:YES];
       
  1414     } else {
       
  1415         [scrollview setVerticalScrollingModeLocked:NO];
       
  1416         [scrollview setVerticalScrollingMode:WebCoreScrollbarAuto];
       
  1417     }
       
  1418 }
       
  1419 
       
  1420 - (BOOL)alwaysShowVerticalScroller
       
  1421 {
       
  1422     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
       
  1423     return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == WebCoreScrollbarAlwaysOn;
       
  1424 }
       
  1425 
       
  1426 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag
       
  1427 {
       
  1428     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
       
  1429     if (flag) {
       
  1430         [scrollview setHorizontalScrollingMode:WebCoreScrollbarAlwaysOn andLock:YES];
       
  1431     } else {
       
  1432         [scrollview setHorizontalScrollingModeLocked:NO];
       
  1433         [scrollview setHorizontalScrollingMode:WebCoreScrollbarAuto];
       
  1434     }
       
  1435 }
       
  1436 
       
  1437 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits
       
  1438 {
       
  1439     Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
       
  1440     if (mainFrame)
       
  1441         mainFrame->setProhibitsScrolling(prohibits);
       
  1442 }
       
  1443 
       
  1444 - (BOOL)alwaysShowHorizontalScroller
       
  1445 {
       
  1446     WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView];
       
  1447     return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == WebCoreScrollbarAlwaysOn;
       
  1448 }
       
  1449 
       
  1450 - (void)_setInViewSourceMode:(BOOL)flag
       
  1451 {
       
  1452     Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
       
  1453     if (mainFrame)
       
  1454         mainFrame->setInViewSourceMode(flag);
       
  1455 }
       
  1456 
       
  1457 - (BOOL)_inViewSourceMode
       
  1458 {
       
  1459     Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
       
  1460     return mainFrame && mainFrame->inViewSourceMode();
       
  1461 }
       
  1462 
       
  1463 - (void)_setUseFastImageScalingMode:(BOOL)flag
       
  1464 {
       
  1465     if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) {
       
  1466         _private->page->setInLowQualityImageInterpolationMode(flag);
       
  1467         [self setNeedsDisplay:YES];
       
  1468     }
       
  1469 }
       
  1470 
       
  1471 - (BOOL)_inFastImageScalingMode
       
  1472 {
       
  1473     if (_private->page)
       
  1474         return _private->page->inLowQualityImageInterpolationMode();
       
  1475     return NO;
       
  1476 }
       
  1477 
       
  1478 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths
       
  1479 {
       
  1480     if (!_private->pluginDatabase)
       
  1481         _private->pluginDatabase = [[WebPluginDatabase alloc] init];
       
  1482         
       
  1483     [_private->pluginDatabase setPlugInPaths:newPaths];
       
  1484     [_private->pluginDatabase refresh];
       
  1485 }
       
  1486 
       
  1487 - (void)_attachScriptDebuggerToAllFrames
       
  1488 {
       
  1489     for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
       
  1490         [kit(frame) _attachScriptDebugger];
       
  1491 }
       
  1492 
       
  1493 - (void)_detachScriptDebuggerFromAllFrames
       
  1494 {
       
  1495     for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext())
       
  1496         [kit(frame) _detachScriptDebugger];
       
  1497 }
       
  1498 
       
  1499 - (void)setBackgroundColor:(NSColor *)backgroundColor
       
  1500 {
       
  1501     if ([_private->backgroundColor isEqual:backgroundColor])
       
  1502         return;
       
  1503 
       
  1504     id old = _private->backgroundColor;
       
  1505     _private->backgroundColor = [backgroundColor retain];
       
  1506     [old release];
       
  1507 
       
  1508     [[self mainFrame] _updateBackground];
       
  1509 }
       
  1510 
       
  1511 - (NSColor *)backgroundColor
       
  1512 {
       
  1513     return _private->backgroundColor;
       
  1514 }
       
  1515 
       
  1516 - (BOOL)defersCallbacks
       
  1517 {
       
  1518     if (!_private->page)
       
  1519         return NO;
       
  1520     return _private->page->defersLoading();
       
  1521 }
       
  1522 
       
  1523 - (void)setDefersCallbacks:(BOOL)defer
       
  1524 {
       
  1525     if (!_private->page)
       
  1526         return;
       
  1527     return _private->page->setDefersLoading(defer);
       
  1528 }
       
  1529 
       
  1530 // For backwards compatibility with the WebBackForwardList API, we honor both
       
  1531 // a per-WebView and a per-preferences setting for whether to use the page cache.
       
  1532 
       
  1533 - (BOOL)usesPageCache
       
  1534 {
       
  1535     return _private->usesPageCache && [[self preferences] usesPageCache];
       
  1536 }
       
  1537 
       
  1538 - (void)setUsesPageCache:(BOOL)usesPageCache
       
  1539 {
       
  1540     _private->usesPageCache = usesPageCache;
       
  1541 
       
  1542     // Post a notification so the WebCore settings update.
       
  1543     [[self preferences] _postPreferencesChangesNotification];
       
  1544 }
       
  1545 
       
  1546 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource 
       
  1547 {
       
  1548     NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window]; 
       
  1549     [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window]; 
       
  1550 } 
       
  1551 
       
  1552 - (void)_clearUndoRedoOperations
       
  1553 {
       
  1554     if (!_private->page)
       
  1555         return;
       
  1556     _private->page->clearUndoRedoOperations();
       
  1557 }
       
  1558 
       
  1559 - (void)_setCatchesDelegateExceptions:(BOOL)f
       
  1560 {
       
  1561     _private->catchesDelegateExceptions = f;
       
  1562 }
       
  1563 
       
  1564 - (BOOL)_catchesDelegateExceptions
       
  1565 {
       
  1566     return _private->catchesDelegateExceptions;
       
  1567 }
       
  1568 
       
  1569 @end
       
  1570 
       
  1571 @implementation _WebSafeForwarder
       
  1572 
       
  1573 // Used to send messages to delegates that implement informal protocols.
       
  1574 
       
  1575 - (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c
       
  1576 {
       
  1577     self = [super init];
       
  1578     if (!self)
       
  1579         return nil;
       
  1580     target = t; // Non retained.
       
  1581     defaultTarget = dt;
       
  1582     catchExceptions = c;
       
  1583     return self;
       
  1584 }
       
  1585 
       
  1586 - (void)forwardInvocation:(NSInvocation *)invocation
       
  1587 {
       
  1588     if ([target respondsToSelector:[invocation selector]]) {
       
  1589         if (catchExceptions) {
       
  1590             @try {
       
  1591                 [invocation invokeWithTarget:target];
       
  1592             } @catch(id exception) {
       
  1593                 ReportDiscardedDelegateException([invocation selector], exception);
       
  1594             }
       
  1595         } else
       
  1596             [invocation invokeWithTarget:target];
       
  1597         return;
       
  1598     }
       
  1599 
       
  1600     if ([defaultTarget respondsToSelector:[invocation selector]])
       
  1601         [invocation invokeWithTarget:defaultTarget];
       
  1602 
       
  1603     // Do nothing quietly if method not implemented.
       
  1604 }
       
  1605 
       
  1606 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
       
  1607 {
       
  1608     return [defaultTarget methodSignatureForSelector:aSelector];
       
  1609 }
       
  1610 
       
  1611 @end
       
  1612 
       
  1613 @implementation WebView
       
  1614 
       
  1615 + (void)initialize
       
  1616 {
       
  1617     static BOOL initialized = NO;
       
  1618     if (initialized)
       
  1619         return;
       
  1620     initialized = YES;
       
  1621 
       
  1622 #ifdef REMOVE_SAFARI_DOM_TREE_DEBUG_ITEM
       
  1623     // This prevents open source users from crashing when using the Show DOM Tree menu item in Safari 2.
       
  1624     // FIXME: remove this when we no longer need to support Safari 2.
       
  1625     if ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"] && [[NSUserDefaults standardUserDefaults] boolForKey:@"IncludeDebugMenu"])
       
  1626         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_finishedLaunching) name:NSApplicationDidFinishLaunchingNotification object:NSApp];
       
  1627 #endif
       
  1628 
       
  1629     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp];
       
  1630     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil];
       
  1631     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil];
       
  1632 }
       
  1633 
       
  1634 + (void)_applicationWillTerminate
       
  1635 {   
       
  1636     applicationIsTerminating = YES;
       
  1637     if (!pluginDatabaseClientCount)
       
  1638         [WebPluginDatabase closeSharedDatabase];
       
  1639 }
       
  1640 
       
  1641 #ifdef REMOVE_SAFARI_DOM_TREE_DEBUG_ITEM
       
  1642 // FIXME: remove this when it is no longer needed to prevent Safari from crashing
       
  1643 + (void)_finishedLaunching
       
  1644 {
       
  1645     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_removeDOMTreeMenuItem:) name:NSMenuDidAddItemNotification object:[NSApp mainMenu]];
       
  1646     [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidFinishLaunchingNotification object:NSApp];
       
  1647 }
       
  1648 
       
  1649 +(void)_removeDOMTreeMenuItem:(NSNotification *)notification
       
  1650 {
       
  1651     NSMenu *debugMenu = [[[[NSApp mainMenu] itemArray] lastObject] submenu];
       
  1652     NSMenuItem *domTree = [debugMenu itemWithTitle:@"Show DOM Tree"];
       
  1653     if (domTree)
       
  1654         [debugMenu removeItem:domTree];
       
  1655     [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMenuDidAddItemNotification object:[NSApp mainMenu]];
       
  1656 }
       
  1657 #endif
       
  1658 
       
  1659 + (BOOL)canShowMIMEType:(NSString *)MIMEType
       
  1660 {
       
  1661     return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType];
       
  1662 }
       
  1663 
       
  1664 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType
       
  1665 {
       
  1666     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType];
       
  1667     if (pluginPackage)
       
  1668         return pluginPackage;
       
  1669     
       
  1670     if (_private->pluginDatabase)
       
  1671         return [_private->pluginDatabase pluginForMIMEType:MIMEType];
       
  1672     
       
  1673     return nil;
       
  1674 }
       
  1675 
       
  1676 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension
       
  1677 {
       
  1678     WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension];
       
  1679     if (pluginPackage)
       
  1680         return pluginPackage;
       
  1681     
       
  1682     if (_private->pluginDatabase)
       
  1683         return [_private->pluginDatabase pluginForExtension:extension];
       
  1684     
       
  1685     return nil;
       
  1686 }
       
  1687 
       
  1688 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType
       
  1689 {
       
  1690     if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType])
       
  1691         return YES;
       
  1692         
       
  1693     if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType])
       
  1694         return YES;
       
  1695     
       
  1696     return NO;
       
  1697 }
       
  1698 
       
  1699 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType
       
  1700 {
       
  1701     return [WebFrameView _canShowMIMETypeAsHTML:MIMEType];
       
  1702 }
       
  1703 
       
  1704 + (NSArray *)MIMETypesShownAsHTML
       
  1705 {
       
  1706     NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES];
       
  1707     NSEnumerator *enumerator = [viewTypes keyEnumerator];
       
  1708     id key;
       
  1709     NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
       
  1710     
       
  1711     while ((key = [enumerator nextObject])) {
       
  1712         if ([viewTypes objectForKey:key] == [WebHTMLView class])
       
  1713             [array addObject:key];
       
  1714     }
       
  1715     
       
  1716     return array;
       
  1717 }
       
  1718 
       
  1719 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes
       
  1720 {
       
  1721     NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy];
       
  1722     NSEnumerator *enumerator = [viewTypes keyEnumerator];
       
  1723     id key;
       
  1724     while ((key = [enumerator nextObject])) {
       
  1725         if ([viewTypes objectForKey:key] == [WebHTMLView class])
       
  1726             [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key];
       
  1727     }
       
  1728     
       
  1729     int i, count = [MIMETypes count];
       
  1730     for (i = 0; i < count; i++) {
       
  1731         [WebView registerViewClass:[WebHTMLView class] 
       
  1732                 representationClass:[WebHTMLRepresentation class] 
       
  1733                 forMIMEType:[MIMETypes objectAtIndex:i]];
       
  1734     }
       
  1735     [viewTypes release];
       
  1736 }
       
  1737 
       
  1738 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard
       
  1739 {
       
  1740     return [pasteboard _web_bestURL];
       
  1741 }
       
  1742 
       
  1743 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard
       
  1744 {
       
  1745     return [pasteboard stringForType:WebURLNamePboardType];
       
  1746 }
       
  1747 
       
  1748 + (void)registerURLSchemeAsLocal:(NSString *)protocol
       
  1749 {
       
  1750     FrameLoader::registerURLSchemeAsLocal(protocol);
       
  1751 }
       
  1752 
       
  1753 - (void)_registerDraggedTypes
       
  1754 {
       
  1755     NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes];
       
  1756     NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL];
       
  1757     NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
       
  1758     [types addObjectsFromArray:URLTypes];
       
  1759     [self registerForDraggedTypes:[types allObjects]];
       
  1760     [types release];
       
  1761 }
       
  1762 
       
  1763 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName
       
  1764 {
       
  1765     WebPreferences *standardPreferences = [WebPreferences standardPreferences];
       
  1766     [standardPreferences willAddToWebView];
       
  1767 
       
  1768     _private->preferences = [standardPreferences retain];
       
  1769     _private->catchesDelegateExceptions = YES;
       
  1770     _private->mainFrameDocumentReady = NO;
       
  1771     _private->drawsBackground = YES;
       
  1772     _private->smartInsertDeleteEnabled = YES;
       
  1773     _private->backgroundColor = [[NSColor whiteColor] retain];
       
  1774 
       
  1775     NSRect f = [self frame];
       
  1776     WebFrameView *frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)];
       
  1777     [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
       
  1778     [self addSubview:frameView];
       
  1779     [frameView release];
       
  1780 
       
  1781     WebKitInitializeLoggingChannelsIfNecessary();
       
  1782     WebCore::InitializeLoggingChannelsIfNecessary();
       
  1783     [WebHistoryItem initWindowWatcherIfNecessary];
       
  1784 
       
  1785     _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self));
       
  1786     [[[WebFrameBridge alloc] initMainFrameWithPage:_private->page frameName:frameName frameView:frameView] release];
       
  1787 
       
  1788     [self _addToAllWebViewsSet];
       
  1789     [self setGroupName:groupName];
       
  1790     
       
  1791     // If there's already a next key view (e.g., from a nib), wire it up to our
       
  1792     // contained frame view. In any case, wire our next key view up to the our
       
  1793     // contained frame view. This works together with our becomeFirstResponder 
       
  1794     // and setNextKeyView overrides.
       
  1795     NSView *nextKeyView = [self nextKeyView];
       
  1796     if (nextKeyView != nil && nextKeyView != frameView) {
       
  1797         [frameView setNextKeyView:nextKeyView];
       
  1798     }
       
  1799     [super setNextKeyView:frameView];
       
  1800 
       
  1801     ++WebViewCount;
       
  1802 
       
  1803     [self _registerDraggedTypes];
       
  1804 
       
  1805     // initialize WebScriptDebugServer here so listeners can register before any pages are loaded.
       
  1806     if ([WebView _scriptDebuggerEnabled])
       
  1807         [WebScriptDebugServer sharedScriptDebugServer];
       
  1808 
       
  1809     WebPreferences *prefs = [self preferences];
       
  1810     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
       
  1811                                                  name:WebPreferencesChangedNotification object:prefs];
       
  1812 
       
  1813     // Post a notification so the WebCore settings update.
       
  1814     [[self preferences] _postPreferencesChangesNotification];
       
  1815 
       
  1816     if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION))
       
  1817         FrameLoader::setRestrictAccessToLocal(true);
       
  1818 }
       
  1819 
       
  1820 - (id)initWithFrame:(NSRect)f
       
  1821 {
       
  1822     return [self initWithFrame:f frameName:nil groupName:nil];
       
  1823 }
       
  1824 
       
  1825 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName;
       
  1826 {
       
  1827     self = [super initWithFrame:f];
       
  1828     if (!self)
       
  1829         return nil;
       
  1830 
       
  1831 #ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH
       
  1832     // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which
       
  1833     // may not work with other WebKit applications.  Unsetting DYLD_FRAMEWORK_PATH removes the
       
  1834     // need for Safari to unset it to prevent it from being passed to applications it launches.
       
  1835     // Unsetting it when a WebView is first created is as good a place as any.
       
  1836     // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details.
       
  1837     if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) {
       
  1838         unsetenv("DYLD_FRAMEWORK_PATH");
       
  1839         unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH");
       
  1840     }
       
  1841 #endif
       
  1842 
       
  1843     _private = [[WebViewPrivate alloc] init];
       
  1844     [self _commonInitializationWithFrameName:frameName groupName:groupName];
       
  1845     [self setMaintainsBackForwardList: YES];
       
  1846     return self;
       
  1847 }
       
  1848 
       
  1849 - (id)initWithCoder:(NSCoder *)decoder
       
  1850 {
       
  1851     WebView *result = nil;
       
  1852 
       
  1853 NS_DURING
       
  1854 
       
  1855     NSString *frameName;
       
  1856     NSString *groupName;
       
  1857     WebPreferences *preferences;
       
  1858     BOOL useBackForwardList = NO;
       
  1859     BOOL allowsUndo = YES;
       
  1860     
       
  1861     result = [super initWithCoder:decoder];
       
  1862     result->_private = [[WebViewPrivate alloc] init];
       
  1863 
       
  1864     // We don't want any of the archived subviews. The subviews will always
       
  1865     // be created in _commonInitializationFrameName:groupName:.
       
  1866     [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
       
  1867 
       
  1868     if ([decoder allowsKeyedCoding]) {
       
  1869         frameName = [decoder decodeObjectForKey:@"FrameName"];
       
  1870         groupName = [decoder decodeObjectForKey:@"GroupName"];
       
  1871         preferences = [decoder decodeObjectForKey:@"Preferences"];
       
  1872         useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"];
       
  1873         if ([decoder containsValueForKey:@"AllowsUndo"])
       
  1874             allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"];
       
  1875     } else {
       
  1876         int version;
       
  1877         [decoder decodeValueOfObjCType:@encode(int) at:&version];
       
  1878         frameName = [decoder decodeObject];
       
  1879         groupName = [decoder decodeObject];
       
  1880         preferences = [decoder decodeObject];
       
  1881         if (version > 1)
       
  1882             [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList];
       
  1883         // The allowsUndo field is no longer written out in encodeWithCoder, but since there are
       
  1884         // version 3 NIBs that have this field encoded, we still need to read it in.
       
  1885         if (version == 3)
       
  1886             [decoder decodeValuesOfObjCTypes:"c", &allowsUndo];
       
  1887     }
       
  1888 
       
  1889     if (![frameName isKindOfClass:[NSString class]])
       
  1890         frameName = nil;
       
  1891     if (![groupName isKindOfClass:[NSString class]])
       
  1892         groupName = nil;
       
  1893     if (![preferences isKindOfClass:[WebPreferences class]])
       
  1894         preferences = nil;
       
  1895 
       
  1896     LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList);
       
  1897     [result _commonInitializationWithFrameName:frameName groupName:groupName];
       
  1898     [result page]->backForwardList()->setEnabled(useBackForwardList);
       
  1899     result->_private->allowsUndo = allowsUndo;
       
  1900     if (preferences)
       
  1901         [result setPreferences:preferences];
       
  1902 
       
  1903 NS_HANDLER
       
  1904 
       
  1905     result = nil;
       
  1906     [self release];
       
  1907 
       
  1908 NS_ENDHANDLER
       
  1909 
       
  1910     return result;
       
  1911 }
       
  1912 
       
  1913 - (void)encodeWithCoder:(NSCoder *)encoder
       
  1914 {
       
  1915     // Set asside the subviews before we archive. We don't want to archive any subviews.
       
  1916     // The subviews will always be created in _commonInitializationFrameName:groupName:.
       
  1917     id originalSubviews = _subviews;
       
  1918     _subviews = nil;
       
  1919 
       
  1920     [super encodeWithCoder:encoder];
       
  1921 
       
  1922     // Restore the subviews we set aside.
       
  1923     _subviews = originalSubviews;
       
  1924 
       
  1925     BOOL useBackForwardList = _private->page && _private->page->backForwardList()->enabled();
       
  1926     if ([encoder allowsKeyedCoding]) {
       
  1927         [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"];
       
  1928         [encoder encodeObject:[self groupName] forKey:@"GroupName"];
       
  1929         [encoder encodeObject:[self preferences] forKey:@"Preferences"];
       
  1930         [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"];
       
  1931         [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"];
       
  1932     } else {
       
  1933         int version = WebViewVersion;
       
  1934         [encoder encodeValueOfObjCType:@encode(int) at:&version];
       
  1935         [encoder encodeObject:[[self mainFrame] name]];
       
  1936         [encoder encodeObject:[self groupName]];
       
  1937         [encoder encodeObject:[self preferences]];
       
  1938         [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList];
       
  1939         // DO NOT encode any new fields here, doing so will break older WebKit releases.
       
  1940     }
       
  1941 
       
  1942     LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList);
       
  1943 }
       
  1944 
       
  1945 - (void)dealloc
       
  1946 {
       
  1947     // call close to ensure we tear-down completely
       
  1948     // this maintains our old behavior for existing applications
       
  1949     [self _close];
       
  1950 
       
  1951     --WebViewCount;
       
  1952     
       
  1953     [_private release];
       
  1954     // [super dealloc] can end up dispatching against _private (3466082)
       
  1955     _private = nil;
       
  1956 
       
  1957     [super dealloc];
       
  1958 }
       
  1959 
       
  1960 - (void)finalize
       
  1961 {
       
  1962     ASSERT(_private->closed);
       
  1963 
       
  1964     --WebViewCount;
       
  1965 
       
  1966     [super finalize];
       
  1967 }
       
  1968 
       
  1969 - (void)close
       
  1970 {
       
  1971     [self _close];
       
  1972 }
       
  1973 
       
  1974 - (void)setShouldCloseWithWindow:(BOOL)close
       
  1975 {
       
  1976     _private->shouldCloseWithWindow = close;
       
  1977 }
       
  1978 
       
  1979 - (BOOL)shouldCloseWithWindow
       
  1980 {
       
  1981     return _private->shouldCloseWithWindow;
       
  1982 }
       
  1983 
       
  1984 - (void)viewWillMoveToWindow:(NSWindow *)window
       
  1985 {
       
  1986     // Don't do anything if we aren't initialized.  This happens when decoding a WebView.
       
  1987     if (!_private)
       
  1988         return;
       
  1989     
       
  1990     if ([self window])
       
  1991         [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]];
       
  1992 
       
  1993     if (window) {
       
  1994         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window];
       
  1995 
       
  1996         // Ensure that we will receive the events that WebHTMLView (at least) needs. It's expensive enough
       
  1997         // that we don't want to call it over and over.
       
  1998         [window setAcceptsMouseMovedEvents:YES];
       
  1999         WKSetNSWindowShouldPostEventNotifications(window, YES);
       
  2000     }
       
  2001 }
       
  2002 
       
  2003 - (void)_windowWillClose:(NSNotification *)notification
       
  2004 {
       
  2005     if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow])))
       
  2006         [self _close];
       
  2007 }
       
  2008 
       
  2009 - (void)setPreferences:(WebPreferences *)prefs
       
  2010 {
       
  2011     if (!prefs)
       
  2012         prefs = [WebPreferences standardPreferences];
       
  2013 
       
  2014     if (_private->preferences == prefs)
       
  2015         return;
       
  2016 
       
  2017     [prefs willAddToWebView];
       
  2018 
       
  2019     WebPreferences *oldPrefs = _private->preferences;
       
  2020 
       
  2021     [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]];
       
  2022     [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]];
       
  2023 
       
  2024     _private->preferences = [prefs retain];
       
  2025 
       
  2026     // After registering for the notification, post it so the WebCore settings update.
       
  2027     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:)
       
  2028         name:WebPreferencesChangedNotification object:[self preferences]];
       
  2029     [[self preferences] _postPreferencesChangesNotification];
       
  2030 
       
  2031     [oldPrefs didRemoveFromWebView];
       
  2032     [oldPrefs release];
       
  2033 }
       
  2034 
       
  2035 - (WebPreferences *)preferences
       
  2036 {
       
  2037     return _private->preferences;
       
  2038 }
       
  2039 
       
  2040 - (void)setPreferencesIdentifier:(NSString *)anIdentifier
       
  2041 {
       
  2042     if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) {
       
  2043         WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier];
       
  2044         [self setPreferences:prefs];
       
  2045         [prefs release];
       
  2046     }
       
  2047 }
       
  2048 
       
  2049 - (NSString *)preferencesIdentifier
       
  2050 {
       
  2051     return [[self preferences] identifier];
       
  2052 }
       
  2053 
       
  2054 
       
  2055 - (void)setUIDelegate:delegate
       
  2056 {
       
  2057     _private->UIDelegate = delegate;
       
  2058     [_private->UIDelegateForwarder release];
       
  2059     _private->UIDelegateForwarder = nil;
       
  2060 }
       
  2061 
       
  2062 - UIDelegate
       
  2063 {
       
  2064     return _private->UIDelegate;
       
  2065 }
       
  2066 
       
  2067 - (void)setResourceLoadDelegate: delegate
       
  2068 {
       
  2069     _private->resourceProgressDelegate = delegate;
       
  2070     [self _cacheResourceLoadDelegateImplementations];
       
  2071 }
       
  2072 
       
  2073 - resourceLoadDelegate
       
  2074 {
       
  2075     return _private->resourceProgressDelegate;
       
  2076 }
       
  2077 
       
  2078 - (void)setDownloadDelegate: delegate
       
  2079 {
       
  2080     _private->downloadDelegate = delegate;
       
  2081 }
       
  2082 
       
  2083 
       
  2084 - downloadDelegate
       
  2085 {
       
  2086     return _private->downloadDelegate;
       
  2087 }
       
  2088 
       
  2089 - (void)setPolicyDelegate:delegate
       
  2090 {
       
  2091     _private->policyDelegate = delegate;
       
  2092     [_private->policyDelegateForwarder release];
       
  2093     _private->policyDelegateForwarder = nil;
       
  2094 }
       
  2095 
       
  2096 - policyDelegate
       
  2097 {
       
  2098     return _private->policyDelegate;
       
  2099 }
       
  2100 
       
  2101 - (void)setFrameLoadDelegate:delegate
       
  2102 {
       
  2103     _private->frameLoadDelegate = delegate;
       
  2104     [self _cacheFrameLoadDelegateImplementations];
       
  2105 }
       
  2106 
       
  2107 - frameLoadDelegate
       
  2108 {
       
  2109     return _private->frameLoadDelegate;
       
  2110 }
       
  2111 
       
  2112 - (WebFrame *)mainFrame
       
  2113 {
       
  2114     // This can be called in initialization, before _private has been set up (3465613)
       
  2115     if (!_private)
       
  2116         return nil;
       
  2117     if (!_private->page)
       
  2118         return nil;
       
  2119     return kit(_private->page->mainFrame());
       
  2120 }
       
  2121 
       
  2122 - (WebFrame *)selectedFrame
       
  2123 {
       
  2124     // If the first responder is a view in our tree, we get the frame containing the first responder.
       
  2125     // This is faster than searching the frame hierarchy, and will give us a result even in the case
       
  2126     // where the focused frame doesn't actually contain a selection.
       
  2127     WebFrame *focusedFrame = [self _focusedFrame];
       
  2128     if (focusedFrame)
       
  2129         return focusedFrame;
       
  2130     
       
  2131     // If the first responder is outside of our view tree, we search for a frame containing a selection.
       
  2132     // There should be at most only one of these.
       
  2133     return [[self mainFrame] _findFrameWithSelection];
       
  2134 }
       
  2135 
       
  2136 - (WebBackForwardList *)backForwardList
       
  2137 {
       
  2138     if (!_private->page)
       
  2139         return nil;
       
  2140     if (!_private->page->backForwardList()->enabled())
       
  2141         return nil;
       
  2142     return kit(_private->page->backForwardList());
       
  2143 }
       
  2144 
       
  2145 - (void)setMaintainsBackForwardList: (BOOL)flag
       
  2146 {
       
  2147     if (!_private->page)
       
  2148         return;
       
  2149     _private->page->backForwardList()->setEnabled(flag);
       
  2150 }
       
  2151 
       
  2152 - (BOOL)goBack
       
  2153 {
       
  2154     if (!_private->page)
       
  2155         return NO;
       
  2156     
       
  2157     return _private->page->goBack();
       
  2158 }
       
  2159 
       
  2160 - (BOOL)goForward
       
  2161 {
       
  2162     if (!_private->page)
       
  2163         return NO;
       
  2164 
       
  2165     return _private->page->goForward();
       
  2166 }
       
  2167 
       
  2168 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item
       
  2169 {
       
  2170     if (!_private->page)
       
  2171         return NO;
       
  2172 
       
  2173     _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward);
       
  2174     return YES;
       
  2175 }
       
  2176 
       
  2177 - (void)setTextSizeMultiplier:(float)m
       
  2178 {
       
  2179     // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>)
       
  2180     if (_private->textSizeMultiplier == m)
       
  2181         return;
       
  2182 
       
  2183     _private->textSizeMultiplier = m;
       
  2184     [self _notifyTextSizeMultiplierChanged];
       
  2185 }
       
  2186 
       
  2187 - (float)textSizeMultiplier
       
  2188 {
       
  2189     return _private->textSizeMultiplier;
       
  2190 }
       
  2191 
       
  2192 - (void)setApplicationNameForUserAgent:(NSString *)applicationName
       
  2193 {
       
  2194     NSString *name = [applicationName copy];
       
  2195     [_private->applicationNameForUserAgent release];
       
  2196     _private->applicationNameForUserAgent = name;
       
  2197     if (!_private->userAgentOverridden)
       
  2198         *_private->userAgent = String();
       
  2199 }
       
  2200 
       
  2201 - (NSString *)applicationNameForUserAgent
       
  2202 {
       
  2203     return [[_private->applicationNameForUserAgent retain] autorelease];
       
  2204 }
       
  2205 
       
  2206 - (void)setCustomUserAgent:(NSString *)userAgentString
       
  2207 {
       
  2208     *_private->userAgent = userAgentString;
       
  2209     _private->userAgentOverridden = userAgentString != nil;
       
  2210 }
       
  2211 
       
  2212 - (NSString *)customUserAgent
       
  2213 {
       
  2214     if (!_private->userAgentOverridden)
       
  2215         return nil;
       
  2216     return *_private->userAgent;
       
  2217 }
       
  2218 
       
  2219 - (void)setMediaStyle:(NSString *)mediaStyle
       
  2220 {
       
  2221     if (_private->mediaStyle != mediaStyle) {
       
  2222         [_private->mediaStyle release];
       
  2223         _private->mediaStyle = [mediaStyle copy];
       
  2224     }
       
  2225 }
       
  2226 
       
  2227 - (NSString *)mediaStyle
       
  2228 {
       
  2229     return _private->mediaStyle;
       
  2230 }
       
  2231 
       
  2232 - (BOOL)supportsTextEncoding
       
  2233 {
       
  2234     id documentView = [[[self mainFrame] frameView] documentView];
       
  2235     return [documentView conformsToProtocol:@protocol(WebDocumentText)]
       
  2236         && [documentView supportsTextEncoding];
       
  2237 }
       
  2238 
       
  2239 - (void)setCustomTextEncodingName:(NSString *)encoding
       
  2240 {
       
  2241     NSString *oldEncoding = [self customTextEncodingName];
       
  2242     if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding])
       
  2243         return;
       
  2244     FrameLoader* mainFrameLoader = [[self mainFrame] _frameLoader];
       
  2245     if (mainFrameLoader)
       
  2246         mainFrameLoader->reloadAllowingStaleData(encoding);
       
  2247 }
       
  2248 
       
  2249 - (NSString *)_mainFrameOverrideEncoding
       
  2250 {
       
  2251     WebDataSource *dataSource = [[self mainFrame] provisionalDataSource];
       
  2252     if (dataSource == nil)
       
  2253         dataSource = [[self mainFrame] _dataSource];
       
  2254     if (dataSource == nil)
       
  2255         return nil;
       
  2256     return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding());
       
  2257 }
       
  2258 
       
  2259 - (NSString *)customTextEncodingName
       
  2260 {
       
  2261     return [self _mainFrameOverrideEncoding];
       
  2262 }
       
  2263 
       
  2264 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
       
  2265 {
       
  2266     // FIXME: We can remove this workaround for VitalSource Bookshelf when they update
       
  2267     // their code so that it no longer calls stringByEvaluatingJavaScriptFromString with a return statement.
       
  2268     // Return statements are only valid in a function.  See <rdar://problem/5095515> for the evangelism bug.
       
  2269     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_VITALSOURCE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.vitalsource.bookshelf"]) {
       
  2270         NSRange returnStringRange = [script rangeOfString:@"return "];
       
  2271         if (returnStringRange.length != 0 && returnStringRange.location == 0)
       
  2272             script = [script substringFromIndex: returnStringRange.location + returnStringRange.length];
       
  2273     }
       
  2274     
       
  2275     NSString *result = [[[self mainFrame] _bridge] stringByEvaluatingJavaScriptFromString:script];
       
  2276     // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script
       
  2277     // Since there's no way to get rid of the main frame, result will never ever be nil here.
       
  2278     ASSERT(result);
       
  2279     
       
  2280     return result;
       
  2281 }
       
  2282 
       
  2283 - (WebScriptObject *)windowScriptObject
       
  2284 {
       
  2285     Frame* coreFrame = core([self mainFrame]);
       
  2286     if (!coreFrame)
       
  2287         return nil;
       
  2288     return coreFrame->windowScriptObject();
       
  2289 }
       
  2290 
       
  2291 // Get the appropriate user-agent string for a particular URL.
       
  2292 - (NSString *)userAgentForURL:(NSURL *)url
       
  2293 {
       
  2294     return [self _userAgentForURL:KURL([url absoluteURL])];
       
  2295 }
       
  2296 
       
  2297 - (void)setHostWindow:(NSWindow *)hostWindow
       
  2298 {
       
  2299     if (!_private->closed && hostWindow != _private->hostWindow) {
       
  2300         [[self mainFrame] _viewWillMoveToHostWindow:hostWindow];
       
  2301         if (_private->hostWindow)
       
  2302             [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow];
       
  2303         if (hostWindow)
       
  2304             [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow];
       
  2305         [_private->hostWindow release];
       
  2306         _private->hostWindow = [hostWindow retain];
       
  2307         [[self mainFrame] _viewDidMoveToHostWindow];
       
  2308     }
       
  2309 }
       
  2310 
       
  2311 - (NSWindow *)hostWindow
       
  2312 {
       
  2313     return _private->hostWindow;
       
  2314 }
       
  2315 
       
  2316 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point
       
  2317 {
       
  2318     return [[self _frameViewAtWindowPoint:point] documentView];
       
  2319 }
       
  2320 
       
  2321 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint
       
  2322 {
       
  2323     WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint];
       
  2324     if (!frameView)
       
  2325         return nil;
       
  2326     NSView <WebDocumentView> *documentView = [frameView documentView];
       
  2327     if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) {
       
  2328         NSPoint point = [documentView convertPoint:windowPoint fromView:nil];
       
  2329         return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point];
       
  2330     }
       
  2331     return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey];
       
  2332 }
       
  2333 
       
  2334 - (NSDictionary *)elementAtPoint:(NSPoint)point
       
  2335 {
       
  2336     return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]];
       
  2337 }
       
  2338 
       
  2339 // The following 2 internal NSView methods are called on the drag destination by make scrolling while dragging work.
       
  2340 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination. 
       
  2341 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination. 
       
  2342 // Forward these calls to the document subview to make its scroll view scroll.
       
  2343 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta
       
  2344 {
       
  2345     NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
       
  2346     [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta];
       
  2347 }
       
  2348 
       
  2349 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo
       
  2350 {
       
  2351     NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
       
  2352     return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo];
       
  2353 }
       
  2354 
       
  2355 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
       
  2356 {
       
  2357     NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
       
  2358     WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
       
  2359     IntPoint client([draggingInfo draggingLocation]);
       
  2360     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
       
  2361     DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
       
  2362     return core(self)->dragController()->dragEntered(&dragData);
       
  2363 }
       
  2364 
       
  2365 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
       
  2366 {
       
  2367     NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
       
  2368     WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
       
  2369     IntPoint client([draggingInfo draggingLocation]);
       
  2370     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
       
  2371     DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
       
  2372     return core(self)->dragController()->dragUpdated(&dragData);
       
  2373 }
       
  2374 
       
  2375 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
       
  2376 {
       
  2377     NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
       
  2378     WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil);
       
  2379     IntPoint client([draggingInfo draggingLocation]);
       
  2380     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
       
  2381     DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
       
  2382     core(self)->dragController()->dragExited(&dragData);
       
  2383 }
       
  2384 
       
  2385 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
       
  2386 {
       
  2387     return YES;
       
  2388 }
       
  2389 
       
  2390 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
       
  2391 {
       
  2392     NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]];
       
  2393     WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]]? (WebHTMLView*)view : nil);
       
  2394     IntPoint client([draggingInfo draggingLocation]);
       
  2395     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
       
  2396     DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper);
       
  2397     return core(self)->dragController()->performDrag(&dragData);
       
  2398 }
       
  2399 
       
  2400 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types
       
  2401 {
       
  2402     NSView *hitView = [super _hitTest:aPoint dragTypes:types];
       
  2403     if (!hitView && [[self superview] mouse:*aPoint inRect:[self frame]]) {
       
  2404         return self;
       
  2405     } else {
       
  2406         return hitView;
       
  2407     }
       
  2408 }
       
  2409 
       
  2410 - (BOOL)acceptsFirstResponder
       
  2411 {
       
  2412     return [[[self mainFrame] frameView] acceptsFirstResponder];
       
  2413 }
       
  2414 
       
  2415 - (BOOL)becomeFirstResponder
       
  2416 {
       
  2417     if (_private->becomingFirstResponder) {
       
  2418         // Fix for unrepro infinite recursion reported in radar 4448181. If we hit this assert on
       
  2419         // a debug build, we should figure out what causes the problem and do a better fix.
       
  2420         ASSERT_NOT_REACHED();
       
  2421         return NO;
       
  2422     }
       
  2423     
       
  2424     // This works together with setNextKeyView to splice the WebView into
       
  2425     // the key loop similar to the way NSScrollView does this. Note that
       
  2426     // WebFrameView has very similar code.
       
  2427     NSWindow *window = [self window];
       
  2428     WebFrameView *mainFrameView = [[self mainFrame] frameView];
       
  2429 
       
  2430     NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming];
       
  2431     BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self);
       
  2432     
       
  2433     if ([window keyViewSelectionDirection] == NSSelectingPrevious) {
       
  2434         NSView *previousValidKeyView = [self previousValidKeyView];
       
  2435         if ((previousValidKeyView != self) && (previousValidKeyView != mainFrameView)) {
       
  2436             _private->becomingFirstResponder = YES;
       
  2437             _private->becomingFirstResponderFromOutside = fromOutside;
       
  2438             [window makeFirstResponder:previousValidKeyView];
       
  2439             _private->becomingFirstResponderFromOutside = NO;
       
  2440             _private->becomingFirstResponder = NO;
       
  2441             return YES;
       
  2442         } else {
       
  2443             return NO;
       
  2444         }
       
  2445     }
       
  2446     
       
  2447     if ([mainFrameView acceptsFirstResponder]) {
       
  2448         _private->becomingFirstResponder = YES;
       
  2449         _private->becomingFirstResponderFromOutside = fromOutside;
       
  2450         [window makeFirstResponder:mainFrameView];
       
  2451         _private->becomingFirstResponderFromOutside = NO;
       
  2452         _private->becomingFirstResponder = NO;
       
  2453         return YES;
       
  2454     } 
       
  2455     
       
  2456     return NO;
       
  2457 }
       
  2458 
       
  2459 - (NSView *)_webcore_effectiveFirstResponder
       
  2460 {
       
  2461     WebFrameView *frameView = [[self mainFrame] frameView];
       
  2462     return frameView ? [frameView _webcore_effectiveFirstResponder] : [super _webcore_effectiveFirstResponder];
       
  2463 }
       
  2464 
       
  2465 - (void)setNextKeyView:(NSView *)aView
       
  2466 {
       
  2467     // This works together with becomeFirstResponder to splice the WebView into
       
  2468     // the key loop similar to the way NSScrollView does this. Note that
       
  2469     // WebFrameView has very similar code.
       
  2470     WebFrameView *mainFrameView = [[self mainFrame] frameView];
       
  2471     if (mainFrameView != nil) {
       
  2472         [mainFrameView setNextKeyView:aView];
       
  2473     } else {
       
  2474         [super setNextKeyView:aView];
       
  2475     }
       
  2476 }
       
  2477 
       
  2478 static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
       
  2479 {
       
  2480     Frame* coreFrame = core(curr);
       
  2481     return kit(forward
       
  2482         ? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
       
  2483         : coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
       
  2484 }
       
  2485 
       
  2486 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
       
  2487 {
       
  2488     return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];
       
  2489 }
       
  2490 
       
  2491 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType
       
  2492 {
       
  2493     [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType];
       
  2494     [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType];
       
  2495     
       
  2496     // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed)
       
  2497     // in the WebCore MIMEType registry.  For now we're doing this in a safe, limited manner
       
  2498     // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness
       
  2499     if ([viewClass class] == [WebHTMLView class])
       
  2500         MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType);
       
  2501 }
       
  2502 
       
  2503 - (void)setGroupName:(NSString *)groupName
       
  2504 {
       
  2505     if (!_private->page)
       
  2506         return;
       
  2507     _private->page->setGroupName(groupName);
       
  2508 }
       
  2509 
       
  2510 - (NSString *)groupName
       
  2511 {
       
  2512     if (!_private->page)
       
  2513         return nil;
       
  2514     return _private->page->groupName();
       
  2515 }
       
  2516 
       
  2517 - (double)estimatedProgress
       
  2518 {
       
  2519     if (!_private->page)
       
  2520         return 0.0;
       
  2521 
       
  2522     return _private->page->progress()->estimatedProgress();
       
  2523 }
       
  2524 
       
  2525 - (NSArray *)pasteboardTypesForSelection
       
  2526 {
       
  2527     NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView];
       
  2528     if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
       
  2529         return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection];
       
  2530     }
       
  2531     return [NSArray array];
       
  2532 }
       
  2533 
       
  2534 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
       
  2535 {
       
  2536     WebFrame *frame = [self _selectedOrMainFrame];
       
  2537     if (frame && [frame _hasSelection]) {
       
  2538         NSView <WebDocumentView> *documentView = [[frame frameView] documentView];
       
  2539         if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)])
       
  2540             [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
       
  2541     }
       
  2542 }
       
  2543 
       
  2544 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element
       
  2545 {
       
  2546     if ([element objectForKey:WebElementImageURLKey] != nil) {
       
  2547         return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)];
       
  2548     } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
       
  2549         return [NSPasteboard _web_writableTypesForURL];
       
  2550     } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
       
  2551         return [self pasteboardTypesForSelection];
       
  2552     }
       
  2553     return [NSArray array];
       
  2554 }
       
  2555 
       
  2556 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard
       
  2557 {
       
  2558     if ([element objectForKey:WebElementImageURLKey] != nil) {
       
  2559         [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard];
       
  2560     } else if ([element objectForKey:WebElementLinkURLKey] != nil) {
       
  2561         [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard];
       
  2562     } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
       
  2563         [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard];
       
  2564     }
       
  2565 }
       
  2566 
       
  2567 - (void)moveDragCaretToPoint:(NSPoint)point
       
  2568 {
       
  2569     if (Page* page = core(self))
       
  2570         page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil]));
       
  2571 }
       
  2572 
       
  2573 - (void)removeDragCaret
       
  2574 {
       
  2575     if (Page* page = core(self))
       
  2576         page->dragController()->dragEnded();
       
  2577 }
       
  2578 
       
  2579 - (void)setMainFrameURL:(NSString *)URLString
       
  2580 {
       
  2581     [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
       
  2582 }
       
  2583 
       
  2584 - (NSString *)mainFrameURL
       
  2585 {
       
  2586     WebDataSource *ds;
       
  2587     ds = [[self mainFrame] provisionalDataSource];
       
  2588     if (!ds)
       
  2589         ds = [[self mainFrame] _dataSource];
       
  2590     return [[[ds request] URL] _web_originalDataAsString];
       
  2591 }
       
  2592 
       
  2593 - (BOOL)isLoading
       
  2594 {
       
  2595     LOG (Bindings, "isLoading = %d", (int)[self _isLoading]);
       
  2596     return [self _isLoading];
       
  2597 }
       
  2598 
       
  2599 - (NSString *)mainFrameTitle
       
  2600 {
       
  2601     NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle];
       
  2602     return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@"";
       
  2603 }
       
  2604 
       
  2605 - (NSImage *)mainFrameIcon
       
  2606 {
       
  2607     return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
       
  2608 }
       
  2609 
       
  2610 - (DOMDocument *)mainFrameDocument
       
  2611 {
       
  2612     // only return the actual value if the state we're in gives NSTreeController
       
  2613     // enough time to release its observers on the old model
       
  2614     if (_private->mainFrameDocumentReady)
       
  2615         return [[self mainFrame] DOMDocument];
       
  2616     return nil;
       
  2617 }
       
  2618 
       
  2619 - (void)setDrawsBackground:(BOOL)drawsBackground
       
  2620 {
       
  2621     if (_private->drawsBackground == drawsBackground)
       
  2622         return;
       
  2623     _private->drawsBackground = drawsBackground;
       
  2624     [[self mainFrame] _updateBackground];
       
  2625 }
       
  2626 
       
  2627 - (BOOL)drawsBackground
       
  2628 {
       
  2629     return _private->drawsBackground;
       
  2630 }
       
  2631 
       
  2632 @end
       
  2633 
       
  2634 @implementation WebView (WebIBActions)
       
  2635 
       
  2636 - (IBAction)takeStringURLFrom: sender
       
  2637 {
       
  2638     NSString *URLString = [sender stringValue];
       
  2639     
       
  2640     [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]];
       
  2641 }
       
  2642 
       
  2643 - (BOOL)canGoBack
       
  2644 {
       
  2645     if (!_private->page)
       
  2646         return NO;
       
  2647 
       
  2648     return !!_private->page->backForwardList()->backItem();
       
  2649 }
       
  2650 
       
  2651 - (BOOL)canGoForward
       
  2652 {
       
  2653     if (!_private->page)
       
  2654         return NO;
       
  2655 
       
  2656     return !!_private->page->backForwardList()->forwardItem();
       
  2657 }
       
  2658 
       
  2659 - (IBAction)goBack:(id)sender
       
  2660 {
       
  2661     [self goBack];
       
  2662 }
       
  2663 
       
  2664 - (IBAction)goForward:(id)sender
       
  2665 {
       
  2666     [self goForward];
       
  2667 }
       
  2668 
       
  2669 - (IBAction)stopLoading:(id)sender
       
  2670 {
       
  2671     [[self mainFrame] stopLoading];
       
  2672 }
       
  2673 
       
  2674 - (IBAction)reload:(id)sender
       
  2675 {
       
  2676     [[self mainFrame] reload];
       
  2677 }
       
  2678 
       
  2679 #define MinimumTextSizeMultiplier       0.5f
       
  2680 #define MaximumTextSizeMultiplier       3.0f
       
  2681 #define TextSizeMultiplierRatio         1.2f
       
  2682 
       
  2683 - (BOOL)canMakeTextSmaller
       
  2684 {
       
  2685     BOOL canShrinkMore = _private->textSizeMultiplier/TextSizeMultiplierRatio > MinimumTextSizeMultiplier;
       
  2686     return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:canShrinkMore selForNonTrackingDocs:@selector(_canMakeTextSmaller) newScaleFactor:0];
       
  2687 }
       
  2688 
       
  2689 - (BOOL)canMakeTextLarger
       
  2690 {
       
  2691     BOOL canGrowMore = _private->textSizeMultiplier*TextSizeMultiplierRatio < MaximumTextSizeMultiplier;
       
  2692     return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:canGrowMore selForNonTrackingDocs:@selector(_canMakeTextLarger) newScaleFactor:0];
       
  2693 }
       
  2694 
       
  2695 - (IBAction)makeTextSmaller:(id)sender
       
  2696 {
       
  2697     float newScale = _private->textSizeMultiplier / TextSizeMultiplierRatio;
       
  2698     BOOL canShrinkMore = newScale > MinimumTextSizeMultiplier;
       
  2699     [self _performTextSizingSelector:@selector(_makeTextSmaller:) withObject:sender onTrackingDocs:canShrinkMore selForNonTrackingDocs:@selector(_canMakeTextSmaller) newScaleFactor:newScale];
       
  2700 }
       
  2701 
       
  2702 - (IBAction)makeTextLarger:(id)sender
       
  2703 {
       
  2704     float newScale = _private->textSizeMultiplier*TextSizeMultiplierRatio;
       
  2705     BOOL canGrowMore = newScale < MaximumTextSizeMultiplier;
       
  2706     [self _performTextSizingSelector:@selector(_makeTextLarger:) withObject:sender onTrackingDocs:canGrowMore selForNonTrackingDocs:@selector(_canMakeTextLarger) newScaleFactor:newScale];
       
  2707 }
       
  2708 
       
  2709 - (IBAction)toggleSmartInsertDelete:(id)sender
       
  2710 {
       
  2711     [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]];
       
  2712 }
       
  2713 
       
  2714 - (IBAction)toggleContinuousSpellChecking:(id)sender
       
  2715 {
       
  2716     [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]];
       
  2717 }
       
  2718 
       
  2719 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
       
  2720 {
       
  2721     id responder = [self _responderForResponderOperations];
       
  2722     if (responder != self && [responder respondsToSelector:[item action]]) {
       
  2723         if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)])
       
  2724             return [responder validateUserInterfaceItemWithoutDelegate:item];
       
  2725         if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)])
       
  2726             return [responder validateUserInterfaceItem:item];
       
  2727         return YES;
       
  2728     }
       
  2729     return NO;
       
  2730 }
       
  2731 
       
  2732 - (BOOL)canMakeTextStandardSize
       
  2733 {
       
  2734     BOOL notAlreadyStandard = _private->textSizeMultiplier != 1.0f;
       
  2735     return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:notAlreadyStandard selForNonTrackingDocs:@selector(_canMakeTextStandardSize) newScaleFactor:0.0f];
       
  2736 }
       
  2737 
       
  2738 - (IBAction)makeTextStandardSize:(id)sender
       
  2739 {
       
  2740     BOOL notAlreadyStandard = _private->textSizeMultiplier != 1.0f;
       
  2741     [self _performTextSizingSelector:@selector(_makeTextStandardSize:) withObject:sender onTrackingDocs:notAlreadyStandard selForNonTrackingDocs:@selector(_canMakeTextStandardSize) newScaleFactor:1.0f];
       
  2742 }
       
  2743 
       
  2744 #define VALIDATE(name) \
       
  2745     else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; }
       
  2746 
       
  2747 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item
       
  2748 {
       
  2749     SEL action = [item action];
       
  2750 
       
  2751     if (action == @selector(goBack:)) {
       
  2752         return [self canGoBack];
       
  2753     } else if (action == @selector(goForward:)) {
       
  2754         return [self canGoForward];
       
  2755     } else if (action == @selector(makeTextLarger:)) {
       
  2756         return [self canMakeTextLarger];
       
  2757     } else if (action == @selector(makeTextSmaller:)) {
       
  2758         return [self canMakeTextSmaller];
       
  2759     } else if (action == @selector(makeTextStandardSize:)) {
       
  2760         return [self canMakeTextStandardSize];
       
  2761     } else if (action == @selector(reload:)) {
       
  2762         return [[self mainFrame] _dataSource] != nil;
       
  2763     } else if (action == @selector(stopLoading:)) {
       
  2764         return [self _isLoading];
       
  2765     } else if (action == @selector(toggleContinuousSpellChecking:)) {
       
  2766         BOOL checkMark = NO;
       
  2767         BOOL retVal = NO;
       
  2768         if ([self _continuousCheckingAllowed]) {
       
  2769             checkMark = [self isContinuousSpellCheckingEnabled];
       
  2770             retVal = YES;
       
  2771         }
       
  2772         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
       
  2773             NSMenuItem *menuItem = (NSMenuItem *)item;
       
  2774             [menuItem setState:checkMark ? NSOnState : NSOffState];
       
  2775         }
       
  2776         return retVal;
       
  2777 #ifndef BUILDING_ON_TIGER
       
  2778     } else if (action == @selector(toggleGrammarChecking:)) {
       
  2779         BOOL checkMark = [self isGrammarCheckingEnabled];
       
  2780         if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) {
       
  2781             NSMenuItem *menuItem = (NSMenuItem *)item;
       
  2782             [menuItem setState:checkMark ? NSOnState : NSOffState];
       
  2783         }
       
  2784         return YES;
       
  2785 #endif
       
  2786     }
       
  2787     FOR_EACH_RESPONDER_SELECTOR(VALIDATE)
       
  2788 
       
  2789     return YES;
       
  2790 }
       
  2791 
       
  2792 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
       
  2793 {
       
  2794     BOOL result = [self validateUserInterfaceItemWithoutDelegate:item];
       
  2795     return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);
       
  2796 }
       
  2797 
       
  2798 @end
       
  2799 
       
  2800 @implementation WebView (WebPendingPublic)
       
  2801 
       
  2802 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
       
  2803 {
       
  2804     if (_private->closed)
       
  2805         return NO;
       
  2806     
       
  2807     // Get the frame holding the selection, or start with the main frame
       
  2808     WebFrame *startFrame = [self _selectedOrMainFrame];
       
  2809     
       
  2810     // Search the first frame, then all the other frames, in order
       
  2811     NSView <WebDocumentSearching> *startSearchView = nil;
       
  2812     WebFrame *frame = startFrame;
       
  2813     do {
       
  2814         WebFrame *nextFrame = incrementFrame(frame, forward, wrapFlag);
       
  2815         
       
  2816         BOOL onlyOneFrame = (frame == nextFrame);
       
  2817         ASSERT(!onlyOneFrame || frame == startFrame);
       
  2818         
       
  2819         id <WebDocumentView> view = [[frame frameView] documentView];
       
  2820         if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) {
       
  2821             NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view;
       
  2822             
       
  2823             if (frame == startFrame)
       
  2824                 startSearchView = searchView;
       
  2825             
       
  2826             BOOL foundString;
       
  2827             // In some cases we have to search some content twice; see comment later in this method.
       
  2828             // We can avoid ever doing this in the common one-frame case by passing YES for wrapFlag 
       
  2829             // here, and then bailing out before we get to the code that would search again in the
       
  2830             // same content.
       
  2831             BOOL wrapOnThisPass = wrapFlag && onlyOneFrame;
       
  2832             if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
       
  2833                 foundString = [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass startInSelection:startInSelection];
       
  2834             else
       
  2835                 foundString = [searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass];
       
  2836             
       
  2837             if (foundString) {
       
  2838                 if (frame != startFrame)
       
  2839                     [startFrame _clearSelection];
       
  2840                 [[self window] makeFirstResponder:searchView];
       
  2841                 return YES;
       
  2842             }
       
  2843             
       
  2844             if (onlyOneFrame)
       
  2845                 return NO;
       
  2846         }
       
  2847         frame = nextFrame;
       
  2848     } while (frame && frame != startFrame);
       
  2849     
       
  2850     // 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 
       
  2851     // 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 
       
  2852     // 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
       
  2853     // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice.
       
  2854     // To fix this, we'd need to add a mechanism to specify a range in which to search.
       
  2855     if (wrapFlag && startSearchView) {
       
  2856         BOOL foundString;
       
  2857         if ([startSearchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)])
       
  2858             foundString = [(NSView <WebDocumentIncrementalSearching> *)startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES startInSelection:startInSelection];
       
  2859         else
       
  2860             foundString = [startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES];
       
  2861         if (foundString) {
       
  2862             [[self window] makeFirstResponder:startSearchView];
       
  2863             return YES;
       
  2864         }
       
  2865     }
       
  2866     return NO;
       
  2867 }
       
  2868 
       
  2869 - (void)setHoverFeedbackSuspended:(BOOL)newValue
       
  2870 {
       
  2871     if (_private->hoverFeedbackSuspended == newValue)
       
  2872         return;
       
  2873     
       
  2874     _private->hoverFeedbackSuspended = newValue;
       
  2875     id <WebDocumentView> documentView = [[[self mainFrame] frameView] documentView];
       
  2876     // FIXME: in a perfect world we'd do this in a general way that worked with any document view,
       
  2877     // such as by calling a protocol method or using respondsToSelector or sending a notification.
       
  2878     // But until there is any need for these more general solutions, we'll just hardwire it to work
       
  2879     // with WebHTMLView.
       
  2880     // Note that _hoverFeedbackSuspendedChanged needs to be called only on the main WebHTMLView, not
       
  2881     // on each subframe separately.
       
  2882     if ([documentView isKindOfClass:[WebHTMLView class]])
       
  2883         [(WebHTMLView *)documentView _hoverFeedbackSuspendedChanged];
       
  2884 }
       
  2885 
       
  2886 - (BOOL)isHoverFeedbackSuspended
       
  2887 {
       
  2888     return _private->hoverFeedbackSuspended;
       
  2889 }
       
  2890 
       
  2891 - (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady
       
  2892 {
       
  2893     // by setting this to NO, calls to mainFrameDocument are forced to return nil
       
  2894     // setting this to YES lets it return the actual DOMDocument value
       
  2895     // we use this to tell NSTreeController to reset its observers and clear its state
       
  2896     if (_private->mainFrameDocumentReady == mainFrameDocumentReady)
       
  2897         return;
       
  2898     [self _willChangeValueForKey:_WebMainFrameDocumentKey];
       
  2899     _private->mainFrameDocumentReady = mainFrameDocumentReady;
       
  2900     [self _didChangeValueForKey:_WebMainFrameDocumentKey];
       
  2901     // this will cause observers to call mainFrameDocument where this flag will be checked
       
  2902 }
       
  2903 
       
  2904 // This method name is used by Mail on Tiger (but not post-Tiger), so we shouldn't delete it 
       
  2905 // until the day comes when we're no longer supporting Mail on Tiger.
       
  2906 - (WebFrame *)_frameForCurrentSelection
       
  2907 {
       
  2908     return [self _selectedOrMainFrame];
       
  2909 }
       
  2910 
       
  2911 - (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements
       
  2912 {
       
  2913     _private->tabKeyCyclesThroughElementsChanged = YES;
       
  2914     if (_private->page)
       
  2915         _private->page->setTabKeyCyclesThroughElements(cyclesElements);
       
  2916 }
       
  2917 
       
  2918 - (BOOL)tabKeyCyclesThroughElements
       
  2919 {
       
  2920     return _private->page && _private->page->tabKeyCyclesThroughElements();
       
  2921 }
       
  2922 
       
  2923 - (void)setScriptDebugDelegate:(id)delegate
       
  2924 {
       
  2925     _private->scriptDebugDelegate = delegate;
       
  2926     [_private->scriptDebugDelegateForwarder release];
       
  2927     _private->scriptDebugDelegateForwarder = nil;
       
  2928     if (delegate)
       
  2929         [self _attachScriptDebuggerToAllFrames];
       
  2930     else
       
  2931         [self _detachScriptDebuggerFromAllFrames];
       
  2932 }
       
  2933 
       
  2934 - (id)scriptDebugDelegate
       
  2935 {
       
  2936     return _private->scriptDebugDelegate;
       
  2937 }
       
  2938 
       
  2939 - (BOOL)shouldClose
       
  2940 {
       
  2941     Frame* coreFrame = core([self mainFrame]);
       
  2942     if (!coreFrame)
       
  2943         return YES;
       
  2944     return coreFrame->shouldClose();
       
  2945 }
       
  2946 
       
  2947 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script
       
  2948 {
       
  2949     return [[[self mainFrame] _bridge] aeDescByEvaluatingJavaScriptFromString:script];
       
  2950 }
       
  2951 
       
  2952 - (BOOL)canMarkAllTextMatches
       
  2953 {
       
  2954     WebFrame *frame = [self mainFrame];
       
  2955     do {
       
  2956         id <WebDocumentView> view = [[frame frameView] documentView];
       
  2957         if (view && ![view conformsToProtocol:@protocol(WebMultipleTextMatches)])
       
  2958             return NO;
       
  2959         
       
  2960         frame = incrementFrame(frame, YES, NO);
       
  2961     } while (frame);
       
  2962     
       
  2963     return YES;
       
  2964 }
       
  2965 
       
  2966 - (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit
       
  2967 {
       
  2968     WebFrame *frame = [self mainFrame];
       
  2969     unsigned matchCount = 0;
       
  2970     do {
       
  2971         id <WebDocumentView> view = [[frame frameView] documentView];
       
  2972         if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
       
  2973             [(NSView <WebMultipleTextMatches>*)view  setMarkedTextMatchesAreHighlighted:highlight];
       
  2974         
       
  2975             ASSERT(limit == 0 || matchCount < limit);
       
  2976             matchCount += [(NSView <WebMultipleTextMatches>*)view markAllMatchesForText:string caseSensitive:caseFlag limit:limit == 0 ? 0 : limit - matchCount];
       
  2977 
       
  2978             // Stop looking if we've reached the limit. A limit of 0 means no limit.
       
  2979             if (limit > 0 && matchCount >= limit)
       
  2980                 break;
       
  2981         }
       
  2982         
       
  2983         frame = incrementFrame(frame, YES, NO);
       
  2984     } while (frame);
       
  2985     
       
  2986     return matchCount;
       
  2987 }
       
  2988 
       
  2989 - (void)unmarkAllTextMatches
       
  2990 {
       
  2991     WebFrame *frame = [self mainFrame];
       
  2992     do {
       
  2993         id <WebDocumentView> view = [[frame frameView] documentView];
       
  2994         if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)])
       
  2995             [(NSView <WebMultipleTextMatches>*)view unmarkAllTextMatches];
       
  2996         
       
  2997         frame = incrementFrame(frame, YES, NO);
       
  2998     } while (frame);
       
  2999 }
       
  3000 
       
  3001 - (NSArray *)rectsForTextMatches
       
  3002 {
       
  3003     NSMutableArray *result = [NSMutableArray array];
       
  3004     WebFrame *frame = [self mainFrame];
       
  3005     do {
       
  3006         id <WebDocumentView> view = [[frame frameView] documentView];
       
  3007         if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) {
       
  3008             NSView <WebMultipleTextMatches> *documentView = (NSView <WebMultipleTextMatches> *)view;
       
  3009             NSRect documentViewVisibleRect = [documentView visibleRect];
       
  3010             NSArray *originalRects = [documentView rectsForTextMatches];
       
  3011             unsigned rectCount = [originalRects count];
       
  3012             unsigned rectIndex;
       
  3013             NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       
  3014             for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
       
  3015                 NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue];
       
  3016                 // Clip rect to document view's visible rect so rect is confined to subframe
       
  3017                 r = NSIntersectionRect(r, documentViewVisibleRect);
       
  3018                 if (NSIsEmptyRect(r))
       
  3019                     continue;
       
  3020                 
       
  3021                 // Convert rect to our coordinate system
       
  3022                 r = [documentView convertRect:r toView:self];
       
  3023                 [result addObject:[NSValue valueWithRect:r]];
       
  3024                 if (rectIndex % 10 == 0) {
       
  3025                     [pool drain];
       
  3026                     pool = [[NSAutoreleasePool alloc] init];
       
  3027                 }
       
  3028             }
       
  3029             [pool drain];
       
  3030         }
       
  3031         
       
  3032         frame = incrementFrame(frame, YES, NO);
       
  3033     } while (frame);
       
  3034     
       
  3035     return result;
       
  3036 }
       
  3037 
       
  3038 - (void)scrollDOMRangeToVisible:(DOMRange *)range
       
  3039 {
       
  3040     [[[range startContainer] _bridge] scrollDOMRangeToVisible:range];
       
  3041 }
       
  3042 
       
  3043 - (BOOL)allowsUndo
       
  3044 {
       
  3045     return _private->allowsUndo;
       
  3046 }
       
  3047 
       
  3048 - (void)setAllowsUndo:(BOOL)flag
       
  3049 {
       
  3050     _private->allowsUndo = flag;
       
  3051 }
       
  3052 
       
  3053 @end
       
  3054 
       
  3055 @implementation WebView (WebViewPrintingPrivate)
       
  3056 
       
  3057 - (float)_headerHeight
       
  3058 {
       
  3059     return CallUIDelegateReturningFloat(self, @selector(webViewHeaderHeight:));
       
  3060 }
       
  3061 
       
  3062 - (float)_footerHeight
       
  3063 {
       
  3064     return CallUIDelegateReturningFloat(self, @selector(webViewFooterHeight:));
       
  3065 }
       
  3066 
       
  3067 - (void)_drawHeaderInRect:(NSRect)rect
       
  3068 {
       
  3069 #ifdef DEBUG_HEADER_AND_FOOTER
       
  3070     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
       
  3071     [currentContext saveGraphicsState];
       
  3072     [[NSColor yellowColor] set];
       
  3073     NSRectFill(rect);
       
  3074     [currentContext restoreGraphicsState];
       
  3075 #endif
       
  3076 
       
  3077     SEL selector = @selector(webView:drawHeaderInRect:);
       
  3078     if (![_private->UIDelegate respondsToSelector:selector])
       
  3079         return;
       
  3080 
       
  3081     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
       
  3082     [currentContext saveGraphicsState];
       
  3083 
       
  3084     NSRectClip(rect);
       
  3085     CallUIDelegate(self, selector, rect);
       
  3086 
       
  3087     [currentContext restoreGraphicsState];
       
  3088 }
       
  3089 
       
  3090 - (void)_drawFooterInRect:(NSRect)rect
       
  3091 {
       
  3092 #ifdef DEBUG_HEADER_AND_FOOTER
       
  3093     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
       
  3094     [currentContext saveGraphicsState];
       
  3095     [[NSColor cyanColor] set];
       
  3096     NSRectFill(rect);
       
  3097     [currentContext restoreGraphicsState];
       
  3098 #endif
       
  3099     
       
  3100     SEL selector = @selector(webView:drawFooterInRect:);
       
  3101     if (![_private->UIDelegate respondsToSelector:selector])
       
  3102         return;
       
  3103 
       
  3104     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
       
  3105     [currentContext saveGraphicsState];
       
  3106 
       
  3107     NSRectClip(rect);
       
  3108     CallUIDelegate(self, selector, rect);
       
  3109 
       
  3110     [currentContext restoreGraphicsState];
       
  3111 }
       
  3112 
       
  3113 - (void)_adjustPrintingMarginsForHeaderAndFooter
       
  3114 {
       
  3115     NSPrintOperation *op = [NSPrintOperation currentOperation];
       
  3116     NSPrintInfo *info = [op printInfo];
       
  3117     NSMutableDictionary *infoDictionary = [info dictionary];
       
  3118     
       
  3119     // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the
       
  3120     // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087),
       
  3121     // we stash away the unmodified top and bottom margins the first time this method is called, and we read from
       
  3122     // those stashed-away values on subsequent calls.
       
  3123     float originalTopMargin;
       
  3124     float originalBottomMargin;
       
  3125     NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey];
       
  3126     if (!originalTopMarginNumber) {
       
  3127         ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]);
       
  3128         originalTopMargin = [info topMargin];
       
  3129         originalBottomMargin = [info bottomMargin];
       
  3130         [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey];
       
  3131         [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey];
       
  3132     } else {
       
  3133         ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]);
       
  3134         ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]);
       
  3135         originalTopMargin = [originalTopMarginNumber floatValue];
       
  3136         originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue];
       
  3137     }
       
  3138     
       
  3139     float scale = [op _web_pageSetupScaleFactor];
       
  3140     [info setTopMargin:originalTopMargin + [self _headerHeight] * scale];
       
  3141     [info setBottomMargin:originalBottomMargin + [self _footerHeight] * scale];
       
  3142 }
       
  3143 
       
  3144 - (void)_drawHeaderAndFooter
       
  3145 {
       
  3146     // The header and footer rect height scales with the page, but the width is always
       
  3147     // all the way across the printed page (inset by printing margins).
       
  3148     NSPrintOperation *op = [NSPrintOperation currentOperation];
       
  3149     float scale = [op _web_pageSetupScaleFactor];
       
  3150     NSPrintInfo *printInfo = [op printInfo];
       
  3151     NSSize paperSize = [printInfo paperSize];
       
  3152     float headerFooterLeft = [printInfo leftMargin]/scale;
       
  3153     float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale;
       
  3154     NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] , 
       
  3155                                    headerFooterWidth, [self _footerHeight]);
       
  3156     NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale, 
       
  3157                                    headerFooterWidth, [self _headerHeight]);
       
  3158     
       
  3159     [self _drawHeaderInRect:headerRect];
       
  3160     [self _drawFooterInRect:footerRect];
       
  3161 }
       
  3162 @end
       
  3163 
       
  3164 @implementation WebView (WebDebugBinding)
       
  3165 
       
  3166 - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
       
  3167 {
       
  3168     LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context);
       
  3169     [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
       
  3170 }
       
  3171 
       
  3172 - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
       
  3173 {
       
  3174     LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath);
       
  3175     [super removeObserver:anObserver forKeyPath:keyPath];
       
  3176 }
       
  3177 
       
  3178 @end
       
  3179 
       
  3180 //==========================================================================================
       
  3181 // Editing
       
  3182 
       
  3183 @implementation WebView (WebViewCSS)
       
  3184 
       
  3185 - (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement
       
  3186 {
       
  3187     // FIXME: is this the best level for this conversion?
       
  3188     if (pseudoElement == nil) {
       
  3189         pseudoElement = @"";
       
  3190     }
       
  3191     return [[element ownerDocument] getComputedStyle:element pseudoElement:pseudoElement];
       
  3192 }
       
  3193 
       
  3194 @end
       
  3195 
       
  3196 @implementation WebView (WebViewEditing)
       
  3197 
       
  3198 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
       
  3199 {
       
  3200     Page* page = core(self);
       
  3201     if (!page)
       
  3202         return nil;
       
  3203     return kit(page->mainFrame()->editor()->rangeForPoint(IntPoint([self convertPoint:point toView:nil])).get());
       
  3204 }
       
  3205 
       
  3206 - (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag;
       
  3207 {
       
  3208     // 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
       
  3209     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"])
       
  3210         return YES;
       
  3211     return [[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag];
       
  3212 }
       
  3213 
       
  3214 - (BOOL)maintainsInactiveSelection
       
  3215 {
       
  3216     return NO;
       
  3217 }
       
  3218 
       
  3219 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity
       
  3220 {
       
  3221     Frame* coreFrame = core([self _selectedOrMainFrame]);
       
  3222     if (!coreFrame)
       
  3223         return;
       
  3224 
       
  3225     if (range == nil)
       
  3226         coreFrame->selectionController()->clear();
       
  3227     else {
       
  3228         // Derive the frame to use from the range passed in.
       
  3229         // Using _bridgeForSelectedOrMainFrame could give us a different document than
       
  3230         // the one the range uses.
       
  3231         coreFrame = core([range startContainer])->document()->frame();
       
  3232         if (!coreFrame)
       
  3233             return;
       
  3234 
       
  3235         ExceptionCode ec = 0;
       
  3236         coreFrame->selectionController()->setSelectedRange([range _range], core(selectionAffinity), true, ec);
       
  3237     }
       
  3238 }
       
  3239 
       
  3240 - (DOMRange *)selectedDOMRange
       
  3241 {
       
  3242     Frame* coreFrame = core([self _selectedOrMainFrame]);
       
  3243     if (!coreFrame)
       
  3244         return nil;
       
  3245     return kit(coreFrame->selectionController()->toRange().get());
       
  3246 }
       
  3247 
       
  3248 - (NSSelectionAffinity)selectionAffinity
       
  3249 {
       
  3250     Frame* coreFrame = core([self _selectedOrMainFrame]);
       
  3251     if (!coreFrame)
       
  3252         return NSSelectionAffinityDownstream;
       
  3253     return kit(coreFrame->selectionController()->affinity());
       
  3254 }
       
  3255 
       
  3256 - (void)setEditable:(BOOL)flag
       
  3257 {
       
  3258     if (_private->editable != flag) {
       
  3259         _private->editable = flag;
       
  3260         if (!_private->tabKeyCyclesThroughElementsChanged && _private->page)
       
  3261             _private->page->setTabKeyCyclesThroughElements(!flag);
       
  3262         Frame* mainFrame = [[[self mainFrame] _bridge] _frame];
       
  3263         if (mainFrame) {
       
  3264             if (flag) {
       
  3265                 mainFrame->applyEditingStyleToBodyElement();
       
  3266                 // If the WebView is made editable and the selection is empty, set it to something.
       
  3267                 if (![self selectedDOMRange])
       
  3268                     mainFrame->setSelectionFromNone();
       
  3269             } else
       
  3270                 mainFrame->removeEditingStyleFromBodyElement();
       
  3271         }
       
  3272     }
       
  3273 }
       
  3274 
       
  3275 - (BOOL)isEditable
       
  3276 {
       
  3277     return _private->editable;
       
  3278 }
       
  3279 
       
  3280 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style
       
  3281 {
       
  3282     // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
       
  3283     // change the API to allow this.
       
  3284     [[self _bridgeForSelectedOrMainFrame] setTypingStyle:style withUndoAction:EditActionUnspecified];
       
  3285 }
       
  3286 
       
  3287 - (DOMCSSStyleDeclaration *)typingStyle
       
  3288 {
       
  3289     return [[self _bridgeForSelectedOrMainFrame] typingStyle];
       
  3290 }
       
  3291 
       
  3292 - (void)setSmartInsertDeleteEnabled:(BOOL)flag
       
  3293 {
       
  3294     _private->smartInsertDeleteEnabled = flag;
       
  3295 }
       
  3296 
       
  3297 - (BOOL)smartInsertDeleteEnabled
       
  3298 {
       
  3299     return _private->smartInsertDeleteEnabled;
       
  3300 }
       
  3301 
       
  3302 - (void)setContinuousSpellCheckingEnabled:(BOOL)flag
       
  3303 {
       
  3304     if (continuousSpellCheckingEnabled != flag) {
       
  3305         continuousSpellCheckingEnabled = flag;
       
  3306         [[NSUserDefaults standardUserDefaults] setBool:continuousSpellCheckingEnabled forKey:WebContinuousSpellCheckingEnabled];
       
  3307     }
       
  3308     
       
  3309     if ([self isContinuousSpellCheckingEnabled]) {
       
  3310         [[self class] _preflightSpellChecker];
       
  3311     } else {
       
  3312         [[self mainFrame] _unmarkAllMisspellings];
       
  3313     }
       
  3314 }
       
  3315 
       
  3316 - (BOOL)isContinuousSpellCheckingEnabled
       
  3317 {
       
  3318     return (continuousSpellCheckingEnabled && [self _continuousCheckingAllowed]);
       
  3319 }
       
  3320 
       
  3321 - (NSInteger)spellCheckerDocumentTag
       
  3322 {
       
  3323     if (!_private->hasSpellCheckerDocumentTag) {
       
  3324         _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag];
       
  3325         _private->hasSpellCheckerDocumentTag = YES;
       
  3326     }
       
  3327     return _private->spellCheckerDocumentTag;
       
  3328 }
       
  3329 
       
  3330 - (NSUndoManager *)undoManager
       
  3331 {
       
  3332     if (!_private->allowsUndo)
       
  3333         return nil;
       
  3334 
       
  3335     NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self];
       
  3336     if (undoManager)
       
  3337         return undoManager;
       
  3338 
       
  3339     return [super undoManager];
       
  3340 }
       
  3341 
       
  3342 - (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector
       
  3343 {
       
  3344     NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
       
  3345     if ([_private->editingDelegate respondsToSelector:selector])
       
  3346         [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self];
       
  3347 }
       
  3348 
       
  3349 - (void)setEditingDelegate:(id)delegate
       
  3350 {
       
  3351     if (_private->editingDelegate == delegate)
       
  3352         return;
       
  3353 
       
  3354     NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
       
  3355 
       
  3356     // remove notifications from current delegate
       
  3357     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidBeginEditingNotification object:self];
       
  3358     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeNotification object:self];
       
  3359     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidEndEditingNotification object:self];
       
  3360     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeTypingStyleNotification object:self];
       
  3361     [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeSelectionNotification object:self];
       
  3362     
       
  3363     _private->editingDelegate = delegate;
       
  3364     [_private->editingDelegateForwarder release];
       
  3365     _private->editingDelegateForwarder = nil;
       
  3366     
       
  3367     // add notifications for new delegate
       
  3368     [self registerForEditingDelegateNotification:WebViewDidBeginEditingNotification selector:@selector(webViewDidBeginEditing:)];
       
  3369     [self registerForEditingDelegateNotification:WebViewDidChangeNotification selector:@selector(webViewDidChange:)];
       
  3370     [self registerForEditingDelegateNotification:WebViewDidEndEditingNotification selector:@selector(webViewDidEndEditing:)];
       
  3371     [self registerForEditingDelegateNotification:WebViewDidChangeTypingStyleNotification selector:@selector(webViewDidChangeTypingStyle:)];
       
  3372     [self registerForEditingDelegateNotification:WebViewDidChangeSelectionNotification selector:@selector(webViewDidChangeSelection:)];
       
  3373 }
       
  3374 
       
  3375 - (id)editingDelegate
       
  3376 {
       
  3377     return _private->editingDelegate;
       
  3378 }
       
  3379 
       
  3380 - (DOMCSSStyleDeclaration *)styleDeclarationWithText:(NSString *)text
       
  3381 {
       
  3382     // FIXME: Should this really be attached to the document with the current selection?
       
  3383     DOMCSSStyleDeclaration *decl = [[[self _selectedOrMainFrame] DOMDocument] createCSSStyleDeclaration];
       
  3384     [decl setCssText:text];
       
  3385     return decl;
       
  3386 }
       
  3387 
       
  3388 @end
       
  3389 
       
  3390 @implementation WebView (WebViewGrammarChecking)
       
  3391 
       
  3392 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze
       
  3393 - (BOOL)isGrammarCheckingEnabled
       
  3394 {
       
  3395 #ifdef BUILDING_ON_TIGER
       
  3396     return NO;
       
  3397 #else
       
  3398     return grammarCheckingEnabled;
       
  3399 #endif
       
  3400 }
       
  3401 
       
  3402 #ifndef BUILDING_ON_TIGER
       
  3403 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze
       
  3404 - (void)setGrammarCheckingEnabled:(BOOL)flag
       
  3405 {
       
  3406     if (grammarCheckingEnabled == flag)
       
  3407         return;
       
  3408     
       
  3409     grammarCheckingEnabled = flag;
       
  3410     [[NSUserDefaults standardUserDefaults] setBool:grammarCheckingEnabled forKey:WebGrammarCheckingEnabled];    
       
  3411     
       
  3412     // FIXME 4811447: workaround for lack of API
       
  3413     NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker];
       
  3414     if ([spellChecker respondsToSelector:@selector(_updateGrammar)])
       
  3415         [spellChecker performSelector:@selector(_updateGrammar)];
       
  3416     
       
  3417     // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here
       
  3418     // because grammar checking only occurs on code paths that already preflight spell checking appropriately.
       
  3419     
       
  3420     if (![self isGrammarCheckingEnabled])
       
  3421         [[self mainFrame] _unmarkAllBadGrammar];
       
  3422 }
       
  3423 
       
  3424 // FIXME: This method should be merged into WebIBActions when we're not in API freeze
       
  3425 - (void)toggleGrammarChecking:(id)sender
       
  3426 {
       
  3427     [self setGrammarCheckingEnabled:![self isGrammarCheckingEnabled]];
       
  3428 }
       
  3429 #endif
       
  3430 
       
  3431 @end
       
  3432 
       
  3433 @implementation WebView (WebViewUndoableEditing)
       
  3434 
       
  3435 - (void)replaceSelectionWithNode:(DOMNode *)node
       
  3436 {
       
  3437     [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:NO];
       
  3438 }    
       
  3439 
       
  3440 - (void)replaceSelectionWithText:(NSString *)text
       
  3441 {
       
  3442     [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithText:text selectReplacement:YES smartReplace:NO];
       
  3443 }
       
  3444 
       
  3445 - (void)replaceSelectionWithMarkupString:(NSString *)markupString
       
  3446 {
       
  3447     [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithMarkupString:markupString baseURLString:nil selectReplacement:YES smartReplace:NO];
       
  3448 }
       
  3449 
       
  3450 - (void)replaceSelectionWithArchive:(WebArchive *)archive
       
  3451 {
       
  3452     [[[[self _bridgeForSelectedOrMainFrame] webFrame] _dataSource] _replaceSelectionWithArchive:archive selectReplacement:YES];
       
  3453 }
       
  3454 
       
  3455 - (void)deleteSelection
       
  3456 {
       
  3457     WebFrame *webFrame = [self _selectedOrMainFrame];
       
  3458     Frame* coreFrame = core(webFrame);
       
  3459     if (coreFrame)
       
  3460         coreFrame->editor()->deleteSelectionWithSmartDelete([(WebHTMLView *)[[webFrame frameView] documentView] _canSmartCopyOrDelete]);
       
  3461 }
       
  3462     
       
  3463 - (void)applyStyle:(DOMCSSStyleDeclaration *)style
       
  3464 {
       
  3465     // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to
       
  3466     // change the API to allow this.
       
  3467     WebFrame *webFrame = [self _selectedOrMainFrame];
       
  3468     Frame* coreFrame = core(webFrame);
       
  3469     if (coreFrame)
       
  3470         coreFrame->editor()->applyStyle(core(style));
       
  3471 }
       
  3472 
       
  3473 @end
       
  3474 
       
  3475 @implementation WebView (WebViewEditingActions)
       
  3476 
       
  3477 - (void)_performResponderOperation:(SEL)selector with:(id)parameter
       
  3478 {
       
  3479     static BOOL reentered = NO;
       
  3480     if (reentered) {
       
  3481         [[self nextResponder] tryToPerform:selector with:parameter];
       
  3482         return;
       
  3483     }
       
  3484 
       
  3485     // There are two possibilities here.
       
  3486     //
       
  3487     // One is that WebView has been called in its role as part of the responder chain.
       
  3488     // In that case, it's fine to call the first responder and end up calling down the
       
  3489     // responder chain again. Later we will return here with reentered = YES and continue
       
  3490     // past the WebView.
       
  3491     //
       
  3492     // The other is that we are being called directly, in which case we want to pass the
       
  3493     // selector down to the view inside us that can handle it, and continue down the
       
  3494     // responder chain as usual.
       
  3495 
       
  3496     // Pass this selector down to the first responder.
       
  3497     NSResponder *responder = [self _responderForResponderOperations];
       
  3498     reentered = YES;
       
  3499     [responder tryToPerform:selector with:parameter];
       
  3500     reentered = NO;
       
  3501 }
       
  3502 
       
  3503 #define FORWARD(name) \
       
  3504     - (void)name:(id)sender { [self _performResponderOperation:_cmd with:sender]; }
       
  3505 
       
  3506 FOR_EACH_RESPONDER_SELECTOR(FORWARD)
       
  3507 
       
  3508 - (void)insertText:(NSString *)text
       
  3509 {
       
  3510     [self _performResponderOperation:_cmd with:text];
       
  3511 }
       
  3512 
       
  3513 @end
       
  3514 
       
  3515 @implementation WebView (WebViewEditingInMail)
       
  3516 
       
  3517 - (void)_insertNewlineInQuotedContent;
       
  3518 {
       
  3519     [[self _bridgeForSelectedOrMainFrame] insertParagraphSeparatorInQuotedContent];
       
  3520 }
       
  3521 
       
  3522 - (void)_replaceSelectionWithNode:(DOMNode *)node matchStyle:(BOOL)matchStyle
       
  3523 {
       
  3524     [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:matchStyle];
       
  3525 }
       
  3526 
       
  3527 @end
       
  3528 
       
  3529 static WebFrameView *containingFrameView(NSView *view)
       
  3530 {
       
  3531     while (view && ![view isKindOfClass:[WebFrameView class]])
       
  3532         view = [view superview];
       
  3533     return (WebFrameView *)view;    
       
  3534 }
       
  3535 
       
  3536 @implementation WebView (WebFileInternal)
       
  3537 
       
  3538 + (void)_setCacheModel:(WebCacheModel)cacheModel
       
  3539 {
       
  3540     if (s_didSetCacheModel && cacheModel == s_cacheModel)
       
  3541         return;
       
  3542 
       
  3543     NSString *nsurlCacheDirectory = [(NSString *)WKCopyFoundationCacheDirectory() autorelease];
       
  3544     if (!nsurlCacheDirectory)
       
  3545         nsurlCacheDirectory = NSHomeDirectory();
       
  3546 
       
  3547     // As a fudge factor, use 1000 instead of 1024, in case the reported byte 
       
  3548     // count doesn't align exactly to a megabyte boundary.
       
  3549     vm_size_t memSize = WebMemorySize() / 1024 / 1000;
       
  3550     unsigned long long diskFreeSize = WebVolumeFreeSize(nsurlCacheDirectory) / 1024 / 1000;
       
  3551     NSURLCache *nsurlCache = [NSURLCache sharedURLCache];
       
  3552 
       
  3553     unsigned cacheTotalCapacity = 0;
       
  3554     unsigned cacheMinDeadCapacity = 0;
       
  3555     unsigned cacheMaxDeadCapacity = 0;
       
  3556 
       
  3557     unsigned pageCacheCapacity = 0;
       
  3558 
       
  3559     NSUInteger nsurlCacheMemoryCapacity = 0;
       
  3560     NSUInteger nsurlCacheDiskCapacity = 0;
       
  3561 
       
  3562     switch (cacheModel) {
       
  3563     case WebCacheModelDocumentViewer: {
       
  3564         // Page cache capacity (in pages)
       
  3565         pageCacheCapacity = 0;
       
  3566 
       
  3567         // Object cache capacities (in bytes)
       
  3568         if (memSize >= 4096)
       
  3569             cacheTotalCapacity = 256 * 1024 * 1024;
       
  3570         else if (memSize >= 3072)
       
  3571             cacheTotalCapacity = 192 * 1024 * 1024;
       
  3572         else if (memSize >= 2048)
       
  3573             cacheTotalCapacity = 128 * 1024 * 1024;
       
  3574         else if (memSize >= 1536)
       
  3575             cacheTotalCapacity = 86 * 1024 * 1024;
       
  3576         else if (memSize >= 1024)
       
  3577             cacheTotalCapacity = 64 * 1024 * 1024;
       
  3578         else if (memSize >= 512)
       
  3579             cacheTotalCapacity = 32 * 1024 * 1024;
       
  3580         else if (memSize >= 256)
       
  3581             cacheTotalCapacity = 16 * 1024 * 1024; 
       
  3582 
       
  3583         cacheMinDeadCapacity = 0;
       
  3584         cacheMaxDeadCapacity = 0;
       
  3585 
       
  3586         // Foundation memory cache capacity (in bytes)
       
  3587         nsurlCacheMemoryCapacity = 0;
       
  3588 
       
  3589         // Foundation disk cache capacity (in bytes)
       
  3590         nsurlCacheDiskCapacity = [nsurlCache diskCapacity];
       
  3591 
       
  3592         break;
       
  3593     }
       
  3594     case WebCacheModelDocumentBrowser: {
       
  3595         // Page cache capacity (in pages)
       
  3596         if (memSize >= 1024)
       
  3597             pageCacheCapacity = 3;
       
  3598         else if (memSize >= 512)
       
  3599             pageCacheCapacity = 2;
       
  3600         else if (memSize >= 256)
       
  3601             pageCacheCapacity = 1;
       
  3602         else
       
  3603             pageCacheCapacity = 0;
       
  3604 
       
  3605         // Object cache capacities (in bytes)
       
  3606         if (memSize >= 4096)
       
  3607             cacheTotalCapacity = 256 * 1024 * 1024;
       
  3608         else if (memSize >= 3072)
       
  3609             cacheTotalCapacity = 192 * 1024 * 1024;
       
  3610         else if (memSize >= 2048)
       
  3611             cacheTotalCapacity = 128 * 1024 * 1024;
       
  3612         else if (memSize >= 1536)
       
  3613             cacheTotalCapacity = 86 * 1024 * 1024;
       
  3614         else if (memSize >= 1024)
       
  3615             cacheTotalCapacity = 64 * 1024 * 1024;
       
  3616         else if (memSize >= 512)
       
  3617             cacheTotalCapacity = 32 * 1024 * 1024;
       
  3618         else if (memSize >= 256)
       
  3619             cacheTotalCapacity = 16 * 1024 * 1024; 
       
  3620 
       
  3621         cacheMinDeadCapacity = cacheTotalCapacity / 8;
       
  3622         cacheMaxDeadCapacity = cacheTotalCapacity / 4;
       
  3623 
       
  3624         // Foundation memory cache capacity (in bytes)
       
  3625         if (memSize >= 2048)
       
  3626             nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
       
  3627         else if (memSize >= 1024)
       
  3628             nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
       
  3629         else if (memSize >= 512)
       
  3630             nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
       
  3631         else
       
  3632             nsurlCacheMemoryCapacity =      512 * 1024; 
       
  3633 
       
  3634         // Foundation disk cache capacity (in bytes)
       
  3635         if (diskFreeSize >= 16384)
       
  3636             nsurlCacheDiskCapacity = 50 * 1024 * 1024;
       
  3637         else if (diskFreeSize >= 8192)
       
  3638             nsurlCacheDiskCapacity = 40 * 1024 * 1024;
       
  3639         else if (diskFreeSize >= 4096)
       
  3640             nsurlCacheDiskCapacity = 30 * 1024 * 1024;
       
  3641         else
       
  3642             nsurlCacheDiskCapacity = 20 * 1024 * 1024;
       
  3643 
       
  3644         break;
       
  3645     }
       
  3646     case WebCacheModelPrimaryWebBrowser: {
       
  3647         // Page cache capacity (in pages)
       
  3648         // (Research indicates that value / page drops substantially after 3 pages.)
       
  3649         if (memSize >= 8192)
       
  3650             pageCacheCapacity = 7;
       
  3651         if (memSize >= 4096)
       
  3652             pageCacheCapacity = 6;
       
  3653         else if (memSize >= 2048)
       
  3654             pageCacheCapacity = 5;
       
  3655         else if (memSize >= 1024)
       
  3656             pageCacheCapacity = 4;
       
  3657         else if (memSize >= 512)
       
  3658             pageCacheCapacity = 3;
       
  3659         else if (memSize >= 256)
       
  3660             pageCacheCapacity = 2;
       
  3661         else
       
  3662             pageCacheCapacity = 1;
       
  3663 
       
  3664         // Object cache capacities (in bytes)
       
  3665         // (Testing indicates that value / MB depends heavily on content and
       
  3666         // browsing pattern. Even growth above 128MB can have substantial 
       
  3667         // value / MB for some content / browsing patterns.)
       
  3668         if (memSize >= 4096)
       
  3669             cacheTotalCapacity = 512 * 1024 * 1024;
       
  3670         else if (memSize >= 3072)
       
  3671             cacheTotalCapacity = 384 * 1024 * 1024;
       
  3672         else if (memSize >= 2048)
       
  3673             cacheTotalCapacity = 256 * 1024 * 1024;
       
  3674         else if (memSize >= 1536)
       
  3675             cacheTotalCapacity = 172 * 1024 * 1024;
       
  3676         else if (memSize >= 1024)
       
  3677             cacheTotalCapacity = 128 * 1024 * 1024;
       
  3678         else if (memSize >= 512)
       
  3679             cacheTotalCapacity = 64 * 1024 * 1024;
       
  3680         else if (memSize >= 256)
       
  3681             cacheTotalCapacity = 32 * 1024 * 1024; 
       
  3682 
       
  3683         cacheMinDeadCapacity = cacheTotalCapacity / 4;
       
  3684         cacheMaxDeadCapacity = cacheTotalCapacity / 2;
       
  3685 
       
  3686         // This code is here to avoid a PLT regression. We can remove it if we
       
  3687         // can prove that the overall system gain would justify the regression.
       
  3688         cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity);
       
  3689 
       
  3690         // Foundation memory cache capacity (in bytes)
       
  3691         // (These values are small because WebCore does most caching itself.)
       
  3692         if (memSize >= 1024)
       
  3693             nsurlCacheMemoryCapacity = 4 * 1024 * 1024;
       
  3694         else if (memSize >= 512)
       
  3695             nsurlCacheMemoryCapacity = 2 * 1024 * 1024;
       
  3696         else if (memSize >= 256)
       
  3697             nsurlCacheMemoryCapacity = 1 * 1024 * 1024;
       
  3698         else
       
  3699             nsurlCacheMemoryCapacity =      512 * 1024; 
       
  3700 
       
  3701         // Foundation disk cache capacity (in bytes)
       
  3702         if (diskFreeSize >= 16384)
       
  3703             nsurlCacheDiskCapacity = 175 * 1024 * 1024;
       
  3704         else if (diskFreeSize >= 8192)
       
  3705             nsurlCacheDiskCapacity = 150 * 1024 * 1024;
       
  3706         else if (diskFreeSize >= 4096)
       
  3707             nsurlCacheDiskCapacity = 125 * 1024 * 1024;
       
  3708         else if (diskFreeSize >= 2048)
       
  3709             nsurlCacheDiskCapacity = 100 * 1024 * 1024;
       
  3710         else if (diskFreeSize >= 1024)
       
  3711             nsurlCacheDiskCapacity = 75 * 1024 * 1024;
       
  3712         else
       
  3713             nsurlCacheDiskCapacity = 50 * 1024 * 1024;
       
  3714 
       
  3715         break;
       
  3716     }
       
  3717     default:
       
  3718         ASSERT_NOT_REACHED();
       
  3719     };
       
  3720 
       
  3721 #ifdef BUILDING_ON_TIGER
       
  3722     // Don't use a big Foundation disk cache on Tiger because, according to the 
       
  3723     // PLT, the Foundation disk cache on Tiger is slower than the network. 
       
  3724     nsurlCacheDiskCapacity = [[NSURLCache sharedURLCache] diskCapacity];
       
  3725 #else
       
  3726     // Don't use a big Foundation disk cache on older versions of Leopard because
       
  3727     // doing so causes a SPOD on launch (<rdar://problem/5465260>).
       
  3728     if (NSVersionOfRunTimeLibrary("CFNetwork") < WEBKIT_FIRST_CFNETWORK_VERSION_WITH_LARGE_DISK_CACHE_FIX)
       
  3729         nsurlCacheDiskCapacity = [[NSURLCache sharedURLCache] diskCapacity];
       
  3730 #endif
       
  3731 
       
  3732     // Don't shrink a big disk cache, since that would cause churn.
       
  3733     nsurlCacheDiskCapacity = max(nsurlCacheDiskCapacity, [nsurlCache diskCapacity]);
       
  3734 
       
  3735     cache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity);
       
  3736     pageCache()->setCapacity(pageCacheCapacity);
       
  3737     [nsurlCache setMemoryCapacity:nsurlCacheMemoryCapacity];
       
  3738     [nsurlCache setDiskCapacity:nsurlCacheDiskCapacity];
       
  3739 
       
  3740     s_cacheModel = cacheModel;
       
  3741     s_didSetCacheModel = YES;
       
  3742 }
       
  3743 
       
  3744 + (WebCacheModel)_cacheModel
       
  3745 {
       
  3746     return s_cacheModel;
       
  3747 }
       
  3748 
       
  3749 + (WebCacheModel)_didSetCacheModel
       
  3750 {
       
  3751     return s_didSetCacheModel;
       
  3752 }
       
  3753 
       
  3754 + (WebCacheModel)_maxCacheModelInAnyInstance
       
  3755 {
       
  3756     WebCacheModel cacheModel = WebCacheModelDocumentViewer;
       
  3757     NSEnumerator *enumerator = [(NSMutableSet *)allWebViewsSet objectEnumerator];
       
  3758     while (WebPreferences *preferences = [[enumerator nextObject] preferences])
       
  3759         cacheModel = max(cacheModel, [preferences cacheModel]);
       
  3760     return cacheModel;
       
  3761 }
       
  3762 
       
  3763 + (void)_preferencesChangedNotification:(NSNotification *)notification
       
  3764 {
       
  3765     WebPreferences *preferences = (WebPreferences *)[notification object];
       
  3766     ASSERT([preferences isKindOfClass:[WebPreferences class]]);
       
  3767 
       
  3768     WebCacheModel cacheModel = [preferences cacheModel];
       
  3769     if (![self _didSetCacheModel] || cacheModel > [self _cacheModel])
       
  3770         [self _setCacheModel:cacheModel];
       
  3771     else if (cacheModel < [self _cacheModel])
       
  3772         [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])];
       
  3773 }
       
  3774 
       
  3775 + (void)_preferencesRemovedNotification:(NSNotification *)notification
       
  3776 {
       
  3777     WebPreferences *preferences = (WebPreferences *)[notification object];
       
  3778     ASSERT([preferences isKindOfClass:[WebPreferences class]]);
       
  3779 
       
  3780     if ([preferences cacheModel] == [self _cacheModel])
       
  3781         [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])];
       
  3782 }
       
  3783 
       
  3784 - (WebFrame *)_focusedFrame
       
  3785 {
       
  3786     NSResponder *resp = [[self window] firstResponder];
       
  3787     if (resp && [resp isKindOfClass:[NSView class]] && [(NSView *)resp isDescendantOf:[[self mainFrame] frameView]]) {
       
  3788         WebFrameView *frameView = containingFrameView((NSView *)resp);
       
  3789         ASSERT(frameView != nil);
       
  3790         return [frameView webFrame];
       
  3791     }
       
  3792     
       
  3793     return nil;
       
  3794 }
       
  3795 
       
  3796 - (WebFrame *)_selectedOrMainFrame
       
  3797 {
       
  3798     WebFrame *result = [self selectedFrame];
       
  3799     if (result == nil)
       
  3800         result = [self mainFrame];
       
  3801     return result;
       
  3802 }
       
  3803 
       
  3804 - (WebFrameBridge *)_bridgeForSelectedOrMainFrame
       
  3805 {
       
  3806     return [[self _selectedOrMainFrame] _bridge];
       
  3807 }
       
  3808 
       
  3809 - (BOOL)_isLoading
       
  3810 {
       
  3811     WebFrame *mainFrame = [self mainFrame];
       
  3812     return [[mainFrame _dataSource] isLoading]
       
  3813         || [[mainFrame provisionalDataSource] isLoading];
       
  3814 }
       
  3815 
       
  3816 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point
       
  3817 {
       
  3818     if (_private->closed)
       
  3819         return nil;
       
  3820     NSView *view = [self hitTest:[[self superview] convertPoint:point fromView:nil]];
       
  3821     if (![view isDescendantOf:[[self mainFrame] frameView]])
       
  3822         return nil;
       
  3823     WebFrameView *frameView = containingFrameView(view);
       
  3824     ASSERT(frameView);
       
  3825     return frameView;
       
  3826 }
       
  3827 
       
  3828 + (void)_preflightSpellCheckerNow:(id)sender
       
  3829 {
       
  3830     [[NSSpellChecker sharedSpellChecker] _preflightChosenSpellServer];
       
  3831 }
       
  3832 
       
  3833 + (void)_preflightSpellChecker
       
  3834 {
       
  3835     // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch.
       
  3836     if ([NSSpellChecker sharedSpellCheckerExists]) {
       
  3837         [self _preflightSpellCheckerNow:self];
       
  3838     } else {
       
  3839         [self performSelector:@selector(_preflightSpellCheckerNow:) withObject:self afterDelay:2.0];
       
  3840     }
       
  3841 }
       
  3842 
       
  3843 - (BOOL)_continuousCheckingAllowed
       
  3844 {
       
  3845     static BOOL allowContinuousSpellChecking = YES;
       
  3846     static BOOL readAllowContinuousSpellCheckingDefault = NO;
       
  3847     if (!readAllowContinuousSpellCheckingDefault) {
       
  3848         if ([[NSUserDefaults standardUserDefaults] objectForKey:@"NSAllowContinuousSpellChecking"]) {
       
  3849             allowContinuousSpellChecking = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSAllowContinuousSpellChecking"];
       
  3850         }
       
  3851         readAllowContinuousSpellCheckingDefault = YES;
       
  3852     }
       
  3853     return allowContinuousSpellChecking;
       
  3854 }
       
  3855 
       
  3856 - (NSResponder *)_responderForResponderOperations
       
  3857 {
       
  3858     NSResponder *responder = [[self window] firstResponder];
       
  3859     WebFrameView *mainFrameView = [[self mainFrame] frameView];
       
  3860     
       
  3861     // If the current responder is outside of the webview, use our main frameView or its
       
  3862     // document view. We also do this for subviews of self that are siblings of the main
       
  3863     // frameView since clients might insert non-webview-related views there (see 4552713).
       
  3864     if (responder != self && ![mainFrameView _web_firstResponderIsSelfOrDescendantView]) {
       
  3865         responder = [mainFrameView documentView];
       
  3866         if (!responder)
       
  3867             responder = mainFrameView;
       
  3868     }
       
  3869     return responder;
       
  3870 }
       
  3871 
       
  3872 - (void)_openFrameInNewWindowFromMenu:(NSMenuItem *)sender
       
  3873 {
       
  3874     ASSERT_ARG(sender, [sender isKindOfClass:[NSMenuItem class]]);
       
  3875 
       
  3876     NSDictionary *element = [sender representedObject];
       
  3877     ASSERT([element isKindOfClass:[NSDictionary class]]);
       
  3878     
       
  3879     NSURLRequest *request = [[[[element objectForKey:WebElementFrameKey] dataSource] request] copy];
       
  3880     ASSERT(request);
       
  3881     
       
  3882     [self _openNewWindowWithRequest:request];
       
  3883     [request release];
       
  3884 }
       
  3885 
       
  3886 - (void)_searchWithGoogleFromMenu:(id)sender
       
  3887 {
       
  3888     id documentView = [[[self selectedFrame] frameView] documentView];
       
  3889     if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) {
       
  3890         return;
       
  3891     }
       
  3892     
       
  3893     NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
       
  3894     if ([selectedString length] == 0) {
       
  3895         return;
       
  3896     }
       
  3897     
       
  3898     NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
       
  3899     [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
       
  3900     NSMutableString *s = [selectedString mutableCopy];
       
  3901     const unichar nonBreakingSpaceCharacter = 0xA0;
       
  3902     NSString *nonBreakingSpaceString = [NSString stringWithCharacters:&nonBreakingSpaceCharacter length:1];
       
  3903     [s replaceOccurrencesOfString:nonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
       
  3904     [pasteboard setString:s forType:NSStringPboardType];
       
  3905     [s release];
       
  3906     
       
  3907     // FIXME: seems fragile to use the service by name, but this is what AppKit does
       
  3908     NSPerformService(@"Search With Google", pasteboard);
       
  3909 }
       
  3910 
       
  3911 - (void)_searchWithSpotlightFromMenu:(id)sender
       
  3912 {
       
  3913     id documentView = [[[self selectedFrame] frameView] documentView];
       
  3914     if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) {
       
  3915         return;
       
  3916     }
       
  3917     
       
  3918     NSString *selectedString = [(id <WebDocumentText>)documentView selectedString];
       
  3919     if ([selectedString length] == 0) {
       
  3920         return;
       
  3921     }
       
  3922 
       
  3923     (void)HISearchWindowShow((CFStringRef)selectedString, kNilOptions);
       
  3924 }
       
  3925 
       
  3926 // Slightly funky method that lets us have one copy of the logic for finding docViews that can do
       
  3927 // text sizing.  It returns whether it found any "suitable" doc views.  It sends sel to any suitable
       
  3928 // doc views, or if sel==0 we do nothing to them.  For doc views that track our size factor, they are
       
  3929 // suitable if doTrackingViews==YES (which in practice means that our size factor isn't at its max or
       
  3930 // min).  For doc views that don't track it, we send them testSel to determine suitablility.  If we
       
  3931 // do find any suitable tracking doc views and newScaleFactor!=0, we will set the common scale factor
       
  3932 // to that new factor before we send sel to any of them. 
       
  3933 - (BOOL)_performTextSizingSelector:(SEL)sel withObject:(id)arg onTrackingDocs:(BOOL)doTrackingViews selForNonTrackingDocs:(SEL)testSel newScaleFactor:(float)newScaleFactor
       
  3934 {
       
  3935     if ([[self mainFrame] _dataSource] == nil)
       
  3936         return NO;
       
  3937     
       
  3938     BOOL foundSome = NO;
       
  3939     NSArray *docViews = [[self mainFrame] _documentViews];
       
  3940     for (int i = [docViews count]-1; i >= 0; i--) {
       
  3941         id docView = [docViews objectAtIndex:i];
       
  3942         if ([docView conformsToProtocol:@protocol(_WebDocumentTextSizing)]) {
       
  3943             id <_WebDocumentTextSizing> sizingDocView = (id <_WebDocumentTextSizing>)docView;
       
  3944             BOOL isSuitable;
       
  3945             if ([sizingDocView _tracksCommonSizeFactor]) {
       
  3946                 isSuitable = doTrackingViews;
       
  3947                 if (isSuitable && newScaleFactor != 0)
       
  3948                     _private->textSizeMultiplier = newScaleFactor;
       
  3949             } else {
       
  3950                 // Incantation to perform a selector returning a BOOL.
       
  3951                 isSuitable = ((BOOL(*)(id, SEL))objc_msgSend)(sizingDocView, testSel);
       
  3952             }
       
  3953             
       
  3954             if (isSuitable) {
       
  3955                 if (sel != 0) {
       
  3956                     foundSome = YES;
       
  3957                     [sizingDocView performSelector:sel withObject:arg];
       
  3958                 } else {
       
  3959                     // if we're just called for the benefit of the return value, we can return at first match
       
  3960                     return YES;
       
  3961                 }
       
  3962             }
       
  3963         }
       
  3964     }
       
  3965     
       
  3966     return foundSome;
       
  3967 }
       
  3968 
       
  3969 - (void)_notifyTextSizeMultiplierChanged
       
  3970 {
       
  3971     if ([[self mainFrame] _dataSource] == nil)
       
  3972         return;
       
  3973 
       
  3974     NSArray *docViews = [[self mainFrame] _documentViews];
       
  3975     for (int i = [docViews count]-1; i >= 0; i--) {
       
  3976         id docView = [docViews objectAtIndex:i];
       
  3977         if ([docView conformsToProtocol:@protocol(_WebDocumentTextSizing)] == NO)
       
  3978             continue;
       
  3979 
       
  3980         id <_WebDocumentTextSizing> sizingDocView = (id <_WebDocumentTextSizing>)docView;
       
  3981         if ([sizingDocView _tracksCommonSizeFactor])
       
  3982             [sizingDocView _textSizeMultiplierChanged];
       
  3983     }
       
  3984 
       
  3985 }
       
  3986 
       
  3987 @end
       
  3988 
       
  3989 @implementation WebView (WebViewInternal)
       
  3990 
       
  3991 - (BOOL)_becomingFirstResponderFromOutside
       
  3992 {
       
  3993     return _private->becomingFirstResponderFromOutside;
       
  3994 }
       
  3995 
       
  3996 - (void)_receivedIconChangedNotification:(NSNotification *)notification
       
  3997 {
       
  3998     // Get the URL for this notification
       
  3999     NSDictionary *userInfo = [notification userInfo];
       
  4000     ASSERT([userInfo isKindOfClass:[NSDictionary class]]);
       
  4001     NSString *urlString = [userInfo objectForKey:WebIconNotificationUserInfoURLKey];
       
  4002     ASSERT([urlString isKindOfClass:[NSString class]]);
       
  4003     
       
  4004     // If that URL matches the current main frame, dispatch the delegate call, which will also unregister
       
  4005     // us for this notification
       
  4006     if ([[self mainFrameURL] isEqualTo:urlString])
       
  4007         [self _dispatchDidReceiveIconFromWebFrame:[self mainFrame]];
       
  4008 }
       
  4009 
       
  4010 - (void)_registerForIconNotification:(BOOL)listen
       
  4011 {
       
  4012     if (listen)
       
  4013         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_receivedIconChangedNotification:) name:WebIconDatabaseDidAddIconNotification object:nil];        
       
  4014     else
       
  4015         [[NSNotificationCenter defaultCenter] removeObserver:self name:WebIconDatabaseDidAddIconNotification object:nil];
       
  4016 }
       
  4017 
       
  4018 - (void)_dispatchDidReceiveIconFromWebFrame:(WebFrame *)webFrame
       
  4019 {
       
  4020     // FIXME: This willChangeValueForKey call is too late, because the icon has already changed by now.
       
  4021     [self _willChangeValueForKey:_WebMainFrameIconKey];
       
  4022     
       
  4023     // 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
       
  4024     // notification any longer
       
  4025     [self _registerForIconNotification:NO];
       
  4026 
       
  4027     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(self);
       
  4028     if (implementations.didReceiveIconForFrameFunc) {
       
  4029         Image* image = iconDatabase()->iconForPageURL(core(webFrame)->loader()->url().url(), IntSize(16, 16));
       
  4030         if (NSImage *icon = webGetNSImage(image, NSMakeSize(16, 16)))
       
  4031             CallFrameLoadDelegate(implementations.didReceiveIconForFrameFunc, self, @selector(webView:didReceiveIcon:forFrame:), icon, webFrame);
       
  4032     }
       
  4033 
       
  4034     [self _didChangeValueForKey:_WebMainFrameIconKey];
       
  4035 }
       
  4036 
       
  4037 - (NSString *)_userVisibleBundleVersionFromFullVersion:(NSString *)fullVersion
       
  4038 {
       
  4039     // If the version is 4 digits long or longer, then the first digit represents
       
  4040     // the version of the OS. Our user agent string should not include this first digit,
       
  4041     // so strip it off and report the rest as the version. <rdar://problem/4997547>
       
  4042     NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
       
  4043     if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4)
       
  4044         return [fullVersion substringFromIndex:1];
       
  4045     if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4)
       
  4046         return [fullVersion substringFromIndex:1];
       
  4047     return fullVersion;
       
  4048 }
       
  4049 
       
  4050 - (NSString *)_userAgentWithApplicationName:(NSString *)applicationName andWebKitVersion:(NSString *)version
       
  4051 {
       
  4052     NSString *language = [NSUserDefaults _webkit_preferredLanguageCode];
       
  4053     if ([applicationName length])
       
  4054         return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X; %@) AppleWebKit/%@ (KHTML, like Gecko) %@", language, version, applicationName];
       
  4055     return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X; %@) AppleWebKit/%@ (KHTML, like Gecko)", language, version];
       
  4056 }
       
  4057 
       
  4058 // Get the appropriate user-agent string for a particular URL.
       
  4059 - (WebCore::String)_userAgentForURL:(const WebCore::KURL&)url
       
  4060 {
       
  4061     if (_private->useSiteSpecificSpoofing) {
       
  4062         // FIXME: Make this a hash table lookup if more domains need spoofing.
       
  4063         // FIXME: Remove yahoo.com once <rdar://problem/5057117> is fixed.
       
  4064         if (url.host().endsWith("yahoo.com")) {
       
  4065             static String yahooUserAgent([self _userAgentWithApplicationName:_private->applicationNameForUserAgent andWebKitVersion:@"422"]);
       
  4066             return yahooUserAgent;
       
  4067         }
       
  4068         
       
  4069         // FIXME: Remove flickr.com workaround once <rdar://problem/5084872> is fixed
       
  4070         if (url.host().endsWith("flickr.com")) {
       
  4071             // Safari 2.0.4's user agent string works here
       
  4072             static String safari204UserAgent([self _userAgentWithApplicationName:@"Safari/419.3" andWebKitVersion:@"419"]);
       
  4073             return safari204UserAgent;
       
  4074         }
       
  4075     }
       
  4076     
       
  4077     if (_private->userAgent->isNull()) {
       
  4078         NSString *sourceVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
       
  4079         sourceVersion = [self _userVisibleBundleVersionFromFullVersion:sourceVersion];
       
  4080         *_private->userAgent = [self _userAgentWithApplicationName:_private->applicationNameForUserAgent andWebKitVersion:sourceVersion];
       
  4081     }
       
  4082 
       
  4083     return *_private->userAgent;
       
  4084 }
       
  4085 
       
  4086 - (void)_addObject:(id)object forIdentifier:(unsigned long)identifier
       
  4087 {
       
  4088     ASSERT(!_private->identifierMap->contains(identifier));
       
  4089 
       
  4090     // If the identifier map is initially empty it means we're starting a load
       
  4091     // of something. The semantic is that the web view should be around as long 
       
  4092     // as something is loading. Because of that we retain the web view.
       
  4093     if (_private->identifierMap->isEmpty())
       
  4094         CFRetain(self);
       
  4095     
       
  4096     _private->identifierMap->set(identifier, object);
       
  4097 }
       
  4098 
       
  4099 - (id)_objectForIdentifier:(unsigned long)identifier
       
  4100 {
       
  4101     return _private->identifierMap->get(identifier).get();
       
  4102 }
       
  4103 
       
  4104 - (void)_removeObjectForIdentifier:(unsigned long)identifier
       
  4105 {
       
  4106     HashMap<unsigned long, RetainPtr<id> >::iterator it = _private->identifierMap->find(identifier);
       
  4107     
       
  4108     // FIXME: This is currently needed because of a bug that causes didFail to be sent twice 
       
  4109     // sometimes, see <rdar://problem/5009627> for more information.
       
  4110     if (it == _private->identifierMap->end())
       
  4111         return;
       
  4112     
       
  4113     _private->identifierMap->remove(it);
       
  4114     
       
  4115     // If the identifier map is now empty it means we're no longer loading anything
       
  4116     // and we should release the web view.
       
  4117     if (_private->identifierMap->isEmpty())
       
  4118         CFRelease(self);
       
  4119 }
       
  4120 
       
  4121 @end
       
  4122 
       
  4123 // We use these functions to call the delegates and block exceptions. These functions are
       
  4124 // declared inside a WebView category to get direct access to the delegate data memebers,
       
  4125 // preventing more ObjC message dispatch and compensating for the expense of the @try/@catch.
       
  4126 
       
  4127 @implementation WebView (WebCallDelegateFunctions)
       
  4128 
       
  4129 #if !(defined(__i386__) || defined(__x86_64__))
       
  4130 typedef double (*ObjCMsgSendFPRet)(id, SEL, ...);
       
  4131 static const ObjCMsgSendFPRet objc_msgSend_fpret = reinterpret_cast<ObjCMsgSendFPRet>(objc_msgSend);
       
  4132 #endif
       
  4133 
       
  4134 static inline id CallDelegate(WebView *self, id delegate, SEL selector)
       
  4135 {
       
  4136     if (!delegate || ![delegate respondsToSelector:selector])
       
  4137         return nil;
       
  4138     if (!self->_private->catchesDelegateExceptions)
       
  4139         return objc_msgSend(delegate, selector, self);
       
  4140     @try {
       
  4141         return objc_msgSend(delegate, selector, self);
       
  4142     } @catch(id exception) {
       
  4143         ReportDiscardedDelegateException(selector, exception);
       
  4144     }
       
  4145     return nil;
       
  4146 }
       
  4147 
       
  4148 static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object)
       
  4149 {
       
  4150     if (!delegate || ![delegate respondsToSelector:selector])
       
  4151         return nil;
       
  4152     if (!self->_private->catchesDelegateExceptions)
       
  4153         return objc_msgSend(delegate, selector, self, object);
       
  4154     @try {
       
  4155         return objc_msgSend(delegate, selector, self, object);
       
  4156     } @catch(id exception) {
       
  4157         ReportDiscardedDelegateException(selector, exception);
       
  4158     }
       
  4159     return nil;
       
  4160 }
       
  4161 
       
  4162 static inline id CallDelegate(WebView *self, id delegate, SEL selector, NSRect rect)
       
  4163 {
       
  4164     if (!delegate || ![delegate respondsToSelector:selector])
       
  4165         return nil;
       
  4166     if (!self->_private->catchesDelegateExceptions)
       
  4167         return reinterpret_cast<id (*)(id, SEL, WebView *, NSRect)>(objc_msgSend)(delegate, selector, self, rect);
       
  4168     @try {
       
  4169         return reinterpret_cast<id (*)(id, SEL, WebView *, NSRect)>(objc_msgSend)(delegate, selector, self, rect);
       
  4170     } @catch(id exception) {
       
  4171         ReportDiscardedDelegateException(selector, exception);
       
  4172     }
       
  4173     return nil;
       
  4174 }
       
  4175 
       
  4176 static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object1, id object2)
       
  4177 {
       
  4178     if (!delegate || ![delegate respondsToSelector:selector])
       
  4179         return nil;
       
  4180     if (!self->_private->catchesDelegateExceptions)
       
  4181         return objc_msgSend(delegate, selector, self, object1, object2);
       
  4182     @try {
       
  4183         return objc_msgSend(delegate, selector, self, object1, object2);
       
  4184     } @catch(id exception) {
       
  4185         ReportDiscardedDelegateException(selector, exception);
       
  4186     }
       
  4187     return nil;
       
  4188 }
       
  4189 
       
  4190 static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object, BOOL boolean)
       
  4191 {
       
  4192     if (!delegate || ![delegate respondsToSelector:selector])
       
  4193         return nil;
       
  4194     if (!self->_private->catchesDelegateExceptions)
       
  4195         return objc_msgSend(delegate, selector, self, object, boolean);
       
  4196     @try {
       
  4197         return objc_msgSend(delegate, selector, self, object, boolean);
       
  4198     } @catch(id exception) {
       
  4199         ReportDiscardedDelegateException(selector, exception);
       
  4200     }
       
  4201     return nil;
       
  4202 }
       
  4203 
       
  4204 static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object1, id object2, id object3)
       
  4205 {
       
  4206     if (!delegate || ![delegate respondsToSelector:selector])
       
  4207         return nil;
       
  4208     if (!self->_private->catchesDelegateExceptions)
       
  4209         return objc_msgSend(delegate, selector, self, object1, object2, object3);
       
  4210     @try {
       
  4211         return objc_msgSend(delegate, selector, self, object1, object2, object3);
       
  4212     } @catch(id exception) {
       
  4213         ReportDiscardedDelegateException(selector, exception);
       
  4214     }
       
  4215     return nil;
       
  4216 }
       
  4217 
       
  4218 static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object, NSUInteger integer)
       
  4219 {
       
  4220     if (!delegate || ![delegate respondsToSelector:selector])
       
  4221         return nil;
       
  4222     if (!self->_private->catchesDelegateExceptions)
       
  4223         return objc_msgSend(delegate, selector, self, object, integer);
       
  4224     @try {
       
  4225         return objc_msgSend(delegate, selector, self, object, integer);
       
  4226     } @catch(id exception) {
       
  4227         ReportDiscardedDelegateException(selector, exception);
       
  4228     }
       
  4229     return nil;
       
  4230 }
       
  4231 
       
  4232 static inline float CallDelegateReturningFloat(WebView *self, id delegate, SEL selector)
       
  4233 {
       
  4234     if (!delegate || ![delegate respondsToSelector:selector])
       
  4235         return 0.0f;
       
  4236     if (!self->_private->catchesDelegateExceptions)
       
  4237         return static_cast<float>(objc_msgSend_fpret(delegate, selector, self));
       
  4238     @try {
       
  4239         return static_cast<float>(objc_msgSend_fpret(delegate, selector, self));
       
  4240     } @catch(id exception) {
       
  4241         ReportDiscardedDelegateException(selector, exception);
       
  4242     }
       
  4243     return 0.0f;
       
  4244 }
       
  4245 
       
  4246 static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector)
       
  4247 {
       
  4248     if (!delegate || ![delegate respondsToSelector:selector])
       
  4249         return result;
       
  4250     if (!self->_private->catchesDelegateExceptions)
       
  4251         return reinterpret_cast<BOOL (*)(id, SEL, WebView *)>(objc_msgSend)(delegate, selector, self);
       
  4252     @try {
       
  4253         return reinterpret_cast<BOOL (*)(id, SEL, WebView *)>(objc_msgSend)(delegate, selector, self);
       
  4254     } @catch(id exception) {
       
  4255         ReportDiscardedDelegateException(selector, exception);
       
  4256     }
       
  4257     return result;
       
  4258 }
       
  4259 
       
  4260 static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object)
       
  4261 {
       
  4262     if (!delegate || ![delegate respondsToSelector:selector])
       
  4263         return result;
       
  4264     if (!self->_private->catchesDelegateExceptions)
       
  4265         return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(delegate, selector, self, object);
       
  4266     @try {
       
  4267         return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(delegate, selector, self, object);
       
  4268     } @catch(id exception) {
       
  4269         ReportDiscardedDelegateException(selector, exception);
       
  4270     }
       
  4271     return result;
       
  4272 }
       
  4273 
       
  4274 static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object, BOOL boolean)
       
  4275 {
       
  4276     if (!delegate || ![delegate respondsToSelector:selector])
       
  4277         return result;
       
  4278     if (!self->_private->catchesDelegateExceptions)
       
  4279         return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL)>(objc_msgSend)(delegate, selector, self, object, boolean);
       
  4280     @try {
       
  4281         return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL)>(objc_msgSend)(delegate, selector, self, object, boolean);
       
  4282     } @catch(id exception) {
       
  4283         ReportDiscardedDelegateException(selector, exception);
       
  4284     }
       
  4285     return result;
       
  4286 }
       
  4287 
       
  4288 static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object1, id object2)
       
  4289 {
       
  4290     if (!delegate || ![delegate respondsToSelector:selector])
       
  4291         return result;
       
  4292     if (!self->_private->catchesDelegateExceptions)
       
  4293         return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(delegate, selector, self, object1, object2);
       
  4294     @try {
       
  4295         return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(delegate, selector, self, object1, object2);
       
  4296     } @catch(id exception) {
       
  4297         ReportDiscardedDelegateException(selector, exception);
       
  4298     }
       
  4299     return result;
       
  4300 }
       
  4301 
       
  4302 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector)
       
  4303 {
       
  4304     if (!delegate)
       
  4305         return nil;
       
  4306     if (!self->_private->catchesDelegateExceptions)
       
  4307         return implementation(delegate, selector, self);
       
  4308     @try {
       
  4309         return implementation(delegate, selector, self);
       
  4310     } @catch(id exception) {
       
  4311         ReportDiscardedDelegateException(selector, exception);
       
  4312     }
       
  4313     return nil;
       
  4314 }
       
  4315 
       
  4316 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object)
       
  4317 {
       
  4318     if (!delegate)
       
  4319         return nil;
       
  4320     if (!self->_private->catchesDelegateExceptions)
       
  4321         return implementation(delegate, selector, self, object);
       
  4322     @try {
       
  4323         return implementation(delegate, selector, self, object);
       
  4324     } @catch(id exception) {
       
  4325         ReportDiscardedDelegateException(selector, exception);
       
  4326     }
       
  4327     return nil;
       
  4328 }
       
  4329 
       
  4330 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2)
       
  4331 {
       
  4332     if (!delegate)
       
  4333         return nil;
       
  4334     if (!self->_private->catchesDelegateExceptions)
       
  4335         return implementation(delegate, selector, self, object1, object2);
       
  4336     @try {
       
  4337         return implementation(delegate, selector, self, object1, object2);
       
  4338     } @catch(id exception) {
       
  4339         ReportDiscardedDelegateException(selector, exception);
       
  4340     }
       
  4341     return nil;
       
  4342 }
       
  4343 
       
  4344 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, id object3)
       
  4345 {
       
  4346     if (!delegate)
       
  4347         return nil;
       
  4348     if (!self->_private->catchesDelegateExceptions)
       
  4349         return implementation(delegate, selector, self, object1, object2, object3);
       
  4350     @try {
       
  4351         return implementation(delegate, selector, self, object1, object2, object3);
       
  4352     } @catch(id exception) {
       
  4353         ReportDiscardedDelegateException(selector, exception);
       
  4354     }
       
  4355     return nil;
       
  4356 }
       
  4357 
       
  4358 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, id object3, id object4)
       
  4359 {
       
  4360     if (!delegate)
       
  4361         return nil;
       
  4362     if (!self->_private->catchesDelegateExceptions)
       
  4363         return implementation(delegate, selector, self, object1, object2, object3, object4);
       
  4364     @try {
       
  4365         return implementation(delegate, selector, self, object1, object2, object3, object4);
       
  4366     } @catch(id exception) {
       
  4367         ReportDiscardedDelegateException(selector, exception);
       
  4368     }
       
  4369     return nil;
       
  4370 }
       
  4371 
       
  4372 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer, id object2)
       
  4373 {
       
  4374     if (!delegate)
       
  4375         return nil;
       
  4376     if (!self->_private->catchesDelegateExceptions)
       
  4377         return implementation(delegate, selector, self, object1, integer, object2);
       
  4378     @try {
       
  4379         return implementation(delegate, selector, self, object1, integer, object2);
       
  4380     } @catch(id exception) {
       
  4381         ReportDiscardedDelegateException(selector, exception);
       
  4382     }
       
  4383     return nil;
       
  4384 }
       
  4385 
       
  4386 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, NSInteger integer, id object3)
       
  4387 {
       
  4388     if (!delegate)
       
  4389         return nil;
       
  4390     if (!self->_private->catchesDelegateExceptions)
       
  4391         return implementation(delegate, selector, self, object1, object2, integer, object3);
       
  4392     @try {
       
  4393         return implementation(delegate, selector, self, object1, object2, integer, object3);
       
  4394     } @catch(id exception) {
       
  4395         ReportDiscardedDelegateException(selector, exception);
       
  4396     }
       
  4397     return nil;
       
  4398 }
       
  4399 
       
  4400 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSTimeInterval interval, id object2, id object3)
       
  4401 {
       
  4402     if (!delegate)
       
  4403         return nil;
       
  4404     if (!self->_private->catchesDelegateExceptions)
       
  4405         return implementation(delegate, selector, self, object1, interval, object2, object3);
       
  4406     @try {
       
  4407         return implementation(delegate, selector, self, object1, interval, object2, object3);
       
  4408     } @catch(id exception) {
       
  4409         ReportDiscardedDelegateException(selector, exception);
       
  4410     }
       
  4411     return nil;
       
  4412 }
       
  4413 
       
  4414 id CallUIDelegate(WebView *self, SEL selector)
       
  4415 {
       
  4416     return CallDelegate(self, self->_private->UIDelegate, selector);
       
  4417 }
       
  4418 
       
  4419 id CallUIDelegate(WebView *self, SEL selector, id object)
       
  4420 {
       
  4421     return CallDelegate(self, self->_private->UIDelegate, selector, object);
       
  4422 }
       
  4423 
       
  4424 id CallUIDelegate(WebView *self, SEL selector, id object, BOOL boolean)
       
  4425 {
       
  4426     return CallDelegate(self, self->_private->UIDelegate, selector, object, boolean);
       
  4427 }
       
  4428 
       
  4429 id CallUIDelegate(WebView *self, SEL selector, NSRect rect)
       
  4430 {
       
  4431     return CallDelegate(self, self->_private->UIDelegate, selector, rect);
       
  4432 }
       
  4433 
       
  4434 id CallUIDelegate(WebView *self, SEL selector, id object1, id object2)
       
  4435 {
       
  4436     return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2);
       
  4437 }
       
  4438 
       
  4439 id CallUIDelegate(WebView *self, SEL selector, id object1, id object2, id object3)
       
  4440 {
       
  4441     return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2, object3);
       
  4442 }
       
  4443 
       
  4444 id CallUIDelegate(WebView *self, SEL selector, id object, NSUInteger integer)
       
  4445 {
       
  4446     return CallDelegate(self, self->_private->UIDelegate, selector, object, integer);
       
  4447 }
       
  4448 
       
  4449 float CallUIDelegateReturningFloat(WebView *self, SEL selector)
       
  4450 {
       
  4451     return CallDelegateReturningFloat(self, self->_private->UIDelegate, selector);
       
  4452 }
       
  4453 
       
  4454 BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector)
       
  4455 {
       
  4456     return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector);
       
  4457 }
       
  4458 
       
  4459 BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object)
       
  4460 {
       
  4461     return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object);
       
  4462 }
       
  4463 
       
  4464 BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object, BOOL boolean)
       
  4465 {
       
  4466     return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object, boolean);
       
  4467 }
       
  4468 
       
  4469 BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, id object2)
       
  4470 {
       
  4471     return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object1, object2);
       
  4472 }
       
  4473 
       
  4474 id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector)
       
  4475 {
       
  4476     return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector);
       
  4477 }
       
  4478 
       
  4479 id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object)
       
  4480 {
       
  4481     return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object);
       
  4482 }
       
  4483 
       
  4484 id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
       
  4485 {
       
  4486     return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2);
       
  4487 }
       
  4488 
       
  4489 id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
       
  4490 {
       
  4491     return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3);
       
  4492 }
       
  4493 
       
  4494 id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
       
  4495 {
       
  4496     return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3, object4);
       
  4497 }
       
  4498 
       
  4499 id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSTimeInterval interval, id object2, id object3)
       
  4500 {
       
  4501     return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, interval, object2, object3);
       
  4502 }
       
  4503 
       
  4504 id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
       
  4505 {
       
  4506     return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2);
       
  4507 }
       
  4508 
       
  4509 id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
       
  4510 {
       
  4511     return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3);
       
  4512 }
       
  4513 
       
  4514 id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
       
  4515 {
       
  4516     return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3, object4);
       
  4517 }
       
  4518 
       
  4519 id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2)
       
  4520 {
       
  4521     return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, integer, object2);
       
  4522 }
       
  4523 
       
  4524 id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3)
       
  4525 {
       
  4526     return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, integer, object3);
       
  4527 }
       
  4528 
       
  4529 // The form delegate needs to have it's own implementation, because the first argument is never the WebView
       
  4530 
       
  4531 id CallFormDelegate(WebView *self, SEL selector, id object1, id object2)
       
  4532 {
       
  4533     id delegate = self->_private->formDelegate;
       
  4534     if (!delegate || ![delegate respondsToSelector:selector])
       
  4535         return nil;
       
  4536     if (!self->_private->catchesDelegateExceptions)
       
  4537         return objc_msgSend(delegate, selector, object1, object2);
       
  4538     @try {
       
  4539         return objc_msgSend(delegate, selector, object1, object2);
       
  4540     } @catch(id exception) {
       
  4541         ReportDiscardedDelegateException(selector, exception);
       
  4542     }
       
  4543     return nil;
       
  4544 }
       
  4545 
       
  4546 id CallFormDelegate(WebView *self, SEL selector, id object1, id object2, id object3, id object4, id object5)
       
  4547 {
       
  4548     id delegate = self->_private->formDelegate;
       
  4549     if (!delegate || ![delegate respondsToSelector:selector])
       
  4550         return nil;
       
  4551     if (!self->_private->catchesDelegateExceptions)
       
  4552         return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5);
       
  4553     @try {
       
  4554         return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5);
       
  4555     } @catch(id exception) {
       
  4556         ReportDiscardedDelegateException(selector, exception);
       
  4557     }
       
  4558     return nil;
       
  4559 }
       
  4560 
       
  4561 BOOL CallFormDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, SEL selectorArg, id object2)
       
  4562 {
       
  4563     id delegate = self->_private->formDelegate;
       
  4564     if (!delegate || ![delegate respondsToSelector:selector])
       
  4565         return result;
       
  4566     if (!self->_private->catchesDelegateExceptions)
       
  4567         return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2);
       
  4568     @try {
       
  4569         return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2);
       
  4570     } @catch(id exception) {
       
  4571         ReportDiscardedDelegateException(selector, exception);
       
  4572     }
       
  4573     return result;
       
  4574 }
       
  4575 
       
  4576 @end